Initial revision

This commit is contained in:
Frederic Culot
2006-07-31 21:00:02 +00:00
commit ac36e94341
43 changed files with 10754 additions and 0 deletions

14
src/Makefile.am Executable file
View File

@@ -0,0 +1,14 @@
# $calcurse: Makefile.am,v 1.1 2006/07/31 21:00:02 culot Exp $
AUTOMAKE_OPTIONS= gnu
bin_PROGRAMS= calcurse
calcurse_SOURCES= calcurse.c apoint.c event.c todo.c utils.c\
calendar.c vars.c io.c help.c custom.c args.c\
day.c recur.c\
apoint.h event.h todo.h utils.h calendar.h\
vars.h io.h help.h custom.h args.h i18n.h\
day.h recur.h
LIBS= -lncurses -lm
LDADD= @LTLIBINTL@
man_MANS= calcurse.1
EXTRA_DIST= calcurse.1

235
src/apoint.c Executable file
View File

@@ -0,0 +1,235 @@
/* $calcurse: apoint.c,v 1.1 2006/07/31 21:00:03 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#include <ncurses.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include "i18n.h"
#include "vars.h"
#include "event.h"
#include "apoint.h"
#include "day.h"
#include "custom.h"
#include "utils.h"
struct apoint_s *apointlist;
struct apoint_s *apoint_new(char *mesg, long start, long dur)
{
struct apoint_s *o, **i;
o = (struct apoint_s *) malloc(sizeof(struct apoint_s));
o->mesg = (char *) malloc(strlen(mesg) + 1);
strcpy(o->mesg, mesg);
o->start = start;
o->dur = dur;
i = &apointlist;
for (;;) {
if (*i == 0 || (*i)->start > start) {
o->next = *i;
*i = o;
break;
}
i = &(*i)->next;
}
return o;
}
unsigned apoint_inday(struct apoint_s *i, long start)
{
if (i->start <= start + 3600 * 24 && i->start + i->dur > start) {
return 1;
}
return 0;
}
void apoint_sec2str(struct apoint_s *o, int type, long day, char *start, char *end)
{
struct tm *lt;
time_t t;
if (o->start < day && type == APPT) {
strcpy(start, "..:..");
} else {
t = o->start;
lt = localtime(&t);
snprintf(start, HRMIN_SIZE, "%02u:%02u", lt->tm_hour,
lt->tm_min);
}
if (o->start + o->dur > day + 24 * 3600 && type == APPT) {
strcpy(end, "..:..");
} else {
t = o->start + o->dur;
lt = localtime(&t);
snprintf(end, HRMIN_SIZE, "%02u:%02u", lt->tm_hour,
lt->tm_min);
}
}
void apoint_write(struct apoint_s *o, FILE * f)
{
struct tm *lt;
time_t t;
t = o->start;
lt = localtime(&t);
fprintf(f, "%02u/%02u/%04u @ %02u:%02u",
lt->tm_mon + 1, lt->tm_mday, 1900 + lt->tm_year,
lt->tm_hour, lt->tm_min);
t = o->start + o->dur;
lt = localtime(&t);
fprintf(f, " -> %02u/%02u/%04u @ %02u:%02u |%s\n",
lt->tm_mon + 1, lt->tm_mday, 1900 + lt->tm_year,
lt->tm_hour, lt->tm_min, o->mesg);
}
struct apoint_s *apoint_scan(FILE * f, struct tm start, struct tm end)
{
struct tm *lt;
char buf[MESG_MAXSIZE], *nl;
time_t tstart, tend, t;
t = time(NULL);
lt = localtime(&t);
/* Read the appointment description */
fgets(buf, MESG_MAXSIZE, f);
nl = strchr(buf, '\n');
if (nl) {
*nl = '\0';
}
start.tm_sec = end.tm_sec = 0;
start.tm_isdst = end.tm_isdst = -1;
start.tm_year -= 1900;
start.tm_mon--;
end.tm_year -= 1900;
end.tm_mon--;
tstart = mktime(&start);
tend = mktime(&end);
if (tstart == -1 || tend == -1 || tstart > tend) {
fputs(_("FATAL ERROR in apoint_scan: date error in the appointment\n"), stderr);
exit(EXIT_FAILURE);
}
return apoint_new(buf, tstart, tend - tstart);
}
void apoint_delete_bynum(long start, unsigned num)
{
unsigned n;
struct apoint_s *i, **iptr;
n = 0;
iptr = &apointlist;
for (i = apointlist; i != 0; i = i->next) {
if (apoint_inday(i, start)) {
if (n == num) {
*iptr = i->next;
free(i->mesg);
free(i);
return;
}
n++;
}
iptr = &i->next;
}
/* NOTREACHED */
fputs(_("FATAL ERROR in apoint_delete_bynum: no such appointment\n"), stderr);
exit(EXIT_FAILURE);
}
/*
* Print an item date in the appointment panel.
*/
void display_item_date(WINDOW *win, int incolor, struct apoint_s *i,
int type, long date, int y, int x)
{
char a_st[100], a_end[100];
apoint_sec2str(i, type, date, a_st, a_end);
if (incolor == 0)
custom_apply_attr(win, ATTR_HIGHEST);
mvwprintw(win, y, x, " - %s -> %s", a_st, a_end);
if (incolor == 0)
custom_remove_attr(awin, ATTR_HIGHEST);
}
/*
* Return the line number of an item (either an appointment or an event) in
* the appointment panel. This is to help the appointment scroll function
* to place beggining of the pad correctly.
*/
int get_item_line(int item_nb, int nb_events_inday)
{
int separator = 2;
int line = 0;
if (item_nb <= nb_events_inday)
line = item_nb - 1;
else
line = nb_events_inday + separator +
(item_nb - (nb_events_inday + 1))*3 - 1;
return line;
}
/*
* Update (if necessary) the first displayed pad line to make the
* appointment panel scroll down next time pnoutrefresh is called.
*/
void scroll_pad_down(int item_nb, int nb_events_inday, int win_length)
{
int pad_last_line = 0;
int item_first_line = 0, item_last_line = 0;
int borders = 6;
int awin_length = win_length - borders;
item_first_line = get_item_line(item_nb, nb_events_inday);
if (item_nb < nb_events_inday)
item_last_line = item_first_line;
else
item_last_line = item_first_line + 1;
pad_last_line = apad->first_onscreen + awin_length;
if (item_last_line >= pad_last_line)
apad->first_onscreen = item_last_line - awin_length;
}
/*
* Update (if necessary) the first displayed pad line to make the
* appointment panel scroll up next time pnoutrefresh is called.
*/
void scroll_pad_up(int item_nb, int nb_events_inday)
{
int item_first_line = 0;
item_first_line = get_item_line(item_nb, nb_events_inday);
if (item_first_line < apad->first_onscreen)
apad->first_onscreen = item_first_line;
}

56
src/apoint.h Executable file
View File

@@ -0,0 +1,56 @@
/* $calcurse: apoint.h,v 1.1 2006/07/31 21:00:03 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#ifndef CALCURSE_APOINT_H
#define CALCURSE_APOINT_H
#include <ncurses.h>
#define HRMIN_SIZE 6
#define MESG_MAXSIZE 256
struct apoint_s {
struct apoint_s *next;
long start; /* seconds since 1 jan 1970 */
long dur; /* duration of the appointment in seconds */
char *mesg;
};
extern struct apoint_s *apointlist;
struct apoint_s *apoint_new(char *, long, long);
unsigned apoint_inday(struct apoint_s *o, long start);
void apoint_sec2str(struct apoint_s *o, int type, long day, char *start, char *end);
void apoint_write(struct apoint_s *o, FILE * f);
struct apoint_s *apoint_scan(FILE * f, struct tm start, struct tm end);
void apoint_delete_bynum(long start, unsigned num);
void display_item_date(WINDOW *win, int color, struct apoint_s *i,
int type, long date, int y, int x);
int get_item_line(int item_nb, int nb_events_inday);
void scroll_pad_down(int item_nb, int nb_events_inday, int win_length);
void scroll_pad_up(int item_nb, int nb_events_inday);
#endif /* CALCURSE_APOINT_H */

431
src/args.c Executable file
View File

@@ -0,0 +1,431 @@
/* $calcurse: args.c,v 1.1 2006/07/31 21:00:03 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#include <ncurses.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include "i18n.h"
#include "utils.h"
#include "args.h"
#include "vars.h"
#include "event.h"
#include "apoint.h"
#include "recur.h"
#include "day.h"
#include "todo.h"
#include "io.h"
/*
* Parse the command-line arguments and call the appropriate
* routines to handle those arguments. Also initialize the data paths.
*/
int parse_args(int argc, char **argv, int colr)
{
int ch, add_line = 0;
int unknown_flag = 0, app_found = 0;
int aflag = 0, cflag = 0, dflag = 0, vflag = 0, hflag = 0, tflag = 0;
int non_interactive = 0, multiple_flag = 0, load_data = 0;
int no_file = 1;
char *ddate = "", *cfile = NULL;
while ((ch = getopt(argc, argv, "hvtad:c:")) != -1) {
switch (ch) {
case 'a':
aflag = 1;
multiple_flag++;
load_data++;
break;
case 'd':
dflag = 1;
multiple_flag++;
load_data++;
ddate = optarg;
break;
case 'c':
cflag = 1;
multiple_flag++;
load_data++;
cfile = optarg;
break;
case 'h':
hflag = 1;
break;
case 't':
tflag = 1;
multiple_flag++;
load_data++;
add_line = 1;
break;
case 'v':
vflag = 1;
break;
default:
usage();
usage_try();
unknown_flag = 1;
non_interactive = 1;
}
}
argc -= optind;
argv += optind;
if (argc >= 1) { /* incorrect arguments */
usage();
usage_try();
return 1;
} else {
if (unknown_flag) {
non_interactive = 1;
} else if (hflag) {
help_arg();
non_interactive = 1;
} else if (vflag) {
version_arg();
non_interactive = 1;
} else if (multiple_flag) {
if (load_data) {
io_init(cfile);
no_file = check_data_files();
if (dflag || aflag)
load_app(colr);
}
if (tflag) {
todo_arg(colr);
non_interactive = 1;
}
if (dflag) {
date_arg(ddate, add_line);
non_interactive = 1;
} else if (aflag) {
app_found = app_arg(add_line,0,0,0,0);
non_interactive = 1;
}
} else {
non_interactive = 0;
io_init(cfile);
no_file = check_data_files();
}
return non_interactive;
}
}
/*
* Print Calcurse version with a short copyright text and exit.
*/
void version_arg()
{
char vtitle[50];
char *vtext =
_("\nCopyright (c) 2004-2006 Frederic Culot.\n"
"This is free software; see the source for copying conditions.\n");
sprintf(vtitle, _("Calcurse %s - text-based organizer\n"), VERSION);
fputs(vtitle, stdout);
fputs(vtext, stdout);
}
/*
* Print the command line options and exit.
*/
void help_arg()
{
char htitle[50];
char *htext =
_("\nMiscellaneous:\n"
" -h print this help and exit.\n"
" -v print calcurse version and exit.\n"
"\nOptions:\n"
" -c <file> specify the calendar <file> to use.\n"
"\nNon-interactive:\n"
" -a print events and appointments for current day and exit.\n"
" -d <date|num> print events and appointments for <date> "
"or <num> upcoming\n\t\tdays and exit. Possible formats are: "
"'mm/dd/yyyy' or 'n'.\n"
" -t print todo list and exit.\n"
"\nFor more information, type '?' from within Calcurse, "
"or read the manpage.\n"
"Mail bug reports and suggestions to <calcurse@culot.org>.\n");
sprintf(htitle, _("Calcurse %s - text-based organizer\n"), VERSION);
fputs(htitle, stdout);
usage();
fputs(htext, stdout);
}
/*
* Print todo list and exit.
*/
void todo_arg(int colr)
{
struct todo_s *i;
int nb_tod;
nb_tod = load_todo(colr);
fputs(_("to do:\n"),stdout);
for (i = todolist; i != 0; i = i->next) {
fputs(" - ",stdout);
fputs(i->mesg,stdout);
fputs("\n",stdout);
}
}
/*
* Print appointments for given day and exit.
* If no year, month, and day is given, the given date is used.
* If there is also no date given, current date is considered.
*/
int app_arg(int add_line, int year, int month, int day, long date)
{
struct recur_event_s *re;
struct event_s *j;
struct recur_apoint_s *ra;
struct apoint_s *i;
long today;
bool print_date = true;
int app_found = 0;
char apoint_start_time[100];
char apoint_end_time[100];
if (date == 0) {
today = get_sec_date(year, month, day);
} else today = date;
/*
* Calculate and print the selected date if there is an event for
* that date and it is the first one, and then print all the events for
* that date.
*/
for (re = recur_elist; re != 0; re = re->next) {
if (recur_item_inday(re->day, re->rpt->type, re->rpt->freq,
re->rpt->until, today)) {
app_found = 1;
if (add_line) {
fputs("\n", stdout);
add_line = 0;
}
if (print_date) {
arg_print_date(today);
print_date = false;
}
fputs(" o ", stdout);
fputs(re->mesg, stdout); fputs("\n", stdout);
}
}
for (j = eventlist; j != 0; j = j->next) {
if (event_inday(j, today)) {
app_found = 1;
if (add_line) {
fputs("\n",stdout);
add_line = 0;
}
if (print_date) {
arg_print_date(today);
print_date = false;
}
fputs(" o ",stdout);
fputs(j->mesg,stdout); fputs("\n",stdout);
}
}
/* Same process is performed but this time on the appointments. */
for (ra = recur_alist; ra != 0; ra = ra->next) {
if (recur_item_inday(ra->start, ra->rpt->type, ra->rpt->freq,
ra->rpt->until, today)) {
app_found = 1;
if (add_line) {
fputs("\n",stdout);
add_line = 0;
}
if (print_date) {
arg_print_date(today);
print_date = false;
}
apoint_sec2str(recur_apoint_s2apoint_s(ra),
RECUR_APPT, today, apoint_start_time,
apoint_end_time);
fputs(" - ",stdout);
fputs(apoint_start_time,stdout);
fputs(" -> ",stdout);
fputs(apoint_end_time,stdout); fputs("\n\t",stdout);
fputs(ra->mesg,stdout); fputs("\n",stdout);
}
}
for (i = apointlist; i != 0; i = i->next) {
if (apoint_inday(i, today)) {
app_found = 1;
if (add_line) {
fputs("\n",stdout);
add_line = 0;
}
if (print_date) {
arg_print_date(today);
print_date = false;
}
apoint_sec2str(i, APPT, today, apoint_start_time,
apoint_end_time);
fputs(" - ",stdout);
fputs(apoint_start_time,stdout);
fputs(" -> ",stdout);
fputs(apoint_end_time,stdout); fputs("\n\t",stdout);
fputs(i->mesg,stdout); fputs("\n",stdout);
}
}
return app_found;
}
/*
* Print appointment for the given date or for the given n upcoming
* days.
*/
void date_arg(char *ddate, int add_line)
{
int i;
int year = 0, month = 0, day = 0;
int numdays = 0, num_digit = 0;
int arg_len = 0, app_found = 0;
int date_valid = 0;
long today, ind;
int sec_in_day = 86400;
/*
* Check (with the argument length) if a date or a number of days
* was entered, and then call app_arg() to print appointments
*/
arg_len = strlen(ddate);
if (arg_len <= 4) { /* a number of days was entered */
for (i = 0; i <= arg_len-1; i++) {
if (isdigit(ddate[i])) num_digit++;
}
if (num_digit == arg_len) numdays = atoi(ddate);
/*
* Get current date, and print appointments for each day
* in the chosen interval. app_found and add_line are used
* to format the output correctly.
*/
today = get_sec_date(year, month, day);
ind = today;
for (i = 0; i < numdays; i++) {
app_found = app_arg(add_line, 0, 0, 0, ind);
add_line = app_found;
ind = ind + sec_in_day;
}
} else { /* a date was entered */
date_valid = check_date(ddate);
if (date_valid) {
sscanf(ddate, "%d / %d / %d", &month, &day, &year);
app_found = app_arg(add_line, year, month, day, 0);
} else {
fputs(_("Argument to the '-d' flag is not valid\n"),stdout);
fputs(_("Possible argument formats are : 'mm/dd/yyyy' or 'n'\n"),stdout);
fputs(_("\nFor more information, type '?' from within Calcurse, or read the manpage.\n"),stdout);
fputs
(_("Mail bug reports and suggestions to <calcurse@culot.org>.\n"),
stdout);
}
}
}
/*
* Check if the entered date is of a valid format.
* First check the format by itself, and then check the
* numbers correctness.
*/
int
check_date(char *date)
{
int ok = 0;
char month[] = " ";
char day[] = " ";
char year[] = " ";
if (
(strlen(date) == 10) &
(isdigit(date[0]) != 0) &
(isdigit(date[1]) != 0) &
(date[2] == '/') &
(isdigit(date[3]) != 0) &
(isdigit(date[4]) != 0) &
(date[5] == '/') &
(isdigit(date[6])!=0) & (isdigit(date[7])!=0) &
(isdigit(date[8])!=0) & (isdigit(date[9])!=0)
) {
strncpy(month, date, 2);
strncpy(day, date + 3, 2);
strncpy(year, date + 6, 4);
if ( (atoi(month) <= 12) &
(atoi(month) >= 1) &
(atoi(day) <= 31) &
(atoi(day) >= 1) &
(atoi(year) <= 9999) &
(atoi(year) > 1))
ok = 1;
}
return ok;
}
/*
* Print the date on stdout.
*/
void arg_print_date(long date)
{
char date_str[30];
time_t t;
struct tm *lt;
t = date;
lt = localtime(&t);
sprintf(date_str,"%02u/%02u/%04u",lt->tm_mon+1,
lt->tm_mday, 1900+lt->tm_year);
fputs(date_str,stdout);
fputs(":\n",stdout);
}
/*
* Print Calcurse usage and exit.
*/
void usage()
{
char *arg_usage =
_("Usage: calcurse [-h | -v] [-at] [-d date|num] [-c file]\n");
fputs(arg_usage, stdout);
}
void usage_try()
{
char *arg_usage_try =
_("Try 'calcurse -h' for more information.\n");
fputs(arg_usage_try, stdout);
}

