📄 calendar.c
字号:
#include <gtk/gtk.h>
#include <sys/time.h>#include <string.h>#include <stdlib.h>#include <time.h>#include <stdio.h>
int timeout_handler = 0;
#include "support.h"
#include "calendar.h"
#include "lunarcalendar.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 calendar_signals[LAST_SIGNAL] = { 0 };static GtkWidgetClass *parent_class = NULL;struct _CalendarPrivateData{ 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 CALENDAR_PRIVATE_DATA(widget) (((CalendarPrivateData*)(CALENDAR (widget)->private_data)))typedef void (*CalendarSignalDate) (GtkObject *object, guint arg1, guint arg2, guint arg3, gpointer data);typedef struct _CalendarPrivateData CalendarPrivateData;
static void calendar_class_init (CalendarClass *class);static void calendar_init (Calendar *calendar);static void calendar_destroy (GtkObject *calendar);static void calendar_realize (GtkWidget *widget);static void calendar_unrealize (GtkWidget *widget);static void calendar_draw_focus (GtkWidget *widget);static void calendar_size_request (GtkWidget *widget, GtkRequisition *requisition);static void calendar_size_allocate (GtkWidget *widget, GtkAllocation *allocation);static gint calendar_expose (GtkWidget *widget, GdkEventExpose *event);static gint calendar_button_press (GtkWidget *widget, GdkEventButton *event);static void calendar_main_button (GtkWidget *widget, GdkEventButton *event);static gint calendar_motion_notify (GtkWidget *widget, GdkEventMotion *event);static gint calendar_enter_notify (GtkWidget *widget, GdkEventCrossing *event);static gint calendar_leave_notify (GtkWidget *widget, GdkEventCrossing *event);static gint calendar_key_press (GtkWidget *widget, GdkEventKey *event);static gint calendar_focus_in (GtkWidget *widget, GdkEventFocus *event);static gint calendar_focus_out (GtkWidget *widget, GdkEventFocus *event);static void calendar_state_changed (GtkWidget *widget, GtkStateType previous_state);static void calendar_style_set (GtkWidget *widget, GtkStyle *previous_style);static void calendar_paint_header (GtkWidget *widget);static void calendar_paint_day_names (GtkWidget *widget);static void calendar_paint_week_numbers (GtkWidget *widget);static void calendar_paint_main (GtkWidget *widget);static void calendar_paint (GtkWidget *widget, GdkRectangle *area);static void calendar_paint_arrow (GtkWidget *widget, guint arrow);static void calendar_paint_day_num (GtkWidget *widget, gint day);static void calendar_paint_day (GtkWidget *widget, gint row, gint col);static void calendar_draw (GtkWidget *widget, GdkRectangle *area);static void calendar_compute_days (Calendar *calendar);static gint left_x_for_column (Calendar *calendar, gint column);static gint top_y_for_row (Calendar *calendar, gint row);static char default_abbreviated_dayname[20][30];static char default_monthname[12][30];GtkTypecalendar_get_type (void){ static GtkType calendar_type = 0; if (!calendar_type) { static const GtkTypeInfo calendar_info = { "Calendar", sizeof (Calendar), sizeof (CalendarClass), (GtkClassInitFunc) calendar_class_init, (GtkObjectInitFunc)calendar_init, /* reserved_1 */ NULL, /* reserved_2 */ NULL, (GtkClassInitFunc) NULL, }; calendar_type = gtk_type_unique (GTK_TYPE_WIDGET, &calendar_info); } return calendar_type;}static voidcalendar_class_init (CalendarClass *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 = calendar_realize; widget_class->unrealize = calendar_unrealize; widget_class->expose_event = calendar_expose; widget_class->draw = calendar_draw; widget_class->draw_focus = calendar_draw_focus; widget_class->size_request = calendar_size_request; widget_class->size_allocate = calendar_size_allocate; widget_class->button_press_event = calendar_button_press; widget_class->motion_notify_event = calendar_motion_notify; widget_class->enter_notify_event = calendar_enter_notify; widget_class->leave_notify_event = calendar_leave_notify; widget_class->key_press_event = calendar_key_press; widget_class->focus_in_event = calendar_focus_in; widget_class->focus_out_event = calendar_focus_out; widget_class->style_set = calendar_style_set; widget_class->state_changed = calendar_state_changed; object_class->destroy = calendar_destroy; calendar_signals[MONTH_CHANGED_SIGNAL] = gtk_signal_new ("month_changed", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (CalendarClass, month_changed), gtk_signal_default_marshaller, GTK_TYPE_NONE, 0); calendar_signals[DAY_SELECTED_SIGNAL] = gtk_signal_new ("day_selected", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (CalendarClass, day_selected), gtk_signal_default_marshaller, GTK_TYPE_NONE, 0); calendar_signals[DAY_SELECTED_DOUBLE_CLICK_SIGNAL] = gtk_signal_new ("day_selected_double_click", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (CalendarClass, day_selected_double_click), gtk_signal_default_marshaller, GTK_TYPE_NONE, 0); calendar_signals[PREV_MONTH_SIGNAL] = gtk_signal_new ("prev_month", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (CalendarClass, prev_month), gtk_signal_default_marshaller, GTK_TYPE_NONE, 0); calendar_signals[NEXT_MONTH_SIGNAL] = gtk_signal_new ("next_month", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (CalendarClass, next_month), gtk_signal_default_marshaller, GTK_TYPE_NONE, 0); calendar_signals[PREV_YEAR_SIGNAL] = gtk_signal_new ("prev_year", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (CalendarClass, prev_year), gtk_signal_default_marshaller, GTK_TYPE_NONE, 0); calendar_signals[NEXT_YEAR_SIGNAL] = gtk_signal_new ("next_year", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (CalendarClass, next_year), gtk_signal_default_marshaller, GTK_TYPE_NONE, 0); gtk_object_class_add_signals (object_class, 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 voidcalendar_init (Calendar *calendar){ time_t secs; struct tm *tm; gint i; char buffer[255]; time_t tmp_time; GtkWidget *widget; char *lc_all = NULL; int local = 1; CalendarPrivateData *private_data; lc_all = getenv("LC_ALL"); if(lc_all) local = strncmp(lc_all,"zh_CN.GB2312",strlen(lc_all)); widget = GTK_WIDGET (calendar); GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS); calendar->private_data = (gpointer) malloc (sizeof (CalendarPrivateData)); private_data = CALENDAR_PRIVATE_DATA (calendar);//if (!default_abbreviated_dayname[0]) for (i=0; i<7; i++) { gchar *tmp; tmp_time= (i+3)*86400; strftime ( buffer, sizeof (buffer), "%a", gmtime (&tmp_time));// sscanf(buffer,"%c",&c[0]); if(local){ buffer[1] = 0;/*Jameswen modify */ // buffer[1] = '\r'; // buffer[2] = '\n'; } tmp = g_strdup (_(buffer)); memcpy(default_abbreviated_dayname[i],tmp,strlen(tmp));// = g_strdup (c);// default_abbreviated_dayname[i] = g_strdup ((buffer)); }
//if (!default_monthname[0]) for (i=0; i<12; i++) { gchar *tmp; tmp_time=i*2764800; strftime ( buffer, sizeof (buffer), "%B", gmtime (&tmp_time)); tmp = g_strdup (_(buffer)); memcpy(default_monthname[i],tmp,strlen(tmp));// default_monthname[i] = g_strdup ((buffer)); g_free(tmp); } /* Set defaults */ secs = time (NULL); tm = localtime (&secs); calendar->month = tm->tm_mon; calendar->year = 1900 + tm->tm_year; for (i=0;i<31;i++) calendar->marked_date[i] = FALSE; calendar->num_marked_dates = 0; calendar->selected_day = 1; calendar->display_flags = ( CALENDAR_SHOW_HEADING | CALENDAR_SHOW_DAY_NAMES );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -