cut/paste feature aded

fixed a 2-years old bug that made repeated items with exceptions to load
uncorrectly in some cases (thanks Jan for reporting it)
This commit is contained in:
Frederic Culot 2009-01-01 17:50:41 +00:00
parent 8fdd1510c6
commit cac30a7e14
16 changed files with 787 additions and 178 deletions

View File

@ -1,3 +1,44 @@
2009-01-01 Frederic Culot <frederic@culot.org>
* src/event.c (event_free_bkp, event_llist_free): new functions
* src/apoint.c (apoint_dup, apoint_paste_item, apoint_free_bkp):
new functions
* src/recur.c (recur_event_free_bkp, recur_event_dup)
(recur_event_paste_item, recur_event_llist_free, recur_add_exc)
(exc_dup, recur_apoint_free_bkp, recur_apoint_dup): new functions
* src/utils.c (get_item_time, get_item_hour, get_item_min): new
functions
* src/recur.c: fixed a two-years old bug (appeared in version 1.5)
that made repeated items with exceptions load uncorrectly in
some cases (thanks Jan for reporting it)
* NEWS: updated (it is now possible to move an item from one date
to another by using the cut/paste feature)
2008-12-30 Frederic Culot <frederic@culot.org>
* src/keys.c: added key bindings for cut and paste
* src/keys.c (keys_fill_missing): new function
* src/io.c (io_load_keys): load default key bindings for missing
keys (meaning they were added with new version of calcurse)
* src/utils.c (status_bar): added status bar labels for cut and
paste commands
* src/calcurse.c: handle cut and paste commands
* src/apoint.c (apoint_cut, apoint_paste): new functions
* src/day.c (day_cut_item, day_paste_item): new functions
* src/event.c (event_dup, event_paste_item): new functions
2008-12-28 Frederic Culot <frederic@culot.org>
* mem.[ch]: new files to build wrappers around libc's memory

1
TODO
View File

@ -12,7 +12,6 @@ this list.
High
----
o Add support for UTF-8
o Allow events and appointments to be moved from one date to another
Average

View File

@ -1,8 +1,8 @@
/* $calcurse: apoint.c,v 1.29 2008/12/28 13:13:59 culot Exp $ */
/* $calcurse: apoint.c,v 1.30 2009/01/01 17:50:41 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2008 Frederic Culot
* Copyright (c) 2004-2009 Frederic Culot
*
* 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
@ -41,8 +41,37 @@
#include "mem.h"
#include "apoint.h"
apoint_llist_t *alist_p;
static int hilt = 0;
apoint_llist_t *alist_p;
static apoint_llist_node_t bkp_cut_apoint;
static int hilt;
void
apoint_free_bkp (void)
{
if (bkp_cut_apoint.mesg)
{
mem_free (bkp_cut_apoint.mesg);
bkp_cut_apoint.mesg = 0;
}
if (bkp_cut_apoint.note)
{
mem_free (bkp_cut_apoint.note);
bkp_cut_apoint.note = 0;
}
}
static void
apoint_dup (apoint_llist_node_t *in, apoint_llist_node_t *bkp)
{
EXIT_IF (!in || !bkp, _("null pointer"));
bkp->start = in->start;
bkp->dur = in->dur;
bkp->state = in->state;
bkp->mesg = mem_strdup (in->mesg);
if (in->note)
bkp->note = mem_strdup (in->note);
}
void
apoint_llist_init (void)
@ -303,6 +332,62 @@ apoint_delete (conf_t *conf, unsigned *nb_events, unsigned *nb_apoints)
}
}
/* Cut an item, so that it can be pasted somewhere else later. */
void
apoint_cut (unsigned *nb_events, unsigned *nb_apoints)
{
const int NBITEMS = *nb_apoints + *nb_events;
int item_type, to_be_removed;
long date;
if (NBITEMS == 0)
return;
to_be_removed = 0;
date = calendar_get_slctd_day_sec ();
item_type = day_cut_item (date, hilt);
if (item_type == EVNT || item_type == RECUR_EVNT)
{
(*nb_events)--;
to_be_removed = 1;
}
else if (item_type == APPT || item_type == RECUR_APPT)
{
(*nb_apoints)--;
to_be_removed = 3;
}
else
EXIT (_("no such type"));
/* NOTREACHED */
if (hilt > 1)
hilt--;
if (apad->first_onscreen >= to_be_removed)
apad->first_onscreen = apad->first_onscreen - to_be_removed;
if (NBITEMS == 1)
hilt = 0;
}
/* Paste a previously cut item. */
void
apoint_paste (unsigned *nb_events, unsigned *nb_apoints)
{
int item_type;
long date;
date = calendar_get_slctd_day_sec ();
item_type = day_paste_item (date);
if (item_type == EVNT || item_type == RECUR_EVNT)
(*nb_events)++;
else if (item_type == APPT || item_type == RECUR_APPT)
(*nb_apoints)++;
else
return;
if (hilt == 0)
hilt++;
}
unsigned
apoint_inday (apoint_llist_node_t *i, long start)
{
@ -434,22 +519,30 @@ apoint_delete_bynum (long start, unsigned num, erase_flag_e flag)
{
if (n == num)
{
if (flag == ERASE_FORCE_ONLY_NOTE)
switch (flag)
{
case ERASE_FORCE_ONLY_NOTE:
erase_note (&i->note, flag);
pthread_mutex_unlock (&(alist_p->mutex));
}
else
{
break;
case ERASE_CUT:
apoint_free_bkp ();
apoint_dup (i, &bkp_cut_apoint);
if (i->note)
mem_free (i->note);
/* FALLTHROUGH */
default:
if (notify_bar ())
need_check_notify = notify_same_item (i->start);
*iptr = i->next;
mem_free (i->mesg);
erase_note (&i->note, flag);
if (flag != ERASE_FORCE_KEEP_NOTE && flag != ERASE_CUT)
erase_note (&i->note, flag);
mem_free (i);
pthread_mutex_unlock (&(alist_p->mutex));
if (need_check_notify)
notify_check_next_app ();
break;
}
return;
}
@ -672,3 +765,16 @@ apoint_update_panel (int which_pan)
win[APP].y + win[APP].h - 2 * bordr,
win[APP].x + win[APP].w - 3 * bordr);
}
void
apoint_paste_item (void)
{
long bkp_time, bkp_start;
bkp_time = get_item_time (bkp_cut_apoint.start);
bkp_start = calendar_get_slctd_day_sec () + bkp_time;
(void)apoint_new (bkp_cut_apoint.mesg, bkp_cut_apoint.note,
bkp_start, bkp_cut_apoint.dur,
bkp_cut_apoint.state);
apoint_free_bkp ();
}