41
src/args.h Executable file
View File

@@ -0,0 +1,41 @@
/* $calcurse: args.h,v 1.1 2006/07/31 21:00:03 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#ifndef CALCURSE_ARGS_H
#define CALCURSE_ARGS_H
void usage();
void usage_try();
int parse_args(int argc, char **argv, int colr);
void version_arg();
void help_arg();
void todo_arg(int colr);
int app_arg(int add_line, int year, int month, int day, long date);
void date_arg(char *ddate, int add_line);
int check_date(char *date);
void arg_print_date(long date);
#endif /* CALCURSE_ARGS_H */

158
src/calcurse.1 Executable file
View File

@@ -0,0 +1,158 @@
.\" $calcurse: calcurse.1,v 1.1 2006/07/31 21:00:03 culot Exp $
.\"
.\" Copyright (c) 2004-2006 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
.\" the Free Software Foundation; either version 2 of the License, or
.\" (at your option) any later version.
.\"
.\" 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.
.\"
.TH CALCURSE 1 "May 07, 2006" "Version 1.4" "Calcurse Manual"
.SH NAME
Calcurse \- text-based organizer
.PP
.SH SYNOPSIS
.B "calcurse "
[
.B "-h "
|
.B "-v "
] [
.B "-at "
] [
.B "-d "
\fIdate\fP|\fInum\fP ] [
.B "-c "
\fIfile\fP ]
.PP
.SH DESCRIPTION
Calcurse is a text-based personal organizer which helps keeping track of
events and everyday tasks. It contains a calendar, a 'todo' list, and
puts your appointments in order. The user interface is configurable,
and one can choose between different color schemes and layouts.
All of the commands are documented within an online help system.
.PP
.SH OPTIONS
The following options are supported:
.TP
.B \-a
Print the appointments and events for the current day and exit.
.br
\fINote:\fP the calendar from which to read the appointments can be specified using
the '\-c' flag.
.TP
.B \-c
Specify the calendar file to use. The default calendar is
.B "'~/.calcurse/apts'"
(see section \fIFILES\fP below).
.TP
.B \-d
Print the appointments and events for the given date or for
the given number of upcoming days, depending on the argument format.
Two possible formats are supported:
.RS 9
.TP 2
\(bu a date of the form 'mm/dd/yyyy'.
.TP 2
\(bu a number 'n'.
.RE
.RS 7
.LP
In the first case, the appointments and events list for the specified
date will be returned, while in the second case the appointments and events
list for the 'n' upcoming days will be returned.
.br
As an example, typing 'calcurse -d 3' will display your appointments
and events for today, tomorrow, and the day after tomorrow.
.br
\fINote:\fP as for the '-a' flag, the calendar from which to read the
appointments can be specified using the '\-c' flag.
.RE
.TP
.B \-h
Print a short help text describing the supported command-line options,
and then exit.
.TP
.B \-t
Print the 'todo' list and exit.
.TP
.B \-v
Display calcurse version and exit.
.SH NOTES
Calcurse interface contains three different panels (calendar,
appointment list, and todo list) on which you can perform different
actions. All the possible actions, together with their associated
keystrokes, are listed on the status bar. This status bar
takes place at the bottom of the screen.
.PP
At any time, the built-in help system can be invoked by pressing the '?'
key. Once viewing the help screens, informations on a specific command
can be accessed by pressing the keystroke corresponding to that command.
.PP
.SH CONFIGURATION
The calcurse options can be changed from the configuration menu (shown
when 'C' is hit). Three possible categories are to be chosen from : the
color scheme, the layout (the location of the three panels on the
screen), and more general options (such as automatic save before
quitting). All of these options are detailed in the configuration menu.
.PP
.SH FILES
The following structure is created in your $HOME directory the first
time calcurse is run :
.PP
.HP 10
$HOME/.calcurse/
.br
|___conf
.br
|___apts
.br
|___todo
.PP
The \fIconf\fP file contains the user configuration. The \fIapts\fP
file contains all of the user's appointments, and the \fItodo\fP
file contains the todo list.
.PP
.SH LICENCE
Copyright (c) 2004-2006 by Frederic Culot.
.br
This software is released under the GNU General Public License. Please
read the COPYING file for more information.
.PP
.SH BUGS
Incorrect highlighting of items appear when using calcurse black and
white theme together with a \fB$TERM\fP variable set to
\fIxterm-color\fP.
To fix this bug, and as advised by Thomas E. Dickey (xterm maintainer),
\fIxterm-xfree86\fP should be used instead of \fIxterm-color\fP to set
the \fB$TERM\fP variable:
"The xterm-color value for $TERM is a bad choice for XFree86
xterm because it is commonly used for a terminfo entry which
happens to not support bce. Use the xterm-xfree86 entry
which is distributed with XFree86 xterm (or the similar one
distributed with ncurses)."
.PP
If you find other bugs, please send a report to calcurse@culot.org or to the
author, below.
.PP
.SH AUTHOR
\fBFrederic Culot\fP <frederic@culot.org>.
.PP
.SH SEE ALSO
ncurses(3), gettext(3)
.br
Calcurse home page : http://culot.org/calcurse/
.br
Calcurse manual found in the doc/ directory of the source package, or
at:
http://culot.org/calcurse/manual.html

1156
src/calcurse.c Executable file

File diff suppressed because it is too large Load Diff

227
src/calendar.c Executable file
View File

@@ -0,0 +1,227 @@
/* $calcurse: calendar.c,v 1.1 2006/07/31 21:00:02 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#include <ncurses.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include "i18n.h"
#include "day.h"
#include "apoint.h"
#include "event.h"
#include "calendar.h"
#include "custom.h"
#include "vars.h"
#include "utils.h"
static unsigned months_to_days(unsigned);
static long years_to_days(unsigned);
/* Load the calendar */
void
update_cal_panel(WINDOW *cwin, int nl_cal,
int nc_cal, int sel_month, int sel_year, int sel_day,
int day, int month, int year,
bool monday_first)
{
int c_day, c_day_1, day_1_sav, numdays, j;
unsigned yr, mo;
int ofs_x, ofs_y;
int item_this_day = 0;
int title_lines = 3;
int sunday_first = 0;
// Inits
erase_window_part(cwin, 1, title_lines, nc_cal - 2, nl_cal - 2);
mo = sel_month;
yr = sel_year;
if (!monday_first) sunday_first = 1;
// Offset for centering calendar in window
ofs_y = 2 + (nl_cal - 9) / 2;
ofs_x = (nc_cal - 27) / 2;
//checking the number of days in february
numdays = days[mo - 1];
if (2 == mo && isBissextile(yr))
++numdays;
//the first calendar day will be monday or sunday, depending on the
//value of week_begins_on_monday
c_day_1 = (int) ((ymd_to_scalar(yr, mo, 1 + sunday_first)
- (long) 1) % 7L);
//Write the current month and year on top of the calendar
custom_apply_attr(cwin, ATTR_HIGH);
mvwprintw(cwin, ofs_y,
(nc_cal - (strlen(_(monthnames[mo - 1])) + 5)) / 2,
"%s %d", _(monthnames[mo - 1]), sel_year);
custom_remove_attr(cwin, ATTR_HIGH);
++ofs_y;
//prints the days, with regards to the first day of the week
custom_apply_attr(cwin, ATTR_HIGH);
for (j = 0; j < 7; j++) {
mvwprintw(cwin, ofs_y, ofs_x + 4 * j, "%s",
_(daynames[1 + j - sunday_first]));
}
custom_remove_attr(cwin, ATTR_HIGH);
day_1_sav = (c_day_1 + 1) * 3 + c_day_1 - 7;
for (c_day = 1; c_day <= numdays; ++c_day, ++c_day_1, c_day_1 %= 7) {
//check if the day contains an event or an appointment
item_this_day = day_check_if_item(sel_year, sel_month, c_day);
/* Go to next line, the week is over. */
if (!c_day_1 && 1 != c_day) {
++ofs_y;
ofs_x = 2 - day_1_sav - 4 * c_day - 1;
}
/* This is today, so print it in yellow. */
if (c_day == day && month == sel_month
&& year == sel_year && day != sel_day)
{
custom_apply_attr(cwin, ATTR_LOWEST);
mvwprintw(cwin, ofs_y + 1,
ofs_x + day_1_sav + 4 * c_day + 1, "%2d",
c_day);
custom_remove_attr(cwin, ATTR_LOWEST);
} else if (c_day == sel_day && ( (day != sel_day) |
(month != sel_month) | (year != sel_year) ))
/* This is the selected day, print it in red. */
{
custom_apply_attr(cwin, ATTR_MIDDLE);
mvwprintw(cwin, ofs_y + 1,
ofs_x + day_1_sav + 4 * c_day + 1, "%2d",
c_day);
custom_remove_attr(cwin, ATTR_MIDDLE);
} else if (c_day == sel_day && day == sel_day && month == sel_month && year == sel_year) //today is the selected day
{
custom_apply_attr(cwin, ATTR_MIDDLE);
mvwprintw(cwin, ofs_y + 1,
ofs_x + day_1_sav + 4 * c_day + 1, "%2d",
c_day);
custom_remove_attr(cwin, ATTR_MIDDLE);
} else if (item_this_day) {
custom_apply_attr(cwin, ATTR_LOW);
mvwprintw(cwin, ofs_y + 1,
ofs_x + day_1_sav + 4 * c_day + 1, "%2d",
c_day);
custom_remove_attr(cwin, ATTR_LOW);
}
else // otherwise, print normal days in black
mvwprintw(cwin, ofs_y + 1,
ofs_x + day_1_sav + 4 * c_day + 1, "%2d",
c_day);
}
wnoutrefresh(cwin);
}
int isBissextile(unsigned annee)
{
return annee % 400 == 0 || (annee % 4 == 0 && annee % 100 != 0);
}
// convertion functions
unsigned months_to_days(unsigned mois)
{
return (mois * 3057 - 3007) / 100;
}
long years_to_days(unsigned annee)
{
return annee * 365L + annee / 4 - annee / 100 + annee / 400;
}
long ymd_to_scalar(unsigned annee, unsigned mois, unsigned jour)
{
long scalaire;
scalaire = jour + months_to_days(mois);
if (mois > 2)
scalaire -= isBissextile(annee) ? 1 : 2;
annee--;
scalaire += years_to_days(annee);
return scalaire;
}
/*
* Ask for a date to jump to, then check the correctness of that date
* and jump to it.
* If the entered date is empty, automatically jump to the current date.
* day, month, year are the current day given to that routine, and
* sel_day, sel_month and sel_year represent the day given back.
*/
void
goto_day(int colr, int day, int month, int year,
int *sel_day, int *sel_month, int *sel_year)
{
char selected_day[50] = "";
int dday, dmonth, dyear;
int wrong_day = 0;
char *mesg_line1 = _("The day you entered is not valid");
char *mesg_line2 = _("Press [ENTER] to continue");
char *request_date = _("Enter the day to go to [ENTER for today] : dd/mm/yyyy");
while (wrong_day != 1) {
status_mesg(request_date, "");
getstring(swin, colr, selected_day, 0, 1);
if (strlen(selected_day) == 0) // go to today
{
*sel_day = day;
*sel_month = month;
*sel_year = year;
break;
} else {
sscanf(selected_day, "%u/%u/%u", &dday, &dmonth,
&dyear);
//check if the entered day is correct
if ((dday <= 0) | (dday >= 32))
wrong_day = 1;
if ((dmonth <= 0) | (dmonth >= 13))
wrong_day = 1;
if ((dyear <= 0) | (dyear >= 3000))
wrong_day = 1;
//go to chosen day
if (wrong_day != 1) {
*sel_day = dday;
*sel_month = dmonth;
*sel_year = dyear;
} else {
status_mesg(mesg_line1, mesg_line2);
wgetch(swin);
}
break;
}
}
return;
}

41
src/calendar.h Executable file
View File

@@ -0,0 +1,41 @@
/* $calcurse: calendar.h,v 1.1 2006/07/31 21:00:02 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#ifndef CALCURSE_CALENDAR_H
#define CALCURSE_CALENDAR_H
#include <stdbool.h>
void update_cal_panel(WINDOW *cwin, int nl_cal,
int nc_cal, int sel_month, int sel_year, int sel_day,
int day, int month, int year,
bool monday_first);
int isBissextile(unsigned);
long ymd_to_scalar(unsigned, unsigned, unsigned);
void goto_day(int colr, int day, int month, int year,
int *sel_day, int *sel_month, int *sel_year);
#endif /* CALCURSE_CALENDAR_H */

178
src/custom.c Executable file
View File

@@ -0,0 +1,178 @@
/* $calcurse: custom.c,v 1.1 2006/07/31 21:00:02 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#include <ncurses.h>
#include "i18n.h"
#include "utils.h"
#include "custom.h"
#include "vars.h"
static struct attribute_s attr;
/*
* Define window attributes (for both color and non-color terminals):
* ATTR_HIGHEST are for window titles
* ATTR_HIGH are for month and days names
* ATTR_MIDDLE are for the selected day inside calendar panel
* ATTR_LOW are for days inside calendar panel which contains an event
* ATTR_LOWEST are for current day inside calendar panel
*/
void custom_init_attr(int colr)
{
attr.color[ATTR_HIGHEST] = COLOR_PAIR(colr);
attr.color[ATTR_HIGH] = COLOR_PAIR(6);
attr.color[ATTR_MIDDLE] = COLOR_PAIR(1);
attr.color[ATTR_LOW] = COLOR_PAIR(4);
attr.color[ATTR_LOWEST] = COLOR_PAIR(5);
attr.color[ATTR_TRUE] = COLOR_PAIR(2);
attr.color[ATTR_FALSE] = COLOR_PAIR(1);
attr.nocolor[ATTR_HIGHEST] = A_BOLD;
attr.nocolor[ATTR_HIGH] = A_REVERSE;
attr.nocolor[ATTR_MIDDLE] = A_REVERSE;
attr.nocolor[ATTR_LOW] = A_UNDERLINE;
attr.nocolor[ATTR_LOWEST] = A_BOLD;
attr.nocolor[ATTR_TRUE] = A_BOLD;
attr.nocolor[ATTR_FALSE] = A_DIM;
}
/* Apply window attribute */
void custom_apply_attr(WINDOW *win, int attr_num)
{
if (colorize)
wattron(win, attr.color[attr_num]);
else
wattron(win, attr.nocolor[attr_num]);
}
/* Remove window attribute */
void custom_remove_attr(WINDOW *win, int attr_num)
{
if (colorize)
wattroff(win, attr.color[attr_num]);
else
wattroff(win, attr.nocolor[attr_num]);
}
/* Draws the configuration bar */
void config_bar()
{
int smlspc, spc;
smlspc = 2;
spc = 15;
custom_apply_attr(swin, ATTR_HIGHEST);
mvwprintw(swin, 0, 2, "Q");
mvwprintw(swin, 1, 2, "G");
mvwprintw(swin, 0, 2 + spc, "L");
mvwprintw(swin, 1, 2 + spc, "C");
custom_remove_attr(swin, ATTR_HIGHEST);
mvwprintw(swin, 0, 2 + smlspc, _("Exit"));
mvwprintw(swin, 1, 2 + smlspc, _("General"));
mvwprintw(swin, 0, 2 + spc + smlspc, _("Layout"));
mvwprintw(swin, 1, 2 + spc + smlspc, _("Color"));
wnoutrefresh(swin);
wmove(swin, 0, 0);
doupdate();
}
/* Choose the layout */
int layout_config(int layout, int colr)
{
int ch, old_layout;
char *layout_mesg = _("Pick the desired layout on next screen [press ENTER]");
char *choice_mesg = _("('A'= Appointment panel, 'c'= calendar panel, 't'= todo panel)");
char *layout_up_mesg = _(" |Ac| |At| |cA| |tA|");
char *layout_down_mesg = _("[1]|At| [2]|Ac| [3]|tA| [4]|cA|");
old_layout = layout;
status_mesg(layout_mesg, choice_mesg);
wgetch(swin);
status_mesg(layout_up_mesg, layout_down_mesg);
wnoutrefresh(swin);
doupdate();
while ((ch = wgetch(swin)) != 'q') {
switch (ch) {
case '1':
layout = 1;
return layout;
case '2':
layout = 2;
return layout;
case '3':
layout = 3;
return layout;
case '4':
layout = 4;
return layout;
}
}
layout = old_layout;
return layout;
}
/* Choose the color theme */
int color_config(int colr)
{
int ascii2dec = 48;
int i, ch, old_colr;
int max_colors = 9;
int spc = 6;
char *choose_color = _("Pick the number corresponding to the color scheme "
"(Q to exit) :");
old_colr = colr;
erase_window_part(swin, 0, 0, col, 2);
for (i = 1; i < max_colors; i++) {
wattron(swin, COLOR_PAIR(i));
mvwprintw(swin, 1, (i - 1) * spc, "[>%d<]", i);
wattroff(swin, COLOR_PAIR(i));
}
mvwprintw(swin, 1, 50, _("([>0<] for black & white)"));
custom_apply_attr(swin, ATTR_HIGHEST);
mvwprintw(swin, 0, 0, choose_color);
custom_remove_attr(swin, ATTR_HIGHEST);
wnoutrefresh(swin);
doupdate();
while ((ch = wgetch(swin)) != 'q') {
ch = ch - ascii2dec;
if ( (ch > 0) && (ch <= max_colors) ) {
colorize = true;
return ch;
} else if (ch == 0) {
colorize = false;
return 0;
} else {
colr = old_colr;
}
}
if (colr == 0) colorize = false;
return colr;
}

42
src/custom.h Executable file
View File

@@ -0,0 +1,42 @@
/* $calcurse: custom.h,v 1.1 2006/07/31 21:00:02 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#ifndef CALCURSE_CUSTOM_H
#define CALCURSE_CUSTOM_H
struct attribute_s {
int color[7];
int nocolor[7];
};
void custom_init_attr(int colr);
void custom_apply_attr(WINDOW *win, int attr_num);
void custom_remove_attr(WINDOW *win, int attr_num);
void config_bar();
int layout_config(int layout, int colr);
int color_config(int colr);
#endif /* CALCURSE_CUSTOM_H */

362
src/day.c Executable file
View File

@@ -0,0 +1,362 @@
/* $calcurse: day.c,v 1.1 2006/07/31 21:00:03 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#include <ncurses.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <stdbool.h>
#include <time.h>
#include "i18n.h"
#include "utils.h"
#include "apoint.h"
#include "event.h"
#include "recur.h"
#include "day.h"
#include "vars.h"
static struct day_item_s *day_items_ptr;
static struct day_saved_item_s *day_saved_item = NULL;
/*
* Store all of the items to be displayed for the selected day.
* Items are of four types: recursive events, normal events,
* recursive appointments and normal appointments.
* The items are stored in the linked list pointed by *day_items_ptr
* and the length of the new pad to write is returned.
* The number of events and appointments in the current day are also updated.
*/
int day_store_items(long date, int *pnb_events, int *pnb_apoints)
{
int pad_length;
int nb_events, nb_recur_events;
int nb_apoints, nb_recur_apoints;
pad_length = nb_events = nb_apoints = 0;
nb_recur_events = nb_recur_apoints = 0;
if (day_items_ptr != 0)
day_free_list();
nb_recur_events = day_store_recur_events(date);
nb_events = day_store_events(date);
*pnb_events = nb_events;
nb_recur_apoints = day_store_recur_apoints(date);
nb_apoints = day_store_apoints(date);
*pnb_apoints = nb_apoints;
pad_length = nb_recur_events + nb_events + 1 +
3*(nb_recur_apoints + nb_apoints);
*pnb_apoints += nb_recur_apoints;
*pnb_events += nb_recur_events;
return pad_length;
}
/* Free the current day linked list containing the events and appointments. */
void day_free_list(void)
{
struct day_item_s *p, *q;
for (p = day_items_ptr; p != 0; p = q) {
q = p->next;
free(p->mesg);
free(p);
}
day_items_ptr = NULL;
}
/*
* Store the recurrent events for the selected day in structure pointed
* by day_items_ptr. This is done by copying the recurrent events
* from the general structure pointed by recur_elist to the structure
* dedicated to the selected day.
* Returns the number of recurrent events for the selected day.
*/
int day_store_recur_events(long date)
{
struct recur_event_s *j;
struct day_item_s *ptr;
int e_nb = 0;
for (j = recur_elist; j != 0; j = j->next) {
if (recur_item_inday(j->day, j->rpt->type, j->rpt->freq,
j->rpt->until, date)) {
e_nb++;
ptr = day_add_event(RECUR_EVNT, j->mesg, j->day, j->id);
}
}
return e_nb;
}
/*
* Store the events for the selected day in structure pointed
* by day_items_ptr. This is done by copying the events
* from the general structure pointed by eventlist to the structure
* dedicated to the selected day.
* Returns the number of events for the selected day.
*/
int day_store_events(long date)
{
struct event_s *j;
struct day_item_s *ptr;
int e_nb = 0;
for (j = eventlist; j != 0; j = j->next) {
if (event_inday(j, date)) {
e_nb++;
ptr = day_add_event(EVNT, j->mesg, j->day, j->id);
}
}
return e_nb;
}
/*
* Store the recurrent apoints for the selected day in structure pointed
* by day_items_ptr. This is done by copying the appointments
* from the general structure pointed by recur_alist to the structure
* dedicated to the selected day.
* Returns the number of recurrent appointments for the selected day.
*/
int day_store_recur_apoints(long date)
{
struct recur_apoint_s *j;
struct day_item_s *ptr;
int a_nb = 0;
for (j = recur_alist; j != 0; j = j->next) {
if (recur_item_inday(j->start, j->rpt->type, j->rpt->freq,
j->rpt->until, date)) {
a_nb++;
ptr = day_add_apoint(RECUR_APPT, j->mesg, j->start, j->dur);
}
}
return a_nb;
}
/*
* Store the apoints for the selected day in structure pointed
* by day_items_ptr. This is done by copying the appointments
* from the general structure pointed by apointlist to the structure
* dedicated to the selected day.
* Returns the number of appointments for the selected day.
*/
int day_store_apoints(long date)
{
struct apoint_s *j;
struct day_item_s *ptr;
int a_nb = 0;
for (j = apointlist; j != 0; j = j->next) {
if (apoint_inday(j, date)) {
a_nb++;
ptr = day_add_apoint(APPT, j->mesg, j->start, j->dur);
}
}
return a_nb;
}
/* Add an event in the current day list */
struct day_item_s *day_add_event(int type, char *mesg, long day, int id)
{
struct day_item_s *o, **i;
o = (struct day_item_s *) malloc(sizeof(struct day_item_s));
o->mesg = (char *) malloc(strlen(mesg) + 1);
strcpy(o->mesg, mesg);
o->type = type;
o->appt_dur = 0;
o->start = day;
o->evnt_id = id;
i = &day_items_ptr;
for (;;) {
if (*i == 0 || (*i)->start > day) {
o->next = *i;
*i = o;
break;
}
i = &(*i)->next;
}
return o;
}
/* Add an appointment in the current day list. */
struct day_item_s *day_add_apoint(int type, char *mesg, long start, long dur)
{
struct day_item_s *o, **i;
o = (struct day_item_s *) malloc(sizeof(struct day_item_s));
o->mesg = (char *) malloc(strlen(mesg) + 1);
strcpy(o->mesg, mesg);
o->start = start;
o->appt_dur = dur;
o->type = type;
o->evnt_id = 0;
i = &day_items_ptr;
for (;;) {
if (*i == 0 || (*i)->start > start) {
o->next = *i;
*i = o;
break;
}
i = &(*i)->next;
}
return o;
}
/*
* Write the appointments and events for the selected day in a pad.
* An horizontal line is drawn between events and appointments, and the
* item selected by user is highlighted. This item is also saved inside
* structure (pointed by day_saved_item), to be later displayed in a
* popup window if requested.
*/
void day_write_pad(long date, int width, int length, int incolor, int colr)
{
struct day_item_s *p;
int line, item_number, max_pos;
const int x_pos = 0;
bool draw_line = true;
line = item_number = 0;
max_pos = length;
/* Initialize the structure used to store highlited item. */
if (day_saved_item == NULL) {
day_saved_item = (struct day_saved_item_s *)
malloc(sizeof(struct day_saved_item_s));
day_saved_item->mesg = (char *) malloc(1);
}
for (p = day_items_ptr; p != 0; p = p->next) {
/* First print the events for current day. */
if (p->type < RECUR_APPT) {
item_number++;
if (item_number - incolor == 0) {
day_saved_item->type = p->type;
day_saved_item->mesg = (char *)
realloc(day_saved_item->mesg,
strlen(p->mesg) + 1);
day_saved_item->mesg = p->mesg;
}
display_item(apad->ptrwin, item_number - incolor, p->mesg,
width - 4, line, x_pos);
line++;
} else {
/* Draw a line between events and appointments. */
if (line > 0 && draw_line){
wmove(apad->ptrwin, line, x_pos);
whline(apad->ptrwin, 0, width);
draw_line = false;
}
/* Last print the appointments for current day. */
item_number++;
if (item_number - incolor == 0) {
day_saved_item->type = p->type;
day_saved_item->mesg = (char *)
realloc(day_saved_item->mesg,
strlen(p->mesg) + 1);
day_saved_item->mesg = p->mesg;
apoint_sec2str(day_item_s2apoint_s(p),
p->type, date,
day_saved_item->start,
day_saved_item->end);
}
display_item_date(apad->ptrwin, item_number - incolor,
day_item_s2apoint_s(p), p->type, date,
line + 1, x_pos);
display_item(apad->ptrwin, item_number - incolor, p->mesg,
width - 6, line + 2, x_pos + 2);
line = line + 3;
}
}
}
/* Returns a structure of type apoint_s given a structure of type day_item_s */
struct apoint_s *day_item_s2apoint_s(struct day_item_s *p)
{
struct apoint_s *a;
a = (struct apoint_s *) malloc(sizeof(struct apoint_s));
a->mesg = (char *) malloc(strlen(p->mesg) + 1);
a->start = p->start;
a->dur = p->appt_dur;
a->mesg = p->mesg;
return a;
}
/* Display an item inside a popup window. */
void day_popup_item(void)
{
char *error =
_("FATAL ERROR in day_popup_item: unknown item type\n");
if (day_saved_item->type == EVNT || day_saved_item->type == RECUR_EVNT)
item_in_popup(NULL, NULL, day_saved_item->mesg, _("Event :"));
else if (day_saved_item->type == APPT ||
day_saved_item->type == RECUR_APPT)
item_in_popup(day_saved_item->start, day_saved_item->end,
day_saved_item->mesg, _("Appointment :"));
else { /* NOT REACHED */
fputs(error, stderr);
exit(EXIT_FAILURE);
}
}
/*
* Need to know if there is an item for the current selected day inside
* calendar. This is used to put the correct colors inside calendar panel.
*/
int day_check_if_item(int year, int month, int day) {
struct recur_event_s *re;
struct recur_apoint_s *ra;
struct event_s *e;
struct apoint_s *a;
const long date = date2sec(year, month, day, 0, 0);
for (re = recur_elist; re != 0; re = re->next)
if (recur_item_inday(re->day, re->rpt->type, re->rpt->freq,
re->rpt->until, date))
return 1;
for (ra = recur_alist; ra != 0; ra = ra->next)
if (recur_item_inday(ra->start, ra->rpt->type, ra->rpt->freq,
ra->rpt->until, date))
return 1;
for (e = eventlist; e != 0; e = e->next)
if (event_inday(e, date))
return 1;
for (a = apointlist; a != 0; a = a->next)
if (apoint_inday(a, date))
return 1;
return 0;
}

66
src/day.h Executable file
View File

@@ -0,0 +1,66 @@
/* $calcurse: day.h,v 1.1 2006/07/31 21:00:03 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#ifndef CALCURSE_DAY_H
#define CALCURSE_DAY_H
#include "apoint.h"
#define RECUR_EVNT 1
#define EVNT 2
#define RECUR_APPT 3
#define APPT 4
struct day_item_s {
struct day_item_s *next;
int type; /* (recursive or normal) event or appointment */
long start; /* seconds since 1 jan 1970 */
char *mesg; /* item description */
int evnt_id; /* event identifier */
long appt_dur; /* appointment duration in seconds */
};
struct day_saved_item_s {
int type ;
char *mesg;
char start[100];
char end[100];
};
int day_store_items(long date, int *pnb_events, int *pnb_apoints);
void day_free_list(void);
int day_store_recur_events(long date);
int day_store_events(long date);
int day_store_recur_apoints(long date);
int day_store_apoints(long date);
struct day_item_s *day_add_event(int type, char *mesg, long day, int id);
struct day_item_s *day_add_apoint(int type, char *mesg, long start, long dur);
void day_write_pad(long date, int width, int length, int incolor, int colr);
struct apoint_s *day_item_s2apoint_s(struct day_item_s *p);
void day_popup_item(void);
int day_check_if_item(int year, int month, int day);
#endif /* CALCURSE_DAY_H */

135
src/event.c Executable file
View File

@@ -0,0 +1,135 @@
/* $calcurse: event.c,v 1.1 2006/07/31 21:00:03 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#include <ncurses.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include "i18n.h"
#include "event.h"
#include "utils.h"
struct event_s *eventlist;
/* Create a new event */
struct event_s *event_new(char *mesg, long day, int id)
{
struct event_s *o, **i;
o = (struct event_s *) malloc(sizeof(struct event_s));
o->mesg = (char *) malloc(strlen(mesg) + 1);
strcpy(o->mesg, mesg);
o->day = day;
o->id = id;
i = &eventlist;
for (;;) {
if (*i == 0 || (*i)->day > day) {
o->next = *i;
*i = o;
break;
}
i = &(*i)->next;
}
return o;
}
/* Check if the event belongs to the selected day */
unsigned event_inday(struct event_s *i, long start)
{
if (i->day <= start + 3600 * 24 && i->day > start) {
return 1;
}
return 0;
}
/* Write to file the event in user-friendly format */
void event_write(struct event_s *o, FILE * f)
{
struct tm *lt;
time_t t;
t = o->day;
lt = localtime(&t);
fprintf(f, "%02u/%02u/%04u [%d] %s\n",
lt->tm_mon + 1, lt->tm_mday, 1900 + lt->tm_year, o->id, o->mesg);
}
/* Load the events from file */
struct event_s *event_scan(FILE * f, struct tm start, int id)
{
struct tm *lt;
char buf[MESG_MAXSIZE], *nl;
time_t tstart, t;
t = time(NULL);
lt = localtime(&t);
/* Read the event description */
fgets(buf, MESG_MAXSIZE, f);
nl = strchr(buf, '\n');
if (nl) {
*nl = '\0';
}
start.tm_hour = 12;
start.tm_min = 0;
start.tm_sec = 0;
start.tm_isdst = -1;
start.tm_year -= 1900;
start.tm_mon--;
tstart = mktime(&start);
if (tstart == -1) {
fputs(_("FATAL ERROR in event_scan: date error in the event\n"), stderr);
exit(EXIT_FAILURE);
}
return event_new(buf, tstart, id);
}
/* Delete an event from the list */
void event_delete_bynum(long start, unsigned num)
{
unsigned n;
struct event_s *i, **iptr;
n = 0;
iptr = &eventlist;
for (i = eventlist; i != 0; i = i->next) {
if (event_inday(i, start)) {
if (n == num) {
*iptr = i->next;
free(i->mesg);
free(i);
return;
}
n++;
}
iptr = &i->next;
}
/* NOTREACHED */
fputs(_("FATAL ERROR in event_delete_bynum: no such event\n"), stderr);
exit(EXIT_FAILURE);
}

48
src/event.h Executable file
View File

@@ -0,0 +1,48 @@
/* $calcurse: event.h,v 1.1 2006/07/31 21:00:03 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#ifndef CALCURSE_EVENT_H
#define CALCURSE_EVENT_H
#define HRMIN_SIZE 6
#define MESG_MAXSIZE 256
struct event_s {
struct event_s *next;
int id; /* event identifier */
long day; /* seconds since 1 jan 1970 */
char *mesg;
};
extern struct event_s *eventlist;
struct event_s *event_new(char *, long, int);
unsigned event_inday(struct event_s *o, long start);
void event_write(struct event_s *o, FILE * f);
struct event_s *event_scan(FILE * f, struct tm start, int id);
void event_delete_bynum(long start, unsigned num);
#endif /* CALCURSE_EVENT_H */

