aboutsummaryrefslogtreecommitdiffstats
path: root/src
Commit message (Collapse)AuthorAgeFilesLines
* Configuration variable for system eventsLars Henriksen2018-10-215-2/+18
| | | | | | | | After user acknowledgement a system event is deleted from the event queue. The configuration variable determines whether it is turned into an appointment (for later inspection) or not. Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Periodic save: report cancelled saveLars Henriksen2018-10-211-1/+3
| | | | Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* System message queueLars Henriksen2018-10-214-0/+112
| | | | | | | | | | | | | | | The screen and user interaction is managed by the main thread. Other parts of calcurse (threads) wishing to use the screen or communicate with the user, must do it via the main thread. For this purpose the main input loop is extended with a message queue. A thread may insert a message in the queue. The main thread tests for messages before listening for user commands. If a message is present, it is displayed (in a popup window) for the user to acknowledge. Depending on the message other actions may be performed, e.g. the message could be turned into a "system appointment/event" and inserted among the usual appointments. Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Quit, autosave and interactive saveLars Henriksen2018-10-211-2/+11
| | | | | | | | Quitting calcurse with auto_save on may lead to an interactive conflict resolution for the save operation. When the result is a cancellation of the save, the quit command is also cancelled. Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Remove the configuraton variable conf.progress_barLars Henriksen2018-10-214-15/+6
| | | | | | | | When loading/saving the configuration file the entry is silently ignored (which means it is removed by the first save). Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk> Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Error return code for io_reload_data()Lars Henriksen2018-10-213-10/+23
| | | | | | | | 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>
* New save/load mutex strategyLars Henriksen2018-10-211-39/+28
| | | | | | | | | | | | | | | | | | | | | | | 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>
* Periodic save mutexLars Henriksen2018-10-211-2/+6
| | | | | | | 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>
* Distinguish between interactive and periodic saveLars Henriksen2018-10-213-9/+17
| | | | | | | | | | 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>
* Data save and removal of the progress barLars Henriksen2018-10-213-128/+27
| | | | | | | | | | | | | | | | | 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>
* Move user information after save/reload to the command levelLars Henriksen2018-10-213-38/+80
| | | | | | | | | | | | | | | | | | | | | 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>
* A save refinement: no action if everything is unchangedLars Henriksen2018-10-212-2/+10
| | | | | | | | | | | | | 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>
* Only reload if data files were changed (replacement)Lars Henriksen2018-10-214-57/+68
| | | | | | | | | | | | | | 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>
* Reload data after resolving save conflict (improved)Lars Henriksen2018-10-213-31/+51
| | | | | | | | | | | | | | | 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>
* Handling of modified flagLars Henriksen2018-10-212-3/+2
| | | | | | | | | | 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>
* Update windows at the right levelLars Henriksen2018-10-211-1/+1
| | | | | | | | 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>
* Stop/start the notify main thread at the right levelLars Henriksen2018-10-211-7/+0
| | | | | | | | | | | | | | | | | | | 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>
* Fix window update after hook executionLars Henriksen2018-10-213-14/+4
| | | | | | | | | | | | | | | | | | | | 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>
* Fix memory leak in run_hook()Lukas Fleischer2018-08-251-2/+4
| | | | | | Fixes GitHub issue #139. Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Minor merge adjustmentsLars Henriksen2018-08-251-36/+43
| | | | | | | | Comments inserted. Slightly different implementations of parse_time() and parse_datetime(). Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Fix memory leak in update_duration()Lars Henriksen2018-08-251-1/+4
| | | | Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Fix seg fault in update_rept()Lars Henriksen2018-08-251-5/+7
| | | | | | | Memory pointers must be initialized at the start in case memory is freed (cleanup) before it is allocated. Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Buffer mixupLars Henriksen2018-08-251-4/+3
| | | | | | Use one (small) buffer long enough to hold a date. Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Major overhaul of appointment/event input routines.Lars Henriksen2018-08-251-194/+241
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When setting start time for a new appointment, a date is disallowed (in all other cases both time and date are still allowed). Both date and time are displayed for the user to correct when an appointment is changed or moved. Built-in help in the status bar for display of input formats. Several bug fixes that resulted in data inconsistencies (end time before start time). The routines use the enhanced parsing funtions to validate input: ui_day_item_add(void) parse_datetime() parse_duration() parse_datetime() ui_day_item_repeat(void) parse_date_duration() parse_date() ui_day_item_edit(void) update_start_time() day_edit_time() parse_datetime() update_duration() parse_duration() parse_datetime() update_rept() parse_date_duration() parse_date() Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Start and end time validation.Lars Henriksen2018-08-252-8/+47
| | | | | | | | | | All appointment times are checked for validity. Overflow by time arithmetic is detected. End times are checked when appointments are moved. Three functions are involved: parse_datetime(), parse_duration() and parse_date_duration(); they all have a new argument for validation purposes. Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* New support functions for input validation.Lars Henriksen2018-08-252-0/+39
| | | | | | check_sec(), overflow_add(), overflow_mul() Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Refactoring update_duration/day_edit_duration.Lars Henriksen2018-08-251-55/+49
| | | | | | Incorporated day_edit_duraton() into update_duration(). Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Make editing of punctual appointments more intuitiveLukas Fleischer2018-08-251-3/+6
| | | | | | | | | | When editing the start time, move the item instead of keeping the previous start time as end time. When editing the end time, start with an empty end time instead of the previous start time. Fixes GitHub issue #89. Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Only stop threads when exiting from interactive modeLukas Fleischer2018-08-251-3/+3
| | | | Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Initialize variables in non-interactive mode in all casesLars Henriksen2018-08-191-3/+1
| | | | | | | | | The changed handling of thread ids implies that they must be initialized before exit of calcurse where they are used. Hence the function vars_init() is now called irrespective of command line arguments. Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk> Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Use a path instead of a file for -C optionQuentin Hibon2018-08-052-24/+27
| | | | | | | | | | | | 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>
* Fix multiple, simultaneous periodic savesLars Henriksen2018-07-281-4/+4
| | | | | | | | | | A new save thread was started every time a positive periodic save value was input in the general options configuration menu. And only one thread can be stopped by entering 0, also when done repeatedly. Always stop the old thread before (possibly) starting a new. Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Solve deadlock in notification barLars Henriksen2018-07-285-16/+28
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* Fix end-before-start inconsistencyLars Henriksen2018-06-051-7/+9
| | | | | | | | | | | | Due to deficient validation, it is possible to get an inconsistent database with an appointment that ends before it begins. Edit an existing one and specify an end time by a date that precedes the start date, or create a new one and give a date as end time that precedes the start. Then exit calcurse; on restart it will report a data error and exit. Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk> Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Fix appointment becoming eventLars Henriksen2018-06-051-4/+4
| | | | | | | | | | | | You try to enter an appointment, but enter an invalid start time (by mistake). Calcurse rejects the input. You enter the correct start time and calcurse asks for the description, not the end time, i.e. you get an event. The check for an event must only be performed on valid input. Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk> Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Support UTF-8 encoded characters in user choicesLars Henriksen2018-06-031-12/+23
| | | | | | | | Translations (in po-files) of texts that are used for alternative choices (e.g. [dwmy]), may use UTF-8 encoded Unicode characters (e.g. [éãüå]). Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Key bindings for UTF-8 encoded charactersLars Henriksen2018-06-034-13/+47
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Internally characters (keys) have two representations: integers and key names. Key names are characters strings, usually the name of the character; e.g., the character A has the representations 65 and "A", and the tab character the representations 9 and "TAB". The function keys_int2str() turns the integer representation of a key/character into the key name. For display purposes the key names are usually confined to have display width at most three. Some curses pseudo-keys have longer key names; e.g., the back-tab character is "KEY_BTAB". A long key name makes a character difficult to recognize in the status bar menu. The key name of a multibyte, UTF-8 encoded character is the conventional Unicode name of the code point; e.g., the character ü has key name "U+00FC" because ü is the code point 0xFC. Most of these look alike in the status bar menu. The patch makes the key name of a multibyte character look like that of a singlebyte character: the character itself, i.e. the key name of the character ü is "ü". The main tool is implementation of a utf8_encode() routine. Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Rename utf8_ord() to utf8_decode()Lars Henriksen2018-06-033-4/+4
| | | | | | | Purely for readability and in preparation for the counterpart utf8_encode(). Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk> Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Do not stop already cancelled notification threadLukas Fleischer2018-06-031-6/+11
| | | | | | | | | Add a static state variable to indicate whether the notification thread is already running or not. Only start the thread if the notification thread is paused. Only stop the thread if the notification thread is actually running. Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Only lock save mutex as short as possibleLukas Fleischer2018-06-031-3/+1
| | | | Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Check for empty string in config_parse_int()Lars Henriksen2018-05-281-3/+6
| | | | Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Add option to specify the configuration file usedQuentin Hibon2018-05-283-8/+21
| | | | | | | | | 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>
* Always NUL-terminate buffer in note_gc()Lukas Fleischer2018-05-261-0/+1
| | | | Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Always NUL-terminate buffer in keys_fill_missing()Lukas Fleischer2018-05-261-0/+1
| | | | Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Fix buffer overflow in keys_action_allkeys()Lukas Fleischer2018-05-261-4/+9
| | | | Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Always NUL-terminate buffer in io_load_keys()Lukas Fleischer2018-05-261-0/+1
| | | | Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* notify.c: fix several buffer overflowsLukas Fleischer2018-05-261-13/+18
| | | | Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Properly NUL-terminate the day heading after editingLukas Fleischer2018-05-261-1/+1
| | | | Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Avoid buffer overrun in config_parse_str()Lukas Fleischer2018-05-261-1/+6
| | | | | | | | | | The previous implementation only read a prefix from the configuration file if the configuration value was too long and forgot to terminate the string with a NUL character. Return 0 if the string is too long instead. Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
* Scrollbar and right window border (corrected)Lars Henriksen2018-05-269-36/+32
| | | | | | | | | | | | | | | | | When a scrollbar is on display in APP or TOD windows, the right vertical border (outside the scrollbar) is not highlighted when the window is selected. The scrollbar is always highlighted: - when APP or TOD is deselected - in configuration windows where borders otherwise are not The patch moves the scrollbar parameters (except highlight) from arguments of draw_scrollbar() to the function itself. The highlight argument was 1; instead it is set higher in the call hierarchy (wins_update_panels()) and passed on down. Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>