pkg://jpilot-0.99.2-8.src.rpm:872711/jpilot-0.99.2.tar.gz
info downloads
jpilot-0.99.2/ 0040755 0001750 0000144 00000000000 07430305566 012177 5 ustar mouse users jpilot-0.99.2/address.c 0100644 0001750 0000144 00000024300 07423403442 013756 0 ustar mouse users /* address.c
* A module of J-Pilot http://jpilot.org
*
* Copyright (C) 1999-2001 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
*/
#include "config.h"
#include "i18n.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <pi-source.h>
#include <pi-socket.h>
#include <pi-address.h>
#include <pi-dlp.h>
#include "address.h"
#include "utils.h"
#include "log.h"
#include "prefs.h"
#include "libplugin.h"
#include "password.h"
#define ADDRESS_EOF 7
static int glob_sort_by_company;
int sort_override=0;
#ifdef JPILOT_DEBUG
int print_address_list(AddressList **al)
{
AddressList *temp_al, *prev_al, *next;
for (prev_al=NULL, temp_al=*al; temp_al;
prev_al=temp_al, temp_al=temp_al->next) {
jpilot_logf(LOG_FILE | LOG_STDOUT, "entry[0]=[%s]\n", temp_al->ma.a.entry[0]);
}
}
#endif
int address_compare(const void *v1, const void *v2)
{
char *str1, *str2;
int sort1, sort2, sort3;
AddressList **al1, **al2;
struct Address *a1, *a2;
int i;
al1=(AddressList **)v1;
al2=(AddressList **)v2;
a1=&((*al1)->ma.a);
a2=&((*al2)->ma.a);
if (glob_sort_by_company) {
sort1=2; /*company */
sort2=0; /*last name */
sort3=1; /*first name */
} else {
sort1=0; /*last name */
sort2=1; /*first name */
sort3=2; /*company */
}
/*sort_by_company: */
/*0 last, first or */
/*1 company, last */
str1=str2=NULL;
if (a1->entry[sort1] || a1->entry[sort2]) {
if (a1->entry[sort1] && a1->entry[sort2]) {
if ((str1 = (char *)malloc(strlen(a1->entry[sort1])+strlen(a1->entry[sort2])+1)) == NULL) {
return 0;
}
strcpy(str1, a1->entry[sort1]);
strcat(str1, a1->entry[sort2]);
}
if (a1->entry[sort1] && (!a1->entry[sort2])) {
if ((str1 = (char *)malloc(strlen(a1->entry[sort1])+1)) == NULL) {
return 0;
}
strcpy(str1, a1->entry[sort1]);
}
if ((!a1->entry[sort1]) && a1->entry[sort2]) {
if ((str1 = (char *)malloc(strlen(a1->entry[sort2])+1)) == NULL) {
return 0;
}
strcpy(str1, a1->entry[sort2]);
}
} else if (a1->entry[sort3]) {
if ((str1 = (char *)malloc(strlen(a1->entry[sort3])+1)) == NULL) {
return 0;
}
strcpy(str1, a1->entry[sort3]);
} else {
return -1;
}
if (a2->entry[sort1] || a2->entry[sort2]) {
if (a2->entry[sort1] && a2->entry[sort2]) {
if ((str2 = (char *)malloc(strlen(a2->entry[sort1])+strlen(a2->entry[sort2])+1)) == NULL) {
return 0;
}
strcpy(str2, a2->entry[sort1]);
strcat(str2, a2->entry[sort2]);
}
if (a2->entry[sort1] && (!a2->entry[sort2])) {
if ((str2 = (char *)malloc(strlen(a2->entry[sort1])+1)) == NULL) {
return 0;
}
strcpy(str2, a2->entry[sort1]);
}
if ((!a2->entry[sort1]) && a2->entry[sort2]) {
if ((str2 = (char *)malloc(strlen(a2->entry[sort2])+1)) == NULL) {
return 0;
}
strcpy(str2, a2->entry[sort2]);
}
} else if (a2->entry[sort3]) {
if ((str2 = (char *)malloc(strlen(a2->entry[sort3])+1)) == NULL) {
return 0;
}
strcpy(str2, a2->entry[sort3]);
} else {
free(str1);
return 1;
}
/* lower case the strings for a better compare */
for (i=strlen(str1)-1; i >= 0; i--) {
str1[i] = tolower(str1[i]);
}
for (i=strlen(str2)-1; i >= 0; i--) {
str2[i] = tolower(str2[i]);
}
i = strcoll(str2, str1);
if (str1) {
free(str1);
}
if (str2) {
free(str2);
}
return i;
}
/*
* sort_order: 0=descending, 1=ascending
*/
int address_sort(AddressList **al, int sort_order)
{
AddressList *temp_al;
AddressList **sort_al;
struct AddressAppInfo ai;
int count, i;
/* Count the entries in the list */
for (count=0, temp_al=*al; temp_al; temp_al=temp_al->next, count++) {
;
}
if (count<2) {
/* We don't have to sort less than 2 items */
return 0;
}
get_address_app_info(&ai);
glob_sort_by_company = ai.sortByCompany;
if (sort_override) {
glob_sort_by_company = !(ai.sortByCompany & 1);
}
/* Allocate an array to be qsorted */
sort_al = calloc(count, sizeof(AddressList *));
if (!sort_al) {
jpilot_logf(LOG_WARN, "address_sort(): Out of Memory\n");
return 0;
}
/* Set our array to be a list of pointers to the nodes in the linked list */
for (i=0, temp_al=*al; temp_al; temp_al=temp_al->next, i++) {
sort_al[i] = temp_al;
}
/* qsort them */
qsort(sort_al, count, sizeof(AddressList *), address_compare);
/* Put the linked list in the order of the array */
if (sort_order==SORT_ASCENDING) {
for (i=count-1; i>0; i--) {
sort_al[i]->next=sort_al[i-1];
}
sort_al[0]->next = NULL;
*al = sort_al[count-1];
} else {
/* Descending order */
sort_al[count-1]->next = NULL;
for (i=count-1; i; i--) {
sort_al[i-1]->next=sort_al[i];
}
*al = sort_al[0];
}
free(sort_al);
return 0;
}
int pc_address_write(struct Address *a, PCRecType rt, unsigned char attrib,
unsigned int *unique_id)
{
char record[65536];
int rec_len,i;
buf_rec br;
long char_set;
get_pref(PREF_CHAR_SET, &char_set, NULL);
if (char_set != CHAR_SET_ENGLISH) {
for (i = 0; i < 19; i++) {
if (a->entry[i]) charset_j2p(a->entry[i], strlen(a->entry[i])+1, char_set);
}
}
rec_len = pack_Address(a, record, 65535);
if (!rec_len) {
PRINT_FILE_LINE;
jpilot_logf(LOG_WARN, "pack_Address %s\n", _("error"));
return -1;
}
br.rt=rt;
br.attrib = attrib;
br.buf = record;
br.size = rec_len;
jp_pc_write("AddressDB", &br);
*unique_id = br.unique_id;
return 0;
}
void free_AddressList(AddressList **al)
{
AddressList *temp_al, *temp_al_next;
for (temp_al = *al; temp_al; temp_al=temp_al_next) {
free_Address(&(temp_al->ma.a));
temp_al_next = temp_al->next;
free(temp_al);
}
*al = NULL;
}
int get_address_app_info(struct AddressAppInfo *ai)
{
int num;
unsigned int rec_size;
unsigned char *buf;
long char_set;
bzero(ai, sizeof(*ai));
jp_get_app_info("AddressDB", &buf, &rec_size);
num = unpack_AddressAppInfo(ai, buf, rec_size);
if (buf) {
free(buf);
}
if (num <= 0) {
jpilot_logf(LOG_WARN, _("Error reading"), "AddressDB.pdb");
return -1;
}
get_pref(PREF_CHAR_SET, &char_set, NULL);
if (char_set != CHAR_SET_ENGLISH) {
/* Convert to character set */
int i;
for (i = 0; i < 16; i++)
if (ai->category.name[i][0] != '\0') {
charset_p2j(ai->category.name[i], 16, char_set);
}
for (i = 0; i < 19 + 3; i++)
if (ai->labels[i][0] != '\0') {
charset_p2j(ai->labels[i],16, char_set);
}
for (i = 0; i < 8; i++)
if (ai->phoneLabels[i][0] != '\0') {
charset_p2j(ai->phoneLabels[i],16, char_set);
}
}
return 0;
}
int get_addresses(AddressList **address_list, int sort_order)
{
return get_addresses2(address_list, sort_order, 1, 1, 1, CATEGORY_ALL);
}
/*
* sort_order: 0=descending, 1=ascending
* modified, deleted and private, 0 for no, 1 for yes, 2 for use prefs
*/
int get_addresses2(AddressList **address_list, int sort_order,
int modified, int deleted, int privates, int category)
{
GList *records;
GList *temp_list;
int recs_returned, i, num;
struct Address a;
AddressList *temp_a_list;
long keep_modified, keep_deleted;
int keep_priv;
long char_set;
buf_rec *br;
jpilot_logf(LOG_DEBUG, "get_addresses2()\n");
if (modified==2) {
get_pref(PREF_SHOW_MODIFIED, &keep_modified, NULL);
} else {
keep_modified = modified;
}
if (deleted==2) {
get_pref(PREF_SHOW_DELETED, &keep_deleted, NULL);
} else {
keep_deleted = deleted;
}
if (privates==2) {
keep_priv = show_privates(GET_PRIVATES, NULL);
} else {
keep_priv = privates;
}
*address_list=NULL;
recs_returned = 0;
num = jp_read_DB_files("AddressDB", &records);
/* Go to first entry in the list */
for (temp_list = records; temp_list; temp_list = temp_list->prev) {
records = temp_list;
}
for (i=0, temp_list = records; temp_list; temp_list = temp_list->next, i++) {
if (temp_list->data) {
br=temp_list->data;
} else {
continue;
}
if (!br->buf) {
continue;
}
if ( ((br->rt==DELETED_PALM_REC) && (!keep_deleted)) ||
((br->rt==MODIFIED_PALM_REC) && (!keep_modified)) ) {
continue;
}
if ((keep_priv != SHOW_PRIVATES) &&
(br->attrib & dlpRecAttrSecret)) {
continue;
}
num = unpack_Address(&a, br->buf, br->size);
if (num <= 0) {
continue;
}
if ( ((br->attrib & 0x0F) != category) && category != CATEGORY_ALL) {
continue;
}
get_pref(PREF_CHAR_SET, &char_set, NULL);
if (char_set != CHAR_SET_ENGLISH) {
for (i = 0; i < 19; i++) {
if ((a.entry[i] != NULL) && (a.entry[i][0] != '\0')) {
charset_p2j(a.entry[i], strlen(a.entry[i])+1, char_set);
}
}
}
temp_a_list = malloc(sizeof(AddressList));
if (!temp_a_list) {
jpilot_logf(LOG_WARN, "get_addresses2(): Out of memory\n");
break;
}
memcpy(&(temp_a_list->ma.a), &a, sizeof(struct Address));
temp_a_list->app_type = ADDRESS;
temp_a_list->ma.rt = br->rt;
temp_a_list->ma.attrib = br->attrib;
temp_a_list->ma.unique_id = br->unique_id;
temp_a_list->next = *address_list;
*address_list = temp_a_list;
recs_returned++;
}
jp_free_DB_records(&records);
#ifdef JPILOT_DEBUG
print_address_list(address_list);
#endif
address_sort(address_list, sort_order);
jpilot_logf(LOG_DEBUG, "Leaving get_addresses2()\n");
return recs_returned;
}
jpilot-0.99.2/address_gui.c 0100644 0001750 0000144 00000161710 07424211157 014632 0 ustar mouse users /* address_gui.c
* A module of J-Pilot http://jpilot.org
*
* Copyright (C) 1999-2001 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
*/
#include "config.h"
#include "i18n.h"
#include <sys/stat.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <gdk/gdk.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include "utils.h"
#include "address.h"
#include "log.h"
#include "prefs.h"
#include "print.h"
#include "password.h"
#include "export.h"
#include <pi-dlp.h>
/*#define SHADOW GTK_SHADOW_IN */
/*#define SHADOW GTK_SHADOW_OUT */
/*#define SHADOW GTK_SHADOW_ETCHED_IN */
#define SHADOW GTK_SHADOW_ETCHED_OUT
#define CONNECT_SIGNALS 400
#define DISCONNECT_SIGNALS 401
#define NUM_MENU_ITEM1 8
#define NUM_MENU_ITEM2 8
#define NUM_ADDRESS_CAT_ITEMS 16
#define NUM_ADDRESS_ENTRIES 19
#define NUM_ADDRESS_LABELS 22
#define NUM_PHONE_ENTRIES 5
#define ADDRESS_NAME_COLUMN 0
#define ADDRESS_NOTE_COLUMN 1
#define ADDRESS_PHONE_COLUMN 2
#define ADDRESS_MAX_CLIST_NAME 24
GtkWidget *clist;
GtkWidget *address_text[22];
GtkWidget *text;
GtkWidget *vscrollbar;
static GtkWidget *private_checkbox;
GtkWidget *phone_list_menu[NUM_PHONE_ENTRIES];
GtkWidget *menu;
GtkWidget *menu_item[NUM_MENU_ITEM1][NUM_MENU_ITEM2];
/*We need an extra one for the ALL category */
GtkWidget *address_cat_menu_item1[NUM_ADDRESS_CAT_ITEMS+1];
GtkWidget *address_cat_menu_item2[NUM_ADDRESS_CAT_ITEMS];
static GtkWidget *category_menu1;
static GtkWidget *category_menu2;
static GtkWidget *scrolled_window;
GtkWidget *address_quickfind_entry;
static GtkWidget *notebook;
static GtkWidget *pane;
static GtkWidget *radio_button[NUM_PHONE_ENTRIES];
static struct AddressAppInfo address_app_info;
static struct sorted_cats sort_l[NUM_ADDRESS_CAT_ITEMS];
int address_category=CATEGORY_ALL;
int address_phone_label_selected[NUM_PHONE_ENTRIES];
static int clist_row_selected;
extern GtkTooltips *glob_tooltips;
static AddressList *glob_address_list=NULL;
static AddressList *export_address_list=NULL;
static GtkWidget *new_record_button;
static GtkWidget *apply_record_button;
static GtkWidget *add_record_button;
static int record_changed;
static int clist_hack;
static void connect_changed_signals(int con_or_dis);
static void address_update_clist(GtkWidget *clist, GtkWidget *tooltip_widget,
AddressList *addr_list, int category, int main);
int address_clist_redraw();
static int address_find();
static void get_address_attrib(unsigned char *attrib);
static void cb_clist_selection(GtkWidget *clist,
gint row,
gint column,
GdkEventButton *event,
gpointer data);
static void init()
{
int i, j;
record_changed=CLEAR_FLAG;
for (i=0; i<NUM_MENU_ITEM1; i++) {
for (j=0; j<NUM_MENU_ITEM2; j++) {
menu_item[i][j] = NULL;
}
}
for (i=0; i<NUM_ADDRESS_CAT_ITEMS; i++) {
address_cat_menu_item2[i] = NULL;
}
}
static void
set_new_button_to(int new_state)
{
jpilot_logf(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_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_SINGLE);
clist_hack=TRUE;
/* The line selected on the clist becomes unhighlighted, so we do this */
gtk_clist_select_row(GTK_CLIST(clist), clist_row_selected, 0);
gtk_widget_show(apply_record_button);
break;
case NEW_FLAG:
gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_SINGLE);
clist_hack=TRUE;
/* The line selected on the clist becomes unhighlighted, so we do this */
gtk_clist_select_row(GTK_CLIST(clist), clist_row_selected, 0);
gtk_widget_show(add_record_button);
break;
case CLEAR_FLAG:
gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_BROWSE);
clist_hack=FALSE;
gtk_widget_show(new_record_button);
break;
default:
return;
}
switch (record_changed) {
case MODIFY_FLAG:
gtk_widget_hide(apply_record_button);
break;
case NEW_FLAG:
gtk_widget_hide(add_record_button);
break;
case CLEAR_FLAG:
gtk_widget_hide(new_record_button);
break;
}
record_changed=new_state;
}
static void
cb_record_changed(GtkWidget *widget,
gpointer data)
{
jpilot_logf(LOG_DEBUG, "cb_record_changed\n");
if (record_changed==CLEAR_FLAG) {
connect_changed_signals(DISCONNECT_SIGNALS);
if (((GtkCList *)clist)->rows > 0) {
set_new_button_to(MODIFY_FLAG);
} else {
set_new_button_to(NEW_FLAG);
}
}
return;
}
static void connect_changed_signals(int con_or_dis)
{
int i, j;
static int connected=0;
/* CONNECT */
if ((con_or_dis==CONNECT_SIGNALS) && (!connected)) {
connected=1;
for (i=0; i<NUM_MENU_ITEM1; i++) {
for (j=0; j<NUM_MENU_ITEM2; j++) {
if (menu_item[i][j]) {
gtk_signal_connect(GTK_OBJECT(menu_item[i][j]), "toggled",
GTK_SIGNAL_FUNC(cb_record_changed), NULL);
}
}
}
for (i=0; i<NUM_PHONE_ENTRIES; i++) {
if (radio_button[i]) {
gtk_signal_connect(GTK_OBJECT(radio_button[i]), "toggled",
GTK_SIGNAL_FUNC(cb_record_changed), NULL);
}
}
for (i=0; i<NUM_ADDRESS_CAT_ITEMS; i++) {
if (address_cat_menu_item2[i]) {
gtk_signal_connect(GTK_OBJECT(address_cat_menu_item2[i]), "toggled",
GTK_SIGNAL_FUNC(cb_record_changed), NULL);
}
}
for (i=0; i<NUM_ADDRESS_ENTRIES; i++) {
gtk_signal_connect(GTK_OBJECT(address_text[i]), "changed",
GTK_SIGNAL_FUNC(cb_record_changed), NULL);
}
gtk_signal_connect(GTK_OBJECT(private_checkbox), "toggled",
GTK_SIGNAL_FUNC(cb_record_changed), NULL);
}
/* DISCONNECT */
if ((con_or_dis==DISCONNECT_SIGNALS) && (connected)) {
connected=0;
for (i=0; i<NUM_MENU_ITEM1; i++) {
for (j=0; j<NUM_MENU_ITEM2; j++) {
if (menu_item[i][j]) {
gtk_signal_disconnect_by_func(GTK_OBJECT(menu_item[i][j]),
GTK_SIGNAL_FUNC(cb_record_changed), NULL);
}
}
}
for (i=0; i<NUM_PHONE_ENTRIES; i++) {
if (radio_button[i]) {
gtk_signal_disconnect_by_func(GTK_OBJECT(radio_button[i]),
GTK_SIGNAL_FUNC(cb_record_changed), NULL);
}
}
for (i=0; i<NUM_ADDRESS_CAT_ITEMS; i++) {
if (address_cat_menu_item2[i]) {
gtk_signal_disconnect_by_func(GTK_OBJECT(address_cat_menu_item2[i]),
GTK_SIGNAL_FUNC(cb_record_changed), NULL);
}
}
for (i=0; i<NUM_ADDRESS_ENTRIES; i++) {
gtk_signal_disconnect_by_func(GTK_OBJECT(address_text[i]),
GTK_SIGNAL_FUNC(cb_record_changed), NULL);
}
gtk_signal_disconnect_by_func(GTK_OBJECT(private_checkbox),
GTK_SIGNAL_FUNC(cb_record_changed), NULL);
}
}
int address_print()
{
long this_many;
MyAddress *ma;
AddressList *address_list;
AddressList address_list1;
get_pref(PREF_PRINT_THIS_MANY, &this_many, NULL);
address_list=NULL;
if (this_many==1) {
ma = gtk_clist_get_row_data(GTK_CLIST(clist), clist_row_selected);
if (ma < (MyAddress *)CLIST_MIN_DATA) {
return -1;
}
memcpy(&(address_list1.ma), ma, sizeof(MyAddress));
address_list1.next=NULL;
address_list = &address_list1;
}
if (this_many==2) {
get_addresses2(&address_list, SORT_ASCENDING, 2, 2, 2, address_category);
}
if (this_many==3) {
get_addresses2(&address_list, SORT_ASCENDING, 2, 2, 2, CATEGORY_ALL);
}
print_addresses(address_list);
if ((this_many==2) || (this_many==3)) {
free_AddressList(&address_list);
}
return 0;
}
int address_to_text(struct Address *addr, char *text, int len)
{
int order[NUM_ADDRESS_LABELS]={
0,1,13,2,3,4,5,6,7,8,9,10,11,12,14,15,16,17,18,19,20,21
};
char *field_names[]={"Last", "First", "Title", "Company", "Phone1",
"Phone2", "Phone3", "Phone4", "Phone5", "Address", "City", "State",
"ZipCode", "Country", "Custom1", "Custom2", "Custom3", "Custom4",
"Note", "phoneLabel1", "phoneLabel2", "phoneLabel3", "phoneLabel4",
"phoneLabel5", "showPhone", NULL};
g_snprintf(text, len,
"%s: %s\n%s: %s\n%s: %s\n%s: %s\n%s: %s\n"
"%s: %s\n%s: %s\n%s: %s\n%s: %s\n%s: %s\n"
"%s: %s\n%s: %s\n%s: %s\n%s: %s\n%s: %s\n"
"%s: %s\n%s: %s\n%s: %s\n%s: %s\n"
"%s: %d\n%s: %d\n%s: %d\n%s: %d\n%s: %d\n"
"%s: %d\n",
field_names[0], addr->entry[order[0]],
field_names[1], addr->entry[order[1]],
field_names[2], addr->entry[order[2]],
field_names[3], addr->entry[order[3]],
field_names[4], addr->entry[order[4]],
field_names[5], addr->entry[order[5]],
field_names[6], addr->entry[order[6]],
field_names[7], addr->entry[order[7]],
field_names[8], addr->entry[order[8]],
field_names[9], addr->entry[order[9]],
field_names[10], addr->entry[order[10]],
field_names[11], addr->entry[order[11]],
field_names[12], addr->entry[order[12]],
field_names[13], addr->entry[order[13]],
field_names[14], addr->entry[order[14]],
field_names[15], addr->entry[order[15]],
field_names[16], addr->entry[order[16]],
field_names[17], addr->entry[order[17]],
field_names[18], addr->entry[order[18]],
field_names[19], addr->phoneLabel[0],
field_names[20], addr->phoneLabel[1],
field_names[21], addr->phoneLabel[2],
field_names[22], addr->phoneLabel[3],
field_names[23], addr->phoneLabel[4],
field_names[24], addr->showPhone
);
text[len-1]='\0';
return 0;
}
/*
* Start Import Code
*/
int address_import_callback(GtkWidget *parent_window, char *file_path, int type)
{
FILE *in;
char text[65536];
struct Address new_addr;
unsigned char attrib;
unsigned int unique_id;
int i, ret, index;
int import_all;
AddressList *addrlist;
AddressList *temp_addrlist;
struct CategoryAppInfo cai;
char old_cat_name[32];
int suggested_cat_num;
int new_cat_num;
int priv;
int order[NUM_ADDRESS_LABELS]={
0,1,13,2,3,4,5,6,7,8,9,10,11,12,14,15,16,17,18,19,20,21
};
get_address_attrib(&attrib);
in=fopen(file_path, "r");
if (!in) {
jpilot_logf(LOG_WARN, _("Could not open file %s\n"), file_path);
return -1;
}
/* CSV */
if (type==IMPORT_TYPE_CSV) {
jpilot_logf(LOG_DEBUG, "Address import CSV [%s]\n", file_path);
/* The first line is format, so we don't need it */
fgets(text, 1000, in);
import_all=FALSE;
while (1) {
/* 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
strncpy(old_cat_name, text, 16);
old_cat_name[16]='\0';
attrib=0;
/* Figure out what the best category number is */
index=temp_addrlist->ma.unique_id-1;
suggested_cat_num=0;
for (i=0; i<NUM_ADDRESS_CAT_ITEMS; i++) {
if (address_app_info.category.name[i][0]=='\0') continue;
if (!strcmp(address_app_info.category.name[i], old_cat_name)) {
suggested_cat_num=i;
i=1000;
break;
}
}
/* Read the private field */
ret = read_csv_field(in, text, 65535);
#ifdef JPILOT_DEBUG
printf("private is [%s]\n", text);
#endif
sscanf(text, "%d", &priv);
for (i=0; i<19; i++) {
new_addr.entry[order[i]]=NULL;
ret = read_csv_field(in, text, 65535);
text[65535]='\0';
new_addr.entry[order[i]]=strdup(text);
}
for (i=0; i<5; i++) {
ret = read_csv_field(in, text, 65535);
text[65535]='\0';
sscanf(text, "%d", &(new_addr.phoneLabel[i]));
}
ret = read_csv_field(in, text, 65535);
text[65535]='\0';
sscanf(text, "%d", &(new_addr.showPhone));
address_to_text(&new_addr, text, 65535);
if (!import_all) {
ret=import_record_ask(parent_window, pane,
text,
&(address_app_info.category),
old_cat_name,
priv,
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) |
(priv ? dlpRecAttrSecret : 0);
if ((ret==DIALOG_SAID_IMPORT_YES) || (import_all)) {
pc_address_write(&new_addr, NEW_PC_REC, attrib, &unique_id);
}
}
}
/* Palm Desktop DAT format */
if (type==IMPORT_TYPE_DAT) {
jpilot_logf(LOG_DEBUG, "Address import DAT [%s]\n", file_path);
if (dat_check_if_dat_file(in)!=DAT_ADDRESS_FILE) {
jpilot_logf(LOG_WARN, _("File doesn't appear to be address.dat format\n"));
fclose(in);
return 1;
}
addrlist=NULL;
dat_get_addresses(in, &addrlist, &cai);
import_all=FALSE;
for (temp_addrlist=addrlist; temp_addrlist; temp_addrlist=temp_addrlist->next) {
index=temp_addrlist->ma.unique_id-1;
if (index<0) {
strncpy(old_cat_name, _("Unfiled"), 16);
old_cat_name[16]='\0';
index=0;
} else {
strncpy(old_cat_name, cai.name[index], 16);
old_cat_name[16]='\0';
}
attrib=0;
/* Figure out what category it was in the dat file */
index=temp_addrlist->ma.unique_id-1;
suggested_cat_num=0;
if (index>-1) {
for (i=0; i<NUM_ADDRESS_CAT_ITEMS; i++) {
if (address_app_info.category.name[i][0]=='\0') continue;
if (!strcmp(address_app_info.category.name[i], old_cat_name)) {
suggested_cat_num=i;
i=1000;
break;
}
}
}
ret=0;
if (!import_all) {
address_to_text(&(temp_addrlist->ma.a), text, 65535);
ret=import_record_ask(parent_window, pane,
text,
&(address_app_info.category),
old_cat_name,
(temp_addrlist->ma.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_addrlist->ma.attrib & 0x10) ? dlpRecAttrSecret : 0);
if ((ret==DIALOG_SAID_IMPORT_YES) || (import_all)) {
pc_address_write(&(temp_addrlist->ma.a), NEW_PC_REC, attrib, &unique_id);
}
}
free_AddressList(&addrlist);
}
address_refresh();
fclose(in);
return 0;
}
int address_import(GtkWidget *window)
{
char *type_desc[] = {
"CSV (Comma Separated Values)",
"DAT/ABA (Palm Archive Formats)",
NULL
};
int type_int[] = {
IMPORT_TYPE_CSV,
IMPORT_TYPE_DAT,
0
};
import_gui(window, pane, type_desc, type_int, address_import_callback);
return 0;
}
/*
* End Import Code
*/
/*
* Start Export code
*/
void cb_addr_export_ok(GtkWidget *export_window, GtkWidget *clist,
int type, const char *filename)
{
MyAddress *ma;
GList *list, *temp_list;
FILE *out;
struct stat statb;
const char *short_date;
time_t ltime;
struct tm *now;
char str1[256], str2[256];
char pref_time[40];
int i, r, n, len;
char *button_text[]={gettext_noop("OK")};
char *button_overwrite_text[]={gettext_noop("Yes"), gettext_noop("No")};
char text[1024];
char csv_text[65550];
int order[NUM_ADDRESS_LABELS]={
0,1,13,2,3,4,5,6,7,8,9,10,11,12,14,15,16,17,18,19,20,21
};
char *field_names[]={"Last", "First", "Title", "Company", "Phone1",
"Phone2", "Phone3", "Phone4", "Phone5", "Address", "City", "State",
"ZipCode", "Country", "Custom1", "Custom2", "Custom3", "Custom4",
"Note", "phoneLabel1", "phoneLabel2", "phoneLabel3", "phoneLabel4",
"phoneLabel5", "showPhone", NULL};
list=GTK_CLIST(clist)->selection;
if (!stat(filename, &statb)) {
if (S_ISDIR(statb.st_mode)) {
g_snprintf(text, 1024, _("%s is a directory"), filename);
dialog_generic(GTK_WIDGET(export_window)->window,
0, 0, _("Error Opening File"),
"Directory", text, 1, button_text);
return;
}
g_snprintf(text, 1024, _("Do you want to overwrite file %s?"), filename);
r = dialog_generic(GTK_WIDGET(export_window)->window,
0, 0, _("Overwrite File?"),
_("Overwrite File"), text, 2, button_overwrite_text);
if (r!=DIALOG_SAID_1) {
return;
}
}
out = fopen(filename, "w");
if (!out) {
g_snprintf(text, 1024, "Error Opening File: %s", filename);
dialog_generic(GTK_WIDGET(export_window)->window,
0, 0, _("Error Opening File"),
"Filename", text, 1, button_text);
return;
}
for (i=0, temp_list=list; temp_list; temp_list = temp_list->next, i++) {
ma = gtk_clist_get_row_data(GTK_CLIST(clist), (int) temp_list->data);
if (!ma) {
continue;
jpilot_logf(LOG_WARN, "Can't export address %d\n", (long) temp_list->data + 1);
}
switch (type) {
case EXPORT_TYPE_TEXT:
get_pref(PREF_SHORTDATE, NULL, &short_date);
get_pref_time_no_secs(pref_time);
time(<ime);
now = localtime(<ime);
strftime(str1, 50, short_date, now);
strftime(str2, 50, pref_time, now);
g_snprintf(text, 100, "%s %s", str1, str2);
text[100]='\0';
/* Todo Should I translate these? */
fprintf(out, "Address: exported from %s on %s\n", PN, text);
fprintf(out, "Category: %s\n", address_app_info.category.name[ma->attrib & 0x0F]);
fprintf(out, "Private: %s\n",
(ma->attrib & dlpRecAttrSecret) ? "Yes":"No");
for (n=0; (field_names[n]) && (n<19); n++) {
fprintf(out, "%s: ", field_names[n]);
fprintf(out, "%s\n", ma->a.entry[order[n]] ?
ma->a.entry[order[n]] : "");
}
for (n=19; (field_names[n]) && (n<24); n++) {
fprintf(out, "%s: ", field_names[n]);
fprintf(out, "%d\n", ma->a.phoneLabel[n-19]);
}
fprintf(out, "Show Phone: %d\n\n", ma->a.showPhone);
break;
case EXPORT_TYPE_CSV:
if (i==0) {
fprintf(out, "CSV address: Category, Private, ");
for (n=0; (field_names[n]) && (n<30); n++) {
fprintf(out, "%s", field_names[n]);
if (field_names[n+1]) {
fprintf(out, ", ");
}
}
fprintf(out, "\n");
}
len=0;
str_to_csv_str(csv_text,
address_app_info.category.name[ma->attrib & 0x0F]);
fprintf(out, "\"%s\", ", csv_text);
fprintf(out, "\"%s\", ", (ma->attrib & dlpRecAttrSecret) ? "1":"0");
for (n=0; n<19; n++) {
csv_text[0]='\0';
if (ma->a.entry[order[n]]) {
if (strlen(ma->a.entry[order[n]])>65535) {
jpilot_logf(LOG_WARN, "Field > 65535\n");
} else {
str_to_csv_str(csv_text, ma->a.entry[order[n]]);
}
}
fprintf(out, "\"%s\", ", csv_text);
}
for (n=0; n<5; n++) {
fprintf(out, "\"%d\", ", ma->a.phoneLabel[n]);
}
fprintf(out, "\"%d\"", ma->a.showPhone);
fprintf(out, "\n");
break;
default:
jpilot_logf(LOG_WARN, "Unknown export type\n");
}
}
if (out) {
fclose(out);
}
}
static void cb_addr_update_clist(GtkWidget *clist, int category)
{
address_update_clist(clist, NULL, export_address_list, category, FALSE);
}
static void cb_addr_export_done(GtkWidget *widget, const char *filename)
{
free_AddressList(&export_address_list);
set_pref(PREF_ADDRESS_EXPORT_FILENAME, 0, filename);
}
int address_export(GtkWidget *window)
{
int w, h, x, y;
gdk_window_get_size(window->window, &w, &h);
gdk_window_get_root_origin(window->window, &x, &y);
w = GTK_PANED(pane)->handle_xpos;
x+=40;
export_gui(w, h, x, y, 3, sort_l,
PREF_ADDRESS_EXPORT_FILENAME,
cb_addr_update_clist,
cb_addr_export_done,
cb_addr_export_ok
);
return 0;
}
/*
* End Export Code
*/
static int find_sorted_cat(int cat)
{
int i;
for (i=0; i< NUM_ADDRESS_CAT_ITEMS; i++) {
if (sort_l[i].cat_num==cat) {
return i;
}
}
return 0;
}
void cb_delete_address(GtkWidget *widget,
gpointer data)
{
MyAddress *ma;
int flag;
int show_priv;
ma = gtk_clist_get_row_data(GTK_CLIST(clist), clist_row_selected);
if (ma < (MyAddress *)CLIST_MIN_DATA) {
return;
}
/* Do masking like Palm OS 3.5 */
show_priv = show_privates(GET_PRIVATES, NULL);
if ((show_priv != SHOW_PRIVATES) &&
(ma->attrib & dlpRecAttrSecret)) {
return;
}
/* End Masking */
flag = GPOINTER_TO_INT(data);
if ((flag==MODIFY_FLAG) || (flag==DELETE_FLAG)) {
delete_pc_record(ADDRESS, ma, 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--;
}
}
}
address_clist_redraw();
}
void cb_resort(GtkWidget *widget,
gpointer data)
{
int by_company;
by_company=GPOINTER_TO_INT(data);
if (sort_override) {
sort_override=0;
} else {
sort_override=1;
by_company=!(by_company & 1);
}
if (by_company) {
gtk_clist_set_column_title(GTK_CLIST(clist), ADDRESS_NAME_COLUMN, _("Company/Name"));
} else {
gtk_clist_set_column_title(GTK_CLIST(clist), ADDRESS_NAME_COLUMN, _("Name/Company"));
}
address_clist_redraw();
}
void cb_phone_menu(GtkWidget *item, unsigned int value)
{
if (!item)
return;
if ((GTK_CHECK_MENU_ITEM(item))->active) {
jpilot_logf(LOG_DEBUG, "phone_menu = %d\n", (value & 0xF0) >> 4);
jpilot_logf(LOG_DEBUG, "selection = %d\n", value & 0x0F);
address_phone_label_selected[(value & 0xF0) >> 4] = value & 0x0F;
}
}
void cb_notebook_changed(GtkWidget *widget,
GtkWidget *widget2,
int page,
gpointer data)
{
int prev_page;
/* GTK calls this function while it is destroying the notebook
* I use this function to tell if it is being destroyed */
prev_page = gtk_notebook_get_current_page(GTK_NOTEBOOK(widget));
if (prev_page<0) {
return;
}
jpilot_logf(LOG_DEBUG, "cb_notebook_changed(), prev_page=%d, page=%d\n", prev_page, page);
set_pref(PREF_ADDRESS_NOTEBOOK_PAGE, page, NULL);
}
static void get_address_attrib(unsigned char *attrib)
{
int i;
/*Get the category that is set from the menu */
*attrib = 0;
for (i=0; i<NUM_ADDRESS_CAT_ITEMS; i++) {
if (GTK_IS_WIDGET(address_cat_menu_item2[i])) {
if (GTK_CHECK_MENU_ITEM(address_cat_menu_item2[i])->active) {
*attrib = sort_l[i].cat_num;
break;
}
}
}
/* Get private flag */
if (GTK_TOGGLE_BUTTON(private_checkbox)->active) {
*attrib |= dlpRecAttrSecret;
}
}
static void cb_add_new_record(GtkWidget *widget,
gpointer data)
{
int i;
struct Address a;
MyAddress *ma;
unsigned char attrib;
unsigned int unique_id;
int show_priv;
bzero(&a, sizeof(a));
/* Do masking like Palm OS 3.5 */
if ((GPOINTER_TO_INT(data)==COPY_FLAG) ||
(GPOINTER_TO_INT(data)==MODIFY_FLAG)) {
show_priv = show_privates(GET_PRIVATES, NULL);
ma = gtk_clist_get_row_data(GTK_CLIST(clist), clist_row_selected);
if (ma < (MyAddress *)CLIST_MIN_DATA) {
return;
}
if ((show_priv != SHOW_PRIVATES) &&
(ma->attrib & dlpRecAttrSecret)) {
return;
}
}
/* End Masking */
if ((GPOINTER_TO_INT(data)==NEW_FLAG) ||
(GPOINTER_TO_INT(data)==COPY_FLAG) ||
(GPOINTER_TO_INT(data)==MODIFY_FLAG)) {
/*These rec_types are both the same for now */
if (GPOINTER_TO_INT(data)==MODIFY_FLAG) {
ma = gtk_clist_get_row_data(GTK_CLIST(clist), clist_row_selected);
if (ma < (MyAddress *)CLIST_MIN_DATA) {
return;
}
if ((ma->rt==DELETED_PALM_REC) || (ma->rt==MODIFIED_PALM_REC)) {
jpilot_logf(LOG_INFO, "You can't modify a record that is deleted\n");
return;
}
}
a.showPhone=0;
for (i=0; i<NUM_PHONE_ENTRIES; i++) {
if (GTK_TOGGLE_BUTTON(radio_button[i])->active) {
a.showPhone=i;
}
}
for (i=0; i<NUM_ADDRESS_ENTRIES; i++) {
a.entry[i] =
gtk_editable_get_chars(GTK_EDITABLE(address_text[i]), 0, -1);
}
for (i=0; i<NUM_PHONE_ENTRIES; i++) {
a.phoneLabel[i]=address_phone_label_selected[i];
}
/*Get the attributes */
get_address_attrib(&attrib);
set_new_button_to(CLEAR_FLAG);
pc_address_write(&a, NEW_PC_REC, attrib, &unique_id);
free_Address(&a);
if (GPOINTER_TO_INT(data) == MODIFY_FLAG) {
cb_delete_address(NULL, data);
} else {
address_clist_redraw();
}
glob_find_id = unique_id;
address_find();
}
}
void clear_details()
{
int i;
int new_cat;
int sorted_position;
/* Need to disconnect these signals first */
set_new_button_to(NEW_FLAG);
connect_changed_signals(DISCONNECT_SIGNALS);
/* Clear the quickview */
gtk_text_set_point(GTK_TEXT(text), 0);
gtk_text_forward_delete(GTK_TEXT(text),
gtk_text_get_length(GTK_TEXT(text)));
/*Clear all the address entry texts */
for (i=0; i<NUM_ADDRESS_ENTRIES; i++) {
gtk_text_set_point(GTK_TEXT(address_text[i]), 0);
gtk_text_forward_delete(GTK_TEXT(address_text[i]),
gtk_text_get_length(GTK_TEXT(address_text[i])));
}
for (i=0; i<NUM_PHONE_ENTRIES; i++) {
if (GTK_IS_WIDGET(menu_item[i][i])) {
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM
(menu_item[i][i]), TRUE);
gtk_option_menu_set_history(GTK_OPTION_MENU(phone_list_menu[i]), i);
}
}
if (address_category==CATEGORY_ALL) {
new_cat = 0;
} else {
new_cat = address_category;
}
sorted_position = find_sorted_cat(new_cat);
if (sorted_position<0) {
jpilot_logf(LOG_WARN, "Category is not legal\n");
} else {
gtk_check_menu_item_set_active
(GTK_CHECK_MENU_ITEM(address_cat_menu_item2[sorted_position]), TRUE);
gtk_option_menu_set_history(GTK_OPTION_MENU(category_menu2), sorted_position);
}
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(private_checkbox), FALSE);
connect_changed_signals(CONNECT_SIGNALS);
}
void cb_address_clear(GtkWidget *widget,
gpointer data)
{
clear_details();
gtk_notebook_set_page(GTK_NOTEBOOK(notebook), 0);
gtk_widget_grab_focus(GTK_WIDGET(address_text[0]));
}
void cb_address_quickfind(GtkWidget *widget,
gpointer data)
{
char *entry_text;
int i, r, found, found_at, line_count;
char *clist_text;
found_at = 0;
entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
if (!strlen(entry_text)) {
return;
}
/*100000 is just to prevent ininite looping during a solar flare */
for (found = i = 0; i<100000; i++) {
r = gtk_clist_get_text(GTK_CLIST(clist), i, ADDRESS_NAME_COLUMN, &clist_text);
if (!r) {
break;
}
if (found) {
continue;
}
if (!strncasecmp(clist_text, entry_text, strlen(entry_text))) {
found = 1;
found_at = i;
gtk_clist_select_row(GTK_CLIST(clist), i, ADDRESS_NAME_COLUMN);
cb_clist_selection(clist, i, ADDRESS_NAME_COLUMN, (GdkEventButton *)455, NULL);
}
}
line_count = i;
if (found) {
move_scrolled_window(scrolled_window,
((float)found_at)/((float)line_count));
}
}
static void cb_category(GtkWidget *item, int selection)
{
int b;
if (!item) return;
b=dialog_save_changed_record(pane, record_changed);
if (b==DIALOG_SAID_1) {
cb_add_new_record(NULL, GINT_TO_POINTER(record_changed));
}
if ((GTK_CHECK_MENU_ITEM(item))->active) {
address_category = selection;
jpilot_logf(LOG_DEBUG, "address_category = %d\n",address_category);
address_update_clist(clist, category_menu1, glob_address_list,
address_category, TRUE);
}
}
/* Do masking like Palm OS 3.5 */
static void clear_myaddress(MyAddress *ma)
{
int i;
ma->unique_id=0;
ma->attrib=ma->attrib & 0xF8;
for (i=0; i<5; i++) {
ma->a.phoneLabel[i]=0;
}
ma->a.showPhone=0;
for (i=0; i<19; i++) {
if (ma->a.entry) {
free(ma->a.entry[i]);
ma->a.entry[i]=NULL;
}
}
return;
}
/* End Masking */
static void cb_clist_selection(GtkWidget *clist,
gint row,
gint column,
GdkEventButton *event,
gpointer data)
{
/* The rename-able phone entries are indexes 3,4,5,6,7 */
struct Address *a;
MyAddress *ma;
int cat, count, sorted_position;
int i, i2;
int keep, b;
/* This is because the palm doesn't show the address entries in order */
int order[NUM_ADDRESS_LABELS]={
0,1,13,2,3,4,5,6,7,8,9,10,11,12,14,15,16,17,18,19,20,21
};
char *clist_text, *entry_text;
if ((!event) && (clist_hack)) return;
/* HACK */
if (clist_hack) {
keep=record_changed;
gtk_clist_select_row(GTK_CLIST(clist), clist_row_selected, column);
b=dialog_save_changed_record(pane, record_changed);
if (b==DIALOG_SAID_1) {
cb_add_new_record(NULL, GINT_TO_POINTER(record_changed));
}
set_new_button_to(CLEAR_FLAG);
/* This doesn't cause an event to occur, it does highlight
* the line, so we do the next call also */
gtk_clist_select_row(GTK_CLIST(clist), row, column);
cb_clist_selection(clist, row, column, GINT_TO_POINTER(1), NULL);
return;
}
clist_row_selected=row;
ma = gtk_clist_get_row_data(GTK_CLIST(clist), row);
if (ma==NULL) {
return;
}
set_new_button_to(CLEAR_FLAG);
connect_changed_signals(DISCONNECT_SIGNALS);
a=&(ma->a);
clist_text = NULL;
gtk_clist_get_text(GTK_CLIST(clist), row, ADDRESS_NAME_COLUMN, &clist_text);
entry_text = gtk_entry_get_text(GTK_ENTRY(address_quickfind_entry));
if (strncasecmp(clist_text, entry_text, strlen(entry_text))) {
gtk_entry_set_text(GTK_ENTRY(address_quickfind_entry), "");
}
gtk_text_freeze(GTK_TEXT(text));
gtk_text_set_point(GTK_TEXT(text), 0);
gtk_text_forward_delete(GTK_TEXT(text),
gtk_text_get_length(GTK_TEXT(text)));
gtk_text_insert(GTK_TEXT(text), NULL,NULL,NULL, _("Category: "), -1);
gtk_text_insert(GTK_TEXT(text), NULL,NULL,NULL,
address_app_info.category.name[ma->attrib & 0x0F], -1);
gtk_text_insert(GTK_TEXT(text), NULL,NULL,NULL, "\n", -1);
for (i=0; i<NUM_ADDRESS_ENTRIES; i++) {
i2=order[i];
if (a->entry[i2]) {
if (i2>2 && i2<8) {
gtk_text_insert(GTK_TEXT(text), NULL,NULL,NULL,
address_app_info.phoneLabels[a->phoneLabel[i2-3]],
-1);
} else {
gtk_text_insert(GTK_TEXT(text), NULL,NULL,NULL, address_app_info.labels[i2], -1);
}
gtk_text_insert(GTK_TEXT(text), NULL,NULL,NULL, ": ", -1);
gtk_text_insert(GTK_TEXT(text), NULL,NULL,NULL, a->entry[i2], -1);
gtk_text_insert(GTK_TEXT(text), NULL,NULL,NULL, "\n", -1);
}
}
gtk_text_thaw(GTK_TEXT(text));
cat = ma->attrib & 0x0F;
sorted_position = find_sorted_cat(cat);
if (address_cat_menu_item2[sorted_position]==NULL) {
/* Illegal category, Assume that category 0 is Unfiled and valid*/
jpilot_logf(LOG_DEBUG, "Category is not legal\n");
cat = sorted_position = 0;
sorted_position = find_sorted_cat(cat);
}
/* We need to count how many items down in the list this is */
for (i=sorted_position, count=0; i>=0; i--) {
if (address_cat_menu_item2[i]) {
count++;
}
}
count--;
if (sorted_position<0) {
jpilot_logf(LOG_WARN, "Category is not legal\n");
} else {
if (address_cat_menu_item2[sorted_position]) {
gtk_check_menu_item_set_active
(GTK_CHECK_MENU_ITEM(address_cat_menu_item2[sorted_position]), TRUE);
}
gtk_option_menu_set_history(GTK_OPTION_MENU(category_menu2), count);
}
for (i=0; i<NUM_ADDRESS_ENTRIES; i++) {
gtk_text_set_point(GTK_TEXT(address_text[i]), 0);
gtk_text_forward_delete(GTK_TEXT(address_text[i]),
gtk_text_get_length(GTK_TEXT(address_text[i])));
if (a->entry[i]) {
gtk_text_insert(GTK_TEXT(address_text[i]), NULL,NULL,NULL, a->entry[i], -1);
}
}
for (i=0; i<NUM_PHONE_ENTRIES; i++) {
if (GTK_IS_WIDGET(menu_item[i][a->phoneLabel[i]])) {
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM
(menu_item[i][a->phoneLabel[i]]), TRUE);
gtk_option_menu_set_history(GTK_OPTION_MENU(phone_list_menu[i]),
a->phoneLabel[i]);
}
}
if ((a->showPhone > -1) && (a->showPhone < NUM_PHONE_ENTRIES)) {
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_button[a->showPhone]),
TRUE);
}
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(private_checkbox),
ma->attrib & dlpRecAttrSecret);
connect_changed_signals(CONNECT_SIGNALS);
}
static void address_update_clist(GtkWidget *clist, GtkWidget *tooltip_widget,
AddressList *addr_list, int category, int main)
{
int num_entries, entries_shown, i;
int row_count;
int show1, show2, show3;
gchar *empty_line[] = { "","","" };
GdkPixmap *pixmap_note;
GdkBitmap *mask_note;
GdkColor color;
GdkColormap *colormap;
AddressList *temp_al;
char str[ADDRESS_MAX_CLIST_NAME+8];
int by_company;
int show_priv;
row_count=((GtkCList *)clist)->rows;
free_AddressList(&addr_list);
#ifdef JPILOT_DEBUG
for (i=0;i<NUM_ADDRESS_CAT_ITEMS;i++) {
jpilot_logf(LOG_DEBUG, "renamed:[%02d]:\n",address_app_info.category.renamed[i]);
jpilot_logf(LOG_DEBUG, "category name:[%02d]:",i);
print_string(address_app_info.category.name[i],16);
jpilot_logf(LOG_DEBUG, "category ID:%d\n", address_app_info.category.ID[i]);
}
for (i=0;i<NUM_ADDRESS_LABELS;i++) {
jpilot_logf(LOG_DEBUG, "labels[%02d]:",i);
print_string(address_app_info.labels[i],16);
}
for (i=0;i<8;i++) {
jpilot_logf(LOG_DEBUG, "phoneLabels[%d]:",i);
print_string(address_app_info.phoneLabels[i],16);
}
jpilot_logf(LOG_DEBUG, "country %d\n",address_app_info.country);
jpilot_logf(LOG_DEBUG, "sortByCompany %d\n",address_app_info.sortByCompany);
#endif
num_entries = get_addresses2(&addr_list, SORT_ASCENDING, 2, 2, 1, CATEGORY_ALL);
if (addr_list==NULL) {
if (tooltip_widget) {
gtk_tooltips_set_tip(glob_tooltips, category_menu1, _("0 records"), NULL);
}
return;
}
/*Clear the text box to make things look nice */
if (main) {
gtk_text_set_point(GTK_TEXT(text), 0);
gtk_text_forward_delete(GTK_TEXT(text),
gtk_text_get_length(GTK_TEXT(text)));
}
gtk_clist_freeze(GTK_CLIST(clist));
by_company = address_app_info.sortByCompany;
if (sort_override) {
by_company=!(by_company & 1);
}
if (by_company) {
show1=2; /*company */
show2=0; /*last name */
show3=1; /*first name */
} else {
show1=0; /*last name */
show2=1; /*first name */
show3=2; /*company */
}
entries_shown=0;
show_priv = show_privates(GET_PRIVATES, NULL);
for (temp_al = addr_list, i=0; temp_al; temp_al=temp_al->next) {
if ( ((temp_al->ma.attrib & 0x0F) != address_category) &&
address_category != CATEGORY_ALL) {
continue;
}
/* Do masking like Palm OS 3.5 */
if ((show_priv == MASK_PRIVATES) &&
(temp_al->ma.attrib & dlpRecAttrSecret)) {
if (entries_shown+1>row_count) {
gtk_clist_append(GTK_CLIST(clist), empty_line);
}
gtk_clist_set_text(GTK_CLIST(clist), entries_shown, ADDRESS_NAME_COLUMN, "---------------");
gtk_clist_set_text(GTK_CLIST(clist), entries_shown, ADDRESS_PHONE_COLUMN, "---------------");
clear_myaddress(&temp_al->ma);
gtk_clist_set_row_data(GTK_CLIST(clist), entries_shown, &(temp_al->ma));
gtk_clist_set_background(GTK_CLIST(clist), entries_shown, NULL);
entries_shown++;
continue;
}
/* End Masking */
if ((show_priv != SHOW_PRIVATES) &&
(temp_al->ma.attrib & dlpRecAttrSecret)) {
continue;
}
str[0]='\0';
if (temp_al->ma.a.entry[show1] || temp_al->ma.a.entry[show2]) {
if (temp_al->ma.a.entry[show1] && temp_al->ma.a.entry[show2]) {
g_snprintf(str, ADDRESS_MAX_CLIST_NAME, "%s, %s", temp_al->ma.a.entry[show1], temp_al->ma.a.entry[show2]);
}
if (temp_al->ma.a.entry[show1] && ! temp_al->ma.a.entry[show2]) {
strncpy(str, temp_al->ma.a.entry[show1], ADDRESS_MAX_CLIST_NAME);
}
if (! temp_al->ma.a.entry[show1] && temp_al->ma.a.entry[show2]) {
strncpy(str, temp_al->ma.a.entry[show2], ADDRESS_MAX_CLIST_NAME);
}
} else if (temp_al->ma.a.entry[show3]) {
strncpy(str, temp_al->ma.a.entry[show3], ADDRESS_MAX_CLIST_NAME);
} else {
strcpy(str, "-Unnamed-");
}
str[ADDRESS_MAX_CLIST_NAME]='\0';
if (entries_shown+1>row_count) {
gtk_clist_append(GTK_CLIST(clist), empty_line);
}
gtk_clist_set_text(GTK_CLIST(clist), entries_shown, ADDRESS_NAME_COLUMN, str);
gtk_clist_set_text(GTK_CLIST(clist), entries_shown, ADDRESS_PHONE_COLUMN, temp_al->ma.a.entry[temp_al->ma.a.showPhone+3]);
gtk_clist_set_row_data(GTK_CLIST(clist), entries_shown, &(temp_al->ma));
switch (temp_al->ma.rt) {
case NEW_PC_REC:
colormap = gtk_widget_get_colormap(clist);
color.red=CLIST_NEW_RED;
color.green=CLIST_NEW_GREEN;
color.blue=CLIST_NEW_BLUE;
gdk_color_alloc(colormap, &color);
gtk_clist_set_background(GTK_CLIST(clist), entries_shown, &color);
break;
case DELETED_PALM_REC:
colormap = gtk_widget_get_colormap(clist);
color.red=CLIST_DEL_RED;
color.green=CLIST_DEL_GREEN;
color.blue=CLIST_DEL_BLUE;
gdk_color_alloc(colormap, &color);
gtk_clist_set_background(GTK_CLIST(clist), entries_shown, &color);
break;
case MODIFIED_PALM_REC:
colormap = gtk_widget_get_colormap(clist);
color.red=CLIST_MOD_RED;
color.green=CLIST_MOD_GREEN;
color.blue=CLIST_MOD_BLUE;
gdk_color_alloc(colormap, &color);
gtk_clist_set_background(GTK_CLIST(clist), entries_shown, &color);
break;
default:
if (temp_al->ma.attrib & dlpRecAttrSecret) {
colormap = gtk_widget_get_colormap(clist);
color.red=CLIST_PRIVATE_RED;
color.green=CLIST_PRIVATE_GREEN;
color.blue=CLIST_PRIVATE_BLUE;
gdk_color_alloc(colormap, &color);
gtk_clist_set_background(GTK_CLIST(clist), entries_shown, &color);
} else {
gtk_clist_set_background(GTK_CLIST(clist), entries_shown, NULL);
}
}
if (temp_al->ma.a.entry[18]) {
/*Put a note pixmap up */
get_pixmaps(clist, PIXMAP_NOTE, &pixmap_note, &mask_note);
gtk_clist_set_pixmap(GTK_CLIST(clist), entries_shown, ADDRESS_NOTE_COLUMN, pixmap_note, mask_note);
} else {
gtk_clist_set_text(GTK_CLIST(clist), entries_shown, ADDRESS_NOTE_COLUMN, "");
}
entries_shown++;
}
/* If there is an item in the list, select the first one */
if ((main) && (entries_shown>0)) {
gtk_clist_select_row(GTK_CLIST(clist), 0, ADDRESS_PHONE_COLUMN);
cb_clist_selection(clist, 0, ADDRESS_PHONE_COLUMN, (GdkEventButton *)455, NULL);
}
for (i=row_count-1; i>=entries_shown; i--) {
gtk_clist_remove(GTK_CLIST(clist), i);
}
gtk_clist_thaw(GTK_CLIST(clist));
sprintf(str, _("%d of %d records"), entries_shown, num_entries);
if (tooltip_widget) {
gtk_tooltips_set_tip(glob_tooltips, category_menu1, str, NULL);
}
if (main) {
set_new_button_to(CLEAR_FLAG);
}
}
/*default set is which menu item is to be set on by default */
/*set is which set in the menu_item array to use */
static int make_phone_menu(int default_set, unsigned int callback_id, int set)
{
int i;
GSList *group;
phone_list_menu[set] = gtk_option_menu_new();
menu = gtk_menu_new();
group = NULL;
for (i=0; i<8; i++) {
if (address_app_info.phoneLabels[i][0]) {
menu_item[set][i] = gtk_radio_menu_item_new_with_label(
group, address_app_info.phoneLabels[i]);
gtk_signal_connect(GTK_OBJECT(menu_item[set][i]), "activate",
cb_phone_menu, GINT_TO_POINTER(callback_id + i));
group = gtk_radio_menu_item_group(GTK_RADIO_MENU_ITEM(menu_item[set][i]));
gtk_menu_append(GTK_MENU(menu), menu_item[set][i]);
gtk_widget_show(menu_item[set][i]);
}
}
/*Set this one to active */
if (GTK_IS_WIDGET(menu_item[set][default_set])) {
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
menu_item[set][default_set]), TRUE);
}
gtk_option_menu_set_menu(GTK_OPTION_MENU(phone_list_menu[set]), menu);
/*Make this one show up by default */
gtk_option_menu_set_history(GTK_OPTION_MENU(phone_list_menu[set]),
default_set);
gtk_widget_show(phone_list_menu[set]);
return 0;
}
/* returns 1 if found, 0 if not */
static int address_find()
{
int r, found_at, total_count;
r = 0;
if (glob_find_id) {
r = clist_find_id(clist,
glob_find_id,
&found_at,
&total_count);
if (r) {
/*avoid dividing by zero */
if (total_count == 0) {
total_count = 1;
}
gtk_clist_select_row(GTK_CLIST(clist), found_at, ADDRESS_PHONE_COLUMN);
cb_clist_selection(clist, found_at, ADDRESS_PHONE_COLUMN, (GdkEventButton *)455, NULL);
if (!gtk_clist_row_is_visible(GTK_CLIST(clist), found_at)) {
move_scrolled_window_hack(scrolled_window,
(float)found_at/(float)total_count);
}
}
glob_find_id = 0;
}
return r;
}
/* This redraws the clist and goes back to the same line number */
int address_clist_redraw()
{
int line_num;
line_num = clist_row_selected;
address_update_clist(clist, category_menu1, glob_address_list,
address_category, TRUE);
gtk_clist_select_row(GTK_CLIST(clist), line_num, ADDRESS_NAME_COLUMN);
cb_clist_selection(clist, line_num, ADDRESS_NAME_COLUMN, (GdkEventButton *)455, NULL);
return 0;
}
int address_refresh()
{
int index;
if (glob_find_id) {
address_category = CATEGORY_ALL;
}
if (address_category==CATEGORY_ALL) {
index=0;
} else {
index=find_sorted_cat(address_category)+1;
}
address_update_clist(clist, category_menu1, glob_address_list,
address_category, TRUE);
if (index<0) {
jpilot_logf(LOG_WARN, "Category not legal\n");
} else {
gtk_option_menu_set_history(GTK_OPTION_MENU(category_menu1), index);
gtk_check_menu_item_set_active
(GTK_CHECK_MENU_ITEM(address_cat_menu_item1[index]), TRUE);
}
address_find();
return 0;
}
static gboolean
cb_key_pressed_quickfind(GtkWidget *widget, GdkEventKey *event, gpointer data)
{
int row_count;
int select_row;
int add;
add=0;
if ((event->keyval == GDK_KP_Down) || (event->keyval == GDK_Down)) {
add=1;
}
if ((event->keyval == GDK_KP_Up) || (event->keyval == GDK_Up)) {
add=-1;
}
if (!add) return FALSE;
row_count=((GtkCList *)clist)->rows;
if (!row_count) return FALSE;
gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "key_press_event");
select_row=clist_row_selected+add;
if (select_row>row_count-1) {
select_row=0;
}
if (select_row<0) {
select_row=row_count-1;
}
gtk_clist_select_row(GTK_CLIST(clist), select_row, ADDRESS_NAME_COLUMN);
cb_clist_selection(clist, select_row, ADDRESS_PHONE_COLUMN, (GdkEventButton *)455, NULL);
if (!gtk_clist_row_is_visible(GTK_CLIST(clist), select_row)) {
move_scrolled_window_hack(scrolled_window,
(float)select_row/(float)row_count);
}
return TRUE;
}
static gboolean
cb_key_pressed(GtkWidget *widget, GdkEventKey *event,
gpointer next_widget)
{
/* This is needed because the text boxes aren't shown on the
* screen in the same order as the array. I show them in the
* same order that the palm does */
int order[NUM_ADDRESS_ENTRIES]={
0,1,13,2,3,4,5,6,7,8,9,10,11,12,14,15,16,17,18
};
int page[NUM_ADDRESS_ENTRIES]={
0,0,0,0,0,0,0,0,0,1,1,1,1,1,2,2,2,2,2
};
int i;
if ((event->keyval == GDK_Tab) ||
(event->keyval == GDK_ISO_Left_Tab)) {
/* See if they are at the end of the text */
if (gtk_text_get_point(GTK_TEXT(widget)) ==
gtk_text_get_length(GTK_TEXT(widget))) {
gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "key_press_event");
/* Find the next/prev widget */
for (i=0; i<NUM_ADDRESS_ENTRIES; i++) {
if (address_text[order[i]] == widget) {
break;
}
}
if (event->keyval == GDK_Tab) i++;
if (event->keyval == GDK_ISO_Left_Tab) i--;
if (i>=NUM_ADDRESS_ENTRIES) i=0;
if (i<0) i=NUM_ADDRESS_ENTRIES-1;
gtk_notebook_set_page(GTK_NOTEBOOK(notebook), page[i]);
gtk_widget_grab_focus(GTK_WIDGET(address_text[order[i]]));
return TRUE;
}
}
return FALSE;
}
int address_gui_cleanup()
{
int b;
free_AddressList(&glob_address_list);
b=dialog_save_changed_record(pane, record_changed);
if (b==DIALOG_SAID_1) {
cb_add_new_record(NULL, GINT_TO_POINTER(record_changed));
}
connect_changed_signals(DISCONNECT_SIGNALS);
set_pref(PREF_ADDRESS_PANE, GTK_PANED(pane)->handle_xpos, NULL);
return 0;
}
/*
* Main function
*/
int address_gui(GtkWidget *vbox, GtkWidget *hbox)
{
extern GtkWidget *glob_date_label;
extern int glob_date_timer_tag;
GtkWidget *pixmapwid;
GdkPixmap *pixmap;
GdkBitmap *mask;
GtkWidget *vbox1, *vbox2;
GtkWidget *hbox_temp;
GtkWidget *vbox_temp1, *vbox_temp2, *vbox_temp3, *hbox_temp4;
GtkWidget *separator;
GtkWidget *label;
GtkWidget *button;
GtkWidget *frame;
GtkWidget *table1, *table2, *table3;
GtkWidget *notebook_tab;
GSList *group;
long ivalue, notebook_page;
const char *svalue;
char *titles[]={"","",""};
int i, i1, i2;
int order[NUM_ADDRESS_ENTRIES+1]={
0,1,13,2,3,4,5,6,7,8,9,10,11,12,14,15,16,17,18,0
};
clist_row_selected=0;
init();
get_address_app_info(&address_app_info);
for (i=0; i<NUM_ADDRESS_CAT_ITEMS; i++) {
sort_l[i].Pcat=address_app_info.category.name[i];
sort_l[i].cat_num=i;
}
qsort(sort_l, NUM_ADDRESS_CAT_ITEMS, sizeof(struct sorted_cats), cat_compare);
#ifdef JPILOT_DEBUG
for (i=0; i<NUM_ADDRESS_CAT_ITEMS; i++) {
printf("cat %d [%s]\n", sort_l[i].cat_num, sort_l[i].Pcat);
}
#endif
if (address_app_info.category.name[address_category][0]=='\0') {
address_category=CATEGORY_ALL;
}
pane = gtk_hpaned_new();
get_pref(PREF_ADDRESS_PANE, &ivalue, &svalue);
gtk_paned_set_position(GTK_PANED(pane), ivalue + 2);
gtk_box_pack_start(GTK_BOX(hbox), pane, TRUE, TRUE, 5);
vbox1 = gtk_vbox_new(FALSE, 0);
vbox2 = gtk_vbox_new(FALSE, 0);
hbox_temp = gtk_hbox_new(FALSE, 0);
gtk_paned_pack1(GTK_PANED(pane), vbox1, 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(CLOCK_TICK, timeout_date, NULL);
/* Separator */
separator = gtk_hseparator_new();
gtk_box_pack_start(GTK_BOX(vbox1), separator, FALSE, FALSE, 5);
/* Put the category menu up */
make_category_menu(&category_menu1, address_cat_menu_item1,
sort_l, cb_category, TRUE);
gtk_box_pack_start(GTK_BOX(vbox1), category_menu1, FALSE, FALSE, 0);
/* Put the address list window up */
scrolled_window = gtk_scrolled_window_new(NULL, NULL);
/*gtk_widget_set_usize(GTK_WIDGET(scrolled_window), 150, 0); */
gtk_container_set_border_width(GTK_CONTAINER(scrolled_window), 0);
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);
clist = gtk_clist_new_with_titles(3, titles);
clist_hack=FALSE;
gtk_clist_column_title_passive(GTK_CLIST(clist), ADDRESS_PHONE_COLUMN);
gtk_clist_column_title_passive(GTK_CLIST(clist), ADDRESS_NOTE_COLUMN);
if (address_app_info.sortByCompany) {
gtk_clist_set_column_title(GTK_CLIST(clist), ADDRESS_NAME_COLUMN, _("Company/Name"));
} else {
gtk_clist_set_column_title(GTK_CLIST(clist), ADDRESS_NAME_COLUMN, _("Name/Company"));
}
gtk_signal_connect(GTK_OBJECT(GTK_CLIST(clist)->column[ADDRESS_NAME_COLUMN].button),
"clicked", GTK_SIGNAL_FUNC(cb_resort),
GINT_TO_POINTER(address_app_info.sortByCompany));
gtk_clist_set_column_title(GTK_CLIST(clist), ADDRESS_PHONE_COLUMN, _("Phone"));
/* 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, ADDRESS_NOTE_COLUMN, pixmapwid);
gtk_signal_connect(GTK_OBJECT(clist), "select_row",
GTK_SIGNAL_FUNC(cb_clist_selection),
text);
gtk_clist_set_shadow_type(GTK_CLIST(clist), SHADOW);
gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_BROWSE);
gtk_clist_set_column_auto_resize(GTK_CLIST(clist), ADDRESS_NAME_COLUMN, TRUE);
gtk_clist_set_column_auto_resize(GTK_CLIST(clist), ADDRESS_NOTE_COLUMN, TRUE);
gtk_clist_set_column_auto_resize(GTK_CLIST(clist), ADDRESS_PHONE_COLUMN, FALSE);
gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(clist));
/*gtk_clist_set_column_justification(GTK_CLIST(clist), 1, GTK_JUSTIFY_RIGHT); */
hbox_temp = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox1), hbox_temp, FALSE, FALSE, 0);
label = gtk_label_new(_("Quick Find"));
gtk_box_pack_start(GTK_BOX(hbox_temp), label, FALSE, FALSE, 0);
address_quickfind_entry = gtk_entry_new();
gtk_signal_connect(GTK_OBJECT(address_quickfind_entry), "key_press_event",
GTK_SIGNAL_FUNC(cb_key_pressed_quickfind), NULL);
gtk_signal_connect(GTK_OBJECT(address_quickfind_entry), "changed",
GTK_SIGNAL_FUNC(cb_address_quickfind),
NULL);
gtk_box_pack_start(GTK_BOX(hbox_temp), address_quickfind_entry, TRUE, TRUE, 0);
gtk_widget_grab_focus(GTK_WIDGET(address_quickfind_entry));
/* The new entry gui */
hbox_temp = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox2), hbox_temp, FALSE, FALSE, 0);
/* Delete Button */
button = gtk_button_new_with_label(_("Delete"));
gtk_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(cb_delete_address),
GINT_TO_POINTER(DELETE_FLAG));
gtk_box_pack_start(GTK_BOX(hbox_temp), button, TRUE, TRUE, 0);
/* Create "Copy" button */
button = gtk_button_new_with_label(_("Copy"));
gtk_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(cb_add_new_record),
GINT_TO_POINTER(COPY_FLAG));
gtk_box_pack_start(GTK_BOX(hbox_temp), button, TRUE, TRUE, 0);
/* Create "New" button */
new_record_button = gtk_button_new_with_label(_("New Record"));
gtk_signal_connect(GTK_OBJECT(new_record_button), "clicked",
GTK_SIGNAL_FUNC(cb_address_clear), NULL);
gtk_box_pack_start(GTK_BOX(hbox_temp), new_record_button, TRUE, TRUE, 0);
/* Create "Add Record" button */
add_record_button = gtk_button_new_with_label(_("Add Record"));
gtk_signal_connect(GTK_OBJECT(add_record_button), "clicked",
GTK_SIGNAL_FUNC(cb_add_new_record),
GINT_TO_POINTER(NEW_FLAG));
gtk_box_pack_start(GTK_BOX(hbox_temp), add_record_button, TRUE, TRUE, 0);
gtk_widget_set_name(GTK_WIDGET(GTK_LABEL(GTK_BIN(add_record_button)->child)),
"label_high");
/* Create "apply changes" button */
apply_record_button = gtk_button_new_with_label(_("Apply Changes"));
gtk_signal_connect(GTK_OBJECT(apply_record_button), "clicked",
GTK_SIGNAL_FUNC(cb_add_new_record),
GINT_TO_POINTER(MODIFY_FLAG));
gtk_box_pack_start(GTK_BOX(hbox_temp), apply_record_button, TRUE, TRUE, 0);
gtk_widget_set_name(GTK_WIDGET(GTK_LABEL(GTK_BIN(apply_record_button)->child)),
"label_high");
/*Separator */
separator = gtk_hseparator_new();
gtk_box_pack_start(GTK_BOX(vbox2), separator, FALSE, FALSE, 5);
/*Private check box */
hbox_temp = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox2), hbox_temp, FALSE, FALSE, 0);
private_checkbox = gtk_check_button_new_with_label(_("Private"));
gtk_box_pack_end(GTK_BOX(hbox_temp), private_checkbox, FALSE, FALSE, 0);
/*Add the new category menu */
make_category_menu(&category_menu2, address_cat_menu_item2,
sort_l, NULL, FALSE);
gtk_box_pack_start(GTK_BOX(hbox_temp), category_menu2, TRUE, TRUE, 0);
/*Add the notebook for new entries */
notebook = gtk_notebook_new();
gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
gtk_notebook_popup_enable(GTK_NOTEBOOK(notebook));
gtk_signal_connect(GTK_OBJECT(notebook), "switch-page",
GTK_SIGNAL_FUNC(cb_notebook_changed), NULL);
gtk_box_pack_start(GTK_BOX(vbox2), notebook, TRUE, TRUE, 0);
/*Page 1 */
notebook_tab = gtk_label_new(_("Name"));
vbox_temp1 = gtk_vbox_new(FALSE, 0);
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox_temp1, notebook_tab);
/* Notebook tabs have to be shown before the show_all */
gtk_widget_show(vbox_temp1);
gtk_widget_show(notebook_tab);
/*Page 2 */
notebook_tab = gtk_label_new(_("Address"));
vbox_temp2 = gtk_vbox_new(FALSE, 0);
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox_temp2, notebook_tab);
/* Notebook tabs have to be shown before the show_all */
gtk_widget_show(vbox_temp2);
gtk_widget_show(notebook_tab);
/*Page 3 */
notebook_tab = gtk_label_new(_("Other"));
vbox_temp3 = gtk_vbox_new(FALSE, 0);
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox_temp3, notebook_tab);
/* Notebook tabs have to be shown before the show_all */
gtk_widget_show(vbox_temp3);
gtk_widget_show(notebook_tab);
/*Page 3 */
notebook_tab = gtk_label_new(_("All"));
hbox_temp4 = gtk_vbox_new(FALSE, 0);
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), hbox_temp4, notebook_tab);
/* Notebook tabs have to be shown before the show_all */
gtk_widget_show(hbox_temp4);
gtk_widget_show(notebook_tab);
/*Put a table on every page */
table1 = gtk_table_new(9, 3, FALSE);
gtk_box_pack_start(GTK_BOX(vbox_temp1), table1, TRUE, TRUE, 0);
table2 = gtk_table_new(9, 2, FALSE);
gtk_box_pack_start(GTK_BOX(vbox_temp2), table2, TRUE, TRUE, 0);
table3 = gtk_table_new(9, 2, FALSE);
gtk_box_pack_start(GTK_BOX(vbox_temp3), table3, TRUE, TRUE, 0);
label = NULL;
for (i=0; i<NUM_ADDRESS_ENTRIES; i++) {
i2=order[i];
if (i2>2 && i2<8) {
make_phone_menu(i2-3, (i2-3)<<4, i2-3);
} else {
label = gtk_label_new(address_app_info.labels[i2]);
gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
}
address_text[i2] = gtk_text_new(NULL, NULL);
gtk_text_set_editable(GTK_TEXT(address_text[i2]), TRUE);
gtk_text_set_word_wrap(GTK_TEXT(address_text[i2]), TRUE);
gtk_widget_set_usize(GTK_WIDGET(address_text[i2]), 0, 25);
/*gtk_box_pack_start(GTK_BOX(hbox_temp), address_text[i2], TRUE, TRUE, 0); */
/*hbox_temp = gtk_hbox_new(FALSE, 0); */
if (i<9) {
if (i2>2 && i2<8) {
gtk_table_attach_defaults(GTK_TABLE(table1), GTK_WIDGET(phone_list_menu[i2-3]),
1, 2, i, i+1);
} else {
gtk_table_attach_defaults(GTK_TABLE(table1), GTK_WIDGET(label),
1, 2, i, i+1);
}
gtk_table_attach_defaults(GTK_TABLE(table1), GTK_WIDGET(address_text[i2]),
2, 3, i, i+1);
/*gtk_box_pack_start(GTK_BOX(vbox_temp1), hbox_temp, TRUE, TRUE, 0); */
}
if (i>8 && i<14) {
gtk_table_attach_defaults(GTK_TABLE(table2), GTK_WIDGET(label),
0, 1, i-9, i-8);
gtk_table_attach_defaults(GTK_TABLE(table2), GTK_WIDGET(address_text[i2]),
1, 2, i-9, i-8);
/*gtk_box_pack_start(GTK_BOX(vbox_temp2), hbox_temp, TRUE, TRUE, 0); */
}
if (i>13 && i<100) {
gtk_table_attach_defaults(GTK_TABLE(table3), GTK_WIDGET(label),
0, 1, i-14, i-13);
gtk_table_attach_defaults(GTK_TABLE(table3), GTK_WIDGET(address_text[i2]),
1, 2, i-14, i-13);
}
}
/* Capture the TAB key to change focus with it */
for (i=0; i<NUM_ADDRESS_ENTRIES; i++) {
i1=order[i];
i2=order[i+1];
if (i2<NUM_ADDRESS_ENTRIES) {
gtk_signal_connect(GTK_OBJECT(address_text[i1]), "key_press_event",
GTK_SIGNAL_FUNC(cb_key_pressed), address_text[i2]);
}
}
/* Put some radio buttons for selecting which number to display in view */
group = NULL;
for (i=0; i<NUM_PHONE_ENTRIES; i++) {
radio_button[i] = gtk_radio_button_new_with_label(group, _("Show\nIn List"));
group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio_button[i]));
gtk_widget_set_usize(GTK_WIDGET(radio_button[i]), 5, 0);
gtk_table_attach_defaults(GTK_TABLE(table1), GTK_WIDGET(radio_button[i]),
0, 1, i+4, i+5);
}
/*The Quickview page */
frame = gtk_frame_new(_("Quick View"));
gtk_frame_set_label_align(GTK_FRAME(frame), 0.5, 0.0);
gtk_box_pack_start(GTK_BOX(hbox_temp4), frame, TRUE, TRUE, 0);
/*The text box on the right side */
hbox_temp = gtk_hbox_new (FALSE, 0);
gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
gtk_container_add(GTK_CONTAINER(frame), hbox_temp);
text = gtk_text_new(NULL, NULL);
gtk_text_set_editable(GTK_TEXT(text), FALSE);
gtk_text_set_word_wrap(GTK_TEXT(text), TRUE);
vscrollbar = gtk_vscrollbar_new(GTK_TEXT(text)->vadj);
gtk_box_pack_start(GTK_BOX(hbox_temp), text, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(hbox_temp), vscrollbar, FALSE, FALSE, 0);
gtk_widget_show_all(vbox);
gtk_widget_show_all(hbox);
gtk_widget_hide(add_record_button);
gtk_widget_hide(apply_record_button);
get_pref(PREF_ADDRESS_NOTEBOOK_PAGE, ¬ebook_page, NULL);
if ((notebook_page<4) && (notebook_page>-1)) {
gtk_notebook_set_page(GTK_NOTEBOOK(notebook), notebook_page);
}
address_refresh();
return 0;
}
jpilot-0.99.2/alarms.c 0100644 0001750 0000144 00000106502 07421115314 013611 0 ustar mouse users /* alarms.c
* A module of J-Pilot http://jpilot.org
*
* Copyright (C) 2000-2001 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
*/
/*
* The PalmOS datebook will alarm on private records even when they are hidden
* and they show up on the screen. Right, or wrong, who knows.
* I will do the same.
*/
#include "config.h"
#include <gtk/gtk.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pi-datebook.h>
#include "utils.h"
#include "log.h"
#include "prefs.h"
#include "i18n.h"
#include "datebook.h"
/* This is how often to check for alarms in seconds */
/* Every call takes CPU time(not much), so you may want it to be greater */
#define ALARM_INTERVAL 1
#define PREV_ALARM_MASK 1
#define NEXT_ALARM_MASK 2
/* #define ALARMS_DEBUG */
/*
* Throughout the code, event_time is the time of the event
* alarm_time is the event_time - advance
* remind_time is the time a window is to be popped up (it may be postponed)
*/
typedef enum {
ALARM_NONE = 0,
ALARM_NEW,
ALARM_MISSED,
ALARM_POSTPONED
} AlarmType;
struct jp_alarms {
unsigned int unique_id;
AlarmType type;
time_t event_time;
time_t alarm_advance;
struct jp_alarms *next;
};
struct alarm_dialog_data {
unsigned int unique_id;
time_t remind_time;
GtkWidget *remind_entry;
GtkWidget *radio1;
GtkWidget *radio2;
int button_hit;
};
static struct jp_alarms *alarm_list=NULL;
static struct jp_alarms *Plast_alarm_list=NULL;
static struct jp_alarms *next_alarm=NULL;
static int glob_skip_all_alarms;
static int total_alarm_windows;
void alarms_add_to_list(unsigned int unique_id,
AlarmType type,
time_t alarm_time,
time_t alarm_advance);
int alarms_find_next(struct tm *date1, struct tm *date2, int soonest_only);
/*
* Alarm GUI
*/
/*
* Start of Dialog window code
*/
static void cb_dialog_button(GtkWidget *widget,
gpointer data)
{
struct alarm_dialog_data *Pdata;
GtkWidget *w;
int i;
for (w=widget, i=10; w && (i>0); w=w->parent, i--) {
if (GTK_IS_WINDOW(w)) {
Pdata = gtk_object_get_data(GTK_OBJECT(w), "alarm");
if (Pdata) {
Pdata->button_hit = GPOINTER_TO_INT(data);
}
gtk_widget_destroy(GTK_WIDGET(w));
}
}
}
static gboolean cb_destroy_dialog(GtkWidget *widget)
{
struct alarm_dialog_data *Pdata;
char *entry;
time_t ltime;
time_t advance;
time_t remind;
total_alarm_windows--;
#ifdef ALARMS_DEBUG
printf("total_alarm_windows=%d\n",total_alarm_windows);
#endif
Pdata = gtk_object_get_data(GTK_OBJECT(widget), "alarm");
if (!Pdata) {
return TRUE;
}
entry = gtk_entry_get_text(GTK_ENTRY(Pdata->remind_entry));
if (Pdata->button_hit==DIALOG_SAID_2) {
remind = atoi(entry);
jpilot_logf(LOG_DEBUG, "remind entry = [%s]\n", entry);
set_pref(PREF_REMIND_IN, 0, entry);
if (GTK_TOGGLE_BUTTON(Pdata->radio1)->active) {
set_pref(PREF_REMIND_UNITS, 0, NULL);
remind *= 60;
} else {
set_pref(PREF_REMIND_UNITS, 1, NULL);
remind *= 3600;
}
time(<ime);
localtime(<ime);
advance = -(ltime + remind - Pdata->remind_time);
alarms_add_to_list(Pdata->unique_id,
ALARM_POSTPONED,
Pdata->remind_time,
advance);
}
free(Pdata);
return TRUE;
}
int dialog_alarm(char *title, char *frame_text,
char *time_str, char *desc_str, char *note_str,
unsigned int unique_id,
time_t remind_time)
{
GSList *group;
GtkWidget *button, *label;
GtkWidget *hbox1, *vbox1;
GtkWidget *vbox_temp;
GtkWidget *frame;
GtkWidget *alarm_dialog;
GtkWidget *remind_entry;
GtkWidget *radio1;
GtkWidget *radio2;
struct alarm_dialog_data *Pdata;
long pref_units;
const char *pref_entry;
/* Prevent alarms from going crazy and using all resources */
if (total_alarm_windows>20) {
return -1;
}
total_alarm_windows++;
#ifdef ALARMS_DEBUG
printf("total_alarm_windows=%d\n",total_alarm_windows);
#endif
alarm_dialog = gtk_widget_new(GTK_TYPE_WINDOW,
"type", GTK_WINDOW_TOPLEVEL,
"title", title,
NULL);
gtk_signal_connect(GTK_OBJECT(alarm_dialog), "destroy",
GTK_SIGNAL_FUNC(cb_destroy_dialog), alarm_dialog);
frame = gtk_frame_new(frame_text);
gtk_frame_set_label_align(GTK_FRAME(frame), 0.5, 0.0);
vbox1 = gtk_vbox_new(FALSE, 2);
hbox1 = gtk_hbox_new(TRUE, 2);
gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
gtk_container_set_border_width(GTK_CONTAINER(vbox1), 5);
gtk_container_set_border_width(GTK_CONTAINER(hbox1), 5);
gtk_container_add(GTK_CONTAINER(alarm_dialog), frame);
gtk_container_add(GTK_CONTAINER(frame), vbox1);
/* Label */
label = gtk_label_new(time_str);
gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
gtk_box_pack_start(GTK_BOX(vbox1), label, FALSE, FALSE, 2);
/* Label */
label = gtk_label_new(desc_str);
gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
gtk_box_pack_start(GTK_BOX(vbox1), label, FALSE, FALSE, 2);
/* Label */
label = gtk_label_new(note_str);
gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
gtk_box_pack_start(GTK_BOX(vbox1), label, FALSE, FALSE, 2);
/* Buttons */
gtk_box_pack_start(GTK_BOX(vbox1), hbox1, TRUE, TRUE, 2);
button = gtk_button_new_with_label(_("OK"));
gtk_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(cb_dialog_button),
GINT_TO_POINTER(DIALOG_SAID_1));
gtk_box_pack_start(GTK_BOX(hbox1), button, TRUE, TRUE, 1);
button = gtk_button_new_with_label(_("Remind me"));
gtk_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(cb_dialog_button),
GINT_TO_POINTER(DIALOG_SAID_2));
gtk_box_pack_start(GTK_BOX(hbox1), button, TRUE, TRUE, 1);
remind_entry = gtk_entry_new_with_max_length(4);
gtk_box_pack_start(GTK_BOX(hbox1), remind_entry, TRUE, TRUE, 1);
group = NULL;
radio1 = gtk_radio_button_new_with_label(NULL, _("Minutes"));
group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio1));
radio2 = gtk_radio_button_new_with_label(group, _("Hours"));
group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio2));
gtk_widget_set_usize(GTK_WIDGET(remind_entry), 5, 0);
gtk_widget_set_usize(GTK_WIDGET(radio1), 5, 0);
gtk_widget_set_usize(GTK_WIDGET(radio2), 5, 0);
Pdata = malloc(sizeof(struct alarm_dialog_data));
if (Pdata) {
Pdata->unique_id = unique_id;
Pdata->remind_time = remind_time;
/* Set the default button pressed to OK */
Pdata->button_hit = DIALOG_SAID_1;
Pdata->remind_entry=remind_entry;
Pdata->radio1=radio1;
Pdata->radio2=radio2;
}
gtk_object_set_data(GTK_OBJECT(alarm_dialog), "alarm", Pdata);
get_pref(PREF_REMIND_IN, NULL, &pref_entry);
gtk_entry_set_text(GTK_ENTRY(remind_entry), pref_entry);
get_pref(PREF_REMIND_UNITS, &pref_units, NULL);
if (pref_units) {
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio2), TRUE);
} else {
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio1), TRUE);
}
vbox_temp = gtk_vbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox1), vbox_temp, TRUE, TRUE, 1);
gtk_box_pack_start(GTK_BOX(vbox_temp), radio1, TRUE, TRUE, 1);
gtk_box_pack_start(GTK_BOX(vbox_temp), radio2, TRUE, TRUE, 1);
gtk_widget_show_all(alarm_dialog);
return 0;
}
/*
* End Alarm GUI
*/
#ifdef ALARMS_DEBUG
const char *print_date(const time_t t1)
{
struct tm *Pnow;
static char str[100];
Pnow = localtime(&t1);
strftime(str, 80, "%B %d, %Y %H:%M:%S", Pnow);
return str;
}
const char *print_type(AlarmType type)
{
switch (type) {
case ALARM_NONE:
return "ALARM_NONE";
case ALARM_NEW:
return "ALARM_NEW";
case ALARM_MISSED:
return "ALARM_MISSED";
case ALARM_POSTPONED:
return "ALARM_POSTPONED";
default:
return "? ALARM_UNKNOWN";
}
}
#else
inline const char *print_date(const time_t t1)
{
return "";
}
inline const char *print_type(AlarmType type)
{
return "";
}
#endif
void alarms_add_to_list(unsigned int unique_id,
AlarmType type,
time_t event_time,
time_t alarm_advance)
{
struct jp_alarms *temp_alarm;
#ifdef ALARMS_DEBUG
printf("alarms_add_to_list()\n");
#endif
temp_alarm = malloc(sizeof(struct jp_alarms));
if (!temp_alarm) {
jpilot_logf(LOG_WARN, "alarms_add_to_list: Out of memory\n");
return;
}
temp_alarm->unique_id = unique_id;
temp_alarm->type = type;
temp_alarm->event_time = event_time;
temp_alarm->alarm_advance = alarm_advance;
temp_alarm->next = NULL;
if (Plast_alarm_list) {
Plast_alarm_list->next=temp_alarm;
Plast_alarm_list=temp_alarm;
} else {
alarm_list=Plast_alarm_list=temp_alarm;
}
Plast_alarm_list=temp_alarm;
}
void alarms_remove_from_to_list(unsigned int unique_id)
{
struct jp_alarms *temp_alarm, *prev_alarm, *next_alarm;
#ifdef ALARMS_DEBUG
printf("remove from list(%d)\n", unique_id);
#endif
for(prev_alarm=NULL, temp_alarm=alarm_list;
temp_alarm;
temp_alarm=next_alarm) {
if (temp_alarm->unique_id==unique_id) {
/* Tail of list? */
if (temp_alarm->next==NULL) {
Plast_alarm_list=prev_alarm;
}
/* Last of list? */
if (Plast_alarm_list==alarm_list) {
Plast_alarm_list=alarm_list=NULL;
}
if (prev_alarm) {
prev_alarm->next=temp_alarm->next;
} else {
/* Head of list */
alarm_list=temp_alarm->next;
}
free(temp_alarm);
return;
} else {
prev_alarm=temp_alarm;
next_alarm=temp_alarm->next;
}
}
}
void free_alarms_list(int mask)
{
struct jp_alarms *ta, *ta_next;
if (mask&PREV_ALARM_MASK) {
for (ta=alarm_list; ta; ta=ta_next) {
ta_next=ta->next;
free(ta);
}
Plast_alarm_list=alarm_list=NULL;
}
if (mask&NEXT_ALARM_MASK) {
for (ta=next_alarm; ta; ta=ta_next) {
ta_next=ta->next;
free(ta);
}
next_alarm=NULL;
}
}
void alarms_write_file(void)
{
FILE *out;
char line[256];
int fail, n;
time_t ltime;
struct tm *now;
jpilot_logf(LOG_DEBUG, "alarms_write_file()\n");
time(<ime);
now = localtime(<ime);
out=jp_open_home_file("jpilot.alarms.tmp", "w");
if (!out) {
jpilot_logf(LOG_WARN, "Could not open jpilot.alarms.tmp file\n");
return;
}
fail=0;
strncpy(line,
"# This file was generated by jpilot, changes will be lost\n",
255);
n = fwrite(line, strlen(line), 1, out);
if (n<1) fail=1;
strncpy(line,
"# This is the last time that jpilot was ran\n",
255);
n = fwrite(line, strlen(line), 1, out);
if (n<1) fail=1;
sprintf(line, "UPTODATE %d %d %d %d %d\n",
now->tm_year+1900,
now->tm_mon+1,
now->tm_mday,
now->tm_hour,
now->tm_min
);
n = fwrite(line, strlen(line), 1, out);
if (n<1) fail=1;
fclose(out);
if (fail) {
unlink_file("jpilot.alarms.tmp");
} else {
rename_file("jpilot.alarms.tmp", "jpilot.alarms");
}
}
/* This attempts to make the command safe.
* I'm sure I'm missing things.
*/
void make_command_safe(char *command)
{
int i, len;
char c;
len = strlen(command);
for (i=0; i<len; i++) {
c=command[i];
if (strchr("\r\n|&;()<>", c)) {
command[i]=' ';
}
}
}
/*
* Pop up window.
* Do alarm setting (play sound, or whatever).
* if user postpones then put in postponed alarm list.
*/
int alarms_do_one(struct Appointment *a,
unsigned long unique_id,
time_t t_alarm,
AlarmType type)
{
struct tm *Pnow;
char time_str[255];
char desc_str[255];
char note_str[255];
char pref_time[50];
char time1_str[50];
char time2_str[50];
char date_str[50];
char command[1024];
char *reason;
long ivalue;
long wants_windows;
long do_command;
const char *pref_date;
const char *pref_command;
char c1, c2;
int i, len;
alarms_write_file();
switch (type) {
case ALARM_NONE:
return 0;
case ALARM_NEW:
reason=_("Appointment Reminder");
break;
case ALARM_MISSED:
reason=_("Past Appointment");
break;
case ALARM_POSTPONED:
reason=_("Postponed Appointment");
break;
default:
reason=_("Appointment");
}
get_pref(PREF_SHORTDATE, &ivalue, &pref_date);
get_pref_time_no_secs(pref_time);
Pnow = localtime(&t_alarm);
strftime(date_str, 50, pref_date, Pnow);
strftime(time1_str, 50, pref_time, Pnow);
strftime(time2_str, 50, pref_time, &(a->end));
sprintf(time_str, "%s %s-%s\n", date_str, time1_str, time2_str);
desc_str[0]='\0';
note_str[0]='\0';
if (a->description) {
strncpy(desc_str, a->description, 200);
desc_str[200]='\0';
}
if (a->note) {
strncpy(note_str, a->note, 200);
note_str[200]='\0';
}
get_pref(PREF_ALARM_COMMAND, &ivalue, &pref_command);
get_pref(PREF_DO_ALARM_COMMAND, &do_command, NULL);
#ifdef ALARMS_DEBUG
printf("pref_command = [%s]\n", pref_command);
#endif
bzero(command, 1024);
if (do_command) {
command[0]='\0';
for (i=0; i<MAX_PREF_VALUE-1; i++) {
c1 = pref_command[i];
c2 = pref_command[i+1];
len = strlen(command);
/* expand '%t' */
if (c1=='%') {
if (c2=='t') {
i++;
strncat(command, time1_str, 1022-len);
continue;
}
/* expand '%d' */
if (c2=='d') {
i++;
strncat(command, date_str, 1022-len);
continue;
}
#ifdef ALARM_SHELL_DESC_NOTE
/* expand '%D' */
if (c2=='D') {
i++;
strncat(command, desc_str, 1022-len);
continue;
}
if (c2=='N') {
i++;
strncat(command, note_str, 1022-len);
continue;
}
#endif
}
if (len<1020) {
command[len++]=c1;
command[len]='\0';
}
if (c1=='\0') {
break;
}
}
command[1022]='\0';
make_command_safe(command);
jpilot_logf(LOG_STDOUT|LOG_FILE, "executing command = [%s]\n", command);
system(command);
}
get_pref(PREF_OPEN_ALARM_WINDOWS, &wants_windows, NULL);
if (wants_windows) {
return dialog_alarm("J-Pilot Alarm", reason,
time_str, desc_str, note_str,
unique_id,
t_alarm);
}
return 0;
}
/*
* See if next_alarm is due in less than ALARM_INTERVAL/2 secs.
* If it is, then do_alarm and find_next_alarm.
*/
gint cb_timer_alarms(gpointer data)
{
struct jp_alarms *temp_alarm, *ta_next;
AppointmentList *a_list;
AppointmentList *temp_al;
static int first=0;
time_t t, diff;
time_t t_alarm_time;
struct tm *Ptm;
struct tm copy_tm;
a_list=NULL;
if (!first) {
alarms_write_file();
first=1;
}
time(&t);
for (temp_alarm=alarm_list; temp_alarm; temp_alarm=ta_next) {
ta_next=temp_alarm->next;
diff = temp_alarm->event_time - t - temp_alarm->alarm_advance;
if (temp_alarm->type!=ALARM_MISSED) {
if (diff >= ALARM_INTERVAL/2) {
continue;
}
}
if (a_list==NULL) {
get_days_appointments2(&a_list, NULL, 0, 0, 1);
}
#ifdef ALARMS_DEBUG
printf("unique_id=%d\n", temp_alarm->unique_id);
printf("type=%s\n", print_type(temp_alarm->type));
printf("event_time=%s\n", print_date(temp_alarm->event_time));
printf("alarm_advance=%ld\n", temp_alarm->alarm_advance);
#endif
for (temp_al = a_list; temp_al; temp_al=temp_al->next) {
if (temp_al->ma.unique_id == temp_alarm->unique_id) {
#ifdef ALARMS_DEBUG
printf("%s\n", temp_al->ma.a.description);
#endif
alarms_do_one(&(temp_al->ma.a),
temp_alarm->unique_id,
temp_alarm->event_time,
ALARM_MISSED);
break;
}
}
/* Be careful, this modifies the list we are parsing and
removes the current node */
alarms_remove_from_to_list(temp_al->ma.unique_id);
}
if (next_alarm) {
diff = next_alarm->event_time - t - next_alarm->alarm_advance;
if (diff <= ALARM_INTERVAL/2) {
if (a_list==NULL) {
get_days_appointments2(&a_list, NULL, 0, 0, 1);
}
for (temp_alarm=next_alarm; temp_alarm; temp_alarm=ta_next) {
for (temp_al = a_list; temp_al; temp_al=temp_al->next) {
if (temp_al->ma.unique_id == temp_alarm->unique_id) {
#ifdef ALARMS_DEBUG
printf("** next unique_id=%d\n", temp_alarm->unique_id);
printf("** next type=%s\n", print_type(temp_alarm->type));
printf("** next event_time=%s\n", print_date(temp_alarm->event_time));
printf("** next alarm_advance=%ld\n", temp_alarm->alarm_advance);
printf("** next %s\n", temp_al->ma.a.description);
#endif
alarms_do_one(&(temp_al->ma.a),
temp_alarm->unique_id,
temp_alarm->event_time,
ALARM_NEW);
break;
}
}
/* This may not be exactly right */
t_alarm_time = temp_alarm->event_time + 1;
#ifdef ALARMS_DEBUG
printf("** t_alarm_time-->%s\n", print_date(t_alarm_time));
#endif
ta_next=temp_alarm->next;
free(temp_alarm);
next_alarm = ta_next;
}
Ptm = localtime(&t_alarm_time);
memcpy(©_tm, Ptm, sizeof(struct tm));
alarms_find_next(©_tm, ©_tm, TRUE);
}
}
if (a_list) {
free_AppointmentList(&a_list);
}
return TRUE;
}
static int find_prev_next(struct Appointment *a,
int adv,
struct tm *date1,
struct tm *date2,
struct tm *tm_prev,
struct tm *tm_next,
int *prev_found,
int *next_found)
{
struct tm t;
struct tm *Pnow;
time_t t_temp;
time_t t1, t2;
time_t t_begin, t_end;
time_t t_alarm;
time_t t_past;
time_t t_future;
time_t t_interval;
int forward, backward;
int offset;
int freq;
int found;
int count;
int dow;
int i;
int safety_counter;
int fdom, ndim;
long fdow;
int days, begin_days;
#ifdef ALARMS_DEBUG
printf("fpn: entered find_previous_next\n");
#endif
*prev_found=*next_found=0;
forward=backward=1;
t1=mktime(date1);
t2=mktime(date2);
bzero(tm_prev, sizeof(struct tm));
bzero(tm_next, sizeof(struct tm));
bzero(&t, sizeof(struct tm));
t.tm_year=a->begin.tm_year;
t.tm_mon=a->begin.tm_mon;
t.tm_mday=a->begin.tm_mday;
t.tm_hour=a->begin.tm_hour;
t.tm_min=a->begin.tm_min;
t.tm_isdst=-1;
freq = 0;
switch (a->repeatType) {
case repeatNone:
#ifdef ALARMS_DEBUG
printf("fpn: repeatNone\n");
#endif
t_alarm=mktime(&(a->begin)) - adv;
if ((t_alarm < t2) && (t_alarm > t1)) {
memcpy(tm_prev, &(a->begin), sizeof(struct tm));
*prev_found=1;
#ifdef ALARMS_DEBUG
printf("fpn: prev_found none\n");
#endif
} else if (t_alarm > t2) {
memcpy(tm_next, &(a->begin), sizeof(struct tm));
*next_found=1;
#ifdef ALARMS_DEBUG
printf("fpn: next_found none\n");
#endif
}
forward=backward=0;
break;
case repeatDaily:
#ifdef ALARMS_DEBUG
printf("fpn: repeatDaily\n");
#endif
freq = a->repeatFrequency;
t_interval = a->repeatFrequency * 86400;
if (t_interval==0) t_interval=1;
t_alarm = mktime(&t);
if ((t2 + adv) > t_alarm) {
t_past = ((t2 + adv - t_alarm) / t_interval) *t_interval + t_alarm;
t_future = (((t2 + adv - t_alarm) / t_interval) + 1) *t_interval + t_alarm;
*prev_found=*next_found=1;
} else {
t_future = t_alarm;
*next_found=1;
}
Pnow = localtime(&t_past);
memcpy(tm_prev, Pnow, sizeof(struct tm));
Pnow = localtime(&t_future);
memcpy(tm_next, Pnow, sizeof(struct tm));
forward=backward=0;
#ifdef ALARMS_DEBUG
{
char str[100];
strftime(str, 80, "%B %d, %Y %H:%M", tm_prev);
printf("fpn: daily tm_prev=%s\n", str);
strftime(str, 80, "%B %d, %Y %H:%M", tm_next);
printf("fpn: daily tm_next=%s\n", str);
}
#endif
break;
case repeatWeekly:
#ifdef ALARMS_DEBUG
printf("fpn: repeatWeekly\n");
#endif
freq = a->repeatFrequency;
t.tm_year=date2->tm_year;
t.tm_mon=date2->tm_mon;
t.tm_mday=date2->tm_mday;
mktime(&t);
begin_days = dateToDays(&(a->begin));
days = dateToDays(&t);
#ifdef ALARMS_DEBUG
printf("fpn: begin_days %d days %d\n", begin_days, days);
printf("fpn: t.tm_wday %d a->begin.tm_wday %d\n", t.tm_wday, a->begin.tm_wday);
#endif
get_pref(PREF_FDOW, &fdow, NULL);
/* Offset is how many weeks we are off of an iteration */
offset = ((int)((days - t.tm_wday) - (begin_days - a->begin.tm_wday))/7)%freq;
#ifdef ALARMS_DEBUG
printf("fpn: offset %d\n", offset);
#endif
if (offset > 0) {
sub_days_from_date(&t, offset*7);
} else {
add_days_to_date(&t, offset*-7);
}
found=0;
for (count=0, i=t.tm_wday; i>=0; i--, count++) {
if (a->repeatDays[i]) {
sub_days_from_date(&t, count);
found=1;
#ifdef ALARMS_DEBUG
{
char str[100];
strftime(str, 80, "%B %d, %Y %H:%M", &t);
printf("fpn: initial weekly=%s\n", str);
}
#endif
break;
}
}
if (!found) {
for (count=0, i=t.tm_wday; i<7; i++, count++) {
if (a->repeatDays[i]) {
add_days_to_date(&t, count);
found=1;
break;
}
}
}
break;
case repeatMonthlyByDay:
#ifdef ALARMS_DEBUG
printf("fpn: repeatMonthlyByDay\n");
#endif
t.tm_mon=date2->tm_mon;
t.tm_year=date2->tm_year;
freq = a->repeatFrequency;
#ifdef ALARMS_DEBUG
printf("fpn: freq=%d\n", freq);
#endif
offset = ((t.tm_year - a->begin.tm_year)*12 +
(t.tm_mon - a->begin.tm_mon))%(a->repeatFrequency);
/* This will adjust for leap year, and exceeding the end of the month */
if (((t.tm_year - a->begin.tm_year)*12 + (t.tm_mon - a->begin.tm_mon)) < 0) {
add_months_to_date(&t, offset);
} else {
sub_months_from_date(&t, offset);
}
get_month_info(t.tm_mon, 1, t.tm_year, &fdom, &ndim);
t.tm_mday=((a->repeatDay+7-fdom)%7) - ((a->repeatDay)%7) + a->repeatDay + 1;
#ifdef ALARMS_DEBUG
printf("fpn: %02d/01/%02d, fdom=%d\n", t.tm_mon+1, t.tm_year+1900, fdom);
printf("fpn: mday = %d\n", t.tm_mday);
#endif
if (t.tm_mday > ndim) {
t.tm_mday -= 7;
}
#ifdef ALARMS_DEBUG
{
char str[100];
strftime(str, 80, "%B %d, %Y %H:%M", &t);
printf("fpn: initial monthly by day=%s\n", str);
}
#endif
break;
case repeatMonthlyByDate:
#ifdef ALARMS_DEBUG
printf("fpn: repeatMonthlyByDate\n");
#endif
t.tm_mon=date2->tm_mon;
t.tm_year=date2->tm_year;
freq = a->repeatFrequency;
offset = ((t.tm_year - a->begin.tm_year)*12 +
(t.tm_mon - a->begin.tm_mon))%(a->repeatFrequency);
/* This will adjust for leap year, and exceeding the end of the month */
if (((t.tm_year - a->begin.tm_year)*12 + (t.tm_mon - a->begin.tm_mon)) < 0) {
add_months_to_date(&t, offset);
} else {
sub_months_from_date(&t, offset);
}
break;
case repeatYearly:
#ifdef ALARMS_DEBUG
printf("fpn: repeatYearly\n");
#endif
t.tm_year=date2->tm_year;
freq = a->repeatFrequency;
offset = (t.tm_year - a->begin.tm_year)%(a->repeatFrequency);
#ifdef ALARMS_DEBUG
printf("fpn: (%d - %d)%%%d\n", t.tm_year,a->begin.tm_year,a->repeatFrequency);
printf("fpn: *** years offset = %d\n", offset);
#endif
/* This will adjust for leap year, and exceeding the end of the month */
if ((t.tm_year - a->begin.tm_year) < 0) {
add_years_to_date(&t, offset);
} else {
sub_years_from_date(&t, offset);
}
break;
}/*switch */
safety_counter=0;
while(forward || backward) {
safety_counter++;
if (safety_counter > 20) {
jpilot_logf(LOG_STDOUT|LOG_FILE, "find_prev_next():infinite loop, breaking\n");
if (a->description) {
jpilot_logf(LOG_STDOUT|LOG_FILE, "desc=[%s]\n", a->description);
}
break;
}
t_temp = mktime(&t);
#ifdef ALARMS_DEBUG
{
char str[100];
strftime(str, 80, "%B %d, %Y %H:%M", &t);
printf("fpn: trying with=%s\n", str);
}
#endif
/* See that we aren't before then begin date */
t_begin = mktime(&(a->begin));
if (t_temp < t_begin - adv) {
#ifdef ALARMS_DEBUG
printf("fpn:1\n");
#endif
backward=0;
}
/* If the appointment has an end date, see that we are not past it */
if (!(a->repeatForever)) {
t_end = mktime(&(a->repeatEnd));
if (t_temp > t_end) {
forward=0;
#ifdef ALARMS_DEBUG
printf("fpn: 2\n");
#endif
}
}
t_temp-=adv;
if (t_temp >= t2) {
memcpy(tm_next, &t, sizeof(t));
*next_found=1;
forward=0;
#ifdef ALARMS_DEBUG
printf("fpn: next found\n");
#endif
} else {
memcpy(tm_prev, &t, sizeof(t));
*prev_found=1;
backward=0;
#ifdef ALARMS_DEBUG
printf("fpn: prev_found\n");
#endif
}
/* increment or decrement time */
if (forward) {
switch (a->repeatType) {
case repeatNone:
break;
case repeatDaily:
break;
case repeatWeekly:
for (count=0, dow=t.tm_wday; count<14; count++) {
add_days_to_date(&t, 1);
#ifdef ALARMS_DEBUG
printf("fpn: weekly forward t.tm_wday=%d, freq=%d\n", t.tm_wday, freq);
#endif
dow++;
if (dow==7) {
#ifdef ALARMS_DEBUG
printf("fpn: dow==7\n");
#endif
add_days_to_date(&t, (freq-1)*7);
dow=0;
}
if (a->repeatDays[dow]) {
#ifdef ALARMS_DEBUG
printf("fpn: repeatDay[dow] dow=%d\n", dow);
#endif
break;
}
}
break;
case repeatMonthlyByDay:
add_months_to_date(&t, freq);
get_month_info(t.tm_mon, 1, t.tm_year, &fdom, &ndim);
t.tm_mday=((a->repeatDay+7-fdom)%7) - ((a->repeatDay)%7) + a->repeatDay + 1;
if (t.tm_mday > ndim-1) {
t.tm_mday -= 7;
}
break;
case repeatMonthlyByDate:
t.tm_mday=a->begin.tm_mday;
add_months_to_date(&t, freq);
break;
case repeatYearly:
t.tm_mday=a->begin.tm_mday;
add_years_to_date(&t, freq);
break;
}/*switch */
continue;
}
if (backward) {
switch (a->repeatType) {
case repeatNone:
break;
case repeatDaily:
break;
case repeatWeekly:
for (count=0, dow=t.tm_wday; count<14; count++) {
sub_days_from_date(&t, 1);
#ifdef ALARMS_DEBUG
printf("fpn: weekly backward t.tm_wday=%d, freq=%d\n", t.tm_wday, freq);
#endif
dow--;
if (dow==-1) {
#ifdef ALARMS_DEBUG
printf("fpn: dow==-1\n");
#endif
sub_days_from_date(&t, (freq-1)*7);
dow=6;
}
if (a->repeatDays[dow]) {
#ifdef ALARMS_DEBUG
printf("fpn: repeatDay[dow] dow=%d\n", dow);
#endif
break;
}
}
break;
case repeatMonthlyByDay:
sub_months_from_date(&t, freq);
get_month_info(t.tm_mon, 1, t.tm_year, &fdom, &ndim);
t.tm_mday=((a->repeatDay+7-fdom)%7) - ((a->repeatDay)%7) + a->repeatDay + 1;
if (t.tm_mday > ndim-1) {
t.tm_mday -= 7;
}
break;
case repeatMonthlyByDate:
t.tm_mday=a->begin.tm_mday;
sub_months_from_date(&t, freq);
break;
case repeatYearly:
t.tm_mday=a->begin.tm_mday;
sub_years_from_date(&t, freq);
break;
}/*switch */
continue;
}
}
return 0;
}
/*
* Find the next appointment alarm
* if soonest_only then return the next alarm, else return all alarms
* that occur between the 2 dates.
*/
int alarms_find_next(struct tm *date1_in, struct tm *date2_in, int soonest_only)
{
AppointmentList *a_list;
AppointmentList *temp_al;
struct jp_alarms *ta;
time_t adv;
time_t ltime;
time_t t1, t2;
time_t t_alarm;
time_t t_begin, t_end;
time_t t_prev;
time_t t_future;
time_t t_interval;
time_t t_soonest;
struct tm *tm_temp;
struct tm date1, date2;
struct tm tm_prev, tm_next;
int prev_found, next_found;
int add_a_next;
jpilot_logf(LOG_DEBUG, "alarms_find_next()\n");
if (glob_skip_all_alarms) return 0;
if (!date1_in) {
time(<ime);
tm_temp = localtime(<ime);
} else {
tm_temp=date1_in;
}
bzero(&date1, sizeof(date1));
date1.tm_year=tm_temp->tm_year;
date1.tm_mon=tm_temp->tm_mon;
date1.tm_mday=tm_temp->tm_mday;
date1.tm_hour=tm_temp->tm_hour;
date1.tm_min=tm_temp->tm_min;
date1.tm_sec=tm_temp->tm_sec;
date1.tm_isdst=tm_temp->tm_isdst;
if (!date2_in) {
time(<ime);
tm_temp = localtime(<ime);
} else {
tm_temp=date2_in;
}
bzero(&date2, sizeof(date2));
date2.tm_year=tm_temp->tm_year;
date2.tm_mon=tm_temp->tm_mon;
date2.tm_mday=tm_temp->tm_mday;
date2.tm_hour=tm_temp->tm_hour;
date2.tm_min=tm_temp->tm_min;
date2.tm_sec=tm_temp->tm_sec;
date2.tm_isdst=tm_temp->tm_isdst;
t1=mktime(&date1);
t2=mktime(&date2);
#ifdef ALARMS_DEBUG
{
char str[100];
struct tm *Pnow;
strftime(str, 80, "%B %d, %Y %H:%M", &date1);
printf("date1=%s\n", str);
strftime(str, 80, "%B %d, %Y %H:%M", &date2);
printf("date2=%s\n", str);
Pnow = localtime(&t1);
strftime(str, 80, "%B %d, %Y %H:%M", Pnow);
printf("^date1=%s\n", str);
}
#endif
if (!soonest_only) {
free_alarms_list(PREV_ALARM_MASK | NEXT_ALARM_MASK);
} else {
free_alarms_list(NEXT_ALARM_MASK);
}
a_list=NULL;
get_days_appointments2(&a_list, NULL, 0, 0, 1);
t_soonest=0;
for (temp_al=a_list; temp_al; temp_al=temp_al->next) {
/*
* No alarm, skip
*/
if (!temp_al->ma.a.alarm) {
continue;
}
#ifdef ALARMS_DEBUG
printf("\n[%s]\n", temp_al->ma.a.description);
#endif
/*
* See if the appointment starts before date1
* and is a non repeating appointment
*/
if (temp_al->ma.a.repeatType == repeatNone) {
t_alarm = mktime(&(temp_al->ma.a.begin));
if (t_alarm < t1) {
#ifdef ALARMS_DEBUG
printf("non repeat before t1, t_alarm<t1, %ld<%ld\n",t_alarm,t1);
#endif
continue;
}
}
/* If the appointment has an end date, see that we are not past it */
if (!(temp_al->ma.a.repeatForever)) {
t_end = mktime(&(temp_al->ma.a.repeatEnd));
/* We need to add 24 hours to the end date to make it inclusive */
t_end += 86400;
t_begin = mktime(&(temp_al->ma.a.begin));
if (t_end < t2) {
#ifdef ALARMS_DEBUG
printf("past end date\n");
#endif
continue;
}
}
#ifdef ALARMS_DEBUG
printf("alarm advance %d ", temp_al->ma.a.advance);
#endif
adv = 0;
if (temp_al->ma.a.advanceUnits == advMinutes) {
#ifdef ALARMS_DEBUG
printf("minutes\n");
#endif
adv = temp_al->ma.a.advance*60;
}
if (temp_al->ma.a.advanceUnits == advHours) {
#ifdef ALARMS_DEBUG
printf("hours\n");
#endif
adv = temp_al->ma.a.advance*3600;
}
if (temp_al->ma.a.advanceUnits == advDays) {
#ifdef ALARMS_DEBUG
printf("days\n");
#endif
adv = temp_al->ma.a.advance*86400;
}
#ifdef ALARMS_DEBUG
printf("adv=%ld\n", adv);
#endif
t_prev=t_future=t_interval=0;
prev_found=next_found=0;
find_prev_next(&(temp_al->ma.a),
adv,
&date1,
&date2,
&tm_prev,
&tm_next,
&prev_found,
&next_found);
t_prev=mktime(&tm_prev);
t_future=mktime(&tm_next);
#ifdef ALARMS_DEBUG
printf("adv = %ld\n", adv);
#endif
/*
* Skip the alarms if they are before date1, or after date2
*/
if (prev_found) {
if (t_prev - adv < t1) {
#ifdef ALARMS_DEBUG
printf("failed prev is before t1\n");
#endif
prev_found=0;
}
if (t_prev - adv > t2) {
#ifdef ALARMS_DEBUG
printf("failed prev is after t2\n");
#endif
continue;
}
}
if (next_found) {
if (!(temp_al->ma.a.repeatForever)) {
t_end = mktime(&(temp_al->ma.a.repeatEnd));
if (t_future > t_end) {
#ifdef ALARMS_DEBUG
printf("failed future is after t_end\n");
#endif
next_found=0;
}
}
}
#ifdef ALARMS_DEBUG
printf("t1= %s\n", print_date(t1));
printf("t2= %s\n", print_date(t2));
printf("t_prev= %s\n", prev_found ? print_date(t_prev):"None");
printf("t_future= %s\n", next_found ? print_date(t_future):"None");
printf("alarm me= %s\n", next_found ? print_date(t_future):"None");
printf("desc=[%s]\n", temp_al->ma.a.description);
#endif
if (!soonest_only) {
if (prev_found) {
alarms_add_to_list(temp_al->ma.unique_id, ALARM_MISSED, t_prev, adv);
}
}
if (next_found) {
add_a_next=0;
if (next_alarm==NULL) {
add_a_next=1;
} else if
(t_future - adv <= next_alarm->event_time - next_alarm->alarm_advance) {
add_a_next=1;
if (t_future - adv < next_alarm->event_time - next_alarm->alarm_advance) {
#ifdef ALARMS_DEBUG
printf("next alarm=%s\n", print_date(next_alarm->event_time - next_alarm->alarm_advance));
printf("freeing next alarms\n");
#endif
free_alarms_list(NEXT_ALARM_MASK);
}
}
if (add_a_next) {
#ifdef ALARMS_DEBUG
printf("found a new next\n");
#endif
ta = malloc(sizeof(struct jp_alarms));
if (ta) {
ta->next = next_alarm;
next_alarm = ta;
next_alarm->unique_id = temp_al->ma.unique_id;
next_alarm->type = ALARM_NEW;
next_alarm->event_time = t_future;
next_alarm->alarm_advance = adv;
}
}
}
}
free_AppointmentList(&a_list);
return 0;
}
/*
* At startup see when rc file was written and find all past-due alarms.
* Add them to the postponed alarm list with 0 minute reminder.
* Find next alarm and put it in list
*/
int alarms_init(unsigned char skip_past_alarms,
unsigned char skip_all_alarms)
{
FILE *in;
time_t ltime;
struct tm now, *Pnow;
struct tm tm1;
char line[256];
int found_uptodate;
int year, mon, day, hour, min, n;
jpilot_logf(LOG_DEBUG, "alarms_init()\n");
alarm_list=NULL;
Plast_alarm_list=NULL;
next_alarm=NULL;
total_alarm_windows = 0;
glob_skip_all_alarms = skip_all_alarms;
if (skip_past_alarms) {
alarms_write_file();
}
if (skip_all_alarms) {
alarms_write_file();
return 0;
}
found_uptodate=0;
in=jp_open_home_file("jpilot.alarms", "r");
if (!in) {
jpilot_logf(LOG_WARN, "Could not open jpilot.alarms file\n");
return -1;
}
while (!feof(in)) {
line[0]='\0';
fgets(line, 255, in);
line[255] = '\0';
if (line[0]=='#') continue;
if (!strncmp(line, "UPTODATE ", 9)) {
n = sscanf(line+9, "%d %d %d %d %d\n", &year, &mon, &day, &hour, &min);
if (n==5) {
found_uptodate=1;
}
jpilot_logf(LOG_DEBUG, "UPTODATE %d %d %d %d %d\n", year, mon, day, hour, min);
}
}
time(<ime);
Pnow = localtime(<ime);
bzero(&now, sizeof(now));
now.tm_year=Pnow->tm_year;
now.tm_mon=Pnow->tm_mon;
now.tm_mday=Pnow->tm_mday;
now.tm_hour=Pnow->tm_hour;
now.tm_min=Pnow->tm_min;
now.tm_isdst=-1;
mktime(&now);
if (!found_uptodate) {
alarms_write_file();
year = now.tm_year+1900;
mon = now.tm_mon+1;
day = now.tm_mday;
hour = now.tm_hour;
min = now.tm_min;
}
bzero(&tm1, sizeof(tm1));
tm1.tm_year=year-1900;
tm1.tm_mon=mon-1;
tm1.tm_mday=day;
tm1.tm_hour=hour;
tm1.tm_min=min;
tm1.tm_isdst=-1;
mktime(&tm1);
alarms_find_next(&tm1, &now, FALSE);
gtk_timeout_add(ALARM_INTERVAL*1000, cb_timer_alarms, NULL);
return 0;
}
jpilot-0.99.2/datebook.c 0100644 0001750 0000144 00000056367 07430116344 014143 0 ustar mouse users /* datebook.c
* A module of J-Pilot http://jpilot.org
*
* Copyright (C) 1999-2001 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
*/
#include "config.h"
#include "i18n.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pi-source.h>
#include <pi-socket.h>
#include <pi-datebook.h>
#include <pi-dlp.h>
#include <pi-file.h>
#include <time.h>
/*#include <sys/stat.h> */
/*#include <sys/types.h> */
#include <unistd.h>
#include <utime.h>
#include "datebook.h"
#include "utils.h"
#include "log.h"
#include "prefs.h"
#include "libplugin.h"
#include "password.h"
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#define DATEBOOK_EOF 7
int datebook_compare(const void *v1, const void *v2)
{
AppointmentList **al1, **al2;
struct Appointment *a1, *a2;
al1=(AppointmentList **)v1;
al2=(AppointmentList **)v2;
a1=&((*al1)->ma.a);
a2=&((*al2)->ma.a);
/* Jim Rees pointed out my sorting error */
/* return ((a1->begin.tm_hour*60 + a1->begin.tm_min) > */
return ((a1->begin.tm_hour*60 + a1->begin.tm_min) -
(a2->begin.tm_hour*60 + a2->begin.tm_min));
}
static int datebook_sort(AppointmentList **al)
{
AppointmentList *temp_al;
AppointmentList **sort_al;
int count, i;
/* Count the entries in the list */
for (count=0, temp_al=*al; temp_al; temp_al=temp_al->next, count++) {
;
}
if (count<2) {
/* We don't have to sort less than 2 items */
return 0;
}
/* Allocate an array to be qsorted */
sort_al = calloc(count, sizeof(AppointmentList *));
if (!sort_al) {
jpilot_logf(LOG_WARN, "datebook_sort(): Out of Memory\n");
return 0;
}
/* Set our array to be a list of pointers to the nodes in the linked list */
for (i=0, temp_al=*al; temp_al; temp_al=temp_al->next, i++) {
sort_al[i] = temp_al;
}
/* qsort them */
qsort(sort_al, count, sizeof(AppointmentList *), datebook_compare);
/* Put the linked list in the order of the array */
sort_al[count-1]->next = NULL;
for (i=count-1; i; i--) {
sort_al[i-1]->next=sort_al[i];
}
*al = sort_al[0];
free(sort_al);
return 0;
}
#ifdef USE_DB3
int db3_hack_date(struct Appointment *a, struct tm *today)
{
int t1, t2;
if (today==NULL) {
return 0;
}
if (!a->note) {
return 0;
}
if (strlen(a->note) > 8) {
if ((a->note[0]=='#') && (a->note[1]=='#')) {
if (a->note[2]=='f') {
/* Check to see if its in the future */
t1 = a->begin.tm_mday + a->begin.tm_mon*31 + a->begin.tm_year*372;
t2 = today->tm_mday + today->tm_mon*31 + today->tm_year*372;
if (t1 > t2) return 0;
/* We found some silly hack, so we lie about the date */
/*memcpy(&(a->begin), today, sizeof(struct tm));*/
/*memcpy(&(a->end), today, sizeof(struct tm));*/
a->begin.tm_mday = today->tm_mday;
a->begin.tm_mon = today->tm_mon;
a->begin.tm_year = today->tm_year;
a->begin.tm_wday = today->tm_wday;
a->begin.tm_yday = today->tm_yday;
a->begin.tm_isdst = today->tm_isdst;
a->end.tm_mday = today->tm_mday;
a->end.tm_mon = today->tm_mon;
a->end.tm_year = today->tm_year;
a->end.tm_wday = today->tm_wday;
a->end.tm_yday = today->tm_yday;
a->end.tm_isdst = today->tm_isdst;
/* If the appointment has an end date, and today is past the end
* date, because of this hack we would never be able to view
* it anymore (or delete it).
*/
if (!(a->repeatForever)) {
if (compareTimesToDay(today, &(a->repeatEnd))==1) {
/* end date is before start date, illegal appointment */
/* make it legal, by only floating upto the end date */
memcpy(&(a->begin), &(a->repeatEnd), sizeof(struct tm));
memcpy(&(a->end), &(a->repeatEnd), sizeof(struct tm));
}
}
}
}
}
return 0;
}
/* Returns a bitmask
* 0 if not a floating OR
* bitmask:
* 1 if float,
* 2 if completed float
* 16 if float has a note
*/
int db3_is_float(struct Appointment *a, int *category)
{
int len, mask=0;
*category=0;
if (!a->note) {
return 0;
}
len = strlen(a->note);
if (len > 8) {
if ((a->note[0]=='#') && (a->note[1]=='#')) {
*category = a->note[4] - '@';
if (len > 10) {
mask=mask | DB3_FLOAT_HAS_NOTE;
}
if (a->note[2]=='f') {
mask=mask | DB3_FLOAT;
return mask;
}
if (a->note[2]=='c') {
mask=mask | DB3_FLOAT_COMPLETE;
return mask;
}
} else if (a->note[0] != '\0') {
mask=mask | DB3_FLOAT_HAS_NOTE;
}
}
return mask;
}
#endif
int pc_datebook_write(struct Appointment *a, PCRecType rt, unsigned char attrib)
{
char record[65536];
int rec_len;
buf_rec br;
long char_set;
get_pref(PREF_CHAR_SET, &char_set, NULL);
if (char_set != CHAR_SET_ENGLISH) {
if (a->description) charset_j2p(a->description, strlen(a->description)+1, char_set);
if (a->note) charset_j2p(a->note, strlen(a->note)+1, char_set);
}
rec_len = pack_Appointment(a, record, 65535);
if (!rec_len) {
PRINT_FILE_LINE;
jpilot_logf(LOG_WARN, "pack_Appointment %s\n", _("error"));
return -1;
}
br.rt=rt;
br.attrib = attrib;
br.buf = record;
br.size = rec_len;
jp_pc_write("DatebookDB", &br);
/* *unique_id = br.unique_id;*/
return 0;
}
void free_AppointmentList(AppointmentList **al)
{
AppointmentList *temp_al, *temp_al_next;
for (temp_al = *al; temp_al; temp_al=temp_al_next) {
free_Appointment(&(temp_al->ma.a));
temp_al_next = temp_al->next;
free(temp_al);
}
*al = NULL;
}
/*
* If a copy is made, then it should be freed through free_Appointment
*/
int datebook_copy_appointment(struct Appointment *a1,
struct Appointment **a2)
{
*a2=malloc(sizeof(struct Appointment));
if (!(*a2)) {
jpilot_logf(LOG_WARN, "datebook_copy_appointment(): Out of memory\n");
return -1;
}
memcpy(*a2, a1, sizeof(struct Appointment));
(*a2)->exception = (struct tm *)malloc(a1->exceptions * sizeof(struct tm));
if (!(*a2)->exception) {
jpilot_logf(LOG_WARN, "datebook_copy_appointment(): Out of memory 2\n");
return -1;
}
memcpy((*a2)->exception, a1->exception, a1->exceptions * sizeof(struct tm));
if (a1->description) {
(*a2)->description=strdup(a1->description);
}
if (a1->note) {
(*a2)->note=strdup(a1->note);
}
return 0;
}
/* Year is years since 1900 */
/* Mon is 0-11 */
/* Day is 1-31 */
/* */
int datebook_add_exception(struct Appointment *a, int year, int mon, int day)
{
struct tm *new_exception, *Ptm;
if (a->exceptions==0) {
a->exception=NULL;
}
new_exception = malloc((a->exceptions + 1) * sizeof(struct tm));
if (!new_exception) {
jpilot_logf(LOG_WARN, "datebook_add_exception(): Out of memory\n");
return -1;
}
memcpy(new_exception, a->exception, (a->exceptions) * sizeof(struct tm));
free(a->exception);
a->exceptions++;
a->exception = new_exception;
Ptm = &(a->exception[a->exceptions - 1]);
Ptm->tm_year = year;
Ptm->tm_mon = mon;
Ptm->tm_mday = day;
Ptm->tm_hour = 0;
Ptm->tm_min = 0;
Ptm->tm_sec = 0;
Ptm->tm_isdst = -1;
mktime(Ptm);
return 0;
}
int dateToSecs(struct tm *tm1)
{
time_t t1;
struct tm *gmt;
struct tm tm2;
static time_t adj = -1;
memcpy(&tm2, tm1, sizeof(struct tm));
tm2.tm_isdst = 0;
tm2.tm_hour=0;
t1 = mktime(&tm2);
if (-1 == adj) {
gmt = gmtime(&t1);
adj = t1 - mktime(gmt);
}
return (t1+adj);
}
int dateToDays(struct tm *tm1)
{
time_t t1;
struct tm *gmt;
struct tm tm2;
static time_t adj = -1;
memcpy(&tm2, tm1, sizeof(struct tm));
tm2.tm_isdst = 0;
tm2.tm_hour=12;
t1 = mktime(&tm2);
if (-1 == adj) {
gmt = gmtime(&t1);
adj = t1 - mktime(gmt);
}
return (t1+adj)/86400; /*There are 86400 secs in a day */
}
/*returns 0 if times equal */
/*returns 1 if time1 is greater (later) */
/*returns 2 if time2 is greater (later) */
/*
int compareTimesToSec(struct tm *tm1, struct tm *tm2)
{
time_t t1, t2;
t1 = mktime(tm1);
t2 = mktime(tm2);
if (t1 > t2) return 1;
if (t1 < t2) return 2;
return 0;
}
*/
/*returns 0 if times equal */
/*returns 1 if time1 is greater (later) */
/*returns 2 if time2 is greater (later) */
int compareTimesToDay(struct tm *tm1, struct tm *tm2)
{
unsigned int t1, t2;
t1 = tm1->tm_year*366+tm1->tm_yday;
t2 = tm2->tm_year*366+tm2->tm_yday;
if (t1 > t2 ) return 1;
if (t1 < t2 ) return 2;
return 0;
}
unsigned int isApptOnDate(struct Appointment *a, struct tm *date)
{
/* long fdow; */
unsigned int ret;
unsigned int r;
int week1, week2;
int dow, ndim;
int i;
/* days_in_month is adjusted for leap year with the date structure */
int days_in_month[]={31,28,31,30,31,30,31,31,30,31,30,31
};
int exception_days;
static int days, begin_days;
static struct tm cached_date;
/* jpilot_logf(LOG_DEBUG, "isApptOnDate\n"); */
ret = FALSE;
if (!date) {
return FALSE;
}
/* To try to speed things up */
if (memcmp(date, &cached_date, sizeof(struct tm))) {
memcpy(&cached_date, date, sizeof(struct tm));
} else {
days=0;
begin_days=0;
}
/* Leap year */
if ((date->tm_year%4 == 0) &&
!(((date->tm_year+1900)%100==0) && ((date->tm_year+1900)%400!=0))
) {
days_in_month[1]++;
}
/* See if the appointment starts after date */
r = compareTimesToDay(&(a->begin), date);
if (r == 1) {
return FALSE;
}
if (r == 0) {
ret = TRUE;
}
/* If the appointment has an end date, see that we are not past it */
if (!(a->repeatForever)) {
r = compareTimesToDay(&(a->repeatEnd), date);
if (r == 2) {
return FALSE;
}
}
switch (a->repeatType) {
case repeatNone:
break;
case repeatDaily:
/* See if this appt repeats on this day */
if (!begin_days) {
begin_days = dateToDays(&(a->begin));
}
if (!days) {
days = dateToDays(date);
}
ret = (((days - begin_days)%(a->repeatFrequency))==0);
break;
case repeatWeekly:
get_month_info(date->tm_mon, date->tm_mday, date->tm_year, &dow, &ndim);
/* See if the appointment repeats on this day */
/*
if (a->repeatWeekstart > 1) {
a->repeatWeekstart = 1;
}
if (a->repeatWeekstart < 0) {
a->repeatWeekstart = 0;
}
*/
/*if (!(a->repeatDays[dow + a->repeatWeekstart])) {*/
if (!(a->repeatDays[dow])) {
ret = FALSE;
break;
}
/*See if we are in a week that is repeated in */
if (!begin_days) {
begin_days = dateToDays(&(a->begin));
}
if (!days) {
days = dateToDays(date);
}
/* get_pref(PREF_FDOW, &fdow, NULL); */
/* Note: Palm Bug? I think the palm does this wrong.
* I prefer this way of doing it so that you can have appts repeating
* from Wed->Tue, for example. The palms way prevents this */
/* ret = (((int)((days - begin_days - fdow)/7))%(a->repeatFrequency)==0);*/
/* But, here is the palm way */
/* ret = (((int)((days-begin_days+a->begin.tm_wday-fdow)/7))
%(a->repeatFrequency)==0); */
/* The above seemed to be wrong for fdow=1 and dow=0 appointment */
ret = (((int)((days-begin_days+a->begin.tm_wday)/7))
%(a->repeatFrequency)==0);
break;
case repeatMonthlyByDay:
/* See if we are in a month that is repeated in */
ret = (((date->tm_year - a->begin.tm_year)*12 +
(date->tm_mon - a->begin.tm_mon))%(a->repeatFrequency)==0);
if (!ret) {
break;
}
/* If the days of the week match - good */
/* e.g. Monday or Thur, etc. */
if (a->repeatDay%7 != date->tm_wday) {
ret = FALSE;
break;
}
/* Are they both in the same week in the month */
/* e.