375
src/help.c Executable file
View File

@@ -0,0 +1,375 @@
/* $calcurse: help.c,v 1.1 2006/07/31 21:00:03 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#include <ncurses.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <sys/types.h>
#include "i18n.h"
#include "help.h"
#include "custom.h"
#include "vars.h"
#include "utils.h"
/*
* Write the desired help text inside the help pad, and return the number
* of lines that were written.
* */
int write_help_pad(WINDOW *win, char *title, char *text, int pad_width)
{
int nl_title = 0;
int nl_text = 0;
nl_text = get_help_lines(text);
nl_title = get_help_lines(title);
erase_window_part(win, 0, 0, MAX_LENGTH, pad_width);
custom_apply_attr(win, ATTR_HIGHEST);
mvwprintw(win, 0, 0, "%s", title);
custom_remove_attr(win, ATTR_HIGHEST);
mvwprintw(win, nl_title, 0, "%s", text);
return nl_text + nl_title;
}
int get_help_lines(char *text)
{
int i;
int nl = 0;
for (i = 0; text[i]; i++) {
if (text[i] == '\n') nl++;
}
return nl + 1;
}
/* Draws the help screen */
void help_screen(int which_pan, int colr)
{
WINDOW *help_win = NULL;
WINDOW *help_pad = NULL;
char label[80];
int ch = '?';
int help_row = row - 2; //size of the help window
int help_col = col;
int title_lines = 3;
int pad_offset = 4;
int text_lines = help_row - (pad_offset + 1);
int pad_width = help_col - 2*pad_offset + 1;
int first_line = 0, nl = 0;
help_page_t help_main;
help_page_t help_redraw;
help_page_t help_save;
help_page_t help_displacement;
help_page_t help_view;
help_page_t help_tab;
help_page_t help_goto;
help_page_t help_delete;
help_page_t help_add;
help_page_t help_config;
help_page_t help_credits;
help_main.title =
_(" Welcome to Calcurse. This is the main help screen.\n");
help_main.text =
_(" Moving around: Press CTRL-P or CTRL-N to scroll text upward or\n"
" downward inside help screens, if necessary.\n\n"
" Exit help: When finished, press 'Q' to exit help and go back\n"
" to the main Calcurse screen.\n\n"
" Help topic: At the bottom of this screen you can see a panel\n"
" with different fields, represented by a letter and\n"
" a short title. This panel contains all the available\n"
" actions you can perform when using Calcurse.\n"
" By pressing one of the letters appearing in this\n"
" panel, you will be shown a short description of the\n"
" corresponding action.\n\n"
" Credits: Press '@' for credits.");
help_redraw.title = _("Redraw:\n");
help_redraw.text =
_("Pressing 'R' redraws the Calcurse panels.\n\n"
"You might want to use this function when you resize your terminal\n"
"screen for example, and you want Calcurse to take into account the new\n"
"size of the terminal.\n\n"
"This function can also be useful when garbage appears in the display,\n"
"and you want to clean it.");
help_save.title = _("Save:\n");
help_save.text =
_("Pressing 'S' saves the Calcurse data.\n\n"
"The data is splitted into three different files which contains :"
"\n\n"
" / ~/.calcurse/conf -> the user configuration\n"
" | (layout, color, general options)\n"
" | ~/.calcurse/apts -> the data related to the appointments\n"
" \\ ~/.calcurse/todo -> the data related to the todo list\n"
"\nIn the config menu, you can choose to save the Calcurse data\n"
"automatically before quitting.");
help_displacement.title = _("Displacement keys:\n");
help_displacement.text =
_("You can use either 'H','J','K','L' or the arrow keys '<','v','^','>'\n"
"to move into the calendar.\n\n"
"The following scheme explains how :\n\n"
" move to previous week\n"
" K ^ \n"
" move to previous day H < > L move to next day\n"
" J v \n"
" move to next week\n"
"\nWhen the Appointment or ToDo panel is selected, the up and down keys\n"
"(respectively K or up arrow, and J or down arrow) allows you to select\n"
"an item from those lists.");
help_view.title = _("View:\n");
help_view.text =
_("Pressing 'V' allows you to view the item you select in either the ToDo\n"
"or Appointment panel.\n"
"\nThis is usefull when an event description is longer than the available\n"
"space to display it. If that is the case, the description will be\n"
"shortened and its end replaced by '...'. To be able to read the entire\n"
"description, just press 'V' and a popup window will appear, containing\n"
"the whole event.\n"
"\nPress any key to close the popup window and go back to the main\n"
"Calcurse screen.");
help_tab.title = _("Tab:\n");
help_tab.text =
_("Pressing 'Tab' allows you to switch between panels.\n"
"The panel currently in use has its border colorized.\n"
"\nSome actions are possible only if the right panel is selected.\n"
"For example, if you want to add a task in the TODO list, you need first\n"
"to press the 'Tab' key to get the TODO panel selected. Then you can\n"
"press 'A' to add your item.\n"
"\nNotice that at the bottom of the screen the list of possible actions\n"
"change while pressing 'Tab', so you always know what action can be\n"
"performed on the selected panel.");
help_goto.title = _("Goto:\n");
help_goto.text =
_("Pressing 'G' allows you to jump to a specific day in the calendar.\n"
"\nUsing this command, you do not need to travel to that day using\n"
"the displacement keys inside the calendar panel.\n"
"If you hit [ENTER] without specifying any date, Calcurse checks the\n"
"system current date and you will be taken to that date.");
help_delete.title = _("Delete:\n");
help_delete.text =
_("Pressing 'D' deletes an element in the ToDo or Appointment list.\n"
"\nDepending on which panel is selected when you press the delete key,\n"
"the hilighted item of either the ToDo or Appointment list will be \n"
"removed from this list.\n"
"\nIf the general option 'confirm_delete' is set to 'YES', then you will\n"
"be asked for confirmation before deleting the selected event.\n"
"Do not forget to save the calendar data to retrieve the modifications\n"
"next time you launch Calcurse.");
help_add.title = _("Add:\n");
help_add.text =
_("Pressing 'A' allows you to add an item in either the ToDo or Appointment\n"
"list, depending on which panel is selected when you press 'A'.\n"
"\nTo enter a new item in the TODO list, you only need to enter the\n"
"description of this new item.\n"
"\nIf the APPOINTMENT panel is selected while pressing 'A', you will be\n"
"able to enter either a new appointment or a new all-day long event.\n"
"To enter a new event, press [ENTER] instead of the item start time, and\n"
"just fill in the event description.\n"
"To enter a new appointment to be added in the APPOINTMENT list, you\n"
"will need to enter successively the time at which the appointment\n"
"begins, the appointment length (either by specifying the duration in\n"
"minutes, or the end time in [hh:mm] or [h:mm] format), and the\n"
"description of the event.\n"
"\nThe day at which occurs the event or appointment is the day currently\n"
"selected in the calendar, so you need to move to the desired day before\n"
"pressing 'A'.\n"
"\nNotes:\n"
" o if an appointment lasts for such a long time that it continues\n"
" on the next days, this event will be indicated on all the\n"
" corresponding days, and the beginning or ending hour will be\n"
" replaced by '..' if the event does not begin or end on the day.\n"
" o if you only press [ENTER] at the APPOINTMENT or TODO event\n"
" description prompt, without any description, no item will be\n"
" added.\n"
" o do not forget to save the calendar data to retrieve the new\n"
" event next time you launch Calcurse.");
help_config.title = _("Config:\n");
help_config.text =
_("Pressing 'C' leads to the configuration submenu, from which you can\n"
"select between color, layout, and general options.\n"
"\nThe color submenu lets you choose the color theme.\n"
"\nThe layout submenu lets you choose the Calcurse screen layout, in other\n"
"words where to place the three different panels on the screen.\n"
"\nThe general options submenu brings a screen with the different options\n"
"which modifies the way Calcurse interacts with the user.\n"
"\nDo not forget to save the calendar data to retrieve your configuration\n"
"next time you launch Calcurse.");
help_credits.title = _("Calcurse - text-based organizer");
help_credits.text =
_("Copyright (c) 2004-2006 Frederic Culot\n"
"\n"
"This program is free software; you can redistribute it and/or modify\n"
"it under the terms of the GNU General Public License as published by\n"
"the Free Software Foundation; either version 2 of the License, or\n"
"(at your option) any later version.\n"
"\nThis program is distributed in the hope that it will be useful,\n"
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
"GNU General Public License for more details.\n"
"\n\n"
"Send your feedback or comments to : calcurse@culot.org\n"
"Calcurse home page : http://culot.org/calcurse");
/*
* Create the help window and panel. The panel is used to make
* the scrolling faster.
*/
help_win = newwin(help_row, help_col, 0, 0);
help_pad = newpad(MAX_LENGTH, pad_width);
box(help_win, 0, 0);
sprintf(label, _("CalCurse %s | help"), VERSION);
win_show(help_win, label);
/* Display the main help screen. */
/* nl = write_help_pad(help_pad, help_main.title, help_main.text, pad_width);
status_bar(which_pan, colr, col, 2);
wmove(swin, 0, 0);
wnoutrefresh(help_win);
pnoutrefresh(help_pad, first_line, 0, pad_offset, pad_offset,
help_row - 2, help_col - pad_offset);
doupdate();
*/
/* Display the help screen related to user input. */
while ( ch != 'q' ) {
erase_window_part(help_win, 1, title_lines,
help_col - 2, help_row - 2);
switch (ch) {
case CTRL('N') :
if (nl > first_line + text_lines) first_line++;
break;
case CTRL('P') :
if (first_line > 0) first_line--;
break;
case '?':
first_line = 0;
nl = write_help_pad(help_pad, help_main.title,
help_main.text, pad_width);
break;
case 'r':
first_line = 0;
nl = write_help_pad(help_pad, help_redraw.title,
help_redraw.text, pad_width);
break;
case 's':
first_line = 0;
nl = write_help_pad(help_pad, help_save.title,
help_save.text, pad_width);
break;
case 'h':
case 'l':
case 'j':
case 'k':
case 259:
case 258:
case 260:
case 261:
first_line = 0;
nl = write_help_pad(help_pad, help_displacement.title,
help_displacement.text, pad_width);
break;
case 'a':
first_line = 0;
nl = write_help_pad(help_pad, help_add.title,
help_add.text, pad_width);
break;
case 'g':
first_line = 0;
nl = write_help_pad(help_pad, help_goto.title,
help_goto.text, pad_width);
break;
case 'd':
first_line = 0;
nl = write_help_pad(help_pad, help_delete.title,
help_delete.text, pad_width);
break;
case 'c':
first_line = 0;
nl = write_help_pad(help_pad, help_config.title,
help_config.text, pad_width);
break;
case 'v':
first_line = 0;
nl = write_help_pad(help_pad, help_view.title,
help_view.text, pad_width);
break;
case 9:
first_line = 0;
nl = write_help_pad(help_pad, help_tab.title,
help_tab.text, pad_width);
break;
case '@':
first_line = 0;
nl = write_help_pad(help_pad, help_credits.title,
help_credits.text, pad_width);
break;
}
/* Draw the scrollbar if necessary. */
if (nl > text_lines){
float ratio = ((float) text_lines + 1) / ((float) nl);
int sbar_length = (int) (ratio * text_lines);
int highend = (int) (ratio * first_line);
int sbar_top = highend + title_lines + 1;
draw_scrollbar(help_win, sbar_top, help_col - 2,
sbar_length, title_lines + 1,
help_row - 1, true);
}
wmove(swin, 0, 0);
wnoutrefresh(help_win);
pnoutrefresh(help_pad, first_line, 0,
pad_offset, pad_offset,
help_row - 2, help_col - pad_offset);
doupdate();
ch = wgetch(swin);
}
delwin(help_pad);
delwin(help_win);
}

