📄 gtkcalendar.c
字号:
/* GTK - The GIMP Toolkit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * GTK Calendar Widget * Copyright (C) 1998 Cesar Miquel, Shawn T. Amundson and Mattias Gr鰊lund * * lib_date routines * Copyright (c) 1995, 1996, 1997, 1998 by Steffen Beyer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//* * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */#include <sys/time.h>#include <string.h>#include <stdlib.h>#include <time.h>#include <stdio.h>#include "gtkcalendar.h"#include "gdk/gdkkeysyms.h"/***************************************************************************//* The following date routines are taken from the lib_date package. Keep * them seperate in case we want to update them if a newer lib_date comes * out with fixes. */typedef unsigned int N_int;typedef unsigned long N_long;typedef signed long Z_long;typedef enum { false = FALSE , true = TRUE } boolean;#define and && /* logical (boolean) operators: lower case */#define or ||static const N_int month_length[2][13] ={ { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }};static const N_int days_in_months[2][14] ={ { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }};static Z_long calc_days(N_int year, N_int mm, N_int dd);static N_int day_of_week(N_int year, N_int mm, N_int dd);static Z_long dates_difference(N_int year1, N_int mm1, N_int dd1, N_int year2, N_int mm2, N_int dd2);static N_int weeks_in_year(N_int year);static boolean leap(N_int year){ return((((year % 4) == 0) and ((year % 100) != 0)) or ((year % 400) == 0));}static N_int day_of_week(N_int year, N_int mm, N_int dd){ Z_long days; days = calc_days(year, mm, dd); if (days > 0L) { days--; days %= 7L; days++; } return( (N_int) days );}static N_int weeks_in_year(N_int year){ return(52 + ((day_of_week(year,1,1)==4) or (day_of_week(year,12,31)==4)));}static boolean check_date(N_int year, N_int mm, N_int dd){ if (year < 1) return(false); if ((mm < 1) or (mm > 12)) return(false); if ((dd < 1) or (dd > month_length[leap(year)][mm])) return(false); return(true);}static N_int week_number(N_int year, N_int mm, N_int dd){ N_int first; first = day_of_week(year,1,1) - 1; return( (N_int) ( (dates_difference(year,1,1, year,mm,dd) + first) / 7L ) + (first < 4) );}static Z_long year_to_days(N_int year){ return( year * 365L + (year / 4) - (year / 100) + (year / 400) );}static Z_long calc_days(N_int year, N_int mm, N_int dd){ boolean lp; if (year < 1) return(0L); if ((mm < 1) or (mm > 12)) return(0L); if ((dd < 1) or (dd > month_length[(lp = leap(year))][mm])) return(0L); return( year_to_days(--year) + days_in_months[lp][mm] + dd );}static boolean week_of_year(N_int *week, N_int *year, N_int mm, N_int dd){ if (check_date(*year,mm,dd)) { *week = week_number(*year,mm,dd); if (*week == 0) *week = weeks_in_year(--(*year)); else if (*week > weeks_in_year(*year)) { *week = 1; (*year)++; } return(true); } return(false);}static Z_long dates_difference(N_int year1, N_int mm1, N_int dd1, N_int year2, N_int mm2, N_int dd2){ return( calc_days(year2, mm2, dd2) - calc_days(year1, mm1, dd1) );}/** END OF lib_date routines ************************************************/#define CALENDAR_MARGIN 0#define CALENDAR_YSEP 4#define CALENDAR_XSEP 4#define INNER_BORDER 4#define DAY_XPAD 2#define DAY_YPAD 2#define DAY_XSEP 0 /* not really good for small calendar */#define DAY_YSEP 0 /* not really good for small calendar *//* Color usage */#define HEADER_FG_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])#define HEADER_BG_COLOR(widget) (& (widget)->style->bg[GTK_WIDGET_STATE (widget)])#define DAY_NAME_COLOR(widget) (& (widget)->style->bg[GTK_STATE_SELECTED])#define NORMAL_DAY_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])#define SELECTION_FOCUS_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])#define SELECTION_NO_FOCUS_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])#define PREV_MONTH_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])#define NEXT_MONTH_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])#define MARKED_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])#define FOREGROUND_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])#define BACKGROUND_COLOR(widget) (& (widget)->style->base[GTK_WIDGET_STATE (widget)])#define HIGHLIGHT_BACK_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])#define HEADER_FONT(widget) ((widget)->style->font)#define LABEL_FONT(widget) ((widget)->style->font)#define DAY_FONT(widget) ((widget)->style->font)enum { ARROW_YEAR_LEFT, ARROW_YEAR_RIGHT, ARROW_MONTH_LEFT, ARROW_MONTH_RIGHT};enum { MONTH_PREV, MONTH_CURRENT, MONTH_NEXT};enum { MONTH_CHANGED_SIGNAL, DAY_SELECTED_SIGNAL, DAY_SELECTED_DOUBLE_CLICK_SIGNAL, PREV_MONTH_SIGNAL, NEXT_MONTH_SIGNAL, PREV_YEAR_SIGNAL, NEXT_YEAR_SIGNAL, LAST_SIGNAL};static gint gtk_calendar_signals[LAST_SIGNAL] = { 0 };static GtkWidgetClass *parent_class = NULL;typedef struct _GtkCalendarPrivateData GtkCalendarPrivateData;struct _GtkCalendarPrivateData{ GdkWindow *header_win; GdkWindow *day_name_win; GdkWindow *main_win; GdkWindow *week_win; GdkWindow *arrow_win[4]; guint header_h; guint day_name_h; guint main_h; guint arrow_state[4]; guint arrow_width; guint max_month_width; guint max_year_width; guint day_width; guint week_width; guint min_day_width; guint max_day_char_width; guint max_day_char_ascent; guint max_day_char_descent; guint max_label_char_ascent; guint max_label_char_descent; guint max_week_char_width; guint freeze_count; /* flags */ guint dirty_header : 1; guint dirty_day_names : 1; guint dirty_main : 1; guint dirty_week : 1;};#define GTK_CALENDAR_PRIVATE_DATA(widget) (((GtkCalendarPrivateData*)(GTK_CALENDAR (widget)->private_data)))typedef void (*GtkCalendarSignalDate) (GtkObject *object, guint arg1, guint arg2, guint arg3, gpointer data);static void gtk_calendar_class_init (GtkCalendarClass *class);static void gtk_calendar_init (GtkCalendar *calendar);static void gtk_calendar_realize (GtkWidget *widget);static void gtk_calendar_unrealize (GtkWidget *widget);static void gtk_calendar_draw_focus (GtkWidget *widget);static void gtk_calendar_size_request (GtkWidget *widget, GtkRequisition *requisition);static void gtk_calendar_size_allocate (GtkWidget *widget, GtkAllocation *allocation);static gint gtk_calendar_expose (GtkWidget *widget, GdkEventExpose *event);static gint gtk_calendar_button_press (GtkWidget *widget, GdkEventButton *event);static void gtk_calendar_main_button (GtkWidget *widget, GdkEventButton *event);static gint gtk_calendar_motion_notify (GtkWidget *widget, GdkEventMotion *event);static gint gtk_calendar_enter_notify (GtkWidget *widget, GdkEventCrossing *event);static gint gtk_calendar_leave_notify (GtkWidget *widget, GdkEventCrossing *event);static gint gtk_calendar_key_press (GtkWidget *widget, GdkEventKey *event);static gint gtk_calendar_focus_in (GtkWidget *widget, GdkEventFocus *event);static gint gtk_calendar_focus_out (GtkWidget *widget, GdkEventFocus *event);static void gtk_calendar_state_changed (GtkWidget *widget, GtkStateType previous_state);static void gtk_calendar_style_set (GtkWidget *widget, GtkStyle *previous_style);static void gtk_calendar_paint_header (GtkWidget *widget);static void gtk_calendar_paint_day_names (GtkWidget *widget);static void gtk_calendar_paint_week_numbers (GtkWidget *widget);static void gtk_calendar_paint_main (GtkWidget *widget);static void gtk_calendar_paint (GtkWidget *widget, GdkRectangle *area);static void gtk_calendar_paint_arrow (GtkWidget *widget, guint arrow);static void gtk_calendar_paint_day_num (GtkWidget *widget, gint day);static void gtk_calendar_paint_day (GtkWidget *widget, gint row, gint col);static void gtk_calendar_draw (GtkWidget *widget, GdkRectangle *area);static void gtk_calendar_compute_days (GtkCalendar *calendar);static gint left_x_for_column (GtkCalendar *calendar, gint column);static gint top_y_for_row (GtkCalendar *calendar, gint row);static char *default_abbreviated_dayname[7];static char *default_monthname[12];GtkTypegtk_calendar_get_type (void){ static GtkType calendar_type = 0; if (!calendar_type) { static const GtkTypeInfo calendar_info = { "GtkCalendar", sizeof (GtkCalendar), sizeof (GtkCalendarClass), (GtkClassInitFunc) gtk_calendar_class_init, (GtkObjectInitFunc) gtk_calendar_init, (GtkArgSetFunc) NULL, (GtkArgGetFunc) NULL, }; calendar_type = gtk_type_unique (GTK_TYPE_WIDGET, &calendar_info); } return calendar_type;}static voidgtk_calendar_class_init (GtkCalendarClass *class){ GtkObjectClass *object_class; GtkWidgetClass *widget_class; object_class = (GtkObjectClass*) class; widget_class = (GtkWidgetClass*) class; parent_class = gtk_type_class (GTK_TYPE_WIDGET); widget_class->realize = gtk_calendar_realize; widget_class->unrealize = gtk_calendar_unrealize; widget_class->expose_event = gtk_calendar_expose; widget_class->draw = gtk_calendar_draw; widget_class->draw_focus = gtk_calendar_draw_focus; widget_class->size_request = gtk_calendar_size_request; widget_class->size_allocate = gtk_calendar_size_allocate; widget_class->button_press_event = gtk_calendar_button_press; widget_class->motion_notify_event = gtk_calendar_motion_notify; widget_class->enter_notify_event = gtk_calendar_enter_notify; widget_class->leave_notify_event = gtk_calendar_leave_notify; widget_class->key_press_event = gtk_calendar_key_press; widget_class->focus_in_event = gtk_calendar_focus_in; widget_class->focus_out_event = gtk_calendar_focus_out; widget_class->style_set = gtk_calendar_style_set; widget_class->state_changed = gtk_calendar_state_changed; gtk_calendar_signals[MONTH_CHANGED_SIGNAL] = gtk_signal_new ("month_changed", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (GtkCalendarClass, month_changed), gtk_signal_default_marshaller, GTK_TYPE_NONE, 0); gtk_calendar_signals[DAY_SELECTED_SIGNAL] = gtk_signal_new ("day_selected", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (GtkCalendarClass, day_selected), gtk_signal_default_marshaller, GTK_TYPE_NONE, 0); gtk_calendar_signals[DAY_SELECTED_DOUBLE_CLICK_SIGNAL] = gtk_signal_new ("day_selected_double_click", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (GtkCalendarClass, day_selected_double_click), gtk_signal_default_marshaller, GTK_TYPE_NONE, 0); gtk_calendar_signals[PREV_MONTH_SIGNAL] = gtk_signal_new ("prev_month", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (GtkCalendarClass, prev_month), gtk_signal_default_marshaller, GTK_TYPE_NONE, 0); gtk_calendar_signals[NEXT_MONTH_SIGNAL] = gtk_signal_new ("next_month", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (GtkCalendarClass, next_month), gtk_signal_default_marshaller, GTK_TYPE_NONE, 0); gtk_calendar_signals[PREV_YEAR_SIGNAL] = gtk_signal_new ("prev_year", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (GtkCalendarClass, prev_year), gtk_signal_default_marshaller, GTK_TYPE_NONE, 0); gtk_calendar_signals[NEXT_YEAR_SIGNAL] = gtk_signal_new ("next_year", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (GtkCalendarClass, next_year), gtk_signal_default_marshaller, GTK_TYPE_NONE, 0); gtk_object_class_add_signals (object_class, gtk_calendar_signals, LAST_SIGNAL); class->month_changed = NULL; class->day_selected = NULL; class->day_selected_double_click = NULL; class->prev_month = NULL; class->next_month = NULL; class->prev_year = NULL; class->next_year = NULL;}static voidgtk_calendar_init (GtkCalendar *calendar){ time_t secs; struct tm *tm; gint i; char buffer[255]; time_t tmp_time; GtkWidget *widget; GtkCalendarPrivateData *private_data; widget = GTK_WIDGET (calendar); GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS); calendar->private_data = (gpointer) malloc (sizeof (GtkCalendarPrivateData)); private_data = GTK_CALENDAR_PRIVATE_DATA (calendar); if (!default_abbreviated_dayname[0]) for (i=0; i<7; i++) { tmp_time= (i+3)*86400; strftime ( buffer, sizeof (buffer), "%a", gmtime (&tmp_time)); default_abbreviated_dayname[i] = g_strdup (buffer); } if (!default_monthname[0]) for (i=0; i<12; i++) { tmp_time=i*2764800; strftime ( buffer, sizeof (buffer), "%B", gmtime (&tmp_time)); default_monthname[i] = g_strdup (buffer); } /* Set defaults */ secs = time (NULL); tm = localtime (&secs);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -