Commit Graph
100 Commits
Author SHA1 Message Date
Lars HenriksenandLukas Fleischer cc86516f64 Treat recurrence item parameters as a unit
An edit session, and in particular, a cancelled edit session should encompass
all parameters.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-06-16 15:03:02 -04:00
Lars HenriksenandLukas Fleischer e6099b2d59 Fix recurrent appointment end time when duration is zero
Fixes a regression introduced in 223810c (Major overhaul of
appointment/event input routines., 2017-11-06) and 16d3032 (Refactoring
update_duration/day_edit_duration., 2017-10-18).

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-06-03 18:42:52 -04:00
Lars HenriksenandLukas Fleischer e6ff3f417c Return at least two days in multiple days mode
Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-05-30 07:46:33 -04:00
Lars HenriksenandLukas Fleischer 0edc2e8637 Mark selected day in the appointments panel in multiple days mode
Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-05-28 17:58:06 -04:00
Lars HenriksenandLukas Fleischer 7e0274bc08 Remove appointments panel scrollbar in multiple days mode
A scrollbar gives the impression of a fixed list. But the list on
display is automatically and silently changed as needed for movements in
the panel or the calendar, thus creating the illusion of an endless
list.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-05-28 17:57:44 -04:00
Lars HenriksenandLukas Fleischer 378db90ada Fix sidebar width to accommodate calendar week column
Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-05-28 17:57:35 -04:00
Lars HenriksenandLukas Fleischer 3674127e80 Fix missing calculation of number of days on resize
Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-05-28 17:57:31 -04:00
Lars HenriksenandLukas Fleischer d15f1e9242 Automate the calculation of number of days to load
Instead of having the user tell how many days to load, calcurse can
calculate an overestimation from the running configuration (panel size,
appearance of headers and separators etc.)

The configuration variable conf.multiple_days is turned into a Boolean
that switches the feature on and off.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-05-26 10:04:28 -04:00
Lars HenriksenandLukas Fleischer 4db9677119 Make separation of days conspicuous
... by adding a horizontal line from border to border above the day
heading and turning the event separator into an empty line. The
horizontal line is left out for the first day loaded.

Also reduce the number of empty lines at the end of a day to at most
one.

A new configuration variable, header_line, turns the horizontal line on
and off.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-05-26 10:04:27 -04:00
Lars HenriksenandLukas Fleischer f9cf5fb0c1 Derive selected day from selected item
Previously, with only one day visible at a time, the appointments panel
displayed the details of the day selected in the calendar (slctd_day);
information required for operations on items (day_items) can often be
derived from the selected day. The items available are derived from the
selected day. In particular, the selected item is derived from the
selected day.

With multiple days in the APP panel, the relation between selected day
(in the calendar) and the selected item (in the APP panel) has, in a
way, been turned around. The selected item may now be moved between days
without explicitly changing the selected day. Implicitly it is changed
when the target day of a move is unavailable.

This commit draws the full consequence: the selected day in the calendar
is always (set to) the day of the selected item in the APP panel.

The static variable 'struct date slctd_day' lives in ui_calendar.c and
is accessible through various public functions. To these are added
ui_calendar_set_slctd_day() which sets slctd_day directly.

The selected day retains its significance for load of the day vector (in
day_store_items()): the range of loaded days begins with the selected
day.  Movements (up/down) in the APP panel will change the selected day
as the selected item moves among the already loaded days. Only when the
target of a movement is unreachable, will further days be loaded. On the
other hand, if the same range of days must be reloaded because of a
changed item, the selected item - and with it the selected day - must be
reset to the first day item (see do_storage()).

Movements in the calendar (generic-next-day, etc.) are not affected and
behave as previously, i.e. they will cause a range of days to be loaded
with the selected day as the first and the selected item as the first of
the selected day.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-05-22 01:56:59 -04:00
Lars HenriksenandLukas Fleischer 80ce812eff Add configuration variables for multiple days
The number of days displayed in the APP panel has been made
configurable, maximum 21 days, default seven days.

With several days in the APP panel, it may be desirable to "squeeze" the
entries by leaving out the final empty line of each appointment and
lower the number of lines between consecutive days (0, 1, or 2). Both
are made general configuration options. To make a uniform display, an
empty line is added to a day without appointments, if appointments have
an empty line.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-05-22 01:56:59 -04:00
Lars HenriksenandLukas Fleischer 0bb4a59b5f Add week numbers in the calendar and full first and last week
Much in the calendar is based on the selected day, struct date
slctd_day, in ui-calendar.c.

On the screen it is highlighted with a deviating colour. The highlight
effect has been changed to a pair of red square brackets that do not
obscure the day colour.