View File

@ -1,8 +1,8 @@
/* $calcurse: apoint.h,v 1.15 2008/12/28 13:13:59 culot Exp $ */
/* $calcurse: apoint.h,v 1.16 2009/01/01 17:50:41 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2008 Frederic Culot
* Copyright (c) 2004-2009 Frederic Culot
*
* 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
@ -59,6 +59,7 @@ apoint_llist_t;
extern apoint_llist_t *alist_p;
void apoint_free_bkp (void);
void apoint_llist_init (void);
void apoint_llist_free (void);
void apoint_hilt_set (int);
@ -68,6 +69,8 @@ int apoint_hilt (void);
apoint_llist_node_t *apoint_new (char *, char *, long, long, char);
void apoint_add (void);
void apoint_delete (conf_t *, unsigned *, unsigned *);
void apoint_cut (unsigned *, unsigned *);
void apoint_paste (unsigned *, unsigned *);
unsigned apoint_inday (apoint_llist_node_t *, long);
void apoint_sec2str (apoint_llist_node_t *, int, long, char *,
char *);
@ -81,5 +84,6 @@ struct notify_app_s *apoint_check_next (struct notify_app_s *, long);
apoint_llist_node_t *apoint_recur_s2apoint_s (recur_apoint_llist_node_t *);
void apoint_switch_notify (void);
void apoint_update_panel (int);
void apoint_paste_item (void);
#endif /* CALCURSE_APOINT_H */

View File

@ -1,4 +1,4 @@
/* $calcurse: calcurse.c,v 1.75 2008/12/28 19:41:45 culot Exp $ */
/* $calcurse: calcurse.c,v 1.76 2009/01/01 17:50:41 culot Exp $ */
/*
* Calcurse - text-based organizer
@ -332,6 +332,22 @@ main (int argc, char **argv)
do_storage = true;
break;
case KEY_GENERIC_CUT:
if (wins_slctd () == APP && apoint_hilt () != 0)
{
apoint_cut (&inday.nb_events, &inday.nb_apoints);
do_storage = true;
}
break;
case KEY_GENERIC_PASTE:
if (wins_slctd () == APP)
{
apoint_paste (&inday.nb_events, &inday.nb_apoints);
do_storage = true;
}
break;
case KEY_REPEAT_ITEM:
if (wins_slctd () == APP && apoint_hilt () != 0)
recur_repeat_item (&conf);

View File

@ -1,8 +1,8 @@
/* $calcurse: day.c,v 1.44 2008/12/28 19:41:45 culot Exp $ */
/* $calcurse: day.c,v 1.45 2009/01/01 17:50:41 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2008 Frederic Culot
* Copyright (c) 2004-2009 Frederic Culot
*
* 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
@ -38,8 +38,9 @@
#include "mem.h"
#include "day.h"
static struct day_item_s *day_items_ptr;
static struct day_saved_item_s *day_saved_item;
static struct day_item_s *day_items_ptr;
static struct day_saved_item_s *day_saved_item;
static int cut_item_type;
void
day_saved_item_init (void)
@ -899,6 +900,71 @@ day_erase_item (long date, int item_number, erase_flag_e flag)
return (p->type);
}
/* Cut an item so it can be pasted somewhere else later. */
int
day_cut_item (long date, int item_number)
{
const int DELETE_WHOLE = 1;
struct day_item_s *p;
p = day_get_item (item_number);
switch (p->type)
{
case EVNT:
event_delete_bynum (date, day_item_nb (date, item_number, EVNT),
ERASE_CUT);
break;
case RECUR_EVNT:
recur_event_erase (date, day_item_nb (date, item_number, RECUR_EVNT),
DELETE_WHOLE, ERASE_CUT);
break;
case APPT:
apoint_delete_bynum (date, day_item_nb (date, item_number, APPT),
ERASE_CUT);
break;
case RECUR_APPT:
recur_apoint_erase (date, p->appt_pos, DELETE_WHOLE, ERASE_CUT);
break;
default:
EXIT (_("unknwon type"));
/* NOTREACHED */
}
cut_item_type = p->type;
return cut_item_type;
}
/* Paste a previously cut item. */
int
day_paste_item (long date)
{
int pasted_item_type;
pasted_item_type = cut_item_type;
switch (cut_item_type)
{
case 0:
return 0;
case EVNT:
event_paste_item ();
break;
case RECUR_EVNT:
recur_event_paste_item ();
break;
case APPT:
apoint_paste_item ();
break;
case RECUR_APPT:
recur_apoint_paste_item ();
break;
default:
EXIT (_("unknwon type"));
/* NOTREACHED */
}
cut_item_type = 0;
return pasted_item_type;
}
/* Returns a structure containing the selected item. */
struct day_item_s *
day_get_item (int item_number)

View File