41
src/help.h Executable file
View File

@@ -0,0 +1,41 @@
/* $calcurse: help.h,v 1.1 2006/07/31 21:00:03 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#ifndef CALCURSE_HELP_H
#define CALCURSE_HELP_H
#include <ncurses.h>
typedef struct {
char *title;
char *text;
} help_page_t;
int write_help_pad(WINDOW *win, char *title, char *text, int pad_width);
int get_help_lines(char *text);
void help_screen(int which_pan, int colr);
#endif /* CALCURSE_HELP_H */

54
src/i18n.h Executable file
View File

@@ -0,0 +1,54 @@
/* $calcurse: i18n.h,v 1.1 2006/07/31 21:00:03 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#ifndef CALCURSE_I18N_H
#define CALCURSE_I18N_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* HAVE_CONFIG_H */
#if ENABLE_NLS
#include <libintl.h>
#undef _
#define _(String) gettext(String)
#ifdef gettext_noop
#define N_(String) gettext_noop(String)
#else
#define N_(String) (String)
#endif
#else /* NLS disabled */
#define _(String) (String)
#define N_(String) (String)
#define textdomain(String) (String)
#define gettext(String) (String)
#define dgettext(String) (String)
#define dcgettext(String) (String)
#define bindtextdomain(String) (String)
#define bind_textdomain_codeset(Domain,Codeset) (Codeset)
#endif /* ENABLE_NLS */
#endif /* CALCURSE_I18N_H */