The week number (in the frame) used to be that of the selected day, but
has no obvious relation to the days in the APP panel. It has been
replaced by the year day number of the selected day. The week numbers of
all visible weeks are displayed to the left of the calendar.

Dates are displayed also for the overlapping parts of the first and last
week of the month (which do not belong to the month).

Days are accessible in the appointments panel as well as in the
calendar. Hence, validation of days (= inside UNIX time limits) must be
extended from the calendar (in ui_calendar_move()) to include loaded
days (in day_store_items()).

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-05-22 01:56:59 -04:00
Lars HenriksenandLukas Fleischer 4284ca91bc Implement scrolling in the appointments panel
With multiple days in the APP panel, up/down movements should change
behaviour at the top and bottom of the list displayed, and load the
previous/next lot of days.

This requires that the move function returns the result of the
operation.  Furthermore, the ability to move the selection to the
beginning of a day is needed when moving down (in order to move from the
first day to the last day).  For this reason a DAY_SEPARATOR has been
inserted also after the last day of a lot.

Appointments have a listbox height of three to separate them clearly
when there is more than one in a day.  This leaves a spurious empty line
at the end of a day with appointments.  The DAY_SEPARATOR height is
reduced from two to one, and a new EMPTY_SEPARATOR of height one is
inserted in any day with only events.

When scrolling up the DAY_HEADING becomes visible when the selection
reaches the first item of the day.

The length of the separator (between events and appointments) is
adjusted to leave a space to the window border at both ends, thereby
making it a part of the day, not a separation between days.

The dummy event must also be recognisable when not the selected item and
is only inserted in interactive mode.

The test for a saved selection must also recognise caption items which
have item pointer NULL.

The function day_get_nb() has been renamed day_get_days().

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-05-22 01:56:59 -04:00
Lars HenriksenandLukas Fleischer 1ccfe128cc Redesign selected-item implementation for the APP panel
The day vector, day_items, is displayed in the appointments panel; the
selected day_item object is highlighted (when the panel has the focus).
When items are inserted, edited, moved etc., and when the day is
changed, the day vector is rebuilt and displayed anew.

Problem: How shall the selection be set automatically in the context of
the new day vector?

In previous versions all of the above is mostly handled by the function
do_storage() in calcurse.c The function saves data about the selection
as needed, rebuilds the day vector, loads the listbox and sets the
selection from the saved selection data.  This works well in "single
day" calcurse in cases where the selected item is present in the day
vector both before and after the rebuild, or when the item ordering in
the listbox is unaffected by the changes.  But when a new item is added
the selection cannot be set to the new object by do_storage().  Instead
the necessary operations are performed by ui_day_item_add(), and
do_storage() is bypassed. In general, when an item cannot be found in
the new vector, the item which occupies the old place in the list gets
selected, e.g. when an item is deleted. When an item is turned into a
repeating one, the old item is deleted and a new is created. Here the
new selection is not always the affected item, but in any case not far
away.  Generally, with only one day in the panel an erronous selection
might not be noticed or be accurate by chance.

In "multiple day" calcurse the existing scheme works less well; in
addition the day vector may now contain more than one object that refer
to the same event or appointment (recurrent items or multi-day
appointments). The scheme has therefore been modified. The do_storage()
function is no longer bypassed, but handles day vector rebuild, load of
listbox and item selection exclusively. To make that possible, data
about the selected item is no longer saved in a local automatic
variable, private to do_storage(), but in an external static variable in
day.c, which may be set not only by do_storage(). The variable is
declared as

static struct day_item sel_data;

and used as follows:

1. On startup sel_data is initialized to empty (i.e. no selection).
2. In any operation involving the appointments panel:
   2.1 Do the work and if necessary set sel_data. This is the case when
       deleting, adding or pasting an item, and when turning an ordinary
       item into a recurrent one.
   2.2 Call do_storage().
3. In do_storage():
   3.1 If sel_data is empty, set it to the current selection.
   3.2 Rebuild the day vector.
   3.3 Set the selection from sel_data.
   3.4 Set sel_data to empty.

Further remarks
---------------

The selection is found in the new day vector by searching for the saved
(order, item.<pointer>) pair. Previously the item.<pointer> alone
sufficed and in some cases it still does. In case the item cannot be
found, the selection stays in the same day as before the rebuild.

An attempt at more consistently named APP-related functions has led to:
ui_day_sel_date() replaces ui_day_sel_day() ui_day_get_sel() replaces
ui_day_selitem()

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-05-22 01:56:59 -04:00
Lars HenriksenandLukas Fleischer 066df02cbf Introduce multiple days in the appointments panel
Overview of existing implementation
-----------------------------------