@ -1,4 +1,4 @@
/* $calcurse: day.h,v 1.20 2008/12/28 13:13:59 culot Exp $ */
/* $calcurse: day.h,v 1.21 2009/01/01 17:50:41 culot Exp $ */
/*
* Calcurse - text-based organizer
@ -76,6 +76,8 @@ void day_popup_item (void);
int day_check_if_item (date_t);
void day_edit_item (conf_t *);
int day_erase_item (long, int, erase_flag_e);
int day_cut_item (long, int);
int day_paste_item (long);
struct day_item_s *day_get_item (int);
int day_item_nb (long, int, int);
void day_edit_note (char *);

View File

@ -1,8 +1,8 @@
/* $calcurse: event.c,v 1.9 2008/12/28 13:13:59 culot Exp $ */
/* $calcurse: event.c,v 1.10 2009/01/01 17:50:41 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2008 Frederic Culot
* Copyright (c) 2004-2009 Frederic Culot
*
* 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
@ -34,7 +34,52 @@
#include "mem.h"
#include "event.h"
struct event_s *eventlist;
struct event_s *eventlist;
static struct event_s bkp_cut_event;
void
event_free_bkp (void)
{
if (bkp_cut_event.mesg)
{
mem_free (bkp_cut_event.mesg);
bkp_cut_event.mesg = 0;
}
if (bkp_cut_event.note)
{
mem_free (bkp_cut_event.note);
bkp_cut_event.note = 0;
}
}
static void
event_dup (struct event_s *in, struct event_s *bkp)
{
EXIT_IF (!in || !bkp, _("null pointer"));
bkp->id = in->id;
bkp->day = in->day;
bkp->mesg = mem_strdup (in->mesg);
if (in->note)
bkp->note = mem_strdup (in->note);
}
void
event_llist_free (void)
{
struct event_s *o, **i;
i = &eventlist;
for (o = eventlist; o; o = o->next)
{
*i = o->next;
mem_free (o->mesg);
if (o->note)
mem_free (o->note);
mem_free (o);
i = &(*i)->next;
}
}
/* Create a new event */
struct event_s *
@ -154,15 +199,25 @@ event_delete_bynum (long start, unsigned num, erase_flag_e flag)
{
if (n == num)
{
if (flag == ERASE_FORCE_ONLY_NOTE)
erase_note (&i->note, flag);
else
{
switch (flag)
{
case ERASE_FORCE_ONLY_NOTE:
erase_note (&i->note, flag);
break;
case ERASE_CUT:
event_free_bkp ();
event_dup (i, &bkp_cut_event);
if (i->note)
mem_free (i->note);
/* FALLTHROUGH */
default:
*iptr = i->next;
mem_free (i->mesg);
erase_note (&i->note, flag);
if (flag != ERASE_FORCE_KEEP_NOTE && flag != ERASE_CUT)
erase_note (&i->note, flag);
mem_free (i);
}
break;
}
return;
}
n++;
@ -172,3 +227,12 @@ event_delete_bynum (long start, unsigned num, erase_flag_e flag)
EXIT (_("event not found"));
/* NOTREACHED */
}
void
event_paste_item (void)
{
(void)event_new (bkp_cut_event.mesg, bkp_cut_event.note,
date2sec (*calendar_get_slctd_day (), 12, 0),
bkp_cut_event.id);
event_free_bkp ();
}

View File

@ -1,8 +1,8 @@
/* $calcurse: event.h,v 1.6 2008/04/12 21:14:03 culot Exp $ */
/* $calcurse: event.h,v 1.7 2009/01/01 17:50:41 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2008 Frederic Culot
* Copyright (c) 2004-2009 Frederic Culot
*
* 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
@ -43,11 +43,14 @@ struct event_s
extern struct event_s *eventlist;
void event_free_bkp (void);
void event_llist_free (void);
struct event_s *event_new (char *, char *, long, int);
unsigned event_inday (struct event_s *, long);
void event_write (struct event_s *, FILE *);
struct event_s *event_scan (FILE *, struct tm, int, char *);
struct event_s *event_get (long, int);
void event_delete_bynum (long, unsigned, erase_flag_e);
void event_paste_item (void);
#endif /* CALCURSE_EVENT_H */

View File

