246 Commits

Author SHA1 Message Date
Lars Henriksen
42abbf5346 Filter option: invert
New filter option: --filter-invert. When present it inverts (negates)
the other filter options combined. This is mostly useful with the -G
option (with -Q the output is limited by the query range (day range)).

The ouput from "calcurse -G <filter options>" is the (set) complement of
"calcurse -G <filter options> --filter-invert". Here <filter options>
may be any combination of filter options.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-01-07 16:58:06 +01:00
Lars Henriksen
4285e88593 Rewrite of io_init()
The introduction of the "-C <confdir>" option is an opportunity to
review the initialization of data paths. It lead to a rewrite.

Two "root" directories are used (data and configuration files); by
default they are identical. The statically allocated path buffers are
turned into dynamically allocated buffers.

Missing files/directories now include hooks.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-12-14 10:35:11 +01:00
Lukas Fleischer
e3ca60eefe Fix default paths for configuration files
Addresses a copy-paste typo introduced in commit 65064ce (Check if the
configuration folder exists, 2018-08-25).

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-11-10 12:34:47 +01:00
Quentin Hibon
65064ceed1 Check if the configuration folder exists
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-10-21 20:02:57 +02:00
Lars Henriksen
3d93ffa7ca Periodic save: report cancelled save
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-10-21 20:02:57 +02:00
Lars Henriksen
4b192c0773 Error return code for io_reload_data()
The return code from new_data() and io_load_data() is explicitly defined as a
bit mask. A file access error is recognised and reported back to the user.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-10-21 20:02:57 +02:00
Lars Henriksen
ff402d21ab New save/load mutex strategy
A complete save or reload operation is made up of several cooperating lower
level function calls. In stead of protecting the lower level read or write calls
on the data files, the entire save or load operation is protected in order to
ensure its integrity.

Thus mutex protection has been moved from the level:

	io_load_data(), io_merge_data(), new_data(),

to two functions at the higher level:

	io_save_cal(), io_reload_data().

The protection includes pre- and post-hooks.

The function io_load_data() needs no protection when calcurse starts up
(threads not yet started) or runs in non-interactive mode (no threads involved).

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-10-21 20:02:57 +02:00
Lars Henriksen
837f629341 Periodic save mutex
To protect the periodic save from being cancelled during a save operation.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-10-21 20:02:57 +02:00
Lars Henriksen
657f007cd2 Distinguish between interactive and periodic save
A new argument to io_save_cal() makes it possible for the periodic save thread
to avoid 1) user interaction and 2) overwriting new data.

At the moment the thread has no way to report on the result of the save.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-10-21 20:01:34 +02:00
Lars Henriksen
39ab4665e6 Data save and removal of the progress bar
The function io_save_cal() saves apts, todos, configuration data and key
bindings. The configuration and key files do not belong with the two data
files, but the progress bar function assumes that all four files are saved in
a fixed sequence. Since it is used nowhere else and contains unused parts,
the function has been removed.

A return code for file access error is introduced, and the EXIT macro moved to
the command level in calcurse.c.

Save of configuration and key data were already moved to the configuration menu
in commit 0124618, A save refinement: no action if everything is unchanged.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-10-21 20:01:34 +02:00
Lars Henriksen
8b39637a62 Move user information after save/reload to the command level
Moving user information to calcurse.c makes it easier to perform the actual
save/reload operatons in io.c, e.g. it is possible to load instead of
reload after a merge in conflict resolving.

The save/reload operations are of such importance that the user should always be
informed of the result (it's a bit disquieting when there is no reaction to a
save or reload command). Hence, the save/reload status messages are no longer
conditioned by show_dialogs(). No confirmation is asked for, so a message stays
until the status bar is updated by another action.

Care is taken to inform about save/reload actions that result in no change.

Texts are kept concise because of the limited message area. When conflicts are
present, whether saving or reloading, the "continue/merge/cancel" pattern seems
easier to grasp.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-10-21 20:01:34 +02:00
Lars Henriksen
d7777ed44e A save refinement: no action if everything is unchanged
A reload action will do nothing if in-memory data as well as data files are
unchanged. This commit accomplishes the equivalent for a save action.