The APP panel displays the 'day_items' vector in the 'lb_apt' listbox. A
listbox consists of a scrollwin (structure) in which a number of items
is displayed. The listbox keeps track of:

    - the number of items
    - the selected item
    - the type of each item in an array type[]
    - the height of each item (ie. how many screen lines) in an array ch[]
    - how to display an item (on the screen)

The latter three are handled by functions fn_type(), fn_height(),
fn_draw(). The first two are used to fill in the corresponding array
entry, type[] or ch[], for item number i, the third draws item number i.

The items are taken from the global variables

    vector_t day_items
    int      day_items_nb

in day.c. Items include captions (DAY_HEADING, DAY_SEPARATOR).
Everything is sorted for display (DAY_HEADING, events, DAY_SEPARATOR,
appts).  These are filled in ("stored") [by day_store_items() for the
selected day in the calendar], before being "loaded" into the listbox.
See do_storage() in calcurse.c and ui_day_item_add() in ui-day.c.

New APP panel design
--------------------

Several days are displayed in the APP panel by loading them with
day_store_items().

With several days come several headings and separators. DAY_SEPARATOR is
reinterpreted to separate days, and a new separator, EVNT_SEPARATOR,
separates events from appointments. To sort everything, an 'order'
member of type time_t is added to the day_item structure. It is set for
headings and separators as well as for appointments and events as
follows:

    item            order
    ---------------------
    DAY_HEADING     BGNOFDAY (= midnight)
    EVNT_SEPARATOR  BGNOFDAY
    DAY_SEPARATOR   ENDOFDAY
    event           start time (midnight)
    appointment     start time (first day)
                    BGNOFDAY (following days, if any)

The sort function day_cmp() (used by vector_sort) is extended to sort by
order first.

The order field always indicates the day to which an item belongs. This
comes in handy, because with several days in the APP panel it is
necessary to distinguish between the selected day in the calendar and
the selected day in the APP panel.  This raises the question which day
should actions (commands) operate on: the one selected in the calendar
or the one selected in the APP panel? Unquestionably the one on the APP
panel which is the one tacitly implied. In most cases it is not a
problem, though, because actions work on the selected item and the
selected day does not come into play. But in some cases it does:

    delete item     When deleting an occurrence of a repeated item, the
                    selected day is the exception day to add.

    view item       day_popup_item() needs the day of the selected item
                    for display of correct start/end times.

    cut/paste item  Paste needs the selected day in which to paste.

    add item        The day of the new item is taken from the calendar.
                    Instead a dummy event is inserted in an empty day.
                    This makes the day selectable, which is otherwise
                    impossible with only the DAY_HEADING displayed.  The
                    dummy event is selectable but cannot be edited or
                    deleted (but viewed or piped).

With more than one day in the day_items vecter, an appointment spanning
more than one day may occur more than once in the vector (with start/end
times suitably adjusted for display). A day_item is no longer (always)
identified by the aptev_ptr (item) value. Instead the combination
(order, item.<ptr>) is used; order is roughly the day.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-05-22 01:56:59 -04:00
Lars HenriksenandLukas Fleischer 8dd694b569 Simplify day storage
The function day_process_storage() is a wrapper for day_store_items().
It has an unused second argument, and is only used twice to load the
selected day. It has been removed.

A new function, get_slctd_day(), is the equivalant of get_today() and
replaces the very awkwardly named ui_calendar_get_slctd_day_sec().

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-05-22 01:56:59 -04:00
Lars HenriksenandLukas Fleischer 06a4449afa Fix initialization of the day_items vector
This patch fixes all failings tests, but one, in PR #193.

Until now the missing initialization of day_items_nb has caused no
problems, because the variable was assigned to (=) before being used. In
the Multiple days implementation it is repeatedly increased (+=) in a
loop without being initialized first. Indeed, this may considered an
easily fixed bug. But the initialization really belongs in
day_init_vector() so that the call day_item_count(0) returns 0 if done
right after the call day_init_vector(). The bug only shows up in command
line mode because day_items_nb is not used in interactive mode.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-05-22 01:56:59 -04:00
Lars HenriksenandLukas Fleischer df2cb2a9c0 Refactor listbox code
The changes are related to the selected item and the visible lines in
the scroll window viewport.

In particular, the function listbox_fix_visible_region() has been
eliminated, and functions previously only called by it have been
removed. It performed several tasks that are now elsewhere. One was
removed in an earlier commit (scroll window pad improvement). The task
of making a multi-line item visible has been moved to
listbox_item_in_view(). The task of making a caption line above a text
line visible is listbox specific (for the ap_list) and will be moved to
ui_day_sel_move(), where it is needed.

Boundary checks for the listbox selection have been moved to
listbox_fix_sel().