484
src/io.c Executable file
View File

@@ -0,0 +1,484 @@
/* $calcurse: io.c,v 1.1 2006/07/31 21:00:03 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#include <ncurses.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <math.h>
#include <unistd.h>
#include "i18n.h"
#include "utils.h"
#include "custom.h"
#include "todo.h"
#include "event.h"
#include "apoint.h"
#include "recur.h"
#include "io.h"
#include "vars.h"
/*
* Initialization of data paths. The argument cfile is the variable
* which contains the calendar file. If none is given, then the default
* one (~/.calcurse/apts) is taken. If the one given does not exist, it
* is created.
*/
void
io_init(char *cfile)
{
FILE *data_file;
char *home;
char apts_file[MAX_LENGTH] = "";
int ch;
home = getenv("HOME");
if (home == NULL) {
home = ".";
}
snprintf(path_dir, MAX_LENGTH, "%s/" DIR_NAME, home);
snprintf(path_todo, MAX_LENGTH, "%s/" TODO_PATH, home);
snprintf(path_conf, MAX_LENGTH, "%s/" CONF_PATH, home);
if (cfile == NULL) {
snprintf(path_apts, MAX_LENGTH, "%s/" APTS_PATH, home);
} else {
snprintf(apts_file, MAX_LENGTH, "%s", cfile);
strncpy(path_apts, apts_file, MAX_LENGTH);
/* check if the file exists, otherwise create it */
data_file = fopen(path_apts, "r");
if (data_file == NULL) {
printf(_("%s does not exist, create it now [y or n] ? "), path_apts);
ch = getchar();
switch (ch) {
case 'N':
case 'n':
printf(_("aborting...\n"));
exit(EXIT_FAILURE);
break;
case 'Y':
case 'y':
data_file = fopen(path_apts, "w");
if (data_file == NULL) {
perror(path_apts);
exit(EXIT_FAILURE);
} else {
printf(_("%s successfully created\n"),path_apts);
printf(_("starting interactive mode...\n"));
}
break;
default:
printf(_("aborting...\n"));
exit(EXIT_FAILURE);
break;
}
}
fclose(data_file);
}
}
/* get data from file */
void extract_data(char *dst_data, const char *org, int len)
{
for (;;) {
if (*org == '\n' || *org == '\0')
break;
*dst_data++ = *org++;
}
*dst_data = '\0';
}
/* Save the calendar data */
void
save_cal(bool auto_save, bool confirm_quit,
bool confirm_delete, bool skip_system_dialogs,
bool skip_progress_bar, bool week_begins_on_monday,
int colr, int layout)
{
FILE *data_file;
struct event_s *k;
struct apoint_s *j;
struct todo_s *i;
char *access_pb = _("Problems accessing data file ...");
char *config_txt =
"#\n# Calcurse configuration file\n#\n# This file sets the configuration options used by Calcurse. These\n# options are usually set from within Calcurse. A line beginning with \n# a space or tab is considered to be a continuation of the previous line.\n# For a variable to be unset its value must be blank.\n# To set a variable to the empty string its value should be \"\".\n# Lines beginning with \"#\" are comments, and ignored by Calcurse.\n";
char *save_success = _("The data files were successfully saved");
char *enter = _("Press [ENTER] to continue");
bool save = true, show_bar = false;
if (!skip_progress_bar) show_bar = true;
/* Save the user configuration. */
if (show_bar) progress_bar(save, 1);
data_file = fopen(path_conf, "w");
if (data_file == (FILE *) 0)
status_mesg(access_pb, "");
else {
fprintf(data_file, "%s\n", config_txt);
fprintf(data_file,
"# If this option is set to yes, automatic save is done when quitting\n");
fprintf(data_file, "auto_save=\n");
fprintf(data_file, "%s\n",
(auto_save) ? "yes" : "no");
fprintf(data_file,
"\n# If this option is set to yes, confirmation is required before quitting\n");
fprintf(data_file, "confirm_quit=\n");
fprintf(data_file, "%s\n",
(confirm_quit) ? "yes" : "no");
fprintf(data_file,
"\n# If this option is set to yes, confirmation is required before deleting an event\n");
fprintf(data_file, "confirm_delete=\n");
fprintf(data_file, "%s\n",
(confirm_delete) ? "yes" : "no");
fprintf(data_file,
"\n# If this option is set to yes, messages about loaded and saved data will not be displayed\n");
fprintf(data_file, "skip_system_dialogs=\n");
fprintf(data_file, "%s\n",
(skip_system_dialogs) ? "yes" : "no");
fprintf(data_file,
"\n# If this option is set to yes, progress bar appearing when saving data will not be displayed\n");
fprintf(data_file, "skip_progress_bar=\n");
fprintf(data_file, "%s\n",
(skip_progress_bar) ? "yes" : "no");
fprintf(data_file,
"\n# If this option is set to yes, monday is the first day of the week, else it is sunday\n");
fprintf(data_file, "week_begins_on_monday=\n");
fprintf(data_file, "%s\n",
(week_begins_on_monday) ? "yes" : "no");
fprintf(data_file,
"\n# This is the color theme used for menus (1 to 8) :\n");
fprintf(data_file, "color-theme=\n");
fprintf(data_file, "%d\n", colr);
fprintf(data_file,
"\n# This is the layout of the calendar (1 to 4) :\n");
fprintf(data_file, "layout=\n");
fprintf(data_file, "%d\n", layout);
fclose(data_file);
}
/* Save the todo data file. */
if (show_bar) progress_bar(save, 2);
data_file = fopen(path_todo, "w");
if (data_file == (FILE *) 0)
status_mesg(access_pb, "");
else {
for (i = todolist; i != 0; i = i->next)
fprintf(data_file, "%s\n", i->mesg);
fclose(data_file);
}
/*
* Save the apts data file, which contains the
* appointments first, and then the events.
* Recursive items are written first.
*/
if (show_bar) progress_bar(save, 3);
data_file = fopen(path_apts, "w");
if (data_file == (FILE *) 0)
status_mesg(access_pb, "");
else {
recur_save_data(data_file);
for (j = apointlist; j != 0; j = j->next)
apoint_write(j, data_file);
for (k = eventlist; k != 0; k = k->next)
event_write(k, data_file);
fclose(data_file);
}
/* Print a message telling data were saved */
if (!skip_system_dialogs){
status_mesg(save_success, enter);
wgetch(swin);
}
}
/*
* Check what type of data is written in the appointment file,
* and then load either: a new appointment, a new event, or a new
* recursive item (which can also be either an event or an appointment).
*/
void load_app()
{
FILE *data_file;
int c, is_appointment, is_event, is_recursive;
struct tm start, end, until, *lt;
time_t t;
int id = 0;
int freq;
char type;
char *error =
_("FATAL ERROR in load_app: wrong format in the appointment or event\n");
t = time(NULL);
lt = localtime(&t);
start = end = until = *lt;
data_file = fopen(path_apts, "r");
for (;;) {
is_appointment = is_event = is_recursive = 0;
c = getc(data_file);
if (c == EOF)
break;
ungetc(c, data_file);
/* Read the date first: it is common to both events
* and appointments.
*/
if (fscanf(data_file, "%u / %u / %u ",
&start.tm_mon, &start.tm_mday, &start.tm_year) != 3) {
fputs(_("FATAL ERROR in load_app: "
"syntax error in the item date\n"), stderr);
exit(EXIT_FAILURE);
}
/* Read the next character : if it is an '@' then we have
* an appointment, else if it is an '[' we have en event.
*/
c = getc(data_file);
if (c == '@')
is_appointment = 1;
else if (c == '[')
is_event = 1;
else {
fputs(_("FATAL ERROR in load_app: "
"no event nor appointment found\n"), stderr);
exit(EXIT_FAILURE);
}
ungetc(c, data_file);
/* Read the remaining informations. */
if (is_appointment) {
fscanf(data_file, "@ %u : %u -> %u / %u / %u @ %u : %u ",
&start.tm_hour, &start.tm_min,
&end.tm_mon, &end.tm_mday, &end.tm_year,
&end.tm_hour, &end.tm_min);
} else if (is_event) {
fscanf(data_file, "[%d] ", &id);
} else { /* NOT REACHED */
fputs(error, stderr);
exit(EXIT_FAILURE);
}
/* Check if we have a recursive item. */
c = getc(data_file);
if (c == '{') {
ungetc(c, data_file);
is_recursive = 1;
fscanf(data_file, "{ %d%c ", &freq, &type);
/* Check if we have an endless recurrent item. */
c = getc(data_file);
if (c == '}') {
ungetc(c, data_file);
fscanf(data_file, "} ");
until.tm_year = 0;
if (is_appointment)
c = getc(data_file); // useless '|'
} else if (c == '-') {
ungetc(c, data_file);
fscanf(data_file, " -> %u / %u / %u } ",
&until.tm_mon, &until.tm_mday,
&until.tm_year);
if (is_appointment)
c = getc(data_file); // useless '|'
} else { /* NOT REACHED */
fputs(error, stderr);
exit(EXIT_FAILURE);
}
} else {
if (is_event) // if appointment we have a useless '|'
ungetc(c, data_file);
}
/*
* Last: read the item description and load it into its
* corresponding linked list, depending on the item type.
*/
if (is_appointment) {
if (is_recursive) {
recur_apoint_scan(data_file, start, end,
type, freq, until);
} else {
apoint_scan(data_file, start, end);
}
} else if (is_event) {
if (is_recursive) {
recur_event_scan(data_file, start, id,
type, freq, until);
} else {
event_scan(data_file, start, id);
}
} else { /* NOT REACHED */
fputs(error, stderr);
exit(EXIT_FAILURE);
}
}
fclose(data_file);
}
/* Load the todo data */
int
load_todo(int colr)
{
FILE *data_file;
char *mesg_line1 = _("Failed to open todo file");
char *mesg_line2 = _("Press [ENTER] to continue");
int nb_tod = 0;
char buf[100], e_todo[100];
data_file = fopen(path_todo, "r");
if (data_file == NULL) {
status_mesg(mesg_line1, mesg_line2);
wgetch(swin);
}
for (;;) {
if (fgets(buf, 99, data_file) == NULL) {
break;
}
extract_data(e_todo, buf, strlen(buf));
todo_add(e_todo);
++nb_tod;
}
fclose(data_file);
return nb_tod;
}
/* Checks if data files exist. If not, create them */
int check_data_files()
{
FILE *data_file;
int no_data_file;
no_data_file = 0;
/* Create the calcurse repertory if not present. */
mkdir(path_dir, 0700);
data_file = fopen(path_todo, "r");
if (data_file == NULL) {
no_data_file++;
data_file = fopen(path_todo, "w");
if (data_file == NULL) {
perror(path_todo);
return no_data_file;
}
}
fclose(data_file);
data_file = fopen(path_apts, "r");
if (data_file == NULL) {
no_data_file++;
data_file = fopen(path_apts, "w");
if (data_file == NULL) {
perror(path_apts);
return no_data_file;
}
}
fclose(data_file);
data_file = fopen(path_conf, "r");
if (data_file == NULL) {
no_data_file++;
data_file = fopen(path_conf, "w");
if (data_file == NULL) {
perror(path_conf);
return no_data_file;
}
}
fclose(data_file);
return no_data_file;
}
/* Draw the startup screen */
void startup_screen(bool skip_dialogs, int no_data_file, int colr)
{
char *welcome_mesg = _("Welcome to Calcurse. Missing data files were created.");
char *data_mesg = _("Data files found. Data will be loaded now.");
char *enter = _("Press [ENTER] to continue");
if (no_data_file != 0) {
status_mesg(welcome_mesg, enter);
wgetch(swin);
} else if (!skip_dialogs){
status_mesg(data_mesg, enter);
wgetch(swin);
}
}
/* Draw a progress bar while saving or loading data. */
void progress_bar(bool save, int progress)
{
int i, nbd = 4;
char *mesg_sav = _("Saving...");
char *mesg_load = _("Loading...");
char *barchar = "|";
char *data[4] = {
"[ ]",
"[ conf ]",
"[ todo ]",
"[ apts ]"};
int ipos = strlen(data[1]) + 2;
int epos[4];
int sleep_time = 125000;
/* progress bar length init. */
epos[0] = floor(col / nbd);
epos[1] = 2*epos[0];
epos[2] = 3*epos[0];
epos[3] = col - 2;
/* Display which data is being saved. */
if (save)
status_mesg(mesg_sav, data[progress]);
else
status_mesg(mesg_load, data[progress]);
/* Draw the progress bar. */
mvwprintw(swin, 1, ipos, barchar);
mvwprintw(swin, 1, epos[nbd - 1], barchar);
custom_apply_attr(swin, ATTR_HIGHEST);
for (i = ipos + 1; i < epos[progress]; i++)
mvwaddch(swin, 1, i, ' ' | A_REVERSE);
custom_remove_attr(swin, ATTR_HIGHEST);
wmove(swin, 0, 0);
wrefresh(swin);
usleep(sleep_time);
}