Because saving of configuration data and key bindings are mixed up with saving
of data files, any changes in those will only be saved if data files also have
changed. Hence, configuration data and key bindings are also saved upon exit
from the configuration menu.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-10-21 20:01:34 +02:00
Lars Henriksen
5ad0019b23 Only reload if data files were changed (replacement)
This is a replacement for commits 57dd3d6 and 912124b.

The idea is to move the check for modified files and the list initialization
into io_load_data(), and let io_load_data() decide what to load. A new
argument is used to force a load.

The return code from new_data() (the renamed version of
io_check_data_files_modified()) tells which files have changed.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-10-21 20:01:34 +02:00
Lars Henriksen
ab0fe68225 Reload data after resolving save conflict (improved)
After resolving a save conflict with the merge tool, a save operation has,
in effect, occurred, and data files must be reloaded to import the result of
the conflict resolution.

This is a replacement for commit 2fe9c7e. The operations concerned with the user
interface are kept out the io-operations (as in all other cases) and take place
at the command-level in calcurse.c. and not at the io-level (io.c).

Shorter, more concise prompt texts.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-10-21 20:01:34 +02:00
Lars Henriksen
8c2ccebe35 Handling of modified flag
The flag modified (io.c) keeps track of the memory state of data:
	modified == 0: unchanged since load or last save
	modified == 1: changed since load or last save
It is now unset in io_load_data() and io_save_cal() only.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-10-21 20:01:34 +02:00
Lars Henriksen
e97360df71 Update windows at the right level
The wins_update() call is the responsibility of the caller of
io_resolve_save_conflict().

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-10-21 20:01:34 +02:00
Lars Henriksen
a5ae7256b3 Stop/start the notify main thread at the right level
The thread is stopped/started in wins_prepare/unprepare_external() when hooks
are run. There is no need to do it in io_reload_data(). In fact, because of the
nested calls

notify_stop_main_thread() <--- io_reload_data()
...
	notify_stop_main_thread() <--- hook/wins_prepare_external()
	...
	notify_start_main_thread() <--- hook/wins_unprepare_external()
...
notify_start_main_thread() <--- io_reload_data()

the thread has been running after the first hook anyway.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-10-21 20:01:34 +02:00
Lars Henriksen
a94b0ecde0 Fix window update after hook execution
The introduction of hooks raised a problem with window updates. The diagnosis
in commit feb059e8 (Fix segmentation fault on reload with pre-load hook) was
right, the cure was wrong.

The problem is wins_update(), not the listbox contents. The wins_update() call
does not belong in wins_unprepare_external() (or in io_reload_data()), but at a
higher level. It should be called _after_ reload, as indeed it is in
key_generic_reload() when the listbox contents have been updated (todo as well
as appointments). The call was introduced in commit 8ae75f3 without comment.

The todo updates in io_reload_data() also belong in key_generic_reload() where
they were before commit 7f06c252.

When saving data, all panels must be updated in case a hook was executed.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-10-21 20:01:34 +02:00
Quentin Hibon
e9611ce3a6 Use a path instead of a file for -C option
Allows to specify a configuration directory containing:
* conf
* keys
* hooks

When used in combination with -D $ddir, $ddir contains all the other
files not mentioned above.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-08-05 18:36:25 +02:00
Lars Henriksen
5e53708648 Solve deadlock in notification bar
calcurse deadlocks when

1) an upcoming appointment is on display in the notification bar,
2) an external command (like help) is started,
3) the time for the upcoming appointment arrives, and
4) the external command is exited.

The notification bar thread is stopped while the external command is
running. Upon exit from the external command, the n-bar thread is
restarted and calcurse locks.

The cause is the way in which the main notification bar thread is
stopped:

static pthread_t notify_t_main;
void notify_stop_main_thread(void)
{
	if (notify_t_main) {
		pthread_cancel(notify_t_main);
		pthread_join(notify_t_main, NULL);
	}
}

Objects of type pthread_t are opaque and should not be accessed
directly.  Initially notify_t_main is an uninitialised static variable
(0), but later it has a value, which may or may not be the thread id of
the notification main thread.

Note that the thread id after exit of a thread may become the thread id
of a new thread. Thus the variable set when the thread is created, is
invalid after exit of the thread.