For future use listbox_sel_move() returns success or failure.

The function wins_scrollwin_ensure_visible() has been renamed
wins_scrollwin_in_view().

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-05-22 01:56:59 -04:00
Lars HenriksenandLukas Fleischer 576994de00 Improve scroll window pad
A scroll window consists of a pad to write on, and a window through
which to view the pad, the viewport. The pad may change in size when new
contents are loaded into the scroll window. If so, the pad size is set
with wins_scrollwin_set_linecount(). But the offset into the pad (the
top line to be displayed in the viewport) is not adjusted, although it
may not be appropriate for the new pad size. The same is the case when a
scroll window is resized and the viewport changes size. This is probably
the cause of the problem solved by commit 0b46ad4, Avoid blank space
after the last list box item, and the fix has been removed.

The wins_scrollwin_set_linecount() has been renamed
wins_scrollwin_set_pad() and sets size as well as offset. The offset is
only changed if necessary.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-05-22 01:56:59 -04:00
Lars HenriksenandLukas Fleischer 52d52208c8 Test cases for impossible dates in recurrence rule
Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-05-20 09:37:17 -04:00
Lars HenriksenandLukas Fleischer 2be32c4bda Impossible dates in recurrence rules
According to RFC 5545 dates like 30 February and 31 June must be ignored
when derived from a recurrence rule.

calcurse relies on mktime() "normalization" of dates (e.g. turning 32
December 2019 into 1 January 2020 when moving from 31 December to the
next day).

Normalization may also lead to impossible dates in monthly and yearly
recurrence rules, and this must be avoided.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-05-20 09:37:11 -04:00
Lars HenriksenandLukas Fleischer 8741334d83 New test cases for next appoinment
The change by commit "Fix display of time left before next appointment"
is not detected by the existing test because the time set has zero
seconds.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-04-13 11:58:16 +02:00
Lars HenriksenandLukas Fleischer 371c7eb00f Fix display of time left before next appointment
In the notify bar, the clock is shown in hours, minutes and seconds,
whereas the time left to the next appointment is shown in hours and
minutes only. When you read the clock in hours and minutes (discarding
the seconds), you are mentally rounding down to the nearest minute. To
agree with that reading, the time left (in seconds) should be
(programmatically) rounded up to the nearest minute for display.

In that way the time left is counted down whenever the minute "hand" of
the clock "ticks", and reaches zero when the clock reaches the time of
the next appointment, not one minute before. Also, the clock (in hours
and minutes) and the time left always add up to the time of the next
appointment.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-04-13 11:58:04 +02:00
Lars HenriksenandLukas Fleischer c8d5397214 Fix daemon notification for short warning periods
When the warning period for notifications is less than 60 seconds
(DAEMON_SLEEP_TIME), the daemon may be at sleep when the appointment
comes up. If that happens, no notification is launched. In stead, the
daemon should launch the notification early.

Addresses GitHub issue #204, part 2.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-04-13 11:57:59 +02:00
Lars HenriksenandLukas Fleischer a5d8ca5cbf Fix one-second warning period for notifications
Adresses GitHub issue #204, the interactive part.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-04-13 11:57:58 +02:00
Lars HenriksenandLukas Fleischer 78a46ac7cb Avoid deadlock in config_save()
Must not exit with nbar.mutex locked.

Addresses GitHub issue #201.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-03-21 06:41:46 +01:00
Lars HenriksenandLukas Fleischer 90f96059c5 Fix calendar (re)draw
Window erasure is moved to the drawing functions.

Adresses GitHub issue #196.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-03-13 17:02:26 +01:00
Lars HenriksenandLukas Fleischer 45fd62cab4 Fix vector_remove()
Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-03-13 17:02:26 +01:00
Lars HenriksenandLukas Fleischer 528368932c View or edit exception days of a recurrent item
The exception days are presented for viewing/editing as a string of
space-separated dates (in the user-preferred input format). After
editing the string is checked for valid dates, but there is no check
that a date is meaningful (an occurrence day of the item between start
day and until day). Although possible, it is best to add exception days
in the usual way by deletion of occurrences.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-02-28 08:03:53 +01:00
Lars HenriksenandLukas Fleischer a47a562322 Fix empty dynamic string
Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-02-28 08:02:35 +01:00
Lars HenriksenandLukas Fleischer 99c7493cd5 Fix deletion of a multi-day recurrent appointment
When the selected day in the calendar is a continuation day (not the first day)
of such an appointment, deleting the occurrence does not work. The reason is
that the selected day, and not the first day of the occurrence, is added as an
exception day.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-02-02 18:19:22 +01:00
Lars HenriksenandLukas Fleischer 870fa1aa32 Overflow check for 32-bit types only
Included is a check of the 'until' date for pasted recurrent items.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-01-18 23:38:33 +01:00
Lars HenriksenandLukas Fleischer 4af76af5ae Legalese for queue.c
Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-01-12 01:53:51 +01:00
Lars HenriksenandLukas Fleischer 8cbd456640 Fix next recurring appointment
Recurring appointments do not show up in the notification bar as next
appointment. This was partly corrected by 2084f35 (Fix notification of
recurrent appointments, 2017-02-09) and 5aa7a09 (Fix another error in
the notification code, 2017-02-11).