42
src/io.h Executable file
View File

@@ -0,0 +1,42 @@
/* $calcurse: io.h,v 1.1 2006/07/31 21:00:03 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#ifndef CALCURSE_IO_H
#define CALCURSE_IO_H
void io_init(char *cfile);
void extract_data(char *dst_data, const char *org, int len);
void save_cal(bool auto_save, bool confirm_quit,
bool confirm_delete, bool skip_system_dialogs,
bool skip_progress_bar, bool week_begins_on_monday,
int colr, int layout);
void load_app();
int load_todo(int colr);
int check_data_files();
void startup_screen(bool skip_dialogs, int no_data_file, int colr);
void progress_bar(bool save, int progress);
#endif /* CALCURSE_IO_H */

355
src/recur.c Executable file
View File

@@ -0,0 +1,355 @@
/* $calcurse: recur.c,v 1.1 2006/07/31 21:00:03 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#include <ncurses.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include "i18n.h"
#include "utils.h"
#include "apoint.h"
#include "event.h"
#include "recur.h"
struct recur_apoint_s *recur_alist;
struct recur_event_s *recur_elist;
/* Insert a new recursive appointment in the general linked list */
struct recur_apoint_s *recur_apoint_new(char *mesg, long start, long dur,
int type, int freq, long until)
{
struct recur_apoint_s *o, **i;
o = (struct recur_apoint_s *) malloc(sizeof(struct recur_apoint_s));
o->rpt = (struct rpt_s *) malloc(sizeof(struct rpt_s));
o->exc = (struct days_s *) malloc(sizeof(struct days_s));
o->mesg = (char *) malloc(strlen(mesg) + 1);
strcpy(o->mesg, mesg);
o->start = start;
o->dur = dur;
o->rpt->type = type;
o->rpt->freq = freq;
o->rpt->until = until;
i = &recur_alist;
for (;;) {
if (*i == 0 || (*i)->start > start) {
o->next = *i;
*i = o;
break;
}
i = &(*i)->next;
}
return o;
}
/* Insert a new recursive event in the general linked list */
struct recur_event_s *recur_event_new(char *mesg, long day, int id,
int type, int freq, long until)
{
struct recur_event_s *o, **i;
o = (struct recur_event_s *) malloc(sizeof(struct recur_event_s));
o->rpt = (struct rpt_s *) malloc(sizeof(struct rpt_s));
o->exc = (struct days_s *) malloc(sizeof(struct days_s));
o->mesg = (char *) malloc(strlen(mesg) + 1);
strcpy(o->mesg, mesg);
o->day = day;
o->id = id;
o->rpt->type = type;
o->rpt->freq = freq;
o->rpt->until = until;
i = &recur_elist;
for (;;) {
if (*i == 0 || (*i)->day > day) {
o->next = *i;
*i = o;
break;
}
i = &(*i)->next;
}
return o;
}
/*
* Correspondance between the defines on recursive type,
* and the letter to be written in file.
*/
char recur_def2char(int define){
char recur_char;
switch (define) {
case 1:
recur_char = 'D';
break;
case 2:
recur_char = 'W';
break;
case 3:
recur_char = 'M';
break;
case 4:
recur_char = 'Y';
break;
}
return recur_char;
}
/*
* Correspondance between the letters written in file and the defines
* concerning the recursive type.
*/
int recur_char2def(char type){
int recur_def;
switch (type) {
case 'D':
recur_def = RECUR_DAILY;
break;
case 'W':
recur_def = RECUR_WEEKLY;
break;
case 'M':
recur_def = RECUR_MONTHLY;
break;
case 'Y':
recur_def = RECUR_YEARLY;
break;
}
return recur_def;
}
/* Writting of a recursive appointment into file. */
void recur_apoint_write(struct recur_apoint_s *o, FILE *f)
{
struct tm *lt;
time_t t;
t = o->start;
lt = localtime(&t);
fprintf(f, "%02u/%02u/%04u @ %02u:%02u",
lt->tm_mon + 1, lt->tm_mday, 1900 + lt->tm_year,
lt->tm_hour, lt->tm_min);
t = o->start + o->dur;
lt = localtime(&t);
fprintf(f, " -> %02u/%02u/%04u @ %02u:%02u",
lt->tm_mon + 1, lt->tm_mday, 1900 + lt->tm_year,
lt->tm_hour, lt->tm_min);
t = o->rpt->until;
if (t == 0) { /* We have an endless recurrent appointment. */
fprintf(f, " {%d%c} |%s\n", o->rpt->freq,
recur_def2char(o->rpt->type), o->mesg);
} else {
lt = localtime(&t);
fprintf(f, " {%d%c -> %02u/%02u/%04u} |%s\n",
o->rpt->freq, recur_def2char(o->rpt->type),
lt->tm_mon + 1, lt->tm_mday, 1900 + lt->tm_year,
o->mesg);
}
}
/* Writting of a recursive event into file. */
void recur_event_write(struct recur_event_s *o, FILE *f)
{
struct tm *lt;
time_t t;
int st_mon, st_day, st_year;
int end_mon, end_day, end_year;
t = o->day;
lt = localtime(&t);
st_mon = lt->tm_mon + 1;
st_day = lt->tm_mday;
st_year = lt->tm_year + 1900;
t = o->rpt->until;
if (t == 0) { /* We have an endless recurrent event. */
fprintf(f, "%02u/%02u/%04u [%d] {%d%c} %s\n",
st_mon, st_day, st_year, o->id, o->rpt->freq,
recur_def2char(o->rpt->type), o->mesg);
} else {
lt = localtime(&t);
end_mon = lt->tm_mon + 1;
end_day = lt->tm_mday;
end_year = lt->tm_year + 1900;
fprintf(f, "%02u/%02u/%04u [%d] {%d%c -> %02u/%02u/%04u} %s\n",
st_mon, st_day, st_year, o->id,
o->rpt->freq, recur_def2char(o->rpt->type),
end_mon, end_day, end_year, o->mesg);
}
}
/* Load the recursive appointment description */
struct recur_apoint_s *recur_apoint_scan(FILE * f, struct tm start,
struct tm end, char type, int freq, struct tm until)
{
struct tm *lt;
char buf[MESG_MAXSIZE], *nl;
time_t tstart, tend, t, tuntil;
t = time(NULL);
lt = localtime(&t);
/* Read the appointment description */
fgets(buf, MESG_MAXSIZE, f);
nl = strchr(buf, '\n');
if (nl) {
*nl = '\0';
}
start.tm_sec = end.tm_sec = 0;
start.tm_isdst = end.tm_isdst = -1;
start.tm_year -= 1900;
start.tm_mon--;
end.tm_year -= 1900;
end.tm_mon--;
tstart = mktime(&start);
tend = mktime(&end);
if (until.tm_year != 0) {
until.tm_hour = 12;
until.tm_min = 0;
until.tm_sec = 0;
until.tm_isdst = -1;
until.tm_year -= 1900;
until.tm_mon--;
tuntil = mktime(&until);
} else {
tuntil = 0;
}
if (tstart == -1 || tend == -1 || tstart > tend || tuntil == -1) {
fputs(_("FATAL ERROR in apoint_scan: date error in the appointment\n"), stderr);
exit(EXIT_FAILURE);
}
return recur_apoint_new(buf, tstart, tend - tstart,
recur_char2def(type), freq, tuntil);
}
/* 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)
{
struct tm *lt;
char buf[MESG_MAXSIZE], *nl;
time_t tstart, t, tuntil;
t = time(NULL);
lt = localtime(&t);
/* Read the event description */
fgets(buf, MESG_MAXSIZE, f);
nl = strchr(buf, '\n');
if (nl) {
*nl = '\0';
}
start.tm_hour = until.tm_hour = 12;
start.tm_min = until.tm_min = 0;
start.tm_sec = until.tm_sec = 0;
start.tm_isdst = until.tm_isdst = -1;
start.tm_year -= 1900;
start.tm_mon--;
if (until.tm_year != 0) {
until.tm_year -= 1900;
until.tm_mon--;
tuntil = mktime(&until);
} else {
tuntil = 0;
}
tstart = mktime(&start);
if ( (tstart == -1) || (tuntil == -1) ) {
fputs(_("FATAL ERROR in recur_event_scan: date error in the event\n"), stderr);
exit(EXIT_FAILURE);
}
return recur_event_new(buf, tstart, id, recur_char2def(type), freq, tuntil);
}
/* Write recursive items to file. */
void recur_save_data(FILE *f)
{
struct recur_event_s *re;
struct recur_apoint_s *ra;
for (re = recur_elist; re != 0; re = re->next)
recur_event_write(re, f);
for (ra = recur_alist; ra != 0; ra = ra->next)
recur_apoint_write(ra, f);
}
/* Check if the recurrent item belongs to the selected day. */
unsigned recur_item_inday(long item_start, int rpt_type, int rpt_freq,
long rpt_until, long day_start)
{
const int DAYINSEC = 86400;
long day_end = day_start + DAYINSEC;
int inday = 0;
struct tm *lt;
time_t t;
char *error =
_("FATAL ERROR in recur_item_inday: unknown item type\n");
if (rpt_until == 0) /* we have an endless recurrent item */
rpt_until = day_end;
while (item_start <= day_end && item_start <= rpt_until) {
if (item_start < day_end && item_start >= day_start) {
inday = 1;
break;
}
t = item_start;
lt = localtime(&t);
if (rpt_type == RECUR_DAILY) {
lt->tm_mday += rpt_freq;
} else if (rpt_type == RECUR_WEEKLY) {
lt->tm_mday += rpt_freq * 7;
} else if (rpt_type == RECUR_MONTHLY) {
lt->tm_mon += rpt_freq;
} else if (rpt_type == RECUR_YEARLY) {
lt->tm_year += rpt_freq;
} else { /* NOT REACHED */
fputs(error, stderr);
exit(EXIT_FAILURE);
}
item_start = date2sec(lt->tm_year + 1900, lt->tm_mon + 1,
lt->tm_mday, 0, 0);
}
return inday;
}
/* Returns a structure of type apoint_s given a structure of type recur_apoint_s */
struct apoint_s *recur_apoint_s2apoint_s(struct recur_apoint_s *p)
{
struct apoint_s *a;
a = (struct apoint_s *) malloc(sizeof(struct apoint_s));
a->mesg = (char *) malloc(strlen(p->mesg) + 1);
a->start = p->start;
a->dur = p->dur;
a->mesg = p->mesg;
return a;
}