Specifically, the first time notify_stop_main_thread() is called (by
notify_start_main_thread() before the thread is created) is harmless
(because notify_t_main is 0). Calling notify_stop_main_thread() later
may be either

OK
    because the main thread is running, or
harmless
    because no thread with id notify_t_main is running: the two
    functions will fail with return value ESRCH (no such process), or
fatal
    because an unrelated thread with this thread id is running: it will
    be cancelled, and the join may or may not succeed depending on
    whether the thread is joinable or detached.

The "unrelated thread" could be the next-appointment thread,
notify_thread_app, launched by notify_check_next_app().

Always calling notify_stop_main_thread() before starting the main thread
becomes fatal when notify_check_next_app() is called shortly before
notify_start_main_thread(). This is the case in the scenario described.
The next-app-thread is then running when notify_stop_main_thread() is
called, and apparently it has the thread id of the old main thread
(confirmed by logging the return values from pthread_cancel() and
pthread_join(); the first succeeds while the second fails with EINVALID
which means that the thread is not joinable). The next-app-thread will
therefore exit without unlocking mutexes.

Ensure that notify_t_main, in case the notify main thread is not
running, has a value that it will never have when it is running. A
possibility is the thread id of the main() calcurse process (returned by
pthread_self()).

Check for this condition in notify_stop_main_thread() and set
notify_t_main when the thread is stopped.

Similar changes have been introduced for the periodic save thread and
the calendar date thread.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-07-28 14:06:15 +02:00
Lukas Fleischer
e55aead126 Only lock save mutex as short as possible
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-06-03 10:28:28 +02:00
Quentin Hibon
407d5abd23 Add option to specify the configuration file used
The configuration file (~/.calcurse/conf by default) can now be
specified with -C or --conf.

Workaround for GitHub issue #86.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-05-28 06:29:09 +02:00
Lukas Fleischer
2cd60c78cf Always NUL-terminate buffer in io_load_keys()
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-05-26 11:52:41 +02:00
Lukas Fleischer
912124bcdc Run pre-load hook before testing for modifications
The pre-load hook is often used to manipulate the data files before
loading, such as by synchronizing with a remote calendar. Make sure we
always execute the pre-load hook upon reloads, even if the data files
have not been modified.

Fixes GitHub issue #98.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-05-23 17:52:05 +02:00
Lukas Fleischer
2d19605ba8 Unlock the save mutex as early as possible
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-05-19 10:34:19 +02:00
Lukas Fleischer
16e7aecd29 Do not prompt when non-interactive import fails
When running calcurse in non-interactive mode, we should not expect any
user input. This is even more important in the case of iCal imports
which are used by calcurse-caldav to import events from CalDAV servers.