The search function recur_apoint_starts_before() had a wrong second
argument, but is really of no use: the start time of a recurring
appointment is the start time of the very first occurrence (in the
past). A comparison against the item in the notify_app structure tells
nothing of the start time of the current day; at most it eliminates some
future recurring appointments. The function can be dropped, and the
entire recurring appointment list looked through.

The proper start time is found in the main search loop (and called
real_recur_start_time) and must be compared against the item in the
notify_app structure.

But because recur_apoint_find_occurrence() is limited to a particular
day (second argument), two searches are necessary to cover 24 hours.

Unrelated cleanups: removed function return value; changed long to
time_t.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-01-11 18:11:52 +01:00
Lars HenriksenandLukas Fleischer f2ca5980e9 Initialize data paths once only
Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-01-08 01:23:21 +01:00
Lars HenriksenandLukas Fleischer 63b03c6b36 Explicit calendar and todo view configuration
The configuration settings for calendar view (monthly/weekly) and todo
view (hide/show completed) used to be saved automatically on calcurse
exit, with values taken from the current interactive settings. They
could not be set explicitly in the configuration menues. Configuration
settings are no longer saved on program exit, but on exit from the
configuration menu. This means that the saved values are those that were
current when the configuration menu was entered. To change a saved
value, you must set the view as desired and then enter/exit the
configuration menu.

The preferred calendar and todo views are no longer automatically taken
from the interactive settings, but are explicitly set in the general
options menu.  Default values are monthly view and hide completed view.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-01-07 16:58:11 +01:00
Lars HenriksenandLukas Fleischer b9f23e134a Purge option glorified
The invert filter option is automatically set for -P (and cannot be used
on the command line). The intention is that the grep option (-G) is used
to find the items that should be removed. To remove them, the same
command is run with -P instead of -G.

In general, purge will remove matching items (silently).