87
src/recur.h Executable file
View File

@@ -0,0 +1,87 @@
/* $calcurse: recur.h,v 1.1 2006/07/31 21:00:03 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#ifndef CALCURSE_RECUR_H
#define CALCURSE_RECUR_H
#include "apoint.h"
#define RECUR_NO 0
#define RECUR_DAILY 1
#define RECUR_WEEKLY 2
#define RECUR_MONTHLY 3
#define RECUR_YEARLY 4
struct days_s {
struct days_s *next;
long st; /* beggining of the considered day, in seconds */
};
struct rpt_s {
int type; /* repetition type, see RECUR_* defines */
int freq; /* repetition frequence */
long until; /* ending date for repeated event */
};
struct recur_apoint_s {
struct recur_apoint_s *next;
struct rpt_s *rpt; /* information about repetition */
struct days_s *exc; /* days when the item should not be repeated */
long start; /* beggining of the appointment */
long dur; /* duration of the appointment */
char *mesg; /* appointment description */
};
struct recur_event_s {
struct recur_event_s *next;
struct rpt_s *rpt; /* information about repetition */
struct days_s *exc; /* days when the item should not be repeated */
int id; /* event type */
long day; /* day at which event occurs */
char *mesg; /* event description */
};
extern struct recur_apoint_s *recur_alist;
extern struct recur_event_s *recur_elist;
struct recur_apoint_s *recur_apoint_new(char *mesg, long start, long duration,
int type, int freq, long until);
struct recur_event_s *recur_event_new(char *mesg, long day, int id,
int type, int freq, long until);
char recur_def2char(int define);
int recur_char2def(char type);
void recur_apoint_write(struct recur_apoint_s *o, FILE * f);
void recur_event_write(struct recur_event_s *o, FILE * f);
struct recur_apoint_s *recur_apoint_scan(FILE * f, struct tm start,
struct tm end, char type, int freq, struct tm until);
struct recur_event_s *recur_event_scan(FILE * f, struct tm start, int id,
char type, int freq, struct tm until);
void recur_save_data(FILE *f);
unsigned recur_item_inday(long item_start, int rpt_type, int rpt_freq,
long rpt_until, long day_start);
struct apoint_s *recur_apoint_s2apoint_s(struct recur_apoint_s *p);
#endif /* CALCURSE_RECUR_H */

80
src/todo.c Executable file
View File

@@ -0,0 +1,80 @@
/* $calcurse: todo.c,v 1.1 2006/07/31 21:00:03 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "i18n.h"
#include "todo.h"
struct todo_s *todolist;
struct todo_s *todo_insert(char *mesg)
{
struct todo_s *o;
o = (struct todo_s *) malloc(sizeof(struct todo_s));
o->mesg = (char *) malloc(strlen(mesg) + 1);
strcpy(o->mesg, mesg);
o->next = todolist;
todolist = o;
return o;
}
struct todo_s *todo_add(char *mesg)
{
struct todo_s *o, **i;
o = (struct todo_s *) malloc(sizeof(struct todo_s));
o->mesg = (char *) malloc(strlen(mesg) + 1);
strcpy(o->mesg, mesg);
for (i = &todolist; *i != 0; i = &(*i)->next) {
}
o->next = *i;
*i = o;
return o;
}
void todo_delete_bynum(unsigned num)
{
unsigned n;
struct todo_s *i, **iptr;
n = 0;
iptr = &todolist;
for (i = todolist; i != 0; i = i->next) {
if (n == num) {
*iptr = i->next;
free(i->mesg);
free(i);
return;
}
iptr = &i->next;
n++;
}
/* not reached */
fputs(_("FATAL ERROR in todo_delete_bynum: no such todo\n"), stderr);
exit(EXIT_FAILURE);
}

41
src/todo.h Executable file
View File

@@ -0,0 +1,41 @@
/* $calcurse: todo.h,v 1.1 2006/07/31 21:00:03 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#ifndef CALCURSE_TODO_H
#define CALCURSE_TODO_H
struct todo_s {
struct todo_s *next;
char *mesg;
};
extern struct todo_s *todolist;
struct todo_s *todo_insert(char *mesg);
struct todo_s *todo_add(char *mesg);
void todo_delete_bynum(unsigned num);
#endif /* CALCURSE_TODO_H */

614
src/utils.c Executable file
View File