Partly fixes GitHub issue #73.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2017-11-23 08:57:45 +01:00
Lukas Fleischer
2fe9c7efce Reload data after resolving save conflict
After resolving a save conflict with the merge tool, we need to reload
the data files to import the result of the conflict resolution.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2017-09-08 21:23:25 +02:00
Lukas Fleischer
e943a8a4db Unset modification flag after merging
Turn off the local modification flag to avoid a bogus warning when
reloading the data files immediately after the merge process.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2017-09-08 21:22:22 +02:00
Lukas Fleischer
f69698569f Recompute hashes after saving
After saving the data files, we need to recompute and store the hashes
to make sure the updated contents is reflected.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2017-09-08 21:21:45 +02:00
Lukas Fleischer
380124c7a2 Factor out hash computation
Move code to compute the hash of a data file to a separate function.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2017-09-08 21:21:11 +02:00
Lukas Fleischer
7a0134204e Use a shared input/output mutex
Replace the save mutex with a common mutex, which is locked whenever
read or write operations on the data files are performed. Also, since
this mutex is an implementation detail, mark the locking functions
static and remove them from the header file.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2017-09-08 21:08:54 +02:00
Lukas Fleischer
57dd3d6b66 Only reload if data files were changed
Instead of blindly reloading data in io_reload_data(), compare the
stored hashes of the data files with hashes of the current file contents
and only reload if any of the hashes differs.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2017-09-08 21:08:54 +02:00
Lukas Fleischer
ba85d9b6f5 Factor out check for external modifications
Move the check to compare the stored hashes of the data files with the
current hash to a separate function. This makes the code easier to read
and reusable.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2017-09-08 21:08:54 +02:00
Lukas Fleischer
9137590e7a Do not blindly overwrite files when saving
When reading the data files, compute a cryptographic hash of the file
contents and store it. When saving the files later, ensure that the hash
still matches the current file contents. If it does not, show a warning
to the user and ask whether she wants to execute the merge tool.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2017-09-08 21:08:53 +02:00
Lukas Fleischer
fb1524b4e2 Use .new as file extension when merging
Using the file name extension .sav and naming the variables "backup" is
slightly misleading, since the affected files actually contain the
updated content and not some old snapshot. Use the term "new" instead.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2017-09-08 21:08:53 +02:00
Lukas Fleischer
e5a824e576 Factor out merge routine
Move the code, which runs the merge tool with current and updated data
files, to a separate function to make it reusable.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2017-09-08 21:08:53 +02:00
Lukas Fleischer
53f0f1d2e3 Add a function to wait for any key press
Introduce a new function keys_wait_for_any_key() and use it instead of
wgetch() whenever the return value is discarded.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2017-09-03 16:37:35 +02:00
Lukas Fleischer
43cd40e8ce Include stdarg.h when using variable argument lists
Fixes GitHub issue #36.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2017-07-28 16:09:43 +02:00
Lukas Fleischer
9f6678bc49 Update copyright ranges
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2017-01-12 08:40:30 +01:00
Lukas Fleischer
9ef5fe2191 Always use memory management wrappers
Use mem_*() wrappers instead of directly accessing libc functions when
allocating/deallocating memory.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2016-10-13 19:51:43 +02:00
Lukas Fleischer
feb059e8cf Fix segmentation fault on reload with pre-load hook
We need to manually force a reinitialization of the todo item list box
before reloading the items. Otherwise, the list box contains dangling
references to the linked list of todo items which has already been
cleared at this point. After the pre-load hook is called, the windows
are redrawn by wins_unprepare_external() and these invalid references
are accessed, leading to a segmentation fault.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2016-02-15 19:03:26 +01:00
Lukas Fleischer
07954626c6 Support format strings when dumping imported items
In commit 3eae7ce (Add --list-imported command line option, 2016-01-12),
we added an option to print the hashes of imported items to stdout.
Extend this command line option such that it dumps the items using the
specified formatting strings. With the new behavior it is, for example,
easier to check items for import errors.

Also, rename the option from --list-imported to --dump-imported (it is
not part of any official release yet so we do not need to care about
backwards compatibility).

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2016-02-11 18:33:57 +01:00
Lukas Fleischer
e9c8197e4e Refactor grep mode
Split io_save_{apts,todo}() into functions that write raw data to a file
and functions that write formatted items to stdout such that one can
easily extend the grep mode for format string support in a follow-up
commit.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2016-02-05 19:06:54 +01:00
Lukas Fleischer
978d24a9d2 Update copyright ranges
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2016-01-30 11:21:53 +01:00
Lukas Fleischer
beea88e5fe Use a separate field for the completed status
Add a new field that indicates whether a todo item is completed or not
instead of encoding completed todo items by negative priorities.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2016-01-18 18:08:34 +01:00
Lukas Fleischer
c3648f08c7 Run pre-save and post-save hooks on reload
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2016-01-15 18:36:41 +01:00
Lukas Fleischer
caee34449c Export item UIDs upon request
Add a new --export-uid command line option that adds each item's hash to
the UID property when exporting.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2016-01-15 18:25:05 +01:00
Lukas Fleischer
39a3c04144 Import data from stdin when the import file is "-"
Support "-" as file name to the -i/--import option and read from stdin
when that file is specified.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2016-01-15 08:44:57 +01:00
Lukas Fleischer
576784bca8 Hide import statistics in quiet mode
Do not show the import summary when system dialogs are disabled or when
the --quiet option is specified, even if calcurse is executed in
non-interactive mode.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2016-01-13 17:39:44 +01:00
Lukas Fleischer
3eae7ce828 Add --list-imported command line option
When this option is used together with -i/--import, the object
identifiers of imported objects are printed to stdout.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2016-01-13 17:39:44 +01:00