Backward compatibility for option -F (no invert filter).

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-01-07 16:58:08 +01:00
Lars HenriksenandLukas Fleischer 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 HenriksenandLukas Fleischer 9300e9154c CLI: detect conflicting filter options
Several start/end-time filter options set the same filter criterion.
Only allow one such filter option at a time.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-01-07 16:58:03 +01:00
Lars HenriksenandLukas Fleischer 620c4eeca5 CLI: Revert to and update of parse_datetimearg()
An earlier commit ("CLI: take input date format from configuration file,
do not accept time") replaced parse_datetimearg() with parse_datearg()
and eliminated time-of-day from command line date arguments. This made
the full use of filter options impossible.

That earlier commit is reverted and updated. The parse_datearg()
function is replaced by an updated parse_datetimearg() function that

- takes the date format from the configuration file
- accepts date, date-time or time

The updated parse_datetimearg() function has been extended to report
back the type of the date string received in order to set (filter)
options correctly.  Input dates for query ranges (--from, --to, --days)
are still limited to dates only.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-01-07 16:58:01 +01:00
Lars HenriksenandLukas Fleischer bcfc71f4fe Safety exit and read-only mode
The key_generic_command() function provides a "safety exit" in case of
online changes that should be dropped at exit when auto_save is on, or
(NEW) should be saved at exit when in read-only mode. A check for
unsaved changes has been added. The command prompt has been extended
with minimal help information.

After commit 05e0fd0 "Quit, autosave and interactive save" you could not
leave calcurse in read-only mode with the quit command because the
key_generic_quit() function interpreted IO_SAVE_CANCEL as a decision (by
the user) to cancel a save-conflict and cancelled the quit as well. Now
the function will quit unconditionally in read-only mode (as stated in
the man page). In normal mode a check for unsaved changes has been added
in case auto-save is off.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-01-07 16:57:58 +01:00
Lars HenriksenandLukas Fleischer a5e6608992 CLI: tests aligned
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-01-07 16:57:57 +01:00
Lars HenriksenandLukas Fleischer d0602625bc Update man page
Rework man page. Add invert filter and purge option.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-01-07 16:57:56 +01:00
Lars HenriksenandLukas Fleischer daa30ef3bb Fix print_date()
In print_date(date, day, ...) it is silently assumed that day is
midnight (beginning) of the day to be printed. Assume only that it
belongs to the day.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-01-07 16:57:55 +01:00
Lars HenriksenandLukas Fleischer ad183c61a9 CLI: do not start daemon if calcurse is running
Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-01-07 16:57:53 +01:00
Lars HenriksenandLukas Fleischer 7851f46fbb CLI: filter options have no effect for dates before the epoch
With the exception of filter.type_mask, a filter is only applied if set
explicitly on the command line with a filter option. Whether that is the
case, is determined by comparison with the initialization value. For
date related filters (start_from/to, end_from/to) that is -1, hence the
criterion is != -1, not >= 0.

In generel, a filter initialization value should be invalid (i.e. one
that cannot be set explicitly). As times before the epoch (1 January
1970 00:00:00 UTC) are negative, -1 is a valid Unix time. However, as it
cannot be set from the command line, it is probably no problem?

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-01-07 16:57:52 +01:00
Lars HenriksenandLukas Fleischer 4ba2cc46d7 CLI: time assignments for filter options
Explanation. There is an important difference between "to <date>" (e.g.
to 15/11/2018)  and "to <date time>" (e.g. to "15/11/2018 13:30"):
<date> is a time span (of 24 hours), while <date time> is a point in
time.

"To <date>" really means "to the end of <date>", while "before <date>"
means "before the beginning of <date>". There are 24 hours between the
two, whereas there is only one second between "before <date time>" and
"to <date time>".  Similar for from/after.

An earlier commit introduced parse_datearg() that only accepts a date
without a time. Hence, a date should be treated as a time span from
midnight to one second before next midnight.

The commit also fixes an error detection bug (filter.start_from/to and
filter.end_from/to were updated too early).

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-01-07 16:57:51 +01:00
Lars HenriksenandLukas Fleischer 42e296c840 CLI: long options to override configuration file settings
The input and output date formats may be set from the command line.
Intended for scripts that must be independent of the local user
configuration.

Cannot be used in interactive mode.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-01-07 16:57:49 +01:00
Lars HenriksenandLukas Fleischer 3d7bb89c88 CLI: take input date format from configuration file, do not accept time
Before this patch the input date parsing accepts three formats:
yyyy/mm/dd, mm/dd/yyyy, yyyy-mm-dd. They are tried in sequence. It also
accepts an additional time (hh:mm), or a time without a date.

There are several issues with this:

- it is not documented
- the date format dd/mm/yyyy is not accepted
- print_date() and filter option settings (in parse_args()) can only
  handle midnight times (which are the result of a date without time)
- it is highly uncertain what happens if a time (without a date) is
  given; at least the -d option treats a time without colon (1215 for
  12:15) as a number

It seems that acceptance of time input is a by-product and not needed.
For these reasons the input date parsing has been changed:

- the format is taken from the configuration file (as is the case for
  the output date format)
- only a date, and no time, is accepted

Because the input date format is used during parsing of the command
line, the configuration file must be loaded first, i.e. the options -D
or -C must be parsed before the remaining ones. Loading the
configuration file may result in errors (e.g. caused by changes between
versions). For this reason config_load() has been made more tolerant and
issues warnings instead of exiting.

A followup patch will introduce two options to allow the configuration
file settings to be overridden for input and output date formats.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-01-07 16:57:48 +01:00
Lars HenriksenandLukas Fleischer 215e90d348 Command line options: -P, option check, usage, help
Option -F/--filter renamed to -P/--purge; -F retained as deprecated.
Check for non-option arguments and for filter, format and query-range
options only.  Update of help and usage messages.

Fixed --status output when calcurse is not running.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-01-07 16:57:46 +01:00
Lars HenriksenandLukas Fleischer 03880a82bf Fix day range for queries
In "--from a --to z", a is included in the range, z not. This is
non-intuitive and disagrees with the semantics of "to" in filter options
like --filter-start-to, where "to" (and "from") are used inclusively (as
opposed to "before" and "after"). It also has the effect that "--from
today --to tomorrow" has a range of 1 day, "--to z" a range of 0 days
(otherwise not allowed), and "--to today --days -1" is allowed and
displays yesterday!

The implementation has been fixed to agree with "inclusive" semantics.
Options --from and -days with negative range are allowed, while --to and
--days are disallowed also when the range is negative.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2019-01-07 16:57:43 +01:00
Lars HenriksenandLukas Fleischer 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
Lars HenriksenandLukas Fleischer e6cffdc6bd DST fix: daylength v. DAYINSEC
The number of seconds in a day and daylength in seconds differ when
Daylight Saving Time is in effect on two days of the year. The day when DST
takes effect is 23 hours long, and the day when DST ends is 25 hours long.

In the latter case the date changing thread wóuld enter a loop in the last hour
before midnight (in the former it would set the date an hour too late).
The next midnight is calculated through mktime(), invoked by date2sec().

Wrong daylength prevented appointments from being stored in the day vector and
caused them to be displayed wrongly in the appts panel.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-11-10 12:19:28 +01:00
Lars HenriksenandLukas Fleischer 4263a28504 DST fix: adjusting time in appointments
Calcurse saves time and date information on disk as local time in readable text
file format. When loaded from disk or when entered by the user, local time is
converted to Unix time (seconds since 00:00:00, 1 January 1970). When
displayed, and later when saved to disk, the Unix time is converted back to
readable local time. Both conversions depend on DST.

Hence, if midnight for a day with DST in effect (i.e. local time) is converted,
increased with an amount and converted back, the amount has changed if DST is
_not_ in effect for the resulting time. In general, calculations on Unix time
variables should be used with caution because of the DST-dependent conversions.
Instead, the calculations should be performed on local time data with the help
of mktime().

The commit fixes start time for pasted appointments (ordinary and recurrent)
and the 'until'-date of recurrent appointments, pasted as well as new and
edited. The latter problem is slightly different in that the adjustment is a
number of days, as it is for exception dates.

Update of the date in parse_datetime() has been corrected to be similar to
update of the time, although no problem has been identified.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-11-10 12:19:28 +01:00
Lars HenriksenandLukas Fleischer f91b7cdee0 DST fix: adding appointments on the day when DST starts or stops
A new apppoint inserted on the day when the clock is adjusted backward by an
hour got a wrong start time (an hour late). Reason: mktime() must not use the
Daylight Saving Time information returned by localtime_r().

Also editorial simplifications.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-11-10 12:19:28 +01:00
Lars HenriksenandLukas Fleischer 8104c4aaf4 po/: queue.c added
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-10-21 20:02:57 +02:00
Lars HenriksenandLukas Fleischer d1075e525f Mutex for the system message queue
The main thread only reads and removes events from the queue. All other threads
only insert events in the queue. Hence, only insertion and removal need protection.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-10-21 20:02:57 +02:00
Lars HenriksenandLukas Fleischer 53b55930e8 Configuration variable for system events
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>
2018-10-21 20:02:57 +02:00
Lars HenriksenandLukas Fleischer 3d93ffa7ca Periodic save: report cancelled save
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-10-21 20:02:57 +02:00
Lars HenriksenandLukas Fleischer 2112b1ca2e System message queue
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>
2018-10-21 20:02:57 +02:00
Lars HenriksenandLukas Fleischer 2339d78cbd Quit, autosave and interactive save
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>
2018-10-21 20:02:57 +02:00
Lars HenriksenandLukas Fleischer c95dd0e685 Remove the configuraton variable conf.progress_bar
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>
2018-10-21 20:02:57 +02:00
Lars HenriksenandLukas Fleischer 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 HenriksenandLukas Fleischer 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 HenriksenandLukas Fleischer 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 HenriksenandLukas Fleischer 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 HenriksenandLukas Fleischer 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 HenriksenandLukas Fleischer 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 HenriksenandLukas Fleischer 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 HenriksenandLukas Fleischer 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 HenriksenandLukas Fleischer 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 HenriksenandLukas Fleischer 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 HenriksenandLukas Fleischer 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 HenriksenandLukas Fleischer 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 HenriksenandLukas Fleischer 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
Lars HenriksenandLukas Fleischer 7f448ee8cd Minor merge adjustments
Comments inserted.

Slightly different implementations of parse_time() and parse_datetime().

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-08-25 10:15:33 +02:00
Lars HenriksenandLukas Fleischer 0543df5f31 Fix memory leak in update_duration()
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-08-25 10:15:33 +02:00
Lars HenriksenandLukas Fleischer b6cdc29255 Fix seg fault in update_rept()
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>
2018-08-25 10:15:33 +02:00
Lars HenriksenandLukas Fleischer fa353e5eb7 Buffer mixup
Use one (small) buffer long enough to hold a date.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-08-25 10:15:33 +02:00
Lars HenriksenandLukas Fleischer 223810cf0e Major overhaul of appointment/event input routines.
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>
2018-08-25 10:15:33 +02:00
Lars HenriksenandLukas Fleischer fd635150a8 Start and end time validation.
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>
2018-08-25 10:03:28 +02:00
Lars HenriksenandLukas Fleischer c45da5f5ca New support functions for input validation.
check_sec(), overflow_add(), overflow_mul()

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-08-25 10:03:28 +02:00
Lars HenriksenandLukas Fleischer 16d30327ba Refactoring update_duration/day_edit_duration.
Incorporated day_edit_duraton() into update_duration().

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-08-25 10:03:28 +02:00
Lars HenriksenandLukas Fleischer ddc3fda5f1 Initialize variables in non-interactive mode in all cases
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>
2018-08-19 09:10:06 +02:00
Lars HenriksenandLukas Fleischer 3788df6d78 Fix multiple, simultaneous periodic saves
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>
2018-07-28 14:21:38 +02:00
Lars HenriksenandLukas Fleischer 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
Lars HenriksenandLukas Fleischer 163730cabf Fix end-before-start inconsistency
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>
2018-06-05 05:52:39 +02:00
Lars HenriksenandLukas Fleischer 40eb6f809e Fix appointment becoming event
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>
2018-06-05 05:52:30 +02:00
Lars HenriksenandLukas Fleischer 500b0c080e Support UTF-8 encoded characters in user choices
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>
2018-06-03 11:28:46 +02:00
Lars HenriksenandLukas Fleischer 7078556f9d Key bindings for UTF-8 encoded characters
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>
2018-06-03 11:26:12 +02:00
Lars HenriksenandLukas Fleischer 431e4a00e7 Rename utf8_ord() to utf8_decode()
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>
2018-06-03 11:24:37 +02:00
Lars HenriksenandLukas Fleischer d5961baa13 Check for empty string in config_parse_int()
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-05-28 17:31:06 +02:00
Lars HenriksenandLukas Fleischer bb7381765c Scrollbar and right window border (corrected)
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>
2018-05-26 11:31:43 +02:00
Lars HenriksenandLukas Fleischer a5cc46cd55 Transparent cursor fix
Commit f8e6e0d (Fix no-colour theme, 2017-12-10) partly destroyed the
cursor in getstring() by turning it into a solid block. The fix
reintroduces wchgat() which requires a color pair argument. When no
colors are wanted, color pair 0 is used.

A similar problem exists in the layout and colour customization windows
and is fixed in the same way: move to the position and apply the reverse
video attribute.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-05-26 11:30:03 +02:00
Lars HenriksenandLukas Fleischer 65dd82a626 Fix end-of-string calculation
In keys_fill_missing() a pointer is walked through a string of
space-separated character names, but misses the string-terminating null
character.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2018-05-24 16:23:23 +02:00
Lars HenriksenandLukas Fleischer f8e6e0d691 Fix no-colour theme
In colour customization, pressing cancel ('ESC' by default) will
deselect all colours and put calcurse in no-color mode. For this
to work, all colour changes must be performed with the routines
custom_apply_attr()/custom_remove_attr(). Fixed for the getstring
cursor, the scroll window border and the week number.

In addition, the week number is unconditionally coloured as the
rest of the calendar contents whether CAL is selected or not.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2017-12-10 14:33:31 +01:00
Lars HenriksenandLukas Fleischer 9e060b96c2 Scrollbar and right window border
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 itself is always highlighted:
- when APP or TOD is deselected
- in configuration windows where borders otherwise are not

The patch moves the scrollbar parameters from arguments of
draw_scrollbar() to the function itself.

The highlight argument to draw_scrollbar() was always 1.
Instead call circumstances are figured out and highlight set
accordingly.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2017-12-10 14:33:31 +01:00
Lars HenriksenandLukas Fleischer e733d09ea0 Default colour as foreground colour
In the default colour setup (white on black), white could only
with great difficulty be used as customized foreground colour,
because the colour pair COLR_CUSTOM then was identical to
COLR_DEFAULT (default on default). This made it impossible to
distinguish the selected element in lists.

The patch turns on the video attribute bold when default is chosen
as foreground colour.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2017-12-10 14:33:31 +01:00
Lars HenriksenandLukas Fleischer 95c5d576fa Update UTF-8 base code
UTF-8 encodes characters in one to four bytes (since 2003).

Because 0 is a valid code point, the decode function utf8_ord()
should return -1, not 0, on error. As a consequence utf8_width()
should return 0 for a continuation byte (as it did previously).

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2017-12-07 09:02:58 +01:00
Lars HenriksenandLukas Fleischer 691d6b33ee Check for the year span 1902-2037
Reintroduce year check for systems with a 32-bit time_t type. Remove the
lower limit (1902) for systems with a 64-bit time_t. This limits
movements in the calendar (for 32-bit systems) and in no way ensures
constistency of data.

Commit a12833e (Handle dates past January 19th, 2038, 2015-01-19)
removed the upper limit (2037) on dates but left the lower limit (1902).
It did not ensure the support of the target system.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
2017-11-23 08:56:38 +01:00