/* $Id: datebook_gui.c,v 1.144 2006/08/28 01:44:38 judd Exp $ */ /******************************************************************************* * datebook_gui.c * A module of J-Pilot http://jpilot.org * * Copyright (C) 1999-2002 by Judd Montgomery * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ******************************************************************************/ #define EASTER #include "config.h" #include "i18n.h" #include #include #include #include #include #include #include #include #include #include #include "datebook.h" #include "todo.h" #include "log.h" #include "prefs.h" #include "utils.h" #include "password.h" #include "export.h" #include "print.h" #include "alarms.h" #include "japanese.h" #include "stock_buttons.h" /* #define DAY_VIEW */ #ifdef DAY_VIEW #include "dayview.h" #endif #define PAGE_NONE 0 #define PAGE_DAY 1 #define PAGE_WEEK 2 #define PAGE_MONTH 3 #define PAGE_YEAR 4 #define BEGIN_DATE_BUTTON 5 #define CAL_DAY_SELECTED 327 #define CONNECT_SIGNALS 400 #define DISCONNECT_SIGNALS 401 /* Maximum length of description (not including the null) */ #define MAX_DESC_LEN 255 /* todo check this before every record write */ #define DB_TIME_COLUMN 0 #define DB_NOTE_COLUMN 1 #define DB_ALARM_COLUMN 2 #ifdef ENABLE_DATEBK #define DB_FLOAT_COLUMN 3 static int DB_APPT_COLUMN=4; #else static int DB_APPT_COLUMN=3; #endif #define NUM_DATEBOOK_CAT_ITEMS 16 #define DATEBOOK_MAX_COLUMN_LEN 80 #define UPDATE_DATE_ENTRIES 0x01 #define UPDATE_DATE_MENUS 0x02 #define START_TIME_FLAG 0x00 #define END_TIME_FLAG 0x80 #define HOURS_FLAG 0x40 extern GtkTooltips *glob_tooltips; static GtkWidget *pane; static GtkWidget *note_pane; static GtkWidget *todo_pane; static GtkWidget *todo_vbox; static void highlight_days(); static int datebook_find(); static int datebook_update_clist(); static void update_endon_button(GtkWidget *button, struct tm *t); static void set_begin_end_labels(struct tm *begin, struct tm *end, int flags); static void cb_clist_selection(GtkWidget *clist, gint row, gint column, GdkEventButton *event, gpointer data); static void cb_add_new_record(GtkWidget *widget, gpointer data); static void cb_cal_changed(GtkWidget *widget, gpointer data); static void set_new_button_to(int new_state); static void connect_changed_signals(int con_or_dis); static GtkWidget *main_calendar; static GtkWidget *dow_label; static GtkWidget *clist; static GtkWidget *text_widget1, *text_widget2; #ifdef ENABLE_GTK2 static GObject *text_widget1_buffer,*text_widget2_buffer; #endif static GtkWidget *private_checkbox; static GtkWidget *check_button_alarm; static GtkWidget *check_button_day_endon; static GtkWidget *check_button_week_endon; static GtkWidget *check_button_mon_endon; static GtkWidget *check_button_year_endon; static GtkWidget *units_entry; static GtkWidget *repeat_day_entry; static GtkWidget *repeat_week_entry; static GtkWidget *repeat_mon_entry; static GtkWidget *repeat_year_entry; static GtkWidget *radio_button_alarm_min; static GtkWidget *radio_button_alarm_hour; static GtkWidget *radio_button_alarm_day; static GtkWidget *glob_endon_day_button; struct tm glob_endon_day_tm; static GtkWidget *glob_endon_week_button; static struct tm glob_endon_week_tm; static GtkWidget *glob_endon_mon_button; struct tm glob_endon_mon_tm; static GtkWidget *glob_endon_year_button; static struct tm glob_endon_year_tm; static GtkWidget *toggle_button_repeat_days[7]; static GtkWidget *toggle_button_repeat_mon_byday; static GtkWidget *toggle_button_repeat_mon_bydate; static GtkWidget *notebook; static int current_day; /*range 1-31 */ static int current_month; /*range 0-11 */ static int current_year; /*years since 1900 */ static int clist_row_selected; static int record_changed; int datebook_category=0xFFFF; /* This is a bitmask */ #ifdef ENABLE_DATEBK static GtkWidget *datebk_entry; #endif static GtkWidget *hbox_alarm1, *hbox_alarm2; static GtkWidget *scrolled_window; static struct tm begin_date, end_date; static GtkWidget *option1, *option2, *option3, *option4; static GtkWidget *begin_date_button; static GtkWidget *begin_time_entry, *end_time_entry; static GtkWidget *check_button_notime; static GtkWidget *new_record_button; static GtkWidget *apply_record_button; static GtkWidget *add_record_button; static GtkWidget *delete_record_button; static GtkWidget *undelete_record_button; static GtkWidget *copy_record_button; static GtkWidget *cancel_record_button; static GtkAccelGroup *accel_group; static AppointmentList *glob_al; /* For todo list */ static GtkWidget *todo_clist; static GtkWidget *show_todos_button; static GtkWidget *todo_scrolled_window; static ToDoList *datebook_todo_list=NULL; int datebook_to_text(struct Appointment *appt, char *text, int len) { int i; const char *short_date; const char *pref_time; char temp[255]; char text_time[200]; char str_begin_date[20]; char str_begin_time[20]; char str_end_time[20]; char text_repeat_type[40]; char text_repeat_day[200]; char text_end_date[200]; char text_repeat_freq[200]; char text_alarm[40]; char text_repeat_days[200]; char text_exceptions[65535]; char *adv_type[]={"Minutes", "Hours", "Days" }; char *repeat_type[]={"Repeat Never", "Repeat Daily", "Repeat Weekly", "Repeat MonthlyByDay", "Repeat MonthlyByDate", "Repeat YearlyDate", "Repeat YearlyDay" }; char *days[] = { N_("Su"), N_("Mo"), N_("Tu"), N_("We"), N_("Th"), N_("Fr"), N_("Sa"), N_("Su") }; if ((appt->repeatWeekstart<0) ||(appt->repeatWeekstart>6)) { appt->repeatWeekstart=0; } get_pref(PREF_SHORTDATE, NULL, &short_date); get_pref(PREF_TIME, NULL, &pref_time); /* Event date/time */ strftime(str_begin_date, sizeof(str_begin_date), short_date, &(appt->begin)); if (appt->event) { sprintf(text_time, "Appointment starts on %s\nTime: Event", str_begin_date); } else { strftime(str_begin_time, sizeof(str_begin_time), pref_time, &(appt->begin)); strftime(str_end_time, sizeof(str_end_time), pref_time, &(appt->end)); str_begin_date[19]='\0'; str_begin_time[19]='\0'; str_end_time[19]='\0'; sprintf(text_time, "Appointment starts on %s\nTime: %s to %s", str_begin_date, str_begin_time, str_end_time); } /* Alarm */ if (appt->alarm) { sprintf(text_alarm, " %d ", appt->advance); i=appt->advanceUnits; if ((i>-1) && (i<3)) { strcat(text_alarm, adv_type[i]); } else { strcat(text_alarm, "Unknown"); } } else { text_alarm[0]='\0'; } /* Repeat Type */ i=appt->repeatType; if ((i > -1) && (i < 7)) { strcpy(text_repeat_type, repeat_type[i]); } else { strcpy(text_repeat_type, "Unknown"); } /* End Date */ if (appt->repeatForever) { sprintf(text_end_date, "End Date: Never\n"); } else { strcpy(text_end_date, "End Date: "); strftime(temp, sizeof(temp), short_date, &(appt->repeatEnd)); strcat(text_end_date, temp); strcat(text_end_date, "\n"); } sprintf(text_repeat_freq, "Repeat Frequency: %d\n", appt->repeatFrequency); if (appt->repeatType==repeatNone) { text_end_date[0]='\0'; text_repeat_freq[0]='\0'; } /* Repeat Day (for MonthlyByDay) */ text_repeat_day[0]='\0'; if (appt->repeatType==repeatMonthlyByDay) { sprintf(text_repeat_day, "Monthly Repeat Day %d\n", appt->repeatDay); } /* Repeat Days (for weekly) */ text_repeat_days[0]='\0'; if (appt->repeatType==repeatWeekly) { strcpy(text_repeat_days, "Repeat Days: "); for (i=0; i<7; i++) { if (appt->repeatDays[i]) { strcat(text_repeat_days, " "); strcat(text_repeat_days, _(days[i])); } } strcat(text_repeat_days, "\n"); } text_exceptions[0]='\0'; if (appt->exceptions > 0) { sprintf(text_exceptions, "Number of exceptions: %d", appt->exceptions); for (i=0; iexceptions; i++) { strcat(text_exceptions, "\n"); strftime(temp, sizeof(temp), short_date, &(appt->exception[i])); strcat(text_exceptions, temp); if (strlen(text_exceptions)>65000) { strcat(text_exceptions, "\nmore..."); break; } } strcat(text_exceptions, "\n"); } g_snprintf(text, len, "Description: %s\n" "Note: %s\n" "%s\n" "Alarm: %s%s\n" "Repeat Type: %s\n" "%s" "%s" "Start of Week: %s\n" "%s" "%s" "%s", appt->description, appt->note, text_time, appt->alarm ? "Yes" : "No", text_alarm, text_repeat_type, text_repeat_freq, text_end_date, _(days[appt->repeatWeekstart]), text_repeat_day, text_repeat_days, text_exceptions ); return EXIT_SUCCESS; } /* * Start Import Code */ int datebook_import_callback(GtkWidget *parent_window, const char *file_path, int type) { FILE *in; char text[65536]; struct Appointment new_appt; struct AppointmentAppInfo ai; unsigned char attrib; int i, str_i, ret, index; int import_all; AppointmentList *alist; AppointmentList *temp_alist; struct CategoryAppInfo cai; char old_cat_name[32]; int suggested_cat_num; int new_cat_num; int priv; int year, month, day, hour, minute; get_datebook_app_info(&ai); attrib=0; in=fopen(file_path, "r"); if (!in) { jp_logf(JP_LOG_WARN, _("Unable to open file: %s\n"), file_path); return EXIT_FAILURE; } /* CSV */ if (type==IMPORT_TYPE_CSV) { jp_logf(JP_LOG_DEBUG, "Datebook import CSV [%s]\n", file_path); /* The first line is format, so we don't need it */ fgets(text, 2000, in); import_all=FALSE; while (1) { memset(&new_appt, 0, sizeof(new_appt)); /* Read the category field */ ret = read_csv_field(in, text, 65535); if (feof(in)) break; #ifdef JPILOT_DEBUG printf("category is [%s]\n", text); #endif g_strlcpy(old_cat_name, text, 17); attrib=0; /* Figure out what the best category number is */ suggested_cat_num=0; for (i=0; i 0) { new_appt.note=strdup(text); } else { new_appt.note=NULL; } /* Event */ ret = read_csv_field(in, text, 65535); text[65535]='\0'; sscanf(text, "%d", &(new_appt.event)); /* Begin */ memset(&(new_appt.begin), 0, sizeof(new_appt.begin)); ret = read_csv_field(in, text, 65535); text[65535]='\0'; sscanf(text, "%d %d %d %d:%d", &year, &month, &day, &hour, &minute); new_appt.begin.tm_year=year-1900; new_appt.begin.tm_mon=month-1; new_appt.begin.tm_mday=day; new_appt.begin.tm_hour=hour; new_appt.begin.tm_min=minute; new_appt.begin.tm_isdst=-1; mktime(&(new_appt.begin)); /* End */ memset(&(new_appt.end), 0, sizeof(new_appt.end)); ret = read_csv_field(in, text, 65535); text[65535]='\0'; sscanf(text, "%d %d %d %d:%d", &year, &month, &day, &hour, &minute); new_appt.end.tm_year=year-1900; new_appt.end.tm_mon=month-1; new_appt.end.tm_mday=day; new_appt.end.tm_hour=hour; new_appt.end.tm_min=minute; new_appt.end.tm_isdst=-1; mktime(&(new_appt.end)); /* Alarm */ ret = read_csv_field(in, text, 65535); text[65535]='\0'; sscanf(text, "%d", &(new_appt.alarm)); /* Advance */ ret = read_csv_field(in, text, 65535); text[65535]='\0'; sscanf(text, "%d", &(new_appt.advance)); /* Advance Units */ ret = read_csv_field(in, text, 65535); text[65535]='\0'; sscanf(text, "%d", &(new_appt.advanceUnits)); /* Repeat Type */ ret = read_csv_field(in, text, 65535); text[65535]='\0'; sscanf(text, "%d", &(i)); new_appt.repeatType=i; /* Repeat Forever */ ret = read_csv_field(in, text, 65535); text[65535]='\0'; sscanf(text, "%d", &(new_appt.repeatForever)); /* Repeat End */ memset(&(new_appt.repeatEnd), 0, sizeof(new_appt.repeatEnd)); ret = read_csv_field(in, text, 65535); text[65535]='\0'; sscanf(text, "%d %d %d", &year, &month, &day); new_appt.repeatEnd.tm_year=year-1900; new_appt.repeatEnd.tm_mon=month-1; new_appt.repeatEnd.tm_mday=day; new_appt.repeatEnd.tm_isdst=-1; mktime(&(new_appt.repeatEnd)); /* Repeat Frequency */ ret = read_csv_field(in, text, 65535); text[65535]='\0'; sscanf(text, "%d", &(new_appt.repeatFrequency)); /* Repeat Day */ ret = read_csv_field(in, text, 65535); text[65535]='\0'; sscanf(text, "%d", &(i)); new_appt.repeatDay=i; /* Repeat Days */ ret = read_csv_field(in, text, 65535); text[65535]='\0'; for (i=0; i<7; i++) { new_appt.repeatDays[i]=(text[i]=='1'); } /* Week Start */ ret = read_csv_field(in, text, 65535); text[65535]='\0'; sscanf(text, "%d", &(new_appt.repeatWeekstart)); /* Number of Exceptions */ ret = read_csv_field(in, text, 65535); text[65535]='\0'; sscanf(text, "%d", &(new_appt.exceptions)); /* Exceptions */ ret = read_csv_field(in, text, 65535); text[65535]='\0'; new_appt.exception=calloc(new_appt.exceptions, sizeof(struct tm)); for (str_i=0, i=0; i MAX_DESC_LEN) { new_appt.description[MAX_DESC_LEN+1]='\0'; jp_logf(JP_LOG_WARN, _("Appointment description text > %d, truncating to %d\n"), MAX_DESC_LEN, MAX_DESC_LEN); } pc_datebook_write(&new_appt, NEW_PC_REC, attrib, NULL); } } } /* Palm Desktop DAT format */ if (type==IMPORT_TYPE_DAT) { jp_logf(JP_LOG_DEBUG, "Datebook import DAT [%s]\n", file_path); if (dat_check_if_dat_file(in)!=DAT_DATEBOOK_FILE) { dialog_generic_ok(notebook, _("Error"), DIALOG_ERROR, _("File doesn't appear to be datebook.dat format\n")); fclose(in); return EXIT_FAILURE; } alist=NULL; dat_get_appointments(in, &alist, &cai); import_all=FALSE; for (temp_alist=alist; temp_alist; temp_alist=temp_alist->next) { index=temp_alist->mappt.unique_id-1; if (index<0) { g_strlcpy(old_cat_name, _("Unfiled"), 17); index=0; } else { g_strlcpy(old_cat_name, cai.name[index], 17); } attrib=0; /* Figure out what category it was in the dat file */ index=temp_alist->mappt.unique_id-1; suggested_cat_num=0; if (index>-1) { for (i=0; imappt.appt), text, 65535); ret=import_record_ask(parent_window, pane, text, &(ai.category), old_cat_name, (temp_alist->mappt.attrib & 0x10), suggested_cat_num, &new_cat_num); } else { new_cat_num=suggested_cat_num; } if (ret==DIALOG_SAID_IMPORT_QUIT) break; if (ret==DIALOG_SAID_IMPORT_SKIP) continue; if (ret==DIALOG_SAID_IMPORT_ALL) { import_all=TRUE; } attrib = (new_cat_num & 0x0F) | ((temp_alist->mappt.attrib & 0x10) ? dlpRecAttrSecret : 0); if ((ret==DIALOG_SAID_IMPORT_YES) || (import_all)) { pc_datebook_write(&(temp_alist->mappt.appt), NEW_PC_REC, attrib, NULL); } } free_AppointmentList(&alist); } datebook_refresh(FALSE, TRUE); fclose(in); return EXIT_SUCCESS; } int datebook_import(GtkWidget *window) { char *type_desc[] = { "CSV (Comma Separated Values)", "DAT/DBA (Palm Archive Formats)", NULL }; int type_int[] = { IMPORT_TYPE_CSV, IMPORT_TYPE_DAT, 0 }; import_gui(window, pane, type_desc, type_int, datebook_import_callback); return EXIT_SUCCESS; } /* * End Import Code */ /* * Start Export code */ GtkWidget *export_window; void appt_export_ok(int type, const char *filename) { MyAppointment *mappt; AppointmentList *al, *temp_list; FILE *out; struct stat statb; int i, r; char *button_text[]={N_("OK")}; char *button_overwrite_text[]={N_("No"), N_("Yes")}; char text[1024]; char csv_text[65550]; char *p; time_t ltime; struct tm *now; char username[256]; char hostname[256]; const char *svalue; long userid; al=NULL; /* this stuff is for ical only. */ /* todo: create a pre-export switch */ get_pref(PREF_USER, NULL, &svalue); g_strlcpy(text, svalue, 128); str_to_ical_str(username, sizeof(username), text); get_pref(PREF_USER_ID, &userid, &svalue); gethostname(text, 127); text[127]='\0'; str_to_ical_str(hostname, sizeof(hostname), text); if (!stat(filename, &statb)) { if (S_ISDIR(statb.st_mode)) { g_snprintf(text, sizeof(text), _("%s is a directory"), filename); dialog_generic(GTK_WINDOW(export_window), _("Error Opening File"), DIALOG_ERROR, text, 1, button_text); return; } g_snprintf(text, sizeof(text), _("Do you want to overwrite file %s?"), filename); r = dialog_generic(GTK_WINDOW(export_window), _("Overwrite File?"), DIALOG_QUESTION, text, 2, button_overwrite_text); if (r!=DIALOG_SAID_2) { return; } } out = fopen(filename, "w"); if (!out) { g_snprintf(text, sizeof(text), _("Error opening file: %s"), filename); dialog_generic(GTK_WINDOW(export_window), _("Error Opening File"), DIALOG_ERROR, text, 1, button_text); return; } get_days_appointments2(&al, NULL, 2, 2, 2, NULL); time(<ime); now = gmtime(<ime); mappt=NULL; for (i=0, temp_list=al; temp_list; temp_list = temp_list->next, i++) { mappt = &(temp_list->mappt); switch (type) { case EXPORT_TYPE_TEXT: csv_text[0]='\0'; datebook_to_text(&(mappt->appt), csv_text, 65535); fprintf(out, "%s\n", csv_text); break; case EXPORT_TYPE_CSV: if (i==0) { fprintf(out, "CSV datebook: Category, Private, " "Description, Note, Event, Begin, End, Alarm, Advance, " "Advance Units, Repeat Type, Repeat Forever, Repeat End, " "Repeat Frequency, Repeat Day, Repeat Days, " "Week Start, Number of Exceptions, Exceptions\n"); } str_to_csv_str(csv_text, ""); fprintf(out, "\"%s\",", csv_text); fprintf(out, "\"%s\",", (mappt->attrib & dlpRecAttrSecret) ? "1":"0"); str_to_csv_str(csv_text, mappt->appt.description); fprintf(out, "\"%s\",", csv_text); str_to_csv_str(csv_text, mappt->appt.note); fprintf(out, "\"%s\",", csv_text); fprintf(out, "\"%d\",", mappt->appt.event); fprintf(out, "\"%d %02d %02d %02d:%02d\",", mappt->appt.begin.tm_year+1900, mappt->appt.begin.tm_mon+1, mappt->appt.begin.tm_mday, mappt->appt.begin.tm_hour, mappt->appt.begin.tm_min); fprintf(out, "\"%d %02d %02d %02d:%02d\",", mappt->appt.end.tm_year+1900, mappt->appt.end.tm_mon+1, mappt->appt.end.tm_mday, mappt->appt.end.tm_hour, mappt->appt.end.tm_min); fprintf(out, "\"%s\",", (mappt->appt.alarm) ? "1":"0"); fprintf(out, "\"%d\",", mappt->appt.advance); fprintf(out, "\"%d\",", mappt->appt.advanceUnits); fprintf(out, "\"%d\",", mappt->appt.repeatType); fprintf(out, "\"%d\",", mappt->appt.repeatForever); fprintf(out, "\"%d %02d %02d\",", mappt->appt.repeatEnd.tm_year+1900, mappt->appt.repeatEnd.tm_mon+1, mappt->appt.repeatEnd.tm_mday); fprintf(out, "\"%d\",", mappt->appt.repeatFrequency); fprintf(out, "\"%d\",", mappt->appt.repeatDay); fprintf(out, "\""); for (i=0; i<7; i++) { fprintf(out, "%d", mappt->appt.repeatDays[i]); } fprintf(out, "\","); fprintf(out, "\"%d\",", mappt->appt.repeatWeekstart); fprintf(out, "\"%d\",", mappt->appt.exceptions); fprintf(out, "\""); if (mappt->appt.exceptions > 0) { for (i=0; iappt.exceptions; i++) { if (i>0) { fprintf(out, ","); } fprintf(out, "%d %02d %02d", mappt->appt.exception[i].tm_year+1900, mappt->appt.exception[i].tm_mon+1, mappt->appt.exception[i].tm_mday); } } fprintf(out, "\"\n"); break; case EXPORT_TYPE_ICALENDAR: /* RFC 2445: Internet Calendaring and Scheduling Core * Object Specification */ if (i == 0) { fprintf(out, "BEGIN:VCALENDAR\nVERSION:2.0\n"); fprintf(out, "PRODID:%s\n", FPI_STRING); } fprintf(out, "BEGIN:VEVENT\n"); /* XXX maybe if it's secret export a VFREEBUSY busy instead? */ if (mappt->attrib & dlpRecAttrSecret) { fprintf(out, "CLASS:PRIVATE\n"); } fprintf(out, "UID:palm-datebook-%08x-%08lx-%s@%s\n", mappt->unique_id, userid, username, hostname); fprintf(out, "DTSTAMP:%04d%02d%02dT%02d%02d%02dZ\n", now->tm_year+1900, now->tm_mon+1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec); /* Handle pathological case with null description. * Bugzilla Bug 1533 */ if (mappt->appt.description) { g_strlcpy(text, mappt->appt.description, 51); } else { text[0] = '\0'; } if ((p = strchr(text, '\n'))) { *p = '\0'; } str_to_ical_str(csv_text, sizeof(csv_text), text); fprintf(out, "SUMMARY:%s%s\n", csv_text, strlen(text) > 49 ? "..." : ""); str_to_ical_str(csv_text, sizeof(csv_text), mappt->appt.description); fprintf(out, "DESCRIPTION:%s", csv_text); if (mappt->appt.note && mappt->appt.note[0]) { str_to_ical_str(csv_text, sizeof(csv_text), mappt->appt.note); fprintf(out, "\\n\n %s\n", csv_text); } else { fprintf(out, "\n"); } if (mappt->appt.event) { fprintf(out, "DTSTART;VALUE=DATE:%04d%02d%02d\n", mappt->appt.begin.tm_year+1900, mappt->appt.begin.tm_mon+1, mappt->appt.begin.tm_mday); /* XXX unclear: can "event" span multiple days? */ /* since DTEND is "noninclusive", should this be the next day? */ if (mappt->appt.end.tm_year != mappt->appt.begin.tm_year || mappt->appt.end.tm_mon != mappt->appt.begin.tm_mon || mappt->appt.end.tm_mday != mappt->appt.begin.tm_mday) { fprintf(out, "DTEND;VALUE=DATE:%04d%02d%02d\n", mappt->appt.end.tm_year+1900, mappt->appt.end.tm_mon+1, mappt->appt.end.tm_mday); } } else { /* * These are "local" times, so will be treated as being in * the other person's timezone when they are imported. This * may or may not be what is desired. (DateBk calls this * "all time zones"). * * DateBk timezones could help us decide what to do here. * * When using DateBk timezones, we could write them out * as iCalendar timezones. * * Maybe the default should be to write an absolute (UTC) time, * and only write a "local" time when using DateBk and it says to. * It'd be interesting to see if repeated events get translated * properly when doing this, or if they become not eligible for * daylight savings. This probably depends on the importing * application. */ fprintf(out, "DTSTART:%04d%02d%02dT%02d%02d00\n", mappt->appt.begin.tm_year+1900, mappt->appt.begin.tm_mon+1, mappt->appt.begin.tm_mday, mappt->appt.begin.tm_hour, mappt->appt.begin.tm_min); fprintf(out, "DTEND:%04d%02d%02dT%02d%02d00\n", mappt->appt.end.tm_year+1900, mappt->appt.end.tm_mon+1, mappt->appt.end.tm_mday, mappt->appt.end.tm_hour, mappt->appt.end.tm_min); } if (mappt->appt.repeatType != repeatNone) { int wcomma, rptday; char *wday[] = {"SU","MO","TU","WE","TH","FR","SA"}; fprintf(out, "RRULE:FREQ="); switch(mappt->appt.repeatType) { case repeatNone: /* can't happen, just here to quiet gcc down. */ break; case repeatDaily: fprintf(out, "DAILY"); break; case repeatWeekly: fprintf(out, "WEEKLY;BYDAY="); wcomma=0; for (i=0; i<7; i++) { if (mappt->appt.repeatDays[i]) { if (wcomma) { fprintf(out, ","); } wcomma = 1; fprintf(out, wday[i]); } } break; case repeatMonthlyByDay: rptday = (mappt->appt.repeatDay / 7) + 1; fprintf(out, "MONTHLY;BYDAY=%d%s", rptday == 5 ? -1 : rptday, wday[mappt->appt.repeatDay % 7]); break; case repeatMonthlyByDate: fprintf(out, "MONTHLY;BYMONTHDAY=%d", mappt->appt.begin.tm_mday); break; case repeatYearly: fprintf(out, "YEARLY"); break; } if (mappt->appt.repeatFrequency != 1) { if (mappt->appt.repeatType == repeatWeekly && mappt->appt.repeatWeekstart >= 0 && mappt->appt.repeatWeekstart < 7) { fprintf(out, ";WKST=%s", wday[mappt->appt.repeatWeekstart]); } fprintf(out, ";INTERVAL=%d", mappt->appt.repeatFrequency); } if (!mappt->appt.repeatForever) { fprintf(out, ";UNTIL=%04d%02d%02d", mappt->appt.repeatEnd.tm_year+1900, mappt->appt.repeatEnd.tm_mon+1, mappt->appt.repeatEnd.tm_mday); } fprintf(out, "\n"); if (mappt->appt.exceptions > 0) { fprintf(out, "EXDATE;VALUE=DATE:"); for (i=0; iappt.exceptions; i++) { if (i>0) { fprintf(out, ","); } fprintf(out, "%04d%02d%02d", mappt->appt.exception[i].tm_year+1900, mappt->appt.exception[i].tm_mon+1, mappt->appt.exception[i].tm_mday); } fprintf(out, "\n"); } } if (mappt->appt.alarm) { char *units; fprintf(out, "BEGIN:VALARM\nACTION:DISPLAY\n"); str_to_ical_str(csv_text, sizeof(csv_text), mappt->appt.description); fprintf(out, "DESCRIPTION:%s\n", csv_text); switch (mappt->appt.advanceUnits) { case advMinutes: units = "M"; break; case advHours: units = "H"; break; case advDays: units = "D"; break; default: /* XXX */ units = "?"; break; } fprintf(out, "TRIGGER:-PT%d%s\n", mappt->appt.advance, units); fprintf(out, "END:VALARM\n"); } fprintf(out, "END:VEVENT\n"); if (temp_list->next == NULL) { fprintf(out, "END:VCALENDAR\n"); } break; default: jp_logf(JP_LOG_WARN, _("Unknown export type\n")); dialog_generic_ok(notebook, _("Error"), DIALOG_ERROR, _("Unknown export type")); } } free_AppointmentList(&al); if (out) { fclose(out); } } /* * Start Export GUI */ #define BROWSE_OK 1 #define BROWSE_CANCEL 2 #define NUM_CAT_ITEMS 16 #define NUM_EXPORT_TYPES 3 static GtkWidget *save_as_entry; static GtkWidget *export_radio_type[NUM_EXPORT_TYPES+1]; static int glob_export_type; static int datebook_export_gui(GtkWidget *main_window, int x, int y); int datebook_export(GtkWidget *window) { int x, y; gdk_window_get_root_origin(window->window, &x, &y); x+=40; datebook_export_gui(window, x, y); return EXIT_SUCCESS; } static gboolean cb_export_destroy(GtkWidget *widget) { const char *filename; filename = gtk_entry_get_text(GTK_ENTRY(save_as_entry)); set_pref(PREF_DATEBOOK_EXPORT_FILENAME, 0, filename, TRUE); gtk_main_quit(); return FALSE; } static void cb_ok(GtkWidget *widget, gpointer data) { const char *filename; filename = gtk_entry_get_text(GTK_ENTRY(save_as_entry)); appt_export_ok(glob_export_type, filename); gtk_widget_destroy(data); } static void cb_export_browse(GtkWidget *widget, gpointer data) { int r; const char *svalue; r = export_browse(GTK_WIDGET(data), PREF_DATEBOOK_EXPORT_FILENAME); if (r==BROWSE_OK) { get_pref(PREF_DATEBOOK_EXPORT_FILENAME, NULL, &svalue); gtk_entry_set_text(GTK_ENTRY(save_as_entry), svalue); } } static void cb_export_quit(GtkWidget *widget, gpointer data) { gtk_widget_destroy(data); } static void cb_export_type(GtkWidget *widget, gpointer data) { glob_export_type=GPOINTER_TO_INT(data); } static int datebook_export_gui(GtkWidget *main_window, int x, int y) { GtkWidget *button; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *label; GSList *group; char *type_text[]={"Text", "CSV", "iCalendar", NULL}; int type_int[]={EXPORT_TYPE_TEXT, EXPORT_TYPE_CSV, EXPORT_TYPE_ICALENDAR}; int i; const char *svalue; jp_logf(JP_LOG_DEBUG, "datebook_export_gui()\n"); glob_export_type=EXPORT_TYPE_TEXT; export_window = gtk_widget_new(GTK_TYPE_WINDOW, "type", GTK_WINDOW_TOPLEVEL, "title", _("Export"), NULL); gtk_widget_set_uposition(export_window, x, y); gtk_window_set_modal(GTK_WINDOW(export_window), TRUE); gtk_window_set_transient_for(GTK_WINDOW(export_window), GTK_WINDOW(main_window)); gtk_container_set_border_width(GTK_CONTAINER(export_window), 5); gtk_signal_connect(GTK_OBJECT(export_window), "destroy", GTK_SIGNAL_FUNC(cb_export_destroy), export_window); vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(export_window), vbox); /* Label for instructions */ label = gtk_label_new(_("Export All Datebook Records")); gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); /* Export Type Buttons */ group = NULL; for (i=0; iactive) != (flag)) { count++; } } } cb_toggle(NULL, count | 0x4000); for (i=0; i<16; i++) { if (GTK_IS_WIDGET(toggle_button[i])) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle_button[i]), flag); /*gtk_signal_emit_stop_by_name(GTK_OBJECT(toggle_button[i]), "toggled");*/ } } if (flag) { datebook_category=0xFFFF; } else { datebook_category=0x0000; } datebook_update_clist(); } static void cb_toggle(GtkWidget *widget, int category) { int bit=1; int cat_bit; int on; static int ignore_count=0; if (category & 0x4000) { ignore_count=category & 0xFF; return; } if (ignore_count) { ignore_count--; return; } if (GTK_TOGGLE_BUTTON(toggle_button[category])->active) { on=1; } else { on=0; } cat_bit = bit << category; if (on) { datebook_category |= cat_bit; } else { datebook_category &= ~cat_bit; } datebook_update_clist(); } void cb_date_cats(GtkWidget *widget, gpointer data) { struct AppointmentAppInfo ai; int i; int bit; char title[200]; GtkWidget *table; GtkWidget *button; GtkWidget *vbox, *hbox; long char_set; jp_logf(JP_LOG_DEBUG, "cb_date_cats\n"); if (GTK_IS_WINDOW(window_date_cats)) { gdk_window_raise(window_date_cats->window); jp_logf(JP_LOG_DEBUG, "date_cats window is already up\n"); return; } get_datebook_app_info(&ai); window_date_cats = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(window_date_cats), GTK_WIN_POS_MOUSE); gtk_window_set_modal(GTK_WINDOW(window_date_cats), TRUE); gtk_window_set_transient_for(GTK_WINDOW(window_date_cats), GTK_WINDOW(gtk_widget_get_toplevel(widget))); gtk_container_set_border_width(GTK_CONTAINER(window_date_cats), 10); g_snprintf(title, sizeof(title), "%s %s", PN, _("Datebook Categories")); gtk_window_set_title(GTK_WINDOW(window_date_cats), title); gtk_signal_connect(GTK_OBJECT(window_date_cats), "destroy", GTK_SIGNAL_FUNC(cb_destroy_date_cats), window_date_cats); vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(window_date_cats), vbox); /* Table */ table = gtk_table_new(8, 2, TRUE); gtk_table_set_row_spacings(GTK_TABLE(table),0); gtk_table_set_col_spacings(GTK_TABLE(table),0); gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0); get_pref(PREF_CHAR_SET, &char_set, NULL); for (i=0, bit=1; i<16; i++, bit <<= 1) { if (ai.category.name[i][0]) { char *l; l = charset_p2newj(ai.category.name[i], sizeof(ai.category.name[0]), char_set); toggle_button[i]=gtk_toggle_button_new_with_label(l); g_free(l); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle_button[i]), datebook_category & bit); gtk_table_attach_defaults (GTK_TABLE(table), GTK_WIDGET(toggle_button[i]), (i>7)?1:0, (i>7)?2:1, (i>7)?i-8:i, (i>7)?i-7:i+1); gtk_signal_connect(GTK_OBJECT(toggle_button[i]), "toggled", GTK_SIGNAL_FUNC(cb_toggle), GINT_TO_POINTER(i)); } else { toggle_button[i]=NULL; } } hbox = gtk_hbutton_box_new(); gtk_button_box_set_spacing(GTK_BUTTON_BOX(hbox), 6); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); /* Create a "Close" button */ #ifdef ENABLE_GTK2 button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); #else button = gtk_button_new_with_label(_("Close")); #endif gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(cb_quit_date_cats), window_date_cats); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); /* Create a "All" button */ button = gtk_button_new_with_label(_("All")); gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(cb_category), GINT_TO_POINTER(1)); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); /* Create a "None" button */ button = gtk_button_new_with_label(_("None")); gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(cb_category), GINT_TO_POINTER(0)); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); gtk_widget_show_all(window_date_cats); } #endif int datebook_print(int type) { struct tm date; long fdow, paper_size; date.tm_mon=current_month; date.tm_mday=current_day; date.tm_year=current_year; date.tm_sec=0; date.tm_min=0; date.tm_hour=11; date.tm_isdst=-1; mktime(&date); switch(type) { case DAILY: jp_logf(JP_LOG_DEBUG, "datebook_print daily\n"); print_days_appts(&date); break; case WEEKLY: jp_logf(JP_LOG_DEBUG, "datebook_print weekly\n"); get_pref(PREF_FDOW, &fdow, NULL); /* Get the first day of the week */ sub_days_from_date(&date, (7 - fdow + date.tm_wday)%7); get_pref(PREF_PAPER_SIZE, &paper_size, NULL); if (paper_size==1) { print_weeks_appts(&date, PAPER_A4); } else { print_weeks_appts(&date, PAPER_Letter); } break; case MONTHLY: jp_logf(JP_LOG_DEBUG, "datebook_print monthly\n"); get_pref(PREF_PAPER_SIZE, &paper_size, NULL); if (paper_size==1) { print_months_appts(&date, PAPER_A4); } else { print_months_appts(&date, PAPER_Letter); } break; } return EXIT_SUCCESS; } void cb_monthview(GtkWidget *widget, gpointer data) { struct tm date; memset(&date, 0, sizeof(date)); date.tm_mon=current_month; date.tm_mday=current_day; date.tm_year=current_year; monthview_gui(&date); } static void cb_cal_dialog(GtkWidget *widget, gpointer data) { long fdow; int r = 0; struct tm *Pt; GtkWidget *Pcheck_button; GtkWidget *Pbutton; switch (GPOINTER_TO_INT(data)) { case PAGE_DAY: Pcheck_button = check_button_day_endon; Pt = &glob_endon_day_tm; Pbutton = glob_endon_day_button; break; case PAGE_WEEK: Pcheck_button = check_button_week_endon; Pt = &glob_endon_week_tm; Pbutton = glob_endon_week_button; break; case PAGE_MONTH: Pcheck_button = check_button_mon_endon; Pt = &glob_endon_mon_tm; Pbutton = glob_endon_mon_button; break; case PAGE_YEAR: Pcheck_button = check_button_year_endon; Pt = &glob_endon_year_tm; Pbutton = glob_endon_year_button; break; case BEGIN_DATE_BUTTON: Pcheck_button = NULL; Pt = &begin_date; Pbutton = begin_date_button; break; default: Pcheck_button = NULL; Pbutton = NULL; jp_logf(JP_LOG_DEBUG, "default hit in cb_cal_dialog()\n"); return; } get_pref(PREF_FDOW, &fdow, NULL); if (GPOINTER_TO_INT(data) == BEGIN_DATE_BUTTON) { r = cal_dialog(GTK_WINDOW(gtk_widget_get_toplevel(widget)), _("Begin On Date"), fdow, &(Pt->tm_mon), &(Pt->tm_mday), &(Pt->tm_year)); } else { r = cal_dialog(GTK_WINDOW(gtk_widget_get_toplevel(widget)), _("End On Date"), fdow, &(Pt->tm_mon), &(Pt->tm_mday), &(Pt->tm_year)); } if (GPOINTER_TO_INT(data) == BEGIN_DATE_BUTTON) { end_date.tm_mon = begin_date.tm_mon; end_date.tm_mday = begin_date.tm_mday; end_date.tm_year = begin_date.tm_year; } if (r==CAL_DONE) { if (Pcheck_button) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Pcheck_button), TRUE); } if (Pbutton) { update_endon_button(Pbutton, Pt); } } } void cb_weekview(GtkWidget *widget, gpointer data) { struct tm date; memset(&date, 0, sizeof(date)); date.tm_mon=current_month; date.tm_mday=current_day; date.tm_year=current_year; date.tm_sec=0; date.tm_min=0; date.tm_hour=11; date.tm_isdst=-1; mktime(&date); weekview_gui(&date); } static void init() { time_t ltime; struct tm *now; AppointmentList *a_list; AppointmentList *temp_al; #ifdef ENABLE_DATEBK long use_db3_tags; #endif #ifdef ENABLE_DATEBK get_pref(PREF_USE_DB3, &use_db3_tags, NULL); if (use_db3_tags) { DB_APPT_COLUMN=4; } else { DB_APPT_COLUMN=3; } #endif record_changed=CLEAR_FLAG; time(<ime); now = localtime(<ime); current_day = now->tm_mday; current_month = now->tm_mon; current_year = now->tm_year; memcpy(&glob_endon_day_tm, now, sizeof(glob_endon_day_tm)); memcpy(&glob_endon_week_tm, now, sizeof(glob_endon_week_tm)); memcpy(&glob_endon_mon_tm, now, sizeof(glob_endon_mon_tm)); memcpy(&glob_endon_year_tm, now, sizeof(glob_endon_year_tm)); if (glob_find_id) { jp_logf(JP_LOG_DEBUG, "init() glob_find_id = %d\n", glob_find_id); /* Search Appointments for this id to get its date */ a_list = NULL; get_days_appointments2(&a_list, NULL, 1, 1, 1, NULL); for (temp_al = a_list; temp_al; temp_al=temp_al->next) { if (temp_al->mappt.unique_id == glob_find_id) { jp_logf(JP_LOG_DEBUG, "init() found glob_find_id\n"); current_month = temp_al->mappt.appt.begin.tm_mon; current_day = temp_al->mappt.appt.begin.tm_mday; current_year = temp_al->mappt.appt.begin.tm_year; break; } } free_AppointmentList(&a_list); } clist_row_selected=0; } int dialog_4_or_last(int dow) { char *days[]={ N_("Sunday"), N_("Monday"), N_("Tuesday"), N_("Wednesday"), N_("Thursday"), N_("Friday"), N_("Saturday") }; char text[255]; char *button_text[]={N_("4th"), N_("Last")}; sprintf(text, _("This appointment can either\n" "repeat on the 4th %s\n" "of the month, or on the last\n" "%s of the month.\n" "Which do you want?"), _(days[dow]), _(days[dow])); return dialog_generic(GTK_WINDOW(gtk_widget_get_toplevel(scrolled_window)), _("Question?"), DIALOG_QUESTION, text, 2, button_text); } int dialog_current_all_cancel() { char text[]= /*--------------------------- */ N_("This is a repeating event.\n" "Do you want to apply these\n" "changes to just the CURRENT\n" "event, or ALL of the\n" "occurrences of this event?"); char *button_text[]={ N_("Current"), N_("All"), N_("Cancel") }; return dialog_generic(GTK_WINDOW(gtk_widget_get_toplevel(scrolled_window)), _("Question?"), DIALOG_QUESTION, _(text), 3, button_text); } #ifdef EASTER int dialog_easter(int mday) { char text[255]; char who[50]; char *button_text[]={"I'll send a present!!!" }; if (mday==29) { strcpy(who, "Judd Montgomery"); } if (mday==20) { strcpy(who, "Jacki Montgomery"); } sprintf(text, /*--------------------------- */ "Today is\n" "%s\'s\n" "Birthday!\n", who); return dialog_generic(GTK_WINDOW(gtk_widget_get_toplevel(scrolled_window)), "Happy Birthday to Me!", DIALOG_INFO, text, 1, button_text); } /* */ /*End of Dialog window code */ /* */ #endif /* */ /* month = 0-11 */ /* dom = day of month 1-31 */ /* year = calendar year - 1900 */ /* dow = day of week 0-6, where 0=Sunday, etc. */ /* */ /* Returns an enum from DayOfMonthType defined in pi-datebook.h */ /* */ long get_dom_type(int month, int dom, int year, int dow) { long r; int ndim; /* ndim = number of days in month 28-31 */ int dow_fdof; /*Day of the week for the first day of the month */ int result; r=((int)((dom-1)/7))*7 + dow; /* If its the 5th occurrence of this dow in the month then it is always */ /*going to be the last occurrence of that dow in the month. */ /*Sometimes this will occur in the 4th week, sometimes in the 5th. */ /* If its the 4th occurrence of this dow in the month and there is a 5th */ /*then it always the 4th occurrence. */ /* If its the 4th occurrence of this dow in the month and there is not a */ /*5th then we need to ask if this appointment repeats on the last dow of */ /*the month, or the 4th dow of every month. */ /* This should be perfectly clear now, right? */ /*These are the last 2 lines of the DayOfMonthType enum: */ /*dom4thSun, dom4thMon, dom4thTue, dom4thWen, dom4thThu, dom4thFri, dom4thSat */ /*domLastSun, domLastMon, domLastTue, domLastWen, domLastThu, domLastFri, domLastSat */ if ((r>=dom4thSun) && (r<=dom4thSat)) { get_month_info(month, dom, year, &dow_fdof, &ndim); if ((ndim - dom < 7)) { /*This is the 4th dow, and there is no 5th in this month. */ result = dialog_4_or_last(dow); /*If they want it to be the last dow in the month instead of the */ /*4th, then we need to add 7. */ if (result == DIALOG_SAID_LAST) { r += 7; } } } return r; } /* flag UPDATE_DATE_ENTRY is to set entry fields * flag UPDATE_DATE_MENUS is to set menu items */ static void set_begin_end_labels(struct tm *begin, struct tm *end, int flags) { char str[255]; char time1_str[255]; char time2_str[255]; char pref_time[40]; const char *pref_date; str[0]='\0'; get_pref(PREF_SHORTDATE, NULL, &pref_date); strftime(str, sizeof(str), pref_date, begin); gtk_label_set_text(GTK_LABEL(GTK_BIN(begin_date_button)->child), str); if (flags & UPDATE_DATE_ENTRIES) { if (GTK_TOGGLE_BUTTON(check_button_notime)->active) { gtk_entry_set_text(GTK_ENTRY(begin_time_entry), ""); gtk_entry_set_text(GTK_ENTRY(end_time_entry), ""); } else { get_pref_time_no_secs(pref_time); jp_strftime(time1_str, sizeof(time1_str), pref_time, begin); jp_strftime(time2_str, sizeof(time2_str), pref_time, end); gtk_entry_set_text(GTK_ENTRY(begin_time_entry), time1_str); gtk_entry_set_text(GTK_ENTRY(end_time_entry), time2_str); } } if (flags & UPDATE_DATE_MENUS) { gtk_option_menu_set_history(GTK_OPTION_MENU(option1), begin_date.tm_hour); gtk_option_menu_set_history(GTK_OPTION_MENU(option2), begin_date.tm_min/5); gtk_option_menu_set_history(GTK_OPTION_MENU(option3), end_date.tm_hour); gtk_option_menu_set_history(GTK_OPTION_MENU(option4), end_date.tm_min/5); } } static void clear_begin_end_labels() { begin_date.tm_mon = current_month; begin_date.tm_mday = current_day; begin_date.tm_year = current_year; begin_date.tm_hour = 8; begin_date.tm_min = 0; begin_date.tm_sec = 0; begin_date.tm_isdst = -1; end_date.tm_mon = current_month; end_date.tm_mday = current_day; end_date.tm_year = current_year; end_date.tm_hour = 9; end_date.tm_min = 0; end_date.tm_sec = 0; end_date.tm_isdst = -1; set_begin_end_labels(&begin_date, &end_date, UPDATE_DATE_ENTRIES | UPDATE_DATE_MENUS); } static void appt_clear_details() { int i; struct tm today; #ifdef ENABLE_DATEBK long use_db3_tags; #endif connect_changed_signals(DISCONNECT_SIGNALS); clear_begin_end_labels(); #ifdef ENABLE_GTK2 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(text_widget1_buffer), "", -1); gtk_text_buffer_set_text(GTK_TEXT_BUFFER(text_widget2_buffer), "", -1); #else gtk_text_set_point(GTK_TEXT(text_widget1), gtk_text_get_length(GTK_TEXT(text_widget1))); gtk_text_set_point(GTK_TEXT(text_widget2), gtk_text_get_length(GTK_TEXT(text_widget2))); gtk_text_backward_delete(GTK_TEXT(text_widget1), gtk_text_get_length(GTK_TEXT(text_widget1))); gtk_text_backward_delete(GTK_TEXT(text_widget2), gtk_text_get_length(GTK_TEXT(text_widget2))); #endif #ifdef ENABLE_DATEBK get_pref(PREF_USE_DB3, &use_db3_tags, NULL); if (use_db3_tags) { gtk_entry_set_text(GTK_ENTRY(datebk_entry), ""); } #endif gtk_notebook_set_page(GTK_NOTEBOOK(notebook), PAGE_NONE); /* Clear the notebook pages */ gtk_entry_set_text(GTK_ENTRY(units_entry), "5"); gtk_entry_set_text(GTK_ENTRY(repeat_day_entry), "1"); gtk_entry_set_text(GTK_ENTRY(repeat_week_entry), "1"); gtk_entry_set_text(GTK_ENTRY(repeat_mon_entry), "1"); gtk_entry_set_text(GTK_ENTRY(repeat_year_entry), "1"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button_day_endon), FALSE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button_week_endon), FALSE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button_mon_endon), FALSE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button_year_endon), FALSE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button_notime), TRUE); for(i=0; i<7; i++) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle_button_repeat_days[i]), FALSE); } gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle_button_repeat_mon_bydate), TRUE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(private_checkbox), FALSE); memset(&today, 0, sizeof(today)); today.tm_year = current_year; today.tm_mon = current_month; today.tm_mday = current_day; today.tm_hour = 12; today.tm_min = 0; mktime(&today); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle_button_repeat_days[today.tm_wday]), TRUE); memcpy(&glob_endon_day_tm, &today, sizeof(glob_endon_day_tm)); memcpy(&glob_endon_week_tm, &today, sizeof(glob_endon_week_tm)); memcpy(&glob_endon_mon_tm, &today, sizeof(glob_endon_mon_tm)); memcpy(&glob_endon_year_tm, &today, sizeof(glob_endon_year_tm)); connect_changed_signals(CONNECT_SIGNALS); } static int appt_get_details(struct Appointment *appt, unsigned char *attrib) { int i; time_t ltime, ltime2; struct tm *now; char str[30]; gint page; int total_repeat_days; char datef[32]; const char *svalue1, *svalue2; const gchar *text1; #ifdef ENABLE_GTK2 GtkTextIter start_iter; GtkTextIter end_iter; #endif #ifdef ENABLE_DATEBK gchar *note_text=NULL; gchar *text2; long use_db3_tags; char null_str[]=""; #endif const char *period[] = { N_("none"), N_("day"), N_("week"), N_("month"), N_("year") }; #ifdef ENABLE_DATEBK get_pref(PREF_USE_DB3, &use_db3_tags, NULL); #endif memset(appt, 0, sizeof(*appt)); *attrib = 0; time(<ime); now = localtime(<ime); total_repeat_days=0; /*The first day of the week */ /*I always use 0, Sunday is always 0 in this code */ appt->repeatWeekstart=0; appt->exceptions = 0; appt->exception = NULL; /*Set the daylight savings flags */ appt->end.tm_isdst=appt->begin.tm_isdst=-1; appt->begin.tm_mon = begin_date.tm_mon; appt->begin.tm_mday = begin_date.tm_mday; appt->begin.tm_year = begin_date.tm_year; appt->begin.tm_hour = begin_date.tm_hour; appt->begin.tm_min = begin_date.tm_min; appt->begin.tm_sec = 0; /*get the end times */ appt->end.tm_mon = end_date.tm_mon; appt->end.tm_mday = end_date.tm_mday; appt->end.tm_year = end_date.tm_year; appt->end.tm_hour = end_date.tm_hour; appt->end.tm_min = end_date.tm_min; appt->end.tm_sec = 0; if (GTK_TOGGLE_BUTTON(check_button_notime)->active) { appt->event=1; /*This event doesn't have a time */ appt->begin.tm_hour = 0; appt->begin.tm_min = 0; appt->begin.tm_sec = 0; appt->end.tm_hour = 0; appt->end.tm_min = 0; appt->end.tm_sec = 0; } else { appt->event=0; } ltime = mktime(&appt->begin); ltime2 = mktime(&appt->end); if (ltime > ltime2) { memcpy(&(appt->end), &(appt->begin), sizeof(struct tm)); } if (GTK_TOGGLE_BUTTON(check_button_alarm)->active) { appt->alarm = 1; text1 = gtk_entry_get_text(GTK_ENTRY(units_entry)); appt->advance=atoi(text1); jp_logf(JP_LOG_DEBUG, "alarm advance %d", appt->advance); if (GTK_TOGGLE_BUTTON(radio_button_alarm_min)->active) { appt->advanceUnits = advMinutes; jp_logf(JP_LOG_DEBUG, "min\n"); } if (GTK_TOGGLE_BUTTON(radio_button_alarm_hour)->active) { appt->advanceUnits = advHours; jp_logf(JP_LOG_DEBUG, "hour\n"); } if (GTK_TOGGLE_BUTTON(radio_button_alarm_day)->active) { appt->advanceUnits = advDays; jp_logf(JP_LOG_DEBUG, "day\n"); } } else { appt->alarm = 0; } page = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)); appt->repeatEnd.tm_hour = 0; appt->repeatEnd.tm_min = 0; appt->repeatEnd.tm_sec = 0; appt->repeatEnd.tm_isdst= -1; switch (page) { case PAGE_NONE: appt->repeatType=repeatNone; jp_logf(JP_LOG_DEBUG, "no repeat\n"); break; case PAGE_DAY: appt->repeatType=repeatDaily; text1 = gtk_entry_get_text(GTK_ENTRY(repeat_day_entry)); appt->repeatFrequency = atoi(text1); jp_logf(JP_LOG_DEBUG, "every %d day(s)\n", appt->repeatFrequency); if (GTK_TOGGLE_BUTTON(check_button_day_endon)->active) { appt->repeatForever=0; jp_logf(JP_LOG_DEBUG, "end on day\n"); appt->repeatEnd.tm_mon = glob_endon_day_tm.tm_mon; appt->repeatEnd.tm_mday = glob_endon_day_tm.tm_mday; appt->repeatEnd.tm_year = glob_endon_day_tm.tm_year; appt->repeatEnd.tm_isdst = -1; mktime(&appt->repeatEnd); } else { appt->repeatForever=1; } break; case PAGE_WEEK: appt->repeatType=repeatWeekly; text1 = gtk_entry_get_text(GTK_ENTRY(repeat_week_entry)); appt->repeatFrequency = atoi(text1); jp_logf(JP_LOG_DEBUG, "every %d week(s)\n", appt->repeatFrequency); if (GTK_TOGGLE_BUTTON(check_button_week_endon)->active) { appt->repeatForever=0; jp_logf(JP_LOG_DEBUG, "end on week\n"); appt->repeatEnd.tm_mon = glob_endon_week_tm.tm_mon; appt->repeatEnd.tm_mday = glob_endon_week_tm.tm_mday; appt->repeatEnd.tm_year = glob_endon_week_tm.tm_year; appt->repeatEnd.tm_isdst = -1; mktime(&appt->repeatEnd); get_pref(PREF_SHORTDATE, NULL, &svalue1); get_pref(PREF_TIME, NULL, &svalue2); if ((svalue1==NULL) || (svalue2==NULL)) { strcpy(datef, "%x %X"); } else { sprintf(datef, "%s %s", svalue1, svalue2); } strftime(str, sizeof(str), datef, &appt->repeatEnd); jp_logf(JP_LOG_DEBUG, "repeat_end time = %s\n",str); } else { appt->repeatForever=1; } jp_logf(JP_LOG_DEBUG, "Repeat Days:"); appt->repeatWeekstart = 0; /*We are going to always use 0 */ for (i=0; i<7; i++) { appt->repeatDays[i]=(GTK_TOGGLE_BUTTON(toggle_button_repeat_days[i])->active); total_repeat_days += appt->repeatDays[i]; } jp_logf(JP_LOG_DEBUG, "\n"); break; case PAGE_MONTH: text1 = gtk_entry_get_text(GTK_ENTRY(repeat_mon_entry)); appt->repeatFrequency = atoi(text1); jp_logf(JP_LOG_DEBUG, "every %d month(s)\n", appt->repeatFrequency); if (GTK_TOGGLE_BUTTON(check_button_mon_endon)->active) { appt->repeatForever=0; jp_logf(JP_LOG_DEBUG, "end on month\n"); appt->repeatEnd.tm_mon = glob_endon_mon_tm.tm_mon; appt->repeatEnd.tm_mday = glob_endon_mon_tm.tm_mday; appt->repeatEnd.tm_year = glob_endon_mon_tm.tm_year; appt->repeatEnd.tm_isdst = -1; mktime(&appt->repeatEnd); get_pref(PREF_SHORTDATE, NULL, &svalue1); get_pref(PREF_TIME, NULL, &svalue2); if ((svalue1==NULL) || (svalue2==NULL)) { strcpy(datef, "%x %X"); } else { sprintf(datef, "%s %s", svalue1, svalue2); } strftime(str, sizeof(str), datef, &appt->repeatEnd); jp_logf(JP_LOG_DEBUG, "repeat_end time = %s\n",str); } else { appt->repeatForever=1; } if (GTK_TOGGLE_BUTTON(toggle_button_repeat_mon_byday)->active) { appt->repeatType=repeatMonthlyByDay; appt->repeatDay = get_dom_type(appt->begin.tm_mon, appt->begin.tm_mday, appt->begin.tm_year, appt->begin.tm_wday); jp_logf(JP_LOG_DEBUG, "***by day\n"); } if (GTK_TOGGLE_BUTTON(toggle_button_repeat_mon_bydate)->active) { appt->repeatType=repeatMonthlyByDate; jp_logf(JP_LOG_DEBUG, "***by date\n"); } break; case PAGE_YEAR: appt->repeatType=repeatYearly; text1 = gtk_entry_get_text(GTK_ENTRY(repeat_year_entry)); appt->repeatFrequency = atoi(text1); jp_logf(JP_LOG_DEBUG, "every %s year(s)\n", appt->repeatFrequency); if (GTK_TOGGLE_BUTTON(check_button_year_endon)->active) { appt->repeatForever=0; jp_logf(JP_LOG_DEBUG, "end on year\n"); appt->repeatEnd.tm_mon = glob_endon_year_tm.tm_mon; appt->repeatEnd.tm_mday = glob_endon_year_tm.tm_mday; appt->repeatEnd.tm_year = glob_endon_year_tm.tm_year; appt->repeatEnd.tm_isdst = -1; mktime(&appt->repeatEnd); get_pref(PREF_SHORTDATE, NULL, &svalue1); get_pref(PREF_TIME, NULL, &svalue2); if ((svalue1==NULL) || (svalue2==NULL)) { strcpy(datef, "%x %X"); } else { sprintf(datef, "%s %s", svalue1, svalue2); } str[0]='\0'; strftime(str, sizeof(str), datef, &appt->repeatEnd); jp_logf(JP_LOG_DEBUG, "repeat_end time = %s\n",str); } else { appt->repeatForever=1; } break; } #ifdef ENABLE_GTK2 gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(text_widget1_buffer),&start_iter,&end_iter); appt->description = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(text_widget1_buffer),&start_iter,&end_iter,TRUE); #else appt->description = gtk_editable_get_chars(GTK_EDITABLE(text_widget1), 0, -1); #endif /* Empty appointment descriptions crash PalmOS 2.0, but are fine in * later versions */ if (appt->description[0]=='\0') { free(appt->description); appt->description=strdup(" "); } if (strlen(appt->description)+1 > MAX_DESC_LEN) { appt->description[MAX_DESC_LEN+1]='\0'; jp_logf(JP_LOG_WARN, _("Appointment description text > %d, truncating to %d\n"), MAX_DESC_LEN, MAX_DESC_LEN); } if (appt->description) { jp_logf(JP_LOG_DEBUG, "description=[%s]\n",appt->description); } #ifdef ENABLE_DATEBK if (use_db3_tags) { text1 = gtk_entry_get_text(GTK_ENTRY(datebk_entry)); #ifdef ENABLE_GTK2 gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(text_widget2_buffer),&start_iter,&end_iter); text2 = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(text_widget2_buffer),&start_iter,&end_iter,TRUE); #else text2 = gtk_editable_get_chars(GTK_EDITABLE(text_widget2), 0, -1); #endif if (!text1) text1=null_str; if (!text2) text2=null_str; /* 8 extra characters is just being paranoid */ note_text=malloc(strlen(text1) + strlen(text2) + 8); note_text[0]='\0'; appt->note=note_text; if ((text1) && (text1[0])) { strcpy(note_text, text1); strcat(note_text, "\n"); } strcat(note_text, text2); } else { #ifdef ENABLE_GTK2 gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(text_widget2_buffer),&start_iter,&end_iter); appt->note = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(text_widget2_buffer),&start_iter,&end_iter,TRUE); #else appt->note = gtk_editable_get_chars(GTK_EDITABLE(text_widget2), 0, -1); #endif } /* This #else is for the Datebk #ifdef */ #else #ifdef ENABLE_GTK2 gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(text_widget2_buffer),&start_iter,&end_iter); appt->note = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(text_widget2_buffer),&start_iter,&end_iter,TRUE); #else appt->note = gtk_editable_get_chars(GTK_EDITABLE(text_widget2), 0, -1); #endif /* This #endif is for the Datebk #ifdef */ #endif if (appt->note[0]=='\0') { free(appt->note); appt->note=NULL; } if (appt->note) { jp_logf(JP_LOG_DEBUG, "text note=[%s]\n",appt->note); } /* We won't allow a repeat frequency of less than 1 */ if ((page != PAGE_NONE) && (appt->repeatFrequency < 1)) { char str[200]; jp_logf(JP_LOG_WARN, _("You cannot have an appointment that repeats every %d %s(s)\n"), appt->repeatFrequency, _(period[page])); g_snprintf(str, sizeof(str), _("You cannot have an appointment that repeats every %d %s(s)\n"), appt->repeatFrequency, _(period[page])); dialog_generic_ok(notebook, _("Error"), DIALOG_ERROR, str); appt->repeatFrequency = 1; return EXIT_FAILURE; } /* We won't allow a weekly repeating that doesn't repeat on any day */ if ((page == PAGE_WEEK) && (total_repeat_days == 0)) { dialog_generic_ok(notebook, _("Error"), DIALOG_ERROR, _("You can not have a weekly repeating appointment that doesn't repeat on any day of the week.")); return EXIT_FAILURE; } if (GTK_TOGGLE_BUTTON(private_checkbox)->active) { *attrib |= dlpRecAttrSecret; } return EXIT_SUCCESS; } static void update_endon_button(GtkWidget *button, struct tm *t) { const char *short_date; char str[255]; get_pref(PREF_SHORTDATE, NULL, &short_date); strftime(str, sizeof(str), short_date, t); gtk_label_set_text(GTK_LABEL(GTK_BIN(button)->child), str); } /* Do masking like Palm OS 3.5 */ static void clear_myappointment(MyAppointment *mappt) { mappt->unique_id=0; mappt->attrib=mappt->attrib & 0xF8; if (mappt->appt.description) { free(mappt->appt.description); mappt->appt.description=strdup(""); } if (mappt->appt.note) { free(mappt->appt.note); mappt->appt.note=strdup(""); } return; } /* End Masking */ static int datebook_update_clist() { int num_entries, entries_shown, num, i; AppointmentList *temp_al; gchar *empty_line[] = { "","","","",""}; char begin_time[32]; char end_time[32]; char a_time[sizeof(begin_time)+sizeof(end_time)+1]; char datef[20]; GdkPixmap *pixmap_note; GdkPixmap *pixmap_alarm; GdkBitmap *mask_note; GdkBitmap *mask_alarm; int has_note; #ifdef ENABLE_DATEBK int ret; int cat_bit; int db3_type; long use_db3_tags; struct db4_struct db4; GdkPixmap *pixmap_float_check; GdkPixmap *pixmap_float_checked; GdkBitmap *mask_float_check; GdkBitmap *mask_float_checked; #endif struct tm new_time; int show_priv; char str[DATEBOOK_MAX_COLUMN_LEN+2]; char str2[DATEBOOK_MAX_COLUMN_LEN]; jp_logf(JP_LOG_DEBUG, "datebook_update_clist()\n"); free_AppointmentList(&glob_al); memset(&new_time, 0, sizeof(new_time)); new_time.tm_hour=11; new_time.tm_mday=current_day; new_time.tm_mon=current_month; new_time.tm_year=current_year; new_time.tm_isdst=-1; mktime(&new_time); num = get_days_appointments2(&glob_al, &new_time, 2, 2, 1, &num_entries); jp_logf(JP_LOG_DEBUG, "get_days_appointments==>%d\n", num); #ifdef ENABLE_DATEBK jp_logf(JP_LOG_DEBUG, "datebook_category = 0x%x\n", datebook_category); #endif /* Freeze clist to prevent flicker during updating */ gtk_clist_freeze(GTK_CLIST(clist)); gtk_signal_disconnect_by_func(GTK_OBJECT(clist), GTK_SIGNAL_FUNC(cb_clist_selection), NULL); gtk_clist_clear(GTK_CLIST(clist)); /* Collect preferences and constant pixmaps for loop */ show_priv = show_privates(GET_PRIVATES); get_pixmaps(scrolled_window, PIXMAP_NOTE, &pixmap_note, &mask_note); get_pixmaps(scrolled_window, PIXMAP_ALARM,&pixmap_alarm, &mask_alarm); # ifdef ENABLE_DATEBK get_pref(PREF_USE_DB3, &use_db3_tags, NULL); get_pixmaps(scrolled_window, PIXMAP_FLOAT_CHECK, &pixmap_float_check, &mask_float_check); get_pixmaps(scrolled_window, PIXMAP_FLOAT_CHECKED, &pixmap_float_checked, &mask_float_checked); # endif entries_shown=0; for (temp_al = glob_al, i=0; temp_al; temp_al=temp_al->next, i++) { #ifdef ENABLE_DATEBK ret=0; if (use_db3_tags) { ret = db3_parse_tag(temp_al->mappt.appt.note, &db3_type, &db4); jp_logf(JP_LOG_DEBUG, "category = 0x%x\n", db4.category); cat_bit=1<mappt.attrib & dlpRecAttrSecret)) { gtk_clist_append(GTK_CLIST(clist), empty_line); gtk_clist_set_text(GTK_CLIST(clist), i, DB_TIME_COLUMN, "----------"); gtk_clist_set_text(GTK_CLIST(clist), i, DB_APPT_COLUMN, "---------------"); clear_myappointment(&temp_al->mappt); gtk_clist_set_row_data(GTK_CLIST(clist), i, &(temp_al->mappt)); gtk_clist_set_row_style(GTK_CLIST(clist), i, NULL); entries_shown++; continue; } /* End Masking */ /* Hide the private records if need be */ if ((show_priv != SHOW_PRIVATES) && (temp_al->mappt.attrib & dlpRecAttrSecret)) { i--; continue; } /* Add entry to clist */ gtk_clist_append(GTK_CLIST(clist), empty_line); entries_shown++; /* Print the event time */ if (temp_al->mappt.appt.event) { /*This is a timeless event */ strcpy(a_time, _("No Time")); } else { get_pref_time_no_secs_no_ampm(datef); strftime(begin_time, sizeof(begin_time), datef, &(temp_al->mappt.appt.begin)); get_pref_time_no_secs(datef); strftime(end_time, sizeof(end_time), datef, &(temp_al->mappt.appt.end)); g_snprintf(a_time, sizeof(a_time), "%s-%s", begin_time, end_time); } gtk_clist_set_text(GTK_CLIST(clist), i, DB_TIME_COLUMN, a_time); #ifdef ENABLE_DATEBK if (use_db3_tags) { if (db4.floating_event==DB3_FLOAT) { gtk_clist_set_pixmap(GTK_CLIST(clist), i, DB_FLOAT_COLUMN, pixmap_float_check, mask_float_check); } if (db4.floating_event==DB3_FLOAT_COMPLETE) { gtk_clist_set_pixmap(GTK_CLIST(clist), i, DB_FLOAT_COLUMN, pixmap_float_checked, mask_float_checked); } } #endif has_note=0; #ifdef ENABLE_DATEBK if (use_db3_tags) { if (db3_type!=DB3_TAG_TYPE_NONE) { if (db4.note) { if (db4.note[0]!='\0') { has_note = 1; } } } else { if (temp_al->mappt.appt.note) { if (temp_al->mappt.appt.note[0]!='\0') { has_note=1; } } } } else { if (temp_al->mappt.appt.note) { if (temp_al->mappt.appt.note[0]!='\0') { has_note=1; } } } #else if (temp_al->mappt.appt.note) { if (temp_al->mappt.appt.note[0]!='\0') { has_note=1; } } #endif /* Put a note pixmap up */ if (has_note) { gtk_clist_set_pixmap(GTK_CLIST(clist), i, DB_NOTE_COLUMN, pixmap_note, mask_note); } /* Put an alarm pixmap up */ if (temp_al->mappt.appt.alarm) { gtk_clist_set_pixmap(GTK_CLIST(clist), i, DB_ALARM_COLUMN, pixmap_alarm, mask_alarm); } /* Print the appointment description */ lstrncpy_remove_cr_lfs(str2, temp_al->mappt.appt.description, DATEBOOK_MAX_COLUMN_LEN); /* Append number of anniversary years if enabled & appropriate */ append_anni_years(str2, sizeof(str2), &new_time, &temp_al->mappt.appt); gtk_clist_set_text(GTK_CLIST(clist), i, DB_APPT_COLUMN, str2); gtk_clist_set_row_data(GTK_CLIST(clist), i, &(temp_al->mappt)); /* Highlight row background depending on status */ switch (temp_al->mappt.rt) { case NEW_PC_REC: case REPLACEMENT_PALM_REC: set_bg_rgb_clist_row(clist, i, CLIST_NEW_RED, CLIST_NEW_GREEN, CLIST_NEW_BLUE); break; case DELETED_PALM_REC: case DELETED_PC_REC: set_bg_rgb_clist_row(clist, i, CLIST_DEL_RED, CLIST_DEL_GREEN, CLIST_DEL_BLUE); break; case MODIFIED_PALM_REC: set_bg_rgb_clist_row(clist, i, CLIST_MOD_RED, CLIST_MOD_GREEN, CLIST_MOD_BLUE); break; default: if (temp_al->mappt.attrib & dlpRecAttrSecret) { set_bg_rgb_clist_row(clist, i, CLIST_PRIVATE_RED, CLIST_PRIVATE_GREEN, CLIST_PRIVATE_BLUE); } else { gtk_clist_set_row_style(GTK_CLIST(clist), i, NULL); } } } gtk_signal_connect(GTK_OBJECT(clist), "select_row", GTK_SIGNAL_FUNC(cb_clist_selection), NULL); /* If there are items in the list, highlight the selected row */ if (i>0) { /* Select the existing requested row, or row 0 if that is impossible */ if (clist_row_selected < entries_shown) { clist_select_row(GTK_CLIST(clist), clist_row_selected, 1); if (!gtk_clist_row_is_visible(GTK_CLIST(clist), clist_row_selected)) { gtk_clist_moveto(GTK_CLIST(clist), clist_row_selected, 0, 0.5, 0.0); } } else { clist_select_row(GTK_CLIST(clist), 0, 1); } } else { set_new_button_to(CLEAR_FLAG); appt_clear_details(); } gtk_clist_thaw(GTK_CLIST(clist)); g_snprintf(str, sizeof(str), _("%d of %d records"), entries_shown, num_entries); gtk_tooltips_set_tip(glob_tooltips, GTK_CLIST(clist)->column[DB_APPT_COLUMN].button, str, NULL); /* return focus to clist after any big operation which requires a redraw */ gtk_widget_grab_focus(GTK_WIDGET(clist)); return EXIT_SUCCESS; } static void set_new_button_to(int new_state) { jp_logf(JP_LOG_DEBUG, "set_new_button_to new %d old %d\n", new_state, record_changed); if (record_changed==new_state) { return; } switch (new_state) { case MODIFY_FLAG: gtk_widget_show(cancel_record_button); gtk_widget_show(copy_record_button); gtk_widget_show(apply_record_button); gtk_widget_hide(add_record_button); gtk_widget_hide(delete_record_button); gtk_widget_hide(new_record_button); gtk_widget_hide(undelete_record_button); break; case NEW_FLAG: gtk_widget_show(cancel_record_button); gtk_widget_show(add_record_button); gtk_widget_hide(apply_record_button); gtk_widget_hide(copy_record_button); gtk_widget_hide(delete_record_button); gtk_widget_hide(new_record_button); gtk_widget_hide(undelete_record_button); break; case CLEAR_FLAG: gtk_widget_show(delete_record_button); gtk_widget_show(copy_record_button); gtk_widget_show(new_record_button); gtk_widget_hide(add_record_button); gtk_widget_hide(apply_record_button); gtk_widget_hide(cancel_record_button); gtk_widget_hide(undelete_record_button); break; case UNDELETE_FLAG: gtk_widget_show(undelete_record_button); gtk_widget_show(copy_record_button); gtk_widget_show(new_record_button); gtk_widget_hide(add_record_button); gtk_widget_hide(apply_record_button); gtk_widget_hide(cancel_record_button); gtk_widget_hide(delete_record_button); break; default: return; } record_changed=new_state; } static gboolean cb_key_pressed_left_side(GtkWidget *widget, GdkEventKey *event, gpointer next_widget) { #ifdef ENABLE_GTK2 GtkTextBuffer *text_buffer; GtkTextIter iter; #endif if (event->keyval == GDK_Return) { gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "key_press_event"); gtk_widget_grab_focus(GTK_WIDGET(next_widget)); #ifdef ENABLE_GTK2 /* Position cursor at start of text */ text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(next_widget)); gtk_text_buffer_get_start_iter(text_buffer, &iter); gtk_text_buffer_place_cursor(text_buffer, &iter); #endif return TRUE; } return FALSE; } static gboolean cb_key_pressed_right_side(GtkWidget *widget, GdkEventKey *event, gpointer next_widget) { if ((event->keyval == GDK_Return) && (event->state & GDK_SHIFT_MASK)) { gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "key_press_event"); /* Call clist_selection to handle any cleanup such as a modified record */ cb_clist_selection(clist, clist_row_selected, 1, GINT_TO_POINTER(1), NULL); gtk_widget_grab_focus(GTK_WIDGET(next_widget)); return TRUE; } return FALSE; } static void cb_record_changed(GtkWidget *widget, gpointer data) { jp_logf(JP_LOG_DEBUG, "cb_record_changed\n"); if (record_changed==CLEAR_FLAG) { connect_changed_signals(DISCONNECT_SIGNALS); if (GTK_CLIST(clist)->rows > 0) { set_new_button_to(MODIFY_FLAG); } else { set_new_button_to(NEW_FLAG); } } else if (record_changed==UNDELETE_FLAG) { jp_logf(JP_LOG_INFO|JP_LOG_GUI, _("This record is deleted.\n" "Undelete it or copy it to make changes.\n")); } } /* fix - move this to utils? */ time_t date2seconds(struct tm *date) { struct tm date2; memset(&date2, 0, sizeof(date2)); memcpy(&date2, date, sizeof(date2)); date2.tm_year=date->tm_year; date2.tm_mon=date->tm_mon; date2.tm_mday=date->tm_mday; date2.tm_hour=date->tm_hour; date2.tm_min=date->tm_min; date2.tm_sec=date->tm_sec; date2.tm_isdst=date->tm_isdst; return mktime(&date2); } static void cb_add_new_record(GtkWidget *widget, gpointer data) { MyAppointment *mappt; struct Appointment *appt; struct Appointment new_appt; int flag; int create_exception=0; int result; int r; unsigned char attrib; int show_priv; unsigned int unique_id; time_t t_begin, t_end; jp_logf(JP_LOG_DEBUG, "cb_add_new_record\n"); unique_id=0; attrib = 0; flag=GPOINTER_TO_INT(data); /* Do masking like Palm OS 3.5 */ if ((flag==COPY_FLAG) || (flag==MODIFY_FLAG)) { show_priv = show_privates(GET_PRIVATES); mappt = gtk_clist_get_row_data(GTK_CLIST(clist), clist_row_selected); if (mappt < (MyAppointment *)CLIST_MIN_DATA) { return; } if ((show_priv != SHOW_PRIVATES) && (mappt->attrib & dlpRecAttrSecret)) { return; } } /* End Masking */ if (flag==CLEAR_FLAG) { /*Clear button was hit */ appt_clear_details(); connect_changed_signals(DISCONNECT_SIGNALS); set_new_button_to(NEW_FLAG); gtk_widget_grab_focus(GTK_WIDGET(text_widget1)); return; } if ((flag!=NEW_FLAG) && (flag!=MODIFY_FLAG) && (flag!=COPY_FLAG)) { return; } if (flag==MODIFY_FLAG) { mappt = gtk_clist_get_row_data(GTK_CLIST(clist), clist_row_selected); unique_id = mappt->unique_id; if (mappt < (MyAppointment *)CLIST_MIN_DATA) { return; } if ((mappt->rt==DELETED_PALM_REC) || (mappt->rt==DELETED_PC_REC) || (mappt->rt==MODIFIED_PALM_REC)) { jp_logf(JP_LOG_INFO, _("You can't modify a record that is deleted\n")); return; } } else { mappt=NULL; } r = appt_get_details(&new_appt, &attrib); if (r < 0) { free_Appointment(&new_appt); return; } /* Do some validation */ if ((new_appt.repeatType != repeatNone) && (!(new_appt.repeatForever))) { t_begin = date2seconds(&(new_appt.begin)); t_end = date2seconds(&(new_appt.repeatEnd)); if (t_begin > t_end) { dialog_generic_ok(notebook, _("Invalid Appointment"), DIALOG_ERROR, _("The End Date of this appointment\nis before the start date.")); free_Appointment(&new_appt); return; } } if ((flag==MODIFY_FLAG) && (new_appt.repeatType != repeatNone)) { /*We need more user input */ /*Pop up a dialog */ result = dialog_current_all_cancel(); if (result==DIALOG_SAID_CANCEL) { return; } if (result==DIALOG_SAID_CURRENT) { /*Create an exception in the appointment */ create_exception=1; new_appt.repeatType = repeatNone; new_appt.begin.tm_year = current_year; new_appt.begin.tm_mon = current_month; new_appt.begin.tm_mday = current_day; new_appt.begin.tm_isdst = -1; mktime(&new_appt.begin); new_appt.repeatType = repeatNone; new_appt.end.tm_year = current_year; new_appt.end.tm_mon = current_month; new_appt.end.tm_mday = current_day; new_appt.end.tm_isdst = -1; mktime(&new_appt.end); } if (result==DIALOG_SAID_ALL) { /*We still need to keep the exceptions of the original record */ new_appt.exception = malloc(mappt->appt.exceptions * sizeof(struct tm)); memcpy(new_appt.exception, mappt->appt.exception, mappt->appt.exceptions * sizeof(struct tm)); new_appt.exceptions = mappt->appt.exceptions; } } set_new_button_to(CLEAR_FLAG); if (flag==MODIFY_FLAG) { /* * We need to take care of the 2 options allowed when modifying * repeating appointments */ delete_pc_record(DATEBOOK, mappt, flag); if (create_exception) { datebook_copy_appointment(&(mappt->appt), &appt); datebook_add_exception(appt, current_year, current_month, current_day); if ((mappt->rt==PALM_REC) || (mappt->rt==REPLACEMENT_PALM_REC)) { /* The original record gets the same ID, this exception gets a new one. */ pc_datebook_write(appt, REPLACEMENT_PALM_REC, attrib, &unique_id); } else { pc_datebook_write(appt, NEW_PC_REC, attrib, NULL); } unique_id = 0; pc_datebook_write(&new_appt, NEW_PC_REC, attrib, &unique_id); free_Appointment(appt); free(appt); } else { if ((mappt->rt==PALM_REC) || (mappt->rt==REPLACEMENT_PALM_REC)) { pc_datebook_write(&new_appt, REPLACEMENT_PALM_REC, attrib, &unique_id); } else { unique_id=0; pc_datebook_write(&new_appt, NEW_PC_REC, attrib, &unique_id); } } } else { unique_id=0; /* Has to be zero */ pc_datebook_write(&new_appt, NEW_PC_REC, attrib, &unique_id); /* FIXME - what should happen here is that the calendar should be positioned on the or the next future occurrence */ gtk_calendar_freeze(GTK_CALENDAR(main_calendar)); /* Unselect current day before changing to a new month. * This prevents a GTK error when the new month does not have the * same number of days. Example: attempting to switch from Jan. 31 to * Feb. 31 */ gtk_calendar_select_day(GTK_CALENDAR(main_calendar), 0); gtk_calendar_select_month(GTK_CALENDAR(main_calendar), new_appt.begin.tm_mon, new_appt.begin.tm_year+1900); gtk_calendar_select_day(GTK_CALENDAR(main_calendar), new_appt.begin.tm_mday); gtk_calendar_thaw(GTK_CALENDAR(main_calendar)); } free_Appointment(&new_appt); datebook_update_clist(); highlight_days(); glob_find_id = unique_id; datebook_find(); /* Make sure that the next alarm will go off */ alarms_find_next(NULL, NULL, TRUE); return; } void cb_delete_appt(GtkWidget *widget, gpointer data) { MyAppointment *mappt; struct Appointment *appt; int flag; int result = 0; int show_priv; mappt = gtk_clist_get_row_data(GTK_CLIST(clist), clist_row_selected); if (mappt < (MyAppointment *)CLIST_MIN_DATA) { return; } /* Do masking like Palm OS 3.5 */ show_priv = show_privates(GET_PRIVATES); if ((show_priv != SHOW_PRIVATES) && (mappt->attrib & dlpRecAttrSecret)) { return; } /* End Masking */ flag = GPOINTER_TO_INT(data); if ((flag!=MODIFY_FLAG) && (flag!=DELETE_FLAG)) { return; } /* */ /*We need to take care of the 2 options allowed when modifying */ /*repeating appointments */ /* */ if (mappt->appt.repeatType != repeatNone) { /*We need more user input */ /*Pop up a dialog */ result = dialog_current_all_cancel(); if (result==DIALOG_SAID_CANCEL) { return; } if (result==DIALOG_SAID_CURRENT) { /*Create an exception in the appointment */ datebook_copy_appointment(&(mappt->appt), &appt); datebook_add_exception(appt, current_year, current_month, current_day); if ((mappt->rt==PALM_REC) || (mappt->rt==REPLACEMENT_PALM_REC)) { pc_datebook_write(appt, REPLACEMENT_PALM_REC, mappt->attrib, &(mappt->unique_id)); } else { pc_datebook_write(appt, NEW_PC_REC, mappt->attrib, NULL); } free_Appointment(appt); free(appt); /*Since this was really a modify, and not a delete */ flag=MODIFY_FLAG; } } delete_pc_record(DATEBOOK, mappt, flag); if (flag==DELETE_FLAG) { /* when we redraw we want to go to the line above the deleted one */ if (clist_row_selected>0) { clist_row_selected--; } } if ((flag == DELETE_FLAG) || (result == DIALOG_SAID_CURRENT)) { datebook_update_clist(); highlight_days(); } } void cb_undelete_appt(GtkWidget *widget, gpointer data) { MyAppointment *mappt; int flag; int show_priv; mappt = gtk_clist_get_row_data(GTK_CLIST(clist), clist_row_selected); if (mappt < (MyAppointment *)CLIST_MIN_DATA) { return; } /* Do masking like Palm OS 3.5 */ show_priv = show_privates(GET_PRIVATES); if ((show_priv != SHOW_PRIVATES) && (mappt->attrib & dlpRecAttrSecret)) { return; } /* End Masking */ jp_logf(JP_LOG_DEBUG, "mappt->unique_id = %d\n",mappt->unique_id); jp_logf(JP_LOG_DEBUG, "mappt->rt = %d\n",mappt->rt); flag = GPOINTER_TO_INT(data); if (flag==UNDELETE_FLAG) { if (mappt->rt == DELETED_PALM_REC || mappt->rt == DELETED_PC_REC) { undelete_pc_record(DATEBOOK, mappt, flag); } /* Possible later addition of undelete for modified records else if (mappt->rt == MODIFIED_PALM_REC) { cb_add_new_record(widget, GINT_TO_POINTER(COPY_FLAG)); } */ } datebook_update_clist(); highlight_days(); } void cb_check_button_alarm(GtkWidget *widget, gpointer data) { if (GTK_TOGGLE_BUTTON(widget)->active) { gtk_widget_show(hbox_alarm2); } else { gtk_widget_hide(hbox_alarm2); } } void cb_check_button_notime(GtkWidget *widget, gpointer data) { /* GTK does not handle nested callbacks well! * When a time is selected from the drop-down menus cb_menu_time * is called. cb_menu_time, in turn, de-selects the notime checkbutton * which causes a signal to be generated which invokes * cb_check_button_notime. Finally, both callback routines call * set_begin_end_labels and in that routine is a call which sets the * currently selected item in the gtk_option_menu. This sequence of * events screws up the option menu for the first click. One solution * would be to disable signals in cb_menu_time, de-select the checkbutton, * and then re-enable signals. Given the frequency with which the menus * are used this solution involves too much of a performance hit. * Instead, in this routine only the entry widgets are updated and the menus * are left alone. Currently(20060111) this produces no difference in * jpilot behavior because the menus have been set to correct values in * other routines. */ /* set_begin_end_labels(&begin_date, &end_date, UPDATE_DATE_ENTRIES | UPDATE_DATE_MENUS); */ set_begin_end_labels(&begin_date, &end_date, UPDATE_DATE_ENTRIES); } void cb_check_button_endon(GtkWidget *widget, gpointer data) { GtkWidget *Pbutton; struct tm *Pt; switch (GPOINTER_TO_INT(data)) { case PAGE_DAY: Pbutton = glob_endon_day_button; Pt = &glob_endon_day_tm; break; case PAGE_WEEK: Pbutton = glob_endon_week_button; Pt = &glob_endon_week_tm; break; case PAGE_MONTH: Pbutton = glob_endon_mon_button; Pt = &glob_endon_mon_tm; break; case PAGE_YEAR: Pbutton = glob_endon_year_button; Pt = &glob_endon_year_tm; break; default: return; } if (GTK_TOGGLE_BUTTON(widget)->active) { update_endon_button(Pbutton, Pt); } else { gtk_label_set_text(GTK_LABEL(GTK_BIN(Pbutton)->child), _("No Date")); } } static void cb_clist_selection(GtkWidget *clist, gint row, gint column, GdkEventButton *event, gpointer data) { struct Appointment *appt; MyAppointment *mappt; char temp[20]; int i, b; unsigned int unique_id = 0; #ifdef ENABLE_DATEBK int type; char *note; int len; long use_db3_tags; #endif #ifdef ENABLE_DATEBK get_pref(PREF_USE_DB3, &use_db3_tags, NULL); #endif if ((record_changed==MODIFY_FLAG) || (record_changed==NEW_FLAG)) { mappt = gtk_clist_get_row_data(GTK_CLIST(clist), row); if (mappt!=NULL) { unique_id = mappt->unique_id; } b=dialog_save_changed_record(pane, record_changed); if (b==DIALOG_SAID_2) { cb_add_new_record(NULL, GINT_TO_POINTER(record_changed)); } set_new_button_to(CLEAR_FLAG); if (unique_id) { glob_find_id = unique_id; datebook_find(); } else { clist_select_row(GTK_CLIST(clist), row, column); } return; } clist_row_selected=row; mappt = gtk_clist_get_row_data(GTK_CLIST(clist), row); if (mappt==NULL) { return; } if (mappt->rt == DELETED_PALM_REC || (mappt->rt == DELETED_PC_REC)) /* Possible later addition of undelete code for modified deleted records || mmemo->rt == MODIFIED_PALM_REC */ { set_new_button_to(UNDELETE_FLAG); } else { set_new_button_to(CLEAR_FLAG); } connect_changed_signals(DISCONNECT_SIGNALS); appt=&(mappt->appt); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button_notime), appt->event); #ifdef ENABLE_GTK2 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(text_widget1_buffer), "", -1); gtk_text_buffer_set_text(GTK_TEXT_BUFFER(text_widget2_buffer), "", -1); #else gtk_text_set_point(GTK_TEXT(text_widget1), 0); gtk_text_forward_delete(GTK_TEXT(text_widget1), gtk_text_get_length(GTK_TEXT(text_widget1))); gtk_text_set_point(GTK_TEXT(text_widget2), 0); gtk_text_forward_delete(GTK_TEXT(text_widget2), gtk_text_get_length(GTK_TEXT(text_widget2))); #endif #ifdef ENABLE_DATEBK if (use_db3_tags) { gtk_entry_set_text(GTK_ENTRY(datebk_entry), ""); } #endif if (appt->alarm) { /* This is to insure that the callback gets called */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button_alarm), FALSE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button_alarm), TRUE); switch (appt->advanceUnits) { case advMinutes: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (radio_button_alarm_min), TRUE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (radio_button_alarm_hour), FALSE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (radio_button_alarm_day), FALSE); break; case advHours: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (radio_button_alarm_min), FALSE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (radio_button_alarm_hour), TRUE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (radio_button_alarm_day), FALSE); break; case advDays: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (radio_button_alarm_min), FALSE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (radio_button_alarm_hour), FALSE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (radio_button_alarm_day), TRUE); break; default: jp_logf(JP_LOG_WARN, _("Error in DateBookDB advanceUnits = %d\n"),appt->advanceUnits); } sprintf(temp, "%d", appt->advance); gtk_entry_set_text(GTK_ENTRY(units_entry), temp); } else { /* This is to insure that the callback gets called */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button_alarm), TRUE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button_alarm), FALSE); gtk_entry_set_text(GTK_ENTRY(units_entry), "0"); } if (appt->description) { #ifdef ENABLE_GTK2 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(text_widget1_buffer), appt->description, -1); #else gtk_text_insert(GTK_TEXT(text_widget1), NULL,NULL, NULL, appt->description, -1); #endif } #ifdef ENABLE_DATEBK if (use_db3_tags) { if (db3_parse_tag(appt->note, &type, NULL) > 0) { /* There is a datebk tag. Need to separate it from the note */ note = strdup(appt->note); len=strlen(note); for (i=0; inote) { #ifdef ENABLE_GTK2 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(text_widget2_buffer), appt->note, -1); #else gtk_text_insert(GTK_TEXT(text_widget2), NULL,NULL, NULL, appt->note, -1); #endif } } } else { if (appt->note) { #ifdef ENABLE_GTK2 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(text_widget2_buffer), appt->note, -1); #else gtk_text_insert(GTK_TEXT(text_widget2), NULL,NULL, NULL, appt->note, -1); #endif } } #else if (appt->note) { #ifdef ENABLE_GTK2 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(text_widget2_buffer), appt->note, -1); #else gtk_text_insert(GTK_TEXT(text_widget2), NULL,NULL, NULL, appt->note, -1); #endif } #endif begin_date.tm_mon = appt->begin.tm_mon; begin_date.tm_mday = appt->begin.tm_mday; begin_date.tm_year = appt->begin.tm_year; begin_date.tm_hour = appt->begin.tm_hour; begin_date.tm_min = appt->begin.tm_min; end_date.tm_mon = appt->end.tm_mon; end_date.tm_mday = appt->end.tm_mday; end_date.tm_year = appt->end.tm_year; end_date.tm_hour = appt->end.tm_hour; end_date.tm_min = appt->end.tm_min; set_begin_end_labels(&begin_date, &end_date, UPDATE_DATE_ENTRIES | UPDATE_DATE_MENUS); /*Do the Repeat information */ switch (appt->repeatType) { case repeatNone: gtk_notebook_set_page(GTK_NOTEBOOK(notebook), PAGE_NONE); break; case repeatDaily: if ((appt->repeatForever)) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (check_button_day_endon), FALSE); } else { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (check_button_day_endon), TRUE); glob_endon_day_tm.tm_mon = appt->repeatEnd.tm_mon; glob_endon_day_tm.tm_mday = appt->repeatEnd.tm_mday; glob_endon_day_tm.tm_year = appt->repeatEnd.tm_year; update_endon_button(glob_endon_day_button, &glob_endon_day_tm); } sprintf(temp, "%d", appt->repeatFrequency); gtk_entry_set_text(GTK_ENTRY(repeat_day_entry), temp); gtk_notebook_set_page(GTK_NOTEBOOK(notebook), PAGE_DAY); break; case repeatWeekly: if ((appt->repeatForever)) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (check_button_week_endon), FALSE); } else { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (check_button_week_endon), TRUE); glob_endon_week_tm.tm_mon = appt->repeatEnd.tm_mon; glob_endon_week_tm.tm_mday = appt->repeatEnd.tm_mday; glob_endon_week_tm.tm_year = appt->repeatEnd.tm_year; update_endon_button(glob_endon_week_button, &glob_endon_week_tm); } sprintf(temp, "%d", appt->repeatFrequency); gtk_entry_set_text(GTK_ENTRY(repeat_week_entry), temp); for (i=0; i<7; i++) { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(toggle_button_repeat_days[i]), /*appt->repeatDays[(i + appt->repeatWeekstart)%7]); */ appt->repeatDays[i]); } gtk_notebook_set_page(GTK_NOTEBOOK(notebook), PAGE_WEEK); break; case repeatMonthlyByDate: case repeatMonthlyByDay: jp_logf(JP_LOG_DEBUG, "repeat day=%d\n",appt->repeatDay); if ((appt->repeatForever)) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (check_button_mon_endon), FALSE); } else { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (check_button_mon_endon), TRUE); glob_endon_mon_tm.tm_mon = appt->repeatEnd.tm_mon; glob_endon_mon_tm.tm_mday = appt->repeatEnd.tm_mday; glob_endon_mon_tm.tm_year = appt->repeatEnd.tm_year; update_endon_button(glob_endon_mon_button, &glob_endon_mon_tm); } sprintf(temp, "%d", appt->repeatFrequency); gtk_entry_set_text(GTK_ENTRY(repeat_mon_entry), temp); if (appt->repeatType == repeatMonthlyByDay) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (toggle_button_repeat_mon_byday), TRUE); } if (appt->repeatType == repeatMonthlyByDate) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (toggle_button_repeat_mon_bydate), TRUE); } gtk_notebook_set_page(GTK_NOTEBOOK(notebook), PAGE_MONTH); break; case repeatYearly: if ((appt->repeatForever)) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (check_button_year_endon), FALSE); } else { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (check_button_year_endon), TRUE); glob_endon_year_tm.tm_mon = appt->repeatEnd.tm_mon; glob_endon_year_tm.tm_mday = appt->repeatEnd.tm_mday; glob_endon_year_tm.tm_year = appt->repeatEnd.tm_year; update_endon_button(glob_endon_year_button, &glob_endon_year_tm); } sprintf(temp, "%d", appt->repeatFrequency); gtk_entry_set_text(GTK_ENTRY(repeat_year_entry), temp); gtk_notebook_set_page(GTK_NOTEBOOK(notebook), PAGE_YEAR); break; default: jp_logf(JP_LOG_WARN, _("Unknown repeatType found in DatebookDB\n")); } gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(private_checkbox), mappt->attrib & dlpRecAttrSecret); connect_changed_signals(CONNECT_SIGNALS); return; } void set_date_labels() { struct tm now; char str[50]; char datef[50]; const char *svalue; now.tm_sec=0; now.tm_min=0; now.tm_hour=11; now.tm_isdst=-1; now.tm_wday=0; now.tm_yday=0; now.tm_mday = current_day; now.tm_mon = current_month; now.tm_year = current_year; mktime(&now); get_pref(PREF_LONGDATE, NULL, &svalue); if (svalue==NULL) { strcpy(datef, "%x"); } else { sprintf(datef, _("%%a., %s"), svalue); } /* Determine today for highlighting */ if (now.tm_mday == get_highlighted_today(&now)) strcat(datef, _(" (TODAY)")); jp_strftime(str, sizeof(str), datef, &now); gtk_label_set_text(GTK_LABEL(dow_label), str); } static void cb_cancel(GtkWidget *widget, gpointer data) { set_new_button_to(CLEAR_FLAG); datebook_refresh(FALSE, FALSE); } /* When a calendar day is pressed */ void cb_cal_changed(GtkWidget *widget, gpointer data) { int num; unsigned int cal_year, cal_month, cal_day; int mon_changed; int b; #ifdef EASTER static int Easter=0; #endif num = GPOINTER_TO_INT(data); if (num!=CAL_DAY_SELECTED) { return; } b=dialog_save_changed_record(pane, record_changed); if (b==DIALOG_SAID_2) { cb_add_new_record(NULL, GINT_TO_POINTER(record_changed)); } set_new_button_to(CLEAR_FLAG); gtk_calendar_get_date(GTK_CALENDAR(main_calendar), &cal_year, &cal_month, &cal_day); /* Day 0 is used in GTK to unselect the current highlighted day -- * NOT to change to the zeroeth day */ if (cal_day==0) { return; } if (cal_year < 1903) { cal_year=1903; gtk_calendar_select_month(GTK_CALENDAR(main_calendar), cal_month, 1903); } if (cal_year > 2037) { cal_year=2037; gtk_calendar_select_month(GTK_CALENDAR(main_calendar), cal_month, 2037); } mon_changed=0; if (current_year!=cal_year-1900) { current_year=cal_year-1900; mon_changed=1; } if (current_month!=cal_month) { current_month=cal_month; mon_changed=1; } current_day=cal_day; jp_logf(JP_LOG_DEBUG, "cb_cal_changed, %02d/%02d/%02d\n", cal_month,cal_day,cal_year); set_date_labels(); /* */ /*Easter Egg */ /* */ #ifdef EASTER if (((current_day==29) && (current_month==7)) || ((current_day==20) && (current_month==11))) { Easter++; if (Easter>4) { Easter=0; dialog_easter(current_day); } } else { Easter=0; } #endif if (mon_changed) { highlight_days(); } clist_row_selected = 0; datebook_update_clist(); /* Keep focus on calendar so that GTK accelerator keys for calendar * can continue to be used */ gtk_widget_grab_focus(GTK_WIDGET(main_calendar)); } /* Called by week and month views when a user clicks on a date so that we * can set the day view to that date */ void datebook_gui_setdate(int year, int month, int day) { /* This refers to the main jpilot window. This should probably * be replaced somehow by a GTK call which works out what the * top-level window is from the widget. Right now it relies * on the fact that there is only one item titled "window" in * the global name space */ extern GtkWidget *window; /* Reset current day pointers to the day the user click on */ current_year = year; current_month = month; current_day = day; /* Redraw the day view */ datebook_refresh(FALSE, FALSE); /* Force exposure of main window */ if (window) { #ifdef ENABLE_GTK2 gtk_window_present(GTK_WINDOW(window)); #else gdk_window_raise(window->window); #endif } } static void highlight_days() { int bit, mask; int dow_int, ndim, i; long ivalue; get_pref(PREF_DATEBOOK_HIGHLIGHT_DAYS, &ivalue, NULL); if (!ivalue) { return; } get_month_info(current_month, 1, current_year, &dow_int, &ndim); appointment_on_day_list(current_month, current_year, &mask); gtk_calendar_freeze(GTK_CALENDAR(main_calendar)); for (i=1, bit=1; i<=ndim; i++, bit = bit<<1) { if (bit & mask) { gtk_calendar_mark_day(GTK_CALENDAR(main_calendar), i); } else { gtk_calendar_unmark_day(GTK_CALENDAR(main_calendar), i); } } gtk_calendar_thaw(GTK_CALENDAR(main_calendar)); } static int datebook_find() { int r, found_at; jp_logf(JP_LOG_DEBUG, "datebook_find(), glob_find_id = %d\n", glob_find_id); if (glob_find_id) { r = clist_find_id(clist, glob_find_id, &found_at); if (r) { if (!gtk_clist_row_is_visible(GTK_CLIST(clist), found_at)) { gtk_clist_moveto(GTK_CLIST(clist), found_at, 0, 0.5, 0.0); } jp_logf(JP_LOG_DEBUG, "datebook_find(), selecting row %d\n", found_at); clist_select_row(GTK_CLIST(clist), found_at, 1); } glob_find_id = 0; } return EXIT_SUCCESS; } int datebook_refresh(int first, int do_init) { int b; int copy_current_day; int copy_current_month; int copy_current_year; b=dialog_save_changed_record(pane, record_changed); if (b==DIALOG_SAID_2) { cb_add_new_record(NULL, GINT_TO_POINTER(record_changed)); } set_new_button_to(CLEAR_FLAG); if (do_init) init(); #ifdef ENABLE_DATEBK if (glob_find_id) { if (GTK_IS_WINDOW(window_date_cats)) { cb_category(NULL, GINT_TO_POINTER(1)); } else { datebook_category = 0xFFFF; } } #endif /* Need to disconnect signal before using gtk_calendar_select_day or callback will be activated inadvertently. */ gtk_signal_disconnect_by_func(GTK_OBJECT(main_calendar), GTK_SIGNAL_FUNC(cb_cal_changed), GINT_TO_POINTER(CAL_DAY_SELECTED)); if (first) { gtk_calendar_select_month(GTK_CALENDAR(main_calendar), current_month, current_year+1900); gtk_calendar_select_day(GTK_CALENDAR(main_calendar), current_day); } else { copy_current_day = current_day; copy_current_month = current_month; copy_current_year = current_year; gtk_calendar_freeze(GTK_CALENDAR(main_calendar)); /* Unselect current day before changing to a new month */ gtk_calendar_select_day(GTK_CALENDAR(main_calendar), 0); gtk_calendar_select_month(GTK_CALENDAR(main_calendar), copy_current_month, copy_current_year+1900); gtk_calendar_select_day(GTK_CALENDAR(main_calendar), copy_current_day); gtk_calendar_thaw(GTK_CALENDAR(main_calendar)); } gtk_signal_connect(GTK_OBJECT(main_calendar), "day_selected", GTK_SIGNAL_FUNC(cb_cal_changed), GINT_TO_POINTER(CAL_DAY_SELECTED)); datebook_update_clist(); highlight_days(); set_date_labels(); datebook_find(); return EXIT_SUCCESS; } void cb_menu_time(GtkWidget *item, gint data) { struct tm *Ptm; if (data&END_TIME_FLAG) { Ptm=&end_date; } else { Ptm=&begin_date; } if (data&HOURS_FLAG) { Ptm->tm_hour = data&0x3F; } else { Ptm->tm_min = data&0x3F; } gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button_notime), 0); set_begin_end_labels(&begin_date, &end_date, UPDATE_DATE_ENTRIES); } static gboolean cb_hide_menu_time(GtkWidget *widget, gpointer data) { /* Require that appt. end times be after the begin time */ /* This mimics the behavior of PalmOs more closely */ if (begin_date.tm_hour > end_date.tm_hour) { end_date.tm_hour = begin_date.tm_hour; } set_begin_end_labels(&begin_date, &end_date, UPDATE_DATE_MENUS | UPDATE_DATE_ENTRIES); return FALSE; } #define PRESSED_P 100 #define PRESSED_A 101 #define PRESSED_TAB 102 #define PRESSED_MINUS 103 static void entry_key_pressed(int next_digit, int begin_or_end) { struct tm *Pt; if (begin_or_end) { Pt = &end_date; } else { Pt = &begin_date; } if ((next_digit>=0) && (next_digit<=9)) { Pt->tm_hour = ((Pt->tm_hour)*10 + (Pt->tm_min)/10)%100; Pt->tm_min = ((Pt->tm_min)*10)%100 + next_digit; } if ((next_digit==PRESSED_P) && ((Pt->tm_hour)<12)) { (Pt->tm_hour) += 12; } if ((next_digit==PRESSED_A) && ((Pt->tm_hour)>11)) { (Pt->tm_hour) -= 12; } /* Don't let the first digit exceed 2 */ if ((int)(Pt->tm_hour/10) > 2) { Pt->tm_hour -= ((int)(Pt->tm_hour/10)-2)*10; } /* Don't let the hour be > 23 */ if (Pt->tm_hour > 23) { Pt->tm_hour = 23; } set_begin_end_labels(&begin_date, &end_date, UPDATE_DATE_ENTRIES | UPDATE_DATE_MENUS); } static gboolean cb_entry_pressed(GtkWidget *w, gpointer data) { if (GTK_TOGGLE_BUTTON(check_button_notime)->active) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button_notime), FALSE); } set_begin_end_labels(&begin_date, &end_date, UPDATE_DATE_ENTRIES | UPDATE_DATE_MENUS); /* return FALSE to let Gtk know we did not handle the event * this allows Gtk to finish handling it.*/ return FALSE; } static gboolean cb_entry_key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data) { int digit=-1; jp_logf(JP_LOG_DEBUG, "cb_entry_key_pressed key = %d\n", event->keyval); gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "key_press_event"); if ((event->keyval >= GDK_0) && (event->keyval <= GDK_9)) { digit = (event->keyval)-GDK_0; } if ((event->keyval >= GDK_KP_0) && (event->keyval <= GDK_KP_9)) { digit = (event->keyval)-GDK_KP_0; } if ((event->keyval == GDK_P) || (event->keyval == GDK_p)) { digit = PRESSED_P; } if ((event->keyval == GDK_A) || (event->keyval == GDK_a)) { digit = PRESSED_A; } if (event->keyval == GDK_Tab) { digit = PRESSED_TAB; } if ((event->keyval == GDK_KP_Subtract) || (event->keyval == GDK_minus)) { digit = PRESSED_MINUS; } /* time entry widgets are cycled focus by pressing "-" * Tab will go to the next text widget */ if ((digit==PRESSED_TAB) || (digit==PRESSED_MINUS)) { if (widget==begin_time_entry) { gtk_widget_grab_focus(GTK_WIDGET(end_time_entry)); } if (widget==end_time_entry) { if (digit==PRESSED_MINUS) { gtk_widget_grab_focus(GTK_WIDGET(begin_time_entry)); } if (digit==PRESSED_TAB) { gtk_widget_grab_focus(GTK_WIDGET(text_widget1)); } } } if (digit>=0) { if ((digit>=0) && (digit<=9)){ if (GTK_TOGGLE_BUTTON(check_button_notime)->active) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button_notime), FALSE); } } if (widget==begin_time_entry) { entry_key_pressed(digit, 0); } if (widget==end_time_entry) { entry_key_pressed(digit, 1); } return TRUE; } return FALSE; } static gboolean cb_key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer next_widget) { #ifdef ENABLE_GTK2 GtkTextIter cursor_pos_iter; GtkTextBuffer *text_buffer; #endif if (event->keyval == GDK_Tab) { #ifdef ENABLE_GTK2 text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget)); gtk_text_buffer_get_iter_at_mark(text_buffer,&cursor_pos_iter,gtk_text_buffer_get_insert(text_buffer)); if (gtk_text_iter_is_end(&cursor_pos_iter)) #else if (gtk_text_get_point(GTK_TEXT(widget)) == gtk_text_get_length(GTK_TEXT(widget))) #endif { gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "key_press_event"); gtk_widget_grab_focus(GTK_WIDGET(next_widget)); return TRUE; } } return FALSE; } static gboolean cb_keyboard(GtkWidget *widget, GdkEventKey *event, gpointer *p) { struct tm day; int up, down; int b; up = down = 0; switch (event->keyval) { case GDK_Page_Up: case GDK_KP_Page_Up: up=1; break; case GDK_Page_Down: case GDK_KP_Page_Down: down=1; break; } if (up || down) { gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "key_press_event"); b=dialog_save_changed_record(pane, record_changed); if (b==DIALOG_SAID_2) { cb_add_new_record(NULL, GINT_TO_POINTER(record_changed)); } set_new_button_to(CLEAR_FLAG); memset(&day, 0, sizeof(day)); day.tm_year = current_year; day.tm_mon = current_month; day.tm_mday = current_day; day.tm_hour = 12; day.tm_min = 0; if (up) { sub_days_from_date(&day, 1); } if (down) { add_days_to_date(&day, 1); } current_year = day.tm_year; current_month = day.tm_mon; current_day = day.tm_mday; /* This next line prevents a Gtk error message from being printed. * e.g. If the day were 31 and the next month has <31 days then the * select month call will cause an error message since the 31st isn't * valid in that month. So, I set it to 1 first. */ gtk_calendar_freeze(GTK_CALENDAR(main_calendar)); gtk_calendar_select_day(GTK_CALENDAR(main_calendar), 1); gtk_calendar_select_month(GTK_CALENDAR(main_calendar), day.tm_mon, day.tm_year+1900); gtk_calendar_select_day(GTK_CALENDAR(main_calendar), day.tm_mday); gtk_calendar_thaw(GTK_CALENDAR(main_calendar)); return TRUE; } return FALSE; } int datebook_gui_cleanup() { int b; b=dialog_save_changed_record(pane, record_changed); if (b==DIALOG_SAID_2) { cb_add_new_record(NULL, GINT_TO_POINTER(record_changed)); } free_AppointmentList(&glob_al); free_ToDoList(&datebook_todo_list); connect_changed_signals(DISCONNECT_SIGNALS); #ifdef ENABLE_GTK2 set_pref(PREF_DATEBOOK_PANE, gtk_paned_get_position(GTK_PANED(pane)), NULL, TRUE); set_pref(PREF_DATEBOOK_NOTE_PANE, gtk_paned_get_position(GTK_PANED(note_pane)), NULL, TRUE); if (GTK_TOGGLE_BUTTON(show_todos_button)->active) { set_pref(PREF_DATEBOOK_TODO_PANE, gtk_paned_get_position(GTK_PANED(todo_pane)), NULL, TRUE); } #else set_pref(PREF_DATEBOOK_PANE, GTK_PANED(pane)->handle_xpos, NULL, TRUE); set_pref(PREF_DATEBOOK_NOTE_PANE, GTK_PANED(note_pane)->handle_ypos, NULL, TRUE); if (GTK_TOGGLE_BUTTON(show_todos_button)->active) { set_pref(PREF_DATEBOOK_TODO_PANE, GTK_PANED(todo_pane)->handle_ypos, NULL, TRUE); } #endif #ifdef ENABLE_DATEBK if (GTK_IS_WIDGET(window_date_cats)) { gtk_widget_destroy(window_date_cats); } #endif /* Remove the accelerators */ #ifdef ENABLE_GTK2 gtk_window_remove_accel_group(GTK_WINDOW(gtk_widget_get_toplevel(main_calendar)), accel_group); #else gtk_accel_group_detach(accel_group, GTK_OBJECT(gtk_widget_get_toplevel(main_calendar))); #endif gtk_signal_disconnect_by_func(GTK_OBJECT(main_calendar), GTK_SIGNAL_FUNC(cb_keyboard), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(clist), GTK_SIGNAL_FUNC(cb_keyboard), NULL); return EXIT_SUCCESS; } static void connect_changed_signals(int con_or_dis) { int i; static int connected=0; #ifdef ENABLE_DATEBK long use_db3_tags; #endif #ifdef ENABLE_DATEBK get_pref(PREF_USE_DB3, &use_db3_tags, NULL); #endif /* CONNECT */ if ((con_or_dis==CONNECT_SIGNALS) && (!connected)) { connected=1; gtk_signal_connect(GTK_OBJECT(radio_button_alarm_min), "toggled", GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_connect(GTK_OBJECT(radio_button_alarm_hour), "toggled", GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_connect(GTK_OBJECT(radio_button_alarm_day), "toggled", GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_connect(GTK_OBJECT(check_button_alarm), "toggled", GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_connect(GTK_OBJECT(check_button_notime), "toggled", GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_connect(GTK_OBJECT(begin_date_button), "pressed", GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_connect(GTK_OBJECT(begin_time_entry), "changed", GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_connect(GTK_OBJECT(end_time_entry), "changed", GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_connect(GTK_OBJECT(units_entry), "changed", GTK_SIGNAL_FUNC(cb_record_changed), NULL); #ifdef ENABLE_GTK2 g_signal_connect(text_widget1_buffer, "changed", GTK_SIGNAL_FUNC(cb_record_changed), NULL); g_signal_connect(text_widget2_buffer, "changed", GTK_SIGNAL_FUNC(cb_record_changed), NULL); #else gtk_signal_connect(GTK_OBJECT(text_widget1), "changed", GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_connect(GTK_OBJECT(text_widget2), "changed", GTK_SIGNAL_FUNC(cb_record_changed), NULL); #endif #ifdef ENABLE_DATEBK if (use_db3_tags) { if (datebk_entry) { gtk_signal_connect(GTK_OBJECT(datebk_entry), "changed", GTK_SIGNAL_FUNC(cb_record_changed), NULL); } } #endif gtk_signal_connect(GTK_OBJECT(notebook), "switch-page", GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_connect(GTK_OBJECT(repeat_day_entry), "changed", GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_connect(GTK_OBJECT(repeat_week_entry), "changed", GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_connect(GTK_OBJECT(repeat_mon_entry), "changed", GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_connect(GTK_OBJECT(repeat_year_entry), "changed", GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_connect(GTK_OBJECT(check_button_day_endon), "toggled", GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_connect(GTK_OBJECT(check_button_week_endon), "toggled", GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_connect(GTK_OBJECT(check_button_mon_endon), "toggled", GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_connect(GTK_OBJECT(check_button_year_endon), "toggled", GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_connect(GTK_OBJECT(glob_endon_day_button), "pressed", GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_connect(GTK_OBJECT(glob_endon_week_button), "pressed", GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_connect(GTK_OBJECT(glob_endon_mon_button), "pressed", GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_connect(GTK_OBJECT(glob_endon_year_button), "pressed", GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_connect(GTK_OBJECT(toggle_button_repeat_mon_byday), "toggled", GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_connect(GTK_OBJECT(toggle_button_repeat_mon_bydate), "toggled", GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_connect(GTK_OBJECT(private_checkbox), "toggled", GTK_SIGNAL_FUNC(cb_record_changed), NULL); for (i=0; i<7; i++) { gtk_signal_connect(GTK_OBJECT(toggle_button_repeat_days[i]), "toggled", GTK_SIGNAL_FUNC(cb_record_changed), NULL); } } /* DISCONNECT */ if ((con_or_dis==DISCONNECT_SIGNALS) && (connected)) { connected=0; gtk_signal_disconnect_by_func(GTK_OBJECT(radio_button_alarm_min), GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(radio_button_alarm_hour), GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(radio_button_alarm_day), GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(check_button_alarm), GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(check_button_notime), GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(begin_date_button), GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(begin_time_entry), GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(end_time_entry), GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(units_entry), GTK_SIGNAL_FUNC(cb_record_changed), NULL); #ifdef ENABLE_GTK2 g_signal_handlers_disconnect_by_func(text_widget1_buffer, GTK_SIGNAL_FUNC(cb_record_changed), NULL); g_signal_handlers_disconnect_by_func(text_widget2_buffer, GTK_SIGNAL_FUNC(cb_record_changed), NULL); #else gtk_signal_disconnect_by_func(GTK_OBJECT(text_widget1), GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(text_widget2), GTK_SIGNAL_FUNC(cb_record_changed), NULL); #endif #ifdef ENABLE_DATEBK if (use_db3_tags) { if (datebk_entry) { gtk_signal_disconnect_by_func(GTK_OBJECT(datebk_entry), GTK_SIGNAL_FUNC(cb_record_changed), NULL); } } #endif gtk_signal_disconnect_by_func(GTK_OBJECT(notebook), GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(repeat_day_entry), GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(repeat_week_entry), GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(repeat_mon_entry), GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(repeat_year_entry), GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(check_button_day_endon), GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(check_button_week_endon), GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(check_button_mon_endon), GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(check_button_year_endon), GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(glob_endon_day_button), GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(glob_endon_week_button), GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(glob_endon_mon_button), GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(glob_endon_year_button), GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(toggle_button_repeat_mon_byday), GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(toggle_button_repeat_mon_bydate), GTK_SIGNAL_FUNC(cb_record_changed), NULL); gtk_signal_disconnect_by_func(GTK_OBJECT(private_checkbox), GTK_SIGNAL_FUNC(cb_record_changed), NULL); for (i=0; i<7; i++) { gtk_signal_disconnect_by_func(GTK_OBJECT(toggle_button_repeat_days[i]), GTK_SIGNAL_FUNC(cb_record_changed), NULL); } } } GtkWidget *create_time_menu(int flags) { GtkWidget *option; GtkWidget *menu; GtkWidget *item; char str[64]; char buf[64]; int i, i_stop; int cb_factor; struct tm t; option = gtk_option_menu_new(); menu = gtk_menu_new(); /* GTK1 doesn't handle size properly so it must be set explicitly */ #ifndef ENABLE_GTK2 gtk_widget_set_usize(option, 60, 10); #endif memset(&t, 0, sizeof(t)); /* Hours menu */ if (flags&HOURS_FLAG) { i_stop=24; cb_factor=1; get_pref_hour_ampm(str); } else { i_stop=12; cb_factor=5; } for (i = 0; i < i_stop; i++) { if (flags&HOURS_FLAG) { t.tm_hour=i; jp_strftime(buf, sizeof(buf), str, &t); } else { snprintf(buf, sizeof(buf), "%02d", i*cb_factor); } item = gtk_menu_item_new_with_label(buf); gtk_signal_connect(GTK_OBJECT(item), "select", GTK_SIGNAL_FUNC(cb_menu_time), GINT_TO_POINTER(i*cb_factor | flags)); gtk_menu_append(GTK_MENU(menu), item); } gtk_option_menu_set_menu(GTK_OPTION_MENU(option), menu); gtk_signal_connect(GTK_OBJECT(menu), "hide", GTK_SIGNAL_FUNC(cb_hide_menu_time), NULL); return option; } /* * TODO code */ static void cb_todo_clist_selection(GtkWidget *clist, gint row, gint column, GdkEventButton *event, gpointer data) { MyToDo *mtodo; if (!event) return; mtodo = gtk_clist_get_row_data(GTK_CLIST(clist), row); if (mtodo == NULL) { return; } glob_find_id = mtodo->unique_id; cb_app_button(NULL, GINT_TO_POINTER(TODO)); } void cb_todos_show(GtkWidget *widget, gpointer data) { int w, h; long ivalue; set_pref(PREF_DATEBOOK_TODO_SHOW, GTK_TOGGLE_BUTTON(show_todos_button)->active, NULL, TRUE); if (!(GTK_TOGGLE_BUTTON(show_todos_button)->active)) { #ifdef ENABLE_GTK2 set_pref(PREF_DATEBOOK_TODO_PANE, gtk_paned_get_position(GTK_PANED(todo_pane)), NULL, TRUE); #else set_pref(PREF_DATEBOOK_TODO_PANE, GTK_PANED(todo_pane)->handle_ypos, NULL, TRUE); #endif } if (GTK_TOGGLE_BUTTON(widget)->active) { get_pref(PREF_DATEBOOK_TODO_PANE, &ivalue, NULL); gtk_paned_set_position(GTK_PANED(todo_pane), ivalue + PANE_CREEP); gtk_widget_show_all(GTK_WIDGET(todo_vbox)); } else { gtk_widget_hide_all(GTK_WIDGET(todo_vbox)); /* This shouldn't need to be done in gtk2 */ gtk_widget_set_usize(todo_vbox, 1, 1); gdk_window_get_size(gtk_widget_get_toplevel(widget)->window, &w, &h); gtk_paned_set_position(GTK_PANED(todo_pane), h + PANE_CREEP); } } /* * End TODO code */ #ifdef DAY_VIEW static void cb_resize(GtkWidget *widget, gpointer data) { printf("resize\n");//undo } static gint cb_datebook_idle(gpointer data) { update_daily_view_undo(NULL); gtk_signal_connect(GTK_OBJECT(scrolled_window), "configure_event", GTK_SIGNAL_FUNC(cb_resize), NULL); return FALSE; /* Cause this function not to be called again */ } #endif int datebook_gui(GtkWidget *vbox, GtkWidget *hbox) { extern GtkWidget *glob_date_label; extern gint glob_date_timer_tag; GtkWidget *pixmapwid; GdkPixmap *pixmap; GdkBitmap *mask; GtkWidget *button; GtkWidget *separator; GtkWidget *label; GtkWidget *table; #ifndef ENABLE_GTK2 GtkWidget *vscrollbar; #endif GtkWidget *vbox1, *vbox2; GtkWidget *hbox2; GtkWidget *hbox_temp; #ifdef DAY_VIEW GtkWidget *vbox_no_time_appts; GtkWidget *scrolled_window2; #endif GtkWidget *vbox_repeat_day; GtkWidget *hbox_repeat_day1; GtkWidget *hbox_repeat_day2; GtkWidget *vbox_repeat_week; GtkWidget *hbox_repeat_week1; GtkWidget *hbox_repeat_week2; GtkWidget *hbox_repeat_week3; GtkWidget *vbox_repeat_mon; GtkWidget *hbox_repeat_mon1; GtkWidget *hbox_repeat_mon2; GtkWidget *hbox_repeat_mon3; GtkWidget *vbox_repeat_year; GtkWidget *hbox_repeat_year1; GtkWidget *hbox_repeat_year2; GtkWidget *notebook_tab1; GtkWidget *notebook_tab2; GtkWidget *notebook_tab3; GtkWidget *notebook_tab4; GtkWidget *notebook_tab5; GSList *group; char *titles[]={"","","","",""}; long fdow; long ivalue; #ifdef ENABLE_DATEBK long use_db3_tags; #endif int i, j; #define MAX_STR 100 char days2[12]; char *days[] = { N_("Su"), N_("Mo"), N_("Tu"), N_("We"), N_("Th"), N_("Fr"), N_("Sa"), N_("Su") }; init(); #ifdef ENABLE_DATEBK datebk_entry = NULL; get_pref(PREF_USE_DB3, &use_db3_tags, NULL); #endif pane = gtk_hpaned_new(); todo_pane = gtk_vpaned_new(); get_pref(PREF_DATEBOOK_PANE, &ivalue, NULL); gtk_paned_set_position(GTK_PANED(pane), ivalue + PANE_CREEP); get_pref(PREF_DATEBOOK_TODO_PANE, &ivalue, NULL); gtk_paned_set_position(GTK_PANED(todo_pane), ivalue + PANE_CREEP); gtk_box_pack_start(GTK_BOX(hbox), pane, TRUE, TRUE, 5); hbox2 = gtk_hbox_new(FALSE, 0); vbox1 = gtk_vbox_new(FALSE, 0); vbox2 = gtk_vbox_new(FALSE, 0); todo_vbox = gtk_vbox_new(FALSE, 0); gtk_paned_pack1(GTK_PANED(todo_pane), vbox1, TRUE, FALSE); gtk_paned_pack2(GTK_PANED(todo_pane), todo_vbox, TRUE, FALSE); gtk_paned_pack1(GTK_PANED(pane), todo_pane, TRUE, FALSE); gtk_paned_pack2(GTK_PANED(pane), vbox2, TRUE, FALSE); /* Separator */ separator = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(vbox1), separator, FALSE, FALSE, 5); /* Make the Today is: label */ glob_date_label = gtk_label_new(" "); gtk_box_pack_start(GTK_BOX(vbox1), glob_date_label, FALSE, FALSE, 0); timeout_date(NULL); glob_date_timer_tag = gtk_timeout_add(get_timeout_interval(), timeout_date, NULL); /* Separator */ separator = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(vbox1), separator, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox1), hbox2, FALSE, FALSE, 3); /* Make the main calendar */ hbox_temp = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox1), hbox_temp, FALSE, FALSE, 0); get_pref(PREF_FDOW, &fdow, NULL); if (fdow==1) { fdow = GTK_CALENDAR_WEEK_START_MONDAY; } else { fdow=0; } main_calendar = gtk_calendar_new(); gtk_calendar_display_options(GTK_CALENDAR(main_calendar), GTK_CALENDAR_SHOW_HEADING | GTK_CALENDAR_SHOW_DAY_NAMES | GTK_CALENDAR_SHOW_WEEK_NUMBERS | fdow); gtk_box_pack_start(GTK_BOX(hbox_temp), main_calendar, FALSE, FALSE, 0); gtk_signal_connect(GTK_OBJECT(main_calendar), "day_selected", GTK_SIGNAL_FUNC(cb_cal_changed), GINT_TO_POINTER(CAL_DAY_SELECTED)); /* Make accelerators for some buttons window */ accel_group = gtk_accel_group_new(); #ifdef ENABLE_GTK2 gtk_window_add_accel_group(GTK_WINDOW(gtk_widget_get_toplevel(vbox)), accel_group); #else gtk_accel_group_attach(accel_group, GTK_OBJECT(gtk_widget_get_toplevel(vbox))); #endif /* Make Weekview button */ button = gtk_button_new_with_label(_("Week")); gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(cb_weekview), NULL); gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 3); gtk_widget_show(button); gtk_label_set_pattern(GTK_LABEL(GTK_BIN(button)->child), "_"); gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel_group, *_("W"), GDK_MOD1_MASK, GTK_ACCEL_VISIBLE); gtk_tooltips_set_tip(glob_tooltips, button, _("View appointments by week"), NULL); /* Make Monthview button */ button = gtk_button_new_with_label(_("Month")); gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(cb_monthview), NULL); gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 3); gtk_widget_show(button); gtk_label_set_pattern(GTK_LABEL(GTK_BIN(button)->child), "_"); gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel_group, *_("M"), GDK_MOD1_MASK, GTK_ACCEL_VISIBLE); gtk_tooltips_set_tip(glob_tooltips, button, _("View appointments by month"), NULL); #ifdef ENABLE_DATEBK if (use_db3_tags) { /* Make Category button */ button = gtk_button_new_with_label(_("Cats")); gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(cb_date_cats), NULL); gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 3); gtk_widget_show(button); } #endif /* Make the DOW label */ dow_label = gtk_label_new(""); gtk_box_pack_start(GTK_BOX(vbox1), dow_label, FALSE, FALSE, 0); #ifdef DAY_VIEW /* create a new scrolled window. */ scrolled_window2 = gtk_scrolled_window_new(NULL, NULL); gtk_container_set_border_width(GTK_CONTAINER(scrolled_window2), 0); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window2), GTK_POLICY_NEVER, GTK_POLICY_NEVER); /* Create the "No Time" appointment box */ vbox_no_time_appts = gtk_vbox_new(FALSE, 0); gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window2), GTK_WIDGET(vbox_no_time_appts)); gtk_box_pack_start(GTK_BOX(vbox1), scrolled_window2, FALSE, FALSE, 0); #endif /* create a new scrolled window. */ scrolled_window = gtk_scrolled_window_new(NULL, NULL); gtk_container_set_border_width(GTK_CONTAINER(scrolled_window), 0); /* the policy is one of GTK_POLICY AUTOMATIC, or GTK_POLICY_ALWAYS. * GTK_POLICY_AUTOMATIC will automatically decide whether you need * scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars * there. The first one is the horizontal scrollbar, the second, * the vertical. */ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_box_pack_start(GTK_BOX(vbox1), scrolled_window, TRUE, TRUE, 0); #ifdef ENABLE_DATEBK if (use_db3_tags) { clist = gtk_clist_new_with_titles(5, titles); } else { clist = gtk_clist_new_with_titles(4, titles); } #else clist = gtk_clist_new_with_titles(4, titles); #endif gtk_clist_column_titles_passive(GTK_CLIST(clist)); gtk_signal_connect(GTK_OBJECT(clist), "select_row", GTK_SIGNAL_FUNC(cb_clist_selection), NULL); gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_BROWSE); gtk_clist_set_column_auto_resize(GTK_CLIST(clist), DB_TIME_COLUMN, TRUE); gtk_clist_set_column_auto_resize(GTK_CLIST(clist), DB_APPT_COLUMN, FALSE); gtk_clist_set_column_auto_resize(GTK_CLIST(clist), DB_NOTE_COLUMN, TRUE); gtk_clist_set_column_auto_resize(GTK_CLIST(clist), DB_ALARM_COLUMN, TRUE); #ifdef ENABLE_DATEBK gtk_clist_set_column_auto_resize(GTK_CLIST(clist), DB_FLOAT_COLUMN, TRUE); #endif gtk_clist_set_column_title(GTK_CLIST(clist), DB_TIME_COLUMN, _("Time")); gtk_clist_set_column_title(GTK_CLIST(clist), DB_APPT_COLUMN, _("Appointment")); /* Put pretty pictures in the clist column headings */ get_pixmaps(vbox, PIXMAP_NOTE, &pixmap, &mask); pixmapwid = gtk_pixmap_new(pixmap, mask); hack_clist_set_column_title_pixmap(clist, DB_NOTE_COLUMN, pixmapwid); get_pixmaps(vbox, PIXMAP_ALARM, &pixmap, &mask); pixmapwid = gtk_pixmap_new(pixmap, mask); hack_clist_set_column_title_pixmap(clist, DB_ALARM_COLUMN, pixmapwid); #ifdef ENABLE_DATEBK if (use_db3_tags) { get_pixmaps(vbox, PIXMAP_FLOAT_CHECKED, &pixmap, &mask); pixmapwid = gtk_pixmap_new(pixmap, mask); hack_clist_set_column_title_pixmap(clist, DB_FLOAT_COLUMN, pixmapwid); } #endif /* gtk_clist_set_column_justification(GTK_CLIST(clist), 0, GTK_JUSTIFY_FILL);*/ gtk_widget_set_usize(GTK_WIDGET(clist), 10, 10); gtk_widget_set_usize(GTK_WIDGET(scrolled_window), 10, 10); #ifdef DAY_VIEW create_daily_view(scrolled_window, vbox_no_time_appts); gtk_idle_add(cb_datebook_idle, NULL); //undo fix this to be in dayview #else gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(clist)); /*gtk_clist_set_sort_column (GTK_CLIST(clist), 0); */ /*gtk_clist_set_auto_sort(GTK_CLIST(clist), TRUE); */ #endif /* * Hide ToDo button */ show_todos_button = gtk_check_button_new_with_label(_("Show ToDos")); gtk_box_pack_start(GTK_BOX(vbox1), show_todos_button, FALSE, FALSE, 0); gtk_signal_connect(GTK_OBJECT(show_todos_button), "clicked", GTK_SIGNAL_FUNC(cb_todos_show), NULL); /* * Put up a ToDo clist */ todo_scrolled_window = gtk_scrolled_window_new(NULL, NULL); gtk_container_set_border_width(GTK_CONTAINER(todo_scrolled_window), 0); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(todo_scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_box_pack_start(GTK_BOX(todo_vbox), todo_scrolled_window, TRUE, TRUE, 0); todo_clist = gtk_clist_new_with_titles(5, titles); gtk_clist_set_column_title(GTK_CLIST(todo_clist), TODO_TEXT_COLUMN, _("Task")); gtk_clist_set_column_title(GTK_CLIST(todo_clist), TODO_DATE_COLUMN, _("Due")); /* Put pretty pictures in the clist column headings */ get_pixmaps(vbox, PIXMAP_NOTE, &pixmap, &mask); pixmapwid = gtk_pixmap_new(pixmap, mask); hack_clist_set_column_title_pixmap(todo_clist, TODO_NOTE_COLUMN, pixmapwid); get_pixmaps(vbox, PIXMAP_BOX_CHECKED, &pixmap, &mask); pixmapwid = gtk_pixmap_new(pixmap, mask); hack_clist_set_column_title_pixmap(todo_clist, TODO_CHECK_COLUMN, pixmapwid); gtk_clist_column_titles_passive(GTK_CLIST(todo_clist)); gtk_signal_connect(GTK_OBJECT(todo_clist), "select_row", GTK_SIGNAL_FUNC(cb_todo_clist_selection), NULL); gtk_clist_set_shadow_type(GTK_CLIST(todo_clist), SHADOW); gtk_clist_set_selection_mode(GTK_CLIST(todo_clist), GTK_SELECTION_BROWSE); gtk_clist_set_column_auto_resize(GTK_CLIST(todo_clist), TODO_CHECK_COLUMN, TRUE); gtk_clist_set_column_auto_resize(GTK_CLIST(todo_clist), TODO_PRIORITY_COLUMN, TRUE); gtk_clist_set_column_auto_resize(GTK_CLIST(todo_clist), TODO_NOTE_COLUMN, TRUE); gtk_clist_set_column_auto_resize(GTK_CLIST(todo_clist), TODO_DATE_COLUMN, TRUE); gtk_clist_set_column_auto_resize(GTK_CLIST(todo_clist), TODO_TEXT_COLUMN, FALSE); gtk_container_add(GTK_CONTAINER(todo_scrolled_window), GTK_WIDGET(todo_clist)); todo_update_clist(todo_clist, NULL, &datebook_todo_list, CATEGORY_ALL, FALSE); /* * End ToDo clist code */ /* * The right hand part of the main window follows: */ hbox_temp = gtk_hbox_new(FALSE, 3); gtk_box_pack_start(GTK_BOX(vbox2), hbox_temp, FALSE, FALSE, 0); /* Add record modification buttons on right side */ /* Create "event" button */ /* Create Cancel button */ CREATE_BUTTON(cancel_record_button, _("Cancel"), CANCEL, _("Cancel the modifications"), GDK_Escape, 0, "ESC") gtk_signal_connect(GTK_OBJECT(cancel_record_button), "clicked", GTK_SIGNAL_FUNC(cb_cancel), NULL); /* Create "Delete" button */ CREATE_BUTTON(delete_record_button, _("Delete"), DELETE, _("Delete the selected record"), GDK_d, GDK_CONTROL_MASK, "Ctrl+D") gtk_signal_connect(GTK_OBJECT(delete_record_button), "clicked", GTK_SIGNAL_FUNC(cb_delete_appt), GINT_TO_POINTER(DELETE_FLAG)); /* Create "Undelete" button */ CREATE_BUTTON(undelete_record_button, _("Undelete"), UNDELETE, _("Undelete the selected record"), 0, 0, "") gtk_signal_connect(GTK_OBJECT(undelete_record_button), "clicked", GTK_SIGNAL_FUNC(cb_undelete_appt), GINT_TO_POINTER(UNDELETE_FLAG)); /* Create "Copy" button */ CREATE_BUTTON(copy_record_button, _("Copy"), COPY, _("Copy the selected record"), GDK_o, GDK_CONTROL_MASK, "Ctrl+O") gtk_signal_connect(GTK_OBJECT(copy_record_button), "clicked", GTK_SIGNAL_FUNC(cb_add_new_record), GINT_TO_POINTER(COPY_FLAG)); /* Create "New" button */ CREATE_BUTTON(new_record_button, _("New Record"), NEW, _("Add a new record"), GDK_n, GDK_CONTROL_MASK, "Ctrl+N") gtk_signal_connect(GTK_OBJECT(new_record_button), "clicked", GTK_SIGNAL_FUNC(cb_add_new_record), GINT_TO_POINTER(CLEAR_FLAG)); /* Create "Add Record" button */ CREATE_BUTTON(add_record_button, _("Add Record"), ADD, _("Add the new record"), GDK_Return, GDK_CONTROL_MASK, "Ctrl+Enter") gtk_signal_connect(GTK_OBJECT(add_record_button), "clicked", GTK_SIGNAL_FUNC(cb_add_new_record), GINT_TO_POINTER(NEW_FLAG)); #ifndef ENABLE_STOCK_BUTTONS gtk_widget_set_name(GTK_WIDGET(GTK_LABEL(GTK_BIN(add_record_button)->child)), "label_high"); #endif /* Create "apply changes" button */ CREATE_BUTTON(apply_record_button, _("Apply Changes"), APPLY, _("Commit the modifications"), GDK_Return, GDK_CONTROL_MASK, "Ctrl+Enter") gtk_signal_connect(GTK_OBJECT(apply_record_button), "clicked", GTK_SIGNAL_FUNC(cb_add_new_record), GINT_TO_POINTER(MODIFY_FLAG)); #ifndef ENABLE_STOCK_BUTTONS gtk_widget_set_name(GTK_WIDGET(GTK_LABEL(GTK_BIN(apply_record_button)->child)), "label_high"); #endif /* start details */ separator = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(vbox2), separator, FALSE, FALSE, 5); /* The checkbox for Alarm */ hbox_alarm1 = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox2), hbox_alarm1, FALSE, FALSE, 0); check_button_alarm = gtk_check_button_new_with_label (_("Alarm")); gtk_box_pack_start(GTK_BOX(hbox_alarm1), check_button_alarm, FALSE, FALSE, 5); gtk_signal_connect(GTK_OBJECT(check_button_alarm), "clicked", GTK_SIGNAL_FUNC(cb_check_button_alarm), NULL); hbox_alarm2 = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox_alarm1), hbox_alarm2, FALSE, FALSE, 0); /* gtk_widget_show(hbox_alarm2); */ /* Units entry for alarm */ units_entry = gtk_entry_new_with_max_length(2); gtk_widget_set_usize(units_entry, 30, 0); gtk_box_pack_start(GTK_BOX(hbox_alarm2), units_entry, FALSE, FALSE, 0); radio_button_alarm_min = gtk_radio_button_new_with_label(NULL, _("Minutes")); group = NULL; group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio_button_alarm_min)); radio_button_alarm_hour = gtk_radio_button_new_with_label(group, _("Hours")); group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio_button_alarm_hour)); radio_button_alarm_day = gtk_radio_button_new_with_label(group, _("Days")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_button_alarm_min), TRUE); gtk_box_pack_start(GTK_BOX(hbox_alarm2), radio_button_alarm_min, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox_alarm2), radio_button_alarm_hour, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox_alarm2), radio_button_alarm_day, FALSE, FALSE, 0); /* Private check box */ private_checkbox = gtk_check_button_new_with_label(_("Private")); gtk_box_pack_end(GTK_BOX(hbox_alarm1), private_checkbox, FALSE, FALSE, 0); /* * Begin begin and end dates */ /* The checkbox for timeless events */ hbox_temp = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox2), hbox_temp, FALSE, FALSE, 0); check_button_notime = gtk_check_button_new_with_label( _("This Event has no particular time")); gtk_box_pack_start(GTK_BOX(hbox_temp), check_button_notime, FALSE, FALSE, 5); gtk_signal_connect(GTK_OBJECT(check_button_notime), "clicked", GTK_SIGNAL_FUNC(cb_check_button_notime), NULL); hbox_temp = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox2), hbox_temp, FALSE, FALSE, 0); label = gtk_label_new(_("Starts on")); gtk_box_pack_start(GTK_BOX(hbox_temp), label, FALSE, FALSE, 0); begin_date_button = gtk_button_new_with_label(""); gtk_box_pack_start(GTK_BOX(hbox_temp), begin_date_button, FALSE, FALSE, 5); gtk_signal_connect(GTK_OBJECT(begin_date_button), "clicked", GTK_SIGNAL_FUNC(cb_cal_dialog), GINT_TO_POINTER(BEGIN_DATE_BUTTON)); table = gtk_table_new(2, 4, FALSE); gtk_table_set_row_spacings(GTK_TABLE(table), 0); gtk_table_set_col_spacings(GTK_TABLE(table), 0); gtk_box_pack_start(GTK_BOX(vbox2), table, FALSE, FALSE, 0); label = gtk_label_new(_("Start Time")); gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(label), 0, 1, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); begin_time_entry = gtk_entry_new_with_max_length(7); gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(begin_time_entry), 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); /* Menu time choosers */ option1=create_time_menu(START_TIME_FLAG | HOURS_FLAG); gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(option1), 2, 3, 0, 1, GTK_SHRINK, GTK_FILL, 0, 0); option2=create_time_menu(START_TIME_FLAG); gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(option2), 3, 4, 0, 1, GTK_SHRINK, GTK_FILL, 0, 0); label = gtk_label_new(_("End Time")); gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(label), 0, 1, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); end_time_entry = gtk_entry_new_with_max_length(7); gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(end_time_entry), 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); gtk_widget_set_usize(GTK_WIDGET(begin_time_entry), 70, 0); gtk_widget_set_usize(GTK_WIDGET(end_time_entry), 70, 0); option3=create_time_menu(END_TIME_FLAG | HOURS_FLAG ); gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(option3), 2, 3, 1, 2, GTK_SHRINK, GTK_FILL, 0, 0); option4=create_time_menu(END_TIME_FLAG); gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(option4), 3, 4, 1, 2, GTK_SHRINK, GTK_FILL, 0, 0); /* End time selection */ /* Need to connect these signals after the menus are created to avoid errors */ gtk_signal_connect(GTK_OBJECT(begin_time_entry), "key_press_event", GTK_SIGNAL_FUNC(cb_entry_key_pressed), NULL); gtk_signal_connect(GTK_OBJECT(end_time_entry), "key_press_event", GTK_SIGNAL_FUNC(cb_entry_key_pressed), NULL); gtk_signal_connect(GTK_OBJECT(begin_time_entry), "button_press_event", GTK_SIGNAL_FUNC(cb_entry_pressed), GINT_TO_POINTER(1)); gtk_signal_connect(GTK_OBJECT(end_time_entry), "button_press_event", GTK_SIGNAL_FUNC(cb_entry_pressed), GINT_TO_POINTER(2)); clear_begin_end_labels(); /* End time chooser */ /* End begin and end dates */ note_pane = gtk_vpaned_new(); get_pref(PREF_DATEBOOK_NOTE_PANE, &ivalue, NULL); gtk_paned_set_position(GTK_PANED(note_pane), ivalue + PANE_CREEP); gtk_box_pack_start(GTK_BOX(vbox2), note_pane, TRUE, TRUE, 5); /* Text 1 */ hbox_temp = gtk_hbox_new(FALSE, 0); gtk_paned_pack1(GTK_PANED(note_pane), hbox_temp, TRUE, FALSE); #ifdef ENABLE_GTK2 text_widget1 = gtk_text_view_new(); text_widget1_buffer = G_OBJECT(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_widget1))); gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text_widget1), GTK_WRAP_WORD); scrolled_window = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); gtk_container_set_border_width(GTK_CONTAINER(scrolled_window), 1); gtk_container_add(GTK_CONTAINER(scrolled_window), text_widget1); gtk_box_pack_start_defaults(GTK_BOX(hbox_temp), scrolled_window); #else text_widget1 = gtk_text_new(NULL, NULL); gtk_text_set_word_wrap(GTK_TEXT(text_widget1), TRUE); vscrollbar = gtk_vscrollbar_new(GTK_TEXT(text_widget1)->vadj); gtk_box_pack_start(GTK_BOX(hbox_temp), text_widget1, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(hbox_temp), vscrollbar, FALSE, FALSE, 0); #endif /* gtk_widget_set_usize(GTK_WIDGET(text_widget1), 255, 50); */ gtk_widget_set_usize(GTK_WIDGET(text_widget1), 10, 10); /* Text 2 */ hbox_temp = gtk_hbox_new(FALSE, 0); gtk_paned_pack2(GTK_PANED(note_pane), hbox_temp, TRUE, FALSE); #ifdef ENABLE_GTK2 text_widget2 = gtk_text_view_new(); text_widget2_buffer = G_OBJECT(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_widget2))); gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text_widget2), GTK_WRAP_WORD); scrolled_window = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); gtk_container_set_border_width(GTK_CONTAINER(scrolled_window), 1); gtk_container_add(GTK_CONTAINER(scrolled_window), text_widget2); gtk_box_pack_start_defaults(GTK_BOX(hbox_temp), scrolled_window); #else text_widget2 = gtk_text_new(NULL, NULL); gtk_text_set_word_wrap(GTK_TEXT(text_widget2), TRUE); vscrollbar = gtk_vscrollbar_new(GTK_TEXT(text_widget2)->vadj); gtk_box_pack_start(GTK_BOX(hbox_temp), text_widget2, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(hbox_temp), vscrollbar, FALSE, FALSE, 0); #endif gtk_widget_set_usize(GTK_WIDGET(text_widget2), 10, 10); /* Datebk tags entry */ #ifdef ENABLE_DATEBK if (use_db3_tags) { hbox_temp = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox2), hbox_temp, FALSE, FALSE, 2); label = gtk_label_new(_("DateBk Tags")); gtk_box_pack_start(GTK_BOX(hbox_temp), label, FALSE, FALSE, 5); datebk_entry = gtk_entry_new_with_max_length(30); gtk_box_pack_start(GTK_BOX(hbox_temp), datebk_entry, TRUE, TRUE, 0); } #endif /* Add the notebook for repeat types */ hbox_temp = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox2), hbox_temp, FALSE, FALSE, 2); notebook = gtk_notebook_new(); gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP); gtk_box_pack_start(GTK_BOX(hbox_temp), notebook, FALSE, FALSE, 5); /* labels for notebook */ notebook_tab1 = gtk_label_new(_("None")); notebook_tab2 = gtk_label_new(_("Day")); notebook_tab3 = gtk_label_new(_("Week")); notebook_tab4 = gtk_label_new(_("Month")); notebook_tab5 = gtk_label_new(_("Year")); /* no repeat page for notebook */ label = gtk_label_new(_("This event will not repeat")); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), label, notebook_tab1); /* end no repeat page */ /* Day Repeat page for notebook */ vbox_repeat_day = gtk_vbox_new(FALSE, 0); hbox_repeat_day1 = gtk_hbox_new(FALSE, 0); hbox_repeat_day2 = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox_repeat_day), hbox_repeat_day1, FALSE, FALSE, 2); gtk_box_pack_start(GTK_BOX(vbox_repeat_day), hbox_repeat_day2, FALSE, FALSE, 2); label = gtk_label_new(_("Frequency is Every")); gtk_box_pack_start(GTK_BOX(hbox_repeat_day1), label, FALSE, FALSE, 2); repeat_day_entry = gtk_entry_new_with_max_length(2); gtk_widget_set_usize(repeat_day_entry, 30, 0); gtk_box_pack_start(GTK_BOX(hbox_repeat_day1), repeat_day_entry, FALSE, FALSE, 0); label = gtk_label_new(_("Day(s)")); gtk_box_pack_start(GTK_BOX(hbox_repeat_day1), label, FALSE, FALSE, 2); /* checkbutton */ check_button_day_endon = gtk_check_button_new_with_label (_("End on")); gtk_signal_connect(GTK_OBJECT(check_button_day_endon), "clicked", GTK_SIGNAL_FUNC(cb_check_button_endon), GINT_TO_POINTER(PAGE_DAY)); gtk_box_pack_start(GTK_BOX(hbox_repeat_day2), check_button_day_endon, FALSE, FALSE, 0); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox_repeat_day, notebook_tab2); glob_endon_day_button = gtk_button_new_with_label(_("No Date")); gtk_box_pack_start(GTK_BOX(hbox_repeat_day2), glob_endon_day_button, FALSE, FALSE, 0); gtk_signal_connect(GTK_OBJECT(glob_endon_day_button), "clicked", GTK_SIGNAL_FUNC(cb_cal_dialog), GINT_TO_POINTER(PAGE_DAY)); /* The Week page */ vbox_repeat_week = gtk_vbox_new(FALSE, 0); hbox_repeat_week1 = gtk_hbox_new(FALSE, 0); hbox_repeat_week2 = gtk_hbox_new(FALSE, 0); hbox_repeat_week3 = gtk_hbox_new(FALSE, 0); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox_repeat_week, notebook_tab3); gtk_box_pack_start(GTK_BOX(vbox_repeat_week), hbox_repeat_week1, FALSE, FALSE, 2); gtk_box_pack_start(GTK_BOX(vbox_repeat_week), hbox_repeat_week2, FALSE, FALSE, 2); gtk_box_pack_start(GTK_BOX(vbox_repeat_week), hbox_repeat_week3, FALSE, FALSE, 2); label = gtk_label_new(_("Frequency is Every")); gtk_box_pack_start(GTK_BOX(hbox_repeat_week1), label, FALSE, FALSE, 2); repeat_week_entry = gtk_entry_new_with_max_length(2); gtk_widget_set_usize(repeat_week_entry, 30, 0); gtk_box_pack_start(GTK_BOX(hbox_repeat_week1), repeat_week_entry, FALSE, FALSE, 0); label = gtk_label_new(_("Week(s)")); gtk_box_pack_start(GTK_BOX(hbox_repeat_week1), label, FALSE, FALSE, 2); /* checkbutton */ check_button_week_endon = gtk_check_button_new_with_label(_("End on")); gtk_signal_connect(GTK_OBJECT(check_button_week_endon), "clicked", GTK_SIGNAL_FUNC(cb_check_button_endon), GINT_TO_POINTER(PAGE_WEEK)); gtk_box_pack_start(GTK_BOX(hbox_repeat_week2), check_button_week_endon, FALSE, FALSE, 0); glob_endon_week_button = gtk_button_new_with_label(_("No Date")); gtk_box_pack_start(GTK_BOX(hbox_repeat_week2), glob_endon_week_button, FALSE, FALSE, 0); gtk_signal_connect(GTK_OBJECT(glob_endon_week_button), "clicked", GTK_SIGNAL_FUNC(cb_cal_dialog), GINT_TO_POINTER(PAGE_WEEK)); label = gtk_label_new (_("Repeat on Days:")); gtk_box_pack_start(GTK_BOX(hbox_repeat_week3), label, FALSE, FALSE, 0); get_pref(PREF_FDOW, &fdow, NULL); for (i=0, j=fdow; i<7; i++, j++) { if (j>6) { j=0; } g_strlcpy(days2, _(days[j]), sizeof(days2)); /* If no translation occurred then use the first letter only */ if (!strcmp(days2, days[j])) { days2[0]=days[j][0]; days2[1]='\0'; } toggle_button_repeat_days[j] = gtk_toggle_button_new_with_label(days2); gtk_box_pack_start(GTK_BOX(hbox_repeat_week3), toggle_button_repeat_days[j], FALSE, FALSE, 0); } /* end week page */ /*The Month page */ vbox_repeat_mon = gtk_vbox_new(FALSE, 0); hbox_repeat_mon1 = gtk_hbox_new(FALSE, 0); hbox_repeat_mon2 = gtk_hbox_new(FALSE, 0); hbox_repeat_mon3 = gtk_hbox_new(FALSE, 0); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox_repeat_mon, notebook_tab4); gtk_box_pack_start(GTK_BOX(vbox_repeat_mon), hbox_repeat_mon1, FALSE, FALSE, 2); gtk_box_pack_start(GTK_BOX(vbox_repeat_mon), hbox_repeat_mon2, FALSE, FALSE, 2); gtk_box_pack_start(GTK_BOX(vbox_repeat_mon), hbox_repeat_mon3, FALSE, FALSE, 2); label = gtk_label_new(_("Frequency is Every")); gtk_box_pack_start(GTK_BOX(hbox_repeat_mon1), label, FALSE, FALSE, 2); repeat_mon_entry = gtk_entry_new_with_max_length(2); gtk_widget_set_usize(repeat_mon_entry, 30, 0); gtk_box_pack_start(GTK_BOX(hbox_repeat_mon1), repeat_mon_entry, FALSE, FALSE, 0); label = gtk_label_new (_("Month(s)")); gtk_box_pack_start(GTK_BOX(hbox_repeat_mon1), label, FALSE, FALSE, 2); /* checkbutton */ check_button_mon_endon = gtk_check_button_new_with_label (_("End on")); gtk_signal_connect(GTK_OBJECT(check_button_mon_endon), "clicked", GTK_SIGNAL_FUNC(cb_check_button_endon), GINT_TO_POINTER(PAGE_MONTH)); gtk_box_pack_start(GTK_BOX(hbox_repeat_mon2), check_button_mon_endon, FALSE, FALSE, 0); glob_endon_mon_button = gtk_button_new_with_label(_("No Date")); gtk_box_pack_start(GTK_BOX(hbox_repeat_mon2), glob_endon_mon_button, FALSE, FALSE, 0); gtk_signal_connect(GTK_OBJECT(glob_endon_mon_button), "clicked", GTK_SIGNAL_FUNC(cb_cal_dialog), GINT_TO_POINTER(PAGE_MONTH)); label = gtk_label_new (_("Repeat by:")); gtk_box_pack_start(GTK_BOX(hbox_repeat_mon3), label, FALSE, FALSE, 0); toggle_button_repeat_mon_byday = gtk_radio_button_new_with_label (NULL, _("Day of week")); gtk_box_pack_start(GTK_BOX(hbox_repeat_mon3), toggle_button_repeat_mon_byday, FALSE, FALSE, 0); group = NULL; group = gtk_radio_button_group(GTK_RADIO_BUTTON(toggle_button_repeat_mon_byday)); toggle_button_repeat_mon_bydate = gtk_radio_button_new_with_label (group, _("Date")); gtk_box_pack_start(GTK_BOX(hbox_repeat_mon3), toggle_button_repeat_mon_bydate, FALSE, FALSE, 0); /* end Month page */ /* Repeat year page for notebook */ vbox_repeat_year = gtk_vbox_new(FALSE, 0); hbox_repeat_year1 = gtk_hbox_new(FALSE, 0); hbox_repeat_year2 = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox_repeat_year), hbox_repeat_year1, FALSE, FALSE, 2); gtk_box_pack_start(GTK_BOX(vbox_repeat_year), hbox_repeat_year2, FALSE, FALSE, 2); label = gtk_label_new(_("Frequency is Every")); gtk_box_pack_start(GTK_BOX (hbox_repeat_year1), label, FALSE, FALSE, 2); repeat_year_entry = gtk_entry_new_with_max_length(2); gtk_widget_set_usize(repeat_year_entry, 30, 0); gtk_box_pack_start(GTK_BOX(hbox_repeat_year1), repeat_year_entry, FALSE, FALSE, 0); label = gtk_label_new(_("Year(s)")); gtk_box_pack_start(GTK_BOX(hbox_repeat_year1), label, FALSE, FALSE, 2); /* checkbutton */ check_button_year_endon = gtk_check_button_new_with_label (_("End on")); gtk_signal_connect(GTK_OBJECT(check_button_year_endon), "clicked", GTK_SIGNAL_FUNC(cb_check_button_endon), GINT_TO_POINTER(PAGE_YEAR)); gtk_box_pack_start(GTK_BOX(hbox_repeat_year2), check_button_year_endon, FALSE, FALSE, 0); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox_repeat_year, notebook_tab5); glob_endon_year_button = gtk_button_new_with_label(_("No Date")); gtk_box_pack_start(GTK_BOX(hbox_repeat_year2), glob_endon_year_button, FALSE, FALSE, 0); gtk_signal_connect(GTK_OBJECT(glob_endon_year_button), "clicked", GTK_SIGNAL_FUNC(cb_cal_dialog), GINT_TO_POINTER(PAGE_YEAR)); /* end repeat year page */ /* Set some sane values */ gtk_entry_set_text(GTK_ENTRY(units_entry), "5"); gtk_entry_set_text(GTK_ENTRY(repeat_day_entry), "1"); gtk_entry_set_text(GTK_ENTRY(repeat_week_entry), "1"); gtk_entry_set_text(GTK_ENTRY(repeat_mon_entry), "1"); gtk_entry_set_text(GTK_ENTRY(repeat_year_entry), "1"); gtk_notebook_set_page(GTK_NOTEBOOK(notebook), 0); /* end details */ /* Capture the TAB key in text_widget1 */ gtk_signal_connect(GTK_OBJECT(text_widget1), "key_press_event", GTK_SIGNAL_FUNC(cb_key_pressed), text_widget2); /* These have to be shown before the show_all */ gtk_widget_show(notebook_tab1); gtk_widget_show(notebook_tab2); gtk_widget_show(notebook_tab3); gtk_widget_show(notebook_tab4); gtk_widget_show(notebook_tab5); gtk_widget_show_all(vbox); gtk_widget_show_all(hbox); gtk_widget_hide(add_record_button); gtk_widget_hide(apply_record_button); gtk_widget_hide(undelete_record_button); gtk_widget_hide(cancel_record_button); get_pref(PREF_DATEBOOK_TODO_SHOW, &ivalue, NULL); if (!ivalue) { gtk_widget_hide_all(todo_vbox); gtk_paned_set_position(GTK_PANED(todo_pane), 100000); } else { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(show_todos_button), TRUE); } #ifdef ENABLE_GTK2 gtk_text_view_set_editable(GTK_TEXT_VIEW(text_widget1), TRUE); gtk_text_view_set_editable(GTK_TEXT_VIEW(text_widget2), TRUE); #else gtk_text_set_editable(GTK_TEXT(text_widget1), TRUE); gtk_text_set_editable(GTK_TEXT(text_widget2), TRUE); #endif /* Capture the Enter & Shift-Enter key combinations to move back and * forth between the left- and right-hand sides of the display. */ gtk_signal_connect(GTK_OBJECT(clist), "key_press_event", GTK_SIGNAL_FUNC(cb_key_pressed_left_side), text_widget1); gtk_signal_connect(GTK_OBJECT(text_widget1), "key_press_event", GTK_SIGNAL_FUNC(cb_key_pressed_right_side), clist); gtk_signal_connect(GTK_OBJECT(text_widget2), "key_press_event", GTK_SIGNAL_FUNC(cb_key_pressed_right_side), clist); gtk_notebook_popup_enable(GTK_NOTEBOOK(notebook)); datebook_refresh(TRUE, TRUE); /* The focus doesn't do any good on the application button */ gtk_widget_grab_focus(GTK_WIDGET(main_calendar)); gtk_signal_connect(GTK_OBJECT(main_calendar), "key_press_event", GTK_SIGNAL_FUNC(cb_keyboard), NULL); gtk_signal_connect(GTK_OBJECT(clist), "key_press_event", GTK_SIGNAL_FUNC(cb_keyboard), NULL); return EXIT_SUCCESS; }