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.
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
41 #include "gtkcalendar.h"
42 #include "gdk/gdkkeysyms.h"
44 /***************************************************************************/
45 /* The following date routines are taken from the lib_date package. Keep
46 * them seperate in case we want to update them if a newer lib_date comes
49 typedef unsigned int N_int;
50 typedef unsigned long N_long;
51 typedef signed long Z_long;
52 typedef enum { false = FALSE , true = TRUE } boolean;
54 #define and && /* logical (boolean) operators: lower case */
57 static const N_int month_length[2][13] =
59 { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
60 { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
63 static const N_int days_in_months[2][14] =
65 { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
66 { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
69 static Z_long calc_days(N_int year, N_int mm, N_int dd);
70 static N_int day_of_week(N_int year, N_int mm, N_int dd);
71 static Z_long dates_difference(N_int year1, N_int mm1, N_int dd1,
72 N_int year2, N_int mm2, N_int dd2);
73 static N_int weeks_in_year(N_int year);
78 return((((year % 4) == 0) and ((year % 100) != 0)) or ((year % 400) == 0));
82 day_of_week(N_int year, N_int mm, N_int dd)
86 days = calc_days(year, mm, dd);
93 return( (N_int) days );
96 static N_int weeks_in_year(N_int year)
98 return(52 + ((day_of_week(year,1,1)==4) or (day_of_week(year,12,31)==4)));
102 check_date(N_int year, N_int mm, N_int dd)
104 if (year < 1) return(false);
105 if ((mm < 1) or (mm > 12)) return(false);
106 if ((dd < 1) or (dd > month_length[leap(year)][mm])) return(false);
111 week_number(N_int year, N_int mm, N_int dd)
115 first = day_of_week(year,1,1) - 1;
116 return( (N_int) ( (dates_difference(year,1,1, year,mm,dd) + first) / 7L ) +
121 year_to_days(N_int year)
123 return( year * 365L + (year / 4) - (year / 100) + (year / 400) );
128 calc_days(N_int year, N_int mm, N_int dd)
132 if (year < 1) return(0L);
133 if ((mm < 1) or (mm > 12)) return(0L);
134 if ((dd < 1) or (dd > month_length[(lp = leap(year))][mm])) return(0L);
135 return( year_to_days(--year) + days_in_months[lp][mm] + dd );
139 week_of_year(N_int *week, N_int *year, N_int mm, N_int dd)
141 if (check_date(*year,mm,dd))
143 *week = week_number(*year,mm,dd);
145 *week = weeks_in_year(--(*year));
146 else if (*week > weeks_in_year(*year))
157 dates_difference(N_int year1, N_int mm1, N_int dd1,
158 N_int year2, N_int mm2, N_int dd2)
160 return( calc_days(year2, mm2, dd2) - calc_days(year1, mm1, dd1) );
163 /** END OF lib_date routines ************************************************/
165 #define CALENDAR_MARGIN 0
166 #define CALENDAR_YSEP 4
167 #define CALENDAR_XSEP 4
168 #define INNER_BORDER 4
172 #define DAY_XSEP 0 /* not really good for small calendar */
173 #define DAY_YSEP 0 /* not really good for small calendar */
176 #define HEADER_FG_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
177 #define HEADER_BG_COLOR(widget) (& (widget)->style->bg[GTK_WIDGET_STATE (widget)])
178 #define DAY_NAME_COLOR(widget) (& (widget)->style->bg[GTK_STATE_SELECTED])
179 #define NORMAL_DAY_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
180 #define SELECTION_FOCUS_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
181 #define SELECTION_NO_FOCUS_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])
182 #define PREV_MONTH_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])
183 #define NEXT_MONTH_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])
184 #define MARKED_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
185 #define FOREGROUND_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
186 #define BACKGROUND_COLOR(widget) (& (widget)->style->base[GTK_WIDGET_STATE (widget)])
187 #define HIGHLIGHT_BACK_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])
189 #define HEADER_FONT(widget) ((widget)->style->font)
190 #define LABEL_FONT(widget) ((widget)->style->font)
191 #define DAY_FONT(widget) ((widget)->style->font)
207 MONTH_CHANGED_SIGNAL,
209 DAY_SELECTED_DOUBLE_CLICK_SIGNAL,
217 static gint gtk_calendar_signals[LAST_SIGNAL] = { 0 };
219 static GtkWidgetClass *parent_class = NULL;
221 typedef struct _GtkCalendarPrivateData GtkCalendarPrivateData;
222 struct _GtkCalendarPrivateData
224 GdkWindow *header_win;
225 GdkWindow *day_name_win;
228 GdkWindow *arrow_win[4];
234 guint arrow_state[4];
236 guint max_month_width;
237 guint max_year_width;
243 guint max_day_char_width;
244 guint max_day_char_ascent;
245 guint max_day_char_descent;
246 guint max_label_char_ascent;
247 guint max_label_char_descent;
248 guint max_week_char_width;
253 guint dirty_header : 1;
254 guint dirty_day_names : 1;
255 guint dirty_main : 1;
256 guint dirty_week : 1;
259 #define GTK_CALENDAR_PRIVATE_DATA(widget) (((GtkCalendarPrivateData*)(GTK_CALENDAR (widget)->private_data)))
261 typedef void (*GtkCalendarSignalDate) (GtkObject *object, guint arg1, guint arg2, guint arg3, gpointer data);
263 static void gtk_calendar_class_init (GtkCalendarClass *class);
264 static void gtk_calendar_init (GtkCalendar *calendar);
265 static void gtk_calendar_realize (GtkWidget *widget);
266 static void gtk_calendar_unrealize (GtkWidget *widget);
267 static void gtk_calendar_draw_focus (GtkWidget *widget);
268 static void gtk_calendar_size_request (GtkWidget *widget,
269 GtkRequisition *requisition);
270 static void gtk_calendar_size_allocate (GtkWidget *widget,
271 GtkAllocation *allocation);
272 static gint gtk_calendar_expose (GtkWidget *widget,
273 GdkEventExpose *event);
274 static gint gtk_calendar_button_press (GtkWidget *widget,
275 GdkEventButton *event);
276 static void gtk_calendar_main_button (GtkWidget *widget,
277 GdkEventButton *event);
278 static gint gtk_calendar_motion_notify (GtkWidget *widget,
279 GdkEventMotion *event);
280 static gint gtk_calendar_enter_notify (GtkWidget *widget,
281 GdkEventCrossing *event);
282 static gint gtk_calendar_leave_notify (GtkWidget *widget,
283 GdkEventCrossing *event);
284 static gint gtk_calendar_key_press (GtkWidget *widget,
286 static gint gtk_calendar_focus_in (GtkWidget *widget,
287 GdkEventFocus *event);
288 static gint gtk_calendar_focus_out (GtkWidget *widget,
289 GdkEventFocus *event);
290 static void gtk_calendar_state_changed (GtkWidget *widget,
291 GtkStateType previous_state);
292 static void gtk_calendar_style_set (GtkWidget *widget,
293 GtkStyle *previous_style);
294 static void gtk_calendar_paint_header (GtkWidget *widget);
295 static void gtk_calendar_paint_day_names (GtkWidget *widget);
296 static void gtk_calendar_paint_week_numbers (GtkWidget *widget);
297 static void gtk_calendar_paint_main (GtkWidget *widget);
300 static void gtk_calendar_paint (GtkWidget *widget,
302 static void gtk_calendar_paint_arrow (GtkWidget *widget,
304 static void gtk_calendar_paint_day_num (GtkWidget *widget,
306 static void gtk_calendar_paint_day (GtkWidget *widget,
309 static void gtk_calendar_draw (GtkWidget *widget,
311 static void gtk_calendar_compute_days (GtkCalendar *calendar);
312 static gint left_x_for_column (GtkCalendar *calendar,
314 static gint top_y_for_row (GtkCalendar *calendar,
317 static char *default_abbreviated_dayname[7];
318 static char *default_monthname[12];
321 gtk_calendar_get_type (void)
323 static GtkType calendar_type = 0;
327 static const GTypeInfo calendar_info =
329 sizeof (GtkCalendarClass),
330 NULL, /* base_init */
331 NULL, /* base_finalize */
332 (GClassInitFunc) gtk_calendar_class_init,
333 NULL, /* class_finalize */
334 NULL, /* class_data */
335 sizeof (GtkCalendar),
336 16, /* n_preallocs */
337 (GInstanceInitFunc) gtk_calendar_init,
340 calendar_type = g_type_register_static (GTK_TYPE_WIDGET, "GtkCalendar", &calendar_info);
343 return calendar_type;
347 gtk_calendar_class_init (GtkCalendarClass *class)
349 GtkObjectClass *object_class;
350 GtkWidgetClass *widget_class;
352 object_class = (GtkObjectClass*) class;
353 widget_class = (GtkWidgetClass*) class;
355 parent_class = gtk_type_class (GTK_TYPE_WIDGET);
357 widget_class->realize = gtk_calendar_realize;
358 widget_class->unrealize = gtk_calendar_unrealize;
359 widget_class->expose_event = gtk_calendar_expose;
360 widget_class->draw = gtk_calendar_draw;
361 widget_class->draw_focus = gtk_calendar_draw_focus;
362 widget_class->size_request = gtk_calendar_size_request;
363 widget_class->size_allocate = gtk_calendar_size_allocate;
364 widget_class->button_press_event = gtk_calendar_button_press;
365 widget_class->motion_notify_event = gtk_calendar_motion_notify;
366 widget_class->enter_notify_event = gtk_calendar_enter_notify;
367 widget_class->leave_notify_event = gtk_calendar_leave_notify;
368 widget_class->key_press_event = gtk_calendar_key_press;
369 widget_class->focus_in_event = gtk_calendar_focus_in;
370 widget_class->focus_out_event = gtk_calendar_focus_out;
371 widget_class->style_set = gtk_calendar_style_set;
372 widget_class->state_changed = gtk_calendar_state_changed;
374 gtk_calendar_signals[MONTH_CHANGED_SIGNAL] =
375 gtk_signal_new ("month_changed",
376 GTK_RUN_FIRST, GTK_CLASS_TYPE (object_class),
377 GTK_SIGNAL_OFFSET (GtkCalendarClass, month_changed),
378 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
379 gtk_calendar_signals[DAY_SELECTED_SIGNAL] =
380 gtk_signal_new ("day_selected",
381 GTK_RUN_FIRST, GTK_CLASS_TYPE (object_class),
382 GTK_SIGNAL_OFFSET (GtkCalendarClass, day_selected),
383 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
384 gtk_calendar_signals[DAY_SELECTED_DOUBLE_CLICK_SIGNAL] =
385 gtk_signal_new ("day_selected_double_click",
386 GTK_RUN_FIRST, GTK_CLASS_TYPE (object_class),
387 GTK_SIGNAL_OFFSET (GtkCalendarClass, day_selected_double_click),
388 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
389 gtk_calendar_signals[PREV_MONTH_SIGNAL] =
390 gtk_signal_new ("prev_month",
391 GTK_RUN_FIRST, GTK_CLASS_TYPE (object_class),
392 GTK_SIGNAL_OFFSET (GtkCalendarClass, prev_month),
393 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
394 gtk_calendar_signals[NEXT_MONTH_SIGNAL] =
395 gtk_signal_new ("next_month",
396 GTK_RUN_FIRST, GTK_CLASS_TYPE (object_class),
397 GTK_SIGNAL_OFFSET (GtkCalendarClass, next_month),
398 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
399 gtk_calendar_signals[PREV_YEAR_SIGNAL] =
400 gtk_signal_new ("prev_year",
401 GTK_RUN_FIRST, GTK_CLASS_TYPE (object_class),
402 GTK_SIGNAL_OFFSET (GtkCalendarClass, prev_year),
403 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
404 gtk_calendar_signals[NEXT_YEAR_SIGNAL] =
405 gtk_signal_new ("next_year",
406 GTK_RUN_FIRST, GTK_CLASS_TYPE (object_class),
407 GTK_SIGNAL_OFFSET (GtkCalendarClass, next_year),
408 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
410 gtk_object_class_add_signals (object_class, gtk_calendar_signals, LAST_SIGNAL);
412 class->month_changed = NULL;
413 class->day_selected = NULL;
414 class->day_selected_double_click = NULL;
415 class->prev_month = NULL;
416 class->next_month = NULL;
417 class->prev_year = NULL;
418 class->next_year = NULL;
422 gtk_calendar_init (GtkCalendar *calendar)
430 GtkCalendarPrivateData *private_data;
432 widget = GTK_WIDGET (calendar);
433 GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
435 calendar->private_data = (gpointer) malloc (sizeof (GtkCalendarPrivateData));
436 private_data = GTK_CALENDAR_PRIVATE_DATA (calendar);
438 if (!default_abbreviated_dayname[0])
441 tmp_time= (i+3)*86400;
442 strftime ( buffer, sizeof (buffer), "%a", gmtime (&tmp_time));
443 default_abbreviated_dayname[i] = g_strdup (buffer);
446 if (!default_monthname[0])
450 strftime ( buffer, sizeof (buffer), "%B", gmtime (&tmp_time));
451 default_monthname[i] = g_strdup (buffer);
456 tm = localtime (&secs);
457 calendar->month = tm->tm_mon;
458 calendar->year = 1900 + tm->tm_year;
461 calendar->marked_date[i] = FALSE;
462 calendar->num_marked_dates = 0;
463 calendar->selected_day = 1;
465 calendar->display_flags = ( GTK_CALENDAR_SHOW_HEADING |
466 GTK_CALENDAR_SHOW_DAY_NAMES );
468 calendar->highlight_row = -1;
469 calendar->highlight_col = -1;
471 calendar->focus_row = -1;
472 calendar->focus_col = -1;
473 calendar->xor_gc = NULL;
475 private_data->max_year_width = 0;
476 private_data->max_month_width = 0;
477 private_data->max_day_char_width = 0;
478 private_data->max_week_char_width = 0;
480 private_data->max_day_char_ascent = 0;
481 private_data->max_day_char_descent = 0;
482 private_data->max_label_char_ascent = 0;
483 private_data->max_label_char_descent = 0;
485 private_data->arrow_width = 10;
487 private_data->freeze_count = 0;
489 private_data->dirty_header = 0;
490 private_data->dirty_day_names = 0;
491 private_data->dirty_week = 0;
492 private_data->dirty_main = 0;
496 gtk_calendar_new (void)
498 return GTK_WIDGET (gtk_type_new (GTK_TYPE_CALENDAR));
501 /* column_from_x: returns the column 0-6 that the
502 * x pixel of the xwindow is in */
504 column_from_x (GtkCalendar *calendar,
508 gint x_left, x_right;
512 for (c = 0; c < 7; c++)
514 x_left = left_x_for_column (calendar, c);
515 x_right = x_left + GTK_CALENDAR_PRIVATE_DATA (calendar)->day_width;
517 if (event_x >= x_left && event_x < x_right)
528 row_height (GtkCalendar *calendar)
530 return (GTK_CALENDAR_PRIVATE_DATA (calendar)->main_h - CALENDAR_MARGIN
531 - ((calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
532 ? CALENDAR_YSEP : CALENDAR_MARGIN)) / 6;
536 /* row_from_y: returns the row 0-5 that the
537 * y pixel of the xwindow is in */
539 row_from_y (GtkCalendar *calendar,
544 gint y_top, y_bottom;
546 height = row_height (calendar);
549 for (r = 0; r < 6; r++)
551 y_top = top_y_for_row (calendar, r);
552 y_bottom = y_top + height;
554 if (event_y >= y_top && event_y < y_bottom)
564 /* left_x_for_column: returns the x coordinate
565 * for the left of the column */
567 left_x_for_column (GtkCalendar *calendar,
573 width = GTK_CALENDAR_PRIVATE_DATA (calendar)->day_width;
574 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
575 x_left = DAY_XSEP + (width + DAY_XSEP) * column;
577 x_left = CALENDAR_MARGIN + (width + DAY_XSEP) * column;
582 /* top_y_for_row: returns the y coordinate
583 * for the top of the row */
585 top_y_for_row (GtkCalendar *calendar,
589 return (GTK_CALENDAR_PRIVATE_DATA (calendar)->main_h
590 - (CALENDAR_MARGIN + (6 - row)
591 * row_height (calendar)));
594 /* This function should be done by the toolkit, but we don't like the
595 * GTK arrows because they don't look good on this widget */
597 draw_arrow_right (GdkWindow *window,
605 for (i = 0; i <= size / 2; i++)
607 gdk_draw_line (window, gc,
615 /* This function should be done by the toolkit, but we don't like the
616 * GTK arrows because they don't look good on this widget */
618 draw_arrow_left (GdkWindow *window,
626 for (i = 0; i <= size / 2; i++)
628 gdk_draw_line (window, gc,
637 gtk_calendar_set_month_prev (GtkCalendar *calendar)
641 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
644 if (calendar->month == 0)
646 calendar->month = 11;
652 month_len = month_length[leap (calendar->year)][calendar->month + 1];
654 gtk_calendar_freeze (calendar);
655 gtk_calendar_compute_days (calendar);
657 gtk_signal_emit (GTK_OBJECT (calendar),
658 gtk_calendar_signals[PREV_MONTH_SIGNAL]);
659 gtk_signal_emit (GTK_OBJECT (calendar),
660 gtk_calendar_signals[MONTH_CHANGED_SIGNAL]);
662 if (month_len < calendar->selected_day)
664 calendar->selected_day = 0;
665 gtk_calendar_select_day (calendar, month_len);
669 if (calendar->selected_day < 0)
670 calendar->selected_day = calendar->selected_day + 1 + month_length[leap (calendar->year)][calendar->month + 1];
671 gtk_calendar_select_day (calendar, calendar->selected_day);
674 gtk_calendar_paint (GTK_WIDGET (calendar), NULL);
675 gtk_calendar_thaw (calendar);
680 gtk_calendar_set_month_next (GtkCalendar *calendar)
684 g_return_if_fail (calendar != NULL);
685 g_return_if_fail (GTK_IS_WIDGET (calendar));
687 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
691 if (calendar->month == 11)
699 gtk_calendar_freeze (calendar);
700 gtk_calendar_compute_days (calendar);
701 gtk_signal_emit (GTK_OBJECT (calendar),
702 gtk_calendar_signals[NEXT_MONTH_SIGNAL]);
703 gtk_signal_emit (GTK_OBJECT (calendar),
704 gtk_calendar_signals[MONTH_CHANGED_SIGNAL]);
706 month_len = month_length[leap (calendar->year)][calendar->month + 1];
708 if (month_len < calendar->selected_day)
710 calendar->selected_day = 0;
711 gtk_calendar_select_day (calendar, month_len);
714 gtk_calendar_select_day (calendar, calendar->selected_day);
716 gtk_calendar_paint (GTK_WIDGET(calendar), NULL);
717 gtk_calendar_thaw (calendar);
721 gtk_calendar_set_year_prev (GtkCalendar *calendar)
725 g_return_if_fail (calendar != NULL);
726 g_return_if_fail (GTK_IS_WIDGET (calendar));
729 gtk_calendar_freeze (calendar);
730 gtk_calendar_compute_days (calendar);
731 gtk_signal_emit (GTK_OBJECT (calendar),
732 gtk_calendar_signals[PREV_YEAR_SIGNAL]);
733 gtk_signal_emit (GTK_OBJECT (calendar),
734 gtk_calendar_signals[MONTH_CHANGED_SIGNAL]);
736 month_len = month_length[leap (calendar->year)][calendar->month + 1];
738 if (month_len < calendar->selected_day)
740 calendar->selected_day = 0;
741 gtk_calendar_select_day (calendar, month_len);
744 gtk_calendar_select_day (calendar, calendar->selected_day);
746 gtk_calendar_paint (GTK_WIDGET (calendar), NULL);
747 gtk_calendar_thaw (calendar);
751 gtk_calendar_set_year_next (GtkCalendar *calendar)
756 g_return_if_fail (calendar != NULL);
757 g_return_if_fail (GTK_IS_WIDGET (calendar));
759 widget = GTK_WIDGET (calendar);
761 gtk_calendar_freeze (calendar);
764 gtk_calendar_compute_days (calendar);
765 gtk_signal_emit (GTK_OBJECT (calendar),
766 gtk_calendar_signals[NEXT_YEAR_SIGNAL]);
767 gtk_signal_emit (GTK_OBJECT (calendar),
768 gtk_calendar_signals[MONTH_CHANGED_SIGNAL]);
770 month_len = month_length[leap (calendar->year)][calendar->month + 1];
772 if (month_len < calendar->selected_day)
774 calendar->selected_day = 0;
775 gtk_calendar_select_day (calendar, month_len);
778 gtk_calendar_select_day (calendar, calendar->selected_day);
780 gtk_calendar_paint (GTK_WIDGET (calendar), NULL);
781 gtk_calendar_thaw (calendar);
785 gtk_calendar_main_button (GtkWidget *widget,
786 GdkEventButton *event)
788 GtkCalendar *calendar;
792 gint old_focus_row, old_focus_col;
794 calendar = GTK_CALENDAR (widget);
796 x = (gint) (event->x);
797 y = (gint) (event->y);
799 row = row_from_y (calendar, y);
800 col = column_from_x (calendar, x);
802 /* If row or column isn't found, just return. */
803 if (row == -1 || col == -1)
806 day_month = calendar->day_month[row][col];
808 if (day_month == MONTH_CURRENT)
810 if (event->type == GDK_2BUTTON_PRESS)
811 gtk_signal_emit (GTK_OBJECT (calendar),
812 gtk_calendar_signals[DAY_SELECTED_DOUBLE_CLICK_SIGNAL]);
815 if (!GTK_WIDGET_HAS_FOCUS (widget))
816 gtk_widget_grab_focus (widget);
817 old_focus_row = calendar->focus_row;
818 old_focus_col = calendar->focus_col;
819 calendar->focus_row = row;
820 calendar->focus_col = col;
821 gtk_calendar_paint_day (widget, old_focus_row, old_focus_col);
822 gtk_calendar_select_day (calendar, calendar->day[row][col]);
825 else if (day_month == MONTH_PREV)
826 gtk_calendar_set_month_prev (calendar);
827 else if (day_month == MONTH_NEXT)
828 gtk_calendar_set_month_next (calendar);
832 gtk_calendar_realize_arrows (GtkWidget *widget)
834 GtkCalendar *calendar;
835 GtkCalendarPrivateData *private_data;
836 GdkWindowAttr attributes;
837 gint attributes_mask;
840 g_return_if_fail (widget != NULL);
841 g_return_if_fail (GTK_IS_CALENDAR (widget));
843 calendar = GTK_CALENDAR (widget);
844 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
846 /* Arrow windows ------------------------------------- */
847 if (! (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
848 && (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING))
850 attributes.wclass = GDK_INPUT_OUTPUT;
851 attributes.window_type = GDK_WINDOW_CHILD;
852 attributes.visual = gtk_widget_get_visual (widget);
853 attributes.colormap = gtk_widget_get_colormap (widget);
854 attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK
855 | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
856 | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
857 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
859 attributes.width = private_data->arrow_width;
860 attributes.height = private_data->header_h - 7;
861 for (i = 0; i < 4; i++)
865 case ARROW_MONTH_LEFT:
868 case ARROW_MONTH_RIGHT:
869 attributes.x = (private_data->arrow_width
870 + private_data->max_month_width);
872 case ARROW_YEAR_LEFT:
873 attributes.x = (widget->allocation.width - 4
874 - (3 + 2*private_data->arrow_width
875 + private_data->max_year_width));
877 case ARROW_YEAR_RIGHT:
878 attributes.x = (widget->allocation.width - 4
879 - 3 - private_data->arrow_width);
882 private_data->arrow_win[i] = gdk_window_new (private_data->header_win,
885 private_data->arrow_state[i] = GTK_STATE_NORMAL;
886 gdk_window_set_background (private_data->arrow_win[i],
887 HEADER_BG_COLOR (GTK_WIDGET (calendar)));
888 gdk_window_show (private_data->arrow_win[i]);
889 gdk_window_set_user_data (private_data->arrow_win[i], widget);
894 for (i = 0; i < 4; i++)
895 private_data->arrow_win[i] = NULL;
900 gtk_calendar_realize_header (GtkWidget *widget)
902 GtkCalendar *calendar;
903 GtkCalendarPrivateData *private_data;
904 GdkWindowAttr attributes;
905 gint attributes_mask;
907 g_return_if_fail (widget != NULL);
908 g_return_if_fail (GTK_IS_CALENDAR (widget));
910 calendar = GTK_CALENDAR (widget);
911 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
913 /* Header window ------------------------------------- */
914 if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING)
916 attributes.wclass = GDK_INPUT_OUTPUT;
917 attributes.window_type = GDK_WINDOW_CHILD;
918 attributes.visual = gtk_widget_get_visual (widget);
919 attributes.colormap = gtk_widget_get_colormap (widget);
920 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
921 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
924 attributes.width = widget->allocation.width - 4;
925 attributes.height = private_data->header_h;
926 private_data->header_win = gdk_window_new (widget->window,
927 &attributes, attributes_mask);
929 gdk_window_set_background (private_data->header_win,
930 HEADER_BG_COLOR (GTK_WIDGET (calendar)));
931 gdk_window_show (private_data->header_win);
932 gdk_window_set_user_data (private_data->header_win, widget);
937 private_data->header_win = NULL;
939 gtk_calendar_realize_arrows (widget);
943 gtk_calendar_realize_day_names (GtkWidget *widget)
945 GtkCalendar *calendar;
946 GtkCalendarPrivateData *private_data;
947 GdkWindowAttr attributes;
948 gint attributes_mask;
950 g_return_if_fail (widget != NULL);
951 g_return_if_fail (GTK_IS_CALENDAR (widget));
953 calendar = GTK_CALENDAR (widget);
954 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
956 /* Day names window --------------------------------- */
957 if ( calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
959 attributes.wclass = GDK_INPUT_OUTPUT;
960 attributes.window_type = GDK_WINDOW_CHILD;
961 attributes.visual = gtk_widget_get_visual (widget);
962 attributes.colormap = gtk_widget_get_colormap (widget);
963 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
964 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
965 attributes.x = (widget->style->klass->xthickness + INNER_BORDER);
966 attributes.y = private_data->header_h + (widget->style->klass->ythickness
968 attributes.width = (widget->allocation.width
969 - (widget->style->klass->xthickness + INNER_BORDER)
971 attributes.height = private_data->day_name_h;
972 private_data->day_name_win = gdk_window_new (widget->window,
975 gdk_window_set_background (private_data->day_name_win,
976 BACKGROUND_COLOR ( GTK_WIDGET ( calendar)));
977 gdk_window_show (private_data->day_name_win);
978 gdk_window_set_user_data (private_data->day_name_win, widget);
982 private_data->day_name_win = NULL;
987 gtk_calendar_realize_week_numbers (GtkWidget *widget)
989 GtkCalendar *calendar;
990 GtkCalendarPrivateData *private_data;
991 GdkWindowAttr attributes;
992 gint attributes_mask;
994 g_return_if_fail (widget != NULL);
995 g_return_if_fail (GTK_IS_CALENDAR (widget));
997 calendar = GTK_CALENDAR (widget);
998 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1000 /* Week number window -------------------------------- */
1001 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1003 attributes.wclass = GDK_INPUT_OUTPUT;
1004 attributes.window_type = GDK_WINDOW_CHILD;
1005 attributes.visual = gtk_widget_get_visual (widget);
1006 attributes.colormap = gtk_widget_get_colormap (widget);
1007 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
1009 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1010 attributes.x = + (widget->style->klass->xthickness + INNER_BORDER);
1011 attributes.y = (private_data->header_h + private_data->day_name_h
1012 + (widget->style->klass->ythickness + INNER_BORDER));
1013 attributes.width = private_data->week_width;
1014 attributes.height = private_data->main_h;
1015 private_data->week_win = gdk_window_new (widget->window,
1016 &attributes, attributes_mask);
1017 gdk_window_set_background (private_data->week_win,
1018 BACKGROUND_COLOR (GTK_WIDGET (calendar)));
1019 gdk_window_show (private_data->week_win);
1020 gdk_window_set_user_data (private_data->week_win, widget);
1024 private_data->week_win = NULL;
1029 gtk_calendar_realize (GtkWidget *widget)
1031 GtkCalendar *calendar;
1032 GtkCalendarPrivateData *private_data;
1033 GdkWindowAttr attributes;
1034 gint attributes_mask;
1037 g_return_if_fail (widget != NULL);
1038 g_return_if_fail (GTK_IS_CALENDAR (widget));
1040 calendar = GTK_CALENDAR (widget);
1041 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1043 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
1044 gtk_calendar_compute_days (calendar);
1046 attributes.x = widget->allocation.x;
1047 attributes.y = widget->allocation.y;
1048 attributes.width = widget->allocation.width;
1049 attributes.height = widget->allocation.height;
1050 attributes.wclass = GDK_INPUT_OUTPUT;
1051 attributes.window_type = GDK_WINDOW_CHILD;
1052 attributes.event_mask = (gtk_widget_get_events (widget)
1053 | GDK_EXPOSURE_MASK |GDK_KEY_PRESS_MASK);
1054 attributes.visual = gtk_widget_get_visual (widget);
1055 attributes.colormap = gtk_widget_get_colormap (widget);
1057 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1058 widget->window = gdk_window_new (widget->parent->window,
1059 &attributes, attributes_mask);
1061 widget->style = gtk_style_attach (widget->style, widget->window);
1063 /* Header window ------------------------------------- */
1064 gtk_calendar_realize_header (widget);
1065 /* Day names window --------------------------------- */
1066 gtk_calendar_realize_day_names (widget);
1067 /* Week number window -------------------------------- */
1068 gtk_calendar_realize_week_numbers (widget);
1069 /* Main Window -------------------------------------- */
1070 attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK
1071 | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
1072 | GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK);
1074 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1075 attributes.x = private_data->week_width;
1078 attributes.x += (widget->style->klass->xthickness + INNER_BORDER);
1079 attributes.y = (private_data->header_h + private_data->day_name_h
1080 + (widget->style->klass->ythickness + INNER_BORDER));
1081 attributes.width = (widget->allocation.width - attributes.x
1082 - (widget->style->klass->xthickness + INNER_BORDER));
1083 attributes.height = private_data->main_h;
1084 private_data->main_win = gdk_window_new (widget->window,
1085 &attributes, attributes_mask);
1086 gdk_window_set_background (private_data->main_win,
1087 BACKGROUND_COLOR ( GTK_WIDGET ( calendar)));
1088 gdk_window_show (private_data->main_win);
1089 gdk_window_set_user_data (private_data->main_win, widget);
1090 gdk_window_set_background (widget->window, BACKGROUND_COLOR (widget));
1091 gdk_window_show (widget->window);
1092 gdk_window_set_user_data (widget->window, widget);
1094 /* Set widgets gc */
1095 calendar->gc = gdk_gc_new (widget->window);
1097 values.foreground = widget->style->white;
1098 values.function = GDK_XOR;
1099 calendar->xor_gc = gdk_gc_new_with_values (widget->window,
1106 gtk_calendar_unrealize (GtkWidget *widget)
1108 GtkCalendar *calendar;
1109 GtkCalendarPrivateData *private_data;
1112 g_return_if_fail (widget != NULL);
1113 g_return_if_fail (GTK_IS_CALENDAR (widget));
1115 calendar = GTK_CALENDAR (widget);
1116 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1118 if (private_data->header_win)
1120 for (i = 0; i < 4; i++)
1122 if (private_data->arrow_win[i])
1124 gdk_window_set_user_data (private_data->arrow_win[i], NULL);
1125 gdk_window_destroy (private_data->arrow_win[i]);
1126 private_data->arrow_win[i] = NULL;
1129 gdk_window_set_user_data (private_data->header_win, NULL);
1130 gdk_window_destroy (private_data->header_win);
1131 private_data->header_win = NULL;
1134 if (private_data->week_win)
1136 gdk_window_set_user_data (private_data->week_win, NULL);
1137 gdk_window_destroy (private_data->week_win);
1138 private_data->week_win = NULL;
1141 if (private_data->main_win)
1143 gdk_window_set_user_data (private_data->main_win, NULL);
1144 gdk_window_destroy (private_data->main_win);
1145 private_data->main_win = NULL;
1148 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1149 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1153 gtk_calendar_size_request (GtkWidget *widget,
1154 GtkRequisition *requisition)
1156 GtkCalendar *calendar;
1157 GtkCalendarPrivateData *private_data;
1162 gint calendar_margin = CALENDAR_MARGIN;
1163 gint header_width, main_width;
1170 calendar = GTK_CALENDAR (widget);
1171 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1174 * Calculate the requisition width for the widget.
1179 if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING)
1181 private_data->max_month_width = 0;
1182 for (i = 0; i < 12; i++)
1184 private_data->max_month_width = MAX (private_data->max_month_width,
1185 gdk_string_measure (HEADER_FONT (widget),
1186 default_monthname[i]) + 8);
1188 private_data->max_year_width = 0;
1189 for (i=0; i<10; i++)
1191 sprintf (buffer, "%d%d%d%d", i,i,i,i);
1192 private_data->max_year_width = MAX (private_data->max_year_width,
1193 gdk_string_measure (HEADER_FONT (widget),
1199 private_data->max_month_width = 0;
1200 private_data->max_year_width = 0;
1203 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
1204 header_width = (private_data->max_month_width
1205 + private_data->max_year_width
1208 header_width = (private_data->max_month_width
1209 + private_data->max_year_width
1210 + 4 * private_data->arrow_width + 3 * 3);
1212 /* Mainwindow labels width */
1214 private_data->max_day_char_width = 0;
1215 for (i = 0; i < 9; i++)
1217 sprintf (buffer, "%d%d", i, i);
1218 private_data->min_day_width = MAX (private_data->max_day_char_width,
1219 gdk_string_measure (DAY_FONT (widget),
1222 /* We add one to max_day_char_width to be able to make the marked day "bold" */
1223 private_data->max_day_char_width = private_data->min_day_width / 2 +1;
1225 if (calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
1226 for (i = 0; i < 7; i++)
1228 gdk_text_extents (LABEL_FONT (widget),
1229 default_abbreviated_dayname[i],
1230 strlen(default_abbreviated_dayname[i]),
1236 private_data->min_day_width = MAX (private_data->min_day_width, width);
1237 private_data->max_label_char_ascent = MAX (private_data->max_label_char_ascent,
1239 private_data->max_label_char_descent = MAX (private_data->max_label_char_descent,
1243 private_data->max_week_char_width = 0;
1244 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1245 for (i = 0; i < 9; i++)
1247 sprintf (buffer, "%d%d", i, i);
1248 private_data->max_week_char_width = MAX (private_data->max_week_char_width,
1249 gdk_string_measure (LABEL_FONT (widget), buffer) / 2);
1252 main_width = (7 * (private_data->min_day_width + DAY_XPAD * 2) + (DAY_XSEP * 6) + CALENDAR_MARGIN * 2
1253 + (private_data->max_week_char_width
1254 ? private_data->max_week_char_width * 2 + DAY_XPAD * 2 + CALENDAR_XSEP * 2
1258 requisition->width = MAX (header_width+4, main_width + (widget->style->klass->xthickness + INNER_BORDER) *2);
1261 * Calculate the requisition height for the widget.
1264 if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING)
1266 private_data->header_h = (HEADER_FONT (widget)->ascent
1267 + HEADER_FONT (widget)->descent
1268 + CALENDAR_YSEP * 2);
1272 private_data->header_h = 0;
1275 if (calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
1277 private_data->day_name_h = (private_data->max_label_char_ascent
1278 + private_data->max_label_char_descent
1279 + 2 * DAY_YPAD + calendar_margin);
1280 calendar_margin = CALENDAR_YSEP;
1284 private_data->day_name_h = 0;
1287 gdk_text_extents (DAY_FONT (widget),
1293 &private_data->max_day_char_ascent,
1294 &private_data->max_day_char_descent);
1296 private_data->main_h = (CALENDAR_MARGIN + calendar_margin
1297 + 6 * (private_data->max_day_char_ascent
1298 + private_data->max_day_char_descent
1303 * If we display weeknumbers we need some extra space
1306 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1308 private_data->main_h = MAX (private_data->main_h,
1309 (CALENDAR_MARGIN + calendar_margin
1310 + 6 * (private_data->max_day_char_ascent
1311 + private_data->max_day_char_descent
1316 height = (private_data->header_h + private_data->day_name_h
1317 + private_data->main_h);
1319 requisition->height = height + (widget->style->klass->ythickness + INNER_BORDER) * 2;
1323 gtk_calendar_size_allocate (GtkWidget *widget,
1324 GtkAllocation *allocation)
1326 GtkCalendar *calendar;
1327 GtkCalendarPrivateData *private_data;
1329 g_return_if_fail (widget != NULL);
1330 g_return_if_fail (GTK_IS_CALENDAR (widget));
1331 g_return_if_fail (allocation != NULL);
1333 widget->allocation = *allocation;
1335 calendar = GTK_CALENDAR (widget);
1336 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1338 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1340 private_data->day_width = (private_data->min_day_width
1341 * ((allocation->width - (widget->style->klass->xthickness + INNER_BORDER) * 2
1342 - (CALENDAR_MARGIN * 2) - (DAY_XSEP * 7) - CALENDAR_XSEP * 2))
1343 / (7 * private_data->min_day_width + private_data->max_week_char_width * 2));
1344 private_data->week_width = ((allocation->width - (widget->style->klass->xthickness + INNER_BORDER) * 2
1345 - (CALENDAR_MARGIN * 2) - (DAY_XSEP * 7) - CALENDAR_XSEP * 2 )
1346 - private_data->day_width * 7 + CALENDAR_MARGIN + CALENDAR_XSEP);
1350 private_data->day_width = (allocation->width
1351 - (widget->style->klass->xthickness + INNER_BORDER) * 2
1352 - (CALENDAR_MARGIN * 2)
1353 - (DAY_XSEP * 7))/7;
1354 private_data->week_width = 0;
1357 if (GTK_WIDGET_REALIZED (widget))
1359 gdk_window_move_resize (widget->window,
1360 allocation->x, allocation->y,
1361 allocation->width, allocation->height);
1362 if (private_data->header_win)
1363 gdk_window_move_resize (private_data->header_win,
1365 allocation->width-4, private_data->header_h);
1366 if (private_data->arrow_win[ARROW_MONTH_LEFT])
1367 gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_LEFT],
1369 private_data->arrow_width,
1370 private_data->header_h - 7);
1371 if (private_data->arrow_win[ARROW_MONTH_RIGHT])
1372 gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_RIGHT],
1373 (private_data->arrow_width
1374 + private_data->max_month_width),
1376 private_data->arrow_width,
1377 private_data->header_h - 7);
1378 if (private_data->arrow_win[ARROW_YEAR_LEFT])
1379 gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_LEFT],
1380 (allocation->width - 4
1381 - (3 + 2*private_data->arrow_width
1382 + private_data->max_year_width)),
1384 private_data->arrow_width,
1385 private_data->header_h - 7);
1386 if (private_data->arrow_win[ARROW_YEAR_RIGHT])
1387 gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_RIGHT],
1388 (allocation->width - 4
1389 - 3 - private_data->arrow_width),
1391 private_data->arrow_width,
1392 private_data->header_h - 7);
1393 if (private_data->day_name_win)
1394 gdk_window_move_resize (private_data->day_name_win,
1395 widget->style->klass->xthickness + INNER_BORDER,
1396 private_data->header_h + (widget->style->klass->ythickness + INNER_BORDER),
1397 allocation->width - (widget->style->klass->xthickness + INNER_BORDER) * 2,
1398 private_data->day_name_h);
1399 if (private_data->week_win)
1400 gdk_window_move_resize (private_data->week_win,
1401 (widget->style->klass->xthickness + INNER_BORDER),
1402 private_data->header_h + private_data->day_name_h
1403 + (widget->style->klass->ythickness + INNER_BORDER),
1404 private_data->week_width,
1405 private_data->main_h);
1406 gdk_window_move_resize (private_data->main_win,
1407 (private_data->week_width ? private_data->week_width + CALENDAR_XSEP :0)
1408 + (widget->style->klass->xthickness + INNER_BORDER),
1409 private_data->header_h + private_data->day_name_h
1410 + (widget->style->klass->ythickness + INNER_BORDER),
1412 - (private_data->week_width ? private_data->week_width + CALENDAR_XSEP :0)
1413 - (widget->style->klass->xthickness + INNER_BORDER) * 2,
1414 private_data->main_h);
1419 gtk_calendar_draw_focus (GtkWidget *widget)
1421 GtkCalendar *calendar;
1422 GtkCalendarPrivateData *private_data;
1426 g_return_if_fail (widget != NULL);
1427 g_return_if_fail (GTK_IS_CALENDAR (widget));
1429 calendar = GTK_CALENDAR (widget);
1430 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1432 if (GTK_WIDGET_DRAWABLE (widget))
1436 gdk_window_get_size (widget->window, &width, &height);
1437 gdk_window_clear (widget->window);
1439 gdk_draw_rectangle (widget->window,
1440 widget->style->base_gc[GTK_WIDGET_STATE (widget)],
1441 FALSE, x + 2, y + 2, width - 5, height - 5);
1443 gtk_draw_shadow (widget->style, widget->window,
1444 GTK_STATE_NORMAL, GTK_SHADOW_IN,
1445 x, y, width, height);
1451 gtk_calendar_expose (GtkWidget *widget,
1452 GdkEventExpose *event)
1454 GtkCalendar *calendar;
1455 GtkCalendarPrivateData *private_data;
1457 g_return_val_if_fail (widget != NULL, FALSE);
1458 g_return_val_if_fail (GTK_IS_CALENDAR (widget), FALSE);
1459 g_return_val_if_fail (event != NULL, FALSE);
1461 calendar = GTK_CALENDAR (widget);
1462 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1464 if (GTK_WIDGET_DRAWABLE (widget))
1466 if (event->window == private_data->main_win)
1467 gtk_calendar_paint_main (widget);
1469 if (event->window == private_data->header_win)
1470 gtk_calendar_paint_header (widget);
1472 if (event->window == private_data->day_name_win)
1473 gtk_calendar_paint_day_names (widget);
1475 if (event->window == private_data->week_win)
1476 gtk_calendar_paint_week_numbers (widget);
1477 if (event->window == widget->window)
1478 gtk_widget_draw_focus (widget);
1485 gtk_calendar_draw (GtkWidget *widget,
1488 g_return_if_fail (widget != NULL);
1489 g_return_if_fail (GTK_IS_CALENDAR (widget));
1490 g_return_if_fail (area != NULL);
1492 if (GTK_WIDGET_DRAWABLE (widget))
1493 gtk_calendar_paint (widget, area);
1498 gtk_calendar_paint (GtkWidget *widget,
1501 GtkCalendar *calendar;
1502 GtkCalendarPrivateData *private_data;
1504 g_return_if_fail (widget != NULL);
1505 g_return_if_fail (widget->window != NULL);
1506 g_return_if_fail (GTK_IS_CALENDAR (widget));
1508 calendar = GTK_CALENDAR (widget);
1509 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1511 if (private_data->main_win != NULL)
1512 gtk_calendar_paint_main (widget);
1514 if (private_data->header_win != NULL)
1515 gtk_calendar_paint_header (widget);
1517 if (private_data->day_name_win != NULL)
1518 gtk_calendar_paint_day_names (widget);
1520 if (private_data->week_win != NULL)
1521 gtk_calendar_paint_week_numbers (widget);
1523 gtk_widget_draw_focus (widget);
1527 gtk_calendar_paint_header (GtkWidget *widget)
1529 GtkCalendar *calendar;
1533 gint header_width, cal_height;
1535 gint max_month_width;
1536 gint max_year_width;
1537 GtkCalendarPrivateData *private_data;
1539 calendar = GTK_CALENDAR (widget);
1540 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1542 if (private_data->freeze_count)
1544 private_data->dirty_header = 1;
1547 private_data->dirty_header = 0;
1551 gdk_window_clear (private_data->header_win);
1553 header_width = widget->allocation.width - 4;
1554 cal_height = widget->allocation.height;
1556 max_month_width = private_data->max_month_width;
1557 max_year_width = private_data->max_year_width;
1559 gdk_gc_set_foreground (gc, BACKGROUND_COLOR (GTK_WIDGET (calendar)));
1560 gtk_draw_shadow (widget->style, private_data->header_win,
1561 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1562 0, 0, header_width, private_data->header_h);
1566 y = private_data->header_h - (private_data->header_h
1567 - HEADER_FONT (widget)->ascent
1568 + HEADER_FONT (widget)->descent) / 2;
1569 y_arrow = (private_data->header_h - 9) / 2;
1571 /* Draw year and its arrows */
1572 sprintf (buffer, "%d", calendar->year);
1573 str_width = gdk_string_measure (HEADER_FONT (widget), buffer);
1574 gdk_gc_set_foreground (gc, HEADER_FG_COLOR (GTK_WIDGET (calendar)));
1575 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
1576 gdk_draw_string (private_data->header_win, HEADER_FONT (widget), gc,
1577 header_width - (3 + max_year_width
1578 - (max_year_width - str_width)/2),
1581 gdk_draw_string (private_data->header_win, HEADER_FONT (widget), gc,
1582 header_width - (3 + private_data->arrow_width + max_year_width
1583 - (max_year_width - str_width)/2),
1587 sprintf (buffer, "%s", default_monthname[calendar->month]);
1588 str_width = gdk_string_measure (HEADER_FONT (widget), buffer);
1589 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
1590 gdk_draw_string (private_data->header_win, HEADER_FONT (widget), gc,
1591 3 + (max_month_width - str_width) / 2,
1594 gdk_draw_string (private_data->header_win, HEADER_FONT (widget), gc,
1595 3 + private_data->arrow_width + (max_month_width - str_width)/2,
1598 y += CALENDAR_YSEP + HEADER_FONT (widget)->descent;
1600 gdk_gc_set_foreground (gc, BACKGROUND_COLOR (GTK_WIDGET (calendar)));
1602 gtk_calendar_paint_arrow (widget, ARROW_MONTH_LEFT);
1603 gtk_calendar_paint_arrow (widget, ARROW_MONTH_RIGHT);
1604 gtk_calendar_paint_arrow (widget, ARROW_YEAR_LEFT);
1605 gtk_calendar_paint_arrow (widget, ARROW_YEAR_RIGHT);
1610 gtk_calendar_paint_day_names (GtkWidget *widget)
1612 GtkCalendar *calendar;
1616 int day_width, cal_width;
1620 GtkCalendarPrivateData *private_data;
1622 g_return_if_fail (widget != NULL);
1623 g_return_if_fail (GTK_IS_CALENDAR (widget));
1624 calendar = GTK_CALENDAR (widget);
1625 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1629 * Handle freeze/thaw functionality
1632 if (private_data->freeze_count)
1634 private_data->dirty_day_names = 1;
1637 private_data->dirty_day_names = 0;
1643 gdk_window_clear (private_data->day_name_win);
1645 day_width = private_data->day_width;
1646 cal_width = widget->allocation.width;
1647 cal_height = widget->allocation.height;
1648 day_wid_sep = day_width + DAY_XSEP;
1651 * Draw rectangles as inverted background for the labels.
1654 gdk_gc_set_foreground (gc, &widget->style->bg[GTK_STATE_SELECTED]);
1655 gdk_draw_rectangle (private_data->day_name_win, gc, TRUE,
1656 CALENDAR_MARGIN, CALENDAR_MARGIN,
1657 cal_width-CALENDAR_MARGIN * 2,
1658 private_data->day_name_h - CALENDAR_MARGIN);
1660 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1661 gdk_draw_rectangle (private_data->day_name_win, gc, TRUE,
1663 private_data->day_name_h - CALENDAR_YSEP,
1664 private_data->week_width - CALENDAR_YSEP - CALENDAR_MARGIN,
1670 gdk_gc_set_foreground (gc, &widget->style->fg[GTK_STATE_SELECTED]);
1671 for (i = 0; i < 7; i++)
1674 if (calendar->display_flags & GTK_CALENDAR_WEEK_START_MONDAY)
1676 sprintf (buffer, "%s", default_abbreviated_dayname[day]);
1677 str_width = gdk_string_measure (LABEL_FONT (widget), buffer);
1678 gdk_draw_string (private_data->day_name_win, LABEL_FONT (widget),
1680 ((private_data->week_width ? CALENDAR_XSEP : CALENDAR_MARGIN)
1682 + private_data->week_width
1683 + (day_width - str_width)/2),
1684 CALENDAR_MARGIN + DAY_YPAD
1685 + private_data->max_label_char_ascent, buffer);
1690 gtk_calendar_paint_week_numbers (GtkWidget *widget)
1692 GtkCalendar *calendar;
1694 gint row, week = 0, year;
1697 gint y_baseline, day_height;
1698 GtkCalendarPrivateData *private_data;
1700 g_return_if_fail (widget != NULL);
1701 g_return_if_fail (widget->window != NULL);
1702 g_return_if_fail (GTK_IS_CALENDAR (widget));
1703 calendar = GTK_CALENDAR (widget);
1704 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1708 * Handle freeze/thaw functionality
1711 if (private_data->freeze_count)
1713 private_data->dirty_week = 1;
1716 private_data->dirty_week = 0;
1722 gdk_window_clear (private_data->week_win);
1725 * Draw a rectangle as inverted background for the labels.
1728 gdk_gc_set_foreground (gc, &widget->style->bg[GTK_STATE_SELECTED]);
1729 if (private_data->day_name_win)
1730 gdk_draw_rectangle (private_data->week_win, gc, TRUE,
1733 private_data->week_width - CALENDAR_MARGIN - CALENDAR_XSEP,
1734 private_data->main_h - CALENDAR_MARGIN);
1736 gdk_draw_rectangle (private_data->week_win, gc, TRUE,
1739 private_data->week_width - CALENDAR_MARGIN - CALENDAR_XSEP,
1740 private_data->main_h - 2 * CALENDAR_MARGIN);
1746 gdk_gc_set_foreground (gc, &widget->style->fg[GTK_STATE_SELECTED]);
1747 day_height = row_height (calendar);
1748 for (row = 0; row < 6; row++)
1750 year = calendar->year;
1751 if (calendar->day[row][6] < 15 && row > 3 && calendar->month == 11)
1753 y_baseline = (top_y_for_row (calendar, row)
1754 + (day_height + LABEL_FONT (widget)->ascent
1755 - LABEL_FONT (widget)->descent)/2);
1756 g_return_if_fail (week_of_year (&week, &year,
1757 ((calendar->day[row][6] < 15 && row > 3 ? 1 : 0)
1758 + calendar->month) % 12 + 1, calendar->day[row][6]));
1759 x_loc= (private_data->week_width - (private_data->week_width - CALENDAR_XSEP
1760 - DAY_XPAD * 2 - CALENDAR_MARGIN ) / 2
1761 - private_data->max_week_char_width
1762 - CALENDAR_XSEP - DAY_XPAD);
1766 sprintf (buffer, "%d", week/10);
1767 gdk_draw_string (private_data->week_win, LABEL_FONT (widget), gc,
1768 x_loc, y_baseline , buffer);
1771 sprintf (buffer, "%d", week%10);
1772 gdk_draw_string (private_data->week_win, LABEL_FONT (widget), gc,
1773 x_loc + private_data->max_week_char_width, y_baseline , buffer);
1778 gtk_calendar_paint_day_num (GtkWidget *widget,
1781 GtkCalendar *calendar;
1782 gint r, c, row, col;
1784 g_return_if_fail (widget != NULL);
1785 g_return_if_fail (GTK_IS_CALENDAR (widget));
1787 calendar = GTK_CALENDAR (widget);
1791 for (r = 0; r < 6; r++)
1792 for (c = 0; c < 7; c++)
1793 if (calendar->day_month[r][c] == MONTH_CURRENT &&
1794 calendar->day[r][c] == day)
1800 g_return_if_fail (row != -1);
1801 g_return_if_fail (col != -1);
1803 gtk_calendar_paint_day (widget, row, col);
1807 gtk_calendar_paint_day (GtkWidget *widget,
1811 GtkCalendar *calendar;
1821 GtkCalendarPrivateData *private_data;
1823 g_return_if_fail (widget != NULL);
1824 g_return_if_fail (GTK_IS_CALENDAR (widget));
1825 g_return_if_fail (row < 6);
1826 g_return_if_fail (col < 7);
1827 calendar = GTK_CALENDAR (widget);
1828 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1831 * Handle freeze/thaw functionality
1834 if (private_data->freeze_count)
1836 private_data->dirty_main = 1;
1840 day_height = row_height (calendar);
1842 day_xspace = private_data->day_width - private_data->max_day_char_width*2;
1844 day = calendar->day[row][col];
1846 x_left = left_x_for_column (calendar, col);
1847 x_loc = x_left + private_data->day_width / 2 + private_data->max_day_char_width;
1849 y_top = top_y_for_row (calendar, row);
1850 y_baseline = y_top + (day_height + private_data->max_day_char_ascent)/2;
1852 gdk_window_clear_area (private_data->main_win, x_left, y_top,
1853 private_data->day_width, day_height);
1857 if (calendar->day_month[row][col] == MONTH_PREV)
1859 gdk_gc_set_foreground (gc, PREV_MONTH_COLOR (GTK_WIDGET (calendar)));
1861 else if (calendar->day_month[row][col] == MONTH_NEXT)
1863 gdk_gc_set_foreground (gc, NEXT_MONTH_COLOR (GTK_WIDGET (calendar)));
1868 if (calendar->highlight_row == row && calendar->highlight_col == col)
1870 gdk_gc_set_foreground (gc, HIGHLIGHT_BACK_COLOR (GTK_WIDGET (calendar)));
1871 gdk_draw_rectangle (private_data->main_win, gc, TRUE, x_left, y_top,
1872 private_data->day_width, day_height);
1875 if (calendar->selected_day == day)
1877 gdk_gc_set_foreground (gc, & (GTK_WIDGET (calendar)->style->bg[GTK_STATE_SELECTED]));
1878 gdk_draw_rectangle (private_data->main_win, gc, TRUE, x_left, y_top,
1879 private_data->day_width, day_height);
1882 if (calendar->marked_date[day-1])
1883 gdk_gc_set_foreground (gc, MARKED_COLOR (GTK_WIDGET (calendar)));
1885 gdk_gc_set_foreground (gc, NORMAL_DAY_COLOR (GTK_WIDGET (calendar)));
1887 if (calendar->selected_day == day)
1888 gdk_gc_set_foreground (gc, & (GTK_WIDGET (calendar)->style->fg[GTK_STATE_SELECTED]));
1890 gdk_gc_set_foreground (gc, & (GTK_WIDGET (calendar)->style->fg[GTK_WIDGET_STATE (calendar)]));
1894 sprintf (buffer, "%d", day);
1895 x_loc -= gdk_string_measure (DAY_FONT (widget), buffer);
1896 sprintf (buffer, "%d", day);
1897 gdk_draw_string (private_data->main_win,
1898 DAY_FONT (widget), gc,
1899 x_loc, y_baseline, buffer);
1900 if (calendar->marked_date[day-1]
1901 && calendar->day_month[row][col] == MONTH_CURRENT)
1902 gdk_draw_string (private_data->main_win,
1903 DAY_FONT (widget), gc,
1904 x_loc-1, y_baseline, buffer);
1906 if (GTK_WIDGET_HAS_FOCUS (calendar)
1907 && calendar->focus_row == row && calendar->focus_col == col)
1909 gdk_draw_rectangle (private_data->main_win, calendar->xor_gc,
1910 FALSE, x_left, y_top,
1911 private_data->day_width-1, day_height-1);
1918 gtk_calendar_paint_main (GtkWidget *widget)
1920 GtkCalendar *calendar;
1921 GtkCalendarPrivateData *private_data;
1924 g_return_if_fail (widget != NULL);
1925 g_return_if_fail (widget->window != NULL);
1926 g_return_if_fail (GTK_IS_CALENDAR (widget));
1928 calendar = GTK_CALENDAR (widget);
1929 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1931 if (private_data->freeze_count)
1933 private_data->dirty_main = 1;
1936 private_data->dirty_main = 0;
1937 gdk_window_clear (private_data->main_win);
1939 /* gtk_calendar_compute_days (calendar); */ /* REMOVE later */
1941 for (col = 0; col < 7; col++)
1942 for (row = 0; row < 6; row++)
1943 gtk_calendar_paint_day (widget, row, col);
1947 gtk_calendar_compute_days (GtkCalendar *calendar)
1951 gint ndays_in_month;
1952 gint ndays_in_prev_month;
1958 g_return_if_fail (calendar != NULL);
1959 g_return_if_fail (GTK_IS_CALENDAR (calendar));
1961 year = calendar->year;
1962 month = calendar->month + 1;
1964 ndays_in_month = month_length[leap (year)][month];
1966 first_day = day_of_week (year, month, 1);
1968 if (calendar->display_flags & GTK_CALENDAR_WEEK_START_MONDAY)
1974 /* Compute days of previous month */
1976 ndays_in_prev_month = month_length[leap (year)][month-1];
1978 ndays_in_prev_month = month_length[leap (year)][12];
1979 day = ndays_in_prev_month - first_day + 1;
1984 for (col = 0; col < first_day; col++)
1986 calendar->day[row][col] = day;
1987 calendar->day_month[row][col] = MONTH_PREV;
1992 /* Compute days of current month */
1994 for (day = 1; day <= ndays_in_month; day++)
1996 calendar->day[row][col] = day;
1997 calendar->day_month[row][col] = MONTH_CURRENT;
2007 /* Compute days of next month */
2009 for (; row <= 5; row++)
2011 for (; col <= 6; col++)
2013 calendar->day[row][col] = day;
2014 calendar->day_month[row][col] = MONTH_NEXT;
2021 /* ----------------------------------------------------------------------
2022 NAME: gtk_calendar_display_options
2023 DESCRIPTION: Set display options (whether to display the
2024 heading and the month headings)
2026 flags is can be an XOR of:
2027 GTK_CALENDAR_SHOW_HEADING
2028 GTK_CALENDAR_SHOW_DAY_NAMES
2029 GTK_CALENDAR_NO_MONTH_CHANGE
2030 GTK_CALENDAR_SHOW_WEEK_NUMBERS
2031 GTK_CALENDAR_WEEK_START_MONDAY
2032 ---------------------------------------------------------------------- */
2035 gtk_calendar_display_options (GtkCalendar *calendar,
2036 GtkCalendarDisplayOptions flags)
2038 GtkCalendarPrivateData *private_data;
2043 g_return_if_fail (calendar != NULL);
2044 g_return_if_fail (GTK_IS_CALENDAR (calendar));
2046 widget = GTK_WIDGET (calendar);
2047 private_data = GTK_CALENDAR_PRIVATE_DATA (calendar);
2049 if (GTK_WIDGET_REALIZED (widget))
2051 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_NO_MONTH_CHANGE)
2054 if (! (flags & GTK_CALENDAR_NO_MONTH_CHANGE)
2055 && (private_data->header_win))
2057 calendar->display_flags &= ~GTK_CALENDAR_NO_MONTH_CHANGE;
2058 gtk_calendar_realize_arrows (widget);
2062 for (i = 0; i < 4; i++)
2064 if (private_data->arrow_win[i])
2066 gdk_window_set_user_data (private_data->arrow_win[i],
2068 gdk_window_destroy (private_data->arrow_win[i]);
2069 private_data->arrow_win[i] = NULL;
2075 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_HEADING)
2079 if (flags & GTK_CALENDAR_SHOW_HEADING)
2081 calendar->display_flags |= GTK_CALENDAR_SHOW_HEADING;
2082 gtk_calendar_realize_header (widget);
2086 for (i = 0; i < 4; i++)
2088 if (private_data->arrow_win[i])
2090 gdk_window_set_user_data (private_data->arrow_win[i],
2092 gdk_window_destroy (private_data->arrow_win[i]);
2093 private_data->arrow_win[i] = NULL;
2096 gdk_window_set_user_data (private_data->header_win, NULL);
2097 gdk_window_destroy (private_data->header_win);
2098 private_data->header_win = NULL;
2103 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_DAY_NAMES)
2107 if (flags & GTK_CALENDAR_SHOW_DAY_NAMES)
2109 calendar->display_flags |= GTK_CALENDAR_SHOW_DAY_NAMES;
2110 gtk_calendar_realize_day_names (widget);
2114 gdk_window_set_user_data (private_data->day_name_win, NULL);
2115 gdk_window_destroy (private_data->day_name_win);
2116 private_data->day_name_win = NULL;
2120 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
2124 if (flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
2126 calendar->display_flags |= GTK_CALENDAR_SHOW_WEEK_NUMBERS;
2127 gtk_calendar_realize_week_numbers (widget);
2131 gdk_window_set_user_data (private_data->week_win, NULL);
2132 gdk_window_destroy (private_data->week_win);
2133 private_data->week_win = NULL;
2137 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_WEEK_START_MONDAY)
2139 if (calendar->display_flags & GTK_CALENDAR_WEEK_START_MONDAY)
2140 calendar->display_flags &= ~GTK_CALENDAR_WEEK_START_MONDAY;
2142 calendar->display_flags |= GTK_CALENDAR_WEEK_START_MONDAY;
2144 gtk_calendar_compute_days (calendar);
2145 gtk_calendar_paint_main (GTK_WIDGET (calendar));
2146 if (private_data->day_name_win)
2147 gtk_calendar_paint_day_names (GTK_WIDGET (calendar));
2150 calendar->display_flags = flags;
2152 gtk_widget_queue_resize (GTK_WIDGET (calendar));
2156 calendar->display_flags = flags;
2161 gtk_calendar_select_month (GtkCalendar *calendar,
2165 g_return_val_if_fail (calendar != NULL, FALSE);
2166 g_return_val_if_fail (GTK_IS_CALENDAR (calendar), FALSE);
2167 g_return_val_if_fail (month <= 11, FALSE);
2169 calendar->month = month;
2170 calendar->year = year;
2172 gtk_calendar_compute_days (calendar);
2174 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar)))
2175 gtk_calendar_paint (GTK_WIDGET (calendar), NULL);
2177 gtk_signal_emit (GTK_OBJECT (calendar),
2178 gtk_calendar_signals[MONTH_CHANGED_SIGNAL]);
2183 gtk_calendar_select_day (GtkCalendar *calendar,
2186 g_return_if_fail (calendar != NULL);
2187 g_return_if_fail (GTK_IS_CALENDAR (calendar));
2188 g_return_if_fail (day <= 31);
2190 /* gtk_calendar_compute_days (calendar); */
2192 /* Deselect the old day */
2193 if (calendar->selected_day > 0)
2197 selected_day = calendar->selected_day;
2198 calendar->selected_day = 0;
2199 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar)))
2200 gtk_calendar_paint_day_num (GTK_WIDGET (calendar), selected_day);
2203 calendar->selected_day = day;
2205 /* Deselect the new day */
2208 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar)))
2209 gtk_calendar_paint_day_num (GTK_WIDGET (calendar), day);
2212 gtk_signal_emit (GTK_OBJECT (calendar),
2213 gtk_calendar_signals[DAY_SELECTED_SIGNAL]);
2217 gtk_calendar_clear_marks (GtkCalendar *calendar)
2221 g_return_if_fail (calendar != NULL);
2222 g_return_if_fail (GTK_IS_CALENDAR (calendar));
2224 for (day = 0; day < 31; day++)
2226 calendar->marked_date[day] = FALSE;
2229 calendar->num_marked_dates = 0;
2231 if (GTK_WIDGET_DRAWABLE (calendar))
2233 gtk_calendar_paint_main (GTK_WIDGET (calendar));
2238 gtk_calendar_mark_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 && calendar->marked_date[day-1] == FALSE)
2246 calendar->marked_date[day - 1] = TRUE;
2247 calendar->num_marked_dates++;
2249 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar)))
2251 gtk_calendar_paint_main (GTK_WIDGET (calendar));
2258 gtk_calendar_unmark_day (GtkCalendar *calendar,
2261 g_return_val_if_fail (calendar != NULL, FALSE);
2262 g_return_val_if_fail (GTK_IS_CALENDAR (calendar), FALSE);
2264 if (day >= 1 && day <= 31 && calendar->marked_date[day-1] == TRUE)
2266 calendar->marked_date[day - 1] = FALSE;
2267 calendar->num_marked_dates--;
2270 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar)))
2272 gtk_calendar_paint_main (GTK_WIDGET (calendar));
2279 gtk_calendar_get_date (GtkCalendar *calendar,
2284 g_return_if_fail (calendar != NULL);
2285 g_return_if_fail (GTK_IS_CALENDAR (calendar));
2288 *year = calendar->year;
2291 *month = calendar->month;
2294 *day = calendar->selected_day;
2298 gtk_calendar_button_press (GtkWidget *widget,
2299 GdkEventButton *event)
2301 GtkCalendar *calendar;
2302 GtkCalendarPrivateData *private_data;
2305 g_return_val_if_fail (widget != NULL, FALSE);
2306 g_return_val_if_fail (GTK_IS_CALENDAR (widget), FALSE);
2307 g_return_val_if_fail (event != NULL, FALSE);
2309 calendar = GTK_CALENDAR (widget);
2310 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2312 x = (gint) (event->x);
2313 y = (gint) (event->y);
2315 if (event->window == private_data->main_win)
2316 gtk_calendar_main_button (widget, event);
2318 if (event->type != GDK_BUTTON_PRESS)
2319 return FALSE; /* Double-clicks? Triple-clicks? No thanks! */
2321 if (event->window == private_data->arrow_win[ARROW_MONTH_LEFT])
2322 gtk_calendar_set_month_prev (calendar);
2324 if (event->window == private_data->arrow_win[ARROW_MONTH_RIGHT])
2325 gtk_calendar_set_month_next (calendar);
2327 if (event->window == private_data->arrow_win[ARROW_YEAR_LEFT])
2328 gtk_calendar_set_year_prev (calendar);
2330 if (event->window == private_data->arrow_win[ARROW_YEAR_RIGHT])
2331 gtk_calendar_set_year_next (calendar);
2337 gtk_calendar_motion_notify (GtkWidget *widget,
2338 GdkEventMotion *event)
2340 GtkCalendar *calendar;
2341 GtkCalendarPrivateData *private_data;
2342 gint event_x, event_y;
2344 gint old_row, old_col;
2346 calendar = GTK_CALENDAR (widget);
2347 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2348 event_x = (gint) (event->x);
2349 event_y = (gint) (event->y);
2351 if (event->window == private_data->main_win)
2354 row = row_from_y (calendar, event_y);
2355 col = column_from_x (calendar, event_x);
2357 if (row != calendar->highlight_row || calendar->highlight_col != col)
2359 old_row = calendar->highlight_row;
2360 old_col = calendar->highlight_col;
2361 if (old_row > -1 && old_col > -1)
2363 calendar->highlight_row = -1;
2364 calendar->highlight_col = -1;
2365 gtk_calendar_paint_day (widget, old_row, old_col);
2368 calendar->highlight_row = row;
2369 calendar->highlight_col = col;
2371 if (row > -1 && col > -1)
2372 gtk_calendar_paint_day (widget, row, col);
2379 gtk_calendar_enter_notify (GtkWidget *widget,
2380 GdkEventCrossing *event)
2382 GtkCalendar *calendar;
2383 GtkCalendarPrivateData *private_data;
2385 g_return_val_if_fail (widget != NULL, FALSE);
2386 g_return_val_if_fail (event != NULL, FALSE);
2388 calendar = GTK_CALENDAR (widget);
2389 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2391 if (event->window == private_data->arrow_win[ARROW_MONTH_LEFT])
2393 private_data->arrow_state[ARROW_MONTH_LEFT] = GTK_STATE_PRELIGHT;
2394 gtk_calendar_paint_arrow (widget, ARROW_MONTH_LEFT);
2397 if (event->window == private_data->arrow_win[ARROW_MONTH_RIGHT])
2399 private_data->arrow_state[ARROW_MONTH_RIGHT] = GTK_STATE_PRELIGHT;
2400 gtk_calendar_paint_arrow (widget, ARROW_MONTH_RIGHT);
2403 if (event->window == private_data->arrow_win[ARROW_YEAR_LEFT])
2405 private_data->arrow_state[ARROW_YEAR_LEFT] = GTK_STATE_PRELIGHT;
2406 gtk_calendar_paint_arrow (widget, ARROW_YEAR_LEFT);
2409 if (event->window == private_data->arrow_win[ARROW_YEAR_RIGHT])
2411 private_data->arrow_state[ARROW_YEAR_RIGHT] = GTK_STATE_PRELIGHT;
2412 gtk_calendar_paint_arrow (widget, ARROW_YEAR_RIGHT);
2419 gtk_calendar_leave_notify (GtkWidget *widget,
2420 GdkEventCrossing *event)
2422 GtkCalendar *calendar;
2423 GtkCalendarPrivateData *private_data;
2427 g_return_val_if_fail (widget != NULL, FALSE);
2428 g_return_val_if_fail (event != NULL, FALSE);
2430 calendar = GTK_CALENDAR (widget);
2431 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2433 if (event->window == private_data->main_win)
2435 row = calendar->highlight_row;
2436 col = calendar->highlight_col;
2437 calendar->highlight_row = -1;
2438 calendar->highlight_col = -1;
2439 if (row > -1 && col > -1)
2440 gtk_calendar_paint_day (widget, row, col);
2443 if (event->window == private_data->arrow_win[ARROW_MONTH_LEFT])
2445 private_data->arrow_state[ARROW_MONTH_LEFT] = GTK_STATE_NORMAL;
2446 gtk_calendar_paint_arrow (widget, ARROW_MONTH_LEFT);
2449 if (event->window == private_data->arrow_win[ARROW_MONTH_RIGHT])
2451 private_data->arrow_state[ARROW_MONTH_RIGHT] = GTK_STATE_NORMAL;
2452 gtk_calendar_paint_arrow (widget, ARROW_MONTH_RIGHT);
2455 if (event->window == private_data->arrow_win[ARROW_YEAR_LEFT])
2457 private_data->arrow_state[ARROW_YEAR_LEFT] = GTK_STATE_NORMAL;
2458 gtk_calendar_paint_arrow (widget, ARROW_YEAR_LEFT);
2461 if (event->window == private_data->arrow_win[ARROW_YEAR_RIGHT])
2463 private_data->arrow_state[ARROW_YEAR_RIGHT] = GTK_STATE_NORMAL;
2464 gtk_calendar_paint_arrow (widget, ARROW_YEAR_RIGHT);
2471 gtk_calendar_paint_arrow (GtkWidget *widget,
2474 GtkCalendarPrivateData *private_data;
2477 GtkCalendar *calendar;
2481 g_return_if_fail (widget != NULL);
2483 calendar = GTK_CALENDAR (widget);
2484 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2486 if (private_data->freeze_count)
2488 private_data->dirty_header = 1;
2491 window = private_data->arrow_win[arrow];
2494 state = private_data->arrow_state[arrow];
2497 gdk_window_clear (window);
2498 gdk_window_set_background (window, &(widget)->style->bg[state]);
2499 gdk_window_get_size (window, &width, &height);
2500 gdk_window_clear_area (window,
2504 gdk_gc_set_foreground (gc, & (widget)->style->fg[state]);
2506 if (arrow == ARROW_MONTH_LEFT || arrow == ARROW_YEAR_LEFT)
2507 draw_arrow_left (window, gc, width/2 - 3, height/2 - 4, 8);
2509 draw_arrow_right (window, gc, width/2 - 2, height/2 - 4, 8);
2515 gtk_calendar_freeze (GtkCalendar *calendar)
2517 g_return_if_fail (calendar != NULL);
2518 g_return_if_fail (GTK_IS_CALENDAR (calendar));
2520 GTK_CALENDAR_PRIVATE_DATA (calendar)->freeze_count++;
2524 gtk_calendar_thaw (GtkCalendar *calendar)
2526 GtkCalendarPrivateData *private_data;
2528 g_return_if_fail (calendar != NULL);
2529 g_return_if_fail (GTK_IS_CALENDAR (calendar));
2531 private_data = GTK_CALENDAR_PRIVATE_DATA (calendar);
2533 if (private_data->freeze_count)
2534 if (!(--private_data->freeze_count))
2536 if (private_data->dirty_header)
2537 if (GTK_WIDGET_DRAWABLE (calendar))
2538 gtk_calendar_paint_header (GTK_WIDGET (calendar));
2540 if (private_data->dirty_day_names)
2541 if (GTK_WIDGET_DRAWABLE (calendar))
2542 gtk_calendar_paint_day_names (GTK_WIDGET (calendar));
2544 if (private_data->dirty_week)
2545 if (GTK_WIDGET_DRAWABLE (calendar))
2546 gtk_calendar_paint_week_numbers (GTK_WIDGET (calendar));
2548 if (private_data->dirty_main)
2549 if (GTK_WIDGET_DRAWABLE (calendar))
2550 gtk_calendar_paint_main (GTK_WIDGET (calendar));
2555 gtk_calendar_set_background (GtkWidget *widget)
2557 GtkCalendar *calendar;
2558 GtkCalendarPrivateData *private_data;
2561 g_return_if_fail (widget != NULL);
2562 g_return_if_fail (GTK_IS_CALENDAR (widget));
2564 calendar = GTK_CALENDAR (widget);
2565 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2567 if (GTK_WIDGET_REALIZED (widget))
2569 for (i = 0; i < 4; i++)
2571 if (private_data->arrow_win[i])
2572 gdk_window_set_background (private_data->arrow_win[i],
2573 HEADER_BG_COLOR (widget));
2575 if (private_data->header_win)
2576 gdk_window_set_background (private_data->header_win,
2577 HEADER_BG_COLOR (widget));
2578 if (private_data->day_name_win)
2579 gdk_window_set_background (private_data->day_name_win,
2580 BACKGROUND_COLOR (widget));
2581 if (private_data->week_win)
2582 gdk_window_set_background (private_data->week_win,
2583 BACKGROUND_COLOR (widget));
2584 if (private_data->main_win)
2585 gdk_window_set_background (private_data->main_win,
2586 BACKGROUND_COLOR (widget));
2588 gdk_window_set_background (widget->window,
2589 BACKGROUND_COLOR (widget));
2594 gtk_calendar_style_set (GtkWidget *widget,
2595 GtkStyle *previous_style)
2597 g_return_if_fail (widget != NULL);
2598 g_return_if_fail (GTK_IS_CALENDAR (widget));
2600 if (previous_style && GTK_WIDGET_REALIZED (widget))
2601 gtk_calendar_set_background(widget);
2605 gtk_calendar_state_changed (GtkWidget *widget,
2606 GtkStateType previous_state)
2608 g_return_if_fail (widget != NULL);
2609 g_return_if_fail (GTK_IS_CALENDAR (widget));
2611 gtk_calendar_set_background (widget);
2615 gtk_calendar_focus_in (GtkWidget *widget,
2616 GdkEventFocus *event)
2618 GtkCalendar *calendar;
2620 g_return_val_if_fail (widget != NULL, FALSE);
2621 g_return_val_if_fail (GTK_IS_CALENDAR (widget), FALSE);
2622 g_return_val_if_fail (event != NULL, FALSE);
2624 calendar = GTK_CALENDAR (widget);
2626 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
2627 gtk_widget_draw_focus (widget);
2628 gtk_calendar_paint_day (widget, calendar->focus_row, calendar->focus_col);
2634 gtk_calendar_focus_out (GtkWidget *widget,
2635 GdkEventFocus *event)
2637 GtkCalendar *calendar;
2639 g_return_val_if_fail (widget != NULL, FALSE);
2640 g_return_val_if_fail (GTK_IS_CALENDAR (widget), FALSE);
2641 g_return_val_if_fail (event != NULL, FALSE);
2643 calendar = GTK_CALENDAR (widget);
2645 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
2646 gtk_widget_draw_focus (widget);
2647 gtk_calendar_paint_day (widget, calendar->focus_row, calendar->focus_col);
2653 gtk_calendar_key_press (GtkWidget *widget,
2656 GtkCalendar *calendar;
2662 g_return_val_if_fail (widget != NULL, FALSE);
2663 g_return_val_if_fail (GTK_IS_CALENDAR (widget), FALSE);
2664 g_return_val_if_fail (event != NULL, FALSE);
2666 calendar = GTK_CALENDAR (widget);
2669 old_focus_row = calendar->focus_row;
2670 old_focus_col = calendar->focus_col;
2672 switch (event->keyval)
2676 if (event->state & GDK_CONTROL_MASK)
2678 gtk_calendar_set_month_prev (calendar);
2682 if (calendar->focus_col > 0)
2684 calendar->focus_col--;
2686 else if (calendar->focus_row > 0)
2688 calendar->focus_col = 6;
2689 calendar->focus_row--;
2691 gtk_calendar_paint_day (widget, old_focus_row, old_focus_col);
2692 gtk_calendar_paint_day (widget, calendar->focus_row,
2693 calendar->focus_col);
2698 if (event->state & GDK_CONTROL_MASK)
2700 gtk_calendar_set_month_next (calendar);
2704 if (calendar->focus_col < 6)
2706 calendar->focus_col++;
2708 else if (calendar->focus_row < 5)
2710 calendar->focus_col = 0;
2711 calendar->focus_row++;
2713 gtk_calendar_paint_day (widget, old_focus_row, old_focus_col);
2714 gtk_calendar_paint_day (widget, calendar->focus_row,
2715 calendar->focus_col);
2720 if (event->state & GDK_CONTROL_MASK)
2722 gtk_calendar_set_year_prev (calendar);
2726 if (calendar->focus_row > 0)
2728 calendar->focus_row--;
2730 gtk_calendar_paint_day (widget, old_focus_row, old_focus_col);
2731 gtk_calendar_paint_day (widget, calendar->focus_row,
2732 calendar->focus_col);
2737 if (event->state & GDK_CONTROL_MASK)
2739 gtk_calendar_set_year_next (calendar);
2743 if (calendar->focus_row < 5)
2745 calendar->focus_row++;
2747 gtk_calendar_paint_day (widget, old_focus_row, old_focus_col);
2748 gtk_calendar_paint_day (widget, calendar->focus_row,
2749 calendar->focus_col);
2753 row = calendar->focus_row;
2754 col = calendar->focus_col;
2755 day = calendar->day[row][col];
2757 if (row > -1 && col > -1)
2759 gtk_calendar_freeze (calendar);
2761 if (calendar->day_month[row][col] == MONTH_PREV)
2763 gtk_calendar_set_month_prev (calendar);
2765 else if (calendar->day_month[row][col] == MONTH_NEXT)
2767 gtk_calendar_set_month_next (calendar);
2770 gtk_calendar_select_day (calendar, day);
2772 for (row = 0; row < 6; row ++)
2773 for (col = 0; col < 7; col++)
2775 if (calendar->day_month[row][col] == MONTH_CURRENT
2776 && calendar->day[row][col] == day)
2778 calendar->focus_row = row;
2779 calendar->focus_col = col;
2782 gtk_calendar_thaw (calendar);