@ -1,8 +1,8 @@
/* $calcurse: io.c,v 1.51 2008/12/28 19:41:45 culot Exp $ */
/* $calcurse: io.c,v 1.52 2009/01/01 17:50:41 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2008 Frederic Culot
* Copyright (c) 2004-2009 Frederic Culot
*
* 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
@ -995,7 +995,7 @@ io_load_app (void)
FILE *data_file;
int c, is_appointment, is_event, is_recursive;
struct tm start, end, until, *lt;
struct days_s *exc = NULL;
struct days_s *exc;
time_t t;
int id = 0;
int freq;
@ -1009,6 +1009,7 @@ io_load_app (void)
data_file = fopen (path_apts, "r");
for (;;)
{
exc = 0;
is_appointment = is_event = is_recursive = 0;
c = getc (data_file);
if (c == EOF)
@ -1144,7 +1145,7 @@ io_load_app (void)
if (is_recursive)
{
recur_apoint_scan (data_file, start, end,
type, freq, until, notep, exc, state);
type, freq, until, notep, &exc, state);
}
else
{
@ -1156,7 +1157,7 @@ io_load_app (void)
if (is_recursive)
{
recur_event_scan (data_file, start, id, type,
freq, until, notep, exc);
freq, until, notep, &exc);
}
else
{
@ -1395,6 +1396,8 @@ io_load_keys (char *pager)
EXIT_IF (skipped > MAX_ERRORS,
_("Too many errors while reading keys file, aborting..."));
if (loaded < NBKEYS)
keys_fill_missing ();
if (keys_check_missing_bindings ())
ERROR_MSG (_("Some actions do not have any associated key bindings!"));
#undef HSIZE
}
@ -1627,7 +1630,7 @@ ical_store_event (char *mesg, char *note, long day, ical_rpt_t *rpt,
if (rpt != NULL)
{
recur_event_new (mesg, note, day, EVENTID, rpt->type, rpt->freq,
rpt->until, exc);
rpt->until, &exc);
mem_free (rpt);
}
else
@ -1649,7 +1652,7 @@ ical_store_apoint (char *mesg, char *note, long start, long dur,
if (rpt != NULL)
{
recur_apoint_new (mesg, note, start, dur, state, rpt->type, rpt->freq,
rpt->until, exc);
rpt->until, &exc);
mem_free (rpt);
}
else

View File

@ -1,4 +1,4 @@
/* $calcurse: keys.c,v 1.11 2008/12/28 13:13:59 culot Exp $ */
/* $calcurse: keys.c,v 1.12 2009/01/01 17:50:41 culot Exp $ */
/*
* Calcurse - text-based organizer
@ -56,6 +56,8 @@ static struct keydef_s keydef[NBKEYS] = {
{"generic-help", "?"},
{"generic-quit", "q Q"},
{"generic-save", "s S C-s"},
{"generic-cut", "C-x"},
{"generic-paste", "C-v"},
{"generic-change-view", "TAB"},
{"generic-import", "i I"},
{"generic-export", "x X"},
@ -591,3 +593,41 @@ keys_check_missing_bindings (void)
}
return 0;
}
void
keys_fill_missing (void)
{
int i;
for (i = 0; i < NBKEYS; i++)
{
if (keys[i] == 0)
{
char *p, tmpbuf[BUFSIZ];
(void)strncpy (tmpbuf, keydef[i].binding, BUFSIZ);
p = tmpbuf;
for (;;)
{
char key_ch[BUFSIZ];
while (*p == ' ')
p++;
if (sscanf (p, "%s", key_ch) == 1)
{
int ch, used;
ch = keys_str2int (key_ch);
used = keys_assign_binding (ch, i);
if (used)
ERROR_MSG (_("When adding default key for \"%s\", "
"\"%s\" was already assigned!"),
keydef[i].label, key_ch);
p += strlen (key_ch) + 1;
}
else
break;
}
}
}
}

View File

@ -1,4 +1,4 @@
/* $calcurse: keys.h,v 1.7 2008/12/28 13:13:59 culot Exp $ */
/* $calcurse: keys.h,v 1.8 2009/01/01 17:50:41 culot Exp $ */
/*
* Calcurse - text-based organizer
@ -27,7 +27,7 @@
#ifndef CALCURSE_KEYS_H
#define CALCURSE_KEYS_H
#define CTRLVAL 0x1F
#define CTRLVAL 0x1F
#define CTRL(x) ((x) & CTRLVAL)
#define ESCAPE 27
#define TAB 9
@ -45,6 +45,8 @@ typedef enum
KEY_GENERIC_HELP,
KEY_GENERIC_QUIT,
KEY_GENERIC_SAVE,
KEY_GENERIC_CUT,
KEY_GENERIC_PASTE,
KEY_GENERIC_CHANGE_VIEW,
KEY_GENERIC_IMPORT,
KEY_GENERIC_EXPORT,
@ -107,5 +109,6 @@ void keys_display_bindings_bar (WINDOW *, binding_t **, int, int);
void keys_popup_info (keys_e);
void keys_save_bindings (FILE *);
int keys_check_missing_bindings (void);
void keys_fill_missing (void);
#endif /* CALCURSE_KEYS_H */

View File