@@ -0,0 +1,614 @@
/* $calcurse: utils.c,v 1.1 2006/07/31 21:00:03 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#include <ncurses.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdbool.h>
#include <sys/types.h>
#include <math.h>
#include "i18n.h"
#include "utils.h"
#include "custom.h"
#include "vars.h"
/*
* Print a message in the status bar.
* Message texts for first line and second line are to be provided.
*/
void status_mesg(char *mesg_line1, char *mesg_line2)
{
erase_window_part(swin, 0, 0, col, 2);
custom_apply_attr(swin, ATTR_HIGHEST);
mvwprintw(swin, 0, 0, mesg_line1);
mvwprintw(swin, 1, 0, mesg_line2);
custom_remove_attr(swin, ATTR_HIGHEST);
}
/*
* Erase part of a window
*/
void erase_window_part(WINDOW *win, int first_col, int first_row,
int last_col, int last_row)
{
int c, r;
for (r = first_row; r <= last_row; r++){
for (c = first_col; c <= last_col; c++){
mvwprintw(win, r, c, " ");
}
}
wnoutrefresh(win);
}
/* draws a popup window */
WINDOW * popup(int pop_row, int pop_col,
int pop_y, int pop_x, char *pop_lab)
{
char *txt_pop = _("Press any key to continue...");
char label[80];
WINDOW *popup_win;
popup_win = newwin(pop_row, pop_col, pop_y, pop_x);
custom_apply_attr(popup_win, ATTR_HIGHEST);
box(popup_win, 0, 0);
sprintf(label, "%s", pop_lab);
win_show(popup_win, label);
mvwprintw(popup_win, pop_row - 2, pop_col - (strlen(txt_pop) + 1), "%s",
txt_pop);
custom_remove_attr(popup_win, ATTR_HIGHEST);
wnoutrefresh(popup_win);
doupdate();
return popup_win;
}
/* prints in middle of a panel */
void
print_in_middle(WINDOW * win, int starty, int startx, int width, char *string)
{
int length, x, y;
float temp;
if (win == NULL)
win = stdscr;
getyx(win, y, x);
if (startx != 0)
x = startx;
if (starty != 0)
y = starty;
if (width == 0)
width = 80;
length = strlen(string);
temp = (width - length) / 2;
x = startx + (int) temp;
custom_apply_attr(win, ATTR_HIGHEST);
mvwprintw(win, y, x, "%s", string);
custom_remove_attr(win, ATTR_HIGHEST);
}
/*
* Getstring allows to get user input and to print it on a window,
* even if noecho() is on.
*/
void getstring(win, colr, string, start_x, start_y)
WINDOW *win;
int colr;
char *string;
int start_x, start_y;
{
int ch;
int charcount = 0;
custom_apply_attr(win, ATTR_HIGHEST);
if (start_x != -1)
wmove(win, start_y, start_x);
while ((ch = wgetch(win)) != '\n') {
if ((ch == KEY_BACKSPACE) ||
(ch == 330) ||
(ch == 263) ||
(ch == 127) ||
(ch == CTRL('H')) ) {
if (charcount > 0) {
string--;
charcount--;
wmove(win, start_y, start_x + charcount);
waddch(win, ' ');
wmove(win, start_y, start_x + charcount);
}
} else {
*string++ = ch;
charcount++;
waddch(win, ch);
}
doupdate();
}
*string = 0;
custom_remove_attr(win, ATTR_HIGHEST);
return;
}
/* checks if a string is only made of digits */
int is_all_digit(char *string)
{
int digit, i;
int all_digit;
digit = 0;
all_digit = 0;
for (i = 0; i <= strlen(string); i++)
if (isdigit(string[i]) != 0)
digit++;
if (digit == strlen(string))
all_digit = 1;
return all_digit;
}
/* draw panel border in color */
void border_color(WINDOW * window, int bcolr)
{
int color_attr = A_BOLD;
int no_color_attr = A_BOLD;
if (colorize) {
wattron(window, color_attr | COLOR_PAIR(bcolr));
box(window, 0, 0);
} else {
wattron(window, no_color_attr);
box(window, 0, 0);
}
if (colorize) {
wattroff(window, color_attr | COLOR_PAIR(bcolr));
} else {
wattroff(window, no_color_attr);
}
wnoutrefresh(window);
}
/* draw panel border without any color */
void border_nocolor(WINDOW * window)
{
int colr = 9;
int color_attr = A_BOLD;
int no_color_attr = A_DIM;
if (colorize) {
wattron(window, color_attr | COLOR_PAIR(colr));
} else {
wattron(window, no_color_attr);
}
box(window, 0, 0);
if (colorize) {
wattroff(window, color_attr | COLOR_PAIR(colr));
} else {
wattroff(window, no_color_attr);
}
wnoutrefresh(window);
}
/* prints and scroll text in a window */
void scroller(WINDOW *win, char *mesg, int x, int y, int nb_row, int nb_col)
{
int x_offset = 3;
int y_offset = 3;
int text_len = nb_col - 2 * x_offset;
int text_max_row = nb_row - 3;
int nlin, i, j, k;
int last_blank_i, last_blank_j;
char buf[] = " ";
char *next_mesg = _("-- Press 'N' for next page --");
char *prev_mesg = _("-- Press 'P' for previous page --");
int ch;
int which_page; //first page : 0, second page : 1
i = 0; //position in the message
j = 0; //x position on the current line
nlin = 1; //line number
last_blank_j = 0;
last_blank_i = 0;
which_page = 0;
while (i <= strlen(mesg)) {
if ((i == strlen(mesg)) & (which_page == 1)) {
// we have finished writing text and we are on second page
custom_apply_attr(win, ATTR_HIGHEST);
mvwprintw(win, nb_row - 2,
nb_col - (strlen(prev_mesg) + 2), "%s",
prev_mesg);
custom_remove_attr(win, ATTR_HIGHEST);
wmove(swin, 0, 0);
wnoutrefresh(win);
wnoutrefresh(swin);
doupdate();
ch = wgetch(win);
if ( (ch == 'P') | (ch == 'p') ) {
erase_window_part(win, y + 1, x + 3, nb_col - 2, nb_row - 2);
nlin = 1;
j = 0;
i = 0;
which_page = 0;
} else { //erase last line and exit next-prev page mode
for (k = 1; k < nb_col - 2; k++)
mvwprintw(win, nb_row - 2, k, " ");
break;
}
}
if (nlin == text_max_row - 2) { // we reach the last line
custom_apply_attr(win, ATTR_HIGHEST);
mvwprintw(win, nb_row - 2,
nb_col - (strlen(next_mesg) + 2), "%s",
next_mesg);
custom_remove_attr(win, ATTR_HIGHEST);
wmove(swin, 0, 0);
wnoutrefresh(win);
wnoutrefresh(swin);
doupdate();
ch = wgetch(win);
if ( (ch == 'N') | (ch == 'n') ) {
erase_window_part(win, y + 1, x + 3, nb_col - 2, nb_row - 2);
nlin = 1;
j = 0;
which_page = 1;
} else {
for (k = 1; k < nb_col - 2; k++)
mvwprintw(win, nb_row - 2, k, " ");
break;
}
}
//write text
strncpy(buf, mesg + i, 1);
i++;
j++;
if ((strncmp(buf, "<EFBFBD>", 1) == 0)) { //<2F> is the character for a new line
buf[0] = '\0';
mvwprintw(win, x + x_offset + nlin, y + y_offset + j,
"%s", buf);
nlin++;
j = 0;
} else {
if (j == text_len - 1) { // if we reach the terminal border
for (k = last_blank_j; k <= text_len - 1;
k++)
mvwprintw(win, x + x_offset + nlin,
y + y_offset + k, " ");
nlin++;
i = last_blank_i;
j = 0;
} else {
if ((strncmp(buf, " ", 1) == 0)) //space between words
{
last_blank_j = j; //save position
last_blank_i = i;
}
mvwprintw(win, x + x_offset + nlin,
y + y_offset + j, "%s", buf);
}
}
}
wmove(swin, 0, 0);
wnoutrefresh(win);
wnoutrefresh(swin);
}
/* Draws the status bar */
void status_bar(int which_pan, int colr, int nc_bar, int nl_bar)
{
int nb_item_cal, nb_item_oth;
int len_let, len_des, spc_lad;
int spc_bet_cal_itm, spc_bet_oth_itm;
int len_cal_itm, len_oth_itm;
nb_item_cal = 10; /* max item number to display in status bar */
nb_item_cal = ceil(nb_item_cal / 2); /* two lines to display items */
nb_item_oth = 12;
nb_item_oth = ceil(nb_item_oth / 2);
len_let = 3;
len_des = 8;
spc_lad = 1;
spc_bet_cal_itm =
floor((col -
nb_item_cal * (len_let + len_des +
spc_lad)) / nb_item_cal);
spc_bet_oth_itm =
floor((col -
nb_item_oth * (len_let + len_des +
spc_lad)) / nb_item_oth);
len_cal_itm = len_let + spc_lad + len_des + spc_bet_cal_itm;
len_oth_itm = len_let + spc_lad + len_des + spc_bet_oth_itm;
erase_window_part(swin, 0, 0, nc_bar, nl_bar);
if (which_pan == 0) {
custom_apply_attr(swin, ATTR_HIGHEST);
mvwprintw(swin, 0, 0, " ?");
mvwprintw(swin, 1, 0, " Q");
mvwprintw(swin, 0, len_cal_itm, " R");
mvwprintw(swin, 1, len_cal_itm, " S");
mvwprintw(swin, 0, 2 * len_cal_itm, "H/L");
mvwprintw(swin, 1, 2 * len_cal_itm, "J/K");
mvwprintw(swin, 0, 3 * len_cal_itm, " G");
mvwprintw(swin, 1, 3 * len_cal_itm, "Tab");
mvwprintw(swin, 0, 4 * len_cal_itm, " C");
custom_remove_attr(swin, ATTR_HIGHEST);
wnoutrefresh(swin);
mvwprintw(swin, 0, len_let + spc_lad, _("Help"));
mvwprintw(swin, 1, len_let + spc_lad, _("Quit"));
mvwprintw(swin, 0, len_cal_itm + len_let + spc_lad,
_("Redraw"));
mvwprintw(swin, 1, len_cal_itm + len_let + spc_lad, _("Save"));
mvwprintw(swin, 0, 2 * len_cal_itm + len_let + spc_lad,
_("-/+1 Day"));
mvwprintw(swin, 1, 2 * len_cal_itm + len_let + spc_lad,
_("-/+1 Week"));
mvwprintw(swin, 0, 3 * len_cal_itm + len_let + spc_lad,
_("GoTo"));
mvwprintw(swin, 1, 3 * len_cal_itm + len_let + spc_lad,
_("Chg View"));
mvwprintw(swin, 0, 4 * len_cal_itm + len_let + spc_lad,
_("Config"));
} else {
custom_apply_attr(swin, ATTR_HIGHEST);
mvwprintw(swin, 0, 0, " ?");
mvwprintw(swin, 1, 0, " Q");
mvwprintw(swin, 0, len_oth_itm, " R");
mvwprintw(swin, 1, len_oth_itm, " S");
mvwprintw(swin, 0, 2 * len_oth_itm, "J/K");
mvwprintw(swin, 1, 2 * len_oth_itm, "Tab");
mvwprintw(swin, 0, 3 * len_oth_itm, " A");
mvwprintw(swin, 1, 3 * len_oth_itm, " D");
mvwprintw(swin, 0, 4 * len_oth_itm, " G");
mvwprintw(swin, 1, 4 * len_oth_itm, " V");
mvwprintw(swin, 0, 5 * len_oth_itm, " C");
custom_remove_attr(swin, ATTR_HIGHEST);
wnoutrefresh(swin);
mvwprintw(swin, 0, len_let + spc_lad, _("Help"));
mvwprintw(swin, 1, len_let + spc_lad, _("Quit"));
mvwprintw(swin, 0, len_oth_itm + len_let + spc_lad,
_("Redraw"));
mvwprintw(swin, 1, len_oth_itm + len_let + spc_lad, _("Save"));
mvwprintw(swin, 0, 2 * len_oth_itm + len_let + spc_lad,
_("Up/Down"));
mvwprintw(swin, 1, 2 * len_oth_itm + len_let + spc_lad,
_("Chg View"));
mvwprintw(swin, 0, 3 * len_oth_itm + len_let + spc_lad,
_("Add Item"));
mvwprintw(swin, 1, 3 * len_oth_itm + len_let + spc_lad,
_("Del Item"));
mvwprintw(swin, 0, 4 * len_oth_itm + len_let + spc_lad,
_( "GoTo"));
mvwprintw(swin, 1, 4 * len_oth_itm + len_let + spc_lad,
_("View"));
mvwprintw(swin, 0, 5 * len_oth_itm + len_let + spc_lad,
_("Config"));
}
wnoutrefresh(swin);
}
long date2sec(unsigned year, unsigned month, unsigned day, unsigned hour,
unsigned min)
{
struct tm start, *lt;
time_t tstart, t;
t = time(NULL);
lt = localtime(&t);
start = *lt;
start.tm_mon = month;
start.tm_mday = day;
start.tm_year = year;
start.tm_hour = hour;
start.tm_min = min;
start.tm_sec = 0;
start.tm_isdst = -1;
start.tm_year -= 1900;
start.tm_mon--;
tstart = mktime(&start);
if (tstart == -1) {
fputs(_("FATAL ERROR in date2sec: failure in mktime\n"), stderr);
fprintf(stderr, "%u %u %u %u %u\n", year, month, day, hour, min);
exit(EXIT_FAILURE);
}
return tstart;
}
/*
* Returns the date in seconds from year 1900.
* If no date is entered, current date is chosen.
*/
long
get_sec_date(int year, int month, int day)
{
struct tm *ptrtime;
time_t timer;
long long_date;
char current_day[3], current_month[3] ,current_year[5];
if (year == 0 && month == 0 && day == 0) {
timer = time(NULL);
ptrtime = localtime(&timer);
strftime(current_day, 3, "%d", ptrtime);
strftime(current_month, 3, "%m", ptrtime);
strftime(current_year, 5, "%Y", ptrtime);
month = atoi(current_month);
day = atoi(current_day);
year = atoi(current_year);
}
long_date = date2sec(year, month, day, 0, 0);
return long_date;
}
long min2sec(unsigned minutes)
{
return minutes * 60;
}
/*
* Checks if a time has a good format.
* The format could be either HH:MM or H:MM or MM, and we should have:
* 0 <= HH <= 24 and 0 <= MM < 999.
* This function returns 1 if the entered time is correct and in
* [h:mm] or [hh:mm] format, and 2 if the entered time is correct and entered
* in [mm] format.
*/
int check_time(char *string)
{
int ok = 0;
char hour[] = " ";
char minutes[] = " ";
if ( // format test [MM]
((strlen(string) == 2) || (strlen(string) == 3)) &
(isdigit(string[0]) != 0) &
(isdigit(string[1]) != 0)
) { // check if we have a valid time
strncpy(minutes, string, 2);
if ( atoi(minutes) >= 0)
ok = 2;
}
else if ( // format test [H:MM]
(strlen(string) == 4) &
(isdigit(string[0]) != 0) &
(isdigit(string[2]) != 0) &
(isdigit(string[3]) != 0) & (string[1] == ':')
) { // check if we have a valid time
strncpy(hour, string, 1);
strncpy(minutes, string + 2, 2);
if ((atoi(hour) <= 24) & (atoi(hour) >=
0) & (atoi(minutes) <
60) & (atoi(minutes) >= 0))
ok = 1;
}
else if ( //format test [HH:MM]
(strlen(string) == 5) &
(isdigit(string[0]) != 0) &
(isdigit(string[1]) != 0) &
(isdigit(string[3]) != 0) &
(isdigit(string[4]) != 0) & (string[2] == ':')
) { // check if we have a valid time
strncpy(hour, string, 2);
strncpy(minutes, string + 3, 2);
if ((atoi(hour) <= 24) & (atoi(hour) >=
0) & (atoi(minutes) <
60) & (atoi(minutes) >= 0))
ok = 1;
}
return ok;
}
/*
* Display a scroll bar when there are so many items that they
* can not be displayed inside the corresponding panel.
*/
void draw_scrollbar(WINDOW *win, int y, int x, int length,
int bar_top, int bar_bottom, bool hilt)
{
mvwvline(win, bar_top, x, ACS_VLINE, bar_bottom - bar_top);
if (hilt)
custom_apply_attr(win, ATTR_HIGHEST);
wattron(win, A_REVERSE);
mvwvline(win, y, x, ' ', length);
wattroff(win, A_REVERSE);
if (hilt)
custom_remove_attr(win, ATTR_HIGHEST);
}
/*
* Print an item (either an appointment, event, or todo) in a
* popup window. This is useful if an item description is too
* long to fit in its corresponding panel window.
*/
void item_in_popup(char *saved_a_start, char *saved_a_end, char *msg,
char *pop_title)
{
WINDOW *popup_win;
popup_win = popup(row - 4, col - 2, 1, 1, pop_title);
if (strncmp(pop_title, _("Appointment"), 11) == 0) {
mvwprintw(popup_win, 4, 4, " - %s -> %s",
saved_a_start, saved_a_end);
}
scroller(popup_win, msg, 1, 1, row - 4, col - 2);
wmove(swin, 0, 0);
doupdate();
wgetch(popup_win);
delwin(popup_win);
}
/* Show the window with a border and a label */
void win_show(WINDOW * win, char *label)
{
int startx, starty, height, width;
getbegyx(win, starty, startx);
getmaxyx(win, height, width);
box(win, 0, 0);
mvwaddch(win, 2, 0, ACS_LTEE);
mvwhline(win, 2, 1, ACS_HLINE, width - 2);
mvwaddch(win, 2, width - 1, ACS_RTEE);
print_in_middle(win, 1, 0, width, label);
}
/*
* Print an item description in the corresponding panel window.
*/
void display_item(WINDOW *win, int incolor, char *msg, int len,
int y, int x)
{
char buf[len];
if (incolor == 0)
custom_apply_attr(win, ATTR_HIGHEST);
if (strlen(msg) < len) {
mvwprintw(win, y, x, "%s", msg);
} else {
strncpy(buf, msg, len - 1);
buf[len - 1] = '\0';
mvwprintw(win, y, x, "%s...", buf);
}
if (incolor == 0)
custom_remove_attr(win, ATTR_HIGHEST);
}

55
src/utils.h Executable file
View File

@@ -0,0 +1,55 @@
/* $calcurse: utils.h,v 1.1 2006/07/31 21:00:03 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#ifndef CALCURSE_UTILS_H
#define CALCURSE_UTILS_H
void status_mesg(char *mesg_line1, char *mesg_line2);
void erase_window_part(WINDOW *win, int first_col, int first_row,
int last_col, int last_row);
WINDOW *popup(int pop_row, int pop_col,
int pop_y, int pop_x, char *pop_lab);
void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string);
void getstring(WINDOW *win, int colr, char *string, int start_x, int start_y);
int is_all_digit(char *string);
void border_color(WINDOW *window, int bcolr);
void border_nocolor(WINDOW *window);
void scroller(WINDOW *win, char *, int x, int y, int nb_row, int nb_col);
void status_bar(int which_pan, int colr, int nc_bar, int nl_bar);
long date2sec(unsigned year, unsigned month, unsigned day, unsigned hour,
unsigned min);
long get_sec_date(int year, int month, int day);
long min2sec(unsigned minutes);
int check_time(char *string);
void draw_scrollbar(WINDOW *win, int y, int x, int length,
int bar_top, int bar_bottom, bool hilt);
void item_in_popup(char *saved_a_start, char *saved_a_end, char *msg,
char *pop_title);
void win_show(WINDOW * win, char *label);
void display_item(WINDOW *win, int incolor, char *msg,
int len, int y, int x);
#endif /* CALCURSE_UTILS_H */

85
src/vars.c Executable file
View File

@@ -0,0 +1,85 @@
/* $calcurse: vars.c,v 1.1 2006/07/31 21:00:03 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#include "i18n.h"
#include "vars.h"
/*
* variables to store window size
*/
int col = 0, row = 0;
/* variable to tell if the terminal supports color */
bool colorize = false;
/*
* variables to store calendar names
*/
int days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
char *monthnames[12] =
{ N_("January"),
N_("February"),
N_("March"),
N_("April"),
N_("May"),
N_("June"),
N_("July"),
N_("August"),
N_("September"),
N_("October"),
N_("November"),
N_("December") };
char *daynames[8] =
{ N_("Sun"),
N_("Mon"),
N_("Tue"),
N_("Wed"),
N_("Thu"),
N_("Fri"),
N_("Sat"),
N_("Sun") };
/*
* variables to store data path names, which are initialized in
* io_init()
*/
char path_dir[] = "";
char path_todo[] = "";
char path_apts[] = "";
char path_conf[] = "";
/*
* Variables to handle calcurse windows:
* cwin = calendar window
* awin = appointment window
* twin = todo window
* swin = status bar window
*/
WINDOW *awin = NULL, *cwin = NULL, *twin = NULL, *swin = NULL;
/* Variable to handle pads. */
struct pad_s *apad;

69
src/vars.h Executable file
View File

@@ -0,0 +1,69 @@
/* $calcurse: vars.h,v 1.1 2006/07/31 21:00:03 culot Exp $ */
/*
* Calcurse - text-based organizer
* Copyright (c) 2004-2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Send your feedback or comments to : calcurse@culot.org
* Calcurse home page : http://culot.org/calcurse
*
*/
#ifndef CALCURSE_VARS_H
#define CALCURSE_VARS_H
#include <ncurses.h>
#include <stdbool.h>
#define DIR_NAME ".calcurse"
#define TODO_PATH ".calcurse/todo"
#define APTS_PATH ".calcurse/apts"
#define CONF_PATH ".calcurse/conf"
#define MAX_LENGTH 512
#define CTRL(x) ((x) & 0x1f)
#define ATTR_FALSE 0
#define ATTR_TRUE 1
#define ATTR_LOWEST 2
#define ATTR_LOW 3
#define ATTR_MIDDLE 4
#define ATTR_HIGH 5
#define ATTR_HIGHEST 6
struct pad_s {
int width;
int length;
int first_onscreen; /* first line to be displayed inside window */
WINDOW *ptrwin; /* pointer to the pad window */
};
extern int col, row;
extern bool colorize;
extern int days[12];
extern char *monthnames[12];
extern char *daynames[8];
extern char path_dir[MAX_LENGTH];
extern char path_todo[MAX_LENGTH];
extern char path_apts[MAX_LENGTH];
extern char path_conf[MAX_LENGTH];
extern WINDOW *awin, *cwin, *twin, *swin;
extern struct pad_s *apad;
#endif /* CALCURSE_VARS_H */