@ -1,8 +1,8 @@
/* $calcurse: recur.c,v 1.46 2008/12/28 13:13:59 culot Exp $ */
/* $calcurse: recur.c,v 1.47 2009/01/01 17:50:41 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2008 Frederic Culot
* Copyright (c) 2004-2009 Frederic Culot
*
* 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
@ -38,8 +38,147 @@
#include "mem.h"
#include "recur.h"
recur_apoint_llist_t *recur_alist_p;
struct recur_event_s *recur_elist;
recur_apoint_llist_t *recur_alist_p;
struct recur_event_s *recur_elist;
static struct recur_event_s bkp_cut_recur_event;
static recur_apoint_llist_node_t bkp_cut_recur_apoint;
static void
free_exc (struct days_s **exc)
{
struct days_s *o, **i;
i = exc;
for (o = *exc; o; o = o->next)
{
*i = o->next;
mem_free (o);
i = &(*i)->next;
}
*exc = 0;
}
static void
recur_add_exc (struct days_s **exc, long day)
{
struct days_s **i, *o;
o = mem_malloc (sizeof (struct days_s));
o->st = day;
i = exc;
for (;;)
{
if (*i == 0 || (*i)->st > day)
{
o->next = *i;
*i = o;
break;
}
i = &(*i)->next;
}
}
static void
exc_dup (struct days_s **in, struct days_s *exc)
{
struct days_s *p;
for (p = exc; p; p = p->next)
recur_add_exc (in, p->st);
}
void
recur_event_free_bkp (void)
{
if (bkp_cut_recur_event.mesg)
{
mem_free (bkp_cut_recur_event.mesg);
bkp_cut_recur_event.mesg = 0;
}
if (bkp_cut_recur_event.note)
{
mem_free (bkp_cut_recur_event.note);
bkp_cut_recur_event.note = 0;
}
if (bkp_cut_recur_event.rpt)
{
mem_free (bkp_cut_recur_event.rpt);
bkp_cut_recur_event.rpt = 0;
}
if (bkp_cut_recur_event.exc)
{
free_exc (&bkp_cut_recur_event.exc);
bkp_cut_recur_event.exc = 0;
}
}
void
recur_apoint_free_bkp (void)
{
if (bkp_cut_recur_apoint.mesg)
{
mem_free (bkp_cut_recur_apoint.mesg);
bkp_cut_recur_apoint.mesg = 0;
}
if (bkp_cut_recur_apoint.note)
{
mem_free (bkp_cut_recur_apoint.note);
bkp_cut_recur_apoint.note = 0;
}
if (bkp_cut_recur_apoint.rpt)
{
mem_free (bkp_cut_recur_apoint.rpt);
bkp_cut_recur_apoint.rpt = 0;
}
if (bkp_cut_recur_apoint.exc)
{
free_exc (&bkp_cut_recur_apoint.exc);
bkp_cut_recur_apoint.exc = 0;
}
}
static void
recur_event_dup (struct recur_event_s *in, struct recur_event_s *bkp)
{
EXIT_IF (!in || !bkp, _("null pointer"));
bkp->id = in->id;
bkp->day = in->day;
bkp->mesg = mem_strdup (in->mesg);
bkp->rpt = mem_malloc (sizeof (struct rpt_s));
bkp->rpt->type = in->rpt->type;
bkp->rpt->freq = in->rpt->freq;
bkp->rpt->until = in->rpt->until;
if (in->exc)
exc_dup (&bkp->exc, in->exc);
if (in->note)
bkp->note = mem_strdup (in->note);
}
static void
recur_apoint_dup (recur_apoint_llist_node_t *in, recur_apoint_llist_node_t *bkp)
{
EXIT_IF (!in || !bkp, _("null pointer"));
bkp->start = in->start;
bkp->dur = in->dur;
bkp->state = in->state;
bkp->mesg = mem_strdup (in->mesg);
bkp->rpt = mem_malloc (sizeof (struct rpt_s));
bkp->rpt->type = in->rpt->type;
bkp->rpt->freq = in->rpt->freq;
bkp->rpt->until = in->rpt->until;
if (in->exc)
exc_dup (&bkp->exc, in->exc);
if (in->note)
bkp->note = mem_strdup (in->note);
}
void
recur_apoint_llist_init (void)
@ -49,21 +188,6 @@ recur_apoint_llist_init (void)
pthread_mutex_init (&(recur_alist_p->mutex), NULL);
}
static void
free_exc (struct days_s *exc)
{
struct days_s *o, **i;
i = &exc;
for (o = exc; o; o = o->next)
{
*i = o->next;
mem_free (o);
i = &(*i)->next;
}
mem_free (exc);
}
void
recur_apoint_llist_free (void)
{
@ -79,31 +203,63 @@ recur_apoint_llist_free (void)
if (o->rpt)
mem_free (o->rpt);
if (o->exc)
free_exc (o->exc);
{
free_exc (&o->exc);
o->exc = 0;
}
mem_free (o);
i = &(*i)->next;
}
mem_free (recur_alist_p);
}
void
recur_event_llist_free (void)
{
struct recur_event_s *o, **i;
i = &recur_elist;
for (o = recur_elist; o; o = o->next)
{
*i = o->next;
mem_free (o->mesg);
if (o->note)
mem_free (o->note);
if (o->rpt)
mem_free (o->rpt);
if (o->exc)
{
free_exc (&o->exc);
o->exc = 0;
}
mem_free (o);
i = &(*i)->next;
}
}
/* Insert a new recursive appointment in the general linked list */
recur_apoint_llist_node_t *
recur_apoint_new (char *mesg, char *note, long start, long dur, char state,
int type, int freq, long until, struct days_s *except)
int type, int freq, long until, struct days_s **except)
{
recur_apoint_llist_node_t *o, **i;
o = (recur_apoint_llist_node_t *)
mem_malloc (sizeof (recur_apoint_llist_node_t));
o->rpt = (struct rpt_s *) mem_malloc (sizeof (struct rpt_s));
o = mem_malloc (sizeof (recur_apoint_llist_node_t));
o->rpt = mem_malloc (sizeof (struct rpt_s));
o->mesg = mem_strdup (mesg);
o->note = (note != NULL) ? strdup (note) : NULL;
o->note = (note != 0) ? strdup (note) : 0;
o->start = start;
o->state = state;
o->dur = dur;
o->rpt->type = type;
o->rpt->freq = freq;
o->rpt->until = until;
o->exc = except;
o->exc = 0;
if (except && *except)
{
exc_dup (&o->exc, *except);
free_exc (except);
}
pthread_mutex_lock (&(recur_alist_p->mutex));
i = &recur_alist_p->root;
@ -125,19 +281,26 @@ recur_apoint_new (char *mesg, char *note, long start, long dur, char state,
/* Insert a new recursive event in the general linked list */
struct recur_event_s *
recur_event_new (char *mesg, char *note, long day, int id, int type, int freq,
long until, struct days_s *except)
long until, struct days_s **except)
{
struct recur_event_s *o, **i;
o = (struct recur_event_s *) mem_malloc (sizeof (struct recur_event_s));
o->rpt = (struct rpt_s *) mem_malloc (sizeof (struct rpt_s));
o = mem_malloc (sizeof (struct recur_event_s));
o->rpt = mem_malloc (sizeof (struct rpt_s));
o->mesg = mem_strdup (mesg);
(void)strncpy (o->mesg, mesg, strlen (mesg) + 1);
o->note = (note != 0) ? strdup (note) : 0;
o->day = day;
o->id = id;
o->rpt->type = type;
o->rpt->freq = freq;
o->rpt->until = until;
o->exc = except;
o->exc = 0;
if (except && *except)
{
exc_dup (&o->exc, *except);
free_exc (except);
}
i = &recur_elist;
for (;;)
{
@ -236,7 +399,7 @@ recur_write_exc (struct days_s *exc, FILE *f)
/* Load the recursive appointment description */
recur_apoint_llist_node_t *
recur_apoint_scan (FILE *f, struct tm start, struct tm end, char type,
int freq, struct tm until, char *note, struct days_s *exc,
int freq, struct tm until, char *note, struct days_s **exc,
char state)
{
struct tm *lt;
@ -286,14 +449,10 @@ recur_apoint_scan (FILE *f, struct tm start, struct tm end, char type,
/* Load the recursive events from file */
struct recur_event_s *
recur_event_scan (FILE *f, struct tm start, int id, char type, int freq,
struct tm until, char *note, struct days_s *exc)
struct tm until, char *note, struct days_s **exc)
{
struct tm *lt;
char buf[MESG_MAXSIZE], *nl;
time_t tstart, t, tuntil;
t = time (NULL);
lt = localtime (&t);
time_t tstart, tuntil;
/* Read the event description */
(void)fgets (buf, MESG_MAXSIZE, f);
@ -322,8 +481,8 @@ recur_event_scan (FILE *f, struct tm start, int id, char type, int freq,
EXIT_IF (tstart == -1 || tuntil == -1,
_("date error in event"));
return (recur_event_new (buf, note, tstart, id, recur_char2def (type),
freq, tuntil, exc));
return recur_event_new (buf, note, tstart, id, recur_char2def (type),
freq, tuntil, exc);
}
/* Writting of a recursive appointment into file. */
@ -519,7 +678,6 @@ recur_event_erase (long start, unsigned num, unsigned delete_whole,
{
unsigned n = 0;
struct recur_event_s *i, **iptr;
struct days_s *o, **j;
iptr = &recur_elist;
for (i = recur_elist; i != 0; i = i->next)
@ -531,34 +689,33 @@ recur_event_erase (long start, unsigned num, unsigned delete_whole,
{
if (delete_whole)
{
if (flag == ERASE_FORCE_ONLY_NOTE)
erase_note (&i->note, flag);
else
{
switch (flag)
{
case ERASE_FORCE_ONLY_NOTE:
erase_note (&i->note, flag);
break;
case ERASE_CUT:
recur_event_free_bkp ();
recur_event_dup (i, &bkp_cut_recur_event);
if (i->note)
mem_free (i->note);
/* FALLTHROUGH */
default:
*iptr = i->next;
mem_free (i->mesg);
mem_free (i->rpt);
mem_free (i->exc);
erase_note (&i->note, flag);
free_exc (&i->exc);
i->exc = 0;
if (flag != ERASE_FORCE_KEEP_NOTE && flag != ERASE_CUT)
erase_note (&i->note, flag);
mem_free (i);
break;
}
return;
}
else
{
o = (struct days_s *) mem_malloc (sizeof (struct days_s));
o->st = start;
j = &i->exc;
for (;;)
{
if (*j == 0 || (*j)->st > start)
{
o->next = *j;
*j = o;
break;
}
j = &(*j)->next;
}
recur_add_exc (&i->exc, start);
return;
}
}
@ -580,7 +737,6 @@ recur_apoint_erase (long start, unsigned num, unsigned delete_whole,
{
unsigned n = 0;
recur_apoint_llist_node_t *i, **iptr;
struct days_s *o, **j;
int need_check_notify = 0;
pthread_mutex_lock (&(recur_alist_p->mutex));
@ -596,37 +752,36 @@ recur_apoint_erase (long start, unsigned num, unsigned delete_whole,
need_check_notify = notify_same_recur_item (i);
if (delete_whole)
{
if (flag == ERASE_FORCE_ONLY_NOTE)
erase_note (&i->note, flag);
else
{
switch (flag)
{
case ERASE_FORCE_ONLY_NOTE:
erase_note (&i->note, flag);
break;
case ERASE_CUT:
recur_apoint_free_bkp ();
recur_apoint_dup (i, &bkp_cut_recur_apoint);
if (i->note)
mem_free (i->note);
/* FALLTHROUGH */
default:
*iptr = i->next;
mem_free (i->mesg);
mem_free (i->rpt);
mem_free (i->exc);
erase_note (&i->note, flag);
free_exc (&i->exc);
i->exc = 0;
if (flag != ERASE_FORCE_KEEP_NOTE && flag != ERASE_CUT)
erase_note (&i->note, flag);
mem_free (i);
pthread_mutex_unlock (&(recur_alist_p->mutex));
if (need_check_notify)
notify_check_next_app ();
break;
}
return;
}
else
{
o = (struct days_s *) mem_malloc (sizeof (struct days_s));
o->st = start;
j = &i->exc;
for (;;)
{
if (*j == 0 || (*j)->st > start)
{
o->next = *j;
*j = o;
break;
}
j = &(*j)->next;
}
recur_add_exc (&i->exc, start);
pthread_mutex_unlock (&(recur_alist_p->mutex));
if (need_check_notify)
notify_check_next_app ();
@ -800,14 +955,10 @@ struct days_s *
recur_exc_scan (FILE *data_file)
{
int c = 0;
struct tm *lt, day;
time_t t;
struct tm day;
struct days_s *exc_head, *exc;
exc_head = NULL;
t = time (NULL);
lt = localtime (&t);
day = *lt;
exc_head = 0;
while ((c = getc (data_file)) == '!')
{
(void)ungetc (c, data_file);
@ -816,16 +967,17 @@ recur_exc_scan (FILE *data_file)
{
EXIT (_("syntax error in item date"));
}
day.tm_sec = 0;
day.tm_hour = 12;
day.tm_min = day.tm_sec = 0;
day.tm_isdst = -1;
day.tm_year -= 1900;
day.tm_mon--;
exc = (struct days_s *) mem_malloc (sizeof (struct days_s));
exc = mem_malloc (sizeof (struct days_s));
exc->st = mktime (&day);
exc->next = exc_head;
exc_head = exc;
}
return (exc_head);
return exc_head;
}
/*
@ -950,3 +1102,61 @@ recur_apoint_switch_notify (long date, int recur_nb)
/* NOTREACHED */
}
void
recur_event_paste_item (void)
{
long new_start, time_shift;
new_start = date2sec (*calendar_get_slctd_day (), 12, 0);
time_shift = new_start - bkp_cut_recur_event.day;
bkp_cut_recur_event.day += time_shift;
if (bkp_cut_recur_event.rpt->until != 0)
bkp_cut_recur_event.rpt->until += time_shift;
if (bkp_cut_recur_event.exc)
{
struct days_s *exc;
for (exc = bkp_cut_recur_event.exc; exc != 0; exc = exc->next)
exc->st += time_shift;
}
(void)recur_event_new (bkp_cut_recur_event.mesg, bkp_cut_recur_event.note,
bkp_cut_recur_event.day, bkp_cut_recur_event.id,
bkp_cut_recur_event.rpt->type,
bkp_cut_recur_event.rpt->freq,
bkp_cut_recur_event.rpt->until,
&bkp_cut_recur_event.exc);
recur_event_free_bkp ();
}
void
recur_apoint_paste_item (void)
{
long new_start, time_shift;
new_start = date2sec (*calendar_get_slctd_day (),
get_item_hour (bkp_cut_recur_apoint.start),
get_item_min (bkp_cut_recur_apoint.start));
time_shift = new_start - bkp_cut_recur_apoint.start;
bkp_cut_recur_apoint.start += time_shift;
if (bkp_cut_recur_apoint.rpt->until != 0)
bkp_cut_recur_apoint.rpt->until += time_shift;
if (bkp_cut_recur_apoint.exc)
{
struct days_s *exc;
for (exc = bkp_cut_recur_apoint.exc; exc != 0; exc = exc->next)
exc->st += time_shift;
}
(void)recur_apoint_new (bkp_cut_recur_apoint.mesg, bkp_cut_recur_apoint.note,
bkp_cut_recur_apoint.start, bkp_cut_recur_apoint.dur,
bkp_cut_recur_apoint.state,
bkp_cut_recur_apoint.rpt->type,
bkp_cut_recur_apoint.rpt->freq,
bkp_cut_recur_apoint.rpt->until,
&bkp_cut_recur_apoint.exc);
recur_apoint_free_bkp ();
}

View File

@ -1,8 +1,8 @@
/* $calcurse: recur.h,v 1.24 2008/12/28 13:13:59 culot Exp $ */
/* $calcurse: recur.h,v 1.25 2009/01/01 17:50:41 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2008 Frederic Culot
* Copyright (c) 2004-2009 Frederic Culot
*
* 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
@ -86,20 +86,23 @@ typedef void (*recur_cb_foreach_date_t)(FILE *, long, char *);
extern recur_apoint_llist_t *recur_alist_p;
extern struct recur_event_s *recur_elist;
void recur_event_free_bkp (void);
void recur_apoint_free_bkp (void);
void recur_apoint_llist_init (void);
void recur_apoint_llist_free (void);
void recur_event_llist_free (void);
recur_apoint_llist_node_t *recur_apoint_new (char *, char *, long, long, char,
int, int, long, struct days_s *);
int, int, long, struct days_s **);
struct recur_event_s *recur_event_new (char *, char *, long, int, int, int,
long, struct days_s *);
long, struct days_s **);
char recur_def2char (recur_types_t);
int recur_char2def (char);
recur_apoint_llist_node_t *recur_apoint_scan (FILE *, struct tm, struct tm,
char, int, struct tm, char *,
struct days_s *, char);
struct days_s **, char);
struct recur_event_s *recur_event_scan (FILE *, struct tm, int, char,
int, struct tm, char *,
struct days_s *);
struct days_s **);
void recur_save_data (FILE *);
unsigned recur_item_inday (long, struct days_s *, int, int,
long, long);
@ -114,5 +117,7 @@ struct notify_app_s *recur_apoint_check_next (struct notify_app_s *,
recur_apoint_llist_node_t *recur_get_apoint (long, int);
struct recur_event_s *recur_get_event (long, int);
void recur_apoint_switch_notify (long, int);
void recur_event_paste_item (void);
void recur_apoint_paste_item (void);
#endif /* CALCURSE_RECUR_H */

View File

@ -1,8 +1,8 @@
/* $calcurse: utils.c,v 1.63 2008/12/28 19:41:45 culot Exp $ */
/* $calcurse: utils.c,v 1.64 2009/01/01 17:50:41 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2008 Frederic Culot
* Copyright (c) 2004-2009 Frederic Culot
*
* 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
@ -42,6 +42,7 @@
#include "keys.h"
#include "io.h"
#include "recur.h"
#include "event.h"
#include "apoint.h"
#include "todo.h"
#include "day.h"
@ -50,7 +51,7 @@
#include "mem.h"
#define NB_CAL_CMDS 24 /* number of commands while in cal view */
#define NB_APP_CMDS 29 /* same thing while in appointment view */
#define NB_APP_CMDS 31 /* same thing while in appointment view */
#define NB_TOD_CMDS 29 /* same thing while in todo view */
#define TOTAL_CMDS NB_CAL_CMDS + NB_APP_CMDS + NB_TOD_CMDS
#define CMDS_PER_LINE 6 /* max number of commands per line */
@ -75,8 +76,14 @@ exit_calcurse (int status)
notify_free_bar ();
day_saved_item_free ();
day_free_list ();
event_llist_free ();
event_free_bkp ();
apoint_llist_free ();
apoint_free_bkp ();
recur_apoint_llist_free ();
recur_event_llist_free ();
recur_apoint_free_bkp ();
recur_event_free_bkp ();
todo_free_list ();
keys_free ();
mem_stats ();
@ -415,7 +422,7 @@ is_all_digit (char *string)
digit++;
if (digit == strlen (string))
all_digit = 1;
return (all_digit);
return all_digit;
}
/*
@ -436,6 +443,8 @@ status_bar (void)
binding_t help = {_("Help"), KEY_GENERIC_HELP};
binding_t quit = {_("Quit"), KEY_GENERIC_QUIT};
binding_t save = {_("Save"), KEY_GENERIC_SAVE};
binding_t cut = {_("Cut"), KEY_GENERIC_CUT};
binding_t paste = {_("Paste"), KEY_GENERIC_PASTE};
binding_t chgvu = {_("Chg View"), KEY_GENERIC_CHANGE_VIEW};
binding_t import = {_("Import"), KEY_GENERIC_IMPORT};
binding_t export = {_("Export"), KEY_GENERIC_EXPORT};
@ -465,7 +474,8 @@ status_bar (void)
binding_t enote = {_("EditNote"), KEY_EDIT_NOTE};
binding_t vnote = {_("ViewNote"), KEY_VIEW_NOTE};
binding_t rprio = {_("Prio.+"), KEY_RAISE_PRIORITY};
binding_t lprio = {_("Prio.-"), KEY_LOWER_PRIORITY};
binding_t lprio = {_("Prio.-"), KEY_LOWER_PRIORITY};
binding_t *binding[TOTAL_CMDS] = {
/* calendar keys */
@ -475,7 +485,8 @@ status_bar (void)
/* appointment keys */
&help, &quit, &save, &chgvu, &import, &export, &add, &del, &edit, &view,
&draw, &othr, &rept, &flag, &enote, &vnote, &up, &down, &gnday, &gpday,
&gnweek, &gpweek, &togo, &othr, &today, &conf, &appt, &todo, &othr,
&gnweek, &gpweek, &togo, &othr, &today, &conf, &appt, &todo, &cut, &paste,
&othr,
/* todo keys */
&help, &quit, &save, &chgvu, &import, &export, &add, &del, &edit, &view,
&draw, &othr, &rprio, &lprio, &enote, &vnote, &up, &down, &gnday, &gpday,
@ -489,6 +500,38 @@ status_bar (void)
keys_display_bindings_bar (win[STA].p, binding, start, end);
}
/* Given an item date expressed in seconds, return its start time in seconds. */
long
get_item_time (long date)
{
return (long)(get_item_hour (date) * HOURINSEC
+ get_item_min (date) * MININSEC);
}
int
get_item_hour (long date)
{
struct tm *lt;
time_t t;
t = (time_t)date;
lt = localtime (&t);
return lt->tm_hour;
}
int
get_item_min (long date)
{
struct tm *lt;
time_t t;
t = (time_t)date;
lt = localtime (&t);
return lt->tm_min;
}
long
date2sec (date_t day, unsigned hour, unsigned min)
{
@ -511,7 +554,7 @@ date2sec (date_t day, unsigned hour, unsigned min)
tstart = mktime (&start);
EXIT_IF (tstart == -1, _("failure in mktime"));
return (tstart);
return tstart;
}
/* Return a string containing the hour of a given date in seconds. */
@ -527,7 +570,7 @@ date_sec2hour_str (long sec)
lt = localtime (&t);
timestr = (char *) mem_malloc (TIME_LEN);
(void)snprintf (timestr, TIME_LEN, "%02u:%02u", lt->tm_hour, lt->tm_min);
return (timestr);
return timestr;
}
/* Return a string containing the date, given a date in seconds. */

View File

@ -1,8 +1,8 @@
/* $calcurse: utils.h,v 1.41 2008/12/28 13:13:59 culot Exp $ */
/* $calcurse: utils.h,v 1.42 2009/01/01 17:50:41 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2008 Frederic Culot
* Copyright (c) 2004-2009 Frederic Culot
*
* 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
@ -96,42 +96,46 @@ typedef enum
ERASE_DONT_FORCE,
ERASE_FORCE,
ERASE_FORCE_KEEP_NOTE,
ERASE_FORCE_ONLY_NOTE
ERASE_FORCE_ONLY_NOTE,
ERASE_CUT
}
erase_flag_e;
void exit_calcurse (int);
void fatalbox (const char *);
void status_mesg (char *, char *);
void erase_status_bar (void);
void erase_window_part (WINDOW *, int, int, int, int);
WINDOW *popup (int, int, int, int, char *, char *, int);
void print_in_middle (WINDOW *, int, int, int, char *);
int getstring (WINDOW *, char *, int, int, int);
int updatestring (WINDOW *, char **, int, int);
int is_all_digit (char *);
void status_bar (void);
long date2sec (date_t, unsigned, unsigned);
char *date_sec2hour_str (long);
char *date_sec2date_str (long, char *);
void date_sec2date_fmt (long, const char *, char *);
long date_sec_change (long, int, int);
long update_time_in_date (long, unsigned, unsigned);
long get_sec_date (date_t);
long min2sec (unsigned);
int check_time (char *);
void draw_scrollbar (WINDOW *, int, int, int, int, int, bool);
void item_in_popup (char *, char *, char *, char *);
void reset_status_page (void);
void other_status_page (int);
long get_today (void);
long now (void);
long mystrtol (const char *);
void print_bool_option_incolor (WINDOW *, bool, int, int);
char *new_tempfile (const char *, int);
void erase_note (char **, erase_flag_e);
int parse_date (char *, int, int *, int *, int *);
char *str_toupper (char *);
void file_close (FILE *, const char *);
void exit_calcurse (int);
void fatalbox (const char *);
void status_mesg (char *, char *);
void erase_status_bar (void);
void erase_window_part (WINDOW *, int, int, int, int);
WINDOW *popup (int, int, int, int, char *, char *, int);
void print_in_middle (WINDOW *, int, int, int, char *);
int getstring (WINDOW *, char *, int, int, int);
int updatestring (WINDOW *, char **, int, int);
int is_all_digit (char *);
void status_bar (void);
long get_item_time (long);
int get_item_hour (long);
int get_item_min (long);
long date2sec (date_t, unsigned, unsigned);
char *date_sec2hour_str (long);
char *date_sec2date_str (long, char *);
void date_sec2date_fmt (long, const char *, char *);
long date_sec_change (long, int, int);
long update_time_in_date (long, unsigned, unsigned);
long get_sec_date (date_t);
long min2sec (unsigned);
int check_time (char *);
void draw_scrollbar (WINDOW *, int, int, int, int, int, bool);
void item_in_popup (char *, char *, char *, char *);
void reset_status_page (void);
void other_status_page (int);
long get_today (void);
long now (void);
long mystrtol (const char *);
void print_bool_option_incolor (WINDOW *, bool, int, int);
char *new_tempfile (const char *, int);
void erase_note (char **, erase_flag_e);
int parse_date (char *, int, int *, int *, int *);
char *str_toupper (char *);
void file_close (FILE *, const char *);
#endif /* CALCURSE_UTILS_H */