aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/lint_python.yml21
-rw-r--r--.github/workflows/make.yml53
-rw-r--r--.gitignore12
-rw-r--r--.travis.yml23
-rw-r--r--.tx/config49
-rw-r--r--AUTHORS3
-rw-r--r--CHANGES.md181
-rw-r--r--COPYING2
-rw-r--r--README.md37
-rwxr-xr-xautogen.sh2
-rwxr-xr-xbuild-aux/git-version-gen2
-rw-r--r--configure.ac75
-rw-r--r--contrib/caldav/README.md13
-rwxr-xr-xcontrib/caldav/calcurse-caldav.py278
-rw-r--r--contrib/caldav/config.sample14
-rwxr-xr-xcontrib/caldav/hooks/post-sync2
-rw-r--r--contrib/import/DST-et.ical11
-rw-r--r--contrib/import/DST-eu.ical11
-rw-r--r--contrib/import/February.ical11
-rw-r--r--contrib/import/Monday-first-last.ical11
-rw-r--r--contrib/import/Tuesday-Thursday.ical11
-rw-r--r--contrib/import/Wednesdays-all.ical11
-rw-r--r--contrib/setup.cfg3
-rw-r--r--doc/Makefile.am2
-rw-r--r--doc/calcurse.1.txt12
-rw-r--r--doc/credits.txt2
-rw-r--r--doc/de/credits.txt2
-rw-r--r--doc/es/credits.txt2
-rw-r--r--doc/fr/credits.txt2
-rw-r--r--doc/manual.txt34
-rw-r--r--doc/nl/credits.txt2
-rw-r--r--doc/pt_BR/credits.txt2
-rw-r--r--doc/repeat.txt173
-rw-r--r--doc/ru/credits.txt2
-rw-r--r--doc/submitting-patches.txt2
-rw-r--r--po/calcurse.pot403
-rw-r--r--po/de.po513
-rw-r--r--po/doc/add-nb_NO.po4
-rw-r--r--po/doc/copy-paste-nb_NO.po4
-rw-r--r--po/doc/credits-nb_NO.po2
-rw-r--r--po/doc/edit-nb_NO.po4
-rw-r--r--po/doc/export-nb_NO.po4
-rw-r--r--po/doc/flag-nb_NO.po4
-rw-r--r--po/doc/save-nb_NO.po4
-rw-r--r--po/doc/tab-nb_NO.po4
-rw-r--r--po/doc/vnote-nb_NO.po4
-rw-r--r--po/en.po1780
-rw-r--r--po/es.po514
-rw-r--r--po/fr.po547
-rw-r--r--po/nl.po456
-rw-r--r--po/pt_BR.po560
-rw-r--r--po/ru.po1146
-rw-r--r--scripts/calcurse-upgrade.sh.in2
-rw-r--r--src/apoint.c31
-rw-r--r--src/args.c42
-rw-r--r--src/calcurse.c202
-rw-r--r--src/calcurse.h190
-rw-r--r--src/config.c32
-rw-r--r--src/custom.c93
-rw-r--r--src/day.c106
-rw-r--r--src/dmon.c12
-rw-r--r--src/event.c20
-rw-r--r--src/getstring.c4
-rw-r--r--src/help.c6
-rw-r--r--src/hooks.c37
-rw-r--r--src/htable.h2
-rw-r--r--src/ical.c1594
-rw-r--r--src/io.c399
-rw-r--r--src/keys.c428
-rw-r--r--src/listbox.c2
-rw-r--r--src/llist.c204
-rw-r--r--src/llist.h5
-rw-r--r--src/llist_ts.h4
-rw-r--r--src/mem.c2
-rw-r--r--src/note.c17
-rw-r--r--src/notify.c38
-rw-r--r--src/pcal.c16
-rw-r--r--src/queue.c2
-rw-r--r--src/recur.c1185
-rw-r--r--src/sha1.c3
-rw-r--r--src/sha1.h4
-rw-r--r--src/sigs.c20
-rw-r--r--src/strings.c3
-rw-r--r--src/todo.c6
-rw-r--r--src/ui-calendar.c123
-rw-r--r--src/ui-day.c953
-rw-r--r--src/ui-todo.c49
-rw-r--r--src/utf8.c2
-rw-r--r--src/utils.c215
-rw-r--r--src/vars.c6
-rw-r--r--src/vector.c2
-rw-r--r--src/vector.h2
-rw-r--r--src/wins.c26
-rw-r--r--test/Makefile.am18
-rw-r--r--test/data/apts-export2
-rw-r--r--test/data/ical-002.ical4
-rw-r--r--test/data/ical-003.ical45
-rw-r--r--test/data/ical-005.ical2
-rw-r--r--test/data/ical-006.ical2
-rw-r--r--test/data/ical-007.ical5
-rw-r--r--test/data/ical-008.ical4
-rw-r--r--test/data/ical-009.ical131
-rw-r--r--test/data/ical-012.ical89
-rw-r--r--test/data/ical-014.ical106
-rw-r--r--test/data/rfc554528
-rw-r--r--test/data/rfc5545.ical238
-rw-r--r--test/data/todo-export1
-rwxr-xr-xtest/ical-001.sh14
-rwxr-xr-xtest/ical-002.sh12
-rwxr-xr-xtest/ical-003.sh117
-rwxr-xr-xtest/ical-004.sh14
-rwxr-xr-xtest/ical-005.sh17
-rwxr-xr-xtest/ical-006.sh12
-rwxr-xr-xtest/ical-007.sh17
-rwxr-xr-xtest/ical-008.sh14
-rwxr-xr-xtest/ical-009.sh46
-rwxr-xr-xtest/ical-010.sh34
-rwxr-xr-xtest/ical-011.sh19
-rwxr-xr-xtest/ical-012.sh67
-rwxr-xr-xtest/ical-013.sh1800
-rwxr-xr-xtest/ical-014.sh28
-rwxr-xr-xtest/io-005.sh1
-rwxr-xr-xtest/io-006.sh1
-rwxr-xr-xtest/recur-008.sh2
-rwxr-xr-xtest/recur-009.sh5342
-rwxr-xr-xtest/recur-010.sh58
-rw-r--r--test/run-test.c2
-rw-r--r--test/test-init.sh5
128 files changed, 16569 insertions, 4843 deletions
diff --git a/.github/workflows/lint_python.yml b/.github/workflows/lint_python.yml
new file mode 100644
index 0000000..c04a772
--- /dev/null
+++ b/.github/workflows/lint_python.yml
@@ -0,0 +1,21 @@
+name: Lint Python
+
+on:
+ pull_request:
+ paths: ['contrib/**']
+ push:
+ paths: ['contrib/**']
+
+jobs:
+ lint_python:
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: contrib
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-python@v2
+ - run: pip install codespell flake8 isort
+ - run: codespell --quiet-level=2 || true
+ - run: flake8 --count --show-source --statistics
+ - run: isort --check-only --profile black .
diff --git a/.github/workflows/make.yml b/.github/workflows/make.yml
new file mode 100644
index 0000000..552bce6
--- /dev/null
+++ b/.github/workflows/make.yml
@@ -0,0 +1,53 @@
+name: Build and test
+
+on:
+ push:
+ branches: [master, pu]
+ paths-ignore:
+ - 'contrib/**'
+ - 'doc/**'
+ - 'po/**'
+ pull_request:
+ branches: [master, pu]
+ paths-ignore:
+ - 'contrib/**'
+ - 'doc/**'
+ - 'po/**'
+
+jobs:
+ build:
+ strategy:
+ matrix:
+ os: ['ubuntu-latest', 'macos-latest']
+ runs-on: ${{ matrix.os }}
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Install dependencies (Ubuntu)
+ run: |
+ sudo apt-get update
+ sudo apt-get install asciidoc autopoint gettext xmlto autoconf-archive
+ if: matrix.os == 'ubuntu-latest'
+ - name: Install dependencies (MacOS)
+ run: |
+ brew install --overwrite python
+ brew update
+ brew install automake
+ brew install asciidoc
+ brew install gettext
+ brew install xmlto
+ brew install autoconf-archive
+ brew link --force gettext
+ sudo mkdir /etc/xml
+ sudo ln -s /usr/local/etc/xml/catalog /etc/xml/catalog
+ if: matrix.os == 'macos-latest'
+ - name: autogen.sh
+ run: ./autogen.sh
+ - name: configure
+ run: ./configure
+ - name: make
+ run: make
+ - name: make check
+ run: make check
+ - name: make distcheck
+ run: make distcheck
diff --git a/.gitignore b/.gitignore
index 09a2eac..fa059ab 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,15 +5,20 @@ Makefile.in
Makefile.in.in
aclocal.m4
configure
+compile
depcomp
install-sh
missing
+mkinstalldirs
stamp-h1
.version
autom4te.cache/
m4/
-./config.*
+/config.*
+
+/contrib/caldav/calcurse-caldav
+/contrib/vdir/calcurse-vdir
doc/*.1
doc/*.html
@@ -24,15 +29,20 @@ po/*.gmo
po/*.header
po/*.sin
po/*.sed
+po/Makevars.template
po/POTFILES
po/Rules-quot
po/stamp-po
+/scripts/calcurse-upgrade
+
src/*.o
src/.deps/
src/calcurse
+test-driver
test/*.o
test/*.log
test/*.trs
test/run-test
+test/.deps/
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 47d27fe..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-language: c
-
-os:
- - linux
- - osx
-
-addons:
- apt:
- packages:
- - asciidoc
- - autopoint
- - xmlto
-
-before_install:
- - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi
- - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install asciidoc; fi
- - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install gettext; fi
- - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install xmlto; fi
- - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew link --force gettext; fi
- - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then sudo mkdir /etc/xml; fi
- - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then sudo ln -s /usr/local/etc/xml/catalog /etc/xml/catalog; fi
-
-script: ./autogen.sh && ./configure && make && make check
diff --git a/.tx/config b/.tx/config
index b9ac976..376e152 100644
--- a/.tx/config
+++ b/.tx/config
@@ -1,123 +1,122 @@
[main]
host = https://www.transifex.com
-type = PO
-[calcurse.calcurse]
+[o:lfleischer:p:calcurse:r:calcurse]
file_filter = po/<lang>.po
source_file = po/calcurse.pot
source_lang = en
-[calcurse.doc-add]
+[o:lfleischer:p:calcurse:r:doc-add]
file_filter = po/doc/add-<lang>.po
source_file = po/doc/add.pot
source_lang = en
-[calcurse.doc-config]
+[o:lfleischer:p:calcurse:r:doc-config]
file_filter = po/doc/config-<lang>.po
source_file = po/doc/config.pot
source_lang = en
-[calcurse.doc-copy-paste]
+[o:lfleischer:p:calcurse:r:doc-copy-paste]
file_filter = po/doc/copy-paste-<lang>.po
source_file = po/doc/copy-paste.pot
source_lang = en
-[calcurse.doc-credits]
+[o:lfleischer:p:calcurse:r:doc-credits]
file_filter = po/doc/credits-<lang>.po
source_file = po/doc/credits.pot
source_lang = en
-[calcurse.doc-delete]
+[o:lfleischer:p:calcurse:r:doc-delete]
file_filter = po/doc/delete-<lang>.po
source_file = po/doc/delete.pot
source_lang = en
-[calcurse.doc-displacement]
+[o:lfleischer:p:calcurse:r:doc-displacement]
file_filter = po/doc/displacement-<lang>.po
source_file = po/doc/displacement.pot
source_lang = en
-[calcurse.doc-edit]
+[o:lfleischer:p:calcurse:r:doc-edit]
file_filter = po/doc/edit-<lang>.po
source_file = po/doc/edit.pot
source_lang = en
-[calcurse.doc-enote]
+[o:lfleischer:p:calcurse:r:doc-enote]
file_filter = po/doc/enote-<lang>.po
source_file = po/doc/enote.pot
source_lang = en
-[calcurse.doc-export]
+[o:lfleischer:p:calcurse:r:doc-export]
file_filter = po/doc/export-<lang>.po
source_file = po/doc/export.pot
source_lang = en
-[calcurse.doc-flag]
+[o:lfleischer:p:calcurse:r:doc-flag]
file_filter = po/doc/flag-<lang>.po
source_file = po/doc/flag.pot
source_lang = en
-[calcurse.doc-general]
+[o:lfleischer:p:calcurse:r:doc-general]
file_filter = po/doc/general-<lang>.po
source_file = po/doc/general.pot
source_lang = en
-[calcurse.doc-goto]
+[o:lfleischer:p:calcurse:r:doc-goto]
file_filter = po/doc/goto-<lang>.po
source_file = po/doc/goto.pot
source_lang = en
-[calcurse.doc-import]
+[o:lfleischer:p:calcurse:r:doc-import]
file_filter = po/doc/import-<lang>.po
source_file = po/doc/import.pot
source_lang = en
-[calcurse.doc-intro]
+[o:lfleischer:p:calcurse:r:doc-intro]
file_filter = po/doc/intro-<lang>.po
source_file = po/doc/intro.pot
source_lang = en
-[calcurse.doc-other]
+[o:lfleischer:p:calcurse:r:doc-other]
file_filter = po/doc/other-<lang>.po
source_file = po/doc/other.pot
source_lang = en
-[calcurse.doc-pipe]
+[o:lfleischer:p:calcurse:r:doc-pipe]
file_filter = po/doc/pipe-<lang>.po
source_file = po/doc/pipe.pot
source_lang = en
-[calcurse.doc-priority]
+[o:lfleischer:p:calcurse:r:doc-priority]
file_filter = po/doc/priority-<lang>.po
source_file = po/doc/priority.pot
source_lang = en
-[calcurse.doc-reload]
+[o:lfleischer:p:calcurse:r:doc-reload]
file_filter = po/doc/reload-<lang>.po
source_file = po/doc/reload.pot
source_lang = en
-[calcurse.doc-repeat]
+[o:lfleischer:p:calcurse:r:doc-repeat]
file_filter = po/doc/repeat-<lang>.po
source_file = po/doc/repeat.pot
source_lang = en
-[calcurse.doc-save]
+[o:lfleischer:p:calcurse:r:doc-save]
file_filter = po/doc/save-<lang>.po
source_file = po/doc/save.pot
source_lang = en
-[calcurse.doc-tab]
+[o:lfleischer:p:calcurse:r:doc-tab]
file_filter = po/doc/tab-<lang>.po
source_file = po/doc/tab.pot
source_lang = en
-[calcurse.doc-view]
+[o:lfleischer:p:calcurse:r:doc-view]
file_filter = po/doc/view-<lang>.po
source_file = po/doc/view.pot
source_lang = en
-[calcurse.doc-vnote]
+[o:lfleischer:p:calcurse:r:doc-vnote]
file_filter = po/doc/vnote-<lang>.po
source_file = po/doc/vnote.pot
source_lang = en
diff --git a/AUTHORS b/AUTHORS
index 4ce42ab..856f728 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,2 +1,3 @@
-Lukas Fleischer <lfleischer@calcurse.org>
Frederic Culot <frederic@culot.org>
+Lars Henriksen <LarsHenriksen@get2net.dk>
+Lukas Fleischer <lfleischer@calcurse.org>
diff --git a/CHANGES.md b/CHANGES.md
index 70a4d2a..acc24e4 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,6 +1,187 @@
Release Notes
=============
+Version 4.8.1 (2023-05-22)
+--------------------------
+
+- Bug fixes:
+
+ * Fixed characters in weekly view.
+
+ * AsciiDoc checks are skipped if --disable-docs is used.
+
+ * Fixed import for iCal files with empty description (fixed by Marian
+ Buschsieweke).
+
+ * Fixed handling of note files edited outside calcurse (fixed by Nicholas
+ Johnson).
+
+ * Fixed handling of recurrent open-ended appointments at 00:00.
+
+ * Default description for items with empty descriptions (reported and
+ partially implemented by Jonathan van der Steege).
+
+- New calcurse-caldav features:
+
+ * The PasswordCommand option can now be used to manage passwords in an
+ external program and is the new recommended way of storing passwords for
+ calcurse-caldav (implemented by Ryan Lue).
+
+Version 4.8.0 (2022-04-16)
+--------------------------
+
+- New features:
+
+ * Support any weekday as first day of week; previously, only Sunday and
+ Monday were allowed (implemented by Morgan Seltzer).
+
+ * Configuration of the format in which appointment time is displayed
+ (implemented by mercurialmoon).
+
+ * Actions without key bindings.
+
+ * generic-prev-view key binding to cycle backwards through windows
+ (implemented by Aurora).
+
+ * Support for Home/End keys in text input mode.
+
+- Bug fixes:
+
+ * Support compilation on big-endian systems (reported by nmeum).
+
+ * Fixed --docdir support (fixed by Marco Sirabella).
+
+ * Allow newlines in iCal SUMMARY by replacing them with blanks (reported by
+ Matthias Braun).
+
+ * Fixed sidebar configuration sometimes not increasing width (fixed by
+ Morgan Seltzer).
+
+ * Layout change recognizes changed appointment space; before this change, a
+ layout change did not update the maximum number of appointments visible
+ until the config menu was left (fixed by Morgan Seltzer).
+
+- calcurse-caldav bug fixes:
+
+ * Fixed InsecureSSL support (reported by Pitido).
+
+Version 4.7.1 (2021-04-11)
+--------------------------
+
+- Bug fixes:
+
+ * Multiple iCal import fixes: Make iCal event import independent of
+ property ordering. Return failure if an item is skipped. Avoid double
+ free on import errors. Fix parsing of UNTIL.
+
+ * Do not remove an empty note file after edit session.
+
+ * Keep internal linked list sorted when moving items.
+
+ * Prevent external hook/notification commands from interacting with the UI.
+
+- calcurse-caldav bug fixes:
+
+ * Allow non-ASCII characters in username and password (fixed by Henrik
+ Grimler).
+
+ * Improved error handling for the configuration file. Unknown keys are now
+ reported as errors instead of ignored.
+
+ * Always request href from server after pushing a new object to prevent
+ items from being erroneously deleted or created when path contains
+ characters that need to be URL-encoded (reported and fixed by Max
+ Deineko).
+
+Version 4.7.0 (2020-10-12)
+--------------------------
+
+- Compatibility notes:
+
+ * Note file contents are now exported as DESCRIPTION in iCal exports. For
+ notes that should not be exported, please use the "-- " separator
+ (dash-dash-space-newline); everything below that separator (including the
+ separator itself) is ignored during export.
+
+ * The item deletion menu has been redesigned and now looks as follows:
+
+ Delete (s)elected occurrence, (a)ll occurrences, or only the (n)ote?
+
+ Options that are not available (e.g. because the item is not recurrent
+ or does not have a note) are omitted.
+
+ * The systemdialogs option has been removed from the configuration. The
+ welcome window has been removed, import/export status messages are now
+ always displayed unless the --quiet command line flag is used.
+
+- New features:
+
+ * Support for advanced recurrence rules (e.g. "every year on last Sunday in
+ October"). Supported in the UI and in iCal imports. For details on how to
+ use advanced recurrences, run :help repeat. Sample iCal files with
+ advanced recurrence rules can be found in contrib/import/ in the calcurse
+ source tree.
+
+ * Repeat counts are accepted in the UI as an alternative to repetition end
+ dates for recurrent items (e.g. "#3" to specify that an item should have
+ three occurrences).
+
+ * The :previous and :next commands can be used to jump to the previous/next
+ occurrence of the currently selected recurrent item. This is useful for
+ verifying that a new (advanced) recurrence rule works as intended.
+
+ * Various improvements in iCal imports: Location, comment and status of
+ iCal events are now imported as special fields in the note file. The time
+ zone identifier (TZID) is now recognized, time fields are converted to a
+ local time and the zone identifier is logged in the note file.
+
+ * Notes are now displayed in the item view dialog (implemented by Ambika
+ Eshwar).
+
+- Bug fixes:
+
+ * Fixed formatting of DTSTART for recurrent events (implemented by
+ Jerem-K).
+
+ * Improvements in hook execution. Hooks are background jobs and must not
+ interfere with the terminal (stdin, stdout, stderr).
+
+- calcurse-caldav bug fixes:
+
+ * Checks to make sure the config and data dirs exist (implemented by
+ Nitroretro).
+
+Version 4.6.0 (2020-03-27)
+--------------------------
+
+- New features:
+
+ * XDG base directory support: While using ~/.calcurse/ is still supported
+ for backwards compatibility, we recommend putting your configuration
+ files in ~/.config/calcurse/ and your data files in
+ ~/.local/share/calcurse/ instead (implemented by Nitroretro).
+
+ * Configurable text for empty days (implemented by Lars Henriksen).
+
+ * Support RET to set the todo item priority to 0 (implemented by Issam
+ Maghni).
+
+ * Various improvements in iCal imports (implemented by Lars Henriksen).
+
+- New calcurse-caldav features:
+
+ * Documentation for Yahoo's Calendar Server.
+
+- Bug fixes:
+
+ * Escape necessary characters in SUMMARY on export (implemented by Kelvin
+ Jackson).
+
+ * Update notification bar properly when certain recurrent appointments are
+ deleted (implemented by Lars Henriksen).
+
+ * Fix save of interactively imported data (implemented by Lars Henriksen).
+
Version 4.5.1 (2019-10-18)
--------------------------
diff --git a/COPYING b/COPYING
index 333597b..ceb0721 100644
--- a/COPYING
+++ b/COPYING
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/README.md b/README.md
index 0d44048..009a5e6 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,26 @@
-calcurse
-========
+# calcurse
+
+[![Build and test](https://github.com/lfos/calcurse/actions/workflows/make.yml/badge.svg)](https://github.com/lfos/calcurse/actions/workflows/make.yml)
+[![Lint Python](https://github.com/lfos/calcurse/actions/workflows/lint_python.yml/badge.svg)](https://github.com/lfos/calcurse/actions/workflows/lint_python.yml)
![Demo](https://calcurse.org/images/demo.gif)
-Building
---------
+## Installation
+
+calcurse is available on a number of Linux distributions:
+
+[![Packaging status](https://repology.org/badge/vertical-allrepos/calcurse.svg)](https://repology.org/project/calcurse/versions)
+
+## Building from Source
-Install the following build dependencies. If your distro segments development
-files from core packages (i.e., \*-devel or \*-dev packages), you may need to
-install those as well:
+Install the following build dependencies. If your distribution segments
+development files from core packages (i.e., \*-devel or \*-dev packages), you
+may need to install those as well:
* gcc
+* autoconf-archive
* automake
+* autopoint
* asciidoc
* gettext with development files
* ncurses with development files
@@ -26,8 +35,7 @@ and install calcurse:
Note that `make install` needs to be run as root. When working on a Git
checkout, you need to run `./autogen.sh` before `./configure`.
-Package Overview
-----------------
+## Source Overview
* `build-aux`: auxiliary files for the build process
* `contrib`: useful tools such as hooks or the CalDAV synchronization script
@@ -37,18 +45,17 @@ Package Overview
* `src`: the actual calcurse source files
* `test`: test suite and test cases for calcurse
-Authors
--------
+## Authors
-calcurse was originally authored by Frederic Culot and is currently maintained
-by Lukas Fleischer.
+calcurse was created by Frederic Culot in 2004. Since 2011, the project is
+maintained by Lukas Fleischer. Many core features added to calcurse since 2017
+were designed and implemented by Lars Henriksen.
Of course, there are numerous other contributors. Check the Git commit log and
the `Thanks` section in the manual for a list of people who have contributed by
reporting bugs, sending fixes, or suggesting improvements.
-Contributing and Donations
---------------------------
+## Contributing and Donations
Patches, bug reports and other requests are always welcome! You can submit them
to one of our mailing lists (check the [patch submission
diff --git a/autogen.sh b/autogen.sh
index f737ace..ee8f12f 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,6 +1,6 @@
#!/bin/sh
#
-# Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+# Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
diff --git a/build-aux/git-version-gen b/build-aux/git-version-gen
index 67e4839..40c04b5 100755
--- a/build-aux/git-version-gen
+++ b/build-aux/git-version-gen
@@ -6,7 +6,7 @@ then
exit 1
fi
-DEF_VER=4.5.1
+DEF_VER=4.8.1
VERFILE="$1"
if [ -d '.git' ]
diff --git a/configure.ac b/configure.ac
index 1f6ec61..da211d0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,16 +1,14 @@
#-------------------------------------------------------------------------------
# Init
#-------------------------------------------------------------------------------
-AC_PREREQ(2.59)
-AC_INIT([calcurse],
- m4_esyscmd([build-aux/git-version-gen .version]),
- [bugs@calcurse.org])
+AC_PREREQ([2.71])
+AC_INIT([calcurse],[m4_esyscmd(build-aux/git-version-gen .version)],[bugs@calcurse.org])
AM_INIT_AUTOMAKE
#m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
AM_GNU_GETTEXT([external])
-AM_GNU_GETTEXT_VERSION([0.14.1])
+AM_GNU_GETTEXT_VERSION([0.19.8])
AC_CONFIG_SRCDIR([src/calcurse.c])
-AC_CONFIG_HEADER([config.h])
+AC_CONFIG_HEADERS([config.h])
#-------------------------------------------------------------------------------
# Checks for system type
#-------------------------------------------------------------------------------
@@ -19,37 +17,22 @@ AC_CANONICAL_HOST
# Checks for programs
#-------------------------------------------------------------------------------
AC_PROG_CC
+AC_C_BIGENDIAN
#-------------------------------------------------------------------------------
# Checks for header files
#-------------------------------------------------------------------------------
-AC_HEADER_STDC
AC_CHECK_HEADERS([ctype.h getopt.h locale.h math.h signal.h stdio.h stdlib.h \
string.h sys/stat.h sys/types.h sys/wait.h time.h unistd.h \
fcntl.h paths.h errno.h limits.h regex.h])
#-------------------------------------------------------------------------------
# Checks for system libs
#-------------------------------------------------------------------------------
-AC_CHECK_FUNC(initscr,,
-[
- available_ncurses="none"
- for lib in ncursesw ncurses
- do
- AC_CHECK_LIB($lib, initscr,
- [available_ncurses="$lib"; break])
- done
- if test "$available_ncurses" = none; then
- AC_MSG_ERROR(Either ncurses or ncursesw library is required to build calcurse!)
- elif test "$available_ncurses" = ncursesw; then
- AC_CHECK_HEADERS([ncursesw/ncurses.h],,
- [AC_CHECK_HEADERS([ncurses.h],,
- AC_MSG_ERROR([Missing ncursesw header file]))])
- else
- AC_CHECK_HEADERS([ncurses/ncurses.h],,
- [AC_CHECK_HEADERS([ncurses.h],,
- AC_MSG_ERROR([Missing ncurses header file]))])
- fi
- LIBS="$LIBS -l$available_ncurses"
-])
+AX_WITH_CURSES
+if test "x$ax_cv_ncursesw" != xyes && test "x$ax_cv_ncurses" != xyes; then
+ AC_MSG_ERROR(Either ncurses or ncursesw library is required to build calcurse!)
+fi
+
+LIBS="$LIBS $CURSES_LIBS"
AC_CHECK_HEADERS([pthread.h], [
AC_CHECK_LIB(pthread, pthread_create, [
@@ -76,7 +59,6 @@ AC_ARG_ENABLE(docs,
[enabledocs=$enableval], [enabledocs=yes])
if test x"$enabledocs" != x"yes"; then
enabledocs=no
- AC_MSG_WARN([Skipping documentation!])
fi
AC_MSG_CHECKING([whether to include documentation])
AC_MSG_RESULT($enabledocs)
@@ -87,7 +69,21 @@ AC_ARG_WITH(asciidoc,
[use AsciiDoc to regenerate documentation]),
[use_asciidoc=$withval],
[use_asciidoc="auto"])
-if test x"$use_asciidoc" = x"auto"; then
+if test x"$enabledocs" = x"no" -o x"$use_asciidoc" = x"no"; then
+ AC_MSG_WARN([Will not rebuild documentation!])
+ have_asciidoc=no
+ have_a2x=no
+elif test x"$use_asciidoc" = x"yes"; then
+ AC_PATH_PROG([ASCIIDOC], [asciidoc])
+ if test -z "$ASCIIDOC"; then
+ AC_MSG_ERROR([AsciiDoc not found and "--with-asciidoc" specified!])
+ fi
+ AC_PATH_PROG([A2X], [a2x])
+ if test -z "$A2X"; then
+ AC_MSG_ERROR([a2x not found and "--with-asciidoc" specified!])
+ fi
+ have_asciidoc=yes
+elif test x"$use_asciidoc" = x"auto"; then
AC_PATH_PROG([ASCIIDOC], [asciidoc])
if test -z "$ASCIIDOC"; then
have_asciidoc=no
@@ -112,20 +108,6 @@ if test x"$use_asciidoc" = x"auto"; then
else
have_a2x=yes
fi
-elif test x"$use_asciidoc" = x"yes"; then
- AC_PATH_PROG([ASCIIDOC], [asciidoc])
- if test -z "$ASCIIDOC"; then
- AC_MSG_ERROR([AsciiDoc not found and "--with-asciidoc" specified!])
- fi
- AC_PATH_PROG([A2X], [a2x])
- if test -z "$A2X"; then
- AC_MSG_ERROR([a2x not found and "--with-asciidoc" specified!])
- fi
- have_asciidoc=yes
-elif test x"$use_asciidoc" = x"no"; then
- AC_MSG_WARN([Will not rebuild documentation!])
- have_asciidoc=no
- have_a2x=no
fi
AM_CONDITIONAL(HAVE_ASCIIDOC, test $have_asciidoc = yes)
AM_CONDITIONAL(HAVE_A2X, test $have_a2x = yes)
@@ -152,9 +134,10 @@ AM_CONDITIONAL(CALCURSE_MEMORY_DEBUG, test x$memdebug = xyes)
#-------------------------------------------------------------------------------
# Create Makefiles
#-------------------------------------------------------------------------------
-AC_OUTPUT(Makefile doc/Makefile src/Makefile test/Makefile \
+AC_CONFIG_FILES([Makefile doc/Makefile src/Makefile test/Makefile \
scripts/Makefile po/Makefile.in po/Makefile \
- contrib/caldav/Makefile contrib/vdir/Makefile)
+ contrib/caldav/Makefile contrib/vdir/Makefile])
+AC_OUTPUT
#-------------------------------------------------------------------------------
# Summary
#-------------------------------------------------------------------------------
diff --git a/contrib/caldav/README.md b/contrib/caldav/README.md
index a842081..b464dc9 100644
--- a/contrib/caldav/README.md
+++ b/contrib/caldav/README.md
@@ -34,13 +34,12 @@ argument. You can choose between the following initialization modes:
For subsequent calcurse-caldav invocations, you don't need to specify any
additional parameters.
-You can specify a username and password for basic authentication in the
-config file. Alternatively, the password can be passed securely from another
-program (such as *pass*) via the `CALCURSE_CALDAV_PASSWORD` environment variable like
-so:
-```
-CALCURSE_CALDAV_PASSWORD=$(pass show calcurse) calcurse-caldav
-```
+Specify your HTTP Basic authentication credentials under the config file's
+`Auth` section. The most secure approach is to save your password in a CLI
+encrypted password store (_e.g.,_ [pass](https://www.passwordstore.org/)), and
+then set `PasswordCommand` to the shell command used to retrieve it.
+If security is not a priority, you may store your password in plain text
+instead.
Hooks
-----
diff --git a/contrib/caldav/calcurse-caldav.py b/contrib/caldav/calcurse-caldav.py
index ec8f8fb..5efd306 100755
--- a/contrib/caldav/calcurse-caldav.py
+++ b/contrib/caldav/calcurse-caldav.py
@@ -3,24 +3,92 @@
import argparse
import base64
import configparser
-import httplib2
import os
+import pathlib
import re
+import shlex
import subprocess
import sys
import textwrap
-import urllib.parse
import xml.etree.ElementTree as etree
+import httplib2
+
# Optional libraries for OAuth2 authentication
try:
- from oauth2client.client import OAuth2WebServerFlow, HttpAccessTokenRefreshError
- from oauth2client.file import Storage
import webbrowser
+
+ from oauth2client.client import HttpAccessTokenRefreshError, OAuth2WebServerFlow
+ from oauth2client.file import Storage
except ModuleNotFoundError:
pass
+class Config:
+ _map = {}
+
+ def __init__(self, fn):
+ self._map = {
+ 'Auth': {
+ 'Password': None,
+ 'PasswordCommand': None,
+ 'Username': None,
+ },
+ 'CustomHeaders': {},
+ 'General': {
+ 'AuthMethod': 'basic',
+ 'Binary': 'calcurse',
+ 'Debug': False,
+ 'DryRun': True,
+ 'HTTPS': True,
+ 'Hostname': None,
+ 'InsecureSSL': False,
+ 'Path': None,
+ 'SyncFilter': 'cal,todo',
+ 'Verbose': False,
+ },
+ 'OAuth2': {
+ 'ClientID': None,
+ 'ClientSecret': None,
+ 'RedirectURI': 'http://127.0.0.1',
+ 'Scope': None,
+ },
+ }
+
+ config = configparser.RawConfigParser()
+ config.optionxform = str
+ if verbose:
+ print('Loading configuration from ' + configfn + '...')
+ try:
+ config.read_file(open(fn))
+ except FileNotFoundError:
+ die('Configuration file not found: {}'.format(fn))
+
+ for sec in config.sections():
+ if sec not in self._map:
+ die('Unexpected config section: {}'.format(sec))
+
+ if not self._map[sec]:
+ # Import section with custom key-value pairs.
+ self._map[sec] = dict(config.items(sec))
+ continue
+
+ # Import section with predefined keys.
+ for key, val in config.items(sec):
+ if key not in self._map[sec]:
+ die('Unexpected config key in section {}: {}'.format(sec, key))
+ if isinstance(self._map[sec][key], bool):
+ self._map[sec][key] = config.getboolean(sec, key)
+ else:
+ self._map[sec][key] = val
+
+ def section(self, section):
+ return self._map[section]
+
+ def get(self, section, key):
+ return self._map[section][key]
+
+
def msgfmt(msg, prefix=''):
lines = []
for line in msg.splitlines():
@@ -37,8 +105,10 @@ def die(msg):
def check_dir(dir):
- if not os.path.isdir(dir):
- die("invalid directory: {0}".format(dir))
+ try:
+ pathlib.Path(dir).mkdir(parents=True, exist_ok=True)
+ except FileExistsError:
+ die("{} is not a directory".format(dir))
def die_atnode(msg, node):
@@ -145,8 +215,8 @@ def calcurse_version():
def get_auth_headers():
if not username or not password:
return {}
- user_password = ('{}:{}'.format(username, password)).encode('ascii')
- user_password = base64.b64encode(user_password).decode('ascii')
+ user_password = ('{}:{}'.format(username, password)).encode('utf-8')
+ user_password = base64.b64encode(user_password).decode('utf-8')
headers = {'Authorization': 'Basic {}'.format(user_password)}
return headers
@@ -351,18 +421,21 @@ def push_object(conn, objhash):
if not headers:
return None
-
- etag = None
headerdict = dict(headers)
- if 'etag' in headerdict:
- etag = headerdict['etag']
- while not etag:
+
+ # Retrieve href from server to match server-side format. Retrieve ETag
+ # unless it can be extracted from the PUT response already.
+ ret_href, ret_etag = None, headerdict.get('etag')
+ while not ret_etag or not ret_href:
etagdict = get_etags(conn, [href])
- if etagdict:
- etag = next(iter(etagdict.values()))
- etag = etag.strip('"')
+ if not etagdict:
+ continue
+ ret_href, new_etag = next(iter(etagdict.items()))
+ # Favor ETag from PUT response to avoid race condition.
+ if not ret_etag:
+ ret_etag = new_etag
- return (urllib.parse.quote(href), etag)
+ return (ret_href, ret_etag.strip('"'))
def push_objects(objhashes, conn, syncdb, etagdict):
@@ -520,20 +593,28 @@ nsmap = {"D": "DAV:", "C": "urn:ietf:params:xml:ns:caldav"}
# Initialize default values.
if os.path.isdir(os.path.expanduser("~/.calcurse")):
- configfn = os.path.expanduser("~/.calcurse/caldav/config")
- lockfn = os.path.expanduser("~/.calcurse/caldav/lock")
- syncdbfn = os.path.expanduser("~/.calcurse/caldav/sync.db")
- hookdir = os.path.expanduser("~/.calcurse/caldav/hooks/")
- oauth_file = os.path.expanduser("~/.calcurse/caldav/oauth2_cred")
+ caldav_path = os.path.expanduser("~/.calcurse/caldav")
+ check_dir(caldav_path)
+
+ configfn = os.path.join(caldav_path, "config")
+ hookdir = os.path.join(caldav_path, "hooks")
+ oauth_file = os.path.join(caldav_path, "oauth2_cred")
+ lockfn = os.path.join(caldav_path, "lock")
+ syncdbfn = os.path.join(caldav_path, "sync.db")
else:
- calcurse_data = os.getenv("XDG_DATA_HOME", os.path.expanduser("~/.local/share")) + "/calcurse"
- calcurse_config = os.getenv("XDG_CONFIG_HOME", os.path.expanduser("~/.local/share")) + "/calcurse"
+ xdg_config_home = os.getenv("XDG_CONFIG_HOME", os.path.expanduser("~/.config"))
+ xdg_data_home = os.getenv("XDG_DATA_HOME", os.path.expanduser("~/.local/share"))
+ caldav_config = os.path.join(xdg_config_home, "calcurse", "caldav")
+ caldav_data = os.path.join(xdg_data_home, "calcurse", "caldav")
+ check_dir(caldav_config)
+ check_dir(caldav_data)
- configfn = os.path.expanduser(calcurse_config + "/caldav/config")
- lockfn = os.path.expanduser(calcurse_data + "/caldav/lock")
- syncdbfn = os.path.expanduser(calcurse_data + "/caldav/sync.db")
- hookdir = os.path.expanduser(calcurse_config + "/caldav/hooks/")
- oauth_file = os.path.expanduser(calcurse_config + "/caldav/oauth2_cred")
+ configfn = os.path.join(caldav_config, "config")
+ hookdir = os.path.join(caldav_config, "hooks")
+ oauth_file = os.path.join(caldav_config, "oauth2_cred")
+
+ lockfn = os.path.join(caldav_data, "lock")
+ syncdbfn = os.path.join(caldav_data, "sync.db")
# Parse command line arguments.
parser = argparse.ArgumentParser('calcurse-caldav')
@@ -578,105 +659,58 @@ verbose = args.verbose
debug = args.debug
debug_raw = args.debug_raw
-# Read environment variables
-password = os.getenv('CALCURSE_CALDAV_PASSWORD')
-
# Read configuration.
-config = configparser.RawConfigParser()
-if verbose:
- print('Loading configuration from ' + configfn + '...')
-try:
- config.read_file(open(configfn))
-except FileNotFoundError as e:
- die('Configuration file not found: {}'.format(configfn))
-
-if config.has_option('General', 'InsecureSSL'):
- insecure_ssl = config.getboolean('General', 'InsecureSSL')
+config = Config(configfn)
+
+authmethod = config.get('General', 'AuthMethod').lower()
+calcurse = [config.get('General', 'Binary')]
+debug = debug or config.get('General', 'Debug')
+dry_run = config.get('General', 'DryRun')
+hostname = config.get('General', 'Hostname')
+https = config.get('General', 'HTTPS')
+insecure_ssl = config.get('General', 'InsecureSSL')
+path = config.get('General', 'Path')
+sync_filter = config.get('General', 'SyncFilter')
+verbose = verbose or config.get('General', 'Verbose')
+
+if os.getenv('CALCURSE_CALDAV_PASSWORD'):
+ # This approach is deprecated, but preserved for backwards compatibility
+ password = os.getenv('CALCURSE_CALDAV_PASSWORD')
+elif config.get('Auth', 'Password'):
+ password = config.get('Auth', 'Password')
+elif config.get('Auth', 'PasswordCommand'):
+ tokenized_cmd = shlex.split(config.get('Auth', 'PasswordCommand'))
+ password = subprocess.run(
+ tokenized_cmd, capture_output=True).stdout.decode('UTF-8').rstrip('\n')
else:
- insecure_ssl = False
+ password = None
-# Read config for "HTTPS" option (default=True)
-if config.has_option('General', 'HTTPS'):
- https = config.getboolean('General', 'HTTPS')
-else:
- https = True
+username = config.get('Auth', 'Username')
-if config.has_option('General', 'Binary'):
- calcurse = [config.get('General', 'Binary')]
-else:
- calcurse = ['calcurse']
+client_id = config.get('OAuth2', 'ClientID')
+client_secret = config.get('OAuth2', 'ClientSecret')
+redirect_uri = config.get('OAuth2', 'RedirectURI')
+scope = config.get('OAuth2', 'Scope')
+
+custom_headers = config.section('CustomHeaders')
+# Append data directory to calcurse command.
if datadir:
check_dir(datadir)
calcurse += ['-D', datadir]
-if config.has_option('General', 'DryRun'):
- dry_run = config.getboolean('General', 'DryRun')
-else:
- dry_run = True
-
-if not verbose and config.has_option('General', 'Verbose'):
- verbose = config.getboolean('General', 'Verbose')
-
-if not debug and config.has_option('General', 'Debug'):
- debug = config.getboolean('General', 'Debug')
-
-if config.has_option('General', 'AuthMethod'):
- authmethod = config.get('General', 'AuthMethod').lower()
-else:
- authmethod = 'basic'
-
-if config.has_option('General', 'SyncFilter'):
- sync_filter = config.get('General', 'SyncFilter')
-
- invalid_filter_values = validate_sync_filter()
-
- if len(invalid_filter_values):
- die('Invalid value(s) in SyncFilter option: ' + ', '.join(invalid_filter_values))
-else:
- sync_filter = 'cal,todo'
-
-if config.has_option('Auth', 'UserName'):
- username = config.get('Auth', 'UserName')
-else:
- username = None
-
-if config.has_option('Auth', 'Password') and not password:
- password = config.get('Auth', 'Password')
-
-if config.has_section('CustomHeaders'):
- custom_headers = dict(config.items('CustomHeaders'))
-else:
- custom_headers = {}
-
-if config.has_option('OAuth2', 'ClientID'):
- client_id = config.get('OAuth2', 'ClientID')
-else:
- client_id = None
-
-if config.has_option('OAuth2', 'ClientSecret'):
- client_secret = config.get('OAuth2', 'ClientSecret')
-else:
- client_secret = None
-
-if config.has_option('OAuth2', 'Scope'):
- scope = config.get('OAuth2', 'Scope')
-else:
- scope = None
-
-if config.has_option('OAuth2', 'RedirectURI'):
- redirect_uri = config.get('OAuth2', 'RedirectURI')
-else:
- redirect_uri = 'http://127.0.0.1'
-
-# Change URl prefix according to HTTP/HTTPS
-if https:
- urlprefix = "https://"
-else:
- urlprefix = "http://"
-
-hostname = config.get('General', 'HostName')
-path = '/' + config.get('General', 'Path').strip('/') + '/'
+# Validate sync filter.
+invalid_filter_values = validate_sync_filter()
+if len(invalid_filter_values):
+ die('Invalid value(s) in SyncFilter option: ' + ', '.join(invalid_filter_values))
+
+# Ensure host name and path are defined and initialize *_uri.
+if not hostname:
+ die('Hostname missing in configuration.')
+if not path:
+ die('Path missing in configuration.')
+urlprefix = "https://" if https else "http://"
+path = '/{}/'.format(path.strip('/'))
hostname_uri = urlprefix + hostname
absolute_uri = hostname_uri + path
@@ -709,9 +743,7 @@ try:
# Connect to the server.
if verbose:
print('Connecting to ' + hostname + '...')
- conn = httplib2.Http()
- if insecure_ssl:
- conn.disable_ssl_certificate_validation = True
+ conn = httplib2.Http(disable_ssl_certificate_validation=insecure_ssl)
if authmethod == 'oauth2':
# Authenticate with OAuth2 and authorize HTTP object
@@ -774,7 +806,7 @@ try:
# Write the synchronization database.
save_syncdb(syncdbfn, syncdb)
- #Clear OAuth2 credentials if used
+ # Clear OAuth2 credentials if used.
if authmethod == 'oauth2':
conn.clear_credentials()
diff --git a/contrib/caldav/config.sample b/contrib/caldav/config.sample
index c89cfb7..0ba8fa8 100644
--- a/contrib/caldav/config.sample
+++ b/contrib/caldav/config.sample
@@ -11,10 +11,12 @@
# Path to the calcurse binary that is used for importing/exporting items.
Binary = calcurse
-# Host name of the server that hosts CalDAV.
+# Host name of the server that hosts CalDAV. Do NOT prepend a protocol prefix,
+# such as http:// or https://. Append :<port> for a port other than 80.
Hostname = some.hostname.com
-# Path to the CalDAV calendar on the host specified above.
+# Path to the CalDAV calendar on the host specified above. This is the base
+# path following your host name in the URL.
Path = /path/to/calendar/on/the/server/
# Type of authentication to use. Must be "basic" or "oauth2"
@@ -46,11 +48,13 @@ DryRun = Yes
# Enable this if you want detailed logs written to stdout.
Verbose = Yes
-# Credentials for HTTP Basic Authentication. Leave this commented out if you do
-# not want to use authentication.
+# Credentials for HTTP Basic Authentication (if required).
+# Set `Password` to your password in plaintext (unsafe),
+# or `PasswordCommand` to a shell command that retrieves it (recommended).
#[Auth]
#Username = user
-#Password = pass
+#Password = password
+#PasswordCommand = pass baikal
# Optionally specify additional HTTP headers here.
#[CustomHeaders]
diff --git a/contrib/caldav/hooks/post-sync b/contrib/caldav/hooks/post-sync
index 62ebe11..db0059b 100755
--- a/contrib/caldav/hooks/post-sync
+++ b/contrib/caldav/hooks/post-sync
@@ -26,7 +26,7 @@ commit_dir() {
if [ -d .git ] && command -v git >/dev/null; then
git add "$@"
if ! git diff-index --quiet --cached HEAD; then
- git commit -m "Automatic commit by the post-save hook"
+ git commit -m "Automatic commit by the post-sync hook"
fi
fi
}
diff --git a/contrib/import/DST-et.ical b/contrib/import/DST-et.ical
new file mode 100644
index 0000000..116fe95
--- /dev/null
+++ b/contrib/import/DST-et.ical
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;VALUE=DATE:20200329
+SUMMARY:Daylight Saving Time begins (EDT)
+RRULE:FREQ=YEARLY;BYDAY=2SU;BYMONTH=3
+END:VEVENT
+END:VCALENDAR
diff --git a/contrib/import/DST-eu.ical b/contrib/import/DST-eu.ical
new file mode 100644
index 0000000..e536cf0
--- /dev/null
+++ b/contrib/import/DST-eu.ical
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;VALUE=DATE:20200329
+SUMMARY:Daylight Saving Time begins (CEST)
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3
+END:VEVENT
+END:VCALENDAR
diff --git a/contrib/import/February.ical b/contrib/import/February.ical
new file mode 100644
index 0000000..15168d4
--- /dev/null
+++ b/contrib/import/February.ical
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART:20200228T080000
+SUMMARY:Penultimate day in February
+RRULE:FREQ=MONTHLY;BYMONTHDAY=-2;BYMONTH=2
+END:VEVENT
+END:VCALENDAR
diff --git a/contrib/import/Monday-first-last.ical b/contrib/import/Monday-first-last.ical
new file mode 100644
index 0000000..431bebb
--- /dev/null
+++ b/contrib/import/Monday-first-last.ical
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART:20200106T120000
+SUMMARY:First and last Monday of the month
+RRULE:FREQ=MONTHLY;BYDAY=1MO,-1MO;COUNT=10
+END:VEVENT
+END:VCALENDAR
diff --git a/contrib/import/Tuesday-Thursday.ical b/contrib/import/Tuesday-Thursday.ical
new file mode 100644
index 0000000..84c5adb
--- /dev/null
+++ b/contrib/import/Tuesday-Thursday.ical
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART:20200102T120000
+SUMMARY:Every Tuesday and Thursday
+RRULE:FREQ=WEEKLY;BYDAY=TU,TH;COUNT=10
+END:VEVENT
+END:VCALENDAR
diff --git a/contrib/import/Wednesdays-all.ical b/contrib/import/Wednesdays-all.ical
new file mode 100644
index 0000000..40730b8
--- /dev/null
+++ b/contrib/import/Wednesdays-all.ical
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;VALUE=DATE:20200603
+SUMMARY:All Wednesdays in June and July
+RRULE:FREQ=MONTHLY;BYDAY=WE;BYMONTH=6,7;UNTIL=20220630
+END:VEVENT
+END:VCALENDAR
diff --git a/contrib/setup.cfg b/contrib/setup.cfg
new file mode 100644
index 0000000..0691fee
--- /dev/null
+++ b/contrib/setup.cfg
@@ -0,0 +1,3 @@
+[flake8]
+max-line-length = 100
+max-complexity = 16
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 73cd8ce..adee962 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -57,8 +57,6 @@ CLEANFILES = \
submitting-patches.html \
calcurse.1
-docdir = $(datadir)/doc/$(PACKAGE)
-
.txt.html:
if HAVE_ASCIIDOC
$(AM_V_GEN) $(ASCIIDOC) $(ASCIIDOC_ARGS) $<
diff --git a/doc/calcurse.1.txt b/doc/calcurse.1.txt
index ff31be2..1f79f9a 100644
--- a/doc/calcurse.1.txt
+++ b/doc/calcurse.1.txt
@@ -1,6 +1,6 @@
////
/*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -57,7 +57,7 @@ The first form shows how to invoke calcurse interactively; the remainder is
command line forms.
The second form shows queries (as opposed to interactive use). For
-convenience, common queries have abbriviated forms shown in the third line.
+convenience, common queries have abbreviated forms shown in the third line.
All queries may be combined with filter options as well as format options.
The fourth form shows operations on the calcurse data files, one for
@@ -91,7 +91,7 @@ and issue reminders; it stops automatically when the interactive mode is
reentered.
This man page mainly describes the command-line mode. The following two
-subsections contain some general desriptions of command line options and usage.
+subsections contain some general descriptions of command line options and usage.
Input and Output Date Format
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -190,7 +190,7 @@ displays those for yesterday and today. The first form is equivalent to *-Q
<<_format_options,Format Options>>.
*--export-uid*::
- When exporting items, add the hash of each item to the exported object as an
+ When exporting items, add the hash of each item to the exported object as a
UID property.
*--from* 'date'::
@@ -206,7 +206,7 @@ displays those for yesterday and today. The first form is equivalent to *-Q
*-g*, *--gc*::
Run the garbage collector for note files. The garbage collector removes
files from the +notes+ directory (see <<_files,FILES>>) that are no longer
- linked to an item. Ususally done automatically by setting the configuration
+ linked to an item. Usually done automatically by setting the configuration
option +general.autogc+ in the 'General Options' submenu in interactive mode.
*-G*, *--grep*::
@@ -764,5 +764,5 @@ AUTHORS
COPYRIGHT
---------
-Copyright (c) 2004-2018 calcurse Development Team.
+Copyright (c) 2004-2023 calcurse Development Team.
This software is released under the BSD License.
diff --git a/doc/credits.txt b/doc/credits.txt
index b9ce181..e1f5ae7 100644
--- a/doc/credits.txt
+++ b/doc/credits.txt
@@ -1,7 +1,7 @@
Calcurse - text-based organizer
===============================
-Copyright (c) 2004-2017 calcurse Development Team
+Copyright (c) 2004-2023 calcurse Development Team
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/doc/de/credits.txt b/doc/de/credits.txt
index b9ce181..e1f5ae7 100644
--- a/doc/de/credits.txt
+++ b/doc/de/credits.txt
@@ -1,7 +1,7 @@
Calcurse - text-based organizer
===============================
-Copyright (c) 2004-2017 calcurse Development Team
+Copyright (c) 2004-2023 calcurse Development Team
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/doc/es/credits.txt b/doc/es/credits.txt
index b9ce181..e1f5ae7 100644
--- a/doc/es/credits.txt
+++ b/doc/es/credits.txt
@@ -1,7 +1,7 @@
Calcurse - text-based organizer
===============================
-Copyright (c) 2004-2017 calcurse Development Team
+Copyright (c) 2004-2023 calcurse Development Team
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/doc/fr/credits.txt b/doc/fr/credits.txt
index b9ce181..e1f5ae7 100644
--- a/doc/fr/credits.txt
+++ b/doc/fr/credits.txt
@@ -1,7 +1,7 @@
Calcurse - text-based organizer
===============================
-Copyright (c) 2004-2017 calcurse Development Team
+Copyright (c) 2004-2023 calcurse Development Team
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/doc/manual.txt b/doc/manual.txt
index de74a32..03a27ff 100644
--- a/doc/manual.txt
+++ b/doc/manual.txt
@@ -1,6 +1,6 @@
////
/*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -117,7 +117,7 @@ gettext library
`gettext` utilities. This means `calcurse` can produce multi-lingual messages
if compiled with native language support (i.e. *NLS*).
-However, *NLS* is optionnal and if you do not want to have support for
+However, *NLS* is optional and if you do not want to have support for
multi-lingual messages, you can disable this feature. This is done by giving
the `--disable-nls` option to `configure` (see section
<<install_process,Install process>>). To check if the `gettext` utilities are
@@ -143,7 +143,7 @@ Install process
First you need to gunzip and untar the source archive:
----
-$ tar zxvf calcurse-4.5.1.tar.gz
+$ tar zxvf calcurse-4.8.1.tar.gz
----
Once you meet the requirements and have extracted the archive, the install
@@ -303,7 +303,7 @@ can be specified using the `-c` flag.
information on format strings.
`--export-uid`::
- When exporting items, add the hash of each item to the exported object as an
+ When exporting items, add the hash of each item to the exported object as a
UID property.
`-F`, `--filter`::
@@ -596,7 +596,7 @@ Environment variable for i18n
<<install_requirements_gettext,gettext library>>). Thus, if you wish to have
messages displayed into your native language, first make sure it is available
by looking at the `po/LINGUAS` file. This file indicates the set of available
-languages by showing the two-letters corresponding code (for exemple, *fr*
+languages by showing the two-letters corresponding code (for example, *fr*
stands for french). If you do not find your language, it would be greatly
appreciated if you could help translating `calcurse` (see the <<contribute,How
to contribute?>> section).
@@ -607,7 +607,7 @@ If your language is available, run `calcurse` with the following command:
$ LC_ALL=fr_FR calcurse
----
-... where *fr_FR* is the locale name in this exemple, but should be replaced by
+... where *fr_FR* is the locale name in this example, but should be replaced by
the locale corresponding to the desired language.
You should also specify the charset to be used, because in some cases the
@@ -650,9 +650,9 @@ directory. Also make sure the scripts are executable.
*pre-load*::
Executed before the data files are loaded.
*post-load*::
- Executed after the data files are saved.
+ Executed after the data files are loaded.
*pre-save*::
- Executed before the data files are loaded.
+ Executed before the data files are saved.
*post-save*::
Executed after the data files are saved.
@@ -933,7 +933,7 @@ Here are the properties that are not implemented:
* negative time durations are not taken into account (item is skipped)
-* some recurence frequences are not recognize: "SECONDLY" / "MINUTELY" /
+* some recurrence frequencies are not recognize: "SECONDLY" / "MINUTELY" /
"HOURLY"
* some recurrence keywords are not recognized (all those starting with `BY`):
@@ -1096,7 +1096,7 @@ applied. It is possible to keep the terminal's default colors by selecting the
corresponding choice in the list.
The chosen color theme will then be applied to the panel borders, to the
-titles, to the keystrokes, and to general informations displayed inside status
+titles, to the keystrokes, and to general information displayed inside status
bar. A black and white theme is also available, in order to support non-color
terminals.
@@ -1241,7 +1241,7 @@ native language, it would be appreciated if you could help translating it.
To do so, just copy one of the existing manual file to `manual_XX.html`, where
*XX* identifies your language. Then translate this newly created file and send
-it to the author (see <<bugs,Reporting bugs and feeback>>), so that it can be
+it to the author (see <<bugs,Reporting bugs and feedback>>), so that it can be
included in the next `calcurse` release.
calcurse i18n
@@ -1251,10 +1251,10 @@ As already mentioned, `gettext` utilities are used by `calcurse` to produce
multi-lingual messages. We are currently using
http://www.transifex.net/[Transifex] to manage those translations.
-This section provides informations about how to translate those messages into
+This section provides information about how to translate those messages into
your native language. However, this howto is deliberately incomplete, focusing
on working with `gettext` for `calcurse` specifically. For more comprehensive
-informations or to grasp the Big Picture of Native Language Support, you should
+information or to grasp the Big Picture of Native Language Support, you should
refer to the `GNU gettext` manual at:
http://www.gnu.org/software/gettext/manual/
@@ -1379,19 +1379,19 @@ msgid ""
You should also fill in the Last-Translator field, so that potential
contributors can contact you if they want to join you in the translation team,
or have remarks/typo fixes to give about the translations. You can either just
-give your name/nick, or add an email address, for exemple:
+give your name/nick, or add an email address, for example:
+
----
"Last-Translator: Frederic Culot <frederic@culot.org>\n"
----
*Comments*::
- Adding comments (lines begining with the `#` character) can be a good way to
+ Adding comments (lines beginning with the `#` character) can be a good way to
point out problems or translation difficulties to proofreaders or other
members of your team.
*Strings size*::
- `calcurse` is a curses/console program, thus it can be heavily dependant on
+ `calcurse` is a curses/console program, thus it can be heavily dependent on
the terminal size (number of columns). You should think about this when
translating. Often, a string must fit into a single line (standard length is
80 characters). Don't translate blindly, try to look where your string will
@@ -1519,7 +1519,7 @@ Thanks
Its time now to thank other people without whom this program would not exist!
So here is a list of contributing persons I would like to thank:
-* Alex for its patches, help and advices with `C` programming
+* Alex for its patches, help and advice with `C` programming
* Gwen for testing and general discussions about how to improve `calcurse`
diff --git a/doc/nl/credits.txt b/doc/nl/credits.txt
index b9ce181..e1f5ae7 100644
--- a/doc/nl/credits.txt
+++ b/doc/nl/credits.txt
@@ -1,7 +1,7 @@
Calcurse - text-based organizer
===============================
-Copyright (c) 2004-2017 calcurse Development Team
+Copyright (c) 2004-2023 calcurse Development Team
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/doc/pt_BR/credits.txt b/doc/pt_BR/credits.txt
index d5a4231..82efeb5 100644
--- a/doc/pt_BR/credits.txt
+++ b/doc/pt_BR/credits.txt
@@ -1,7 +1,7 @@
Calcurse - organizador baseado em texto
=======================================
-Copyright (c) 2004-2017 Equipe de Desenvolvimento do Calcurse
+Copyright (c) 2004-2023 Equipe de Desenvolvimento do Calcurse
Todos os direitos reservados.
A redistribuição e uso na forma de código-fonte e binário, com ou
diff --git a/doc/repeat.txt b/doc/repeat.txt
index 16a71da..584a442 100644
--- a/doc/repeat.txt
+++ b/doc/repeat.txt
@@ -4,32 +4,147 @@ Repeat
Repeat an event or an appointment.
You must first select the item to be repeated by moving inside the appointment
-panel. Then running the repeat command will lead you to a set of three
-questions, with which you will be able to specify the repetition
-characteristics:
-
- o type: you can choose between a daily, weekly, monthly or
- yearly repetition by pressing 'D', 'W', 'M' or 'Y'
- respectively.
-
- o frequency: this indicates how often the item shall be repeated.
- For example, if you want to remember an anniversary,
- choose a 'yearly' repetition with a frequency of '1',
- which means it must be repeated every year. Another
- example: if you go to the restaurant every two days,
- choose a 'daily' repetition with a frequency of '2'.
-
- o ending date: this specifies when to stop repeating the selected
- event or appointment. To indicate an endless
- repetition, enter '0' and the item will be repeated
- forever.
-
-Notes
------
-
-* Repeated items are marked with an '*' inside the appointment panel, to be
- easily recognizable from non-repeated ones.
-
-* The 'Repeat' and 'Delete' command can be mixed to create complicated
- configurations, as it is possible to delete only one occurrence of a repeated
- item.
+panel. Then invoke the repeat command, and you will be asked you to select a
+simple or advanced repetition. A simple repetition will lead you to a set of
+three questions with which you specify the basic repetition characteristics:
+
+ o type: choose between a daily, weekly, monthly or yearly base period
+
+ o frequency: choose the interval between base periods. '1' means every day
+ (week, month or year), '2' means every other day (week, ...).
+ For example, if you want to remember an anniversary, choose a
+ yearly type with a frequency of 1, which means it will be
+ repeated every year. Another example: if you go to a restaurant
+ every second day, choose a daily type with a frequency of 2.
+
+ o until date: specifies a day after which the repetitions do not occur. To
+ indicate an endless repetition, enter 0 (zero) or RETURN, and
+ the item will be repeated forever. To obtain a specific
+ number of repetitions (a repeat count) enter '#' followed by
+ a number (e.g. #10); it will be turned into the appropriate
+ until date.
+
+For an advanced repetition you may, in addition to the basic characteristics,
+specify three lists of either days of the week, months of the year or days of
+the month. The three lists modify the simple repetition in some way by either
+limiting or expanding the basic pattern.
+
+ o Weekdays: abbreviated names of days of the week (as they appear above
+ the calendar). For monthly or yearly repetitions the name may
+ have a numerical prefix (1, 2, ... or -1, -2, ...) to specify
+ a particular weekday of the month or year, counted from either
+ the start or the end of the month or year.
+
+ o Months: the numerical name of a month (1, 2,..., 12).
+
+ o Monthdays: the numerical name of a day of the month (1, 2,..., 31) or the
+ opposites (-1, -2,..., -31) which count from the end of the
+ month.
+
+For each list you may enter one or several values separated by spaces. The
+prompt for the list gives a hint as to the format. If you enter '?' only, you
+get very terse, context dependent information as to the effect on the
+repetition. Note that both format and effect depend on the basic type. The
+combined effect on the basic type of the listed days and months is derived
+from the iCalendar specification (RFC5545).
+
+Briefly, a weekday or monthday limits the repetitions of type daily, but
+expands those of type weekly, monthly and yearly. For example, with 'Weekdays'
+set to 'Sat Sun' a daily type (with frequency one) is only repeated on
+Saturdays and Sundays (two instead of seven repetitions per week), while a
+weekly type is also repeated on the extra day (two instead of one repetition
+per week).
+
+Similarly, a month limits the repetitions of type daily, weekly and monthly,
+but expands those of type yearly. For example, with 'Months' set to '3 10', a
+weekly type is only repeated in March and October, while a yearly type is also
+repeated in the extra month (two instead of one yearly repetition).
+
+Mnemonic. If the list type (day or month) is shorter than the basic type (day,
+week, month, year), it expands the repetitions of the basic type, if not, it
+limits them.
+
+There are a some important exceptions, though, for 'Weekdays':
+
+ o For a monthly type, the expanded repetitions are special: a weekday with a
+ prefix expands to that particular weekday of the month ('3Mon' = third
+ Monday), while a weekday without prefix expands to all weekdays of the
+ month ('Wed' = all Wednesdays). Furthermore, repetitions are limited if
+ 'Monthdays' is also set (for example, if 'Weekdays' is set to 'Fri' with
+ 'Monthdays' set to '13', the monthly repetition occurs only on Friday 13th).
+
+ o For a yearly type, the expanded repetitions are special and depend also on
+ the setting of 'Months'. A weekday with a prefix expands to that particular
+ weekday of the year ('-1Sun' = last Sunday of the year), or, if 'Months' is
+ also set, to that weekday of the listed months. A weekday without prefix
+ expands to all weekdays ('Thu' = all Thursdays in either the year or listed
+ months). Furthermore, repetitions are limited if 'Monthdays' is also set
+ as for monthly type.
+
+When you are finished setting up the repeating item, you may test it
+interactively with the 'next' command, a subcommand of the generic command
+(default ': n'). Invoked with a repeating item selected in the appointments
+panel, it will go to the next repetition. By doing this repeatedly, you may
+step through the repetitions one by one.
+
+If you edit an item that is already repeating, you will be led through all six
+characteristics and can modify any of them.
+
+Here are some typical examples. It is assumed that you have invoked the repeat
+command on what will become the first repetition and have selected an advanced
+repetition, that your date input format is dd/mm/yyyy, and that your language
+is English.
+
+ o an event that occurs every Tuesday and Thursday forever
+ type: weekly
+ frequency: 1
+ until: 0
+ weekdays: Tue Thu
+ months: (empty)
+ monthdays: (not possible)
+
+ o an event that occurs on workdays except in July forever (holidays are not
+ taken into account)
+ type: daily
+ frequency: 1
+ until: 0
+ weekdays: Mon Tue Wed Thu Fri
+ months: 1 2 3 4 5 6 8 9 10 11 12
+ monthdays: (empty)
+
+ o an appointment that occurs on the first and last Monday of the month forever
+ type: monthly
+ frequency: 1
+ until: 0
+ weekdays: 1Mon -1Mon
+ months: (empty)
+ monthdays: (empty)
+
+ o an appointment that occurs on all Wednesdays in June and July until the
+ end of June 2022
+ type: monthly
+ frequency: 1
+ until: 30/6/2022
+ weekdays: Wed
+ months: 6 7
+ monthdays: (empty)
+
+ o an event that occurs when Daylight Saving Time begins in the EU (last
+ Sunday in March)
+ type: yearly
+ frequency: 1
+ until: 0
+ weekdays: -1Sun
+ months: 3
+ monthdays: (empty)
+
+ o an event that occurs on the penultimate day of February forever
+ type: monthly
+ frequency: 1
+ until: 0
+ weekdays: (empty)
+ months: 2
+ monthdays: -2
+
+For an example that is not possible to specify consider an event that occurs
+on the last workday of each month.
diff --git a/doc/ru/credits.txt b/doc/ru/credits.txt
index b9ce181..e1f5ae7 100644
--- a/doc/ru/credits.txt
+++ b/doc/ru/credits.txt
@@ -1,7 +1,7 @@
Calcurse - text-based organizer
===============================
-Copyright (c) 2004-2017 calcurse Development Team
+Copyright (c) 2004-2023 calcurse Development Team
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/doc/submitting-patches.txt b/doc/submitting-patches.txt
index cec82ae..6514949 100644
--- a/doc/submitting-patches.txt
+++ b/doc/submitting-patches.txt
@@ -1,6 +1,6 @@
////
/*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/po/calcurse.pot b/po/calcurse.pot
index b0914ef..2fd17ea 100644
--- a/po/calcurse.pot
+++ b/po/calcurse.pot
@@ -1,14 +1,14 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR calcurse Development Team <misc@calcurse.org>
-# This file is distributed under the same license as the PACKAGE package.
+# This file is distributed under the same license as the calcurse package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
+"Project-Id-Version: calcurse 4.8.1-11-g9f7e\n"
"Report-Msgid-Bugs-To: bugs@calcurse.org\n"
-"POT-Creation-Date: 2019-06-16 15:27-0400\n"
+"POT-Creation-Date: 2024-01-26 18:28+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -21,6 +21,12 @@ msgstr ""
msgid "null pointer"
msgstr ""
+msgid "illegal date in appointment"
+msgstr ""
+
+msgid "error in appointment description"
+msgstr ""
+
msgid "date error in appointment"
msgstr ""
@@ -33,7 +39,7 @@ msgid ""
"calcurse -Q [--from <date>] [--to <date>] [--days <number>]\n"
"calcurse -a | -d <date> | -d <number> | -n | -r[<number>] | -s[<date>] | -"
"t[<number>]\n"
-"calcurse -h | -v | --status | -G | -P | -g | -i <file> | -x[<file>] | --"
+"calcurse -h | -v | --status | -G | -P | -g | -i <file> | -x[<format>] | --"
"daemon"
msgstr ""
@@ -44,7 +50,7 @@ msgstr ""
msgid "calcurse %s -- text-based organizer\n"
msgstr ""
-msgid "Copyright (c) 2004-2017 calcurse Development Team."
+msgid "Copyright (c) 2004-2023 calcurse Development Team."
msgstr ""
msgid "This is free software; see the source for copying conditions."
@@ -119,7 +125,7 @@ msgstr ""
msgid " -i, --import <file> Import iCal data from file"
msgstr ""
-msgid " -q, --quiet Suppress system dialogs"
+msgid " -q, --quiet Suppress import/export result message"
msgstr ""
msgid " --read-only Do not save configuration or data files"
@@ -269,7 +275,7 @@ msgstr ""
msgid "Do you really want to quit?"
msgstr ""
-msgid "Command: [ h(elp) | w(rite)(!) | q(uit)(!) | wq(!) ]"
+msgid "Command: [ h(elp) | w(rite)(!) | q(uit)(!) | wq(!) | n(ext) | p(rev) ]"
msgstr ""
msgid "Read-only mode - use w!"
@@ -282,6 +288,18 @@ msgstr ""
msgid "Help topic does not exist: %s"
msgstr ""
+msgid "Select a repeating item in the appointments panel."
+msgstr ""
+
+msgid "Not a repeating item."
+msgstr ""
+
+msgid "Last occurrence."
+msgstr ""
+
+msgid "First occurrence."
+msgstr ""
+
#, c-format
msgid "No such command: %s"
msgstr ""
@@ -377,6 +395,9 @@ msgstr ""
msgid "(insert an empty line after each appointment)"
msgstr ""
+msgid "(text for a day without events and appointments)"
+msgstr ""
+
msgid "(display more than one day in the appointments panel)"
msgstr ""
@@ -398,15 +419,6 @@ msgstr ""
msgid "(if set to YES, confirmation is required before deleting an event)"
msgstr ""
-msgid "(if set to YES, messages about loaded and saved data will be displayed)"
-msgstr ""
-
-msgid "Monday"
-msgstr ""
-
-msgid "Sunday"
-msgstr ""
-
msgid "(specifies the first day of week in the calendar view)"
msgstr ""
@@ -431,9 +443,18 @@ msgstr ""
msgid "(Format of the date displayed in the appointments panel)"
msgstr ""
+msgid "(Format of the time displayed in the appointments panel)"
+msgstr ""
+
+msgid "Enter a text string (an empty string for the default text)"
+msgstr ""
+
msgid "Enter the date format (see 'man 3 strftime' for possible formats) "
msgstr ""
+msgid "Enter the time format (see 'man 3 strftime' for possible formats) "
+msgstr ""
+
msgid "Enter the date format: "
msgstr ""
@@ -446,7 +467,7 @@ msgstr ""
msgid "Undefined option!"
msgstr ""
-msgid "undefined"
+msgid "UNDEFINED"
msgstr ""
msgid "keys configuration"
@@ -459,7 +480,7 @@ msgstr ""
msgid "The key '%s' is already used for %s. Choose another one."
msgstr ""
-msgid "Some actions do not have any associated key bindings!"
+msgid "Some actions are left undefined!"
msgstr ""
msgid ""
@@ -474,7 +495,7 @@ msgstr ""
msgid "unknown item type"
msgstr ""
-msgid "(none)"
+msgid "Note:"
msgstr ""
msgid "Event:"
@@ -545,10 +566,10 @@ msgstr ""
msgid "Could not stop calcurse daemon: %s\n"
msgstr ""
-msgid "date error in event"
+msgid "illegal date in event"
msgstr ""
-msgid "date error in the event\n"
+msgid "date error in event\n"
msgstr ""
msgid "Internal error: line too long"
@@ -560,54 +581,137 @@ msgstr ""
msgid "unknown ical type"
msgstr ""
-msgid "recurrence rule malformed."
+msgid "(empty)"
msgstr ""
-msgid "recurrence frequency not found."
+msgid "ical_store_event: out of memory"
msgstr ""
-msgid "recurrence frequency not recognized."
+msgid "need DTSTART to determine event type."
msgstr ""
-msgid "recurrence exception dates malformed."
+msgid "malformed recurrence line."
msgstr ""
-msgid "description malformed."
+msgid "frequency not set in rrule."
msgstr ""
-msgid "could not get entire item description."
+msgid "frequency absent in rrule."
msgstr ""
-msgid "could not retrieve item summary."
+msgid "rrule frequency not supported."
msgstr ""
-msgid "item start date is not defined."
+msgid "invalid interval."
msgstr ""
-msgid "item has a negative duration."
+msgid "either until or count."
msgstr ""
-msgid "item could not be identified."
+msgid "missing until value."
+msgstr ""
+
+msgid "invalid until format."
+msgstr ""
+
+msgid "invalid count value."
+msgstr ""
+
+msgid "invalid bymonth list."
+msgstr ""
+
+msgid "invalid bymonthday list."
+msgstr ""
+
+msgid "invalid byday list."
+msgstr ""
+
+msgid "invalid exception date value type."
+msgstr ""
+
+msgid "malformed exceptions line."
+msgstr ""
+
+msgid "invalid exception."
+msgstr ""
+
+#, c-format
+msgid "malformed %s line."
+msgstr ""
+
+#, c-format
+msgid "malformed %s."
msgstr ""
-msgid "event start time malformed."
+msgid "malformed summary line."
msgstr ""
-msgid "could not retrieve event start time."
+msgid "malformed summary."
msgstr ""
-msgid "event end time malformed."
+msgid "item start date not defined."
msgstr ""
-msgid "could not retrieve event end time."
+msgid "malformed start time line."
msgstr ""
-msgid "item duration malformed."
+msgid "invalid or malformed event start time."
+msgstr ""
+
+msgid "invalid end time value type."
+msgstr ""
+
+msgid "malformed end time line."
+msgstr ""
+
+msgid "malformed event end time."
+msgstr ""
+
+msgid "end must be later than start."
+msgstr ""
+
+msgid "either end or duration."
+msgstr ""
+
+msgid "malformed duration line."
+msgstr ""
+
+msgid "invalid duration."
+msgstr ""
+
+msgid "exception date, but no recurrence rule."
+msgstr ""
+
+msgid "multi-day event changed to one-day event"
+msgstr ""
+
+#, c-format
+msgid "Location: %s"
+msgstr ""
+
+#, c-format
+msgid "Comment: %s"
+msgstr ""
+
+#, c-format
+msgid "rrule does not match start day (%s)."
+msgstr ""
+
+msgid "item could not be identified."
+msgstr ""
+
+msgid "only one description allowed."
+msgstr ""
+
+msgid "only one location allowed."
msgstr ""
msgid "The ical file seems to be malformed. The end of item was not found."
msgstr ""
+msgid "could not retrieve item summary."
+msgstr ""
+
msgid "item priority is invalid (must be between 0 and 9)."
msgstr ""
@@ -678,6 +782,21 @@ msgstr ""
msgid "syntax error in item repetition"
msgstr ""
+msgid "syntax error in until date"
+msgstr ""
+
+msgid "until date error"
+msgstr ""
+
+msgid "BYMONTHDAY illegal with WEEKLY"
+msgstr ""
+
+msgid "missing end of recurrence"
+msgstr ""
+
+msgid "syntax error in item state"
+msgstr ""
+
msgid "failed to open todo file"
msgstr ""
@@ -687,49 +806,49 @@ msgstr ""
msgid "failed to open key file"
msgstr ""
-msgid ""
-"\n"
-"Too many errors while reading configuration file!\n"
-"Please backup your keys file, remove it from directory, and launch calcurse "
-"again.\n"
-msgstr ""
-
msgid "Could not read key label"
msgstr ""
-msgid "Key label not recognized"
+#, c-format
+msgid "Key label not recognized: \"%s\""
msgstr ""
#, c-format
-msgid "Error reading key: \"%s\""
+msgid "No keys assigned to \"%s\"."
msgstr ""
#, c-format
-msgid "\"%s\" assigned multiple times!"
+msgid "Keyname not recognized: \"%s\""
msgstr ""
-msgid "There were some errors when loading keys file."
+#, c-format
+msgid "\"%s\" assigned twice: \"%s\"."
msgstr ""
-msgid "Too many errors while reading keys file, aborting..."
+#, c-format
+msgid ""
+"Action \"%s\" absent, but default key \"%s\" assigned to another action."
msgstr ""
-#, c-format
-msgid "FATAL ERROR: could not create %s: %s\n"
+msgid "Errors in the keys file."
msgstr ""
-msgid "Press [ENTER] to continue"
+msgid "Remove offending line(s) from the keys file, aborting..."
msgstr ""
-msgid "Welcome to Calcurse. Missing data files were created."
+msgid "Some actions do not have any associated key bindings!"
msgstr ""
-msgid "Data files found. Data will be loaded now."
+#, c-format
+msgid "FATAL ERROR: could not create %s: %s\n"
msgstr ""
msgid "The data were successfully exported"
msgstr ""
+msgid "Press [ENTER] to continue"
+msgstr ""
+
msgid "unknown export type"
msgstr ""
@@ -800,7 +919,9 @@ msgstr ""
msgid "Invalid delay"
msgstr ""
-msgid "Periodic save: data files have changed. Save cancelled."
+msgid ""
+"Periodic save cancelled. Data files have changed. Save and merge "
+"interactively"
msgstr ""
#, c-format
@@ -842,6 +963,9 @@ msgstr ""
msgid "Chg Win"
msgstr ""
+msgid "Prev Win"
+msgstr ""
+
msgid "Import"
msgstr ""
@@ -1020,6 +1144,9 @@ msgstr ""
msgid "Select next panel in calcurse main screen."
msgstr ""
+msgid "Select previous panel in calcurse main screen."
+msgstr ""
+
msgid "Import data from an external file."
msgstr ""
@@ -1140,7 +1267,7 @@ msgid "FATAL ERROR: null file pointer."
msgstr ""
#, c-format
-msgid "When adding default key for \"%s\", \"%s\" was already assigned!"
+msgid "Default key(s) assigned to %d action%s."
msgstr ""
msgid "xmalloc: zero size"
@@ -1233,12 +1360,6 @@ msgstr ""
msgid "Warning: could not open %s, Aborting..."
msgstr ""
-msgid "error while launching command: could not fork"
-msgstr ""
-
-msgid "error while launching command"
-msgstr ""
-
msgid "(if set to YES, notify-bar will be displayed)"
msgstr ""
@@ -1264,9 +1385,6 @@ msgstr ""
msgid "(Log activity when running in background)"
msgstr ""
-msgid "Enter the time format (see 'man 3 strftime' for possible formats) "
-msgstr ""
-
msgid "Enter the number of seconds (0 not to be warned before an appointment)"
msgstr ""
@@ -1282,10 +1400,26 @@ msgstr ""
msgid "System event"
msgstr ""
-msgid "unknown repetition type"
+msgid "unknown character"
msgstr ""
-msgid "unknown character"
+#, c-format
+msgid "recurrence error: not on start day (%s)"
+msgstr ""
+
+msgid "illegel date in event"
+msgstr ""
+
+msgid "date error in event"
+msgstr ""
+
+msgid "month day is zero"
+msgstr ""
+
+msgid "no daily frequency check"
+msgstr ""
+
+msgid "illegal BYDAY value"
msgstr ""
msgid "event not found"
@@ -1294,14 +1428,22 @@ msgstr ""
msgid "appointment not found"
msgstr ""
-msgid "syntax error in item date"
+msgid "syntax error in bymonthday"
msgstr ""
-msgid "date error in item exception"
+msgid "syntax error in bywday"
msgstr ""
-#, c-format
-msgid "Could not remove calcurse lock file: %s\n"
+msgid "syntax error in bymonth"
+msgstr ""
+
+msgid "illegal bymonth value"
+msgstr ""
+
+msgid "syntax error in item date"
+msgstr ""
+
+msgid "date error in item exception"
msgstr ""
#, c-format
@@ -1341,6 +1483,10 @@ msgstr ""
msgid "Invalid time: start time must come before end time!"
msgstr ""
+#, c-format
+msgid "Repetition must begin on start day (%s)."
+msgstr ""
+
msgid "Enter end date (and/or time) or duration ('?' for input formats):"
msgstr ""
@@ -1366,51 +1512,111 @@ msgstr ""
msgid "Invalid date format - try again:."
msgstr ""
-msgid "Enter the new repetition type:"
+msgid "Limit repetition to listed days."
msgstr ""
-msgid "(d)aily"
+msgid "Expand repetition to listed days."
msgstr ""
-msgid "(w)eekly"
+msgid "Expand repetition to listed days, either all or 1st, 2nd, ... of month."
msgstr ""
-msgid "(m)onthly"
+msgid "Note: limit to monthdays, if any."
msgstr ""
-msgid "(y)early"
+msgid "Expand repetition to listed days, either all or 1st, 2nd, ... of year."
+msgstr ""
+
+msgid "Note: expand to listed months, if any; limit to monthdays, if any."
+msgstr ""
+
+msgid "Limit repetition to listed months."
+msgstr ""
+
+msgid "Expand repetition to listed months."
+msgstr ""
+
+msgid "Limit repetition to listed days of month."
+msgstr ""
+
+msgid "Expand repetition to listed days of month."
+msgstr ""
+
+#, c-format
+msgid "Weekdays %s|..|%s, space-separated list, '?' for help:"
+msgstr ""
+
+#, c-format
+msgid ""
+"Weekdays [n]%s|..|[n]%s, space-separated list, n=1,-1,..,5,-5, '?' for help:"
msgstr ""
#, c-format
-msgid "(currently using %s)"
+msgid ""
+"Weekdays [n]%s|..|[n]%s, space-separated list, n=1,-1,..,53,-53, '?' for "
+"help:"
+msgstr ""
+
+msgid "Months 1|..|12, space-separated list, '?' for help:"
+msgstr ""
+
+msgid "Monthdays 1|..|31 or -1|..|-31, space-separated list, '?' for help:"
+msgstr ""
+
+msgid "Invalid format - try again."
+msgstr ""
+
+msgid "Press any key to continue."
+msgstr ""
+
+msgid "Base period:"
+msgstr ""
+
+msgid "day"
+msgstr ""
+
+msgid "week"
+msgstr ""
+
+msgid "month"
+msgstr ""
+
+msgid "year"
msgstr ""
msgid "[dwmy]"
msgstr ""
-msgid "Invalid frequency."
+msgid "Frequency:"
msgstr ""
-msgid "Enter the repetition frequency:"
+msgid "Invalid frequency."
msgstr ""
-msgid "Enter end date or duration ('?' for input formats):"
+msgid "Until date, increment or repeat count ('?' for input formats):"
msgstr ""
#, c-format
-msgid "Date: %s (year or month may be omitted). Endless duration: 0."
+msgid "Date: %s (year, month may be omitted, endless: 0)."
msgstr ""
-msgid "Duration in days: +dd. Duration in weeks and days: +??w??d."
+msgid "Increment: +?? (days) or: +??w??d (weeks). Repeat count: #?? (number)."
msgstr ""
#, c-format
-msgid "Invalid date: end date must come after start date (%s)."
+msgid "Invalid date: until date must come after start date (%s)."
msgstr ""
msgid "Invalid date."
msgstr ""
+msgid "Repeat count is too big."
+msgstr ""
+
+#, c-format
+msgid "Repetition must begin on start day (%s); any change discarded."
+msgstr ""
+
msgid "Description"
msgstr ""
@@ -1449,32 +1655,39 @@ msgstr ""
msgid "Invalid start time."
msgstr ""
-msgid "Do you really want to delete this item?"
+msgid ""
+"This item is recurrent and has a note attached to it. Delete (s)elected "
+"occurrence, (a)ll occurrences, or just its (n)ote?"
msgstr ""
-msgid "This item is recurrent. Delete (a)ll occurences or just this (o)ne?"
+msgid "[san]"
msgstr ""
-msgid "[ao]"
+msgid ""
+"This item has a note attached to it. Delete (s)elected occurrence or just "
+"its (n)ote?"
msgstr ""
-msgid "This item has a note attached to it. Delete (i)tem or just its (n)ote?"
+msgid "[sn]"
msgstr ""
-msgid "[in]"
+msgid ""
+"This item is recurrent. Delete (s)elected occurrence or (a)ll occurrences?"
msgstr ""
-msgid "Enter the repetition type:"
+msgid "[sa]"
msgstr ""
-#, c-format
-msgid "Date: %s (year or month may be omitted). Endless duration: '0'."
+msgid "Confirm deletion. Delete (s)elected occurrence? Press (s) to confirm."
msgstr ""
-msgid "This item is already a repeated one."
+msgid "[s]"
msgstr ""
-msgid "wrong item type"
+msgid "Already repeated."
+msgstr ""
+
+msgid "A (s)imple or (a)dvanced repetition?"
msgstr ""
msgid "Enter the new TODO item:"
@@ -1498,6 +1711,10 @@ msgstr ""
msgid "TODO:"
msgstr ""
+#, c-format
+msgid "Could not remove calcurse lock file: %s\n"
+msgstr ""
+
msgid "/!\\ INTERNAL ERROR /!\\"
msgstr ""
@@ -1556,7 +1773,7 @@ msgstr ""
msgid ""
"\n"
-"Copyright (c) 2004-2017 calcurse Development Team.\n"
+"Copyright (c) 2004-2023 calcurse Development Team.\n"
"This is free software; see the source for copying conditions.\n"
msgstr ""
diff --git a/po/de.po b/po/de.po
index 277f595..568ec93 100644
--- a/po/de.po
+++ b/po/de.po
@@ -1,21 +1,23 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR calcurse Development Team <misc@calcurse.org>
-# This file is distributed under the same license as the PACKAGE package.
+# This file is distributed under the same license as the calcurse package.
#
# Translators:
# delix, 2012
-# delix, 2012
+# 854c965733f966783769d2df566aaebe_fdcf60e, 2012
+# Lukas Fleischer, 2019
# Stefan Schroeder <ondekoza@gmail.com>, 2017
# Tim, 2013
-# Tim, 2013
+# Tim Summerer <summerer.tim@gmail.com>, 2019
+# 8eda48bac0dbbe266f569e2487f7fa50_208ec8f, 2013
msgid ""
msgstr ""
"Project-Id-Version: calcurse\n"
"Report-Msgid-Bugs-To: bugs@calcurse.org\n"
-"POT-Creation-Date: 2019-06-16 15:27-0400\n"
-"PO-Revision-Date: 2019-05-30 11:52+0000\n"
-"Last-Translator: Lukas Fleischer\n"
-"Language-Team: German (http://www.transifex.com/lfleischer/calcurse/language/"
+"POT-Creation-Date: 2024-01-26 18:28+0100\n"
+"PO-Revision-Date: 2013-07-23 08:43+0000\n"
+"Last-Translator: Tim Summerer <summerer.tim@gmail.com>, 2019\n"
+"Language-Team: German (http://app.transifex.com/lfleischer/calcurse/language/"
"de/)\n"
"Language: de\n"
"MIME-Version: 1.0\n"
@@ -26,6 +28,12 @@ msgstr ""
msgid "null pointer"
msgstr "Null-Zeiger"
+msgid "illegal date in appointment"
+msgstr ""
+
+msgid "error in appointment description"
+msgstr ""
+
msgid "date error in appointment"
msgstr "Datumsfehler im Termin"
@@ -38,7 +46,7 @@ msgid ""
"calcurse -Q [--from <date>] [--to <date>] [--days <number>]\n"
"calcurse -a | -d <date> | -d <number> | -n | -r[<number>] | -s[<date>] | -"
"t[<number>]\n"
-"calcurse -h | -v | --status | -G | -P | -g | -i <file> | -x[<file>] | --"
+"calcurse -h | -v | --status | -G | -P | -g | -i <file> | -x[<format>] | --"
"daemon"
msgstr ""
@@ -49,14 +57,14 @@ msgstr "Der Aufruf `calcurse -h` zeigt weitere Hilfen."
msgid "calcurse %s -- text-based organizer\n"
msgstr "calcurse %s -- Terminplaner im Textmodus\n"
-msgid "Copyright (c) 2004-2017 calcurse Development Team."
-msgstr "Copyright (c) 2004-2017 calcurse Entwickler-Team."
+msgid "Copyright (c) 2004-2023 calcurse Development Team."
+msgstr ""
msgid "This is free software; see the source for copying conditions."
msgstr "This is free software; see the source for copying conditions."
msgid "Operations in command line mode:"
-msgstr ""
+msgstr "Operationen im Befehlszeilenmodus:"
msgid " -Q, --query Print items in a given query range"
msgstr " -Q, --query Ausgabe bestimmter Werte gemäß Suche"
@@ -124,7 +132,7 @@ msgstr ""
msgid " -i, --import <file> Import iCal data from file"
msgstr ""
-msgid " -q, --quiet Suppress system dialogs"
+msgid " -q, --quiet Suppress import/export result message"
msgstr ""
msgid " --read-only Do not save configuration or data files"
@@ -277,7 +285,7 @@ msgstr ""
msgid "Do you really want to quit?"
msgstr "Möchten Sie das Programm wirklich beenden?"
-msgid "Command: [ h(elp) | w(rite)(!) | q(uit)(!) | wq(!) ]"
+msgid "Command: [ h(elp) | w(rite)(!) | q(uit)(!) | wq(!) | n(ext) | p(rev) ]"
msgstr ""
msgid "Read-only mode - use w!"
@@ -290,6 +298,18 @@ msgstr ""
msgid "Help topic does not exist: %s"
msgstr "Hilfethema existiert nicht: %s"
+msgid "Select a repeating item in the appointments panel."
+msgstr ""
+
+msgid "Not a repeating item."
+msgstr ""
+
+msgid "Last occurrence."
+msgstr ""
+
+msgid "First occurrence."
+msgstr ""
+
#, c-format
msgid "No such command: %s"
msgstr "Unbekannter Befehl: %s"
@@ -387,6 +407,9 @@ msgstr ""
msgid "(insert an empty line after each appointment)"
msgstr ""
+msgid "(text for a day without events and appointments)"
+msgstr ""
+
msgid "(display more than one day in the appointments panel)"
msgstr ""
@@ -410,17 +433,6 @@ msgstr ""
"(Ist JA gewählt, ist eine Bestätigung erforderlich, um ein Ereignis zu "
"löschen)"
-msgid "(if set to YES, messages about loaded and saved data will be displayed)"
-msgstr ""
-"(Ist JA gewählt, werden Nachrichten über geladene und gespeicherte Daten "
-"angezeigt)"
-
-msgid "Monday"
-msgstr "Montag"
-
-msgid "Sunday"
-msgstr "Sonntag"
-
msgid "(specifies the first day of week in the calendar view)"
msgstr "(lege den ersten Tag der Woche in der Kalenderansicht fest)"
@@ -445,9 +457,18 @@ msgstr "(Position des Titels in der Terminleiste)"
msgid "(Format of the date displayed in the appointments panel)"
msgstr "(Format des Datums in der Termin-Anzeige)"
+msgid "(Format of the time displayed in the appointments panel)"
+msgstr ""
+
+msgid "Enter a text string (an empty string for the default text)"
+msgstr ""
+
msgid "Enter the date format (see 'man 3 strftime' for possible formats) "
msgstr "Geben Sie das Datumsformat an (vgl. 'man 3 strftime')"
+msgid "Enter the time format (see 'man 3 strftime' for possible formats) "
+msgstr "Zeitformat eingeben (vgl. 'man 3 strftime')"
+
msgid "Enter the date format: "
msgstr "Datumsformat eingeben:"
@@ -462,8 +483,8 @@ msgstr "Allgemeine Einstellungen"
msgid "Undefined option!"
msgstr "Unbestimmte Einstellung!"
-msgid "undefined"
-msgstr "unbestimmt"
+msgid "UNDEFINED"
+msgstr ""
msgid "keys configuration"
msgstr "Tasteneinstellung"
@@ -475,8 +496,8 @@ msgstr "Taste drücken, die zugewiesen werden soll:"
msgid "The key '%s' is already used for %s. Choose another one."
msgstr "Die Taste '%s' wird schon von %s benutzt. Wählen Sie eine andere."
-msgid "Some actions do not have any associated key bindings!"
-msgstr "Einige Aktionen haben keine Tastenzuordnung!"
+msgid "Some actions are left undefined!"
+msgstr ""
msgid ""
"Sorry, colors are not supported by your terminal\n"
@@ -492,7 +513,7 @@ msgstr ""
msgid "unknown item type"
msgstr "Unbekannte Position"
-msgid "(none)"
+msgid "Note:"
msgstr ""
msgid "Event:"
@@ -563,11 +584,11 @@ msgstr "Aufgeweckt als %s\n"
msgid "Could not stop calcurse daemon: %s\n"
msgstr "Kann den calcurse-Dienst nicht beenden: %s\n"
-msgid "date error in event"
-msgstr "Datumsfehler im Ereignis"
+msgid "illegal date in event"
+msgstr ""
-msgid "date error in the event\n"
-msgstr "Fehlerhafte Zeit für das Ereignis\n"
+msgid "date error in event\n"
+msgstr ""
msgid "Internal error: line too long"
msgstr "INTERNER FEHLER: Die Zeile ist zu lang"
@@ -578,54 +599,137 @@ msgstr "Hauptspeicher reicht nicht aus"
msgid "unknown ical type"
msgstr "Unbekannter ICal-Typ"
-msgid "recurrence rule malformed."
-msgstr "Wiederholungstyp falsch."
+msgid "(empty)"
+msgstr ""
-msgid "recurrence frequency not found."
-msgstr "Wiederholung nicht gefunden."
+msgid "ical_store_event: out of memory"
+msgstr ""
-msgid "recurrence frequency not recognized."
-msgstr "Wiederholung nicht erkannt."
+msgid "need DTSTART to determine event type."
+msgstr ""
-msgid "recurrence exception dates malformed."
-msgstr "Ausnahmen des Wiederholungstyp falsch."
+msgid "malformed recurrence line."
+msgstr ""
-msgid "description malformed."
-msgstr "Beschreibung Fehlerhaft."
+msgid "frequency not set in rrule."
+msgstr ""
-msgid "could not get entire item description."
-msgstr "Kann nicht die ganze Beschreibung lesen."
+msgid "frequency absent in rrule."
+msgstr ""
-msgid "could not retrieve item summary."
-msgstr "Kann die Zusammenfassung des Eintrags nicht lesen."
+msgid "rrule frequency not supported."
+msgstr ""
-msgid "item start date is not defined."
-msgstr "Anfangsdatum des Eintrags fehlt."
+msgid "invalid interval."
+msgstr ""
-msgid "item has a negative duration."
-msgstr "Eintrag hat eine negative Dauer."
+msgid "either until or count."
+msgstr ""
-msgid "item could not be identified."
-msgstr "Element kann nicht erkannt werden."
+msgid "missing until value."
+msgstr ""
+
+msgid "invalid until format."
+msgstr ""
+
+msgid "invalid count value."
+msgstr ""
+
+msgid "invalid bymonth list."
+msgstr ""
+
+msgid "invalid bymonthday list."
+msgstr ""
-msgid "event start time malformed."
-msgstr "Startzeit des Ereignisses hat ein ungültiges Format."
+msgid "invalid byday list."
+msgstr ""
-msgid "could not retrieve event start time."
-msgstr "Kann die Startzeit des Ereignis nicht lesen."
+msgid "invalid exception date value type."
+msgstr ""
-msgid "event end time malformed."
-msgstr "Ereignis-Endzeit hat ein ungültiges Format."
+msgid "malformed exceptions line."
+msgstr ""
-msgid "could not retrieve event end time."
-msgstr "Kann die Endzeit des Ereignis nicht lesen."
+msgid "invalid exception."
+msgstr ""
-msgid "item duration malformed."
-msgstr "Dauer des Eintrags fehlerhaft."
+#, c-format
+msgid "malformed %s line."
+msgstr ""
+
+#, c-format
+msgid "malformed %s."
+msgstr ""
+
+msgid "malformed summary line."
+msgstr ""
+
+msgid "malformed summary."
+msgstr ""
+
+msgid "item start date not defined."
+msgstr ""
+
+msgid "malformed start time line."
+msgstr ""
+
+msgid "invalid or malformed event start time."
+msgstr ""
+
+msgid "invalid end time value type."
+msgstr ""
+
+msgid "malformed end time line."
+msgstr ""
+
+msgid "malformed event end time."
+msgstr ""
+
+msgid "end must be later than start."
+msgstr ""
+
+msgid "either end or duration."
+msgstr ""
+
+msgid "malformed duration line."
+msgstr ""
+
+msgid "invalid duration."
+msgstr ""
+
+msgid "exception date, but no recurrence rule."
+msgstr ""
+
+msgid "multi-day event changed to one-day event"
+msgstr ""
+
+#, c-format
+msgid "Location: %s"
+msgstr ""
+
+#, c-format
+msgid "Comment: %s"
+msgstr ""
+
+#, c-format
+msgid "rrule does not match start day (%s)."
+msgstr ""
+
+msgid "item could not be identified."
+msgstr "Element kann nicht erkannt werden."
+
+msgid "only one description allowed."
+msgstr ""
+
+msgid "only one location allowed."
+msgstr ""
msgid "The ical file seems to be malformed. The end of item was not found."
msgstr "Die ICal Datei ist fehlerhaft. Keine Enddatum des Eintrags gefunden."
+msgid "could not retrieve item summary."
+msgstr "Kann die Zusammenfassung des Eintrags nicht lesen."
+
msgid "item priority is invalid (must be between 0 and 9)."
msgstr "Priorität des Eintrags ist ungültig (gültig sind 0 bis 9)"
@@ -698,6 +802,21 @@ msgstr "Falsches Format für den Termin oder das Ereignis"
msgid "syntax error in item repetition"
msgstr "Syntaxfehler in Item-Wiederholung"
+msgid "syntax error in until date"
+msgstr ""
+
+msgid "until date error"
+msgstr ""
+
+msgid "BYMONTHDAY illegal with WEEKLY"
+msgstr ""
+
+msgid "missing end of recurrence"
+msgstr ""
+
+msgid "syntax error in item state"
+msgstr ""
+
msgid "failed to open todo file"
msgstr "konnte Aufgaben-Datei nicht öffnen"
@@ -707,53 +826,49 @@ msgstr ""
msgid "failed to open key file"
msgstr "Konnte Tastenkonfigurationsdatei nicht öffnen"
-msgid ""
-"\n"
-"Too many errors while reading configuration file!\n"
-"Please backup your keys file, remove it from directory, and launch calcurse "
-"again.\n"
-msgstr ""
-"\n"
-"Zu viele Fehler beim Lesen der Konfigurationsdatei!\n"
-"Bitte die Einstellungsdatei der Tastaturkürzel sichern, diese aus dem\n"
-"Verzeichnis löschen und calcurse neu starten.\n"
-
msgid "Could not read key label"
msgstr "Tastenbezeichnung nicht lesbar"
-msgid "Key label not recognized"
-msgstr "Tastenbezeichnung nicht erkannt"
-
#, c-format
-msgid "Error reading key: \"%s\""
-msgstr "Fehler beim Lesen der Taste \"%s\""
+msgid "Key label not recognized: \"%s\""
+msgstr ""
#, c-format
-msgid "\"%s\" assigned multiple times!"
-msgstr "\"%s\" ist mehrfach zugeordnet!"
+msgid "No keys assigned to \"%s\"."
+msgstr ""
-msgid "There were some errors when loading keys file."
+#, c-format
+msgid "Keyname not recognized: \"%s\""
msgstr ""
-msgid "Too many errors while reading keys file, aborting..."
-msgstr "Zu viele Fehler beim Lesen der 'keys'-Datei, Abbruch..."
+#, c-format
+msgid "\"%s\" assigned twice: \"%s\"."
+msgstr ""
#, c-format
-msgid "FATAL ERROR: could not create %s: %s\n"
-msgstr "SCHWERER FEHLER Konnte %s nicht erstellen: %s\n"
+msgid ""
+"Action \"%s\" absent, but default key \"%s\" assigned to another action."
+msgstr ""
-msgid "Press [ENTER] to continue"
-msgstr "[EINGABE]-Taste um fortzufahren"
+msgid "Errors in the keys file."
+msgstr ""
-msgid "Welcome to Calcurse. Missing data files were created."
-msgstr "Willkommen zu calcurse. Fehlende Dateien werden erzeugt."
+msgid "Remove offending line(s) from the keys file, aborting..."
+msgstr ""
-msgid "Data files found. Data will be loaded now."
-msgstr "Benutzerdaten gefunden. Daten werden geladen."
+msgid "Some actions do not have any associated key bindings!"
+msgstr "Einige Aktionen haben keine Tastenzuordnung!"
+
+#, c-format
+msgid "FATAL ERROR: could not create %s: %s\n"
+msgstr "SCHWERER FEHLER Konnte %s nicht erstellen: %s\n"
msgid "The data were successfully exported"
msgstr "Die Daten wurden erfolgreich exportiert"
+msgid "Press [ENTER] to continue"
+msgstr "[EINGABE]-Taste um fortzufahren"
+
msgid "unknown export type"
msgstr "Unbekanntes Exportformat"
@@ -824,7 +939,9 @@ msgstr "WARNUNG Kann temporäre Logdatei %s nicht löschen. Abbruch..."
msgid "Invalid delay"
msgstr "Ungültige Verzögerung"
-msgid "Periodic save: data files have changed. Save cancelled."
+msgid ""
+"Periodic save cancelled. Data files have changed. Save and merge "
+"interactively"
msgstr ""
#, c-format
@@ -871,6 +988,9 @@ msgstr "Einfügen"
msgid "Chg Win"
msgstr "Wechseln"
+msgid "Prev Win"
+msgstr ""
+
msgid "Import"
msgstr "Importieren"
@@ -1058,6 +1178,9 @@ msgstr "Item an aktueller Position einfügen."
msgid "Select next panel in calcurse main screen."
msgstr "Wähle nächstes Fenster im calcurse-Hauptbildschirm."
+msgid "Select previous panel in calcurse main screen."
+msgstr ""
+
msgid "Import data from an external file."
msgstr "Importiere Daten von einer externen Datei."
@@ -1190,9 +1313,8 @@ msgid "FATAL ERROR: null file pointer."
msgstr "SCHWERER FEHLER: Null-Datei-Zeiger."
#, c-format
-msgid "When adding default key for \"%s\", \"%s\" was already assigned!"
+msgid "Default key(s) assigned to %d action%s."
msgstr ""
-"Beim Hinzufügen einer Default-Taste für \"%s\" war \"%s\" bereits zugewiesen!"
msgid "xmalloc: zero size"
msgstr "xmalloc: Länge 0"
@@ -1284,12 +1406,6 @@ msgstr " belegte Blöcke: %u\n"
msgid "Warning: could not open %s, Aborting..."
msgstr "WARNUNG: Kann %s nicht öffnen. Abbruch..."
-msgid "error while launching command: could not fork"
-msgstr "Fehler beim Ausführen einer Befehlszeile: Kann nicht Ausführen"
-
-msgid "error while launching command"
-msgstr "Fehler beim Ausführen einer Befehlszeile"
-
msgid "(if set to YES, notify-bar will be displayed)"
msgstr "(Ist JA gewählt, wird die Benachrichtigungszeile angezeigt)"
@@ -1316,9 +1432,6 @@ msgstr ""
msgid "(Log activity when running in background)"
msgstr "(Aufzeichnen von Aktivitäten, wenn im Hintergrund ausgeführt)"
-msgid "Enter the time format (see 'man 3 strftime' for possible formats) "
-msgstr "Zeitformat eingeben (vgl. 'man 3 strftime')"
-
msgid "Enter the number of seconds (0 not to be warned before an appointment)"
msgstr "Geben Sie die Zeit in Sekunden ein (0 um keine Hinweis zu erhalten)."
@@ -1334,18 +1447,46 @@ msgstr "Unzusammenhängende Wiederholung"
msgid "System event"
msgstr ""
-msgid "unknown repetition type"
-msgstr "Unbekannter Wiederholungstyp"
-
msgid "unknown character"
msgstr "Unbekanntes Zeichen"
+#, c-format
+msgid "recurrence error: not on start day (%s)"
+msgstr ""
+
+msgid "illegel date in event"
+msgstr ""
+
+msgid "date error in event"
+msgstr "Datumsfehler im Ereignis"
+
+msgid "month day is zero"
+msgstr ""
+
+msgid "no daily frequency check"
+msgstr ""
+
+msgid "illegal BYDAY value"
+msgstr ""
+
msgid "event not found"
msgstr "Ereignis nicht gefunden"
msgid "appointment not found"
msgstr "Termin nicht gefunden"
+msgid "syntax error in bymonthday"
+msgstr ""
+
+msgid "syntax error in bywday"
+msgstr ""
+
+msgid "syntax error in bymonth"
+msgstr ""
+
+msgid "illegal bymonth value"
+msgstr ""
+
msgid "syntax error in item date"
msgstr "Eingabefehler im Datum"
@@ -1353,10 +1494,6 @@ msgid "date error in item exception"
msgstr "Abbruch wegen Datumsfehler"
#, c-format
-msgid "Could not remove calcurse lock file: %s\n"
-msgstr "Kann die Sperrdatei nicht löschen: %s\n"
-
-#, c-format
msgid "Error setting signal #%d : %s\n"
msgstr "Fehler bei Signal: #%d : %s\n"
@@ -1393,6 +1530,10 @@ msgstr ""
msgid "Invalid time: start time must come before end time!"
msgstr ""
+#, c-format
+msgid "Repetition must begin on start day (%s)."
+msgstr ""
+
msgid "Enter end date (and/or time) or duration ('?' for input formats):"
msgstr ""
@@ -1418,51 +1559,111 @@ msgstr ""
msgid "Invalid date format - try again:."
msgstr ""
-msgid "Enter the new repetition type:"
-msgstr "Neuen Wiederholungstyp eingeben:"
+msgid "Limit repetition to listed days."
+msgstr ""
+
+msgid "Expand repetition to listed days."
+msgstr ""
+
+msgid "Expand repetition to listed days, either all or 1st, 2nd, ... of month."
+msgstr ""
-msgid "(d)aily"
-msgstr "(t)äglich"
+msgid "Note: limit to monthdays, if any."
+msgstr ""
-msgid "(w)eekly"
-msgstr "(w)öchentlich"
+msgid "Expand repetition to listed days, either all or 1st, 2nd, ... of year."
+msgstr ""
-msgid "(m)onthly"
-msgstr "(m)onatlich"
+msgid "Note: expand to listed months, if any; limit to monthdays, if any."
+msgstr ""
-msgid "(y)early"
-msgstr "(j)ährlich"
+msgid "Limit repetition to listed months."
+msgstr ""
+
+msgid "Expand repetition to listed months."
+msgstr ""
+
+msgid "Limit repetition to listed days of month."
+msgstr ""
+
+msgid "Expand repetition to listed days of month."
+msgstr ""
+
+#, c-format
+msgid "Weekdays %s|..|%s, space-separated list, '?' for help:"
+msgstr ""
#, c-format
-msgid "(currently using %s)"
-msgstr "(verwende momentan %s)"
+msgid ""
+"Weekdays [n]%s|..|[n]%s, space-separated list, n=1,-1,..,5,-5, '?' for help:"
+msgstr ""
+
+#, c-format
+msgid ""
+"Weekdays [n]%s|..|[n]%s, space-separated list, n=1,-1,..,53,-53, '?' for "
+"help:"
+msgstr ""
+
+msgid "Months 1|..|12, space-separated list, '?' for help:"
+msgstr ""
+
+msgid "Monthdays 1|..|31 or -1|..|-31, space-separated list, '?' for help:"
+msgstr ""
+
+msgid "Invalid format - try again."
+msgstr ""
+
+msgid "Press any key to continue."
+msgstr ""
+
+msgid "Base period:"
+msgstr ""
+
+msgid "day"
+msgstr ""
+
+msgid "week"
+msgstr ""
+
+msgid "month"
+msgstr ""
+
+msgid "year"
+msgstr ""
msgid "[dwmy]"
msgstr "[twmj]"
+msgid "Frequency:"
+msgstr ""
+
msgid "Invalid frequency."
msgstr "Ungültige Wiederholungsrate."
-msgid "Enter the repetition frequency:"
-msgstr "Eingabe der Wiederholungsrate:"
-
-msgid "Enter end date or duration ('?' for input formats):"
+msgid "Until date, increment or repeat count ('?' for input formats):"
msgstr ""
#, c-format
-msgid "Date: %s (year or month may be omitted). Endless duration: 0."
+msgid "Date: %s (year, month may be omitted, endless: 0)."
msgstr ""
-msgid "Duration in days: +dd. Duration in weeks and days: +??w??d."
+msgid "Increment: +?? (days) or: +??w??d (weeks). Repeat count: #?? (number)."
msgstr ""
#, c-format
-msgid "Invalid date: end date must come after start date (%s)."
+msgid "Invalid date: until date must come after start date (%s)."
msgstr ""
msgid "Invalid date."
msgstr ""
+msgid "Repeat count is too big."
+msgstr ""
+
+#, c-format
+msgid "Repetition must begin on start day (%s); any change discarded."
+msgstr ""
+
msgid "Description"
msgstr "Beschreibung"
@@ -1503,34 +1704,40 @@ msgstr ""
msgid "Invalid start time."
msgstr ""
-msgid "Do you really want to delete this item?"
-msgstr "Möchten Sie diesen Eintrag wirklich löschen?"
+msgid ""
+"This item is recurrent and has a note attached to it. Delete (s)elected "
+"occurrence, (a)ll occurrences, or just its (n)ote?"
+msgstr ""
+
+msgid "[san]"
+msgstr ""
-msgid "This item is recurrent. Delete (a)ll occurences or just this (o)ne?"
-msgstr "Dieser Eintrag ist wiederkehrend. Lösche (a)lle oder nur einen (o)?"
+msgid ""
+"This item has a note attached to it. Delete (s)elected occurrence or just "
+"its (n)ote?"
+msgstr ""
-msgid "[ao]"
-msgstr "[ae]"
+msgid "[sn]"
+msgstr ""
-msgid "This item has a note attached to it. Delete (i)tem or just its (n)ote?"
+msgid ""
+"This item is recurrent. Delete (s)elected occurrence or (a)ll occurrences?"
msgstr ""
-"An diesem Eintrag ist eine Notiz. E(i)ntrag löschen oder nur die (n)otiz?"
-msgid "[in]"
-msgstr "[in]"
+msgid "[sa]"
+msgstr ""
-msgid "Enter the repetition type:"
-msgstr "Wiederholungstyp eingeben:"
+msgid "Confirm deletion. Delete (s)elected occurrence? Press (s) to confirm."
+msgstr ""
-#, c-format
-msgid "Date: %s (year or month may be omitted). Endless duration: '0'."
+msgid "[s]"
msgstr ""
-msgid "This item is already a repeated one."
-msgstr "Es handelt sich bereits um einen wiederkehrenden Eintrag."
+msgid "Already repeated."
+msgstr ""
-msgid "wrong item type"
-msgstr "Falscher Typ des Eintrags"
+msgid "A (s)imple or (a)dvanced repetition?"
+msgstr ""
msgid "Enter the new TODO item:"
msgstr "Neue Aufgabe eingeben: "
@@ -1554,6 +1761,10 @@ msgstr "Beschreibung der neuen Aufgabe:"
msgid "TODO:"
msgstr "Zu erledigen:"
+#, c-format
+msgid "Could not remove calcurse lock file: %s\n"
+msgstr "Kann die Sperrdatei nicht löschen: %s\n"
+
msgid "/!\\ INTERNAL ERROR /!\\"
msgstr "INTERNER FEHLER"
@@ -1612,13 +1823,9 @@ msgstr "Verwendung: calcurse-upgrade [-h|-v|--config <file>]"
msgid ""
"\n"
-"Copyright (c) 2004-2017 calcurse Development Team.\n"
+"Copyright (c) 2004-2023 calcurse Development Team.\n"
"This is free software; see the source for copying conditions.\n"
msgstr ""
-"\n"
-"Copyright (c) 2004-2017 calcurse Entwickler-Team.\n"
-"Calcurse ist freie Software; die Lizenzbedingungen sind in den Quelltexten "
-"vermerkt.\n"
msgid "unrecognized option:"
msgstr "unbekannte Option:"
diff --git a/po/doc/add-nb_NO.po b/po/doc/add-nb_NO.po
index c981c8b..19838eb 100644
--- a/po/doc/add-nb_NO.po
+++ b/po/doc/add-nb_NO.po
@@ -1,13 +1,13 @@
#
# Translators:
-# Alexander F Rødseth <rodseth@gmail.com>, 2013
+# Alexander F. Rødseth <rodseth@gmail.com>, 2013
msgid ""
msgstr ""
"Project-Id-Version: calcurse\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-02-22 10:27+0200\n"
"PO-Revision-Date: 2017-09-19 19:05+0000\n"
-"Last-Translator: Alexander F Rødseth <rodseth@gmail.com>\n"
+"Last-Translator: Alexander F. Rødseth <rodseth@gmail.com>\n"
"Language-Team: Norwegian Bokmål (Norway) (http://www.transifex.com/lfleischer/calcurse/language/nb_NO/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
diff --git a/po/doc/copy-paste-nb_NO.po b/po/doc/copy-paste-nb_NO.po
index c84f2ba..363ac2a 100644
--- a/po/doc/copy-paste-nb_NO.po
+++ b/po/doc/copy-paste-nb_NO.po
@@ -1,13 +1,13 @@
#
# Translators:
-# Alexander F Rødseth <rodseth@gmail.com>, 2017
+# Alexander F. Rødseth <rodseth@gmail.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: calcurse\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-02-22 10:27+0200\n"
"PO-Revision-Date: 2017-09-19 19:05+0000\n"
-"Last-Translator: Alexander F Rødseth <rodseth@gmail.com>\n"
+"Last-Translator: Alexander F. Rødseth <rodseth@gmail.com>\n"
"Language-Team: Norwegian Bokmål (Norway) (http://www.transifex.com/lfleischer/calcurse/language/nb_NO/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
diff --git a/po/doc/credits-nb_NO.po b/po/doc/credits-nb_NO.po
index 76ddeef..074595b 100644
--- a/po/doc/credits-nb_NO.po
+++ b/po/doc/credits-nb_NO.po
@@ -1,6 +1,6 @@
#
# Translators:
-# Alexander F Rødseth <rodseth@gmail.com>, 2017
+# Alexander F. Rødseth <rodseth@gmail.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: calcurse\n"
diff --git a/po/doc/edit-nb_NO.po b/po/doc/edit-nb_NO.po
index 89fc52e..42d4951 100644
--- a/po/doc/edit-nb_NO.po
+++ b/po/doc/edit-nb_NO.po
@@ -1,13 +1,13 @@
#
# Translators:
-# Alexander F Rødseth <rodseth@gmail.com>, 2013
+# Alexander F. Rødseth <rodseth@gmail.com>, 2013
msgid ""
msgstr ""
"Project-Id-Version: calcurse\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-02-22 10:27+0200\n"
"PO-Revision-Date: 2017-09-19 19:05+0000\n"
-"Last-Translator: Alexander F Rødseth <rodseth@gmail.com>\n"
+"Last-Translator: Alexander F. Rødseth <rodseth@gmail.com>\n"
"Language-Team: Norwegian Bokmål (Norway) (http://www.transifex.com/lfleischer/calcurse/language/nb_NO/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
diff --git a/po/doc/export-nb_NO.po b/po/doc/export-nb_NO.po
index 4fcd275..80d78e9 100644
--- a/po/doc/export-nb_NO.po
+++ b/po/doc/export-nb_NO.po
@@ -1,13 +1,13 @@
#
# Translators:
-# Alexander F Rødseth <rodseth@gmail.com>, 2017
+# Alexander F. Rødseth <rodseth@gmail.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: calcurse\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-02-22 10:27+0200\n"
"PO-Revision-Date: 2017-09-19 19:05+0000\n"
-"Last-Translator: Alexander F Rødseth <rodseth@gmail.com>\n"
+"Last-Translator: Alexander F. Rødseth <rodseth@gmail.com>\n"
"Language-Team: Norwegian Bokmål (Norway) (http://www.transifex.com/lfleischer/calcurse/language/nb_NO/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
diff --git a/po/doc/flag-nb_NO.po b/po/doc/flag-nb_NO.po
index 60e4a19..bfd2673 100644
--- a/po/doc/flag-nb_NO.po
+++ b/po/doc/flag-nb_NO.po
@@ -1,13 +1,13 @@
#
# Translators:
-# Alexander F Rødseth <rodseth@gmail.com>, 2013
+# Alexander F. Rødseth <rodseth@gmail.com>, 2013
msgid ""
msgstr ""
"Project-Id-Version: calcurse\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-02-22 10:27+0200\n"
"PO-Revision-Date: 2017-09-19 19:05+0000\n"
-"Last-Translator: Alexander F Rødseth <rodseth@gmail.com>\n"
+"Last-Translator: Alexander F. Rødseth <rodseth@gmail.com>\n"
"Language-Team: Norwegian Bokmål (Norway) (http://www.transifex.com/lfleischer/calcurse/language/nb_NO/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
diff --git a/po/doc/save-nb_NO.po b/po/doc/save-nb_NO.po
index 0b35dc9..9f5a111 100644
--- a/po/doc/save-nb_NO.po
+++ b/po/doc/save-nb_NO.po
@@ -1,13 +1,13 @@
#
# Translators:
-# Alexander F Rødseth <rodseth@gmail.com>, 2017
+# Alexander F. Rødseth <rodseth@gmail.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: calcurse\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-02-22 10:27+0200\n"
"PO-Revision-Date: 2017-09-19 19:05+0000\n"
-"Last-Translator: Alexander F Rødseth <rodseth@gmail.com>\n"
+"Last-Translator: Alexander F. Rødseth <rodseth@gmail.com>\n"
"Language-Team: Norwegian Bokmål (Norway) (http://www.transifex.com/lfleischer/calcurse/language/nb_NO/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
diff --git a/po/doc/tab-nb_NO.po b/po/doc/tab-nb_NO.po
index 386f0bc..6b2a512 100644
--- a/po/doc/tab-nb_NO.po
+++ b/po/doc/tab-nb_NO.po
@@ -1,13 +1,13 @@
#
# Translators:
-# Alexander F Rødseth <rodseth@gmail.com>, 2017
+# Alexander F. Rødseth <rodseth@gmail.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: calcurse\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-02-22 10:27+0200\n"
"PO-Revision-Date: 2017-09-19 19:05+0000\n"
-"Last-Translator: Alexander F Rødseth <rodseth@gmail.com>\n"
+"Last-Translator: Alexander F. Rødseth <rodseth@gmail.com>\n"
"Language-Team: Norwegian Bokmål (Norway) (http://www.transifex.com/lfleischer/calcurse/language/nb_NO/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
diff --git a/po/doc/vnote-nb_NO.po b/po/doc/vnote-nb_NO.po
index c008471..16876ba 100644
--- a/po/doc/vnote-nb_NO.po
+++ b/po/doc/vnote-nb_NO.po
@@ -1,13 +1,13 @@
#
# Translators:
-# Alexander F Rødseth <rodseth@gmail.com>, 2013
+# Alexander F. Rødseth <rodseth@gmail.com>, 2013
msgid ""
msgstr ""
"Project-Id-Version: calcurse\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-02-22 10:27+0200\n"
"PO-Revision-Date: 2017-09-19 19:05+0000\n"
-"Last-Translator: Alexander F Rødseth <rodseth@gmail.com>\n"
+"Last-Translator: Alexander F. Rødseth <rodseth@gmail.com>\n"
"Language-Team: Norwegian Bokmål (Norway) (http://www.transifex.com/lfleischer/calcurse/language/nb_NO/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
diff --git a/po/en.po b/po/en.po
index 1417da6..4e15252 100644
--- a/po/en.po
+++ b/po/en.po
@@ -1,15 +1,13 @@
-# English/GB translation of calcurse.
-# Copyright (C) 2006 Copyright (c) Frederic Culot <frederic@culot.org>
+# English/GB translation of calcurse
+# Copyright (C) 2021 calcurse Development Team <misc@calcurse.org>
# This file is distributed under the same license as the calcurse package.
# Neil Williams <linux@codehelp.co.uk>, 2006.
-# , fuzzy
-#
#
msgid ""
msgstr ""
-"Project-Id-Version: calcurse 1.4\n"
+"Project-Id-Version: calcurse\n"
"Report-Msgid-Bugs-To: bugs@calcurse.org\n"
-"POT-Creation-Date: 2019-06-16 15:27-0400\n"
+"POT-Creation-Date: 2024-01-26 18:28+0100\n"
"PO-Revision-Date: 2006-07-03 00:05+0100\n"
"Last-Translator: Neil Williams <linux@codehelp.co.uk>\n"
"Language-Team: English/GB <en_GB@li.org>\n"
@@ -17,17 +15,22 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgid "null pointer"
msgstr ""
-#, fuzzy
+msgid "illegal date in appointment"
+msgstr ""
+
+msgid "error in appointment description"
+msgstr ""
+
msgid "date error in appointment"
-msgstr "Appointment :"
+msgstr ""
-#, fuzzy
msgid "no such appointment"
-msgstr "Appointment :"
+msgstr ""
msgid ""
"Usage:\n"
@@ -35,35 +38,25 @@ msgid ""
"calcurse -Q [--from <date>] [--to <date>] [--days <number>]\n"
"calcurse -a | -d <date> | -d <number> | -n | -r[<number>] | -s[<date>] | -"
"t[<number>]\n"
-"calcurse -h | -v | --status | -G | -P | -g | -i <file> | -x[<file>] | --"
+"calcurse -h | -v | --status | -G | -P | -g | -i <file> | -x[<format>] | --"
"daemon"
msgstr ""
-#, fuzzy
msgid "Try `calcurse -h` for more information."
-msgstr "Try 'calcurse -h' for more information.\n"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "calcurse %s -- text-based organizer\n"
-msgstr "Calcurse %s - text-based organizer\n"
+msgstr ""
-#, fuzzy
-msgid "Copyright (c) 2004-2017 calcurse Development Team."
+msgid "Copyright (c) 2004-2023 calcurse Development Team."
msgstr ""
-"\n"
-"Copyright (c) 2004-2006 Frederic Culot.\n"
-"This is free software; see the source for copying conditions.\n"
-#, fuzzy
msgid "This is free software; see the source for copying conditions."
msgstr ""
-"\n"
-"Copyright (c) 2004-2006 Frederic Culot.\n"
-"This is free software; see the source for copying conditions.\n"
-#, fuzzy
msgid "Operations in command line mode:"
-msgstr "starting interactive mode...\n"
+msgstr ""
msgid " -Q, --query Print items in a given query range"
msgstr ""
@@ -131,7 +124,7 @@ msgstr ""
msgid " -i, --import <file> Import iCal data from file"
msgstr ""
-msgid " -q, --quiet Suppress system dialogs"
+msgid " -q, --quiet Suppress import/export result message"
msgstr ""
msgid " --read-only Do not save configuration or data files"
@@ -147,20 +140,15 @@ msgid ""
" -x, --export[<format>] Export to stdout in ical (default) or pcal format"
msgstr ""
-#, fuzzy
msgid ""
"For more information, type '?' from within calcurse, or read the manpage."
msgstr ""
-"\n"
-"For more information, type '?' from within Calcurse, or read the manpage.\n"
-#, fuzzy
msgid "Submit feature requests and suggestions to <misc@calcurse.org>."
-msgstr "Mail bug reports and suggestions to <misc@calcurse.org>.\n"
+msgstr ""
-#, fuzzy
msgid "Submit bug reports to <bugs@calcurse.org>."
-msgstr "Mail bug reports and suggestions to <misc@calcurse.org>.\n"
+msgstr ""
#, c-format
msgid ""
@@ -184,11 +172,10 @@ msgid "completed tasks:\n"
msgstr ""
msgid "to do:\n"
-msgstr "to do:\n"
+msgstr ""
-#, fuzzy
msgid "next appointment:\n"
-msgstr "Appointment :"
+msgstr ""
#, c-format
msgid "invalid range: %s"
@@ -228,13 +215,13 @@ msgstr ""
msgid "calcurse is running (pid = %d)"
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "invalid input date format: %s"
-msgstr "Enter the new ToDo item : "
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "invalid output date format: %s"
-msgstr "Enter the new ToDo item : "
+msgstr ""
msgid "invalid argument combination"
msgstr ""
@@ -248,13 +235,11 @@ msgstr ""
msgid "Unable to find documentation."
msgstr ""
-#, fuzzy
msgid "Data were saved successfully"
-msgstr "The data files were successfully saved"
+msgstr ""
-#, fuzzy
msgid "Data were saved/reloaded successfully"
-msgstr "The data files were successfully saved"
+msgstr ""
msgid "Save cancelled"
msgstr ""
@@ -262,17 +247,14 @@ msgstr ""
msgid "Data were already saved"
msgstr ""
-#, fuzzy
msgid "Cannot open data file"
-msgstr "Failed to open todo file"
+msgstr ""
-#, fuzzy
msgid "Data were reloaded successfully"
-msgstr "The data files were successfully saved"
+msgstr ""
-#, fuzzy
msgid "Date were merged/reloaded successfully"
-msgstr "The data files were successfully saved"
+msgstr ""
msgid "Reload cancelled"
msgstr ""
@@ -289,11 +271,10 @@ msgstr ""
msgid "There are unsaved changes. Should they be saved?"
msgstr ""
-#, fuzzy
msgid "Do you really want to quit?"
-msgstr "Do you really want to quit ?"
+msgstr ""
-msgid "Command: [ h(elp) | w(rite)(!) | q(uit)(!) | wq(!) ]"
+msgid "Command: [ h(elp) | w(rite)(!) | q(uit)(!) | wq(!) | n(ext) | p(rev) ]"
msgstr ""
msgid "Read-only mode - use w!"
@@ -306,17 +287,27 @@ msgstr ""
msgid "Help topic does not exist: %s"
msgstr ""
+msgid "Select a repeating item in the appointments panel."
+msgstr ""
+
+msgid "Not a repeating item."
+msgstr ""
+
+msgid "Last occurrence."
+msgstr ""
+
+msgid "First occurrence."
+msgstr ""
+
#, c-format
msgid "No such command: %s"
msgstr ""
-#, fuzzy
msgid "unknown color"
-msgstr "Colour"
+msgstr "unknown colour"
-#, fuzzy
msgid "failed to open configuration file"
-msgstr "Failed to open config file"
+msgstr ""
#, c-format
msgid "invalid configuration directive: \"%s\""
@@ -331,21 +322,20 @@ msgstr ""
msgid "unknown user option: \"%s\" (ignored)"
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "invalid option format: \"%s\" (ignored)"
-msgstr "Enter the new ToDo item : "
+msgstr ""
#, c-format
msgid "unknown user option: \"%s\" (disabled)"
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "invalid option format: \"%s\" (disabled)"
-msgstr "Enter the new ToDo item : "
+msgstr ""
-#, fuzzy
msgid "layout configuration"
-msgstr "CalCurse %s | general options"
+msgstr ""
msgid "Foreground"
msgstr ""
@@ -356,19 +346,17 @@ msgstr ""
msgid "(terminal's default)"
msgstr ""
-#, fuzzy
msgid "color theme"
-msgstr "CalCurse %s | help"
+msgstr "colour theme"
-#, fuzzy
msgid "(if set to YES, compact panels are used)"
-msgstr "(if set to YES, progress bar will not be displayed when saving data)"
+msgstr ""
msgid "Calendar"
-msgstr "Calendar"
+msgstr ""
msgid "Appointments"
-msgstr "Appointments"
+msgstr ""
msgid "TODO"
msgstr ""
@@ -406,11 +394,14 @@ msgstr ""
msgid "(insert an empty line after each appointment)"
msgstr ""
+msgid "(text for a day without events and appointments)"
+msgstr ""
+
msgid "(display more than one day in the appointments panel)"
msgstr ""
msgid "(if set to YES, automatic save is done when quitting)"
-msgstr "(if set to YES, automatic save is done when quitting)"
+msgstr ""
msgid "(run the garbage collector when quitting)"
msgstr ""
@@ -422,20 +413,9 @@ msgid "(if YES, system events are turned into appointments (or else deleted))"
msgstr ""
msgid "(if set to YES, confirmation is required before quitting)"
-msgstr "(if set to YES, confirmation is required before quitting)"
-
-msgid "(if set to YES, confirmation is required before deleting an event)"
-msgstr "(if set to YES, confirmation is required before deleting an event)"
-
-#, fuzzy
-msgid "(if set to YES, messages about loaded and saved data will be displayed)"
-msgstr ""
-"(if set to YES, messages about loaded and saved data will not be displayed)"
-
-msgid "Monday"
msgstr ""
-msgid "Sunday"
+msgid "(if set to YES, confirmation is required before deleting an event)"
msgstr ""
msgid "(specifies the first day of week in the calendar view)"
@@ -462,29 +442,35 @@ msgstr ""
msgid "(Format of the date displayed in the appointments panel)"
msgstr ""
+msgid "(Format of the time displayed in the appointments panel)"
+msgstr ""
+
+msgid "Enter a text string (an empty string for the default text)"
+msgstr ""
+
msgid "Enter the date format (see 'man 3 strftime' for possible formats) "
msgstr ""
-#, fuzzy
+msgid "Enter the time format (see 'man 3 strftime' for possible formats) "
+msgstr ""
+
msgid "Enter the date format: "
-msgstr "Enter the new ToDo item : "
+msgstr ""
msgid "Enter the delay, in minutes, between automatic saves (0 to disable) "
msgstr ""
-#, fuzzy
msgid "general options"
-msgstr "CalCurse %s | general options"
+msgstr ""
msgid "Undefined option!"
msgstr ""
-msgid "undefined"
+msgid "UNDEFINED"
msgstr ""
-#, fuzzy
msgid "keys configuration"
-msgstr "CalCurse %s | general options"
+msgstr ""
msgid "Press the key you want to assign to:"
msgstr ""
@@ -493,7 +479,7 @@ msgstr ""
msgid "The key '%s' is already used for %s. Choose another one."
msgstr ""
-msgid "Some actions do not have any associated key bindings!"
+msgid "Some actions are left undefined!"
msgstr ""
msgid ""
@@ -503,66 +489,62 @@ msgstr ""
"Sorry, colours are not supported by your terminal\n"
"(Press [ENTER] to continue)"
-#, fuzzy, c-format
+#, c-format
msgid "Could not save %s."
-msgstr "Enter description :"
+msgstr ""
msgid "unknown item type"
msgstr ""
-msgid "(none)"
+msgid "Note:"
msgstr ""
-#, fuzzy
msgid "Event:"
-msgstr "Event :"
+msgstr ""
-#, fuzzy
msgid "Appointment:"
-msgstr "Appointment :"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Could not stop daemon properly: %s\n"
-msgstr "Enter description :"
+msgstr ""
#, c-format
msgid "terminated at %s with signal %d\n"
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Could not remove daemon lock file: %s\n"
-msgstr "Enter description :"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Could not fork: %s\n"
-msgstr "Enter description :"
+msgstr ""
#, c-format
msgid "Could not detach from the controlling terminal: %s\n"
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Could not change working directory: %s\n"
-msgstr "Enter description :"
+msgstr ""
msgid "Cannot daemonize, aborting\n"
msgstr ""
-#, fuzzy
msgid "Could not set lock file\n"
-msgstr "Enter description :"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Could not access \"%s\": %s\n"
-msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
+msgstr ""
#, c-format
msgid "started at %s\n"
msgstr ""
-#, fuzzy
msgid "error loading next appointment\n"
-msgstr "Appointment :"
+msgstr ""
#, c-format
msgid "launching notification at %s for: \"%s\"\n"
@@ -581,16 +563,15 @@ msgstr[1] ""
msgid "awakened at %s\n"
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Could not stop calcurse daemon: %s\n"
-msgstr "Enter description :"
+msgstr ""
-msgid "date error in event"
+msgid "illegal date in event"
msgstr ""
-#, fuzzy
-msgid "date error in the event\n"
-msgstr "FATAL ERROR in event_scan: date error in the event\n"
+msgid "date error in event\n"
+msgstr ""
msgid "Internal error: line too long"
msgstr ""
@@ -598,61 +579,140 @@ msgstr ""
msgid "out of memory"
msgstr ""
-#, fuzzy
msgid "unknown ical type"
-msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
+msgstr ""
-msgid "recurrence rule malformed."
+msgid "(empty)"
msgstr ""
-msgid "recurrence frequency not found."
+msgid "ical_store_event: out of memory"
msgstr ""
-msgid "recurrence frequency not recognized."
+msgid "need DTSTART to determine event type."
msgstr ""
-msgid "recurrence exception dates malformed."
+msgid "malformed recurrence line."
msgstr ""
-msgid "description malformed."
+msgid "frequency not set in rrule."
msgstr ""
-#, fuzzy
-msgid "could not get entire item description."
-msgstr "Enter description :"
+msgid "frequency absent in rrule."
+msgstr ""
-#, fuzzy
-msgid "could not retrieve item summary."
-msgstr "Enter description :"
+msgid "rrule frequency not supported."
+msgstr ""
+
+msgid "invalid interval."
+msgstr ""
-#, fuzzy
-msgid "item start date is not defined."
-msgstr "The day you entered is not valid"
+msgid "either until or count."
+msgstr ""
-msgid "item has a negative duration."
+msgid "missing until value."
msgstr ""
-msgid "item could not be identified."
+msgid "invalid until format."
+msgstr ""
+
+msgid "invalid count value."
+msgstr ""
+
+msgid "invalid bymonth list."
+msgstr ""
+
+msgid "invalid bymonthday list."
+msgstr ""
+
+msgid "invalid byday list."
+msgstr ""
+
+msgid "invalid exception date value type."
+msgstr ""
+
+msgid "malformed exceptions line."
+msgstr ""
+
+msgid "invalid exception."
+msgstr ""
+
+#, c-format
+msgid "malformed %s line."
+msgstr ""
+
+#, c-format
+msgid "malformed %s."
+msgstr ""
+
+msgid "malformed summary line."
+msgstr ""
+
+msgid "malformed summary."
+msgstr ""
+
+msgid "item start date not defined."
+msgstr ""
+
+msgid "malformed start time line."
+msgstr ""
+
+msgid "invalid or malformed event start time."
+msgstr ""
+
+msgid "invalid end time value type."
+msgstr ""
+
+msgid "malformed end time line."
+msgstr ""
+
+msgid "malformed event end time."
+msgstr ""
+
+msgid "end must be later than start."
+msgstr ""
+
+msgid "either end or duration."
+msgstr ""
+
+msgid "malformed duration line."
+msgstr ""
+
+msgid "invalid duration."
+msgstr ""
+
+msgid "exception date, but no recurrence rule."
+msgstr ""
+
+msgid "multi-day event changed to one-day event"
+msgstr ""
+
+#, c-format
+msgid "Location: %s"
msgstr ""
-msgid "event start time malformed."
+#, c-format
+msgid "Comment: %s"
msgstr ""
-msgid "could not retrieve event start time."
+#, c-format
+msgid "rrule does not match start day (%s)."
msgstr ""
-msgid "event end time malformed."
+msgid "item could not be identified."
msgstr ""
-msgid "could not retrieve event end time."
+msgid "only one description allowed."
msgstr ""
-msgid "item duration malformed."
+msgid "only one location allowed."
msgstr ""
msgid "The ical file seems to be malformed. The end of item was not found."
msgstr ""
+msgid "could not retrieve item summary."
+msgstr ""
+
msgid "item priority is invalid (must be between 0 and 9)."
msgstr ""
@@ -665,13 +725,12 @@ msgstr ""
msgid "The file cannot be accessed, please enter another file name."
msgstr ""
-#, fuzzy
msgid "Press [ENTER] to continue."
-msgstr "Press [ENTER] to continue"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Failed to open \"%s\", - %s\n"
-msgstr "Failed to open todo file"
+msgstr ""
msgid "Failed to build message\n"
msgstr ""
@@ -688,9 +747,8 @@ msgstr ""
msgid "%s does not exist"
msgstr ""
-#, fuzzy
msgid "Data files have changed and will be overwritten:"
-msgstr "Data files found. Data will be loaded now."
+msgstr ""
msgid "(c)ontinue"
msgstr ""
@@ -704,88 +762,93 @@ msgstr ""
msgid "[cma]"
msgstr ""
-#, fuzzy
msgid "failed to open appointment file"
-msgstr "Failed to open config file"
+msgstr ""
-#, fuzzy
msgid "syntax error in the item date"
-msgstr "FATAL ERROR in load_app: syntax error in the item date\n"
+msgstr ""
-#, fuzzy
msgid "no event nor appointment found"
-msgstr "FATAL ERROR in load_app: no event nor appointment found\n"
+msgstr ""
-#, fuzzy
msgid "syntax error in item time or duration"
-msgstr "FATAL ERROR in load_app: syntax error in the item date\n"
+msgstr ""
-#, fuzzy
msgid "syntax error in item identifier"
-msgstr "FATAL ERROR in load_app: syntax error in the item date\n"
+msgstr ""
-#, fuzzy
msgid "wrong format in the appointment or event"
-msgstr "FATAL ERROR in load_app: wrong format in the appointment or event\n"
+msgstr ""
-#, fuzzy
msgid "syntax error in item repetition"
-msgstr "FATAL ERROR in load_app: syntax error in the item date\n"
+msgstr ""
+
+msgid "syntax error in until date"
+msgstr ""
+
+msgid "until date error"
+msgstr ""
+
+msgid "BYMONTHDAY illegal with WEEKLY"
+msgstr ""
+
+msgid "missing end of recurrence"
+msgstr ""
+
+msgid "syntax error in item state"
+msgstr ""
-#, fuzzy
msgid "failed to open todo file"
-msgstr "Failed to open todo file"
+msgstr ""
msgid "Screen data have changed and will be lost:"
msgstr ""
-#, fuzzy
msgid "failed to open key file"
-msgstr "Failed to open todo file"
-
-msgid ""
-"\n"
-"Too many errors while reading configuration file!\n"
-"Please backup your keys file, remove it from directory, and launch calcurse "
-"again.\n"
msgstr ""
msgid "Could not read key label"
msgstr ""
-msgid "Key label not recognized"
+#, c-format
+msgid "Key label not recognized: \"%s\""
msgstr ""
#, c-format
-msgid "Error reading key: \"%s\""
+msgid "No keys assigned to \"%s\"."
msgstr ""
#, c-format
-msgid "\"%s\" assigned multiple times!"
+msgid "Keyname not recognized: \"%s\""
msgstr ""
-msgid "There were some errors when loading keys file."
+#, c-format
+msgid "\"%s\" assigned twice: \"%s\"."
msgstr ""
-msgid "Too many errors while reading keys file, aborting..."
+#, c-format
+msgid ""
+"Action \"%s\" absent, but default key \"%s\" assigned to another action."
msgstr ""
-#, fuzzy, c-format
-msgid "FATAL ERROR: could not create %s: %s\n"
-msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
+msgid "Errors in the keys file."
+msgstr ""
-msgid "Press [ENTER] to continue"
-msgstr "Press [ENTER] to continue"
+msgid "Remove offending line(s) from the keys file, aborting..."
+msgstr ""
-msgid "Welcome to Calcurse. Missing data files were created."
-msgstr "Welcome to Calcurse. Missing data files were created."
+msgid "Some actions do not have any associated key bindings!"
+msgstr ""
-msgid "Data files found. Data will be loaded now."
-msgstr "Data files found. Data will be loaded now."
+#, c-format
+msgid "FATAL ERROR: could not create %s: %s\n"
+msgstr ""
-#, fuzzy
msgid "The data were successfully exported"
-msgstr "The data files were successfully saved"
+msgstr ""
+
+msgid "Press [ENTER] to continue"
+msgstr ""
msgid "unknown export type"
msgstr ""
@@ -806,9 +869,8 @@ msgstr ""
msgid "FATAL ERROR: the input file cannot be accessed, Aborting..."
msgstr ""
-#, fuzzy
msgid "FATAL ERROR: wrong import mode"
-msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
+msgstr ""
#, c-format
msgid "%d app"
@@ -858,7 +920,9 @@ msgstr ""
msgid "Invalid delay"
msgstr ""
-msgid "Periodic save: data files have changed. Save cancelled."
+msgid ""
+"Periodic save cancelled. Data files have changed. Save and merge "
+"interactively"
msgstr ""
#, c-format
@@ -880,13 +944,13 @@ msgid "Credits"
msgstr ""
msgid "Help"
-msgstr "Help"
+msgstr ""
msgid "Quit"
-msgstr "Quit"
+msgstr ""
msgid "Save"
-msgstr "Save"
+msgstr ""
msgid "Reload"
msgstr ""
@@ -897,9 +961,11 @@ msgstr ""
msgid "Paste"
msgstr ""
-#, fuzzy
msgid "Chg Win"
-msgstr "Chg View"
+msgstr ""
+
+msgid "Prev Win"
+msgstr ""
msgid "Import"
msgstr ""
@@ -907,41 +973,35 @@ msgstr ""
msgid "Export"
msgstr ""
-#, fuzzy
msgid "Go to"
-msgstr "Goto:\n"
+msgstr ""
msgid "OtherCmd"
msgstr ""
msgid "Config"
-msgstr "Config"
+msgstr ""
msgid "Redraw"
-msgstr "Redraw"
+msgstr ""
-#, fuzzy
msgid "Add Appt"
-msgstr "Add Item"
+msgstr ""
msgid "Add Todo"
msgstr ""
-#, fuzzy
msgid "-1 Day"
-msgstr "-/+1 Day"
+msgstr ""
-#, fuzzy
msgid "+1 Day"
-msgstr "-/+1 Day"
+msgstr ""
-#, fuzzy
msgid "-1 Week"
-msgstr "-/+1 Week"
+msgstr ""
-#, fuzzy
msgid "+1 Week"
-msgstr "-/+1 Week"
+msgstr ""
msgid "-1 Month"
msgstr ""
@@ -955,13 +1015,11 @@ msgstr ""
msgid "+1 Year"
msgstr ""
-#, fuzzy
msgid "Nxt View"
-msgstr "View"
+msgstr ""
-#, fuzzy
msgid "Prv View"
-msgstr "View"
+msgstr ""
msgid "Today"
msgstr ""
@@ -975,51 +1033,44 @@ msgstr ""
msgid "Left"
msgstr ""
-#, fuzzy
msgid "Down"
-msgstr "Up/Down"
+msgstr ""
msgid "Up"
msgstr ""
-#, fuzzy
msgid "beg Week"
-msgstr "-/+1 Week"
+msgstr ""
-#, fuzzy
msgid "end Week"
-msgstr "-/+1 Week"
+msgstr ""
msgid "Add Item"
-msgstr "Add Item"
+msgstr ""
msgid "Del Item"
-msgstr "Del Item"
+msgstr ""
-#, fuzzy
msgid "Edit Itm"
-msgstr "Add Item"
+msgstr ""
msgid "View"
-msgstr "View"
+msgstr ""
msgid "Pipe"
msgstr ""
-#, fuzzy
msgid "Flag Itm"
-msgstr "Del Item"
+msgstr ""
msgid "Repeat"
msgstr ""
-#, fuzzy
msgid "EditNote"
-msgstr "Add Item"
+msgstr ""
-#, fuzzy
msgid "ViewNote"
-msgstr "View"
+msgstr ""
msgid "Prio.+"
msgstr ""
@@ -1037,25 +1088,23 @@ msgid ""
"# interface. It should not be edited directly.\n"
msgstr ""
-#, fuzzy
msgid "FATAL ERROR: could not create default keys file."
-msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
+msgstr ""
-#, fuzzy
msgid "FATAL ERROR: key value out of bounds"
-msgstr "FATAL ERROR in update_windows: no window selected\n"
+msgstr ""
msgid "General"
-msgstr "General"
+msgstr ""
msgid "Layout"
-msgstr "Layout"
+msgstr ""
msgid "Sidebar"
msgstr ""
msgid "Color"
-msgstr "Colour"
+msgstr ""
msgid "Notify"
msgstr ""
@@ -1063,9 +1112,8 @@ msgstr ""
msgid "Keys"
msgstr ""
-#, fuzzy
msgid "Unknown"
-msgstr "Colour"
+msgstr ""
msgid "Cancel the ongoing action."
msgstr ""
@@ -1097,6 +1145,9 @@ msgstr ""
msgid "Select next panel in calcurse main screen."
msgstr ""
+msgid "Select previous panel in calcurse main screen."
+msgstr ""
+
msgid "Import data from an external file."
msgstr ""
@@ -1109,9 +1160,8 @@ msgstr ""
msgid "Show next possible actions inside status bar."
msgstr ""
-#, fuzzy
msgid "Enter the configuration menu."
-msgstr "CalCurse %s | general options"
+msgstr ""
msgid "Redraw calcurse's screen."
msgstr ""
@@ -1214,12 +1264,11 @@ msgstr ""
msgid "Lower a task priority inside the todo panel."
msgstr ""
-#, fuzzy
msgid "FATAL ERROR: null file pointer."
-msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
+msgstr ""
#, c-format
-msgid "When adding default key for \"%s\", \"%s\" was already assigned!"
+msgid "Default key(s) assigned to %d action%s."
msgstr ""
msgid "xmalloc: zero size"
@@ -1249,9 +1298,8 @@ msgstr ""
msgid "could not allocate memory to store block info"
msgstr ""
-#, fuzzy
msgid "Block not found"
-msgstr "Appointment :"
+msgstr ""
#, c-format
msgid "overflow at %s"
@@ -1313,16 +1361,8 @@ msgstr ""
msgid "Warning: could not open %s, Aborting..."
msgstr ""
-#, fuzzy
-msgid "error while launching command: could not fork"
-msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-msgid "error while launching command"
-msgstr ""
-
-#, fuzzy
msgid "(if set to YES, notify-bar will be displayed)"
-msgstr "(if set to YES, progress bar will not be displayed when saving data)"
+msgstr ""
msgid "(Format of the date to be displayed inside notify-bar)"
msgstr ""
@@ -1346,9 +1386,6 @@ msgstr ""
msgid "(Log activity when running in background)"
msgstr ""
-msgid "Enter the time format (see 'man 3 strftime' for possible formats) "
-msgstr ""
-
msgid "Enter the number of seconds (0 not to be warned before an appointment)"
msgstr ""
@@ -1364,30 +1401,51 @@ msgstr ""
msgid "System event"
msgstr ""
-msgid "unknown repetition type"
+msgid "unknown character"
msgstr ""
-msgid "unknown character"
+#, c-format
+msgid "recurrence error: not on start day (%s)"
+msgstr ""
+
+msgid "illegel date in event"
+msgstr ""
+
+msgid "date error in event"
+msgstr ""
+
+msgid "month day is zero"
+msgstr ""
+
+msgid "no daily frequency check"
+msgstr ""
+
+msgid "illegal BYDAY value"
msgstr ""
msgid "event not found"
msgstr ""
-#, fuzzy
msgid "appointment not found"
-msgstr "Appointment :"
+msgstr ""
+
+msgid "syntax error in bymonthday"
+msgstr ""
+
+msgid "syntax error in bywday"
+msgstr ""
+
+msgid "syntax error in bymonth"
+msgstr ""
+
+msgid "illegal bymonth value"
+msgstr ""
-#, fuzzy
msgid "syntax error in item date"
-msgstr "FATAL ERROR in load_app: syntax error in the item date\n"
+msgstr ""
-#, fuzzy
msgid "date error in item exception"
-msgstr "FATAL ERROR in event_scan: date error in the event\n"
-
-#, fuzzy, c-format
-msgid "Could not remove calcurse lock file: %s\n"
-msgstr "Enter description :"
+msgstr ""
#, c-format
msgid "Error setting signal #%d : %s\n"
@@ -1403,22 +1461,22 @@ msgid "ERROR setting first day of week"
msgstr ""
msgid "The day you entered is not valid"
-msgstr "The day you entered is not valid"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Enter the day to go to [ENTER for today] : %s"
-msgstr "Enter the day to go to [ENTER for today] : dd/mm/yyyy"
+msgstr ""
#, c-format
msgid "The move failed (%d/%d/%d)."
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Enter start date [%s] and/or time ([hh:mm] or [hhmm]):"
-msgstr "Enter end time ([hh:mm] or [h:mm]) or duration (in minutes) : "
+msgstr ""
msgid "Press [Enter] to continue"
-msgstr "Press [Enter] to continue"
+msgstr ""
msgid "Invalid date or time."
msgstr ""
@@ -1426,6 +1484,10 @@ msgstr ""
msgid "Invalid time: start time must come before end time!"
msgstr ""
+#, c-format
+msgid "Repetition must begin on start day (%s)."
+msgstr ""
+
msgid "Enter end date (and/or time) or duration ('?' for input formats):"
msgstr ""
@@ -1436,82 +1498,134 @@ msgstr ""
msgid "Time: hh:mm (hh: or :mm) or hhmm. Duration: +mm, +hh:mm, +??d??h??m."
msgstr ""
-#, fuzzy
msgid "Invalid time or duration."
-msgstr "FATAL ERROR in load_app: syntax error in the item date\n"
+msgstr ""
msgid "Invalid date: end time must come after start time."
msgstr ""
-#, fuzzy
msgid "Enter the new item description:"
-msgstr "Enter description :"
+msgstr ""
msgid "Exception days:"
msgstr ""
-#, fuzzy
msgid "Invalid date format - try again:."
-msgstr "FATAL ERROR in load_app: syntax error in the item date\n"
+msgstr ""
+
+msgid "Limit repetition to listed days."
+msgstr ""
+
+msgid "Expand repetition to listed days."
+msgstr ""
+
+msgid "Expand repetition to listed days, either all or 1st, 2nd, ... of month."
+msgstr ""
-#, fuzzy
-msgid "Enter the new repetition type:"
-msgstr "Enter description :"
+msgid "Note: limit to monthdays, if any."
+msgstr ""
+
+msgid "Expand repetition to listed days, either all or 1st, 2nd, ... of year."
+msgstr ""
-msgid "(d)aily"
+msgid "Note: expand to listed months, if any; limit to monthdays, if any."
msgstr ""
-msgid "(w)eekly"
+msgid "Limit repetition to listed months."
msgstr ""
-msgid "(m)onthly"
+msgid "Expand repetition to listed months."
msgstr ""
-msgid "(y)early"
+msgid "Limit repetition to listed days of month."
+msgstr ""
+
+msgid "Expand repetition to listed days of month."
+msgstr ""
+
+#, c-format
+msgid "Weekdays %s|..|%s, space-separated list, '?' for help:"
msgstr ""
#, c-format
-msgid "(currently using %s)"
+msgid ""
+"Weekdays [n]%s|..|[n]%s, space-separated list, n=1,-1,..,5,-5, '?' for help:"
+msgstr ""
+
+#, c-format
+msgid ""
+"Weekdays [n]%s|..|[n]%s, space-separated list, n=1,-1,..,53,-53, '?' for "
+"help:"
+msgstr ""
+
+msgid "Months 1|..|12, space-separated list, '?' for help:"
+msgstr ""
+
+msgid "Monthdays 1|..|31 or -1|..|-31, space-separated list, '?' for help:"
+msgstr ""
+
+msgid "Invalid format - try again."
+msgstr ""
+
+msgid "Press any key to continue."
+msgstr ""
+
+msgid "Base period:"
+msgstr ""
+
+msgid "day"
+msgstr ""
+
+msgid "week"
+msgstr ""
+
+msgid "month"
+msgstr ""
+
+msgid "year"
msgstr ""
msgid "[dwmy]"
msgstr ""
-msgid "Invalid frequency."
+msgid "Frequency:"
msgstr ""
-#, fuzzy
-msgid "Enter the repetition frequency:"
-msgstr "Enter description :"
+msgid "Invalid frequency."
+msgstr ""
-#, fuzzy
-msgid "Enter end date or duration ('?' for input formats):"
-msgstr "Possible argument formats are : 'mm/dd/yyyy' or 'n'\n"
+msgid "Until date, increment or repeat count ('?' for input formats):"
+msgstr ""
#, c-format
-msgid "Date: %s (year or month may be omitted). Endless duration: 0."
+msgid "Date: %s (year, month may be omitted, endless: 0)."
msgstr ""
-msgid "Duration in days: +dd. Duration in weeks and days: +??w??d."
+msgid "Increment: +?? (days) or: +??w??d (weeks). Repeat count: #?? (number)."
msgstr ""
#, c-format
-msgid "Invalid date: end date must come after start date (%s)."
+msgid "Invalid date: until date must come after start date (%s)."
msgstr ""
msgid "Invalid date."
msgstr ""
-#, fuzzy
+msgid "Repeat count is too big."
+msgstr ""
+
+#, c-format
+msgid "Repetition must begin on start day (%s); any change discarded."
+msgstr ""
+
msgid "Description"
-msgstr "Enter description :"
+msgstr ""
msgid "Repetition"
msgstr ""
-#, fuzzy
msgid "Edit: "
-msgstr "Add Item"
+msgstr ""
msgid "Start time"
msgstr ""
@@ -1525,18 +1639,15 @@ msgstr ""
msgid "Pipe item to external command:"
msgstr ""
-#, fuzzy
msgid "Enter start time ([hh:mm] or [hhmm]), leave blank for an all-day event:"
msgstr ""
-"Enter start time ([hh:mm] or [h:mm]), leave blank for an all-day event : "
msgid ""
"Enter end time as date (and/or time) or duration ('?' for input formats):"
msgstr ""
-#, fuzzy
msgid "Enter description:"
-msgstr "Enter description :"
+msgstr ""
#, c-format
msgid "Date: %s (and/or time), year or month may be omitted."
@@ -1545,46 +1656,49 @@ msgstr ""
msgid "Invalid start time."
msgstr ""
-#, fuzzy
-msgid "Do you really want to delete this item?"
-msgstr "Do you really want to delete this item ?"
+msgid ""
+"This item is recurrent and has a note attached to it. Delete (s)elected "
+"occurrence, (a)ll occurrences, or just its (n)ote?"
+msgstr ""
-msgid "This item is recurrent. Delete (a)ll occurences or just this (o)ne?"
+msgid "[san]"
msgstr ""
-msgid "[ao]"
+msgid ""
+"This item has a note attached to it. Delete (s)elected occurrence or just "
+"its (n)ote?"
msgstr ""
-msgid "This item has a note attached to it. Delete (i)tem or just its (n)ote?"
+msgid "[sn]"
msgstr ""
-msgid "[in]"
+msgid ""
+"This item is recurrent. Delete (s)elected occurrence or (a)ll occurrences?"
msgstr ""
-#, fuzzy
-msgid "Enter the repetition type:"
-msgstr "Enter description :"
+msgid "[sa]"
+msgstr ""
-#, c-format
-msgid "Date: %s (year or month may be omitted). Endless duration: '0'."
+msgid "Confirm deletion. Delete (s)elected occurrence? Press (s) to confirm."
msgstr ""
-msgid "This item is already a repeated one."
+msgid "[s]"
msgstr ""
-msgid "wrong item type"
+msgid "Already repeated."
+msgstr ""
+
+msgid "A (s)imple or (a)dvanced repetition?"
msgstr ""
-#, fuzzy
msgid "Enter the new TODO item:"
-msgstr "Enter the new ToDo item : "
+msgstr ""
msgid "Enter the TODO priority [0 (none), 1 (highest) - 9 (lowest)]:"
msgstr ""
-#, fuzzy
msgid "Do you really want to delete this task?"
-msgstr "Do you really want to delete this task ?"
+msgstr ""
msgid "This item has a note attached to it. Delete (t)odo or just its (n)ote?"
msgstr ""
@@ -1592,13 +1706,16 @@ msgstr ""
msgid "[tn]"
msgstr ""
-#, fuzzy
msgid "Enter the new TODO description:"
-msgstr "Enter the new ToDo item : "
+msgstr ""
msgid "TODO:"
msgstr ""
+#, c-format
+msgid "Could not remove calcurse lock file: %s\n"
+msgstr ""
+
msgid "/!\\ INTERNAL ERROR /!\\"
msgstr ""
@@ -1609,7 +1726,7 @@ msgid "[yn]"
msgstr ""
msgid "Press any key to continue..."
-msgstr "Press any key to continue..."
+msgstr ""
msgid "failure in mktime"
msgstr ""
@@ -1618,10 +1735,10 @@ msgid "error in mktime"
msgstr ""
msgid "yes"
-msgstr "yes"
+msgstr ""
msgid "no"
-msgstr "no"
+msgstr ""
msgid "option not defined"
msgstr ""
@@ -1655,30 +1772,23 @@ msgstr ""
msgid "Usage: calcurse-upgrade [-h|-v|--config <file>]"
msgstr ""
-#, fuzzy
msgid ""
"\n"
-"Copyright (c) 2004-2017 calcurse Development Team.\n"
+"Copyright (c) 2004-2023 calcurse Development Team.\n"
"This is free software; see the source for copying conditions.\n"
msgstr ""
-"\n"
-"Copyright (c) 2004-2006 Frederic Culot.\n"
-"This is free software; see the source for copying conditions.\n"
msgid "unrecognized option:"
msgstr ""
-#, fuzzy
msgid "Configuration file not found:"
-msgstr "FATAL ERROR in fill_config_var: wrong configuration variable format.\n"
+msgstr ""
-#, fuzzy
msgid "Pre-3.0.0 configuration file format detected..."
-msgstr "FATAL ERROR in fill_config_var: wrong configuration variable format.\n"
+msgstr ""
-#, fuzzy
msgid "Create temporary backup of the configuration file..."
-msgstr "Failed to open config file"
+msgstr ""
msgid "Old backup file found:"
msgstr ""
@@ -1707,989 +1817,3 @@ msgstr ""
msgid "Remove temporary backup..."
msgstr ""
-
-#, fuzzy
-#~ msgid "configuration variable unknown: \"%s\""
-#~ msgstr ""
-#~ "FATAL ERROR in fill_config_var: wrong configuration variable format.\n"
-
-#, fuzzy
-#~ msgid "wrong configuration variable format for \"%s\""
-#~ msgstr ""
-#~ "FATAL ERROR in fill_config_var: wrong configuration variable format.\n"
-
-#, fuzzy
-#~ msgid "(if set to YES, progress bar will be displayed when saving data)"
-#~ msgstr ""
-#~ "(if set to YES, progress bar will not be displayed when saving data)"
-
-#~ msgid "Saving..."
-#~ msgstr "Saving..."
-
-#~ msgid "Loading..."
-#~ msgstr "Loading..."
-
-#, fuzzy
-#~ msgid "Exporting..."
-#~ msgstr "aborting...\n"
-
-#~ msgid "Problems accessing data file ..."
-#~ msgstr "Problems accessing data file ..."
-
-#~ msgid "The data files were successfully saved"
-#~ msgstr "The data files were successfully saved"
-
-#, fuzzy
-#~ msgid "You entered an invalid time, should be [hh:mm] or [hhmm]"
-#~ msgstr "You entered an invalid start time, should be [h:mm] or [hh:mm]"
-
-#, fuzzy
-#~ msgid ""
-#~ "Enter end time ([hh:mm], [hhmm]) or duration ([+hh:mm], [+xxxdxxhxxm]):"
-#~ msgstr "Enter end time ([hh:mm] or [h:mm]) or duration (in minutes) : "
-
-#, fuzzy
-#~ msgid "The entered date is not valid."
-#~ msgstr "The day you entered is not valid"
-
-#, fuzzy
-#~ msgid "Possible formats are [%s] or '0' for an endless repetition."
-#~ msgstr "Possible argument formats are : 'mm/dd/yyyy' or 'n'\n"
-
-#, fuzzy
-#~ msgid "Enter the new repetition frequency:"
-#~ msgstr "Enter description :"
-
-#, fuzzy
-#~ msgid "Enter end date ([%s]), duration ([+xxwxxd]) or '0':"
-#~ msgstr "Enter end time ([hh:mm] or [h:mm]) or duration (in minutes) : "
-
-#, fuzzy
-#~ msgid "You entered an invalid start time, should be [hh:mm] or [hhmm]"
-#~ msgstr "You entered an invalid start time, should be [h:mm] or [hh:mm]"
-
-#, fuzzy
-#~ msgid ""
-#~ "Invalid end time/duration, should be [hh:mm], [hhmm], [+hh:mm], "
-#~ "[+xxxdxxhxxm] or [+mm]"
-#~ msgstr ""
-#~ "You entered an invalid end time, should be [h:mm] or [hh:mm] or [mm]"
-
-#, fuzzy
-#~ msgid "Possible formats are [%s], [+xxwxxd] or '0'."
-#~ msgstr "Possible argument formats are : 'mm/dd/yyyy' or 'n'\n"
-
-#, fuzzy
-#~ msgid "Enter an option number to change its value"
-#~ msgstr "Enter an option number to change its value [Q to quit] "
-
-#, fuzzy
-#~ msgid "The frequence you entered is not valid."
-#~ msgstr "The day you entered is not valid"
-
-#~ msgid "January"
-#~ msgstr "January"
-
-#~ msgid "February"
-#~ msgstr "February"
-
-#~ msgid "March"
-#~ msgstr "March"
-
-#~ msgid "April"
-#~ msgstr "April"
-
-#~ msgid "May"
-#~ msgstr "May"
-
-#~ msgid "June"
-#~ msgstr "June"
-
-#~ msgid "July"
-#~ msgstr "July"
-
-#~ msgid "August"
-#~ msgstr "August"
-
-#~ msgid "September"
-#~ msgstr "September"
-
-#~ msgid "October"
-#~ msgstr "October"
-
-#~ msgid "November"
-#~ msgstr "November"
-
-#~ msgid "December"
-#~ msgstr "December"
-
-#~ msgid "Sun"
-#~ msgstr "Sun"
-
-#~ msgid "Mon"
-#~ msgstr "Mon"
-
-#~ msgid "Tue"
-#~ msgstr "Tue"
-
-#~ msgid "Wed"
-#~ msgstr "Wed"
-
-#~ msgid "Thu"
-#~ msgstr "Thu"
-
-#~ msgid "Fri"
-#~ msgstr "Fri"
-
-#~ msgid "Sat"
-#~ msgstr "Sat"
-
-#, fuzzy
-#~ msgid ""
-#~ "Usage: calcurse [-g|-h|-v] [-an] [-t[num]] [-i<file>] [-x[format]]\n"
-#~ " [-d <date>|<num>] [-s[date]] [-r[range]]\n"
-#~ " [-c<file>] [-D<dir>] [-S<regex>] [--status]\n"
-#~ " [--read-only]\n"
-#~ msgstr "Usage: calcurse [-h | -v] [-at] [-d date|num] [-c file]\n"
-
-#, fuzzy
-#~ msgid ""
-#~ "\n"
-#~ "Miscellaneous:\n"
-#~ " -h, --help\n"
-#~ "\tprint this help and exit.\n"
-#~ "\n"
-#~ " -v, --version\n"
-#~ "\tprint calcurse version and exit.\n"
-#~ "\n"
-#~ " --status\n"
-#~ "\tdisplay the status of running instances of calcurse.\n"
-#~ "\n"
-#~ " --read-only\n"
-#~ "\tDon't save configuration nor appointments/todos. Use with care.\n"
-#~ "\n"
-#~ "Files:\n"
-#~ " -c <file>, --calendar <file>\n"
-#~ "\tspecify the calendar <file> to use (has precedence over '-D').\n"
-#~ "\n"
-#~ " -D <dir>, --directory <dir>\n"
-#~ "\tspecify the data directory to use.\n"
-#~ "\tIf not specified, the default directory is ~/.calcurse\n"
-#~ "\n"
-#~ "Non-interactive:\n"
-#~ " -a, --appointment\n"
-#~ " \tprint events and appointments for current day and exit.\n"
-#~ "\n"
-#~ " -d <date|num>, --day <date|num>\n"
-#~ "\tprint events and appointments for <date> or <num> upcoming days and\n"
-#~ "\texit. To specify both a starting date and a range, use the\n"
-#~ "\t'--startday' and the '--range' option.\n"
-#~ "\n"
-#~ " -g, --gc\n"
-#~ "\trun the garbage collector for note files and exit. \n"
-#~ "\n"
-#~ " -i <file>, --import <file>\n"
-#~ "\timport the icalendar data contained in <file>. \n"
-#~ "\n"
-#~ " -n, --next\n"
-#~ "\tprint next appointment within upcoming 24 hours and exit. Also given\n"
-#~ "\tis the remaining time before this next appointment.\n"
-#~ "\n"
-#~ " -l <num>, --limit <num>\n"
-#~ "\tonly print information regarding the next <num> items. \n"
-#~ "\n"
-#~ " -r[num], --range[=num]\n"
-#~ "\tprint events and appointments for the [num] number of days\n"
-#~ "\tand exit. If no [num] is given, a range of 1 day is considered.\n"
-#~ "\n"
-#~ " -s[date], --startday[=date]\n"
-#~ "\tprint events and appointments from [date] and exit.\n"
-#~ "\tIf no [date] is given, the current day is considered.\n"
-#~ "\n"
-#~ " -S<regex>, --search=<regex>\n"
-#~ "\tsearch for the given regular expression within events, appointments,\n"
-#~ "\tand todos description.\n"
-#~ "\n"
-#~ " -t[num], --todo[=num]\n"
-#~ "\tprint todo list and exit. If the optional number [num] is given,\n"
-#~ "\tthen only todos having a priority equal to [num] will be returned.\n"
-#~ "\tThe priority number must be between 1 (highest) and 9 (lowest).\n"
-#~ "\tIt is also possible to specify '0' for the priority, in which case\n"
-#~ "\tonly completed tasks will be shown.\n"
-#~ "\n"
-#~ " -x[format], --export[=format]\n"
-#~ "\texport user data to the specified format. Events, appointments and\n"
-#~ "\ttodos are converted and echoed to stdout.\n"
-#~ "\tTwo possible formats are available: 'ical' and 'pcal'.\n"
-#~ "\tIf the optional argument format is not given, ical format is\n"
-#~ "\tselected by default.\n"
-#~ "\tnote: redirect standard output to export data to a file,\n"
-#~ "\tby issuing a command such as: calcurse --export > calcurse.dat\n"
-#~ msgstr ""
-#~ "\n"
-#~ "Miscellaneous:\n"
-#~ " -h\t\tprint this help and exit.\n"
-#~ " -v\t\tprint calcurse version and exit.\n"
-#~ "\n"
-#~ "Options:\n"
-#~ " -c <file>\tspecify the calendar <file> to use.\n"
-#~ "\n"
-#~ "Non-interactive:\n"
-#~ " -a \t\tprint events and appointments for current day and exit.\n"
-#~ " -d <date|num>\tprint events and appointments for <date> or <num> "
-#~ "upcoming\n"
-#~ "\t\tdays and exit.\n"
-#~ " -t\t\tprint todo list and exit.\n"
-#~ "\n"
-#~ "For more information, type '?' from within Calcurse, or read the "
-#~ "manpage.\n"
-#~ "Mail bug reports and suggestions to <misc@calcurse.org>.\n"
-
-#, fuzzy
-#~ msgid "Enter the new ending date: [%s] or '0'"
-#~ msgstr "Possible argument formats are : 'mm/dd/yyyy' or 'n'\n"
-
-#, fuzzy
-#~ msgid "Possible formats are [%s] or '0' for an endless repetition"
-#~ msgstr "Possible argument formats are : 'mm/dd/yyyy' or 'n'\n"
-
-#~ msgid "Argument to the '-d' flag is not valid\n"
-#~ msgstr "Argument to the '-d' flag is not valid\n"
-
-#, fuzzy
-#~ msgid "Argument is not valid\n"
-#~ msgstr "Argument to the '-d' flag is not valid\n"
-
-#, fuzzy
-#~ msgid "%s does not exist, create it now [y/n]? "
-#~ msgstr "%s does not exist, create it now [y or n] ? "
-
-#~ msgid "aborting...\n"
-#~ msgstr "aborting...\n"
-
-#~ msgid "%s successfully created\n"
-#~ msgstr "%s successfully created\n"
-
-#~ msgid "Exit"
-#~ msgstr "Exit"
-
-#, fuzzy
-#~ msgid "No color"
-#~ msgstr "Colour"
-
-#, fuzzy
-#~ msgid "Add key"
-#~ msgstr "Add Item"
-
-#, fuzzy
-#~ msgid "Del key"
-#~ msgstr "Del Item"
-
-#, fuzzy
-#~ msgid "unknwon type"
-#~ msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-#~ msgid "To do :"
-#~ msgstr "To do :"
-
-#, fuzzy
-#~ msgid "Calcurse help"
-#~ msgstr "CalCurse %s | help"
-
-#~ msgid " Welcome to Calcurse. This is the main help screen.\n"
-#~ msgstr " Welcome to Calcurse. This is the main help screen.\n"
-
-#, fuzzy
-#~ msgid ""
-#~ "Moving around: Press '%s' or '%s' to scroll text upward or downward\n"
-#~ " inside help screens, if necessary.\n"
-#~ "\n"
-#~ " Exit help: When finished, press '%s' to exit help and go back to\n"
-#~ " the main Calcurse screen.\n"
-#~ "\n"
-#~ " Help topic: At the bottom of this screen you can see a panel with\n"
-#~ " different fields, represented by a letter and a short\n"
-#~ " title. This panel contains all the available actions\n"
-#~ " you can perform when using Calcurse.\n"
-#~ " By pressing one of the letters appearing in this\n"
-#~ " panel, you will be shown a short description of the\n"
-#~ " corresponding action. At the top right side of the\n"
-#~ " description screen are indicated the user-defined key\n"
-#~ " bindings that lead to the action.\n"
-#~ "\n"
-#~ " Credits: Press '%s' for credits."
-#~ msgstr ""
-#~ " Moving around: Press CTRL-P or CTRL-N to scroll text upward or\n"
-#~ " downward inside help screens, if necessary.\n"
-#~ "\n"
-#~ " Exit help: When finished, press 'Q' to exit help and go back\n"
-#~ " to the main Calcurse screen.\n"
-#~ "\n"
-#~ " Help topic: At the bottom of this screen you can see a panel\n"
-#~ " with different fields, represented by a letter and\n"
-#~ " a short title. This panel contains all the available\n"
-#~ " actions you can perform when using Calcurse.\n"
-#~ " By pressing one of the letters appearing in this\n"
-#~ " panel, you will be shown a short description of the\n"
-#~ " corresponding action.\n"
-#~ "\n"
-#~ " Credits: Press '@' for credits."
-
-#, fuzzy
-#~ msgid "Save\n"
-#~ msgstr "Save:\n"
-
-#, fuzzy
-#~ msgid ""
-#~ "Save calcurse data.\n"
-#~ "Data are splitted into four different files which contain :\n"
-#~ "\n"
-#~ " / ~/.calcurse/conf -> user configuration\n"
-#~ " | (layout, color, general options)\n"
-#~ " | ~/.calcurse/apts -> data related to the appointments\n"
-#~ " | ~/.calcurse/todo -> data related to the todo list\n"
-#~ " \\ ~/.calcurse/keys -> user-defined key bindings\n"
-#~ "\n"
-#~ "In the config menu, you can choose to save the Calcurse data\n"
-#~ "automatically before quitting."
-#~ msgstr ""
-#~ "Pressing 'S' saves the Calcurse data.\n"
-#~ "\n"
-#~ "The data is splitted into three different files which contains :\n"
-#~ "\n"
-#~ " / ~/.calcurse/conf -> the user configuration\n"
-#~ " | (layout, colour, general options)\n"
-#~ " | ~/.calcurse/apts -> the data related to the appointments\n"
-#~ " \\ ~/.calcurse/todo -> the data related to the todo list\n"
-#~ "\n"
-#~ "In the config menu, you can choose to save the Calcurse data\n"
-#~ "automatically before quitting."
-
-#, fuzzy
-#~ msgid "Export\n"
-#~ msgstr "aborting...\n"
-
-#, fuzzy
-#~ msgid "Displacement keys\n"
-#~ msgstr "Displacement keys:\n"
-
-#, fuzzy
-#~ msgid "View\n"
-#~ msgstr "View:\n"
-
-#, fuzzy
-#~ msgid ""
-#~ "View the item you select in either the Todo or Appointment panel.\n"
-#~ "\n"
-#~ "This is usefull when an event description is longer than the available\n"
-#~ "space to display it. If that is the case, the description will be\n"
-#~ "shortened and its end replaced by '...'. To be able to read the entire\n"
-#~ "description, just press '%s' and a popup window will appear, containing\n"
-#~ "the whole event.\n"
-#~ "\n"
-#~ "Press any key to close the popup window and go back to the main\n"
-#~ "Calcurse screen."
-#~ msgstr ""
-#~ "Pressing 'V' allows you to view the item you select in either the ToDo\n"
-#~ "or Appointment panel.\n"
-#~ "\n"
-#~ "This is usefull when an event description is longer than the available\n"
-#~ "space to display it. If that is the case, the description will be\n"
-#~ "shortened and its end replaced by '...'. To be able to read the entire\n"
-#~ "description, just press 'V' and a popup window will appear, containing\n"
-#~ "the whole event.\n"
-#~ "\n"
-#~ "Press any key to close the popup window and go back to the main\n"
-#~ "Calcurse screen."
-
-#, fuzzy
-#~ msgid "Tab\n"
-#~ msgstr "Tab:\n"
-
-#, fuzzy
-#~ msgid ""
-#~ "Switch between panels.\n"
-#~ "The panel currently in use has its border colorized.\n"
-#~ "\n"
-#~ "Some actions are possible only if the right panel is selected.\n"
-#~ "For example, if you want to add a task in the TODO list, you need first\n"
-#~ "to press the '%s' key to get the TODO panel selected. Then you can\n"
-#~ "press '%s' to add your item.\n"
-#~ "\n"
-#~ "Notice that at the bottom of the screen the list of possible actions\n"
-#~ "change while pressing '%s', so you always know what action can be\n"
-#~ "performed on the selected panel."
-#~ msgstr ""
-#~ "Pressing 'Tab' allows you to switch between panels.\n"
-#~ "The panel currently in use has its border in colour.\n"
-#~ "\n"
-#~ "Some actions are possible only if the right panel is selected.\n"
-#~ "For example, if you want to add a task in the TODO list, you need first\n"
-#~ "to press the 'Tab' key to get the TODO panel selected. Then you can\n"
-#~ "press 'A' to add your item.\n"
-#~ "\n"
-#~ "Notice that at the bottom of the screen the list of possible actions\n"
-#~ "change while pressing 'Tab', so you always know what action can be\n"
-#~ "performed on the selected panel."
-
-#, fuzzy
-#~ msgid "Goto\n"
-#~ msgstr "Goto:\n"
-
-#, fuzzy
-#~ msgid ""
-#~ "Jump to a specific day in the calendar.\n"
-#~ "\n"
-#~ "Using this command, you do not need to travel to that day using\n"
-#~ "the displacement keys inside the calendar panel.\n"
-#~ "If you hit [ENTER] without specifying any date, Calcurse checks the\n"
-#~ "system current date and you will be taken to that date.\n"
-#~ "\n"
-#~ "Notice that pressing '%s', whatever panel is\n"
-#~ "selected, will select current day in the calendar."
-#~ msgstr ""
-#~ "Pressing 'G' allows you to jump to a specific day in the calendar.\n"
-#~ "\n"
-#~ "Using this command, you do not need to travel to that day using\n"
-#~ "the displacement keys inside the calendar panel.\n"
-#~ "If you hit [ENTER] without specifying any date, Calcurse checks the\n"
-#~ "system current date and you will be taken to that date."
-
-#, fuzzy
-#~ msgid "Delete\n"
-#~ msgstr "Delete:\n"
-
-#, fuzzy
-#~ msgid ""
-#~ "Delete an element in the ToDo or Appointment list.\n"
-#~ "\n"
-#~ "Depending on which panel is selected when you press the delete key,\n"
-#~ "the hilighted item of either the ToDo or Appointment list will be \n"
-#~ "removed from this list.\n"
-#~ "\n"
-#~ "If the item to be deleted is recurrent, you will be asked if you\n"
-#~ "wish to suppress all of the item occurences or just the one you\n"
-#~ "selected.\n"
-#~ "\n"
-#~ "If the general option 'confirm_delete' is set to 'YES', then you will\n"
-#~ "be asked for confirmation before deleting the selected event.\n"
-#~ "Do not forget to save the calendar data to retrieve the modifications\n"
-#~ "next time you launch Calcurse."
-#~ msgstr ""
-#~ "Pressing 'D' deletes an element in the ToDo or Appointment list.\n"
-#~ "\n"
-#~ "Depending on which panel is selected when you press the delete key,\n"
-#~ "the highlighted item of either the ToDo or Appointment list will be \n"
-#~ "removed from this list.\n"
-#~ "\n"
-#~ "If the general option 'confirm_delete' is set to 'YES', then you will\n"
-#~ "be asked for confirmation before deleting the selected event.\n"
-#~ "Do not forget to save the calendar data to retrieve the modifications\n"
-#~ "next time you launch Calcurse."
-
-#, fuzzy
-#~ msgid "Add\n"
-#~ msgstr "Add:\n"
-
-#, fuzzy
-#~ msgid ""
-#~ "Add an item in either the ToDo or Appointment list, depending on which\n"
-#~ "panel is selected when you press '%s'.\n"
-#~ "\n"
-#~ "To enter a new item in the TODO list, you will need first to enter the\n"
-#~ "description of this new item. Then you will be asked to specify the todo\n"
-#~ "priority. This priority is represented by a number going from 9 for the\n"
-#~ "lowest priority, to 1 for the highest one. It is still possible to\n"
-#~ "change the item priority afterwards, by using the '%s' and '%s' keys\n"
-#~ "inside the todo panel.\n"
-#~ "\n"
-#~ "If the APPOINTMENT panel is selected while pressing '%s', you will be\n"
-#~ "able to enter either a new appointment or a new all-day long event.\n"
-#~ "To enter a new event, press [ENTER] instead of the item start time, and\n"
-#~ "just fill in the event description.\n"
-#~ "To enter a new appointment to be added in the APPOINTMENT list, you\n"
-#~ "will need to enter successively the time at which the appointment\n"
-#~ "begins, the appointment length (either by specifying the end time in\n"
-#~ "[hh:mm] or the duration in [+hh:mm], [+xxdxxhxxm] or [+mm] format), \n"
-#~ "and the description of the event.\n"
-#~ "\n"
-#~ "The day at which occurs the event or appointment is the day currently\n"
-#~ "selected in the calendar, so you need to move to the desired day before\n"
-#~ "pressing '%s'.\n"
-#~ "\n"
-#~ "Notes:\n"
-#~ " o if an appointment lasts for such a long time that it continues\n"
-#~ " on the next days, this event will be indicated on all the\n"
-#~ " corresponding days, and the beginning or ending hour will be\n"
-#~ " replaced by '..' if the event does not begin or end on the day.\n"
-#~ " o if you only press [ENTER] at the APPOINTMENT or TODO event\n"
-#~ " description prompt, without any description, no item will be\n"
-#~ " added.\n"
-#~ " o do not forget to save the calendar data to retrieve the new\n"
-#~ " event next time you launch Calcurse."
-#~ msgstr ""
-#~ "Pressing 'A' allows you to add an item in either the ToDo or Appointment\n"
-#~ "list, depending on which panel is selected when you press 'A'.\n"
-#~ "\n"
-#~ "To enter a new item in the TODO list, you only need to enter the\n"
-#~ "description of this new item.\n"
-#~ "\n"
-#~ "If the APPOINTMENT panel is selected while pressing 'A', you will be\n"
-#~ "able to enter either a new appointment or a new all-day long event.\n"
-#~ "To enter a new event, press [ENTER] instead of the item start time, and\n"
-#~ "just fill in the event description.\n"
-#~ "To enter a new appointment to be added in the APPOINTMENT list, you\n"
-#~ "will need to enter successively the time at which the appointment\n"
-#~ "begins, the appointment length (either by specifying the duration in\n"
-#~ "minutes, or the end time in [hh:mm] or [h:mm] format), and the\n"
-#~ "description of the event.\n"
-#~ "\n"
-#~ "The day at which occurs the event or appointment is the day currently\n"
-#~ "selected in the calendar, so you need to move to the desired day before\n"
-#~ "pressing 'A'.\n"
-#~ "\n"
-#~ "Notes:\n"
-#~ " o if an appointment lasts for such a long time that it continues\n"
-#~ " into the next days, this event will be indicated on all the\n"
-#~ " corresponding days, and the beginning or ending hour will be\n"
-#~ " replaced by '..' if the event does not begin or end on the day.\n"
-#~ " o if you only press [ENTER] at the APPOINTMENT or TODO event\n"
-#~ " description prompt, without any description, no item will be\n"
-#~ " added.\n"
-#~ " o do not forget to save the calendar data to retrieve the new\n"
-#~ " event next time you launch Calcurse."
-
-#, fuzzy
-#~ msgid "Edit Item\n"
-#~ msgstr "Add Item"
-
-#, fuzzy
-#~ msgid "EditNote\n"
-#~ msgstr "Add Item"
-
-#, fuzzy
-#~ msgid "ViewNote\n"
-#~ msgstr "View:\n"
-
-#, fuzzy
-#~ msgid "Repeat\n"
-#~ msgstr "Redraw:\n"
-
-#, fuzzy
-#~ msgid "Flag Item\n"
-#~ msgstr "Add Item"
-
-#, fuzzy
-#~ msgid "Config\n"
-#~ msgstr "Config:\n"
-
-#, fuzzy
-#~ msgid ""
-#~ "Open the configuration submenu.\n"
-#~ "From this submenu, you can select between color, layout, notification\n"
-#~ "and general options, and you can also configure your keybindings.\n"
-#~ "\n"
-#~ "The color submenu lets you choose the color theme.\n"
-#~ "The layout submenu lets you choose the Calcurse screen layout, in other\n"
-#~ "words where to place the three different panels on the screen.\n"
-#~ "The general options submenu brings a screen with the different options\n"
-#~ "which modifies the way Calcurse interacts with the user.\n"
-#~ "The notify submenu allows you to change the notify-bar settings.\n"
-#~ "The keys submenu lets you define your own key bindings.\n"
-#~ "\n"
-#~ "Do not forget to save the calendar data to retrieve your configuration\n"
-#~ "next time you launch Calcurse."
-#~ msgstr ""
-#~ "Pressing 'C' leads to the configuration submenu, from which you can\n"
-#~ "select between colour, layout, and general options.\n"
-#~ "\n"
-#~ "The colour submenu lets you choose the colour theme.\n"
-#~ "\n"
-#~ "The layout submenu lets you choose the Calcurse screen layout, in other\n"
-#~ "words where to place the three different panels on the screen.\n"
-#~ "\n"
-#~ "The general options submenu brings a screen with the different options\n"
-#~ "which modifies the way Calcurse interacts with the user.\n"
-#~ "\n"
-#~ "Do not forget to save the calendar data to retrieve your configuration\n"
-#~ "next time you launch Calcurse."
-
-#~ msgid "Calcurse - text-based organizer"
-#~ msgstr "Calcurse - text-based organizer"
-
-#, fuzzy
-#~ msgid ""
-#~ "Enter end time ([hh:mm] or [hhmm]) or duration ([+hh:mm], [+xxxdxxhxxm] "
-#~ "or [+mm]) : "
-#~ msgstr "Enter end time ([hh:mm] or [h:mm]) or duration (in minutes) : "
-
-#, fuzzy
-#~ msgid "could not convert string"
-#~ msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-#~ msgid "ToDo"
-#~ msgstr "ToDo"
-
-#~ msgid "Appointment"
-#~ msgstr "Appointment"
-
-#, fuzzy
-#~ msgid "missing colors in config file"
-#~ msgstr "Failed to open config file"
-
-#~ msgid "auto_save = "
-#~ msgstr "auto_save = "
-
-#, fuzzy
-#~ msgid "periodic_save = "
-#~ msgstr "auto_save = "
-
-#~ msgid "confirm_quit = "
-#~ msgstr "confirm_quit = "
-
-#~ msgid "confirm_delete = "
-#~ msgstr "confirm_delete = "
-
-#~ msgid "skip_system_dialogs = "
-#~ msgstr "skip_system_dialogues = "
-
-#~ msgid "skip_progress_bar = "
-#~ msgstr "skip_progress_bar = "
-
-#~ msgid "week_begins_on_monday = "
-#~ msgstr "week_begins_on_monday = "
-
-#~ msgid ""
-#~ "(if set to YES, monday is the first day of the week, else it is sunday)"
-#~ msgstr ""
-#~ "(if set to YES, monday is the first day of the week, otherwise it is "
-#~ "sunday)"
-
-#, fuzzy
-#~ msgid "Week"
-#~ msgstr "-/+1 Week"
-
-#, fuzzy
-#~ msgid "could not find any key file."
-#~ msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-#, fuzzy
-#~ msgid "could not remove note"
-#~ msgstr "Enter description :"
-
-#~ msgid "Enter an option number to change its value [Q to quit] "
-#~ msgstr "Enter an option number to change its value [Q to quit] "
-
-#, fuzzy
-#~ msgid "CalCurse %s | notify-bar options"
-#~ msgstr "CalCurse %s | general options"
-
-#, fuzzy
-#~ msgid ""
-#~ "\n"
-#~ "Copyright (c) 2004-2008 Frederic Culot\n"
-#~ "\n"
-#~ "This program is free software; you can redistribute it and/or modify\n"
-#~ "it under the terms of the GNU General Public License as published by\n"
-#~ "the Free Software Foundation; either version 2 of the License, or\n"
-#~ "(at your option) any later version.\n"
-#~ "\n"
-#~ "This program is distributed in the hope that it will be useful,\n"
-#~ "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
-#~ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
-#~ "GNU General Public License for more details.\n"
-#~ "\n"
-#~ "\n"
-#~ "Send your feedback or comments to : misc@calcurse.org\n"
-#~ "Calcurse home page : http://calcurse.org"
-#~ msgstr ""
-#~ "Copyright (c) 2004-2006 Frederic Culot\n"
-#~ "\n"
-#~ "This program is free software; you can redistribute it and/or modify\n"
-#~ "it under the terms of the GNU General Public License as published by\n"
-#~ "the Free Software Foundation; either version 2 of the License, or\n"
-#~ "(at your option) any later version.\n"
-#~ "\n"
-#~ "This program is distributed in the hope that it will be useful,\n"
-#~ "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
-#~ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
-#~ "GNU General Public License for more details.\n"
-#~ "\n"
-#~ "\n"
-#~ "Send your feedback or comments to : misc@calcurse.org\n"
-#~ "Calcurse home page : http://calcurse.org"
-
-#~ msgid "Pick the desired layout on next screen [press ENTER]"
-#~ msgstr "Pick the desired layout on next screen [press ENTER]"
-
-#, fuzzy
-#~ msgid "('A'= Appointment panel, 'C'= calendar panel, 'T'= todo panel)"
-#~ msgstr "('A'= Appointment panel, 'c'= calendar panel, 't'= todo panel)"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in apoint_delete: no such type\n"
-#~ msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-#~ msgid "FATAL ERROR in apoint_scan: date error in the appointment\n"
-#~ msgstr "FATAL ERROR in apoint_scan: date error in the appointment\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in apoint_get: no such item\n"
-#~ msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in apoint_delete_bynum: no such appointment"
-#~ msgstr "FATAL ERROR in apoint_delete_bynum: no such appointment\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in apoint_switch_notify: no such appointment"
-#~ msgstr "FATAL ERROR in apoint_delete_bynum: no such appointment\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in custom_load_color: wrong color number.\n"
-#~ msgstr ""
-#~ "FATAL ERROR in fill_config_var: wrong configuration variable format.\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in custom_load_color: wrong color name.\n"
-#~ msgstr "FATAL ERROR in load_app: wrong format in the appointment or event\n"
-
-#, fuzzy
-#~ msgid ""
-#~ "FATAL ERROR in custom_load_color: wrong configuration variable format.\n"
-#~ msgstr ""
-#~ "FATAL ERROR in fill_config_var: wrong configuration variable format.\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in custom_color_theme_name: unknown color\n"
-#~ msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in day_popup_item: unknown item type\n"
-#~ msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in event_get: no such item\n"
-#~ msgstr "FATAL ERROR in event_delete_bynum: no such event\n"
-
-#~ msgid "FATAL ERROR in event_delete_bynum: no such event\n"
-#~ msgstr "FATAL ERROR in event_delete_bynum: no such event\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in foreach_date_dump: incoherent repetition type\n"
-#~ msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-#, fuzzy
-#~ msgid ""
-#~ "FATAL ERROR in pcal_export_recur_events: incoherent repetition type\n"
-#~ msgstr "FATAL ERROR in event_delete_bynum: no such event\n"
-
-#, fuzzy
-#~ msgid ""
-#~ "FATAL ERROR in pcal_export_recur_apoints: incoherent repetition type\n"
-#~ msgstr "FATAL ERROR in apoint_delete_bynum: no such appointment\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in io_export_data: wrong export mode\n"
-#~ msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in io_export_data: unknown export type\n"
-#~ msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in io_import_data: unknown import type"
-#~ msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in launch_cmd: could not launch user command"
-#~ msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in recur_def2char: unknown recur type\n"
-#~ msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in recur_char2def: unknown char\n"
-#~ msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in recur_event_scan: date error in the event\n"
-#~ msgstr "FATAL ERROR in event_scan: date error in the event\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in recur_item_inday: unknown item type\n"
-#~ msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in recur_event_erase: no such event\n"
-#~ msgstr "FATAL ERROR in event_delete_bynum: no such event\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in recur_apoint_erase: no such appointment\n"
-#~ msgstr "FATAL ERROR in apoint_delete_bynum: no such appointment\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in recur_repeat_item: wrong item type\n"
-#~ msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in recur_exc_scan: syntax error in the item date\n"
-#~ msgstr "FATAL ERROR in load_app: syntax error in the item date\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in recur_get_apoint: no such item\n"
-#~ msgstr "FATAL ERROR in apoint_delete_bynum: no such appointment\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in recur_get_event: no such item\n"
-#~ msgstr "FATAL ERROR in event_delete_bynum: no such event\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in recur_apoint_switch_notify: no such item\n"
-#~ msgstr "FATAL ERROR in apoint_delete_bynum: no such appointment\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in todo_delete_note_bynum: no note attached\n"
-#~ msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in todo_delete_note_bynum: no such todo\n"
-#~ msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-#~ msgid "FATAL ERROR in todo_delete_bynum: no such todo\n"
-#~ msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in todo_get_position: todo not found\n"
-#~ msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in todo_chg_priority: no such action\n"
-#~ msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-#~ msgid "FATAL ERROR in date2sec: failure in mktime\n"
-#~ msgstr "FATAL ERROR in date2sec: failure in mktime\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in date_sec_change: failure in mktime\n"
-#~ msgstr "FATAL ERROR in date2sec: failure in mktime\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in other_status_page: unknown panel\n"
-#~ msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in mystrtol: number is out of range"
-#~ msgstr "FATAL ERROR in update_windows: no window selected\n"
-
-#~ msgid "option not defined - Problem in print_option_incolor()"
-#~ msgstr "option not defined - Problem in print_option_incolor()"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in erase_note: could not remove note\n"
-#~ msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in wins_update: no window selected\n"
-#~ msgstr "FATAL ERROR in update_windows: no window selected\n"
-
-#, fuzzy
-#~ msgid ""
-#~ "You can use either 'H','J','K','L' or the arrow keys '<','v','^','>'\n"
-#~ "to move into the calendar.\n"
-#~ "\n"
-#~ "The following scheme explains how :\n"
-#~ "\n"
-#~ " move to previous week\n"
-#~ " K ^ \n"
-#~ " move to previous day H < > L move to next day\n"
-#~ " J v \n"
-#~ " move to next week\n"
-#~ "\n"
-#~ "Moreover, while inside the calendar panel, the '0' (zero) key moves\n"
-#~ "to the first day of the week, and the '$' key selects the last day of\n"
-#~ "the week.\n"
-#~ "\n"
-#~ "When the Appointment or ToDo panel is selected, the up and down keys\n"
-#~ "(respectively K or up arrow, and J or down arrow) allows you to select\n"
-#~ "an item from those lists."
-#~ msgstr ""
-#~ "You can use either 'H','J','K','L' or the arrow keys '<','v','^','>'\n"
-#~ "to move into the calendar.\n"
-#~ "\n"
-#~ "The following scheme explains how :\n"
-#~ "\n"
-#~ " move to previous week\n"
-#~ " K ^ \n"
-#~ " move to previous day H < > L move to next day\n"
-#~ " J v \n"
-#~ " move to next week\n"
-#~ "\n"
-#~ "When the Appointment or ToDo panel is selected, the up and down keys\n"
-#~ "(respectively K or up arrow, and J or down arrow) allows you to select\n"
-#~ "an item from those lists."
-
-#~ msgid "CalCurse %s | help"
-#~ msgstr "CalCurse %s | help"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in wins_prop: property unknown\n"
-#~ msgstr "FATAL ERROR in todo_delete_bynum: no such todo\n"
-
-#~ msgid ""
-#~ "Please resize your terminal screen\n"
-#~ "(to at least 80x24),\n"
-#~ "and restart calcurse.\n"
-#~ msgstr ""
-#~ "Please resize your terminal screen\n"
-#~ "(to at least 80x24),\n"
-#~ "and restart calcurse.\n"
-
-#, fuzzy
-#~ msgid "FATAL ERROR in update_time_in_date: failure in mktime\n"
-#~ msgstr "FATAL ERROR in date2sec: failure in mktime\n"
-
-#~ msgid "Pick the number corresponding to the color scheme (Q to exit) :"
-#~ msgstr "Pick the number corresponding to the colour scheme (Q to exit) :"
-
-#~ msgid "([>0<] for black & white)"
-#~ msgstr "([>0<] for black & white)"
-
-#~ msgid "-- Press 'N' for next page --"
-#~ msgstr "-- Press 'N' for next page --"
-
-#~ msgid "-- Press 'P' for previous page --"
-#~ msgstr "-- Press 'P' for previous page --"
-
-#~ msgid " |Ac| |At| |cA| |tA|"
-#~ msgstr " |Ac| |At| |cA| |tA|"
-
-#~ msgid "[1]|At| [2]|Ac| [3]|tA| [4]|cA|"
-#~ msgstr "[1]|At| [2]|Ac| [3]|tA| [4]|cA|"
-
-#~ msgid "Redraw:\n"
-#~ msgstr "Redraw:\n"
-
-#, fuzzy
-#~ msgid ""
-#~ "Pressing CTRL-L redraws the Calcurse panels.\n"
-#~ "\n"
-#~ "You might want to use this function when you resize your terminal\n"
-#~ "screen for example, and you want Calcurse to take into account the new\n"
-#~ "size of the terminal.\n"
-#~ "\n"
-#~ "This function can also be useful when garbage appears in the display,\n"
-#~ "and you want to clean it."
-#~ msgstr ""
-#~ "Pressing 'R' redraws the Calcurse panels.\n"
-#~ "\n"
-#~ "You might want to use this function when you resize your terminal\n"
-#~ "screen for example, and you want Calcurse to take into account the new\n"
-#~ "size of the terminal.\n"
-#~ "\n"
-#~ "This function can also be useful when garbage appears in the display,\n"
-#~ "and you want to clear it."
-
-#~ msgid "GoTo"
-#~ msgstr "GoTo"
diff --git a/po/es.po b/po/es.po
index 21b44af..c15fa5b 100644
--- a/po/es.po
+++ b/po/es.po
@@ -1,6 +1,6 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR calcurse Development Team <misc@calcurse.org>
-# This file is distributed under the same license as the PACKAGE package.
+# This file is distributed under the same license as the calcurse package.
#
# Translators:
# Emmanuel M <emmanuelbendavid@gmail.com>, 2017
@@ -12,20 +12,27 @@ msgid ""
msgstr ""
"Project-Id-Version: calcurse\n"
"Report-Msgid-Bugs-To: bugs@calcurse.org\n"
-"POT-Creation-Date: 2019-06-16 15:27-0400\n"
-"PO-Revision-Date: 2019-05-30 11:52+0000\n"
-"Last-Translator: Lukas Fleischer\n"
-"Language-Team: Spanish (http://www.transifex.com/lfleischer/calcurse/"
+"POT-Creation-Date: 2024-01-26 18:28+0100\n"
+"PO-Revision-Date: 2013-07-23 08:43+0000\n"
+"Last-Translator: Victorhck <victorhck@opensuse.org>, 2018\n"
+"Language-Team: Spanish (http://app.transifex.com/lfleischer/calcurse/"
"language/es/)\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? "
+"1 : 2;\n"
msgid "null pointer"
msgstr "puntero nulo"
+msgid "illegal date in appointment"
+msgstr ""
+
+msgid "error in appointment description"
+msgstr ""
+
msgid "date error in appointment"
msgstr "error en la fecha de la cita"
@@ -38,7 +45,7 @@ msgid ""
"calcurse -Q [--from <date>] [--to <date>] [--days <number>]\n"
"calcurse -a | -d <date> | -d <number> | -n | -r[<number>] | -s[<date>] | -"
"t[<number>]\n"
-"calcurse -h | -v | --status | -G | -P | -g | -i <file> | -x[<file>] | --"
+"calcurse -h | -v | --status | -G | -P | -g | -i <file> | -x[<format>] | --"
"daemon"
msgstr ""
@@ -49,8 +56,8 @@ msgstr "Consulte `calcurse -h` para más información."
msgid "calcurse %s -- text-based organizer\n"
msgstr "calcurse %s -- organizador basado en texto\n"
-msgid "Copyright (c) 2004-2017 calcurse Development Team."
-msgstr "Copyright (c) 2004-2017 Equipo de desarrollo de calcurse."
+msgid "Copyright (c) 2004-2023 calcurse Development Team."
+msgstr ""
msgid "This is free software; see the source for copying conditions."
msgstr ""
@@ -128,7 +135,7 @@ msgstr ""
msgid " -i, --import <file> Import iCal data from file"
msgstr ""
-msgid " -q, --quiet Suppress system dialogs"
+msgid " -q, --quiet Suppress import/export result message"
msgstr ""
msgid " --read-only Do not save configuration or data files"
@@ -283,7 +290,7 @@ msgstr ""
msgid "Do you really want to quit?"
msgstr "¿Está seguro de que quiere salir?"
-msgid "Command: [ h(elp) | w(rite)(!) | q(uit)(!) | wq(!) ]"
+msgid "Command: [ h(elp) | w(rite)(!) | q(uit)(!) | wq(!) | n(ext) | p(rev) ]"
msgstr ""
msgid "Read-only mode - use w!"
@@ -296,6 +303,18 @@ msgstr ""
msgid "Help topic does not exist: %s"
msgstr "El tema de ayuda no existe: %s"
+msgid "Select a repeating item in the appointments panel."
+msgstr ""
+
+msgid "Not a repeating item."
+msgstr ""
+
+msgid "Last occurrence."
+msgstr ""
+
+msgid "First occurrence."
+msgstr ""
+
#, c-format
msgid "No such command: %s"
msgstr "No existe el comando: %s"
@@ -393,6 +412,9 @@ msgstr ""
msgid "(insert an empty line after each appointment)"
msgstr ""
+msgid "(text for a day without events and appointments)"
+msgstr ""
+
msgid "(display more than one day in the appointments panel)"
msgstr ""
@@ -417,16 +439,6 @@ msgid "(if set to YES, confirmation is required before deleting an event)"
msgstr ""
"(si se le asigna YES, se requiere confirmación antes de borrar un evento)"
-msgid "(if set to YES, messages about loaded and saved data will be displayed)"
-msgstr ""
-"(si se le asigna YES, se mostraran mensajes sobre datos leídos y guardados)"
-
-msgid "Monday"
-msgstr "Lunes"
-
-msgid "Sunday"
-msgstr "Domingo"
-
msgid "(specifies the first day of week in the calendar view)"
msgstr "(especifica el primer día de la semana en la vista de calendario)"
@@ -451,11 +463,22 @@ msgstr "(posición de la cabecera en el panel de citas)"
msgid "(Format of the date displayed in the appointments panel)"
msgstr "(Formato de la fecha mostrado en el panel de citas)"
+msgid "(Format of the time displayed in the appointments panel)"
+msgstr ""
+
+msgid "Enter a text string (an empty string for the default text)"
+msgstr ""
+
msgid "Enter the date format (see 'man 3 strftime' for possible formats) "
msgstr ""
"Ingrese el formato de la fecha (ver 'man 3 strftime' para los formatos "
"posibles) "
+msgid "Enter the time format (see 'man 3 strftime' for possible formats) "
+msgstr ""
+"Introduzca el formato de la hora (ver 'man 3 strftime' para los formatos "
+"posibles) "
+
msgid "Enter the date format: "
msgstr "Ingrese el formato de fecha:"
@@ -470,8 +493,8 @@ msgstr "opciones generales"
msgid "Undefined option!"
msgstr "¡Opción no definida!"
-msgid "undefined"
-msgstr "sin definir"
+msgid "UNDEFINED"
+msgstr ""
msgid "keys configuration"
msgstr "configuración de teclas"
@@ -483,8 +506,8 @@ msgstr "Presione la tecla que quiere asignarle a:"
msgid "The key '%s' is already used for %s. Choose another one."
msgstr "La tecla '%s' ya está en uso por %s. Elija otra."
-msgid "Some actions do not have any associated key bindings!"
-msgstr "¡Algunas acciones no tienen ninguna tecla asociada!"
+msgid "Some actions are left undefined!"
+msgstr ""
msgid ""
"Sorry, colors are not supported by your terminal\n"
@@ -500,7 +523,7 @@ msgstr ""
msgid "unknown item type"
msgstr "tipo de elemento desconocido"
-msgid "(none)"
+msgid "Note:"
msgstr ""
msgid "Event:"
@@ -562,6 +585,7 @@ msgid "sleeping at %s for %d second\n"
msgid_plural "sleeping at %s for %d seconds\n"
msgstr[0] "durmiendo en %s por %d segundo\n"
msgstr[1] "durmiendo en %s por %d segundos\n"
+msgstr[2] "durmiendo en %s por %d segundos\n"
#, c-format
msgid "awakened at %s\n"
@@ -571,11 +595,11 @@ msgstr "despertado %s\n"
msgid "Could not stop calcurse daemon: %s\n"
msgstr "No pudo detenerse el demonio de calcurse: %s\n"
-msgid "date error in event"
-msgstr "error de fecha en evento"
+msgid "illegal date in event"
+msgstr ""
-msgid "date error in the event\n"
-msgstr "error de fecha en el evento\n"
+msgid "date error in event\n"
+msgstr ""
msgid "Internal error: line too long"
msgstr "Error interno: línea demasiado larga"
@@ -586,56 +610,139 @@ msgstr "memoria agotada"
msgid "unknown ical type"
msgstr "tipo ical desconocido"
-msgid "recurrence rule malformed."
-msgstr "regla de recurrencia mal formada"
+msgid "(empty)"
+msgstr ""
-msgid "recurrence frequency not found."
-msgstr "frecuencia recurrente no encontrada."
+msgid "ical_store_event: out of memory"
+msgstr ""
-msgid "recurrence frequency not recognized."
-msgstr "frecuencia recurrente no reconocida."
+msgid "need DTSTART to determine event type."
+msgstr ""
-msgid "recurrence exception dates malformed."
-msgstr "excepción de recurrencia mal formada."
+msgid "malformed recurrence line."
+msgstr ""
-msgid "description malformed."
-msgstr "descripción mal formada."
+msgid "frequency not set in rrule."
+msgstr ""
-msgid "could not get entire item description."
-msgstr "no se pudo obtener la descripción completa del elemento."
+msgid "frequency absent in rrule."
+msgstr ""
-msgid "could not retrieve item summary."
-msgstr "no se pudo recuperar el resumen del elemento."
+msgid "rrule frequency not supported."
+msgstr ""
-msgid "item start date is not defined."
-msgstr "la fecha de comienzo del elemento no está definida."
+msgid "invalid interval."
+msgstr ""
-msgid "item has a negative duration."
-msgstr "el elemento tiene una duración negativa."
+msgid "either until or count."
+msgstr ""
-msgid "item could not be identified."
-msgstr "el elemento no pudo ser identificado."
+msgid "missing until value."
+msgstr ""
+
+msgid "invalid until format."
+msgstr ""
+
+msgid "invalid count value."
+msgstr ""
+
+msgid "invalid bymonth list."
+msgstr ""
+
+msgid "invalid bymonthday list."
+msgstr ""
+
+msgid "invalid byday list."
+msgstr ""
+
+msgid "invalid exception date value type."
+msgstr ""
+
+msgid "malformed exceptions line."
+msgstr ""
+
+msgid "invalid exception."
+msgstr ""
-msgid "event start time malformed."
-msgstr "fecha de comienzo del evento mal formada."
+#, c-format
+msgid "malformed %s line."
+msgstr ""
-msgid "could not retrieve event start time."
-msgstr "no se pudo recuperar la fecha de comienzo del evento."
+#, c-format
+msgid "malformed %s."
+msgstr ""
-msgid "event end time malformed."
-msgstr "fecha de finalización del evento mal formada."
+msgid "malformed summary line."
+msgstr ""
+
+msgid "malformed summary."
+msgstr ""
-msgid "could not retrieve event end time."
-msgstr "no se pudo recuperar la fecha de finalización del evento."
+msgid "item start date not defined."
+msgstr ""
+
+msgid "malformed start time line."
+msgstr ""
+
+msgid "invalid or malformed event start time."
+msgstr ""
+
+msgid "invalid end time value type."
+msgstr ""
+
+msgid "malformed end time line."
+msgstr ""
-msgid "item duration malformed."
-msgstr "duración del elemento mal formada."
+msgid "malformed event end time."
+msgstr ""
+
+msgid "end must be later than start."
+msgstr ""
+
+msgid "either end or duration."
+msgstr ""
+
+msgid "malformed duration line."
+msgstr ""
+
+msgid "invalid duration."
+msgstr ""
+
+msgid "exception date, but no recurrence rule."
+msgstr ""
+
+msgid "multi-day event changed to one-day event"
+msgstr ""
+
+#, c-format
+msgid "Location: %s"
+msgstr ""
+
+#, c-format
+msgid "Comment: %s"
+msgstr ""
+
+#, c-format
+msgid "rrule does not match start day (%s)."
+msgstr ""
+
+msgid "item could not be identified."
+msgstr "el elemento no pudo ser identificado."
+
+msgid "only one description allowed."
+msgstr ""
+
+msgid "only one location allowed."
+msgstr ""
msgid "The ical file seems to be malformed. The end of item was not found."
msgstr ""
"El archivo ical parece estar mal formado. No se pudo encontrar el fin del "
"elemento."
+msgid "could not retrieve item summary."
+msgstr "no se pudo recuperar el resumen del elemento."
+
msgid "item priority is invalid (must be between 0 and 9)."
msgstr "La prioridad del elemento es inválida (debe estar entre 0 y 9)."
@@ -708,6 +815,21 @@ msgstr "formato inválido en la cita o evento"
msgid "syntax error in item repetition"
msgstr "error de sintaxis en el valor de repetición del elemento"
+msgid "syntax error in until date"
+msgstr ""
+
+msgid "until date error"
+msgstr ""
+
+msgid "BYMONTHDAY illegal with WEEKLY"
+msgstr ""
+
+msgid "missing end of recurrence"
+msgstr ""
+
+msgid "syntax error in item state"
+msgstr ""
+
msgid "failed to open todo file"
msgstr "No pudo abrirse archivo de tareas"
@@ -717,54 +839,49 @@ msgstr ""
msgid "failed to open key file"
msgstr "no pudo abrirse el archivo de teclas"
-msgid ""
-"\n"
-"Too many errors while reading configuration file!\n"
-"Please backup your keys file, remove it from directory, and launch calcurse "
-"again.\n"
-msgstr ""
-"\n"
-"¡Demasiados errores al leer el archivo de configuración!\n"
-"Por favor respalde el archivo de teclas, elimínelo del directorio y vuelva a "
-"iniciar calcurse.\n"
-
msgid "Could not read key label"
msgstr "No se pudo leer etiqueta de tecla"
-msgid "Key label not recognized"
-msgstr "Etiqueta de tecla no reconocida"
-
#, c-format
-msgid "Error reading key: \"%s\""
-msgstr "Error leyendo tecla: \"%s\""
+msgid "Key label not recognized: \"%s\""
+msgstr ""
#, c-format
-msgid "\"%s\" assigned multiple times!"
-msgstr "¡\"%s\" asignado múltiples veces!"
+msgid "No keys assigned to \"%s\"."
+msgstr ""
-msgid "There were some errors when loading keys file."
+#, c-format
+msgid "Keyname not recognized: \"%s\""
msgstr ""
-msgid "Too many errors while reading keys file, aborting..."
-msgstr "Demasiados errores al leer archivo de teclas, abortando..."
+#, c-format
+msgid "\"%s\" assigned twice: \"%s\"."
+msgstr ""
#, c-format
-msgid "FATAL ERROR: could not create %s: %s\n"
-msgstr "ERROR FATAL: no pudo crearse %s: %s\n"
+msgid ""
+"Action \"%s\" absent, but default key \"%s\" assigned to another action."
+msgstr ""
-msgid "Press [ENTER] to continue"
-msgstr "Pulse [INTRO] para continuar"
+msgid "Errors in the keys file."
+msgstr ""
-msgid "Welcome to Calcurse. Missing data files were created."
+msgid "Remove offending line(s) from the keys file, aborting..."
msgstr ""
-"Bienvenido/a a calcurse. Se crearon los archivos de datos que faltaban."
-msgid "Data files found. Data will be loaded now."
-msgstr "Archivos de datos encontrados. Ahora se cargaran los datos."
+msgid "Some actions do not have any associated key bindings!"
+msgstr "¡Algunas acciones no tienen ninguna tecla asociada!"
+
+#, c-format
+msgid "FATAL ERROR: could not create %s: %s\n"
+msgstr "ERROR FATAL: no pudo crearse %s: %s\n"
msgid "The data were successfully exported"
msgstr "Los datos se han exportado correctamente"
+msgid "Press [ENTER] to continue"
+msgstr "Pulse [INTRO] para continuar"
+
msgid "unknown export type"
msgstr "tipo de exportación desconocido"
@@ -792,18 +909,21 @@ msgid "%d app"
msgid_plural "%d apps"
msgstr[0] "%d app"
msgstr[1] "%d apps"
+msgstr[2] "%d apps"
#, c-format
msgid "%d event"
msgid_plural "%d events"
msgstr[0] "%d evento"
msgstr[1] "%d eventos"
+msgstr[2] "%d eventos"
#, c-format
msgid "%d todo"
msgid_plural "%d todos"
msgstr[0] "%d tarea"
msgstr[1] "%d tareas"
+msgstr[2] "%d tareas"
#, c-format
msgid "%d skipped"
@@ -839,7 +959,9 @@ msgstr ""
msgid "Invalid delay"
msgstr "Demora inválida"
-msgid "Periodic save: data files have changed. Save cancelled."
+msgid ""
+"Periodic save cancelled. Data files have changed. Save and merge "
+"interactively"
msgstr ""
#, c-format
@@ -886,6 +1008,9 @@ msgstr "Pegar"
msgid "Chg Win"
msgstr "CmbVent"
+msgid "Prev Win"
+msgstr ""
+
msgid "Import"
msgstr "Importar"
@@ -1073,6 +1198,9 @@ msgstr "Pegar un elemento en la posición actual."
msgid "Select next panel in calcurse main screen."
msgstr "Seleccionar el panel siguiente en la pantalla principal de calcurse."
+msgid "Select previous panel in calcurse main screen."
+msgstr ""
+
msgid "Import data from an external file."
msgstr "Importar datos desde un archivo externo."
@@ -1216,9 +1344,8 @@ msgid "FATAL ERROR: null file pointer."
msgstr "ERROR FATAL: puntero nulo a archivo."
#, c-format
-msgid "When adding default key for \"%s\", \"%s\" was already assigned!"
+msgid "Default key(s) assigned to %d action%s."
msgstr ""
-"Al añadir la tecla por defecto para \"%s\", ¡\"%s\" ya estaba asignada!!"
msgid "xmalloc: zero size"
msgstr "xmalloc: tamaño cero"
@@ -1310,12 +1437,6 @@ msgstr " bloques sin liberar: %u\n"
msgid "Warning: could not open %s, Aborting..."
msgstr "Advertencia: no pudo abrirse %s. Abortando..."
-msgid "error while launching command: could not fork"
-msgstr "error al lanzar comando: no pudo realizarse fork"
-
-msgid "error while launching command"
-msgstr "error al lanzar comando"
-
msgid "(if set to YES, notify-bar will be displayed)"
msgstr "(si selecciona SÃ, se mostrará la barra de notificaciones)"
@@ -1343,11 +1464,6 @@ msgstr ""
msgid "(Log activity when running in background)"
msgstr "(Registrar actividad al ejecutar en segundo plano)"
-msgid "Enter the time format (see 'man 3 strftime' for possible formats) "
-msgstr ""
-"Introduzca el formato de la hora (ver 'man 3 strftime' para los formatos "
-"posibles) "
-
msgid "Enter the number of seconds (0 not to be warned before an appointment)"
msgstr ""
"Introduzca el número de segundos (con 0 no se avisará antes de una cita)"
@@ -1364,18 +1480,46 @@ msgstr "tipo de repetición incoherente"
msgid "System event"
msgstr ""
-msgid "unknown repetition type"
-msgstr "tipo de repetición desconocido"
-
msgid "unknown character"
msgstr "carácter inválido"
+#, c-format
+msgid "recurrence error: not on start day (%s)"
+msgstr ""
+
+msgid "illegel date in event"
+msgstr ""
+
+msgid "date error in event"
+msgstr "error de fecha en evento"
+
+msgid "month day is zero"
+msgstr ""
+
+msgid "no daily frequency check"
+msgstr ""
+
+msgid "illegal BYDAY value"
+msgstr ""
+
msgid "event not found"
msgstr "evento no encontrado"
msgid "appointment not found"
msgstr "cita no encontrada"
+msgid "syntax error in bymonthday"
+msgstr ""
+
+msgid "syntax error in bywday"
+msgstr ""
+
+msgid "syntax error in bymonth"
+msgstr ""
+
+msgid "illegal bymonth value"
+msgstr ""
+
msgid "syntax error in item date"
msgstr "error de sintaxis en la fecha del elemento"
@@ -1383,10 +1527,6 @@ msgid "date error in item exception"
msgstr "error en la fecha de la excepción del elemento"
#, c-format
-msgid "Could not remove calcurse lock file: %s\n"
-msgstr "No pudo borrarse el archivo lock de calcurse: %s\n"
-
-#, c-format
msgid "Error setting signal #%d : %s\n"
msgstr "Error fijando señal #%d : %s\n"
@@ -1423,6 +1563,10 @@ msgstr ""
msgid "Invalid time: start time must come before end time!"
msgstr ""
+#, c-format
+msgid "Repetition must begin on start day (%s)."
+msgstr ""
+
msgid "Enter end date (and/or time) or duration ('?' for input formats):"
msgstr ""
@@ -1448,51 +1592,111 @@ msgstr ""
msgid "Invalid date format - try again:."
msgstr ""
-msgid "Enter the new repetition type:"
-msgstr "Ingrese el tipo de repetición:"
+msgid "Limit repetition to listed days."
+msgstr ""
+
+msgid "Expand repetition to listed days."
+msgstr ""
-msgid "(d)aily"
-msgstr "(d)iario"
+msgid "Expand repetition to listed days, either all or 1st, 2nd, ... of month."
+msgstr ""
-msgid "(w)eekly"
-msgstr "semanal (w)"
+msgid "Note: limit to monthdays, if any."
+msgstr ""
-msgid "(m)onthly"
-msgstr "(m)ensual"
+msgid "Expand repetition to listed days, either all or 1st, 2nd, ... of year."
+msgstr ""
-msgid "(y)early"
-msgstr "anual (y)"
+msgid "Note: expand to listed months, if any; limit to monthdays, if any."
+msgstr ""
+
+msgid "Limit repetition to listed months."
+msgstr ""
+
+msgid "Expand repetition to listed months."
+msgstr ""
+
+msgid "Limit repetition to listed days of month."
+msgstr ""
+
+msgid "Expand repetition to listed days of month."
+msgstr ""
#, c-format
-msgid "(currently using %s)"
-msgstr "(actualmente utilizando %s)"
+msgid "Weekdays %s|..|%s, space-separated list, '?' for help:"
+msgstr ""
+
+#, c-format
+msgid ""
+"Weekdays [n]%s|..|[n]%s, space-separated list, n=1,-1,..,5,-5, '?' for help:"
+msgstr ""
+
+#, c-format
+msgid ""
+"Weekdays [n]%s|..|[n]%s, space-separated list, n=1,-1,..,53,-53, '?' for "
+"help:"
+msgstr ""
+
+msgid "Months 1|..|12, space-separated list, '?' for help:"
+msgstr ""
+
+msgid "Monthdays 1|..|31 or -1|..|-31, space-separated list, '?' for help:"
+msgstr ""
+
+msgid "Invalid format - try again."
+msgstr ""
+
+msgid "Press any key to continue."
+msgstr ""
+
+msgid "Base period:"
+msgstr ""
+
+msgid "day"
+msgstr ""
+
+msgid "week"
+msgstr ""
+
+msgid "month"
+msgstr ""
+
+msgid "year"
+msgstr ""
msgid "[dwmy]"
msgstr "[dwmy]"
+msgid "Frequency:"
+msgstr ""
+
msgid "Invalid frequency."
msgstr "Frecuencia inválida."
-msgid "Enter the repetition frequency:"
-msgstr "Introduzca la frecuencia de repetición:"
-
-msgid "Enter end date or duration ('?' for input formats):"
+msgid "Until date, increment or repeat count ('?' for input formats):"
msgstr ""
#, c-format
-msgid "Date: %s (year or month may be omitted). Endless duration: 0."
+msgid "Date: %s (year, month may be omitted, endless: 0)."
msgstr ""
-msgid "Duration in days: +dd. Duration in weeks and days: +??w??d."
+msgid "Increment: +?? (days) or: +??w??d (weeks). Repeat count: #?? (number)."
msgstr ""
#, c-format
-msgid "Invalid date: end date must come after start date (%s)."
+msgid "Invalid date: until date must come after start date (%s)."
msgstr ""
msgid "Invalid date."
msgstr ""
+msgid "Repeat count is too big."
+msgstr ""
+
+#, c-format
+msgid "Repetition must begin on start day (%s); any change discarded."
+msgstr ""
+
msgid "Description"
msgstr "Descripción"
@@ -1533,36 +1737,40 @@ msgstr ""
msgid "Invalid start time."
msgstr ""
-msgid "Do you really want to delete this item?"
-msgstr "¿Quiere eliminar este elemento?"
+msgid ""
+"This item is recurrent and has a note attached to it. Delete (s)elected "
+"occurrence, (a)ll occurrences, or just its (n)ote?"
+msgstr ""
+
+msgid "[san]"
+msgstr ""
-msgid "This item is recurrent. Delete (a)ll occurences or just this (o)ne?"
+msgid ""
+"This item has a note attached to it. Delete (s)elected occurrence or just "
+"its (n)ote?"
msgstr ""
-"Este elemento es recurrente. ¿Eliminar tod(a)s las ocurrencias o sól(o) ésta?"
-msgid "[ao]"
-msgstr "[ao]"
+msgid "[sn]"
+msgstr ""
-msgid "This item has a note attached to it. Delete (i)tem or just its (n)ote?"
+msgid ""
+"This item is recurrent. Delete (s)elected occurrence or (a)ll occurrences?"
msgstr ""
-"Este elemento tiene una nota adjunta. ¿Eliminar el elemento m(i)smo o sólo "
-"su (n)ota?"
-msgid "[in]"
-msgstr "[in]"
+msgid "[sa]"
+msgstr ""
-msgid "Enter the repetition type:"
-msgstr "Ingrese el tipo de repetición:"
+msgid "Confirm deletion. Delete (s)elected occurrence? Press (s) to confirm."
+msgstr ""
-#, c-format
-msgid "Date: %s (year or month may be omitted). Endless duration: '0'."
+msgid "[s]"
msgstr ""
-msgid "This item is already a repeated one."
-msgstr "Este elemento es ya un elemento repetido."
+msgid "Already repeated."
+msgstr ""
-msgid "wrong item type"
-msgstr "tipo de elemento inválido"
+msgid "A (s)imple or (a)dvanced repetition?"
+msgstr ""
msgid "Enter the new TODO item:"
msgstr "Ingrese la nueva tarea:"
@@ -1587,6 +1795,10 @@ msgstr "Ingrese la descripción de la nueva tarea:"
msgid "TODO:"
msgstr "PENDIENTE:"
+#, c-format
+msgid "Could not remove calcurse lock file: %s\n"
+msgstr "No pudo borrarse el archivo lock de calcurse: %s\n"
+
msgid "/!\\ INTERNAL ERROR /!\\"
msgstr "/!\\ ERROR INTERNO /!\\"
@@ -1645,13 +1857,9 @@ msgstr "Uso: calcurse-upgrade [-h|-v|--config <file>]"
msgid ""
"\n"
-"Copyright (c) 2004-2017 calcurse Development Team.\n"
+"Copyright (c) 2004-2023 calcurse Development Team.\n"
"This is free software; see the source for copying conditions.\n"
msgstr ""
-"\n"
-"Copyright (c) 2004-2017 Equipo de desarrollo de calcurse. \n"
-"Esto es software libre; consulte el código fuente para las condiciones de "
-"copia.\n"
msgid "unrecognized option:"
msgstr "opción no reconocida:"
diff --git a/po/fr.po b/po/fr.po
index 1ac87e6..4af80ea 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -1,12 +1,12 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR calcurse Development Team <misc@calcurse.org>
-# This file is distributed under the same license as the PACKAGE package.
+# This file is distributed under the same license as the calcurse package.
#
# Translators:
# esaule <godrik@mandragor.org>, 2011
# Gwendal Rogel <pythot@yahoo.fr>, 2018-2019
# Lukas Fleischer <transifex@cryptocrack.de>, 2011
-# lkppo, 2012
+# 4a14a73d523224463300dea5e0502458_3dab472, 2012
# SubS0, 2017
# tikismoke <webmaster@tikijs.dyndns.org>, 2014
# zorun <zerstorer@free.fr>, 2012
@@ -14,20 +14,27 @@ msgid ""
msgstr ""
"Project-Id-Version: calcurse\n"
"Report-Msgid-Bugs-To: bugs@calcurse.org\n"
-"POT-Creation-Date: 2019-06-16 15:27-0400\n"
-"PO-Revision-Date: 2019-05-30 11:52+0000\n"
-"Last-Translator: Lukas Fleischer\n"
-"Language-Team: French (http://www.transifex.com/lfleischer/calcurse/language/"
+"POT-Creation-Date: 2024-01-26 18:28+0100\n"
+"PO-Revision-Date: 2013-07-23 08:43+0000\n"
+"Last-Translator: Gwendal Rogel <pythot@yahoo.fr>, 2018-2019\n"
+"Language-Team: French (http://app.transifex.com/lfleischer/calcurse/language/"
"fr/)\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % "
+"1000000 == 0 ? 1 : 2;\n"
msgid "null pointer"
msgstr "Pointeur nul"
+msgid "illegal date in appointment"
+msgstr ""
+
+msgid "error in appointment description"
+msgstr ""
+
msgid "date error in appointment"
msgstr "erreur de date sur ce rendez-vous"
@@ -40,16 +47,9 @@ msgid ""
"calcurse -Q [--from <date>] [--to <date>] [--days <number>]\n"
"calcurse -a | -d <date> | -d <number> | -n | -r[<number>] | -s[<date>] | -"
"t[<number>]\n"
-"calcurse -h | -v | --status | -G | -P | -g | -i <file> | -x[<file>] | --"
+"calcurse -h | -v | --status | -G | -P | -g | -i <file> | -x[<format>] | --"
"daemon"
msgstr ""
-"Usage :\n"
-"calcurse [-D <directory>] [-C <directory>] [-c <calendar file>]\n"
-"calcurse -Q [--from <date>] [--to <date>] [--days <number>]\n"
-"calcurse -a | -d <date> | -d <number> | -n | -r[<number>] | -s[<date>] | -"
-"t[<number>]\n"
-"calcurse -h | -v | --status | -G | -P | -g | -i <file> | -x[<file>] | --"
-"daemon"
msgid "Try `calcurse -h` for more information."
msgstr "Tapez `calcurse -h` pour plus d'informations"
@@ -58,9 +58,8 @@ msgstr "Tapez `calcurse -h` pour plus d'informations"
msgid "calcurse %s -- text-based organizer\n"
msgstr "calcurse %s -- organiseur en mode texte\n"
-msgid "Copyright (c) 2004-2017 calcurse Development Team."
+msgid "Copyright (c) 2004-2023 calcurse Development Team."
msgstr ""
-"(c) 2004-2017. L'équipe de développement de calcurse. Tous droits réservés."
msgid "This is free software; see the source for copying conditions."
msgstr ""
@@ -144,8 +143,8 @@ msgstr " -h, --help Affiche cette aide"
msgid " -i, --import <file> Import iCal data from file"
msgstr " -i, --import <file> Importe des données iCal depuis le fichier"
-msgid " -q, --quiet Suppress system dialogs"
-msgstr " -q, --quiet Supprime les messages système"
+msgid " -q, --quiet Suppress import/export result message"
+msgstr ""
msgid " --read-only Do not save configuration or data files"
msgstr ""
@@ -305,8 +304,8 @@ msgstr ""
msgid "Do you really want to quit?"
msgstr "Voulez-vous vraiment quitter?"
-msgid "Command: [ h(elp) | w(rite)(!) | q(uit)(!) | wq(!) ]"
-msgstr "Commande : [ h (aide) | w(!) (écrire) | q(!) (quitter) | wq(!) ]"
+msgid "Command: [ h(elp) | w(rite)(!) | q(uit)(!) | wq(!) | n(ext) | p(rev) ]"
+msgstr ""
msgid "Read-only mode - use w!"
msgstr "Mode écriture seule - utiliser w!"
@@ -318,6 +317,18 @@ msgstr "Il y a des modifications non sauvegardées - utiliser w ou q!"
msgid "Help topic does not exist: %s"
msgstr "Le sujet n'existe pas dans l'aide : %s"
+msgid "Select a repeating item in the appointments panel."
+msgstr ""
+
+msgid "Not a repeating item."
+msgstr ""
+
+msgid "Last occurrence."
+msgstr ""
+
+msgid "First occurrence."
+msgstr ""
+
#, c-format
msgid "No such command: %s"
msgstr "Commande inconnue : %s"
@@ -415,6 +426,9 @@ msgstr ""
msgid "(insert an empty line after each appointment)"
msgstr ""
+msgid "(text for a day without events and appointments)"
+msgstr ""
+
msgid "(display more than one day in the appointments panel)"
msgstr ""
@@ -441,17 +455,6 @@ msgid "(if set to YES, confirmation is required before deleting an event)"
msgstr ""
"(si fixé à OUI, il est nécessaire de confirmer avant d'effacer un élément)"
-msgid "(if set to YES, messages about loaded and saved data will be displayed)"
-msgstr ""
-"(si fixé à OUI, les messages concernant le chargement et l'enregistrement "
-"des données seront affichés)"
-
-msgid "Monday"
-msgstr "Lundi"
-
-msgid "Sunday"
-msgstr "Dimanche"
-
msgid "(specifies the first day of week in the calendar view)"
msgstr "(indique le premier jour de la semaine dans la vue de calendrier)"
@@ -476,10 +479,21 @@ msgstr "(position de l'entête dans le panneau rendez-vous)"
msgid "(Format of the date displayed in the appointments panel)"
msgstr "(Format de la date affichée dans le panneau rendez-vous)"
+msgid "(Format of the time displayed in the appointments panel)"
+msgstr ""
+
+msgid "Enter a text string (an empty string for the default text)"
+msgstr ""
+
msgid "Enter the date format (see 'man 3 strftime' for possible formats) "
msgstr ""
"Saisir le format de date (voir 'man 3 strftime' pour les formats possibles)"
+msgid "Enter the time format (see 'man 3 strftime' for possible formats) "
+msgstr ""
+"Saisir le format de l'heure (voir 'man 3 strftime' pour les formats "
+"possibles)"
+
msgid "Enter the date format: "
msgstr "Saisir le format de date : "
@@ -494,8 +508,8 @@ msgstr "options générales"
msgid "Undefined option!"
msgstr "Option inconnue !"
-msgid "undefined"
-msgstr "inconnue"
+msgid "UNDEFINED"
+msgstr ""
msgid "keys configuration"
msgstr "Configuration des raccourcis"
@@ -507,8 +521,8 @@ msgstr "Pressez la touche que vous voulez assigner :"
msgid "The key '%s' is already used for %s. Choose another one."
msgstr "Le raccourci '%s' est déjà utilisé for %s. Choisissez en un autre."
-msgid "Some actions do not have any associated key bindings!"
-msgstr "Certaines actions n'ont pas de raccourcis clavier associés !"
+msgid "Some actions are left undefined!"
+msgstr ""
msgid ""
"Sorry, colors are not supported by your terminal\n"
@@ -524,7 +538,7 @@ msgstr "N'a pu sauvegarder %s."
msgid "unknown item type"
msgstr "type d'élément inconnu"
-msgid "(none)"
+msgid "Note:"
msgstr ""
msgid "Event:"
@@ -586,6 +600,7 @@ msgid "sleeping at %s for %d second\n"
msgid_plural "sleeping at %s for %d seconds\n"
msgstr[0] "endormi à %s pour %d seconde\n"
msgstr[1] "endormi à %s pour %d secondes\n"
+msgstr[2] "endormi à %s pour %d secondes\n"
#, c-format
msgid "awakened at %s\n"
@@ -595,11 +610,11 @@ msgstr "réveillé à %s\n"
msgid "Could not stop calcurse daemon: %s\n"
msgstr "Impossible d'arrêter le démon calcurse : %s\n"
-msgid "date error in event"
-msgstr "date erronée dans l'événement"
+msgid "illegal date in event"
+msgstr ""
-msgid "date error in the event\n"
-msgstr "erreur dans la date de l'événement\n"
+msgid "date error in event\n"
+msgstr ""
msgid "Internal error: line too long"
msgstr "Erreur interne : ligne trop longue"
@@ -610,55 +625,138 @@ msgstr "dépassement de mémoire"
msgid "unknown ical type"
msgstr "type ical inconnu"
-msgid "recurrence rule malformed."
-msgstr "règle de répétition mal formée."
+msgid "(empty)"
+msgstr ""
-msgid "recurrence frequency not found."
-msgstr "fréquence de répétition introuvable."
+msgid "ical_store_event: out of memory"
+msgstr ""
-msgid "recurrence frequency not recognized."
-msgstr "fréquence de répétition non reconnue."
+msgid "need DTSTART to determine event type."
+msgstr ""
+
+msgid "malformed recurrence line."
+msgstr ""
-msgid "recurrence exception dates malformed."
-msgstr "dates de répétition exceptées mal formées."
+msgid "frequency not set in rrule."
+msgstr ""
-msgid "description malformed."
-msgstr "description mal formée."
+msgid "frequency absent in rrule."
+msgstr ""
-msgid "could not get entire item description."
-msgstr "impossible de trouver la description entière de l'élément."
+msgid "rrule frequency not supported."
+msgstr ""
-msgid "could not retrieve item summary."
-msgstr "impossible de récupérer le résumé de l'événement."
+msgid "invalid interval."
+msgstr ""
-msgid "item start date is not defined."
-msgstr "la date de début de l'élément n'est pas définie."
+msgid "either until or count."
+msgstr ""
-msgid "item has a negative duration."
-msgstr "l'élément a une durée négative."
+msgid "missing until value."
+msgstr ""
-msgid "item could not be identified."
-msgstr "l'élément n'a pu être identifié."
+msgid "invalid until format."
+msgstr ""
-msgid "event start time malformed."
-msgstr "heure de début de l'événement mal formée."
+msgid "invalid count value."
+msgstr ""
-msgid "could not retrieve event start time."
-msgstr "impossible de récupérer l'heure de début de l'événement."
+msgid "invalid bymonth list."
+msgstr ""
-msgid "event end time malformed."
-msgstr "heure de fin de l'événement mal formée."
+msgid "invalid bymonthday list."
+msgstr ""
-msgid "could not retrieve event end time."
-msgstr "impossible de récupérer l'heure de fin de l'événement."
+msgid "invalid byday list."
+msgstr ""
+
+msgid "invalid exception date value type."
+msgstr ""
+
+msgid "malformed exceptions line."
+msgstr ""
-msgid "item duration malformed."
-msgstr "durée de l'élément mal formée."
+msgid "invalid exception."
+msgstr ""
+
+#, c-format
+msgid "malformed %s line."
+msgstr ""
+
+#, c-format
+msgid "malformed %s."
+msgstr ""
+
+msgid "malformed summary line."
+msgstr ""
+
+msgid "malformed summary."
+msgstr ""
+
+msgid "item start date not defined."
+msgstr ""
+
+msgid "malformed start time line."
+msgstr ""
+
+msgid "invalid or malformed event start time."
+msgstr ""
+
+msgid "invalid end time value type."
+msgstr ""
+
+msgid "malformed end time line."
+msgstr ""
+
+msgid "malformed event end time."
+msgstr ""
+
+msgid "end must be later than start."
+msgstr ""
+
+msgid "either end or duration."
+msgstr ""
+
+msgid "malformed duration line."
+msgstr ""
+
+msgid "invalid duration."
+msgstr ""
+
+msgid "exception date, but no recurrence rule."
+msgstr ""
+
+msgid "multi-day event changed to one-day event"
+msgstr ""
+
+#, c-format
+msgid "Location: %s"
+msgstr ""
+
+#, c-format
+msgid "Comment: %s"
+msgstr ""
+
+#, c-format
+msgid "rrule does not match start day (%s)."
+msgstr ""
+
+msgid "item could not be identified."
+msgstr "l'élément n'a pu être identifié."
+
+msgid "only one description allowed."
+msgstr ""
+
+msgid "only one location allowed."
+msgstr ""
msgid "The ical file seems to be malformed. The end of item was not found."
msgstr ""
"Le fichier ical semble mal formé. La fin de l'élément n'a pas été trouvée."
+msgid "could not retrieve item summary."
+msgstr "impossible de récupérer le résumé de l'événement."
+
msgid "item priority is invalid (must be between 0 and 9)."
msgstr ""
"La priorité de l'élément est invalide (doit être comprise entre 0 et 9)"
@@ -733,6 +831,21 @@ msgstr "format incorrect du rendez-vous ou de l'événement"
msgid "syntax error in item repetition"
msgstr "erreur de syntaxe dans la répétition de l'élément"
+msgid "syntax error in until date"
+msgstr ""
+
+msgid "until date error"
+msgstr ""
+
+msgid "BYMONTHDAY illegal with WEEKLY"
+msgstr ""
+
+msgid "missing end of recurrence"
+msgstr ""
+
+msgid "syntax error in item state"
+msgstr ""
+
msgid "failed to open todo file"
msgstr "impossible d'ouvrir le fichier des tâches"
@@ -742,57 +855,49 @@ msgstr "Les données à l'écran ont été modifiées et seront perdues :"
msgid "failed to open key file"
msgstr "impossible d'ouvrir le fichier des raccourcis clavier"
-msgid ""
-"\n"
-"Too many errors while reading configuration file!\n"
-"Please backup your keys file, remove it from directory, and launch calcurse "
-"again.\n"
-msgstr ""
-"\n"
-"Trop d'erreurs à la lecture du fichier de configuration !\n"
-"Veuillez faire une sauvegarde de votre fichier de raccourcis, supprimer le "
-"du répertoire, puis relancer calcurse.\n"
-
msgid "Could not read key label"
msgstr "Impossible de lire le libellé de la touche"
-msgid "Key label not recognized"
-msgstr "Libellé de la touche non reconnu"
-
#, c-format
-msgid "Error reading key: \"%s\""
-msgstr "Erreur de lecture de la touche : \"%s\""
+msgid "Key label not recognized: \"%s\""
+msgstr ""
#, c-format
-msgid "\"%s\" assigned multiple times!"
-msgstr "\"%s\" est assignée plusieurs fois !"
-
-msgid "There were some errors when loading keys file."
+msgid "No keys assigned to \"%s\"."
msgstr ""
-"Il y a eu des erreurs au chargement du fichier de configuration des "
-"raccourcis."
-msgid "Too many errors while reading keys file, aborting..."
+#, c-format
+msgid "Keyname not recognized: \"%s\""
msgstr ""
-"Trop d'erreurs durant la lecture du fichier de raccourcis, annulation..."
#, c-format
-msgid "FATAL ERROR: could not create %s: %s\n"
-msgstr "ERREUR FATALE : impossible de créer %s : %s\n"
+msgid "\"%s\" assigned twice: \"%s\"."
+msgstr ""
-msgid "Press [ENTER] to continue"
-msgstr "Appuyer sur [ENTRÉE] pour continuer"
+#, c-format
+msgid ""
+"Action \"%s\" absent, but default key \"%s\" assigned to another action."
+msgstr ""
-msgid "Welcome to Calcurse. Missing data files were created."
-msgstr "Bienvenue dans Calcurse. Les fichiers manquants ont été créés."
+msgid "Errors in the keys file."
+msgstr ""
-msgid "Data files found. Data will be loaded now."
+msgid "Remove offending line(s) from the keys file, aborting..."
msgstr ""
-"Fichiers de données trouvés. Les données seront chargées immédiatement."
+
+msgid "Some actions do not have any associated key bindings!"
+msgstr "Certaines actions n'ont pas de raccourcis clavier associés !"
+
+#, c-format
+msgid "FATAL ERROR: could not create %s: %s\n"
+msgstr "ERREUR FATALE : impossible de créer %s : %s\n"
msgid "The data were successfully exported"
msgstr "Les données ont été correctement exportées"
+msgid "Press [ENTER] to continue"
+msgstr "Appuyer sur [ENTRÉE] pour continuer"
+
msgid "unknown export type"
msgstr "type d'exportation inconnu"
@@ -820,18 +925,21 @@ msgid "%d app"
msgid_plural "%d apps"
msgstr[0] "%d app"
msgstr[1] "%d apps"
+msgstr[2] "%d apps"
#, c-format
msgid "%d event"
msgid_plural "%d events"
msgstr[0] "%d événement"
msgstr[1] "%d événements"
+msgstr[2] "%d événements"
#, c-format
msgid "%d todo"
msgid_plural "%d todos"
msgstr[0] "%d tâche"
msgstr[1] "%d tâches"
+msgstr[2] "%d tâches"
#, c-format
msgid "%d skipped"
@@ -863,10 +971,10 @@ msgstr "Attention : impossible d'effacer le journal temporaire %s, Abandon..."
msgid "Invalid delay"
msgstr "Délai invalide"
-msgid "Periodic save: data files have changed. Save cancelled."
+msgid ""
+"Periodic save cancelled. Data files have changed. Save and merge "
+"interactively"
msgstr ""
-"Sauvegarde périodique : les fichiers de données ont été modifiés. "
-"L'enregistrement est annulé."
#, c-format
msgid ""
@@ -914,6 +1022,9 @@ msgstr "Coller"
msgid "Chg Win"
msgstr "Chg.Fen."
+msgid "Prev Win"
+msgstr ""
+
msgid "Import"
msgstr "Importer"
@@ -1103,6 +1214,9 @@ msgstr "Coller un élément à la position actuelle."
msgid "Select next panel in calcurse main screen."
msgstr "Sélectionner le panneau suivant dans l'écran général de calcurse."
+msgid "Select previous panel in calcurse main screen."
+msgstr ""
+
msgid "Import data from an external file."
msgstr "Importer les données d'un fichier externe."
@@ -1242,10 +1356,8 @@ msgid "FATAL ERROR: null file pointer."
msgstr "ERREUR FATALE : pointeur de fichier nul."
#, c-format
-msgid "When adding default key for \"%s\", \"%s\" was already assigned!"
+msgid "Default key(s) assigned to %d action%s."
msgstr ""
-"Pendant l'ajout de la touche par défaut pour \"%s\", \"%s\" était déjà "
-"assignée !"
msgid "xmalloc: zero size"
msgstr "xmalloc : taille nulle"
@@ -1338,12 +1450,6 @@ msgstr " blocs non libérés : %u\n"
msgid "Warning: could not open %s, Aborting..."
msgstr "Attention : impossible d'ouvrir %s, abandon..."
-msgid "error while launching command: could not fork"
-msgstr "erreur pendant le lancement de la commande : fork impossible"
-
-msgid "error while launching command"
-msgstr "erreur durant le lancement de la commande"
-
msgid "(if set to YES, notify-bar will be displayed)"
msgstr "(si fixé à OUI, la barre de notification sera affichée)"
@@ -1376,11 +1482,6 @@ msgstr ""
msgid "(Log activity when running in background)"
msgstr "(Enregistrer l'activité lors de l'exécution en arrière-plan)"
-msgid "Enter the time format (see 'man 3 strftime' for possible formats) "
-msgstr ""
-"Saisir le format de l'heure (voir 'man 3 strftime' pour les formats "
-"possibles)"
-
msgid "Enter the number of seconds (0 not to be warned before an appointment)"
msgstr ""
"Saisir le nombre de secondes (0 pour désactiver l'alerte qui précéde un "
@@ -1398,18 +1499,46 @@ msgstr "type de répétition incohérent"
msgid "System event"
msgstr "Événement système"
-msgid "unknown repetition type"
-msgstr "type de répétition inconnu"
-
msgid "unknown character"
msgstr "caractère inconnu"
+#, c-format
+msgid "recurrence error: not on start day (%s)"
+msgstr ""
+
+msgid "illegel date in event"
+msgstr ""
+
+msgid "date error in event"
+msgstr "date erronée dans l'événement"
+
+msgid "month day is zero"
+msgstr ""
+
+msgid "no daily frequency check"
+msgstr ""
+
+msgid "illegal BYDAY value"
+msgstr ""
+
msgid "event not found"
msgstr "événement introuvable"
msgid "appointment not found"
msgstr "rendez-vous introuvable"
+msgid "syntax error in bymonthday"
+msgstr ""
+
+msgid "syntax error in bywday"
+msgstr ""
+
+msgid "syntax error in bymonth"
+msgstr ""
+
+msgid "illegal bymonth value"
+msgstr ""
+
msgid "syntax error in item date"
msgstr "erreur de syntaxe dans la date de l'élément"
@@ -1417,10 +1546,6 @@ msgid "date error in item exception"
msgstr "erreur dans la date de l'exception de l'événement"
#, c-format
-msgid "Could not remove calcurse lock file: %s\n"
-msgstr "Impossible d'effacer le fichier verrou de calcurse : %s\n"
-
-#, c-format
msgid "Error setting signal #%d : %s\n"
msgstr "Erreur d'affectation du signal #%d : %s\n"
@@ -1460,6 +1585,10 @@ msgid "Invalid time: start time must come before end time!"
msgstr ""
"Heure non valide : l'heure de départ doit être antérieure à l'heure de fin!"
+#, c-format
+msgid "Repetition must begin on start day (%s)."
+msgstr ""
+
msgid "Enter end date (and/or time) or duration ('?' for input formats):"
msgstr ""
"Entrer la date de fin (et/ou l'heure) ou la durée ('?' pour les formats "
@@ -1485,57 +1614,114 @@ msgstr "Saisir la description du nouvel élément :"
msgid "Exception days:"
msgstr ""
-#, fuzzy
msgid "Invalid date format - try again:."
-msgstr "Date ou heure non valide."
+msgstr ""
-msgid "Enter the new repetition type:"
-msgstr "Saisir le nouveau type de répétition :"
+msgid "Limit repetition to listed days."
+msgstr ""
-msgid "(d)aily"
-msgstr "(q)uotidien"
+msgid "Expand repetition to listed days."
+msgstr ""
-msgid "(w)eekly"
-msgstr "(h)ebdomadaire"
+msgid "Expand repetition to listed days, either all or 1st, 2nd, ... of month."
+msgstr ""
-msgid "(m)onthly"
-msgstr "(m)ensuel"
+msgid "Note: limit to monthdays, if any."
+msgstr ""
-msgid "(y)early"
-msgstr "(a)nnuel"
+msgid "Expand repetition to listed days, either all or 1st, 2nd, ... of year."
+msgstr ""
+
+msgid "Note: expand to listed months, if any; limit to monthdays, if any."
+msgstr ""
+
+msgid "Limit repetition to listed months."
+msgstr ""
+
+msgid "Expand repetition to listed months."
+msgstr ""
+
+msgid "Limit repetition to listed days of month."
+msgstr ""
+
+msgid "Expand repetition to listed days of month."
+msgstr ""
+
+#, c-format
+msgid "Weekdays %s|..|%s, space-separated list, '?' for help:"
+msgstr ""
+
+#, c-format
+msgid ""
+"Weekdays [n]%s|..|[n]%s, space-separated list, n=1,-1,..,5,-5, '?' for help:"
+msgstr ""
#, c-format
-msgid "(currently using %s)"
-msgstr "(actuellement : %s)"
+msgid ""
+"Weekdays [n]%s|..|[n]%s, space-separated list, n=1,-1,..,53,-53, '?' for "
+"help:"
+msgstr ""
+
+msgid "Months 1|..|12, space-separated list, '?' for help:"
+msgstr ""
+
+msgid "Monthdays 1|..|31 or -1|..|-31, space-separated list, '?' for help:"
+msgstr ""
+
+msgid "Invalid format - try again."
+msgstr ""
+
+msgid "Press any key to continue."
+msgstr ""
+
+msgid "Base period:"
+msgstr ""
+
+msgid "day"
+msgstr ""
+
+msgid "week"
+msgstr ""
+
+msgid "month"
+msgstr ""
+
+msgid "year"
+msgstr ""
msgid "[dwmy]"
msgstr "[qhma]"
+msgid "Frequency:"
+msgstr ""
+
msgid "Invalid frequency."
msgstr "Fréquence invalide."
-msgid "Enter the repetition frequency:"
-msgstr "Saisir la fréquence de répétition :"
-
-msgid "Enter end date or duration ('?' for input formats):"
-msgstr "Entrer la date de fin ou la durée ('?' pour les formats d'entrée) :"
+msgid "Until date, increment or repeat count ('?' for input formats):"
+msgstr ""
#, c-format
-msgid "Date: %s (year or month may be omitted). Endless duration: 0."
-msgstr "Date : %s (année ou mois peuvent être omis). Durée infinie : 0."
+msgid "Date: %s (year, month may be omitted, endless: 0)."
+msgstr ""
-msgid "Duration in days: +dd. Duration in weeks and days: +??w??d."
-msgstr "Durée en jours : +dd. Durée en semaines et jours : +??w??d."
+msgid "Increment: +?? (days) or: +??w??d (weeks). Repeat count: #?? (number)."
+msgstr ""
#, c-format
-msgid "Invalid date: end date must come after start date (%s)."
+msgid "Invalid date: until date must come after start date (%s)."
msgstr ""
-"Date non valide : la date de fin doit être postérieure à la date de début "
-"(%s)."
msgid "Invalid date."
msgstr "Date non valide."
+msgid "Repeat count is too big."
+msgstr ""
+
+#, c-format
+msgid "Repetition must begin on start day (%s); any change discarded."
+msgstr ""
+
msgid "Description"
msgstr "Description"
@@ -1578,37 +1764,40 @@ msgstr "Date : %s (et/ou heure), année ou mois peuvent être omis."
msgid "Invalid start time."
msgstr "Heure de départ non valide."
-msgid "Do you really want to delete this item?"
-msgstr "Voulez-vous vraiment effacer cet élément ?"
+msgid ""
+"This item is recurrent and has a note attached to it. Delete (s)elected "
+"occurrence, (a)ll occurrences, or just its (n)ote?"
+msgstr ""
+
+msgid "[san]"
+msgstr ""
-msgid "This item is recurrent. Delete (a)ll occurences or just this (o)ne?"
+msgid ""
+"This item has a note attached to it. Delete (s)elected occurrence or just "
+"its (n)ote?"
msgstr ""
-"Cet élément est répétitif. Effacer (t)outes les occurrences ou seulement "
-"(c)elle-ci ?"
-msgid "[ao]"
-msgstr "[tc]"
+msgid "[sn]"
+msgstr ""
-msgid "This item has a note attached to it. Delete (i)tem or just its (n)ote?"
+msgid ""
+"This item is recurrent. Delete (s)elected occurrence or (a)ll occurrences?"
msgstr ""
-"Une note est associée à cet élément. Effacer l'élém(e)nt ou seulement la "
-"(n)ote ?"
-msgid "[in]"
-msgstr "[en]"
+msgid "[sa]"
+msgstr ""
-msgid "Enter the repetition type:"
-msgstr "Saisir le type de répétition :"
+msgid "Confirm deletion. Delete (s)elected occurrence? Press (s) to confirm."
+msgstr ""
-#, c-format
-msgid "Date: %s (year or month may be omitted). Endless duration: '0'."
-msgstr "Date : %s (année or mois peuvent être omis). Durée infinie : '0'."
+msgid "[s]"
+msgstr ""
-msgid "This item is already a repeated one."
-msgstr "Cet élément est déjà répétitif."
+msgid "Already repeated."
+msgstr ""
-msgid "wrong item type"
-msgstr "type d'élément incorrect"
+msgid "A (s)imple or (a)dvanced repetition?"
+msgstr ""
msgid "Enter the new TODO item:"
msgstr "Saisir la nouvelle tâche :"
@@ -1635,6 +1824,10 @@ msgstr "Saisir la description de la nouvelle tâche :"
msgid "TODO:"
msgstr "À FAIRE:"
+#, c-format
+msgid "Could not remove calcurse lock file: %s\n"
+msgstr "Impossible d'effacer le fichier verrou de calcurse : %s\n"
+
msgid "/!\\ INTERNAL ERROR /!\\"
msgstr "/!\\ ERREUR INTERNE /!\\"
@@ -1693,13 +1886,9 @@ msgstr "Utilisation : calcurse-upgrade [-h|-v|--config <fichier>]"
msgid ""
"\n"
-"Copyright (c) 2004-2017 calcurse Development Team.\n"
+"Copyright (c) 2004-2023 calcurse Development Team.\n"
"This is free software; see the source for copying conditions.\n"
msgstr ""
-"\n"
-"(c) 2004-2017. L'équipe de développement de calcurse. Tous droits réservés.\n"
-"Ceci est un logiciel libre ; voir le code source pour les conditions légales "
-"d'utilisation.\n"
msgid "unrecognized option:"
msgstr "option non reconnue :"
diff --git a/po/nl.po b/po/nl.po
index d7bb163..8392ccc 100644
--- a/po/nl.po
+++ b/po/nl.po
@@ -1,6 +1,6 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR calcurse Development Team <misc@calcurse.org>
-# This file is distributed under the same license as the PACKAGE package.
+# This file is distributed under the same license as the calcurse package.
#
# Translators:
# Frob Nicator <mart@martlubbers.net>, 2016
@@ -11,10 +11,10 @@ msgid ""
msgstr ""
"Project-Id-Version: calcurse\n"
"Report-Msgid-Bugs-To: bugs@calcurse.org\n"
-"POT-Creation-Date: 2019-06-16 15:27-0400\n"
-"PO-Revision-Date: 2019-05-30 11:52+0000\n"
-"Last-Translator: Lukas Fleischer\n"
-"Language-Team: Dutch (http://www.transifex.com/lfleischer/calcurse/language/"
+"POT-Creation-Date: 2024-01-26 18:28+0100\n"
+"PO-Revision-Date: 2013-07-23 08:43+0000\n"
+"Last-Translator: Marco van Hulten <marco@hulten.org>, 2018\n"
+"Language-Team: Dutch (http://app.transifex.com/lfleischer/calcurse/language/"
"nl/)\n"
"Language: nl\n"
"MIME-Version: 1.0\n"
@@ -25,6 +25,12 @@ msgstr ""
msgid "null pointer"
msgstr "null pointer"
+msgid "illegal date in appointment"
+msgstr ""
+
+msgid "error in appointment description"
+msgstr ""
+
msgid "date error in appointment"
msgstr "datumfout in de afspraak"
@@ -37,7 +43,7 @@ msgid ""
"calcurse -Q [--from <date>] [--to <date>] [--days <number>]\n"
"calcurse -a | -d <date> | -d <number> | -n | -r[<number>] | -s[<date>] | -"
"t[<number>]\n"
-"calcurse -h | -v | --status | -G | -P | -g | -i <file> | -x[<file>] | --"
+"calcurse -h | -v | --status | -G | -P | -g | -i <file> | -x[<format>] | --"
"daemon"
msgstr ""
@@ -48,7 +54,7 @@ msgstr "Probeer `calcurse -h` voor meer informatie."
msgid "calcurse %s -- text-based organizer\n"
msgstr "calcurse %s -- tekst gebaseerde agenda\n"
-msgid "Copyright (c) 2004-2017 calcurse Development Team."
+msgid "Copyright (c) 2004-2023 calcurse Development Team."
msgstr ""
msgid "This is free software; see the source for copying conditions."
@@ -123,7 +129,7 @@ msgstr ""
msgid " -i, --import <file> Import iCal data from file"
msgstr ""
-msgid " -q, --quiet Suppress system dialogs"
+msgid " -q, --quiet Suppress import/export result message"
msgstr ""
msgid " --read-only Do not save configuration or data files"
@@ -273,7 +279,7 @@ msgstr ""
msgid "Do you really want to quit?"
msgstr ""
-msgid "Command: [ h(elp) | w(rite)(!) | q(uit)(!) | wq(!) ]"
+msgid "Command: [ h(elp) | w(rite)(!) | q(uit)(!) | wq(!) | n(ext) | p(rev) ]"
msgstr ""
msgid "Read-only mode - use w!"
@@ -286,6 +292,18 @@ msgstr ""
msgid "Help topic does not exist: %s"
msgstr ""
+msgid "Select a repeating item in the appointments panel."
+msgstr ""
+
+msgid "Not a repeating item."
+msgstr ""
+
+msgid "Last occurrence."
+msgstr ""
+
+msgid "First occurrence."
+msgstr ""
+
#, c-format
msgid "No such command: %s"
msgstr "Geen dergelijk commando: %s"
@@ -383,6 +401,9 @@ msgstr ""
msgid "(insert an empty line after each appointment)"
msgstr ""
+msgid "(text for a day without events and appointments)"
+msgstr ""
+
msgid "(display more than one day in the appointments panel)"
msgstr ""
@@ -404,15 +425,6 @@ msgstr "(Bij JA, wordt er een bevestiging gevraagd bij eindigen programma"
msgid "(if set to YES, confirmation is required before deleting an event)"
msgstr "(Bij JA, is een bevestiging nodig voor het wissen van een gebeurtenis)"
-msgid "(if set to YES, messages about loaded and saved data will be displayed)"
-msgstr ""
-
-msgid "Monday"
-msgstr "maandag"
-
-msgid "Sunday"
-msgstr "zondag"
-
msgid "(specifies the first day of week in the calendar view)"
msgstr ""
@@ -437,9 +449,18 @@ msgstr ""
msgid "(Format of the date displayed in the appointments panel)"
msgstr ""
+msgid "(Format of the time displayed in the appointments panel)"
+msgstr ""
+
+msgid "Enter a text string (an empty string for the default text)"
+msgstr ""
+
msgid "Enter the date format (see 'man 3 strftime' for possible formats) "
msgstr "Geef het formaat van de datum (zie 'man 3 strftime')"
+msgid "Enter the time format (see 'man 3 strftime' for possible formats) "
+msgstr "Geef het formaat van de tijd (zie 'man 3 strftime')"
+
msgid "Enter the date format: "
msgstr ""
@@ -454,8 +475,8 @@ msgstr "Algemene opties"
msgid "Undefined option!"
msgstr "Niet gekende optie!"
-msgid "undefined"
-msgstr "Ongekend"
+msgid "UNDEFINED"
+msgstr ""
msgid "keys configuration"
msgstr "Toetsinstellingen"
@@ -467,7 +488,7 @@ msgstr "Druk de toets die u wilt toewijzen:"
msgid "The key '%s' is already used for %s. Choose another one."
msgstr ""
-msgid "Some actions do not have any associated key bindings!"
+msgid "Some actions are left undefined!"
msgstr ""
msgid ""
@@ -484,7 +505,7 @@ msgstr ""
msgid "unknown item type"
msgstr "ongekend type item"
-msgid "(none)"
+msgid "Note:"
msgstr ""
msgid "Event:"
@@ -555,10 +576,10 @@ msgstr ""
msgid "Could not stop calcurse daemon: %s\n"
msgstr ""
-msgid "date error in event"
-msgstr "datumfout in gebeurtenis"
+msgid "illegal date in event"
+msgstr ""
-msgid "date error in the event\n"
+msgid "date error in event\n"
msgstr ""
msgid "Internal error: line too long"
@@ -570,54 +591,137 @@ msgstr ""
msgid "unknown ical type"
msgstr "onbekend ical type"
-msgid "recurrence rule malformed."
-msgstr "herhalingsregel onjuist"
+msgid "(empty)"
+msgstr ""
-msgid "recurrence frequency not found."
+msgid "ical_store_event: out of memory"
msgstr ""
-msgid "recurrence frequency not recognized."
+msgid "need DTSTART to determine event type."
msgstr ""
-msgid "recurrence exception dates malformed."
-msgstr "herhaling exceptie datum onjuist"
+msgid "malformed recurrence line."
+msgstr ""
-msgid "description malformed."
-msgstr "omschrijving beschadigd"
+msgid "frequency not set in rrule."
+msgstr ""
-msgid "could not get entire item description."
-msgstr "onvolledige item omschrijving"
+msgid "frequency absent in rrule."
+msgstr ""
-msgid "could not retrieve item summary."
-msgstr "kan item onderwerp niet ophalen"
+msgid "rrule frequency not supported."
+msgstr ""
-msgid "item start date is not defined."
+msgid "invalid interval."
msgstr ""
-msgid "item has a negative duration."
-msgstr "item heeft een negatieve tijdsduur"
+msgid "either until or count."
+msgstr ""
-msgid "item could not be identified."
-msgstr "item onbekend"
+msgid "missing until value."
+msgstr ""
+
+msgid "invalid until format."
+msgstr ""
+
+msgid "invalid count value."
+msgstr ""
+
+msgid "invalid bymonth list."
+msgstr ""
+
+msgid "invalid bymonthday list."
+msgstr ""
+
+msgid "invalid byday list."
+msgstr ""
+
+msgid "invalid exception date value type."
+msgstr ""
+
+msgid "malformed exceptions line."
+msgstr ""
+
+msgid "invalid exception."
+msgstr ""
+
+#, c-format
+msgid "malformed %s line."
+msgstr ""
+
+#, c-format
+msgid "malformed %s."
+msgstr ""
+
+msgid "malformed summary line."
+msgstr ""
+
+msgid "malformed summary."
+msgstr ""
+
+msgid "item start date not defined."
+msgstr ""
+
+msgid "malformed start time line."
+msgstr ""
+
+msgid "invalid or malformed event start time."
+msgstr ""
+
+msgid "invalid end time value type."
+msgstr ""
+
+msgid "malformed end time line."
+msgstr ""
+
+msgid "malformed event end time."
+msgstr ""
-msgid "event start time malformed."
+msgid "end must be later than start."
msgstr ""
-msgid "could not retrieve event start time."
-msgstr "kan begintijd van gebeurtenis niet ophalen"
+msgid "either end or duration."
+msgstr ""
-msgid "event end time malformed."
+msgid "malformed duration line."
msgstr ""
-msgid "could not retrieve event end time."
-msgstr "kan eindtijd van gebeurtenis niet ophalen"
+msgid "invalid duration."
+msgstr ""
-msgid "item duration malformed."
-msgstr "item tijdsduur onjuist"
+msgid "exception date, but no recurrence rule."
+msgstr ""
+
+msgid "multi-day event changed to one-day event"
+msgstr ""
+
+#, c-format
+msgid "Location: %s"
+msgstr ""
+
+#, c-format
+msgid "Comment: %s"
+msgstr ""
+
+#, c-format
+msgid "rrule does not match start day (%s)."
+msgstr ""
+
+msgid "item could not be identified."
+msgstr "item onbekend"
+
+msgid "only one description allowed."
+msgstr ""
+
+msgid "only one location allowed."
+msgstr ""
msgid "The ical file seems to be malformed. The end of item was not found."
msgstr "Ical-bestand oogt onjuist. Het einde van item niet gevonden."
+msgid "could not retrieve item summary."
+msgstr "kan item onderwerp niet ophalen"
+
msgid "item priority is invalid (must be between 0 and 9)."
msgstr ""
@@ -688,6 +792,21 @@ msgstr "fout formaat in de afspraak of gebeurtenis"
msgid "syntax error in item repetition"
msgstr "syntaxfout in de herhaling van het item"
+msgid "syntax error in until date"
+msgstr ""
+
+msgid "until date error"
+msgstr ""
+
+msgid "BYMONTHDAY illegal with WEEKLY"
+msgstr ""
+
+msgid "missing end of recurrence"
+msgstr ""
+
+msgid "syntax error in item state"
+msgstr ""
+
msgid "failed to open todo file"
msgstr "kon het todo-bestand niet openen"
@@ -697,54 +816,49 @@ msgstr ""
msgid "failed to open key file"
msgstr ""
-msgid ""
-"\n"
-"Too many errors while reading configuration file!\n"
-"Please backup your keys file, remove it from directory, and launch calcurse "
-"again.\n"
+msgid "Could not read key label"
msgstr ""
-"\n"
-"Teveel fouten tijdens het lezen van het configuratiebestand!\n"
-"Maak een backup van het sneltoetsenbestand, verwijder het van de map en "
-"start calcurse opnieuw op.\n"
-msgid "Could not read key label"
+#, c-format
+msgid "Key label not recognized: \"%s\""
+msgstr ""
+
+#, c-format
+msgid "No keys assigned to \"%s\"."
msgstr ""
-msgid "Key label not recognized"
+#, c-format
+msgid "Keyname not recognized: \"%s\""
msgstr ""
#, c-format
-msgid "Error reading key: \"%s\""
+msgid "\"%s\" assigned twice: \"%s\"."
msgstr ""
#, c-format
-msgid "\"%s\" assigned multiple times!"
-msgstr "\"%s\" meer dan eens toegewezen!"
+msgid ""
+"Action \"%s\" absent, but default key \"%s\" assigned to another action."
+msgstr ""
-msgid "There were some errors when loading keys file."
+msgid "Errors in the keys file."
msgstr ""
-msgid "Too many errors while reading keys file, aborting..."
+msgid "Remove offending line(s) from the keys file, aborting..."
+msgstr ""
+
+msgid "Some actions do not have any associated key bindings!"
msgstr ""
-"Teveel fouten bij het laden van het sneltoetsenbestand, wordt afgebroken ..."
#, c-format
msgid "FATAL ERROR: could not create %s: %s\n"
msgstr "FATALE FOUT: kan %s niet aanmaken: %s\n"
-msgid "Press [ENTER] to continue"
-msgstr "Druk op [ENTER] om door te gaan)"
-
-msgid "Welcome to Calcurse. Missing data files were created."
-msgstr "Welkom bij Calcurse. De missende databestanden zijn aangemaakt."
-
-msgid "Data files found. Data will be loaded now."
-msgstr "Databestanden gevonden. Data wordt geladen."
-
msgid "The data were successfully exported"
msgstr "De data is met succes geëxporteerd"
+msgid "Press [ENTER] to continue"
+msgstr "Druk op [ENTER] om door te gaan)"
+
msgid "unknown export type"
msgstr "onbekend exporttype"
@@ -816,7 +930,9 @@ msgstr ""
msgid "Invalid delay"
msgstr ""
-msgid "Periodic save: data files have changed. Save cancelled."
+msgid ""
+"Periodic save cancelled. Data files have changed. Save and merge "
+"interactively"
msgstr ""
#, c-format
@@ -858,6 +974,9 @@ msgstr "Plak"
msgid "Chg Win"
msgstr ""
+msgid "Prev Win"
+msgstr ""
+
msgid "Import"
msgstr "Import"
@@ -1036,6 +1155,9 @@ msgstr ""
msgid "Select next panel in calcurse main screen."
msgstr ""
+msgid "Select previous panel in calcurse main screen."
+msgstr ""
+
msgid "Import data from an external file."
msgstr "Importeer gegevens uit een extern bestand."
@@ -1158,7 +1280,7 @@ msgid "FATAL ERROR: null file pointer."
msgstr ""
#, c-format
-msgid "When adding default key for \"%s\", \"%s\" was already assigned!"
+msgid "Default key(s) assigned to %d action%s."
msgstr ""
msgid "xmalloc: zero size"
@@ -1251,12 +1373,6 @@ msgstr ""
msgid "Warning: could not open %s, Aborting..."
msgstr "Pas op: bestand %s niet te openen. Stoppen..."
-msgid "error while launching command: could not fork"
-msgstr ""
-
-msgid "error while launching command"
-msgstr "fout bij uitvoeren commando"
-
msgid "(if set to YES, notify-bar will be displayed)"
msgstr "(Bij JA, wordt de informatiebalk weergegeven)"
@@ -1284,9 +1400,6 @@ msgstr ""
msgid "(Log activity when running in background)"
msgstr ""
-msgid "Enter the time format (see 'man 3 strftime' for possible formats) "
-msgstr "Geef het formaat van de tijd (zie 'man 3 strftime')"
-
msgid "Enter the number of seconds (0 not to be warned before an appointment)"
msgstr "Geef het aantal seconden (0 voor geen waarschuwing voor een afspraak)."
@@ -1302,18 +1415,46 @@ msgstr "Herhalingstype is niet coherent"
msgid "System event"
msgstr ""
-msgid "unknown repetition type"
-msgstr ""
-
msgid "unknown character"
msgstr "onbekend karakter"
+#, c-format
+msgid "recurrence error: not on start day (%s)"
+msgstr ""
+
+msgid "illegel date in event"
+msgstr ""
+
+msgid "date error in event"
+msgstr "datumfout in gebeurtenis"
+
+msgid "month day is zero"
+msgstr ""
+
+msgid "no daily frequency check"
+msgstr ""
+
+msgid "illegal BYDAY value"
+msgstr ""
+
msgid "event not found"
msgstr "Gebeurtenis niet gevonden"
msgid "appointment not found"
msgstr "afspraak niet gevonden"
+msgid "syntax error in bymonthday"
+msgstr ""
+
+msgid "syntax error in bywday"
+msgstr ""
+
+msgid "syntax error in bymonth"
+msgstr ""
+
+msgid "illegal bymonth value"
+msgstr ""
+
msgid "syntax error in item date"
msgstr "syntaxfout in datum van item"
@@ -1321,10 +1462,6 @@ msgid "date error in item exception"
msgstr ""
#, c-format
-msgid "Could not remove calcurse lock file: %s\n"
-msgstr ""
-
-#, c-format
msgid "Error setting signal #%d : %s\n"
msgstr ""
@@ -1361,6 +1498,10 @@ msgstr ""
msgid "Invalid time: start time must come before end time!"
msgstr ""
+#, c-format
+msgid "Repetition must begin on start day (%s)."
+msgstr ""
+
msgid "Enter end date (and/or time) or duration ('?' for input formats):"
msgstr ""
@@ -1386,51 +1527,111 @@ msgstr ""
msgid "Invalid date format - try again:."
msgstr ""
-msgid "Enter the new repetition type:"
+msgid "Limit repetition to listed days."
+msgstr ""
+
+msgid "Expand repetition to listed days."
+msgstr ""
+
+msgid "Expand repetition to listed days, either all or 1st, 2nd, ... of month."
+msgstr ""
+
+msgid "Note: limit to monthdays, if any."
+msgstr ""
+
+msgid "Expand repetition to listed days, either all or 1st, 2nd, ... of year."
+msgstr ""
+
+msgid "Note: expand to listed months, if any; limit to monthdays, if any."
+msgstr ""
+
+msgid "Limit repetition to listed months."
+msgstr ""
+
+msgid "Expand repetition to listed months."
msgstr ""
-msgid "(d)aily"
-msgstr "(d)agelijks"
+msgid "Limit repetition to listed days of month."
+msgstr ""
-msgid "(w)eekly"
-msgstr "(w)ekelijks"
+msgid "Expand repetition to listed days of month."
+msgstr ""
-msgid "(m)onthly"
-msgstr "(m)aandelijks"
+#, c-format
+msgid "Weekdays %s|..|%s, space-separated list, '?' for help:"
+msgstr ""
-msgid "(y)early"
-msgstr "(y)aarlijks"
+#, c-format
+msgid ""
+"Weekdays [n]%s|..|[n]%s, space-separated list, n=1,-1,..,5,-5, '?' for help:"
+msgstr ""
#, c-format
-msgid "(currently using %s)"
+msgid ""
+"Weekdays [n]%s|..|[n]%s, space-separated list, n=1,-1,..,53,-53, '?' for "
+"help:"
+msgstr ""
+
+msgid "Months 1|..|12, space-separated list, '?' for help:"
+msgstr ""
+
+msgid "Monthdays 1|..|31 or -1|..|-31, space-separated list, '?' for help:"
+msgstr ""
+
+msgid "Invalid format - try again."
+msgstr ""
+
+msgid "Press any key to continue."
+msgstr ""
+
+msgid "Base period:"
+msgstr ""
+
+msgid "day"
+msgstr ""
+
+msgid "week"
+msgstr ""
+
+msgid "month"
+msgstr ""
+
+msgid "year"
msgstr ""
msgid "[dwmy]"
msgstr "[dwmy]"
-msgid "Invalid frequency."
+msgid "Frequency:"
msgstr ""
-msgid "Enter the repetition frequency:"
+msgid "Invalid frequency."
msgstr ""
-msgid "Enter end date or duration ('?' for input formats):"
+msgid "Until date, increment or repeat count ('?' for input formats):"
msgstr ""
#, c-format
-msgid "Date: %s (year or month may be omitted). Endless duration: 0."
+msgid "Date: %s (year, month may be omitted, endless: 0)."
msgstr ""
-msgid "Duration in days: +dd. Duration in weeks and days: +??w??d."
+msgid "Increment: +?? (days) or: +??w??d (weeks). Repeat count: #?? (number)."
msgstr ""
#, c-format
-msgid "Invalid date: end date must come after start date (%s)."
+msgid "Invalid date: until date must come after start date (%s)."
msgstr ""
msgid "Invalid date."
msgstr ""
+msgid "Repeat count is too big."
+msgstr ""
+
+#, c-format
+msgid "Repetition must begin on start day (%s); any change discarded."
+msgstr ""
+
msgid "Description"
msgstr ""
@@ -1469,32 +1670,39 @@ msgstr ""
msgid "Invalid start time."
msgstr ""
-msgid "Do you really want to delete this item?"
+msgid ""
+"This item is recurrent and has a note attached to it. Delete (s)elected "
+"occurrence, (a)ll occurrences, or just its (n)ote?"
msgstr ""
-msgid "This item is recurrent. Delete (a)ll occurences or just this (o)ne?"
+msgid "[san]"
msgstr ""
-msgid "[ao]"
+msgid ""
+"This item has a note attached to it. Delete (s)elected occurrence or just "
+"its (n)ote?"
msgstr ""
-msgid "This item has a note attached to it. Delete (i)tem or just its (n)ote?"
+msgid "[sn]"
msgstr ""
-msgid "[in]"
+msgid ""
+"This item is recurrent. Delete (s)elected occurrence or (a)ll occurrences?"
msgstr ""
-msgid "Enter the repetition type:"
+msgid "[sa]"
msgstr ""
-#, c-format
-msgid "Date: %s (year or month may be omitted). Endless duration: '0'."
+msgid "Confirm deletion. Delete (s)elected occurrence? Press (s) to confirm."
msgstr ""
-msgid "This item is already a repeated one."
-msgstr "Dit item wordt al herhaald."
+msgid "[s]"
+msgstr ""
+
+msgid "Already repeated."
+msgstr ""
-msgid "wrong item type"
+msgid "A (s)imple or (a)dvanced repetition?"
msgstr ""
msgid "Enter the new TODO item:"
@@ -1518,6 +1726,10 @@ msgstr ""
msgid "TODO:"
msgstr ""
+#, c-format
+msgid "Could not remove calcurse lock file: %s\n"
+msgstr ""
+
msgid "/!\\ INTERNAL ERROR /!\\"
msgstr "/!\\ INTERNE FOUT /!\\"
@@ -1576,7 +1788,7 @@ msgstr ""
msgid ""
"\n"
-"Copyright (c) 2004-2017 calcurse Development Team.\n"
+"Copyright (c) 2004-2023 calcurse Development Team.\n"
"This is free software; see the source for copying conditions.\n"
msgstr ""
diff --git a/po/pt_BR.po b/po/pt_BR.po
index 3ebeeac..bcee694 100644
--- a/po/pt_BR.po
+++ b/po/pt_BR.po
@@ -1,28 +1,36 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR calcurse Development Team <misc@calcurse.org>
-# This file is distributed under the same license as the PACKAGE package.
+# This file is distributed under the same license as the calcurse package.
#
# Translators:
# Fabio Bianchi <fabiobianchi10@gmail.com>, 2019
# Rafael Fontenelle <rffontenelle@gmail.com>, 2012-2014
+# Vitor Henrique, 2023
msgid ""
msgstr ""
"Project-Id-Version: calcurse\n"
"Report-Msgid-Bugs-To: bugs@calcurse.org\n"
-"POT-Creation-Date: 2019-06-16 15:27-0400\n"
-"PO-Revision-Date: 2019-05-30 11:52+0000\n"
-"Last-Translator: Lukas Fleischer\n"
-"Language-Team: Portuguese (Brazil) (http://www.transifex.com/lfleischer/"
+"POT-Creation-Date: 2024-01-26 18:28+0100\n"
+"PO-Revision-Date: 2013-07-23 08:43+0000\n"
+"Last-Translator: Vitor Henrique, 2023\n"
+"Language-Team: Portuguese (Brazil) (http://app.transifex.com/lfleischer/"
"calcurse/language/pt_BR/)\n"
"Language: pt_BR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % "
+"1000000 == 0 ? 1 : 2;\n"
msgid "null pointer"
msgstr "ponteiro nulo"
+msgid "illegal date in appointment"
+msgstr ""
+
+msgid "error in appointment description"
+msgstr ""
+
msgid "date error in appointment"
msgstr "erro de data no agendamento"
@@ -35,16 +43,9 @@ msgid ""
"calcurse -Q [--from <date>] [--to <date>] [--days <number>]\n"
"calcurse -a | -d <date> | -d <number> | -n | -r[<number>] | -s[<date>] | -"
"t[<number>]\n"
-"calcurse -h | -v | --status | -G | -P | -g | -i <file> | -x[<file>] | --"
+"calcurse -h | -v | --status | -G | -P | -g | -i <file> | -x[<format>] | --"
"daemon"
msgstr ""
-"Uso:\n"
-"calcurse [-D <directory>] [-C <directory>] [-c <calendar file>]\n"
-"calcurse -Q [--from <date>] [--to <date>] [--days <number>]\n"
-"calcurse -a | -d <date> | -d <number> | -n | -r[<number>] | -s[<date>] | -"
-"t[<number>]\n"
-"calcurse -h | -v | --status | -G | -P | -g | -i <file> | -x[<file>] | --"
-"daemon"
msgid "Try `calcurse -h` for more information."
msgstr "Tente `calcurse -h` para mais informações."
@@ -53,8 +54,8 @@ msgstr "Tente `calcurse -h` para mais informações."
msgid "calcurse %s -- text-based organizer\n"
msgstr "calcurse %s -- agenda baseada em texto\n"
-msgid "Copyright (c) 2004-2017 calcurse Development Team."
-msgstr "Copyright (c) 2004-2017 calcurse Equipe de Desenvolvimento."
+msgid "Copyright (c) 2004-2023 calcurse Development Team."
+msgstr ""
msgid "This is free software; see the source for copying conditions."
msgstr ""
@@ -122,13 +123,13 @@ msgstr ""
" -c, --calendar <file> O arquivo correspondente da agenda a ser usada"
msgid " -C, --confdir <dir> The configuration directory to use"
-msgstr ""
+msgstr " -C, --confdir <dir> O diretório de configuração a ser usado"
msgid " --daemon Run notification daemon in the background"
msgstr " --daemon Executa a notificação em segundo plano"
msgid " -D, --datadir <dir> The data directory to use"
-msgstr ""
+msgstr " -D, --datadir <dir> O diretório de dados a ser usado"
msgid " -g, --gc Run the garbage collector"
msgstr " -g, --gc Execute o coletor de lixo"
@@ -139,8 +140,8 @@ msgstr " -h, --help Mostra o texto de ajuda"
msgid " -i, --import <file> Import iCal data from file"
msgstr " -i, --import <file> Importa o arquivo iCal"
-msgid " -q, --quiet Suppress system dialogs"
-msgstr " -q, --quiet Esconde os diálogos do sistema"
+msgid " -q, --quiet Suppress import/export result message"
+msgstr ""
msgid " --read-only Do not save configuration or data files"
msgstr ""
@@ -296,8 +297,8 @@ msgstr "Existem alterações não salvas. Salvar?"
msgid "Do you really want to quit?"
msgstr "Você certeza que deseja sair?"
-msgid "Command: [ h(elp) | w(rite)(!) | q(uit)(!) | wq(!) ]"
-msgstr "Comando: [ h(ajuda) | w(escrever)(!) | q(sair)(!) | wq(!) ]"
+msgid "Command: [ h(elp) | w(rite)(!) | q(uit)(!) | wq(!) | n(ext) | p(rev) ]"
+msgstr ""
msgid "Read-only mode - use w!"
msgstr "Modo somente-leitura - usar w!"
@@ -309,6 +310,18 @@ msgstr "Existem alterações não salvas - use w ou q!"
msgid "Help topic does not exist: %s"
msgstr "Tópico de ajuda não existe: %s"
+msgid "Select a repeating item in the appointments panel."
+msgstr ""
+
+msgid "Not a repeating item."
+msgstr ""
+
+msgid "Last occurrence."
+msgstr ""
+
+msgid "First occurrence."
+msgstr ""
+
#, c-format
msgid "No such command: %s"
msgstr "Comando inexistente: %s"
@@ -332,19 +345,19 @@ msgstr ""
#, c-format
msgid "unknown user option: \"%s\" (ignored)"
-msgstr ""
+msgstr "opção de usuário desconhecida: \"%s\" (ignorada)"
#, c-format
msgid "invalid option format: \"%s\" (ignored)"
-msgstr ""
+msgstr "formato de opção inválido: \"%s\" (ignorado)"
#, c-format
msgid "unknown user option: \"%s\" (disabled)"
-msgstr ""
+msgstr "opção de usuário desconhecida: \"%s\" (desabilitada)"
#, c-format
msgid "invalid option format: \"%s\" (disabled)"
-msgstr ""
+msgstr "formato de opção inválido: \"%s\" (desabilitada)"
msgid "layout configuration"
msgstr "Configuração de layout"
@@ -406,6 +419,9 @@ msgstr ""
msgid "(insert an empty line after each appointment)"
msgstr ""
+msgid "(text for a day without events and appointments)"
+msgstr ""
+
msgid "(display more than one day in the appointments panel)"
msgstr ""
@@ -435,17 +451,6 @@ msgstr ""
"(se definida como SIM, uma confirmação será necessária antes da exclusão de "
"um evento)"
-msgid "(if set to YES, messages about loaded and saved data will be displayed)"
-msgstr ""
-"(se definida como SIM, mensagens sobre dados carregados e salvados serão "
-"exibidos)"
-
-msgid "Monday"
-msgstr "Segunda-feira"
-
-msgid "Sunday"
-msgstr "Domingo"
-
msgid "(specifies the first day of week in the calendar view)"
msgstr "(especifica o primeiro dia da semana na visão de calendário)"
@@ -470,17 +475,26 @@ msgstr "(posição do cabeçalho no painel de agendamentos)"
msgid "(Format of the date displayed in the appointments panel)"
msgstr "(Formato da data exibida no painel de agendamentos)"
+msgid "(Format of the time displayed in the appointments panel)"
+msgstr ""
+
+msgid "Enter a text string (an empty string for the default text)"
+msgstr "Insira um texto (deixe vazio para o texto padrão)"
+
msgid "Enter the date format (see 'man 3 strftime' for possible formats) "
msgstr ""
-"Entre com o formato da data (veja \"man 3 strftime\" para formatos "
+"Insira o formato da data (veja \"man 3 strftime\" para formatos possíveis) "
+
+msgid "Enter the time format (see 'man 3 strftime' for possible formats) "
+msgstr ""
+"Insira o formato do horário (veja \"man 3 strftime\" para formatos "
"possíveis) "
msgid "Enter the date format: "
-msgstr "Entre com formato da data: "
+msgstr "Insira o formato da data: "
msgid "Enter the delay, in minutes, between automatic saves (0 to disable) "
-msgstr ""
-"Entre com a distância, em minutos, entre salvamentos (0 = desabilitar) "
+msgstr "Insira a distância, em minutos, entre salvamentos (0 = desabilitar) "
msgid "general options"
msgstr "Opções Gerais"
@@ -488,8 +502,8 @@ msgstr "Opções Gerais"
msgid "Undefined option!"
msgstr "Opção indefinida!"
-msgid "undefined"
-msgstr "indefinida"
+msgid "UNDEFINED"
+msgstr ""
msgid "keys configuration"
msgstr "Configuração das Teclas"
@@ -501,8 +515,8 @@ msgstr "Pressione a tecla que você quer designar para:"
msgid "The key '%s' is already used for %s. Choose another one."
msgstr "A tecla '%s' já está em uso para %s. Selecione outra."
-msgid "Some actions do not have any associated key bindings!"
-msgstr "Algumas ações não têm teclas de atalho associadas!"
+msgid "Some actions are left undefined!"
+msgstr ""
msgid ""
"Sorry, colors are not supported by your terminal\n"
@@ -518,7 +532,7 @@ msgstr "Não foi possível salvarCould not save %s."
msgid "unknown item type"
msgstr "tipo de item desconhecido"
-msgid "(none)"
+msgid "Note:"
msgstr ""
msgid "Event:"
@@ -580,6 +594,7 @@ msgid "sleeping at %s for %d second\n"
msgid_plural "sleeping at %s for %d seconds\n"
msgstr[0] "Dormir em %s por %d segundo\n"
msgstr[1] "Dormir em %s por %d segundos\n"
+msgstr[2] "Dormir em %s por %d segundos\n"
#, c-format
msgid "awakened at %s\n"
@@ -589,11 +604,11 @@ msgstr "Acordou em %s\n"
msgid "Could not stop calcurse daemon: %s\n"
msgstr "Não foi possível parar o daemon do calcurse: %s\n"
-msgid "date error in event"
-msgstr "erro na data em evento"
+msgid "illegal date in event"
+msgstr ""
-msgid "date error in the event\n"
-msgstr "erro de data no evento\n"
+msgid "date error in event\n"
+msgstr ""
msgid "Internal error: line too long"
msgstr "Erro interno: linha muito comprida"
@@ -604,55 +619,138 @@ msgstr "memória insuficiente"
msgid "unknown ical type"
msgstr "tipo de ical desconhecido"
-msgid "recurrence rule malformed."
-msgstr "regra de recorrência mal-formulada."
+msgid "(empty)"
+msgstr ""
+
+msgid "ical_store_event: out of memory"
+msgstr ""
+
+msgid "need DTSTART to determine event type."
+msgstr ""
-msgid "recurrence frequency not found."
-msgstr "periodicidade de recorrência não encontrada."
+msgid "malformed recurrence line."
+msgstr ""
-msgid "recurrence frequency not recognized."
-msgstr "periodicidade de recorrência não reconhecida."
+msgid "frequency not set in rrule."
+msgstr ""
-msgid "recurrence exception dates malformed."
-msgstr "Exceção de datas de recorrência mal-formulada."
+msgid "frequency absent in rrule."
+msgstr ""
-msgid "description malformed."
-msgstr "descrição mal-formulada."
+msgid "rrule frequency not supported."
+msgstr ""
-msgid "could not get entire item description."
-msgstr "não foi possível adquirir a descrição completa do item."
+msgid "invalid interval."
+msgstr ""
-msgid "could not retrieve item summary."
-msgstr "não foi possível adquirir sumário do item."
+msgid "either until or count."
+msgstr ""
-msgid "item start date is not defined."
-msgstr "data de início do ítem não foi definida."
+msgid "missing until value."
+msgstr ""
-msgid "item has a negative duration."
-msgstr "item tem uma duração negativa."
+msgid "invalid until format."
+msgstr ""
-msgid "item could not be identified."
-msgstr "item não pôde ser identificado."
+msgid "invalid count value."
+msgstr ""
+
+msgid "invalid bymonth list."
+msgstr ""
+
+msgid "invalid bymonthday list."
+msgstr ""
+
+msgid "invalid byday list."
+msgstr ""
+
+msgid "invalid exception date value type."
+msgstr ""
+
+msgid "malformed exceptions line."
+msgstr ""
+
+msgid "invalid exception."
+msgstr ""
+
+#, c-format
+msgid "malformed %s line."
+msgstr ""
+
+#, c-format
+msgid "malformed %s."
+msgstr ""
+
+msgid "malformed summary line."
+msgstr ""
+
+msgid "malformed summary."
+msgstr ""
+
+msgid "item start date not defined."
+msgstr ""
+
+msgid "malformed start time line."
+msgstr ""
+
+msgid "invalid or malformed event start time."
+msgstr ""
+
+msgid "invalid end time value type."
+msgstr ""
+
+msgid "malformed end time line."
+msgstr ""
+
+msgid "malformed event end time."
+msgstr ""
+
+msgid "end must be later than start."
+msgstr ""
+
+msgid "either end or duration."
+msgstr ""
-msgid "event start time malformed."
+msgid "malformed duration line."
msgstr ""
-msgid "could not retrieve event start time."
-msgstr "não foi possível adquirir hora de início do evento."
+msgid "invalid duration."
+msgstr ""
-msgid "event end time malformed."
+msgid "exception date, but no recurrence rule."
msgstr ""
-msgid "could not retrieve event end time."
-msgstr "não foi possível adquirir hora de término do evento."
+msgid "multi-day event changed to one-day event"
+msgstr ""
+
+#, c-format
+msgid "Location: %s"
+msgstr ""
+
+#, c-format
+msgid "Comment: %s"
+msgstr ""
+
+#, c-format
+msgid "rrule does not match start day (%s)."
+msgstr ""
+
+msgid "item could not be identified."
+msgstr "item não pôde ser identificado."
+
+msgid "only one description allowed."
+msgstr ""
-msgid "item duration malformed."
-msgstr "duração de item mal-formulada."
+msgid "only one location allowed."
+msgstr ""
msgid "The ical file seems to be malformed. The end of item was not found."
msgstr ""
"O arquivo ical parece estar mal-formulada. O fim do item não foi encontrado."
+msgid "could not retrieve item summary."
+msgstr "não foi possível adquirir sumário do item."
+
msgid "item priority is invalid (must be between 0 and 9)."
msgstr ""
@@ -725,6 +823,21 @@ msgstr "formato errado no agendamento ou evento"
msgid "syntax error in item repetition"
msgstr "erro de sintaxe na repetição do item"
+msgid "syntax error in until date"
+msgstr ""
+
+msgid "until date error"
+msgstr ""
+
+msgid "BYMONTHDAY illegal with WEEKLY"
+msgstr ""
+
+msgid "missing end of recurrence"
+msgstr ""
+
+msgid "syntax error in item state"
+msgstr ""
+
msgid "failed to open todo file"
msgstr "falha na abertura do arquivo de tarefas"
@@ -734,54 +847,49 @@ msgstr ""
msgid "failed to open key file"
msgstr "falha na abertura do arquivo de teclas"
-msgid ""
-"\n"
-"Too many errors while reading configuration file!\n"
-"Please backup your keys file, remove it from directory, and launch calcurse "
-"again.\n"
-msgstr ""
-"\n"
-"Muitos erros de leitura do arquivo de configuração!\n"
-"Favor faça backup de seus arquivos de teclas, exclua-o de seu diretório e "
-"carregue calcurse novamente.\n"
-
msgid "Could not read key label"
msgstr "Não foi possível ler o rótulo de tecla"
-msgid "Key label not recognized"
-msgstr "Rótulo de tecla não reconhecida"
-
#, c-format
-msgid "Error reading key: \"%s\""
-msgstr "Erro na leitura da tecla: \"%s\""
+msgid "Key label not recognized: \"%s\""
+msgstr ""
#, c-format
-msgid "\"%s\" assigned multiple times!"
-msgstr "\"%s\" alocada múltiplas vezes!"
+msgid "No keys assigned to \"%s\"."
+msgstr ""
-msgid "There were some errors when loading keys file."
+#, c-format
+msgid "Keyname not recognized: \"%s\""
msgstr ""
-msgid "Too many errors while reading keys file, aborting..."
-msgstr "Erros demais na leitura do arquivo de chaves, abortando..."
+#, c-format
+msgid "\"%s\" assigned twice: \"%s\"."
+msgstr ""
#, c-format
-msgid "FATAL ERROR: could not create %s: %s\n"
-msgstr "ERRO FATAL: não foi possível criar %s: %s\n"
+msgid ""
+"Action \"%s\" absent, but default key \"%s\" assigned to another action."
+msgstr ""
-msgid "Press [ENTER] to continue"
-msgstr "Pressione [ENTER] para continuar"
+msgid "Errors in the keys file."
+msgstr ""
-msgid "Welcome to Calcurse. Missing data files were created."
+msgid "Remove offending line(s) from the keys file, aborting..."
msgstr ""
-"Bem-vindo ao Calcurse. Arquivos de dados não encontrados foram criados."
-msgid "Data files found. Data will be loaded now."
-msgstr "Arquivos de dados encontrados. Os dados serão carregados agora."
+msgid "Some actions do not have any associated key bindings!"
+msgstr "Algumas ações não têm teclas de atalho associadas!"
+
+#, c-format
+msgid "FATAL ERROR: could not create %s: %s\n"
+msgstr "ERRO FATAL: não foi possível criar %s: %s\n"
msgid "The data were successfully exported"
msgstr "Os dados foram exportados com sucesso"
+msgid "Press [ENTER] to continue"
+msgstr "Pressione [ENTER] para continuar"
+
msgid "unknown export type"
msgstr "tipo de exportação desconhecido"
@@ -789,7 +897,7 @@ msgid "wrong export mode"
msgstr "modo de exportação errado"
msgid "Enter the file name to import data from:"
-msgstr "Entre com o nome do arquivo de onde serão importados os dados:"
+msgstr "Insira o nome do arquivo de onde serão importados os dados:"
#, c-format
msgid "Import process report: %04d lines read"
@@ -809,18 +917,21 @@ msgid "%d app"
msgid_plural "%d apps"
msgstr[0] "%d agend."
msgstr[1] "%d agends."
+msgstr[2] "%d agends."
#, c-format
msgid "%d event"
msgid_plural "%d events"
msgstr[0] "%d evento"
msgstr[1] "%d eventos"
+msgstr[2] "%d eventos"
#, c-format
msgid "%d todo"
msgid_plural "%d todos"
msgstr[0] "%d tarefa"
msgstr[1] "%d tarefas"
+msgstr[2] "%d tarefas"
#, c-format
msgid "%d skipped"
@@ -854,7 +965,9 @@ msgstr ""
msgid "Invalid delay"
msgstr "Atraso inválido"
-msgid "Periodic save: data files have changed. Save cancelled."
+msgid ""
+"Periodic save cancelled. Data files have changed. Save and merge "
+"interactively"
msgstr ""
#, c-format
@@ -901,6 +1014,9 @@ msgstr "Colar"
msgid "Chg Win"
msgstr "MudarJan"
+msgid "Prev Win"
+msgstr ""
+
msgid "Import"
msgstr "Importar"
@@ -1021,6 +1137,15 @@ msgid ""
"# via the key configuration menu of the interactive user\n"
"# interface. It should not be edited directly.\n"
msgstr ""
+"#\n"
+"# Arquivo de configuração das teclas do Calcurse\n"
+"#\n"
+"# Nesse arquivo, são definidos os atalhos de teclado\n"
+"# usados pelo Calcurse. Ele é gerado automaticamente\n"
+"# pelo Calcurse e é mantido por meio do menu de\n"
+"# configuração de teclas da interface interativa do usuário\n"
+"# interface interativa do usuário. Ele não deve ser editado\n"
+"# diretamente.\n"
msgid "FATAL ERROR: could not create default keys file."
msgstr "ERRO FATAL: não foi possível criar arquivo de teclas padrões."
@@ -1079,6 +1204,9 @@ msgstr "Cola um item na posição atual."
msgid "Select next panel in calcurse main screen."
msgstr "Seleciona o próximo painel na tela principal do calcurse."
+msgid "Select previous panel in calcurse main screen."
+msgstr ""
+
msgid "Import data from an external file."
msgstr "Importa dados a partir de um arquivo externo."
@@ -1224,8 +1352,8 @@ msgid "FATAL ERROR: null file pointer."
msgstr "ERRO FATAL: ponteiro nulo de arquivo."
#, c-format
-msgid "When adding default key for \"%s\", \"%s\" was already assigned!"
-msgstr "Quando adicionava tecla padrão para \"%s\", \"%s\" já foi designada!"
+msgid "Default key(s) assigned to %d action%s."
+msgstr ""
msgid "xmalloc: zero size"
msgstr "xmalloc: tamanho zero"
@@ -1317,12 +1445,6 @@ msgstr " blocos não livres: %u\n"
msgid "Warning: could not open %s, Aborting..."
msgstr "Aviso: não foi possível abrir %s. Abortando..."
-msgid "error while launching command: could not fork"
-msgstr "erro durante o lançamento do comando: não foi possível realizar fork"
-
-msgid "error while launching command"
-msgstr "erro durante o lançamento do comando"
-
msgid "(if set to YES, notify-bar will be displayed)"
msgstr "(Se definida como SIM, a barra de notificação será exibida)"
@@ -1335,8 +1457,8 @@ msgstr "(Formato de horário a ser exibido dentro da barra de notificação)"
msgid ""
"(Warn user if an appointment is within next 'notify-bar_warning' seconds)"
msgstr ""
-"(Avisa o usuário se um agendamento ocorrerá nos próximos \"notify-bar_warning"
-"\" segundos)"
+"(Avisa o usuário se um agendamento ocorrerá nos próximos \"notify-"
+"bar_warning\" segundos)"
msgid "(Command used to notify user of an upcoming appointment)"
msgstr "(Comando usado para notificar usuário de um agendamento próximo)"
@@ -1350,17 +1472,12 @@ msgstr "(Executa em plano de fundo para pegar notificações depois de sair)"
msgid "(Log activity when running in background)"
msgstr "(Registra atividades quando estiver executando em plano de fundo)"
-msgid "Enter the time format (see 'man 3 strftime' for possible formats) "
-msgstr ""
-"Entre com o formato do horário (veja \"man 3 strftime\" para formatos "
-"possíveis) "
-
msgid "Enter the number of seconds (0 not to be warned before an appointment)"
msgstr ""
-"Entre com o número de segundos (0 para não ser avisado antes do agendamento)"
+"Insira o número de segundos (0 para não ser avisado antes do agendamento)"
msgid "Enter the notification command "
-msgstr "Entre com o comando de notificação "
+msgstr "Insira o comando de notificação "
msgid "notification options"
msgstr "opções de notificação"
@@ -1373,18 +1490,46 @@ msgstr ""
msgid "System event"
msgstr ""
-msgid "unknown repetition type"
-msgstr "tipo de repetição desconhecida"
-
msgid "unknown character"
msgstr "caractere desconhecido"
+#, c-format
+msgid "recurrence error: not on start day (%s)"
+msgstr ""
+
+msgid "illegel date in event"
+msgstr ""
+
+msgid "date error in event"
+msgstr "erro na data em evento"
+
+msgid "month day is zero"
+msgstr ""
+
+msgid "no daily frequency check"
+msgstr ""
+
+msgid "illegal BYDAY value"
+msgstr ""
+
msgid "event not found"
msgstr "evento não encontrado"
msgid "appointment not found"
msgstr "agendamento não encontrado"
+msgid "syntax error in bymonthday"
+msgstr ""
+
+msgid "syntax error in bywday"
+msgstr ""
+
+msgid "syntax error in bymonth"
+msgstr ""
+
+msgid "illegal bymonth value"
+msgstr ""
+
msgid "syntax error in item date"
msgstr "erro de sintaxe no item data"
@@ -1392,10 +1537,6 @@ msgid "date error in item exception"
msgstr "erro de data em exceção de item"
#, c-format
-msgid "Could not remove calcurse lock file: %s\n"
-msgstr "Não foi possível excluir arquivo de trava do Calcurse: %s\n"
-
-#, c-format
msgid "Error setting signal #%d : %s\n"
msgstr "Erro na definição de sinal #%d : %s\n"
@@ -1432,6 +1573,10 @@ msgstr ""
msgid "Invalid time: start time must come before end time!"
msgstr ""
+#, c-format
+msgid "Repetition must begin on start day (%s)."
+msgstr ""
+
msgid "Enter end date (and/or time) or duration ('?' for input formats):"
msgstr ""
@@ -1454,55 +1599,114 @@ msgstr "Insira uma descrição para o novo item:"
msgid "Exception days:"
msgstr ""
-#, fuzzy
msgid "Invalid date format - try again:."
-msgstr "formato de data inválido: %s"
+msgstr ""
-msgid "Enter the new repetition type:"
-msgstr "Insira o novo tipo de repetição:"
+msgid "Limit repetition to listed days."
+msgstr ""
+
+msgid "Expand repetition to listed days."
+msgstr ""
+
+msgid "Expand repetition to listed days, either all or 1st, 2nd, ... of month."
+msgstr ""
+
+msgid "Note: limit to monthdays, if any."
+msgstr ""
+
+msgid "Expand repetition to listed days, either all or 1st, 2nd, ... of year."
+msgstr ""
+
+msgid "Note: expand to listed months, if any; limit to monthdays, if any."
+msgstr ""
+
+msgid "Limit repetition to listed months."
+msgstr ""
+
+msgid "Expand repetition to listed months."
+msgstr ""
-msgid "(d)aily"
-msgstr "(d)iária"
+msgid "Limit repetition to listed days of month."
+msgstr ""
-msgid "(w)eekly"
-msgstr "(s)emanal"
+msgid "Expand repetition to listed days of month."
+msgstr ""
-msgid "(m)onthly"
-msgstr "(m)ensal"
+#, c-format
+msgid "Weekdays %s|..|%s, space-separated list, '?' for help:"
+msgstr ""
-msgid "(y)early"
-msgstr "(a)nual"
+#, c-format
+msgid ""
+"Weekdays [n]%s|..|[n]%s, space-separated list, n=1,-1,..,5,-5, '?' for help:"
+msgstr ""
#, c-format
-msgid "(currently using %s)"
-msgstr "(atualmente usando %s)"
+msgid ""
+"Weekdays [n]%s|..|[n]%s, space-separated list, n=1,-1,..,53,-53, '?' for "
+"help:"
+msgstr ""
+
+msgid "Months 1|..|12, space-separated list, '?' for help:"
+msgstr ""
+
+msgid "Monthdays 1|..|31 or -1|..|-31, space-separated list, '?' for help:"
+msgstr ""
+
+msgid "Invalid format - try again."
+msgstr ""
+
+msgid "Press any key to continue."
+msgstr ""
+
+msgid "Base period:"
+msgstr ""
+
+msgid "day"
+msgstr ""
+
+msgid "week"
+msgstr ""
+
+msgid "month"
+msgstr ""
+
+msgid "year"
+msgstr ""
msgid "[dwmy]"
msgstr "[dsma]"
-msgid "Invalid frequency."
+msgid "Frequency:"
msgstr ""
-msgid "Enter the repetition frequency:"
+msgid "Invalid frequency."
msgstr ""
-msgid "Enter end date or duration ('?' for input formats):"
+msgid "Until date, increment or repeat count ('?' for input formats):"
msgstr ""
#, c-format
-msgid "Date: %s (year or month may be omitted). Endless duration: 0."
+msgid "Date: %s (year, month may be omitted, endless: 0)."
msgstr ""
-msgid "Duration in days: +dd. Duration in weeks and days: +??w??d."
+msgid "Increment: +?? (days) or: +??w??d (weeks). Repeat count: #?? (number)."
msgstr ""
#, c-format
-msgid "Invalid date: end date must come after start date (%s)."
+msgid "Invalid date: until date must come after start date (%s)."
msgstr ""
msgid "Invalid date."
msgstr ""
+msgid "Repeat count is too big."
+msgstr ""
+
+#, c-format
+msgid "Repetition must begin on start day (%s); any change discarded."
+msgstr ""
+
msgid "Description"
msgstr "Descrição"
@@ -1534,7 +1738,7 @@ msgid ""
msgstr ""
msgid "Enter description:"
-msgstr "Insera uma descrição:"
+msgstr "Insira uma descrição:"
#, c-format
msgid "Date: %s (and/or time), year or month may be omitted."
@@ -1543,36 +1747,40 @@ msgstr ""
msgid "Invalid start time."
msgstr ""
-msgid "Do you really want to delete this item?"
-msgstr "Tem certeza que deseja excluir este item?"
+msgid ""
+"This item is recurrent and has a note attached to it. Delete (s)elected "
+"occurrence, (a)ll occurrences, or just its (n)ote?"
+msgstr ""
-msgid "This item is recurrent. Delete (a)ll occurences or just this (o)ne?"
+msgid "[san]"
msgstr ""
-"Este item é recorrente. Excluir (t)odas as ocorrências ou (s)omente esta?"
-msgid "[ao]"
-msgstr "[ts]"
+msgid ""
+"This item has a note attached to it. Delete (s)elected occurrence or just "
+"its (n)ote?"
+msgstr ""
-msgid "This item has a note attached to it. Delete (i)tem or just its (n)ote?"
+msgid "[sn]"
msgstr ""
-"Este item tem uma anotação anexada a ele. Excluir o (i)tem ou somente sua "
-"(n)ota?"
-msgid "[in]"
-msgstr "[in]"
+msgid ""
+"This item is recurrent. Delete (s)elected occurrence or (a)ll occurrences?"
+msgstr ""
-msgid "Enter the repetition type:"
-msgstr "Insira o tipo da repetição:"
+msgid "[sa]"
+msgstr ""
-#, c-format
-msgid "Date: %s (year or month may be omitted). Endless duration: '0'."
+msgid "Confirm deletion. Delete (s)elected occurrence? Press (s) to confirm."
msgstr ""
-msgid "This item is already a repeated one."
-msgstr "Este é um item repetido."
+msgid "[s]"
+msgstr ""
+
+msgid "Already repeated."
+msgstr ""
-msgid "wrong item type"
-msgstr "tipo de item errado"
+msgid "A (s)imple or (a)dvanced repetition?"
+msgstr ""
msgid "Enter the new TODO item:"
msgstr "Insira o novo item da TAREFA:"
@@ -1597,6 +1805,10 @@ msgstr "Insira a nova descrição da TAREFA:"
msgid "TODO:"
msgstr "TAREFA:"
+#, c-format
+msgid "Could not remove calcurse lock file: %s\n"
+msgstr "Não foi possível excluir arquivo de trava do Calcurse: %s\n"
+
msgid "/!\\ INTERNAL ERROR /!\\"
msgstr "/!\\ ERRO INTERNO /!\\"
@@ -1655,7 +1867,7 @@ msgstr "Uso: calcurse-upgrade [-h|-v|--config <arquivo>]"
msgid ""
"\n"
-"Copyright (c) 2004-2017 calcurse Development Team.\n"
+"Copyright (c) 2004-2023 calcurse Development Team.\n"
"This is free software; see the source for copying conditions.\n"
msgstr ""
diff --git a/po/ru.po b/po/ru.po
index 65c3399..7243440 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -1,37 +1,53 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR calcurse Development Team <misc@calcurse.org>
-# This file is distributed under the same license as the PACKAGE package.
+# This file is distributed under the same license as the calcurse package.
#
# Translators:
# ÐлекÑей Мехоношин <ruskidecko@gmail.com>, 2011-2012
# ÐлекÑей Мехоношин <ruskidecko@gmail.com>, 2012-2014,2016
+# Vladimir Kalashnikov, 2023
# Lukas Fleischer <transifex@cryptocrack.de>, 2011
-# ÐлекÑей Мехоношин <ruskidecko@gmail.com>, 2016-2017,2019
+# Vladimir Kalashnikov, 2023
+# Vladimir Kalashnikov, 2023
+# Vlad Savikin, 2021
+# Vlad Savikin, 2021
+# ÐлекÑей Мехоношин <ruskidecko@gmail.com>, 2016-2017,2019-2020
msgid ""
msgstr ""
"Project-Id-Version: calcurse\n"
"Report-Msgid-Bugs-To: bugs@calcurse.org\n"
-"POT-Creation-Date: 2019-06-16 15:27-0400\n"
-"PO-Revision-Date: 2019-05-30 21:49+0000\n"
-"Last-Translator: ÐлекÑей Мехоношин <ruskidecko@gmail.com>\n"
-"Language-Team: Russian (http://www.transifex.com/lfleischer/calcurse/"
+"POT-Creation-Date: 2024-01-26 18:28+0100\n"
+"PO-Revision-Date: 2013-07-23 08:43+0000\n"
+"Last-Translator: Vlad Savikin, 2021\n"
+"Language-Team: Russian (http://app.transifex.com/lfleischer/calcurse/"
"language/ru/)\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
-"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
-"%100>=11 && n%100<=14)? 2 : 3);\n"
+"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
+"n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || "
+"(n%100>=11 && n%100<=14)? 2 : 3);\n"
msgid "null pointer"
-msgstr "пуÑтой указатель"
+msgstr ""
+"Ошибка в работе программы: null pointer (указатель не указывает на "
+"корректные данные)."
+
+msgid "illegal date in appointment"
+msgstr "ÐеÑущеÑÑ‚Ð²ÑƒÑŽÑ‰Ð°Ñ Ð´Ð°Ñ‚Ð° Ð´Ð»Ñ Ð¼ÐµÑ€Ð¾Ð¿Ñ€Ð¸ÑтиÑ."
+
+msgid "error in appointment description"
+msgstr "Ошибка в опиÑании мероприÑтиÑ."
msgid "date error in appointment"
-msgstr "ошибка даты в задаче"
+msgstr ""
+"Ошибка в работе программы: date error in appointment (некорректно указана "
+"дата мероприÑтиÑ)."
msgid "no such appointment"
-msgstr "задача отÑутÑтвует"
+msgstr ""
+"Ошибка в работе программы: no such appointment (мероприÑтие не найдено)."
msgid ""
"Usage:\n"
@@ -39,9 +55,16 @@ msgid ""
"calcurse -Q [--from <date>] [--to <date>] [--days <number>]\n"
"calcurse -a | -d <date> | -d <number> | -n | -r[<number>] | -s[<date>] | -"
"t[<number>]\n"
-"calcurse -h | -v | --status | -G | -P | -g | -i <file> | -x[<file>] | --"
+"calcurse -h | -v | --status | -G | -P | -g | -i <file> | -x[<format>] | --"
"daemon"
msgstr ""
+"ИÑпользуйте:\n"
+"calcurse [-D <directory>] [-C <directory>] [-c <calendar file>]\n"
+"calcurse -Q [--from <date>] [--to <date>] [--days <number>]\n"
+"calcurse -a | -d <date> | -d <number> | -n | -r[<number>] | -s[<date>] | -"
+"t[<number>]\n"
+"calcurse -h | -v | --status | -G | -P | -g | -i <file> | -x[<format>] | --"
+"daemon"
msgid "Try `calcurse -h` for more information."
msgstr "Выполните 'calcurse -h' Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ñправки."
@@ -50,16 +73,17 @@ msgstr "Выполните 'calcurse -h' Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ ÑправкÐ
msgid "calcurse %s -- text-based organizer\n"
msgstr "calcurse %s - текÑтовый органайзер\n"
-msgid "Copyright (c) 2004-2017 calcurse Development Team."
-msgstr "Copyright (c) 2004-2017 calcurse Development Team."
+msgid "Copyright (c) 2004-2023 calcurse Development Team."
+msgstr "Copyright (c) 2004-2023 calcurse Development Team."
msgid "This is free software; see the source for copying conditions."
msgstr ""
-"Это Ñвободное ПО. Ð”Ð»Ñ Ð¾Ð·Ð½Ð°ÐºÐ¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ñ ÑƒÑловиÑми ÐºÐ¾Ð¿Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ ÐŸÐž, ознакомьтеÑÑŒ "
-"Ñ Ð¸Ñходным кодом."
+"Это Ñвободное программное обеÑпечение.\n"
+"Ð”Ð»Ñ Ð¾Ð·Ð½Ð°ÐºÐ¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ñ ÑƒÑловиÑми ÐºÐ¾Ð¿Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñтого программного обеÑпечениÑ,\n"
+"ознакомьтеÑÑŒ Ñ Ð¸Ñходным кодом."
msgid "Operations in command line mode:"
-msgstr ""
+msgstr "Операции в режиме командной Ñтроки:"
msgid " -Q, --query Print items in a given query range"
msgstr ""
@@ -71,79 +95,92 @@ msgstr ""
msgid " -P, --purge Read items and write them back"
msgstr ""
+" -P, --purge ИÑпользование рег. выражений Ð´Ð»Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð·Ð°Ð¿Ð¸Ñей в календаре"
msgid ""
"Query short forms:\n"
"-a, -d <date>|<number>, -n, -r[<number>], -s[<date>], -t<number>"
msgstr ""
+" Краткие запроÑÑ‹:\n"
+" -a, -d <date>|<number>, -n, -r[<number>], -s[<date>], -t<number>"
msgid "Note that filter, format and day-range options affect input or output:"
msgstr ""
+" Заметьте, еÑÑ‚ÑŒ опции Ð´Ð»Ñ Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð°, формата и временного диапазона "
+"влиÑющие на ввод или вывод: "
msgid " --filter-* Filter items loaded by -Q, -G, -P and -x"
msgstr ""
+" --filter-* Фильтрует загруженные Ñлементы Ð´Ð»Ñ -Q, -G, -"
+"P и -x"
msgid ""
" --format-* Rewrite output from -Q, -G and --dump-imported"
msgstr ""
+" --format-* Переоформить вывод -Q, -G и --dump-imported"
msgid " --from <date> Limit day range of -Q."
-msgstr ""
+msgstr " --from <date> Ðачало временного диапазона Ð´Ð»Ñ -Q"
msgid " --to <date> Limit day range of -Q."
-msgstr ""
+msgstr " --to <date> Конец временного диапазона Ð´Ð»Ñ -Q"
msgid " --days <number> Limit day range of -Q."
-msgstr ""
+msgstr " --days <number> От \"СегоднÑ\" отÑчёт дней Ð´Ð»Ñ -Q"
msgid " --limit, -l <number> Limit number of query results"
-msgstr ""
+msgstr " --limit, -l <number> Ограничение вывода (количеÑтвенно)"
msgid " --search, -S <regexp> Match regular expression in queries"
msgstr ""
+" --search, -S <regexp> ИÑпользование рег. выражений в запроÑах"
msgid "Consult the man page for details."
-msgstr ""
+msgstr " ПодробноÑти Ñмотрите в man-Ñтранице"
msgid "Miscellaneous:"
msgstr "Разное:"
msgid " -c, --calendar <file> The calendar data file to use"
-msgstr ""
+msgstr " -c, --calendar <file> Выбор файла Ñ Ð´Ð°Ð½Ð½Ñ‹Ð¼Ð¸ нужного календарÑ"
msgid " -C, --confdir <dir> The configuration directory to use"
-msgstr ""
+msgstr " -C, --confdir <dir> Выбор рабочей директории Ð´Ð»Ñ Ð½Ð°Ñтроек"
msgid " --daemon Run notification daemon in the background"
-msgstr "--daemon ЗапуÑтить демон уведомлений в фоне"
+msgstr " --daemon ЗапуÑтить демон уведомлений в фоне"
msgid " -D, --datadir <dir> The data directory to use"
-msgstr ""
+msgstr " -D, --datadir <dir> Выбор рабочей директории Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ…"
msgid " -g, --gc Run the garbage collector"
-msgstr ""
+msgstr " -g, --gc ЗапуÑтить Ñборщик муÑора"
msgid " -h, --help Show this help text"
-msgstr ""
+msgstr " -h, --help Показать Ñту Ñправку"
msgid " -i, --import <file> Import iCal data from file"
-msgstr ""
+msgstr " -i, --import <file> Импорт данных в формате iCalendar (*.ics)"
-msgid " -q, --quiet Suppress system dialogs"
-msgstr ""
+msgid " -q, --quiet Suppress import/export result message"
+msgstr " -q, --quiet Подавить вывод при импорте/ÑкÑпорте"
msgid " --read-only Do not save configuration or data files"
-msgstr "--read-only Ðе ÑохранÑÑ‚ÑŒ наÑтройки или файлы Ñ Ð´Ð°Ð½Ð½Ñ‹Ð¼Ð¸"
+msgstr " --read-only Ðе ÑохранÑÑ‚ÑŒ наÑтройки или файлы Ñ Ð´Ð°Ð½Ð½Ñ‹Ð¼Ð¸"
msgid " --status Display status of running instances"
msgstr ""
+" --status Показать информацию о запущенных ÑкземплÑрах "
+"программы"
msgid " -v, --version Show version information"
-msgstr ""
+msgstr " -v, --version Показать информацию о верÑии программы"
msgid ""
" -x, --export[<format>] Export to stdout in ical (default) or pcal format"
msgstr ""
+" -x, --export[<format>] ЭкÑпорт в iCalendar (по умолчанию) (*.ics) или "
+"Pcal (*.ps)"
msgid ""
"For more information, type '?' from within calcurse, or read the manpage."
@@ -152,7 +189,7 @@ msgstr ""
"обратитеÑÑŒ к man."
msgid "Submit feature requests and suggestions to <misc@calcurse.org>."
-msgstr "ÐŸÐ¾Ð¶ÐµÐ»Ð°Ð½Ð¸Ñ Ð¸Ð»Ð¸ ваши идеи приÑылайте на <misc@calcurse.org>."
+msgstr "ÐŸÐ¾Ð¶ÐµÐ»Ð°Ð½Ð¸Ñ Ð¸/или Ваши идеи приÑылайте на <misc@calcurse.org>."
msgid "Submit bug reports to <bugs@calcurse.org>."
msgstr "Обнаруженные ошибки приÑылайте на <bugs@calcurse.org>."
@@ -176,101 +213,101 @@ msgid "calcurse is running in background (pid %d)\n"
msgstr "calcurse запущен в фоновом режиме (pid: %d)\n"
msgid "calcurse is not running"
-msgstr ""
+msgstr "calcurse не запущен"
msgid "completed tasks:\n"
-msgstr "Выполненные задачи:\n"
+msgstr "Прошедшие мероприÑтиÑ:\n"
msgid "to do:\n"
msgstr "СпиÑок дел:\n"
msgid "next appointment:\n"
-msgstr "Ð¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ Ð·Ð°Ð´Ð°Ñ‡Ð°:\n"
+msgstr "Следующее мероприÑтие:\n"
#, c-format
msgid "invalid range: %s"
-msgstr "неверный диапазон: %s"
+msgstr "Ðеверный диапазон: %s."
#, c-format
msgid "invalid date: %s"
-msgstr "Ð½ÐµÐ²ÐµÑ€Ð½Ð°Ñ Ð´Ð°Ñ‚Ð°: %s"
+msgstr "ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ð´Ð°Ñ‚Ð°: %s."
#, c-format
msgid "invalid priority: %s"
-msgstr "неверный приоритет: %s"
+msgstr "Ðеверный приоритет: %s."
#, c-format
msgid "invalid export format: %s"
-msgstr "неверный формат ÑкÑпорта: %s"
+msgstr "Ðеверный формат ÑкÑпорта: %s."
msgid "invalid filter mask"
-msgstr "Ð½ÐµÐ²ÐµÑ€Ð½Ð°Ñ Ð¼Ð°Ñка фильтра"
+msgstr "ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ð¼Ð°Ñка фильтра."
msgid "cannot handle more than one regular expression"
-msgstr "невозможно иÑпользовать более одного рег. выражениÑ"
+msgstr "Ðевозможно иÑпользовать более одного рег. выражениÑ."
#, c-format
msgid "could not compile regular expression: %s"
-msgstr "невозможно Ñкомпилировать рег. выражение: %s"
+msgstr "Ðевозможно Ñкомпилировать рег. выражение: %s."
#, c-format
msgid "filter criterion already in use: %s"
-msgstr ""
+msgstr "Критерий уже иÑпользован: %s."
#, c-format
msgid "invalid date range: %s"
-msgstr "неверный диапазон дат: %s"
+msgstr "Ðеверный диапазон дат: %s."
#, c-format
msgid "calcurse is running (pid = %d)"
-msgstr ""
+msgstr "calcurse запущен (pid = %d)"
#, c-format
msgid "invalid input date format: %s"
-msgstr ""
+msgstr "Ðеверный формат ввода даты %s."
#, c-format
msgid "invalid output date format: %s"
-msgstr ""
+msgstr "Ðеверный формат вывода даты %s."
msgid "invalid argument combination"
-msgstr "Ð½ÐµÐ²ÐµÑ€Ð½Ð°Ñ ÐºÐ¾Ð¼Ð±Ð¸Ð½Ð°Ñ†Ð¸Ñ Ð°Ñ€Ð³ÑƒÐ¼ÐµÐ½Ñ‚Ð¾Ð²"
+msgstr "ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ ÐºÐ¾Ð¼Ð±Ð¸Ð½Ð°Ñ†Ð¸Ñ Ð°Ñ€Ð³ÑƒÐ¼ÐµÐ½Ñ‚Ð¾Ð²."
msgid "cannot specify a range and an end date"
-msgstr "невозможно задать диапазон и конечную дату"
+msgstr "Ðевозможно задать диапазон и конечную дату."
msgid "end date cannot come before start date"
-msgstr ""
+msgstr "ÐšÐ¾Ð½ÐµÑ‡Ð½Ð°Ñ Ð´Ð°Ñ‚Ð° не может быть до даты начала."
msgid "Unable to find documentation."
-msgstr "Ðевозможно найти документацию"
+msgstr "Ðевозможно найти документацию."
msgid "Data were saved successfully"
-msgstr ""
+msgstr "Данные уÑпешно Ñохранены."
msgid "Data were saved/reloaded successfully"
-msgstr ""
+msgstr "Данные уÑпешно Ñохранены/обновлены."
msgid "Save cancelled"
-msgstr ""
+msgstr "Сохранение отменено."
msgid "Data were already saved"
-msgstr ""
+msgstr "Данные уже были Ñохранены."
msgid "Cannot open data file"
-msgstr ""
+msgstr "Ðевозможно открыть файл данных."
msgid "Data were reloaded successfully"
-msgstr ""
+msgstr "Данные уÑпешно обновлены."
msgid "Date were merged/reloaded successfully"
-msgstr ""
+msgstr "Данные уÑпешно Ñинхронизированы."
msgid "Reload cancelled"
-msgstr ""
+msgstr "Обновление отменено."
msgid "Data were already loaded"
-msgstr ""
+msgstr "Данные уже были загружены."
msgid "Export to (i)cal or (p)cal format?"
msgstr "Формат ÑкÑпорта (i)cal или (p)cal?"
@@ -279,37 +316,51 @@ msgid "[ip]"
msgstr "[ip]"
msgid "There are unsaved changes. Should they be saved?"
-msgstr ""
+msgstr "ИмеютÑÑ Ð½ÐµÑохранённые изменениÑ. Сохранить?"
msgid "Do you really want to quit?"
msgstr "Вы уверены, что хотите выйти?"
-msgid "Command: [ h(elp) | w(rite)(!) | q(uit)(!) | wq(!) ]"
-msgstr ""
+msgid "Command: [ h(elp) | w(rite)(!) | q(uit)(!) | wq(!) | n(ext) | p(rev) ]"
+msgstr "Команды: [ h(elp) | w(rite)(!) | q(uit)(!) | wq(!) | n(ext) | p(rev) ]"
msgid "Read-only mode - use w!"
-msgstr ""
+msgstr "Режим Ñ‡Ñ‚ÐµÐ½Ð¸Ñ - иÑпользуйте w!"
msgid "There are unsaved changes - use w or q!"
msgstr ""
+"ИмеютÑÑ Ð½ÐµÑохранённые Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ - иÑпользуйте w (запиÑÑŒ) или q! (выход без "
+"ÑохранениÑ)."
#, c-format
msgid "Help topic does not exist: %s"
-msgstr "Раздел Ñправки не ÑущеÑтвует: %s"
+msgstr "Раздел Ñправки не ÑущеÑтвует: %s."
+
+msgid "Select a repeating item in the appointments panel."
+msgstr "Выберете повторÑющуюÑÑ Ð·Ð°Ð¿Ð¸ÑÑŒ на панели МероприÑтий."
+
+msgid "Not a repeating item."
+msgstr "Ðе повторÑющаÑÑÑ Ð·Ð°Ð¿Ð¸ÑÑŒ."
+
+msgid "Last occurrence."
+msgstr "ПоÑледний пункт из поÑледовательноÑти."
+
+msgid "First occurrence."
+msgstr "Первый пункт из поÑледовательноÑти."
#, c-format
msgid "No such command: %s"
-msgstr "Команда не обнаружено: %s"
+msgstr "Команда не обнаружена: %s."
msgid "unknown color"
-msgstr "неизвеÑтный цвет"
+msgstr "ÐеизвеÑтный цвет."
msgid "failed to open configuration file"
-msgstr "ошибка Ð¾Ñ‚Ñ€Ñ‹Ñ‚Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° конфигурации"
+msgstr "Ошибка Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° конфигурации."
#, c-format
msgid "invalid configuration directive: \"%s\""
-msgstr "invalid configuration directive: \"%s\""
+msgstr "Ðеверные параметры конфигурации: \"%s\""
msgid ""
"Pre-3.0.0 configuration file format detected, please upgrade running "
@@ -320,19 +371,19 @@ msgstr ""
#, c-format
msgid "unknown user option: \"%s\" (ignored)"
-msgstr ""
+msgstr "ÐеизвеÑÑ‚Ð½Ð°Ñ Ð¾Ð¿Ñ†Ð¸Ñ: \"%s\" (игнорируетÑÑ)"
#, c-format
msgid "invalid option format: \"%s\" (ignored)"
-msgstr ""
+msgstr "Ðеверный формат опции: \"%s\" (игнорируетÑÑ)"
#, c-format
msgid "unknown user option: \"%s\" (disabled)"
-msgstr ""
+msgstr "ÐеизвеÑÑ‚Ð½Ð°Ñ Ð¾Ð¿Ñ†Ð¸Ñ: \"%s\" (отключена)"
#, c-format
msgid "invalid option format: \"%s\" (disabled)"
-msgstr ""
+msgstr "Ðеверный формат опции: \"%s\" (отключена)"
msgid "layout configuration"
msgstr "ÐаÑтройки раÑположениÑ"
@@ -350,82 +401,77 @@ msgid "color theme"
msgstr "Ð¦Ð²ÐµÑ‚Ð¾Ð²Ð°Ñ Ñхема"
msgid "(if set to YES, compact panels are used)"
-msgstr "(ЕÑли выбрано ДÐ/YES, будет иÑпользован компактный вид панелей)"
+msgstr "(да/нет) Компактное отображение"
msgid "Calendar"
msgstr "Календарь"
msgid "Appointments"
-msgstr "Задачи"
+msgstr "МероприÑтиÑ"
msgid "TODO"
-msgstr "Дела"
+msgstr "СпиÑок дел"
msgid "(specifies the panel that is selected by default)"
-msgstr "(Задаёт панель, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð±ÑƒÐ´ÐµÑ‚ активна по умолчанию)"
+msgstr "Определение панели выделенной по умолчанию"
msgid "monthly"
-msgstr ""
+msgstr "ЕжемеÑÑчно"
msgid "weekly"
-msgstr ""
+msgstr "Еженедельно"
msgid "(preferred calendar display)"
-msgstr ""
+msgstr "Предпочитаемый вид календарÑ"
msgid "show completed"
-msgstr ""
+msgstr "Показывать выполненные"
msgid "hide completed"
-msgstr ""
+msgstr "СпрÑтать выполненные"
msgid "(preferred todo display)"
-msgstr ""
+msgstr "Предпочитаемый вид ÑпиÑка дел"
msgid "(horizontal line above the day heading)"
msgstr ""
+"(да/нет) Отобразить разделительную линию между днÑми в панели календарÑ"
msgid "(empty line between events and appointments)"
-msgstr ""
+msgstr "(да/нет) Добавить раÑÑтоÑние между мероприÑтиÑми и вÑтречами"
msgid "(each day ends with an empty line)"
-msgstr ""
+msgstr "(да/нет) Окончить предÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð½Ñ Ð¿ÑƒÑтой Ñтрокой"
msgid "(insert an empty line after each appointment)"
-msgstr ""
+msgstr "(да/нет) Добавить пуÑтую Ñтроку между мероприÑтиÑми"
+
+msgid "(text for a day without events and appointments)"
+msgstr "Отображаемый текÑÑ‚ на поле Ñвободного днÑ"
msgid "(display more than one day in the appointments panel)"
-msgstr ""
+msgstr "(да/нет) Показывать неÑколько дней на панели мероприÑтий"
msgid "(if set to YES, automatic save is done when quitting)"
-msgstr "(yes/no) ÐвтоÑохранение при выходе из программы"
+msgstr "(да/нет) ÐвтоматичеÑкое Ñохранение при выходе из программы"
msgid "(run the garbage collector when quitting)"
-msgstr "(yes/no) запуÑтить Ñборщик муÑора при выходе"
+msgstr "(да/нет) ЗапуÑтить Ñборщик муÑора при выходе"
msgid "(if not null, automatically save data every 'periodic_save' minutes)"
-msgstr "(N/0) ÐвтоÑохранение каждые N минут. (Ð´Ð»Ñ Ð¾Ñ‚Ð¼ÐµÐ½Ñ‹ '0')"
+msgstr "ÐвтоматичеÑкое Ñохранение каждые n минут. (Ð´Ð»Ñ Ð¾Ñ‚Ð¼ÐµÐ½Ñ‹ '0')"
msgid "(if YES, system events are turned into appointments (or else deleted))"
-msgstr ""
+msgstr "(да/нет) Ð’Ñе ÑиÑтемные мероприÑÑ‚Ð¸Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÑÑŽÑ‚ÑÑ Ð² общие (или нет)"
msgid "(if set to YES, confirmation is required before quitting)"
-msgstr "(yes/no) Подтверждение выхода из программы"
+msgstr "(да/нет) Подтверждение выхода из программы"
msgid "(if set to YES, confirmation is required before deleting an event)"
-msgstr "(yes/no) Подтверждение ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ñобытий"
-
-msgid "(if set to YES, messages about loaded and saved data will be displayed)"
-msgstr "(yes/no) Отображение ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾ загрузке и Ñохранении данных"
-
-msgid "Monday"
-msgstr "Пн"
-
-msgid "Sunday"
-msgstr "Ð’Ñ"
+msgstr "(да/нет) Подтверждение ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ñобытий"
msgid "(specifies the first day of week in the calendar view)"
-msgstr "(указание первого Ð´Ð½Ñ Ð½ÐµÐ´ÐµÐ»Ð¸ в календаре)"
+msgstr "Указание первого Ð´Ð½Ñ Ð½ÐµÐ´ÐµÐ»Ð¸ в календаре"
msgid "(Format of the date to be displayed in non-interactive mode)"
msgstr "Формат даты отображаетÑÑ Ð² неинтерактивном режиме"
@@ -443,28 +489,40 @@ msgid "to the right"
msgstr "вправо"
msgid "(position of the heading in the appointments panel)"
-msgstr ""
+msgstr "РаÑположение шапки на панели мероприÑтий"
msgid "(Format of the date displayed in the appointments panel)"
-msgstr "(Формат даты, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶Ð°ÐµÑ‚ÑÑ Ð² панели задач)"
+msgstr "Формат даты, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶Ð°ÐµÑ‚ÑÑ Ð² панели задач"
+
+msgid "(Format of the time displayed in the appointments panel)"
+msgstr "Формат времени, которое отображаетÑÑ Ð² панели задач"
+
+msgid "Enter a text string (an empty string for the default text)"
+msgstr ""
+"Добавить текÑтовую Ñтроку (иначе будет отображатьÑÑ Ñ‚ÐµÐºÑÑ‚ по умолчанию)"
msgid "Enter the date format (see 'man 3 strftime' for possible formats) "
msgstr "Задайте формат даты (Ñм. 'man 3 strftime' Ð´Ð»Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ñ‹Ñ… форматов)"
+msgid "Enter the time format (see 'man 3 strftime' for possible formats) "
+msgstr "Задайте формат времени (Ñм. 'man 3 strftime' Ð´Ð»Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ñ‹Ñ… форматов) "
+
msgid "Enter the date format: "
msgstr "Задайте формат даты: "
msgid "Enter the delay, in minutes, between automatic saves (0 to disable) "
-msgstr "Введите задержку между автоÑохранениÑми (в минутах) или 0 Ð´Ð»Ñ Ð¾Ñ‚Ð¼ÐµÐ½Ñ‹ "
+msgstr ""
+"Введите задержку между автоматичеÑкими ÑохранениÑми (в минутах) или 0 Ð´Ð»Ñ "
+"отмены "
msgid "general options"
msgstr "ОÑновные наÑтройки"
msgid "Undefined option!"
-msgstr "ÐÐµÐ¾Ð¿Ñ€ÐµÐ´ÐµÐ»Ñ‘Ð½Ð½Ð°Ñ Ð½Ð°Ñтройка!"
+msgstr "ÐÐµÐºÐ¾Ñ€Ñ€ÐµÐºÑ‚Ð½Ð°Ñ Ð½Ð°Ñтройка!"
-msgid "undefined"
-msgstr "неопределено"
+msgid "UNDEFINED"
+msgstr "ОтÑутÑтвует инициализациÑ!"
msgid "keys configuration"
msgstr "ÐаÑтройка клавиш"
@@ -474,31 +532,33 @@ msgstr "Ðажмите клавишу, чтобы привÑзать её к:"
#, c-format
msgid "The key '%s' is already used for %s. Choose another one."
-msgstr "Ключ '%s' уже иÑпользуетÑÑ Ð´Ð»Ñ %s. Выберите другой ключ."
+msgstr "Клавиша '%s' уже иÑпользуетÑÑ Ð´Ð»Ñ %s. Выберите другую клавишу."
-msgid "Some actions do not have any associated key bindings!"
-msgstr "Ðекоторые дейÑÑ‚Ð²Ð¸Ñ Ð½Ðµ привÑзаны к клавишам!"
+msgid "Some actions are left undefined!"
+msgstr "Ðекоторые дейÑÑ‚Ð²Ð¸Ñ Ð½Ðµ определены!"
msgid ""
"Sorry, colors are not supported by your terminal\n"
"(Press [ENTER] to continue)"
-msgstr "Цвета не поддерживаютÑÑ Ð²Ð°ÑˆÐ¸Ð¼ терминалом (Ðажмите [ENTER])"
+msgstr ""
+"Цвета не поддерживаютÑÑ Ð²Ð°ÑˆÐ¸Ð¼ терминалом\n"
+"(Ðажмите [ENTER], чтобы продолжить)"
#, c-format
msgid "Could not save %s."
-msgstr ""
+msgstr "Ðевоможно Ñохранить %s"
msgid "unknown item type"
-msgstr "неизвеÑтный тип запиÑи"
+msgstr "ÐеизвеÑтный тип запиÑи"
-msgid "(none)"
-msgstr ""
+msgid "Note:"
+msgstr "Заметка:"
msgid "Event:"
msgstr "Событие:"
msgid "Appointment:"
-msgstr "Задача:"
+msgstr "МероприÑтие:"
#, c-format
msgid "Could not stop daemon properly: %s\n"
@@ -506,7 +566,7 @@ msgstr "Ðевозможно оÑтановить демон должным об
#, c-format
msgid "terminated at %s with signal %d\n"
-msgstr "завершено %s Ñ Ñигналом %d\n"
+msgstr "Завершено %s Ñ Ñигналом %d\n"
#, c-format
msgid "Could not remove daemon lock file: %s\n"
@@ -522,13 +582,13 @@ msgstr "Ðевозможно прервать Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñющего тер
#, c-format
msgid "Could not change working directory: %s\n"
-msgstr "Ðевозможно выбрать рабочую директориюг: %s\n"
+msgstr "Ðевозможно выбрать рабочую директорию: %s\n"
msgid "Cannot daemonize, aborting\n"
-msgstr "Ðевозможно демонизировать процеÑÑ. Завершение\n"
+msgstr "Ðевозможно демонизировать процеÑÑ. Завершение...\n"
msgid "Could not set lock file\n"
-msgstr "Ðевозможно выбрать заблокированный файл\n"
+msgstr "Ðе удалоÑÑŒ Ñоздать файл блокировки\n"
#, c-format
msgid "Could not access \"%s\": %s\n"
@@ -536,103 +596,188 @@ msgstr "Ðет доÑтупа \"%s\": %s\n"
#, c-format
msgid "started at %s\n"
-msgstr "запуÑк в %s\n"
+msgstr "ЗапуÑк в %s\n"
msgid "error loading next appointment\n"
-msgstr "ошибка при загрузке Ñледующей задачи\n"
+msgstr "Ошибка при загрузке Ñледующего мероприÑтиÑ\n"
#, c-format
msgid "launching notification at %s for: \"%s\"\n"
-msgstr "запуÑк ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ %s длÑ: \"%s\"\n"
+msgstr "ЗапуÑк ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ %s длÑ: \"%s\"\n"
msgid "error while sending notification\n"
-msgstr "ошибка во Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²ÐºÐ¸ уведомлениÑ\n"
+msgstr "Ошибка во Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²ÐºÐ¸ уведомлениÑ\n"
#, c-format
msgid "sleeping at %s for %d second\n"
msgid_plural "sleeping at %s for %d seconds\n"
-msgstr[0] "ÑпÑщий режим %s на %d Ñек.\n"
+msgstr[0] "СпÑщий режим %s на %d Ñек.\n"
msgstr[1] "ÑпÑщий режим %s на %d Ñек.\n"
msgstr[2] "ÑпÑщий режим %s на %d Ñек.\n"
-msgstr[3] "ÑпÑщий режим %s на %d Ñек.\n"
+msgstr[3] "СпÑщий режим %s на %d Ñек.\n"
#, c-format
msgid "awakened at %s\n"
-msgstr "пробуждение %s\n"
+msgstr "Пробуждение %s\n"
#, c-format
msgid "Could not stop calcurse daemon: %s\n"
msgstr "Ðевозможно оÑтановить демон calcurse: %s\n"
-msgid "date error in event"
-msgstr "ошибка даты в Ñобытии"
+msgid "illegal date in event"
+msgstr "Ошибка в дате мероприÑтиÑ."
-msgid "date error in the event\n"
-msgstr "ошибка даты в Ñобытии\n"
+msgid "date error in event\n"
+msgstr "Ошибка в дате мероприÑтиÑ.\n"
msgid "Internal error: line too long"
msgstr "ВнутреннÑÑ Ð¾ÑˆÐ¸Ð±ÐºÐ°: Ñлишком Ð´Ð»Ð¸Ð½Ð½Ð°Ñ Ñтрока"
msgid "out of memory"
-msgstr "нехватка памÑти"
+msgstr "Ðе хватает памÑти"
msgid "unknown ical type"
-msgstr "неизвеÑтный тип ical"
+msgstr "ÐеизвеÑтный тип файла iCalendar"
-msgid "recurrence rule malformed."
-msgstr "рекуррентные правила повреждены."
+msgid "(empty)"
+msgstr "(пуÑто)"
-msgid "recurrence frequency not found."
-msgstr "Ñ€ÐµÐºÑƒÑ€Ñ€ÐµÐ½Ñ‚Ð½Ð°Ñ Ñ‡Ð°Ñтота не найдена"
+msgid "ical_store_event: out of memory"
+msgstr "ical_store_event: не хватает памÑти"
-msgid "recurrence frequency not recognized."
-msgstr "Ñ€ÐµÐºÑƒÑ€Ñ€ÐµÐ½Ñ‚Ð½Ð°Ñ Ñ‡Ð°Ñтота не раÑпознана"
+msgid "need DTSTART to determine event type."
+msgstr "Ðеобходим DTSTART Ð´Ð»Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ñ‚Ð¸Ð¿Ð° мероприÑтиÑ."
-msgid "recurrence exception dates malformed."
-msgstr "рекурентные ÑÐ¾Ð¾Ñ‚Ð½Ð¾ÑˆÐµÐ½Ð¸Ñ Ð´Ð°Ñ‚ повреждены."
+msgid "malformed recurrence line."
+msgstr "Ðекорректно ÑÑ„Ð¾Ñ€Ð¼Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ð°Ñ Ð² Ñтрочке поÑледовательноÑÑ‚ÑŒ."
-msgid "description malformed."
-msgstr "опиÑание повреждено."
+msgid "frequency not set in rrule."
+msgstr "Ðе задана продолжительноÑÑ‚ÑŒ повторений Ð´Ð»Ñ Ð¿Ð¾ÑледовательноÑти."
-msgid "could not get entire item description."
-msgstr "невозможно получить опиÑание полноÑтью."
+msgid "frequency absent in rrule."
+msgstr ""
+"Ðе ÑоответÑтвует Ñтандарту продолжительноÑÑ‚ÑŒ повторений Ð´Ð»Ñ "
+"поÑледовательноÑти."
-msgid "could not retrieve item summary."
-msgstr "невозможно воÑÑтановить Ñуммарные запиÑи."
+msgid "rrule frequency not supported."
+msgstr "Ð”Ð»Ñ Ð¿Ð¾ÑледовательноÑти Ð·Ð°Ð´Ð°Ð½Ð½Ð°Ñ Ñ‡Ð°Ñтота повторений не поддерживаетÑÑ."
-msgid "item start date is not defined."
-msgstr "Ð²Ñ€ÐµÐ¼Ñ Ð½Ð°Ñ‡Ð°Ð»Ð° ÑÐ¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð½Ðµ определено."
+msgid "invalid interval."
+msgstr "Ðекорректный интервал."
-msgid "item has a negative duration."
-msgstr "значение имеет отрицательную продолжительноÑÑ‚ÑŒ."
+msgid "either until or count."
+msgstr "Выберете дату или продолжительноÑÑ‚ÑŒ."
-msgid "item could not be identified."
-msgstr "значение не может быть раÑпознано."
+msgid "missing until value."
+msgstr "ОтÑутÑтвует Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð¿Ð¾ÑледовательноÑти."
+
+msgid "invalid until format."
+msgstr "Ðекорректный формат Ð´Ð»Ñ Ð¿Ð¾ÑледовательноÑти."
-msgid "event start time malformed."
-msgstr "Ð²Ñ€ÐµÐ¼Ñ Ð½Ð°Ñ‡Ð°Ð»Ð° ÑÐ¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð½ÐµÐ²ÐµÑ€Ð½Ð¾ оформлено"
+msgid "invalid count value."
+msgstr "Ðекорректное значение Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð»Ð¶Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ñти."
-msgid "could not retrieve event start time."
-msgstr "невозможно воÑÑтановить Ð²Ñ€ÐµÐ¼Ñ Ð½Ð°Ñ‡Ð°Ð»Ð° ÑобытиÑ."
+msgid "invalid bymonth list."
+msgstr "Ðекорректно задан ÑпиÑок по меÑÑцам."
-msgid "event end time malformed."
-msgstr "Ñобытие и Ð²Ñ€ÐµÐ¼Ñ Ð½ÐµÐ²ÐµÑ€Ð½Ð¾ оформлены"
+msgid "invalid bymonthday list."
+msgstr "Ðекорректно задан ÑпиÑок по днÑм в меÑÑце."
-msgid "could not retrieve event end time."
-msgstr "невозможно воÑÑтановить Ð²Ñ€ÐµÐ¼Ñ Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ ÑобытиÑ."
+msgid "invalid byday list."
+msgstr "Ðекорректно задан ÑпиÑок по днÑм."
+
+msgid "invalid exception date value type."
+msgstr "Ðекорректный тип Ð´Ð»Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð´Ð°Ñ‚Ñ‹ иÑключениÑ."
+
+msgid "malformed exceptions line."
+msgstr "Ðекорректно Ñформированное в Ñтроке иÑключение."
+
+msgid "invalid exception."
+msgstr "Ðекорректное иÑключение."
+
+#, c-format
+msgid "malformed %s line."
+msgstr "Ðекорректно ÑÑ„Ð¾Ñ€Ð¼Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ð°Ñ %s Ñтрока."
+
+#, c-format
+msgid "malformed %s."
+msgstr "Ðекорректно Ñформированный %s."
-msgid "item duration malformed."
-msgstr "значение продолжительноÑти повреждено."
+msgid "malformed summary line."
+msgstr "Ðекорректно ÑÑ„Ð¾Ñ€Ð¼Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ð°Ñ Ð² Ñтроке ÐºÑ€Ð°Ñ‚ÐºÐ°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ "
+
+msgid "malformed summary."
+msgstr "Ðекорректно ÑÑ„Ð¾Ñ€Ð¼Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ð°Ñ ÐºÑ€Ð°Ñ‚ÐºÐ°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ."
+
+msgid "item start date not defined."
+msgstr "Дата начала мероприÑÑ‚Ð¸Ñ Ð½Ðµ определена."
+
+msgid "malformed start time line."
+msgstr "Ðекорректно Ñформировано Ð²Ñ€ÐµÐ¼Ñ Ð½Ð°Ñ‡Ð°Ð»Ð°."
+
+msgid "invalid or malformed event start time."
+msgstr "ÐедопуÑтимое или некорректно Ñформированное Ð²Ñ€ÐµÐ¼Ñ Ð½Ð°Ñ‡Ð°Ð»Ð° мероприÑтиÑ."
+
+msgid "invalid end time value type."
+msgstr "Ðекорректный тип Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð¸ окончаниÑ."
+
+msgid "malformed end time line."
+msgstr "Ðекорректно Ñформировано Ð²Ñ€ÐµÐ¼Ñ Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ."
+
+msgid "malformed event end time."
+msgstr "Ðекорректно Ñформировано Ð²Ñ€ÐµÐ¼Ñ Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ Ð¼ÐµÑ€Ð¾Ð¿Ñ€Ð¸ÑтиÑ. "
+
+msgid "end must be later than start."
+msgstr "Окончание должно быть поÑле начала."
+
+msgid "either end or duration."
+msgstr "Либо окончание, либо продолжительноÑÑ‚ÑŒ."
+
+msgid "malformed duration line."
+msgstr "Ðе правильный формат Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð»Ð¶Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ñти."
+
+msgid "invalid duration."
+msgstr "ÐÐµÐºÐ¾Ñ€Ñ€ÐµÐºÑ‚Ð½Ð°Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð»Ð¶Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾ÑÑ‚ÑŒ."
+
+msgid "exception date, but no recurrence rule."
+msgstr "Дата-иÑключение, но не задано правило повтора."
+
+msgid "multi-day event changed to one-day event"
+msgstr "Многодневное мероприÑтие изменено на однодневное."
+
+#, c-format
+msgid "Location: %s"
+msgstr "РаÑположение: %s"
+
+#, c-format
+msgid "Comment: %s"
+msgstr "Комментарий: %s"
+
+#, c-format
+msgid "rrule does not match start day (%s)."
+msgstr "ÐÐµÐºÐ¾Ñ€Ñ€ÐµÐºÑ‚Ð½Ð°Ñ Ð·Ð°Ð´Ð°Ñ‡Ð° поÑледовательноÑти отноÑительно даты начала (%s)."
+
+msgid "item could not be identified."
+msgstr "ЗапиÑÑŒ не может быть идентифицирована."
+
+msgid "only one description allowed."
+msgstr "ДопуÑтимо лишь одно опиÑание. "
+
+msgid "only one location allowed."
+msgstr "ДопуÑтимо лишь одно раÑположение."
msgid "The ical file seems to be malformed. The end of item was not found."
-msgstr "Файл ical Ñкорее вÑего повреждён. Ðе найдено окончание запиÑи."
+msgstr "Файл iСalendar Ñкорее-вÑего повреждён. Ðе найдено окончание запиÑи."
+
+msgid "could not retrieve item summary."
+msgstr "Ðевозможно получить краткое опиÑание запиÑи."
msgid "item priority is invalid (must be between 0 and 9)."
-msgstr "приоритет запиÑи в неверном формате (должно быть чиÑло между 0 и 9)"
+msgstr "Приоритет запиÑи в неверном формате (должно быть чиÑло от 0 и до 9)."
msgid "Warning: ical header malformed or wrong version number. Aborting..."
msgstr ""
-"Внимание: заголовок ical повреждён или неправильный номер верÑии. "
+"Внимание: заголовок iCalendar повреждён или его верÑÐ¸Ñ Ð½Ðµ поддерживаетÑÑ. "
"Завершение..."
msgid "Choose the file used to export calcurse data:"
@@ -642,145 +787,162 @@ msgid "The file cannot be accessed, please enter another file name."
msgstr "Файл не может быть добавлен, попробуйте другое Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð°."
msgid "Press [ENTER] to continue."
-msgstr "Ðажмите [ENTER]."
+msgstr "Ðажмите [Enter], чтобы продолжить..."
#, c-format
msgid "Failed to open \"%s\", - %s\n"
-msgstr "Ошибка Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ñ \"%s\", - %s\n"
+msgstr "Ошибка Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ñ \"%s\", - %s.\n"
msgid "Failed to build message\n"
-msgstr "Ошибка ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÑообщениÑ\n"
+msgstr "Ошибка ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÑообщениÑ.\n"
#, c-format
msgid "Failed to print message \"%s\"\n"
-msgstr "Ошибка вывода ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ \"%s\"\n"
+msgstr "Ошибка вывода ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ \"%s\".\n"
#, c-format
msgid "Failed to close \"%s\" - %s\n"
-msgstr "Ошибка Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ð¸Ñ \"%s\" - %s\n"
+msgstr "Ошибка Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ð¸Ñ \"%s\" - %s.\n"
#, c-format
msgid "%s does not exist"
-msgstr "%s не ÑущеÑтвует"
+msgstr "%s не ÑущеÑтвует."
msgid "Data files have changed and will be overwritten:"
-msgstr ""
+msgstr "Файлы данных были изменены и будут перезапиÑаны:"
msgid "(c)ontinue"
-msgstr ""
+msgstr "(c)продолжить"
msgid "(m)erge"
msgstr "(m)ÑлиÑние"
msgid "c(a)ncel"
-msgstr ""
+msgstr "(a)отмена"
msgid "[cma]"
-msgstr ""
+msgstr "[cma]"
msgid "failed to open appointment file"
-msgstr "ошибка Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° задач"
+msgstr "Ошибка Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° Ñ Ð¼ÐµÑ€Ð¾Ð¿Ñ€Ð¸ÑтиÑми."
msgid "syntax error in the item date"
-msgstr "опечатка в запиÑе даты"
+msgstr "Опечатка даты в запиÑи"
msgid "no event nor appointment found"
-msgstr "ÑÐ¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð¸ задачи не найдены"
+msgstr "МероприÑÑ‚Ð¸Ñ Ð¾Ñ‚ÑутÑтвуют."
msgid "syntax error in item time or duration"
-msgstr "опечатка в запиÑи даты или продолжительноÑти"
+msgstr "Опечатка во времени или в продолжительноÑти запиÑи."
msgid "syntax error in item identifier"
-msgstr "опечатка в запиÑи опознавателÑ"
+msgstr "Опечатка в идентификаторе запиÑи."
msgid "wrong format in the appointment or event"
-msgstr "неверный формат ÑÐ¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð¸Ð»Ð¸ задачи"
+msgstr "Ðеверный формат мероприÑтиÑ."
msgid "syntax error in item repetition"
-msgstr "опечатка в запиÑи повторениÑ"
+msgstr "Опечатка в запиÑи повторениÑ."
+
+msgid "syntax error in until date"
+msgstr "Опечатка в дате Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ Ð¿Ð¾ÑледовательноÑти."
+
+msgid "until date error"
+msgstr "Ошибка в дате Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ Ð¿Ð¾ÑледовательноÑти."
+
+msgid "BYMONTHDAY illegal with WEEKLY"
+msgstr "ÐеÑовмеÑтимые параметры."
+
+msgid "missing end of recurrence"
+msgstr "ОтÑутÑтвует дата Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ Ð¿Ð¾ÑледовательноÑти."
+
+msgid "syntax error in item state"
+msgstr "СинтакÑичеÑÐºÐ°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° в данных запиÑи."
msgid "failed to open todo file"
-msgstr "ошибка Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ñ todo-файла"
+msgstr "Ðе удалоÑÑŒ открыть файл Ñо ÑпиÑком дел."
msgid "Screen data have changed and will be lost:"
-msgstr ""
+msgstr "Обнаружены неÑохранённые изменениÑ, которые могут быть утрачены:"
msgid "failed to open key file"
-msgstr "ошибка Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° ключа"
-
-msgid ""
-"\n"
-"Too many errors while reading configuration file!\n"
-"Please backup your keys file, remove it from directory, and launch calcurse "
-"again.\n"
-msgstr ""
-"\n"
-"Обнаружены ошибки при чтении файла наÑтроек!\n"
-"Сделайте копию keys-файла, удалите его из каталога и запуÑтите calcurse "
-"Ñнова.\n"
+msgstr "Ðе удалоÑÑŒ открыть файл Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñющими клавишами."
msgid "Could not read key label"
-msgstr "Ðевозможно раÑпознать клавишу"
-
-msgid "Key label not recognized"
-msgstr "Клавиша не опознана"
+msgstr "Ðекорректный формат Ð´Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñющей клавиши."
#, c-format
-msgid "Error reading key: \"%s\""
-msgstr "Ошибка Ñ‡Ñ‚ÐµÐ½Ð¸Ñ ÐºÐ»Ð°Ð²Ð¸ÑˆÐ¸: \"%s\""
+msgid "Key label not recognized: \"%s\""
+msgstr "ÐераÑÐ¿Ð¾Ð·Ð½Ð°Ð½Ð½Ð°Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»ÑÑŽÑ‰Ð°Ñ ÐºÐ»Ð°Ð²Ð¸ÑˆÐ°: \"%s\""
#, c-format
-msgid "\"%s\" assigned multiple times!"
-msgstr "\"%s\" определено множеÑтво времён!"
+msgid "No keys assigned to \"%s\"."
+msgstr "Ðе назначено управлÑющей клавиши Ð´Ð»Ñ \"%s\"."
-msgid "There were some errors when loading keys file."
-msgstr ""
+#, c-format
+msgid "Keyname not recognized: \"%s\""
+msgstr "УправлÑÑŽÑ‰Ð°Ñ ÐºÐ»Ð°Ð²Ð¸ÑˆÐ° не раÑпознана: \"%s\"."
-msgid "Too many errors while reading keys file, aborting..."
-msgstr "Обнаружены ошибки при чтении keys-файла, отмена..."
+#, c-format
+msgid "\"%s\" assigned twice: \"%s\"."
+msgstr "\"%s\" приÑвоена дважды: \"%s\"."
#, c-format
-msgid "FATAL ERROR: could not create %s: %s\n"
-msgstr "ФÐТÐЛЬÐÐЯ ОШИБКÐ: невозможно Ñоздать %s: %s\n"
+msgid ""
+"Action \"%s\" absent, but default key \"%s\" assigned to another action."
+msgstr ""
+"Команда \"%s\" невыполнима, управ. клавиша \"%s\" назначена Ð´Ð»Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð¹ "
+"команды."
-msgid "Press [ENTER] to continue"
-msgstr "Ðажмите [ENTER]"
+msgid "Errors in the keys file."
+msgstr "Ошибки в файле Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñющими клавишами."
-msgid "Welcome to Calcurse. Missing data files were created."
-msgstr "Добро пожаловать в Calcurse. ОтÑутÑтвующие файлы данных будут Ñозданы."
+msgid "Remove offending line(s) from the keys file, aborting..."
+msgstr ""
+"Удалите некорректную Ñтроку(и) из файла Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñющими клавишами. "
+"Завершение..."
-msgid "Data files found. Data will be loaded now."
-msgstr "Данные найдены и будут загружены"
+msgid "Some actions do not have any associated key bindings!"
+msgstr "Ð”Ð»Ñ Ð½ÐµÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ñ… дейÑтвий не назначены клавиши!"
+
+#, c-format
+msgid "FATAL ERROR: could not create %s: %s\n"
+msgstr "Ðварийное завершение программы: не удалоÑÑŒ Ñоздать %s: %s\n"
msgid "The data were successfully exported"
-msgstr "Данные уÑпешно ÑкÑпортированы"
+msgstr "Данные уÑпешно ÑкÑпортированы."
+
+msgid "Press [ENTER] to continue"
+msgstr "Ðажмите [Enter], чтобы продолжить"
msgid "unknown export type"
-msgstr "неизвеÑтный тип ÑкÑпорта"
+msgstr "ÐеизвеÑтный тип ÑкÑпорта."
msgid "wrong export mode"
-msgstr "ошибочный режим ÑкÑпорта"
+msgstr "Ошибочный режим ÑкÑпорта."
msgid "Enter the file name to import data from:"
-msgstr "Ð˜Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð° Ð´Ð»Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð°: "
+msgstr "Ð˜Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð° Ð´Ð»Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð°:"
#, c-format
msgid "Import process report: %04d lines read"
-msgstr "Отчёт процеÑÑа импорта:%04d lines read"
+msgstr "Отчёт процеÑÑа импорта: %04d Ñтрок прочитано"
msgid "unknown import type"
-msgstr "неизвеÑтный тип импорта"
+msgstr "ÐеизвеÑтный тип импорта"
msgid "FATAL ERROR: the input file cannot be accessed, Aborting..."
-msgstr "ФÐТÐЛЬÐÐЯ ОШИБКÐ: входÑщий файл не может быть добавлен. Завершение..."
+msgstr ""
+"Ðварийное завершение программы: входÑщий файл не может быть добавлен. "
+"Завершение..."
msgid "FATAL ERROR: wrong import mode"
-msgstr "ФÐТÐЛЬÐÐЯ ОШИБКÐ: неправильный режим импорта"
+msgstr "Ðварийное завершение программы: неправильный режим импорта."
#, c-format
msgid "%d app"
msgid_plural "%d apps"
-msgstr[0] "%d app"
+msgstr[0] "%d мероприÑтий"
msgstr[1] "%d apps"
msgstr[2] "%d apps"
msgstr[3] "%d apps"
@@ -788,7 +950,7 @@ msgstr[3] "%d apps"
#, c-format
msgid "%d event"
msgid_plural "%d events"
-msgstr[0] "%d Ñобытие"
+msgstr[0] "%d Ñобытий"
msgstr[1] "%d ÑобытиÑ"
msgstr[2] "%d ÑобытиÑ"
msgstr[3] "%d ÑобытиÑ"
@@ -796,17 +958,17 @@ msgstr[3] "%d ÑобытиÑ"
#, c-format
msgid "%d todo"
msgid_plural "%d todos"
-msgstr[0] "%d дело"
+msgstr[0] "%d дел"
msgstr[1] "%d дела"
msgstr[2] "%d дела"
msgstr[3] "%d дела"
#, c-format
msgid "%d skipped"
-msgstr "%d пропущен"
+msgstr "%d пропущено"
msgid "Some items could not be imported."
-msgstr ""
+msgstr "Ðекоторые запиÑи не прошли импорт. "
msgid "Warning: could not open temporary log file, Aborting..."
msgstr "Внимание: невозможно открыть временный log-файл. Завершение..."
@@ -819,20 +981,24 @@ msgstr "Ðет log-файла Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ!"
#, c-format
msgid "See %s for details."
-msgstr ""
+msgstr "Детали в %s."
msgid "Display log file?"
-msgstr ""
+msgstr "Отобразить лог файл?"
#, c-format
msgid "Warning: could not erase temporary log file %s, Aborting..."
msgstr "Внимание: невозможно очиÑтить временный log-файл %s. Завершение..."
msgid "Invalid delay"
-msgstr "ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ð·Ð°Ð´ÐµÑ€Ð¶ÐºÐ°"
+msgstr "Ðекорректный интервал Ð´Ð»Ñ ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ."
-msgid "Periodic save: data files have changed. Save cancelled."
+msgid ""
+"Periodic save cancelled. Data files have changed. Save and merge "
+"interactively"
msgstr ""
+"ÐвтоÑохранение не выполнено. Данные изменены. Сохр./объедините данные "
+"вручную."
#, c-format
msgid ""
@@ -876,7 +1042,10 @@ msgid "Paste"
msgstr "Ð’Ñтавить"
msgid "Chg Win"
-msgstr "Панель"
+msgstr "След.Панель"
+
+msgid "Prev Win"
+msgstr "Пред.Панель"
msgid "Import"
msgstr "Импорт"
@@ -888,7 +1057,7 @@ msgid "Go to"
msgstr "Переход"
msgid "OtherCmd"
-msgstr "..."
+msgstr ". . ."
msgid "Config"
msgstr "ÐаÑтройки"
@@ -897,7 +1066,7 @@ msgid "Redraw"
msgstr "Обновить"
msgid "Add Appt"
-msgstr "Доб.Задачу"
+msgstr "Доб.Меропр."
msgid "Add Todo"
msgstr "Доб.Дело"
@@ -966,10 +1135,10 @@ msgid "Edit Itm"
msgstr "Изм.ЗапиÑÑŒ"
msgid "View"
-msgstr "Смотреть"
+msgstr "ПроÑмотреть"
msgid "Pipe"
-msgstr "Программный канал (pipe)"
+msgstr "Передать ->"
msgid "Flag Itm"
msgstr "Флаг"
@@ -1001,16 +1170,21 @@ msgstr ""
"#\n"
"# Файл наÑтройки быÑтрых клавиш Calcurse\n"
"#\n"
-"# Ð’ Ñтом файле определены быÑтрые клавиши, которые иÑпользуютÑÑ Ð² Calcurse.\n"
+"# Ð’ Ñтом файле определены управлÑющие клавиши, которые иÑпользуютÑÑ Ð² "
+"Calcurse.\n"
"# Calcurse Ñоздал их автоматичеÑки и редактируютÑÑ Ð¾Ð½Ð¸ в меню наÑтроек в "
"программе.\n"
"# ÐапрÑмую редактировать быÑтрые клавиши нельзÑ.\n"
msgid "FATAL ERROR: could not create default keys file."
-msgstr "FATAL ERROR: could not create default keys file."
+msgstr ""
+"Ðварийное завершение программы: не удалоÑÑŒ Ñоздать файл Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñющими "
+"клавишами."
msgid "FATAL ERROR: key value out of bounds"
-msgstr "FATAL ERROR: key value out of bounds"
+msgstr ""
+"Ðварийное завершение программы: значение Ð´Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñющей клавиши не "
+"корректно. "
msgid "General"
msgstr "ОÑновные"
@@ -1034,34 +1208,37 @@ msgid "Unknown"
msgstr "ÐезвеÑтный(аÑ)"
msgid "Cancel the ongoing action."
-msgstr "Отмена поÑтоÑнного дейÑтвиÑ."
+msgstr "Прервать выполнÑемое дейÑтвие."
msgid "Select the highlighted item."
msgstr "Выбрать подÑвеченную запиÑÑŒ."
msgid "Print general information about calcurse's authors, license, etc."
-msgstr "ПроÑмотреть оÑновную информацию об авторах, лицензии и Ñ‚.п."
+msgstr "ПроÑмотреть оÑновную информацию об авторах, лицензии и прочем."
msgid "Display hints whenever some help screens are available."
msgstr "Показать Ñправку, еÑли Ñ‚Ð°ÐºÐ¾Ð²Ð°Ñ Ð¸Ð¼ÐµÐµÑ‚ÑÑ."
msgid "Exit from the current menu, or quit calcurse."
-msgstr "Выйти из текущего меню или из calcurse"
+msgstr "Выйти из текущего меню, или из calcurse."
msgid "Save calcurse data."
-msgstr "Сохр. данные calcurse"
+msgstr "Сохр. данные calcurse."
msgid "Reload appointments and todo items."
-msgstr "Обновить задачу и ÑпиÑок дел."
+msgstr "Обновить запиÑи мероприÑтий и ÑпиÑка дел."
msgid "Copy the item that is currently selected."
-msgstr "Копировать выделенную запиÑÑŒ (пункт?)"
+msgstr "Копировать выделенную запиÑÑŒ."
msgid "Paste an item at the current position."
-msgstr "Ð’Ñтавить запиÑÑŒ в текущую позицию"
+msgstr "Ð’Ñтавить запиÑÑŒ в текущую позицию."
msgid "Select next panel in calcurse main screen."
-msgstr "Выбрать Ñлед. панель на главном Ñкране calcurse"
+msgstr "Выбрать Ñлед. панель на главном Ñкране calcurse."
+
+msgid "Select previous panel in calcurse main screen."
+msgstr "Выбрать пред. панель на главном Ñкране calcurse."
msgid "Import data from an external file."
msgstr "Импортированть данные Ñ Ð²Ð½ÐµÑˆÐ½ÐµÐ³Ð¾ файла."
@@ -1070,19 +1247,19 @@ msgid "Export data to a new file format."
msgstr "ЭкÑпортировать данные в файл."
msgid "Select the day to go to."
-msgstr "Выбрать день Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÑ…Ð¾Ð´Ð° на него."
+msgstr "Выбрать день Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÑ…Ð¾Ð´Ð° к нему."
msgid "Show next possible actions inside status bar."
-msgstr "Отобразить в полоÑе ÑтатуÑа ещё одни возможные дейÑтвиÑ. "
+msgstr "Отобразить в полоÑе ÑтатуÑа ещё одни возможные дейÑтвиÑ."
msgid "Enter the configuration menu."
msgstr "Войти в меню наÑтроек."
msgid "Redraw calcurse's screen."
-msgstr "Обновить Ñкран calcurse"
+msgstr "Обновить Ñкран calcurse."
msgid "Add an appointment, whichever panel is currently selected."
-msgstr "Добавить Задачу. Может быть выбрана Ð»ÑŽÐ±Ð°Ñ Ð¿Ð°Ð½ÐµÐ»ÑŒ."
+msgstr "Добавить МероприÑтие. Может быть выбрана Ð»ÑŽÐ±Ð°Ñ Ð¿Ð°Ð½ÐµÐ»ÑŒ."
msgid "Add a todo item, whichever panel is currently selected."
msgstr "Добавить Дело. Может быть выбрана Ð»ÑŽÐ±Ð°Ñ Ð¿Ð°Ð½ÐµÐ»ÑŒ."
@@ -1125,7 +1302,7 @@ msgid "Go to today, whichever panel is selected."
msgstr "Ð¢ÐµÐºÑƒÑ‰Ð°Ñ Ð´Ð°Ñ‚Ð°. Может быть выбрана Ð»ÑŽÐ±Ð°Ñ Ð¿Ð°Ð½ÐµÐ»ÑŒ."
msgid "Enter command mode."
-msgstr "Введите командный режим."
+msgstr "Введите в командном режиме."
msgid "Move to the right."
msgstr "Вправо"
@@ -1165,15 +1342,14 @@ msgid "Repeat an item"
msgstr "Повторить запиÑÑŒ"
msgid "Pipe the currently selected item to an external program."
-msgstr ""
-"Открыть программный канал (pipe) выбранной запиÑи Ñ Ð²Ð½ÐµÑˆÐ½ÐµÐ¹ программой."
+msgstr "Передать выбранный Ñлемент на обработку внешней программе."
msgid "Attach (or edit if one exists) a note to the currently selected item"
msgstr ""
-"ПривÑзать (или задать, еÑли не ÑущеÑтвует) заметку Ð´Ð»Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð¹ запиÑи"
+"Добавить (или редактировать, еÑли ÑущеÑтвует) заметку Ð´Ð»Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð¹ запиÑи"
msgid "View the note attached to the currently selected item."
-msgstr "ПроÑмотр вложенной запиÑки."
+msgstr "ПроÑмотреть заметку, прикреплённую к выбранному Ñлементу."
msgid "Raise a task priority inside the todo panel."
msgstr "ПовыÑить приоритет дела внутри панели дел."
@@ -1182,381 +1358,484 @@ msgid "Lower a task priority inside the todo panel."
msgstr "Понизить приоритет дела внутри ÑпиÑка дел."
msgid "FATAL ERROR: null file pointer."
-msgstr "FATAL ERROR: null file pointer."
+msgstr ""
+"Ðварийное завершение программы: указатель указывает на некорректные данные."
#, c-format
-msgid "When adding default key for \"%s\", \"%s\" was already assigned!"
-msgstr "При назначении клав. \"%s\", \"%s\" уже была назначена!"
+msgid "Default key(s) assigned to %d action%s."
+msgstr "По умолчанию иÑпользуетÑÑ ÐºÐ»Ð°Ð²Ð¸ÑˆÐ°(и) %d Ð´Ð»Ñ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ %s."
msgid "xmalloc: zero size"
-msgstr "xmalloc: zero size"
+msgstr "xmalloc: попытка выделить памÑÑ‚ÑŒ нулевого размера"
msgid "xmalloc: out of memory"
-msgstr "xmalloc: out of memory"
+msgstr "xmalloc: не хватает памÑти"
msgid "xcalloc: zero size"
-msgstr "xcalloc: zero size"
+msgstr "xcalloc: попытка выделить памÑÑ‚ÑŒ нулевого размера"
msgid "xcalloc: overflow"
-msgstr "xcalloc: overflow"
+msgstr "xcalloc: переполнение"
msgid "xcalloc: out of memory"
-msgstr "xcalloc: out of memory"
+msgstr "xcalloc: не хватает памÑти"
msgid "xrealloc: zero size"
-msgstr "xrealloc: zero size"
+msgstr "xrealloc: попытка выделить памÑÑ‚ÑŒ нулевого размера"
msgid "xrealloc: overflow"
-msgstr "xrealloc: overflow"
+msgstr "xrealloc: переполнение"
msgid "xrealloc: out of memory"
-msgstr "xrealloc: out of memory"
+msgstr "xrealloc: не хватает памÑти"
msgid "could not allocate memory to store block info"
-msgstr "could not allocate memory to store block info"
+msgstr "Ðе удалоÑÑŒ выделить памÑÑ‚ÑŒ Ð´Ð»Ñ Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ð¸ о блоке"
msgid "Block not found"
-msgstr "Block not found"
+msgstr "Блок не обнаружен"
#, c-format
msgid "overflow at %s"
-msgstr "overflow at %s"
+msgstr "Переполнение в %s"
#, c-format
msgid "dbg_free: null pointer at %s"
-msgstr "dbg_free: null pointer at %s"
+msgstr "dbg_free: нулевой указатель в %s"
#, c-format
msgid "block seems already freed at %s"
-msgstr "block seems already freed at %s"
+msgstr "Блок памÑти уже был выÑвобожден в %s"
#, c-format
msgid "corrupt block header at %s"
-msgstr "corrupt block header at %s"
+msgstr "Повреждённый заголовок блока в %s"
#, c-format
msgid "corrupt block end at %s, (end = %u, should be %d)"
-msgstr "corrupt block end at %s, (end = %u, should be %d)"
+msgstr "Повреждённый конец блока в %s, (окончание = %u, ожидалоÑÑŒ %d)"
msgid "---==== MEMORY BLOCK ====----------------\n"
-msgstr "---==== MEMORY BLOCK ====----------------\n"
+msgstr "---==== БЛОК ПÐМЯТИ ====-----------------\n"
#, c-format
msgid " id: %u\n"
-msgstr " id: %u\n"
+msgstr " Идентификатор: %u\n"
#, c-format
msgid " size: %u\n"
-msgstr " size: %u\n"
+msgstr " Размер: %u\n"
#, c-format
msgid " allocated in: %s\n"
-msgstr " allocated in: %s\n"
+msgstr " Выделено в: %s\n"
msgid "-----------------------------------------\n"
msgstr "-----------------------------------------\n"
msgid "+------------------------------+\n"
-msgstr "+------------------------------+\n"
+msgstr "+----------------------------------------+\n"
msgid "| calcurse memory usage report |\n"
-msgstr "| calcurse memory usage report |\n"
+msgstr "| отчёт об иÑпользовании памÑти calcurse |\n"
#, c-format
msgid " number of calls: %u\n"
-msgstr " number of calls: %u\n"
+msgstr " КоличеÑтво вызовов: %u\n"
#, c-format
msgid " allocated blocks: %u\n"
-msgstr " allocated blocks: %u\n"
+msgstr " Выделенные блоки Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ…: %u\n"
#, c-format
msgid " unfreed blocks: %u\n"
-msgstr " unfreed blocks: %u\n"
+msgstr " Ðе выÑбождённые блоки: %u\n"
#, c-format
msgid "Warning: could not open %s, Aborting..."
msgstr "Внимание: невозможно открыть %s, Завершение..."
-msgid "error while launching command: could not fork"
-msgstr "ошибка во Ð²Ñ€ÐµÐ¼Ñ Ð·Ð°Ð¿ÑƒÑка команды: невозможно разделитьÑÑ (fork)"
-
-msgid "error while launching command"
-msgstr "ошибка во Ð²Ñ€ÐµÐ¼Ñ Ð·Ð°Ð¿ÑƒÑка команды"
-
msgid "(if set to YES, notify-bar will be displayed)"
-msgstr "(ЕÑли выбрано yes, будет выводитÑÑ Ð¾ÐºÐ½Ð¾ уведомлениÑ)"
+msgstr "(да/нет) Выводить окно уведомлениÑ"
msgid "(Format of the date to be displayed inside notify-bar)"
-msgstr "(Формат даты выводитÑÑ Ð²Ð½ÑƒÑ‚Ñ€Ð¸ окна уведомлениÑ)"
+msgstr "Формат даты внутри окна уведомлениÑ"
msgid "(Format of the time to be displayed inside notify-bar)"
-msgstr "(Формат времени выводитÑÑ Ð²Ð½ÑƒÑ‚Ñ€Ð¸ окна уведомлениÑ)"
+msgstr "Формат времени внутри окна уведомлениÑ"
msgid ""
"(Warn user if an appointment is within next 'notify-bar_warning' seconds)"
-msgstr "(Предупреждать Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¾ Ñобытии за 'notify-bar_warning' Ñекунд)"
+msgstr "Предупреждать Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¾ мероприÑтии за n Ñекунд"
msgid "(Command used to notify user of an upcoming appointment)"
-msgstr "(Команда уведомлÑет Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¾ грÑдущем Ñобытии)"
+msgstr "Команда уведомлÑет Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¾ грÑдущем Ñобытии"
msgid "(Notify all appointments instead of flagged ones only)"
-msgstr ""
-"(Извещать обо вÑех задачах, вмеÑто тех, которые помечены Ð´Ð»Ñ Ð¸Ð·Ð²ÐµÑ‰ÐµÐ½Ð¸Ñ)"
+msgstr "Извещать обо вÑех задачах, вмеÑто тех, которые помечены Ð´Ð»Ñ Ð¸Ð·Ð²ÐµÑ‰ÐµÐ½Ð¸Ñ"
msgid "(Run in background to get notifications after exiting)"
-msgstr "(ЗапуÑтить в фоновом режиме, Ð´Ð»Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾Ñти получать уведомлениÑ)"
+msgstr "(да/нет) ЗапуÑтить ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð² фоновом режиме"
msgid "(Log activity when running in background)"
-msgstr "(Лог активен во Ð²Ñ€ÐµÐ¼Ñ Ñ„Ð¾Ð½Ð¾Ð²Ð¾Ð³Ð¾ режима)"
-
-msgid "Enter the time format (see 'man 3 strftime' for possible formats) "
-msgstr "Задайте формат времени (Ñм. 'man 3 strftime' Ð´Ð»Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ñ‹Ñ… форматов) "
+msgstr "(да/нет) ВеÑти журналирование во Ð²Ñ€ÐµÐ¼Ñ Ñ„Ð¾Ð½Ð¾Ð²Ð¾Ð³Ð¾ режима"
msgid "Enter the number of seconds (0 not to be warned before an appointment)"
-msgstr "Введите количеÑтво Ñекунд (0 - отмена Ð¾Ð¿Ð¾Ð²ÐµÑ‰ÐµÐ½Ð¸Ñ Ð´Ð¾ ÑобытиÑ)"
+msgstr "Введите количеÑтво Ñекунд (0 - отмена Ð¾Ð¿Ð¾Ð²ÐµÑ‰ÐµÐ½Ð¸Ñ Ð´Ð¾ мероприÑтиÑ)"
msgid "Enter the notification command "
msgstr "Введите команду ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ "
msgid "notification options"
-msgstr "наÑтройки уведомлениÑ"
+msgstr "ÐаÑтройки уведомлениÑ"
msgid "incoherent repetition type"
-msgstr "беÑÑвÑзный тип повторениÑ"
+msgstr "БеÑÑвÑзный тип повторениÑ."
msgid "System event"
-msgstr ""
-
-msgid "unknown repetition type"
-msgstr "неизвеÑтный тип повторениÑ"
+msgstr "СиÑтемное Ñобытие."
msgid "unknown character"
-msgstr "неизвеÑтный Ñимвол"
+msgstr "ÐеизвеÑтный Ñимвол."
+
+#, c-format
+msgid "recurrence error: not on start day (%s)"
+msgstr "Ошибка при повторении: не Ñовпадение Ñ Ð´Ð½Ñ‘Ð¼ начала (%s). "
+
+msgid "illegel date in event"
+msgstr "ÐедопуÑÑ‚Ð¸Ð¼Ð°Ñ Ð´Ð°Ñ‚Ð° Ð´Ð»Ñ ÑобытиÑ"
+
+msgid "date error in event"
+msgstr "Ошибка при запиÑи даты ÑобытиÑ"
+
+msgid "month day is zero"
+msgstr "Ошибка при чиÑленном обозначении Ð´Ð½Ñ Ð¼ÐµÑÑца."
+
+msgid "no daily frequency check"
+msgstr "ОтÑутÑтвует контроль за повторениÑми."
+
+msgid "illegal BYDAY value"
+msgstr "ÐедопуÑтимое значение Ð´Ð»Ñ Ð¾Ð±Ð¾Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð´Ð½Ñ"
msgid "event not found"
-msgstr "Ñобытие не найдено"
+msgstr "Событий не найдено"
msgid "appointment not found"
-msgstr "задача не найдена"
+msgstr "МероприÑтий не найдено"
+
+msgid "syntax error in bymonthday"
+msgstr "Ошибка при запиÑи Ð´Ð½Ñ Ð¼ÐµÑÑца."
+
+msgid "syntax error in bywday"
+msgstr "Ошибка при запиÑи Ð´Ð½Ñ Ð½ÐµÐ´ÐµÐ»Ð¸."
+
+msgid "syntax error in bymonth"
+msgstr "Ошибка при запиÑи меÑÑца."
+
+msgid "illegal bymonth value"
+msgstr "ÐедопуÑтимое значение Ð´Ð»Ñ Ð¾Ð±Ð¾Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¼ÐµÑÑца."
msgid "syntax error in item date"
-msgstr "опечатка в запиÑи даты"
+msgstr "Ошибка при запиÑи даты."
msgid "date error in item exception"
-msgstr "ошибка даты в значении"
-
-#, c-format
-msgid "Could not remove calcurse lock file: %s\n"
-msgstr "Ðевозможно удалить занÑтый файл: %s\n"
+msgstr "Ошибка в дате при обозначении иÑключений."
#, c-format
msgid "Error setting signal #%d : %s\n"
-msgstr "Сигнал ошибки наÑтройки #%d : %s\n"
+msgstr "Ошибка уÑтановки Ñигнала #%d : %s\n"
msgid "no note attached"
-msgstr "запиÑка отÑутÑтвует"
+msgstr "Заметка отÑутÑтвует"
msgid "no such todo"
-msgstr "дело не найдено"
+msgstr "Дел не найдено"
msgid "ERROR setting first day of week"
msgstr "ОШИБКРнаÑтройки первого Ð´Ð½Ñ Ð½ÐµÐ´ÐµÐ»Ð¸"
msgid "The day you entered is not valid"
-msgstr "День введён вами Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ¾Ð¹"
+msgstr "Введённые данные о желаемом дне не ÑвлÑÑŽÑ‚ÑÑ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ‚Ð½Ñ‹Ð¼Ð¸."
#, c-format
msgid "Enter the day to go to [ENTER for today] : %s"
-msgstr "Переход на N-ый день [ENTER Ð´Ð»Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ³Ð¾ днÑ] : %s"
+msgstr "Переход [Enter Ð´Ð»Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ³Ð¾ днÑ] на n-ый день: %s"
#, c-format
msgid "The move failed (%d/%d/%d)."
-msgstr ""
+msgstr "Ошибка Ð¿ÐµÑ€ÐµÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° (%d/%d/%d)."
#, c-format
msgid "Enter start date [%s] and/or time ([hh:mm] or [hhmm]):"
-msgstr ""
+msgstr "Введите дату [%s] и/или Ð²Ñ€ÐµÐ¼Ñ ([ЧЧ:ММ] или [ЧЧММ]) начала:"
msgid "Press [Enter] to continue"
-msgstr "Ðажмите [Enter]"
+msgstr "Ðажмите [Enter] Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð»Ð¶ÐµÐ½Ð¸Ñ..."
msgid "Invalid date or time."
-msgstr "ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ð´Ð°Ñ‚Ð° или времÑ."
+msgstr "Ðекорректно задано дата или времÑ."
msgid "Invalid time: start time must come before end time!"
-msgstr "Ðеверное времÑ: Ð²Ñ€ÐµÐ¼Ñ Ð½Ð°Ñ‡Ð°Ð»Ð° должно идти до времени конца"
+msgstr ""
+"Ðекорректно задано времÑ: начальное Ð²Ñ€ÐµÐ¼Ñ Ð´Ð¾Ð»Ð¶Ð½Ð¾ идти до времени окончаниÑ!"
+
+#, c-format
+msgid "Repetition must begin on start day (%s)."
+msgstr "Повторение должно начинатьÑÑ Ñ Ð¸Ð·Ð½Ð°Ñ‡Ð°Ð»ÑŒÐ½Ð¾ указанного Ð´Ð½Ñ (%s)."
msgid "Enter end date (and/or time) or duration ('?' for input formats):"
msgstr ""
-"Введите конечную дату (и/или времÑ) или продолжительноÑÑ‚ÑŒ ('?' Ñм. форматы):"
+"Введите дату Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ (и/или времÑ) или продолжительноÑÑ‚ÑŒ ('?' Ñм. Ñправку):"
#, c-format
msgid "Date: %s, year or month may be omitted."
-msgstr ""
+msgstr "Дата: %s, год или меÑÑц можно пропуÑтить."
msgid "Time: hh:mm (hh: or :mm) or hhmm. Duration: +mm, +hh:mm, +??d??h??m."
msgstr ""
-"ВремÑ: hh:mm (hh: или :mm) или hhmm. ПродолжительноÑÑ‚ÑŒ: +mm, +hh:mm, +??d??"
-"h??m."
+"ВремÑ: ЧЧ:ММ (ЧЧ: или :ММ) или ЧЧММ. ПродолжительноÑÑ‚ÑŒ: +ММ, +ЧЧ:ММ, +??д??"
+"ч??м"
msgid "Invalid time or duration."
-msgstr "Ðеверное Ð²Ñ€ÐµÐ¼Ñ Ð¸Ð»Ð¸ продолжительноÑÑ‚ÑŒ."
+msgstr "Ðекорректно задано Ð²Ñ€ÐµÐ¼Ñ Ð¸Ð»Ð¸ продолжительноÑÑ‚ÑŒ."
msgid "Invalid date: end time must come after start time."
-msgstr "ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ð´Ð°Ñ‚Ð°: конечное Ð²Ñ€ÐµÐ¼Ñ Ð´Ð¾Ð»Ð¶Ð½Ð¾ идти поÑле начального времени."
+msgstr "Ðекорректно задана дата: окончание должно идти поÑле начала."
msgid "Enter the new item description:"
-msgstr "ОпиÑание: "
+msgstr "ОпиÑание:"
msgid "Exception days:"
-msgstr ""
+msgstr "ИÑключаемые дни:"
-#, fuzzy
msgid "Invalid date format - try again:."
-msgstr "ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ð´Ð°Ñ‚Ð° или времÑ."
+msgstr "Ðекорректный формат даты - попробуйте Ñнова."
+
+msgid "Limit repetition to listed days."
+msgstr "Ð’ краткой запиÑи обозначить по каким именно днÑм ограничить."
+
+msgid "Expand repetition to listed days."
+msgstr "Ð’ краткой запиÑи обозначить по каким именно днÑм повторÑÑ‚ÑŒ."
+
+msgid "Expand repetition to listed days, either all or 1st, 2nd, ... of month."
+msgstr ""
+"ЧиÑленно обозначить по каким именно днÑм в меÑÑце повторÑÑ‚ÑŒ: 1 2 .. 22 .."
-msgid "Enter the new repetition type:"
-msgstr "Введите тип повторениÑ:"
+msgid "Note: limit to monthdays, if any."
+msgstr "Примечание: Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾ конкретным днÑм меÑÑца (опционально)."
-msgid "(d)aily"
-msgstr "(d)ежедневно"
+msgid "Expand repetition to listed days, either all or 1st, 2nd, ... of year."
+msgstr ""
+"ЧиÑленно обозначить по каким именно днÑм в году повторÑÑ‚ÑŒ: 1 2 .. 322 .."
+
+msgid "Note: expand to listed months, if any; limit to monthdays, if any."
+msgstr ""
+"Примечание: раÑширить по меÑÑцам и/или ограничить по днÑм (опционально)."
+
+msgid "Limit repetition to listed months."
+msgstr "ЧиÑленно обозначить по каким именно меÑÑцам ограничить."
-msgid "(w)eekly"
-msgstr "(w)еженедельно"
+msgid "Expand repetition to listed months."
+msgstr "ЧиÑленно обозначить по каким именно меÑÑцам повторÑÑ‚ÑŒ."
-msgid "(m)onthly"
-msgstr "(m)ежемеÑÑчно"
+msgid "Limit repetition to listed days of month."
+msgstr "ЧиÑленно обозначить по каким именно днÑм в меÑÑце ограничить."
-msgid "(y)early"
-msgstr "(y)ежегодно"
+msgid "Expand repetition to listed days of month."
+msgstr "ЧиÑленно обозначить по каким именно днÑм в меÑÑце повторÑÑ‚ÑŒ."
#, c-format
-msgid "(currently using %s)"
-msgstr "(иÑпользуетÑÑ %s)"
+msgid "Weekdays %s|..|%s, space-separated list, '?' for help:"
+msgstr "Задайте днÑми %s .. %s, разделÑÑ Ð¿Ñ€Ð¾Ð±ÐµÐ»Ð¾Ð¼ ('?' Ñм. Ñправку):"
+
+#, c-format
+msgid ""
+"Weekdays [n]%s|..|[n]%s, space-separated list, n=1,-1,..,5,-5, '?' for help:"
+msgstr ""
+"Задайте днÑми [n]%s .. [n]%s (-5<=n<=5), разделÑÑ Ð¿Ñ€Ð¾Ð±ÐµÐ»Ð¾Ð¼ ('?' Ñм. Ñправку):"
+
+#, c-format
+msgid ""
+"Weekdays [n]%s|..|[n]%s, space-separated list, n=1,-1,..,53,-53, '?' for "
+"help:"
+msgstr ""
+"Задайте днÑми [n]%s .. [n]%s (-53<=n<=53), разделÑÑ Ð¿Ñ€Ð¾Ð±ÐµÐ»Ð¾Ð¼ ('?' Ñм. "
+"Ñправку):"
+
+msgid "Months 1|..|12, space-separated list, '?' for help:"
+msgstr ""
+"Задайте меÑÑцы 1 2 .. n (1<=n<=12), разделÑÑ Ð¿Ñ€Ð¾Ð±ÐµÐ»Ð¾Ð¼ ('?' Ñм. Ñправку):"
+
+msgid "Monthdays 1|..|31 or -1|..|-31, space-separated list, '?' for help:"
+msgstr ""
+"Задайте дни меÑÑца 1 2 .. 31 или -1 .. -31, разделÑÑ Ð¿Ñ€Ð¾Ð±ÐµÐ»Ð¾Ð¼ ('?' Ñм."
+"Ñправку):"
+
+msgid "Invalid format - try again."
+msgstr "Указан некорректный формат. ПожалуйÑта, попробуйте ещё раз."
+
+msgid "Press any key to continue."
+msgstr "Ðажмите любую клавишу..."
+
+msgid "Base period:"
+msgstr "Базовый период:"
+
+msgid "day"
+msgstr "(d)день"
+
+msgid "week"
+msgstr "(w)неделÑ"
+
+msgid "month"
+msgstr "(m)меÑÑц"
+
+msgid "year"
+msgstr "(y)год"
msgid "[dwmy]"
-msgstr "[днмг]"
+msgstr "[dwmy]"
-msgid "Invalid frequency."
-msgstr "ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ñ‡Ð°Ñтота."
+msgid "Frequency:"
+msgstr "ЧаÑтота повторов:"
-msgid "Enter the repetition frequency:"
-msgstr "Введите чаÑтоту повторениÑ:"
+msgid "Invalid frequency."
+msgstr "Указано некорректное значение Ð´Ð»Ñ Ñ‡Ð°Ñтоты повторов."
-msgid "Enter end date or duration ('?' for input formats):"
-msgstr "Введите конечную дату или продолжительноÑÑ‚ÑŒ ('?' Ñм. форматы):"
+msgid "Until date, increment or repeat count ('?' for input formats):"
+msgstr ""
+"Задайте дату Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€ÐµÐ½Ð¸Ð¹, период. или кол-во повтор. ('?' Ñм. "
+"Ñправку)"
#, c-format
-msgid "Date: %s (year or month may be omitted). Endless duration: 0."
+msgid "Date: %s (year, month may be omitted, endless: 0)."
msgstr ""
+"Дата: %s (год, меÑÑц могут быть опущены или впиÑать \"0\" - беÑконечно)."
-msgid "Duration in days: +dd. Duration in weeks and days: +??w??d."
+msgid "Increment: +?? (days) or: +??w??d (weeks). Repeat count: #?? (number)."
msgstr ""
-"ПродолжительноÑÑ‚ÑŒ в днÑÑ…: +dd. ПродолжительноÑÑ‚ÑŒ в неделÑÑ… и днÑÑ…: +??w??d"
+"ПовторÑÑ‚ÑŒ: +?? (дней) или: +??н??д (недель). Кол-во повторений: #?? (чиÑлом)"
#, c-format
-msgid "Invalid date: end date must come after start date (%s)."
-msgstr "ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ð´Ð°Ñ‚Ð°: ÐºÐ¾Ð½ÐµÑ‡Ð½Ð°Ñ Ð´Ð°Ñ‚Ð° должны идти поÑле начальной даты (%s)."
+msgid "Invalid date: until date must come after start date (%s)."
+msgstr "Дата Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° Ñледовать за датой начала (%s)."
msgid "Invalid date."
-msgstr "ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ð´Ð°Ñ‚Ð°."
+msgstr "Указано некорректное значение даты."
+
+msgid "Repeat count is too big."
+msgstr "Элементов в поÑледовательноÑти мероприÑтий Ñлишком много."
+
+#, c-format
+msgid "Repetition must begin on start day (%s); any change discarded."
+msgstr "ПоÑледовательноÑÑ‚ÑŒ должна идти от начала (%s); ÑÐ±Ñ€Ð¾Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ð¹."
msgid "Description"
-msgstr "ОпиÑание"
+msgstr "опиÑание"
msgid "Repetition"
-msgstr "Повторение"
+msgstr "поÑлед."
msgid "Edit: "
-msgstr "Редактировать:"
+msgstr "Изм.:"
msgid "Start time"
-msgstr "Ðачальное времÑ"
+msgstr "начало"
msgid "End time"
-msgstr "Конечное времÑ"
+msgstr "окончание"
msgid "Move"
-msgstr "Вперёд"
+msgstr "Ñдвиг"
msgid "Pipe item to external command:"
-msgstr "Программный канал (pipe) во внешнюю команду:"
+msgstr "Передать Ñлемент во внешнюю команду:"
msgid "Enter start time ([hh:mm] or [hhmm]), leave blank for an all-day event:"
msgstr ""
-"Ðачало ([чч:мм] или [ччмм]). ОÑтавьте пуÑтым еÑли Ñобытие займёт веÑÑŒ день: "
+"Ðачало ([ЧЧ:ММ] или [ЧЧММ]). ОÑтавьте пуÑтым еÑли Ñобытие займёт веÑÑŒ день:"
msgid ""
"Enter end time as date (and/or time) or duration ('?' for input formats):"
msgstr ""
+"Введите дату Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ (и/или времÑ) или продолжительноÑÑ‚ÑŒ ('?' Ñм. Ñправку):"
msgid "Enter description:"
-msgstr "ОпиÑание: "
+msgstr "Введите опиÑание:"
#, c-format
msgid "Date: %s (and/or time), year or month may be omitted."
-msgstr ""
+msgstr "Дата: %s (и/или времÑ), год и меÑÑц можно опуÑтить."
msgid "Invalid start time."
-msgstr "Ðеверное начальное времÑ."
-
-msgid "Do you really want to delete this item?"
-msgstr "Удалить?"
+msgstr "Указан некорректный формат Ð´Ð»Ñ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð¸ начала мероприÑтиÑ."
-msgid "This item is recurrent. Delete (a)ll occurences or just this (o)ne?"
+msgid ""
+"This item is recurrent and has a note attached to it. Delete (s)elected "
+"occurrence, (a)ll occurrences, or just its (n)ote?"
msgstr ""
-"Эта запиÑÑŒ имеет повторениÑ. Удалить (a)вÑе подобные запиÑи или только "
-"(o)Ñту ?"
+"ПоÑледов. мероприÑтий Ñ Ð·Ð°Ð¼ÐµÑ‚ÐºÐ¾Ð¹. УдалÑем (s)одно, (a)вÑÑ‘ или (n)заметку?"
-msgid "[ao]"
-msgstr "[ао]"
+msgid "[san]"
+msgstr "[san]"
-msgid "This item has a note attached to it. Delete (i)tem or just its (n)ote?"
-msgstr "Эта запиÑÑŒ Ñодержит заметку. Удалить (i)запиÑÑŒ или только (n)заметку ?"
+msgid ""
+"This item has a note attached to it. Delete (s)elected occurrence or just "
+"its (n)ote?"
+msgstr "МероприÑтие Ñ Ð·Ð°Ð¼ÐµÑ‚ÐºÐ¾Ð¹. УдалÑем вÑÑ‘ (s)выбранное или (n)заметку?"
-msgid "[in]"
-msgstr "[в]"
+msgid "[sn]"
+msgstr "[sn]"
-msgid "Enter the repetition type:"
-msgstr "Ðазначить тип повторениÑ:"
+msgid ""
+"This item is recurrent. Delete (s)elected occurrence or (a)ll occurrences?"
+msgstr "ПоÑледовательноÑÑ‚ÑŒ мероприÑтий. УдалÑем (s)одно или (a)вÑÑ‘?"
-#, c-format
-msgid "Date: %s (year or month may be omitted). Endless duration: '0'."
-msgstr ""
+msgid "[sa]"
+msgstr "[sa]"
-msgid "This item is already a repeated one."
-msgstr "Эта запиÑÑŒ уже повторÑетÑÑ."
+msgid "Confirm deletion. Delete (s)elected occurrence? Press (s) to confirm."
+msgstr "Подтвердите удаление. Удалить (s)выбранное?"
-msgid "wrong item type"
-msgstr "неправильный тип запиÑи"
+msgid "[s]"
+msgstr "[s]"
+
+msgid "Already repeated."
+msgstr "Уже повторÑетÑÑ."
+
+msgid "A (s)imple or (a)dvanced repetition?"
+msgstr "ТребуетÑÑ (s)проÑтое или (a)замыÑловатое повторение?"
msgid "Enter the new TODO item:"
msgstr "Дело: "
msgid "Enter the TODO priority [0 (none), 1 (highest) - 9 (lowest)]:"
-msgstr "Введите приоритет Дела [0 (без приоритета), 1 (выÑокий) - 9 (низкий)]:"
+msgstr ""
+"Введите приоритет Ð´Ð»Ñ Ð”ÐµÐ»Ð° [0 (без приоритета), 1 (выÑокий), … , 9 (низкий)]:"
msgid "Do you really want to delete this task?"
msgstr "Удалить Ñту запиÑÑŒ?"
msgid "This item has a note attached to it. Delete (t)odo or just its (n)ote?"
-msgstr "К делу прикреплена запиÑка. Удалить (t)дело или только (n)запиÑку ?"
+msgstr "К делу прикреплена заметка. Удалить вÑÑ‘ (t)дело или (n)заметку?"
msgid "[tn]"
msgstr "[tn]"
msgid "Enter the new TODO description:"
-msgstr "ОпиÑание дела: "
+msgstr "ОпиÑание Дела:"
msgid "TODO:"
-msgstr "Дело:"
+msgstr "Дела:"
+
+#, c-format
+msgid "Could not remove calcurse lock file: %s\n"
+msgstr "Ðевозможно удалить файл блокировки Ð´Ð»Ñ calcurse: %s\n"
msgid "/!\\ INTERNAL ERROR /!\\"
-msgstr "/!\\ INTERNAL ERROR /!\\"
+msgstr "/!\\ ÐЕПОÐЯТÐÐЯ ОШИБКР/!\\"
msgid "Please report the following bug:"
-msgstr "Сообщите об ошибке:"
+msgstr "ПожалуйÑта, Ñообщите об ошибке:"
msgid "[yn]"
msgstr "[yn]"
@@ -1565,57 +1844,62 @@ msgid "Press any key to continue..."
msgstr "Ðажмите любую клавишу..."
msgid "failure in mktime"
-msgstr "ошибка в mktime"
+msgstr "Сбой в mktime"
msgid "error in mktime"
-msgstr "ошибка в mktime"
+msgstr "Ошибка в mktime"
msgid "yes"
-msgstr "yes"
+msgstr "Да"
msgid "no"
-msgstr "no"
+msgstr "Ðет"
msgid "option not defined"
-msgstr "параметр не уÑтановлен"
+msgstr "ÐžÐ¿Ñ†Ð¸Ñ Ð½Ðµ определена"
#, c-format
msgid "temporary file \"%s\" could not be created"
-msgstr "временный файл \"%s\" не может быть Ñоздан"
+msgstr "Временный файл \"%s\" не может быть Ñоздан"
#, c-format
msgid "Error when closing file at %s"
-msgstr "Ошибка во Ð²Ñ€ÐµÐ¼Ñ Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° %s"
+msgstr "Ошибка в процеÑÑе Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° %s"
msgid "No note file found\n"
msgstr "Файл Ñ Ð·Ð°Ð¼ÐµÑ‚ÐºÐ¾Ð¹ не найден\n"
msgid "mm/dd/yyyy"
-msgstr "мм/дд/гггг"
+msgstr "ММ/ДД/ГГГГ"
msgid "dd/mm/yyyy"
-msgstr "дд/мм/гггг"
+msgstr "ДД/ММ/ГГГГ"
msgid "yyyy/mm/dd"
-msgstr "гггг/мм/дд"
+msgstr "ГГГГ/ММ/ДД"
msgid "yyyy-mm-dd"
-msgstr "гггг-мм-дд"
+msgstr "ГГГГ-ММ-ДД"
msgid "unknown panel"
-msgstr "неизвеÑÑ‚Ð½Ð°Ñ Ð¿Ð°Ð½ÐµÐ»ÑŒ"
+msgstr "ÐераÑÐ¿Ð¾Ð·Ð½Ð°Ð½Ð½Ð°Ñ Ð¿Ð°Ð½ÐµÐ»ÑŒ"
msgid "Usage: calcurse-upgrade [-h|-v|--config <file>]"
-msgstr "ИÑпользовать: calcurse-upgrade [-h|-v|--config <file>]"
+msgstr "ИÑпользуйте: calcurse-upgrade [ -h | -v | --config <file> ]"
msgid ""
"\n"
-"Copyright (c) 2004-2017 calcurse Development Team.\n"
+"Copyright (c) 2004-2023 calcurse Development Team.\n"
"This is free software; see the source for copying conditions.\n"
msgstr ""
+"\n"
+"Copyright (c) 2004-2023 calcurse Development Team.\n"
+"Это Ñвободное программное обеÑпечение.\n"
+"Ð”Ð»Ñ Ð¾Ð·Ð½Ð°ÐºÐ¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ñ ÑƒÑловиÑми ÐºÐ¾Ð¿Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñтого программного обеÑпечениÑ,\n"
+"ознакомьтеÑÑŒ Ñ Ð¸Ñходным кодом.\n"
msgid "unrecognized option:"
-msgstr "неизвеÑÑ‚Ð½Ð°Ñ Ð¾Ð¿Ñ†Ð¸Ñ:"
+msgstr "ÐеизвеÑÑ‚Ð½Ð°Ñ Ð¾Ð¿Ñ†Ð¸Ñ:"
msgid "Configuration file not found:"
msgstr "Файл конфигурации не найден:"
@@ -1627,7 +1911,7 @@ msgid "Create temporary backup of the configuration file..."
msgstr "Создать временную архивную копию файла конфигурации..."
msgid "Old backup file found:"
-msgstr "Предыдущий файл архивной копии найден:"
+msgstr "ÐÐ°Ð¹Ð´ÐµÐ½Ð½Ð°Ñ Ð¿Ñ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰Ð°Ñ ÐºÐ¾Ð¿Ð¸Ñ Ð°Ñ€Ñ…Ð¸Ð²Ð° данных:"
msgid ""
"\n"
@@ -1635,14 +1919,14 @@ msgid ""
"configuration from this backup and then remove the backup file."
msgstr ""
"\n"
-"ЕÑли Ð¿Ñ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰Ð°Ñ ÐºÐ¾Ð½Ð²ÐµÑ€Ñ‚Ð°Ñ†Ð¸Ñ Ð½Ðµ завершилаÑÑŒ, воÑÑтановите вашу конфигурацию "
-"из Ñтого архивного файла, затем его удалив."
+"ЕÑли Ð¿Ñ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰Ð°Ñ ÐºÐ¾Ð½Ð²ÐµÑ€Ñ‚Ð°Ñ†Ð¸Ñ Ð½Ðµ завершилаÑÑŒ,\n"
+"воÑÑтановите вашу конфигурацию из Ñтого архивного файла, затем его удалив."
msgid "done"
-msgstr "завершено"
+msgstr "Готово"
msgid "Old temporary file found:"
-msgstr "Обнаружен предыдущий временный файл данных:"
+msgstr "Ðайденный предыдущий временный файл:"
msgid ""
"\n"
@@ -1651,11 +1935,11 @@ msgid ""
"start over with a backup of your old configuration file."
msgstr ""
"\n"
-"ЕÑли Ð¿Ñ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰Ð°Ñ ÐºÐ¾Ð½Ð²ÐµÑ€Ñ‚Ð°Ñ†Ð¸Ñ Ð½Ðµ завершилаÑÑŒ, удалите файл и попробуйте Ñнова, "
-"иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð°Ñ€Ñ…Ð¸Ð²Ð½Ñ‹Ð¹ файл Ñ Ð¿Ñ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰ÐµÐ¹ конфигурацией."
+"ЕÑли Ð¿Ñ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰Ð°Ñ ÐºÐ¾Ð½Ð²ÐµÑ€Ñ‚Ð°Ñ†Ð¸Ñ Ð½Ðµ завершилаÑÑŒ, удалите файл и\n"
+"попробуйте Ñнова, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð°Ñ€Ñ…Ð¸Ð²Ð½Ñ‹Ð¹ файл Ñ Ð¿Ñ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰ÐµÐ¹ конфигурацией."
msgid "Upgrade configuration directives..."
msgstr "Обновление конфигурации..."
msgid "Remove temporary backup..."
-msgstr "Удалить временный архивный файл..."
+msgstr "Удаление временной копии архива данных..."
diff --git a/scripts/calcurse-upgrade.sh.in b/scripts/calcurse-upgrade.sh.in
index 1df1547..b6a7438 100644
--- a/scripts/calcurse-upgrade.sh.in
+++ b/scripts/calcurse-upgrade.sh.in
@@ -15,7 +15,7 @@ if [ "$#" -gt 0 ]; then
elif [ "$1" = "-v" -o "$1" = "--version" ]; then
echo "calcurse-upgrade @PACKAGE_VERSION@"
echo "$(gettext "
-Copyright (c) 2004-2017 calcurse Development Team.
+Copyright (c) 2004-2023 calcurse Development Team.
This is free software; see the source for copying conditions.
")"
else
diff --git a/src/apoint.c b/src/apoint.c
index 5a9802a..e138e5e 100644
--- a/src/apoint.c
+++ b/src/apoint.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -42,6 +42,8 @@
#include "calcurse.h"
#include "sha1.h"
+#define APPT_TIME_LENGTH 25
+
llist_ts_t alist_p;
void apoint_free(struct apoint *apt)
@@ -134,16 +136,14 @@ void apoint_sec2str(struct apoint *o, time_t day, char *start, char *end)
} else {
t = o->start;
localtime_r(&t, &lt);
- snprintf(start, HRMIN_SIZE, "%02u:%02u", lt.tm_hour,
- lt.tm_min);
+ strftime(start, APPT_TIME_LENGTH, conf.timefmt, &lt);
}
if (o->start + o->dur > day + DAYLEN(day)) {
strncpy(end, "..:..", 6);
} else {
t = o->start + o->dur;
localtime_r(&t, &lt);
- snprintf(end, HRMIN_SIZE, "%02u:%02u", lt.tm_hour,
- lt.tm_min);
+ strftime(end, APPT_TIME_LENGTH, conf.timefmt, &lt);
}
}
@@ -195,7 +195,7 @@ void apoint_write(struct apoint *o, FILE * f)
mem_free(str);
}
-struct apoint *apoint_scan(FILE * f, struct tm start, struct tm end,
+char *apoint_scan(FILE * f, struct tm start, struct tm end,
char state, char *note, struct item_filter *filter)
{
char buf[BUFSIZ], *newline;
@@ -203,15 +203,15 @@ struct apoint *apoint_scan(FILE * f, struct tm start, struct tm end,
struct apoint *apt = NULL;
int cond;
- EXIT_IF(!check_date(start.tm_year, start.tm_mon, start.tm_mday) ||
- !check_date(end.tm_year, end.tm_mon, end.tm_mday) ||
- !check_time(start.tm_hour, start.tm_min) ||
- !check_time(end.tm_hour, end.tm_min),
- _("date error in appointment"));
+ if (!check_date(start.tm_year, start.tm_mon, start.tm_mday) ||
+ !check_date(end.tm_year, end.tm_mon, end.tm_mday) ||
+ !check_time(start.tm_hour, start.tm_min) ||
+ !check_time(end.tm_hour, end.tm_min))
+ return _("illegal date in appointment");
/* Read the appointment description */
if (!fgets(buf, sizeof buf, f))
- return NULL;
+ return _("error in appointment description");
newline = strchr(buf, '\n');
if (newline)
@@ -226,8 +226,8 @@ struct apoint *apoint_scan(FILE * f, struct tm start, struct tm end,
tstart = mktime(&start);
tend = mktime(&end);
- EXIT_IF(tstart == -1 || tend == -1 || tstart > tend,
- _("date error in appointment"));
+ if (tstart == -1 || tend == -1 || tstart > tend)
+ return _("date error in appointment");
/* Filter item. */
if (filter) {
@@ -255,8 +255,7 @@ struct apoint *apoint_scan(FILE * f, struct tm start, struct tm end,
}
if (!apt)
apt = apoint_new(buf, note, tstart, tend - tstart, state);
-
- return apt;
+ return NULL;
}
void apoint_delete(struct apoint *apt)
diff --git a/src/args.c b/src/args.c
index e6444e4..57cbe63 100644
--- a/src/args.c
+++ b/src/args.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -97,7 +97,7 @@ static void usage(void)
"calcurse [-D <directory>] [-C <directory>] [-c <calendar file>]\n"
"calcurse -Q [--from <date>] [--to <date>] [--days <number>]\n"
"calcurse -a | -d <date> | -d <number> | -n | -r[<number>] | -s[<date>] | -t[<number>]\n"
- "calcurse -h | -v | --status | -G | -P | -g | -i <file> | -x[<file>] | --daemon"));
+ "calcurse -h | -v | --status | -G | -P | -g | -i <file> | -x[<format>] | --daemon"));
}
static void usage_try(void)
@@ -112,7 +112,7 @@ static void version_arg(void)
{
printf(_("calcurse %s -- text-based organizer\n"), VERSION);
putchar('\n');
- printf("%s\n", _("Copyright (c) 2004-2017 calcurse Development Team."));
+ printf("%s\n", _("Copyright (c) 2004-2023 calcurse Development Team."));
printf("%s\n", _("This is free software; see the source for copying conditions."));
}
@@ -149,7 +149,7 @@ static void help_arg(void)
printf("%s\n", _(" -g, --gc Run the garbage collector"));
printf("%s\n", _(" -h, --help Show this help text"));
printf("%s\n", _(" -i, --import <file> Import iCal data from file"));
- printf("%s\n", _(" -q, --quiet Suppress system dialogs"));
+ printf("%s\n", _(" -q, --quiet Suppress import/export result message"));
printf("%s\n", _(" --read-only Do not save configuration or data files"));
printf("%s\n", _(" --status Display status of running instances"));
printf("%s\n", _(" -v, --version Show version information"));
@@ -398,7 +398,7 @@ cleanup:
/*
* Parse the command-line arguments and call the appropriate
* routines to handle those arguments. Also initialize the data paths.
- * Returns the non-interactive value.
+ * Exit here in case of errors else return the non-interactive value.
*/
int parse_args(int argc, char **argv)
{
@@ -425,9 +425,10 @@ int parse_args(int argc, char **argv)
int dump_imported = 0, export_uid = 0;
/* Data file locations */
const char *datadir = NULL;
- const char *cfile = NULL, *ifile = NULL, *confdir = NULL;
+ const char *cfile = NULL, *confdir = NULL;
+ char *ifile = NULL;
- int non_interactive = 1;
+ int ret, non_interactive = 1;
int ch, cpid, type;
regex_t reg;
char buf[BUFSIZ];
@@ -514,6 +515,10 @@ int parse_args(int argc, char **argv)
case 'c':
cfile = optarg;
break;
+ case '?':
+ usage();
+ usage_try();
+ exit(EXIT_FAILURE); \
}
}
io_init(cfile, datadir, confdir);
@@ -556,7 +561,7 @@ int parse_args(int argc, char **argv)
break;
case 'h':
help_arg();
- goto cleanup;
+ exit(EXIT_SUCCESS);
case 'g':
gc = 1;
break;
@@ -614,7 +619,7 @@ int parse_args(int argc, char **argv)
break;
case 'v':
version_arg();
- goto cleanup;
+ exit(EXIT_SUCCESS);
case 'x':
export = 1;
if (optarg) {
@@ -859,10 +864,6 @@ int parse_args(int argc, char **argv)
'\0';
cmd_line = 1;
break;
- default:
- usage();
- usage_try();
- goto cleanup;
}
}
@@ -875,12 +876,8 @@ int parse_args(int argc, char **argv)
(format_opt && !(grep + query + dump_imported)) ||
(query_range && !query) ||
(purge && !filter.invert)
- ) {
- ERROR_MSG(_("invalid argument combination"));
- usage();
- usage_try();
- goto cleanup;
- }
+ )
+ EXIT(_("invalid argument combination"));
EXIT_IF(to >= 0 && range, _("cannot specify a range and an end date"));
if (from == -1)
@@ -966,10 +963,12 @@ int parse_args(int argc, char **argv)
fmt_apt = fmt_rapt = fmt_ev = fmt_rev = NULL;
fmt_todo = NULL;
}
- io_import_data(IO_IMPORT_ICAL, ifile, fmt_ev, fmt_rev, fmt_apt,
- fmt_rapt, fmt_todo);
+ ret = io_import_data(IO_IMPORT_ICAL, ifile, fmt_ev, fmt_rev,
+ fmt_apt, fmt_rapt, fmt_todo);
io_save_apts(path_apts);
io_save_todo(path_todo);
+ if (!ret)
+ exit_calcurse(EXIT_FAILURE);
} else if (export) {
io_check_file(path_apts);
io_check_file(path_todo);
@@ -983,7 +982,6 @@ int parse_args(int argc, char **argv)
non_interactive = 0;
}
-cleanup:
/* Free filter parameters. */
if (filter.regex)
regfree(filter.regex);
diff --git a/src/calcurse.c b/src/calcurse.c
index 7eb6b12..c89d1dd 100644
--- a/src/calcurse.c
+++ b/src/calcurse.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -41,36 +41,6 @@
#define HANDLE_KEY(key, fn) case key: fn(); break;
int count, reg;
-/*
- * Store events and appointments for a range of days in the day vector -
- * beginning with the selected day - and load them into the APP listbox. If no
- * day-change occurs, reset the selected APP item and with it the selected day,
- * thereby storing and loading the same range of days.
- */
-static void do_storage(int day_changed)
-{
- /*
- * Save the selected item before rebuilding the day vector -
- * unless already set.
- */
- if (!day_check_sel_data())
- day_set_sel_data(ui_day_get_sel());
-
- if (!day_changed)
- ui_day_sel_reset();
-
- /* The day_items vector. */
- day_store_items(get_slctd_day(), 1, day_get_days());
- /* The APP listbox. */
- ui_day_load_items();
-
- if (day_changed)
- ui_day_sel_reset();
- else
- ui_day_find_sel();
-
- day_set_sel_data(&empty_day);
-}
static inline void key_generic_change_view(void)
{
@@ -79,6 +49,13 @@ static inline void key_generic_change_view(void)
wins_update(FLAG_ALL);
}
+static inline void key_generic_prev_view(void)
+{
+ wins_reset_status_page();
+ wins_slctd_prev();
+ wins_update(FLAG_ALL);
+}
+
static inline void key_generic_other_cmd(void)
{
wins_other_status_page();
@@ -90,7 +67,7 @@ static inline void key_generic_goto(void)
wins_erase_status_bar();
ui_calendar_set_current_date();
ui_calendar_change_day(conf.input_datefmt);
- do_storage(1);
+ day_do_storage(1);
wins_update(FLAG_CAL | FLAG_APP | FLAG_STA);
}
@@ -99,7 +76,7 @@ static inline void key_generic_goto_today(void)
wins_erase_status_bar();
ui_calendar_set_current_date();
ui_calendar_goto_today();
- do_storage(1);
+ day_do_storage(1);
wins_update(FLAG_CAL | FLAG_APP | FLAG_STA);
}
@@ -117,14 +94,14 @@ static inline void key_generic_config_menu(void)
wins_erase_status_bar();
wins_reset_status_page();
custom_config_main();
- do_storage(0);
+ day_do_storage(0);
wins_update(FLAG_ALL);
}
static inline void key_generic_add_appt(void)
{
ui_day_item_add();
- do_storage(0);
+ day_do_storage(0);
wins_update(FLAG_CAL | FLAG_APP | FLAG_STA);
}
@@ -140,7 +117,7 @@ static inline void key_add_item(void)
case APP:
case CAL:
ui_day_item_add();
- do_storage(0);
+ day_do_storage(0);
wins_update(FLAG_CAL | FLAG_APP | FLAG_STA);
break;
case TOD:
@@ -156,7 +133,7 @@ static inline void key_edit_item(void)
{
if (wins_slctd() == APP && !event_dummy(ui_day_get_sel())) {
ui_day_item_edit();
- do_storage(0);
+ day_do_storage(0);
wins_update(FLAG_CAL | FLAG_APP | FLAG_STA);
} else if (wins_slctd() == TOD) {
ui_todo_edit();
@@ -168,7 +145,7 @@ static inline void key_del_item(void)
{
if (wins_slctd() == APP && !event_dummy(ui_day_get_sel())) {
ui_day_item_delete(reg);
- do_storage(0);
+ day_do_storage(0);
wins_update(FLAG_CAL | FLAG_APP | FLAG_STA);
} else if (wins_slctd() == TOD) {
ui_todo_delete();
@@ -186,7 +163,7 @@ static inline void key_generic_paste(void)
{
if (wins_slctd() == APP) {
ui_day_item_paste(reg);
- do_storage(0);
+ day_do_storage(0);
wins_update(FLAG_CAL | FLAG_APP);
}
}
@@ -195,7 +172,7 @@ static inline void key_repeat_item(void)
{
if (wins_slctd() == APP && !event_dummy(ui_day_get_sel())) {
ui_day_item_repeat();
- do_storage(0);
+ day_do_storage(0);
wins_update(FLAG_CAL | FLAG_APP | FLAG_STA);
}
}
@@ -204,7 +181,7 @@ static inline void key_flag_item(void)
{
if (wins_slctd() == APP && !event_dummy(ui_day_get_sel())) {
ui_day_flag();
- do_storage(0);
+ day_do_storage(0);
wins_update(FLAG_APP);
} else if (wins_slctd() == TOD) {
ui_todo_flag();
@@ -243,7 +220,7 @@ static inline void key_edit_note(void)
{
if (wins_slctd() == APP && !event_dummy(ui_day_get_sel())) {
ui_day_edit_note();
- do_storage(0);
+ day_do_storage(0);
} else if (wins_slctd() == TOD) {
ui_todo_edit_note();
}
@@ -283,7 +260,7 @@ static inline void key_generic_save(void)
if (ret == IO_SAVE_RELOAD) {
ui_todo_load_items();
ui_todo_sel_reset();
- do_storage(0);
+ day_do_storage(0);
notify_check_next_app(1);
ui_calendar_monthly_view_cache_set_invalid();
}
@@ -318,7 +295,7 @@ static inline void key_generic_reload(void)
ret == IO_RELOAD_MERGE) {
ui_todo_load_items();
ui_todo_sel_reset();
- do_storage(0);
+ day_do_storage(0);
notify_check_next_app(1);
ui_calendar_monthly_view_cache_set_invalid();
}
@@ -348,7 +325,8 @@ static inline void key_generic_import(void)
wins_erase_status_bar();
io_import_data(IO_IMPORT_ICAL, NULL, NULL, NULL, NULL, NULL, NULL);
ui_calendar_monthly_view_cache_set_invalid();
- do_storage(0);
+ day_do_storage(0);
+ ui_todo_load_items();
wins_update(FLAG_ALL);
}
@@ -372,14 +350,14 @@ static inline void key_generic_export()
break;
}
- do_storage(0);
+ day_do_storage(0);
wins_update(FLAG_ALL);
}
static inline void key_generic_prev_day(void)
{
ui_calendar_move(DAY_PREV, count);
- do_storage(1);
+ day_do_storage(1);
wins_update(FLAG_CAL | FLAG_APP);
}
@@ -392,7 +370,7 @@ static inline void key_move_left(void)
static inline void key_generic_next_day(void)
{
ui_calendar_move(DAY_NEXT, count);
- do_storage(1);
+ day_do_storage(1);
wins_update(FLAG_CAL | FLAG_APP);
}
@@ -405,7 +383,7 @@ static inline void key_move_right(void)
static inline void key_generic_prev_week(void)
{
ui_calendar_move(WEEK_PREV, count);
- do_storage(1);
+ day_do_storage(1);
wins_update(FLAG_CAL | FLAG_APP);
}
@@ -416,7 +394,7 @@ static inline void key_move_up(void)
} else if (wins_slctd() == APP) {
if (!ui_day_sel_move(-1)) {
ui_calendar_move(DAY_PREV, 1);
- do_storage(1);
+ day_do_storage(1);
ui_day_sel_dayend();
}
wins_update(FLAG_APP | FLAG_CAL);
@@ -429,7 +407,7 @@ static inline void key_move_up(void)
static inline void key_generic_next_week(void)
{
ui_calendar_move(WEEK_NEXT, count);
- do_storage(1);
+ day_do_storage(1);
wins_update(FLAG_CAL | FLAG_APP);
}
@@ -440,7 +418,7 @@ static inline void key_move_down(void)
} else if (wins_slctd() == APP) {
if (!ui_day_sel_move(1)) {
ui_calendar_move(DAY_PREV, day_get_days() - 2);
- do_storage(1);
+ day_do_storage(1);
ui_day_sel_daybegin(day_get_days() - 1);
}
wins_update(FLAG_APP | FLAG_CAL);
@@ -453,28 +431,28 @@ static inline void key_move_down(void)
static inline void key_generic_prev_month(void)
{
ui_calendar_move(MONTH_PREV, count);
- do_storage(1);
+ day_do_storage(1);
wins_update(FLAG_CAL | FLAG_APP);
}
static inline void key_generic_next_month(void)
{
ui_calendar_move(MONTH_NEXT, count);
- do_storage(1);
+ day_do_storage(1);
wins_update(FLAG_CAL | FLAG_APP);
}
static inline void key_generic_prev_year(void)
{
ui_calendar_move(YEAR_PREV, count);
- do_storage(1);
+ day_do_storage(1);
wins_update(FLAG_CAL | FLAG_APP);
}
static inline void key_generic_next_year(void)
{
ui_calendar_move(YEAR_NEXT, count);
- do_storage(1);
+ day_do_storage(1);
wins_update(FLAG_CAL | FLAG_APP);
}
@@ -482,7 +460,7 @@ static inline void key_start_of_week(void)
{
if (wins_slctd() == CAL) {
ui_calendar_move(WEEK_START, count);
- do_storage(1);
+ day_do_storage(1);
wins_update(FLAG_CAL | FLAG_APP);
}
}
@@ -491,7 +469,7 @@ static inline void key_end_of_week(void)
{
if (wins_slctd() == CAL) {
ui_calendar_move(WEEK_END, count);
- do_storage(1);
+ day_do_storage(1);
wins_update(FLAG_CAL | FLAG_APP);
}
}
@@ -555,7 +533,8 @@ static inline void key_generic_cmd(void)
int valid = 0, force = 0, ret;
char *error_msg;
- status_mesg(_("Command: [ h(elp) | w(rite)(!) | q(uit)(!) | wq(!) ]"), "");
+ status_mesg(_("Command: "
+ "[ h(elp) | w(rite)(!) | q(uit)(!) | wq(!) | n(ext) | p(rev) ]"), "");
if (getstring(win[STA].p, cmd, BUFSIZ, 0, 1) != GETSTRING_VALID)
goto cleanup;
cmd_name = strtok(cmd, " ");
@@ -607,6 +586,96 @@ static inline void key_generic_cmd(void)
valid = 1;
}
+ if (!strcmp(cmd_name, "next") || !strcmp(cmd_name, "n")) {
+ struct day_item *item;
+ time_t day, next;
+ struct recur_apoint *rapt;
+ struct recur_event *rev;
+ int more = 0;
+
+ if (wins_slctd() != APP) {
+ error_msg =
+ _("Select a repeating item in the appointments panel.");
+ warnbox(error_msg);
+ goto cleanup;
+ }
+ item = ui_day_get_sel();
+ /*
+ * The selected day need not be the (item) start day
+ * for multi-day occurrences.
+ */
+ day = DAY(item->start);
+ if (item->type == RECUR_EVNT) {
+ rev = item->item.rev;
+ more = recur_next_occurrence(rev->day, -1, rev->rpt, &rev->exc,
+ day, &next);
+ } else if (item->type == RECUR_APPT) {
+ rapt = item->item.rapt;
+ more = recur_next_occurrence(rapt->start, rapt->dur, rapt->rpt,
+ &rapt->exc, day, &next);
+ } else {
+ error_msg = _("Not a repeating item.");
+ warnbox(error_msg);
+ goto cleanup;
+ }
+ if (!more) {
+ error_msg = _("Last occurrence.");
+ warnbox(error_msg);
+ goto cleanup;
+ }
+ item->order = next;
+ ui_calendar_set_slctd_day(sec2date(next));
+ day_set_sel_data(item);
+ day_do_storage(1);
+
+ valid = 1;
+ }
+ if (!strcmp(cmd_name, "prev") || !strcmp(cmd_name, "p")) {
+ struct day_item *item;
+ time_t day, prev;
+ struct recur_apoint *rapt;
+ struct recur_event *rev;
+ int more = 0;
+
+ if (wins_slctd() != APP) {
+ error_msg = _("Select a repeating item in the"
+ " appointments panel.");
+ warnbox(error_msg);
+ goto cleanup;
+ }
+ item = ui_day_get_sel();
+ /*
+ * The selected day need not be the (item) start day
+ * for multi-day occurrences.
+ */
+ day = DAY(item->start);
+ if (item->type == RECUR_EVNT) {
+ rev = item->item.rev;
+ more = recur_prev_occurrence(rev->day, -1, rev->rpt,
+ &rev->exc, day, &prev);
+ } else if (item->type == RECUR_APPT) {
+ rapt = item->item.rapt;
+ more = recur_prev_occurrence(rapt->start, rapt->dur,
+ rapt->rpt, &rapt->exc,
+ day, &prev);
+ } else {
+ error_msg = _("Not a repeating item.");
+ warnbox(error_msg);
+ goto cleanup;
+ }
+ if (!more) {
+ error_msg = _("First occurrence.");
+ warnbox(error_msg);
+ goto cleanup;
+ }
+ item->order = prev;
+ ui_calendar_set_slctd_day(sec2date(prev));
+ day_set_sel_data(item);
+ day_do_storage(1);
+
+ valid = 1;
+ }
+
if (!valid) {
asprintf(&error_msg, _("No such command: %s"), cmd);
status_mesg(error_msg, "");
@@ -627,8 +696,6 @@ cleanup:
*/
int main(int argc, char **argv)
{
- int no_data_file = 1;
-
#if ENABLE_NLS
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
@@ -643,7 +710,7 @@ int main(int argc, char **argv)
/* Non-interactive mode. */
exit_calcurse(EXIT_SUCCESS);
} else {
- no_data_file = io_check_data_files();
+ io_check_data_files();
dmon_stop();
io_set_lock();
}
@@ -713,12 +780,8 @@ int main(int argc, char **argv)
* implicitly calling wrefresh() later (causing ncurses race conditions).
*/
wins_wrefresh(win[KEY].p);
- if (show_dialogs()) {
- wins_update(FLAG_ALL);
- io_startup_screen(no_data_file);
- }
ui_calendar_monthly_view_cache_set_invalid();
- do_storage(1);
+ day_do_storage(1);
ui_todo_load_items();
ui_todo_sel_reset();
wins_update(FLAG_ALL);
@@ -738,7 +801,7 @@ int main(int argc, char **argv)
que_show();
if (conf.systemevents) {
que_save();
- do_storage(0);
+ day_do_storage(0);
}
wins_update(FLAG_ALL);
que_rem();
@@ -748,7 +811,7 @@ int main(int argc, char **argv)
resize = 0;
wins_reset();
if (conf.multiple_days) {
- do_storage(0);
+ day_do_storage(0);
wins_update(FLAG_APP);
}
}
@@ -764,6 +827,7 @@ int main(int argc, char **argv)
wtimeout(win[KEY].p, -1);
switch (key) {
HANDLE_KEY(KEY_GENERIC_CHANGE_VIEW, key_generic_change_view);
+ HANDLE_KEY(KEY_GENERIC_PREV_VIEW, key_generic_prev_view);
HANDLE_KEY(KEY_GENERIC_OTHER_CMD, key_generic_other_cmd);
HANDLE_KEY(KEY_GENERIC_GOTO, key_generic_goto);
HANDLE_KEY(KEY_GENERIC_GOTO_TODAY, key_generic_goto_today);
diff --git a/src/calcurse.h b/src/calcurse.h
index e41bc32..8322416 100644
--- a/src/calcurse.h
+++ b/src/calcurse.h
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -111,9 +111,6 @@
#define STATUSHEIGHT 2
#define MAX_NOTESIZ 40
-/* Format for appointment hours is: HH:MM */
-#define HRMIN_SIZE 6
-
/* Maximum number of colors available. */
#define NBUSERCOLORS 6
@@ -142,12 +139,20 @@
*/
#define DAYINSEC (DAYINMIN * MININSEC)
#define NEXTDAY(date) date_sec_change((date), 0, 1)
+#define PREVDAY(date) date_sec_change((date), 0, -1)
#define DAYLEN(date) (NEXTDAY(date) - (date))
#define ENDOFDAY(date) (NEXTDAY(date) - 1)
#define HOURINSEC (HOURINMIN * MININSEC)
+#define DAY(date) (update_time_in_date(date, 0, 0))
/* Calendar window. */
#define CALHEIGHT 8
+/*
+ * Week day numbering (0, 1,..., 6) which depends on the first day of the week.
+ * The argument (d) is the "Sunday"-numbering of member tm_wday in struct tm.
+ */
+#define WDAY(d) \
+ (modify_wday(d, -ui_calendar_get_wday_start()))
/* Key definitions. */
#define CTRLVAL 0x1F
@@ -161,8 +166,11 @@
#define KEYS_LABELEN 8 /* length of command description */
#define KEYS_CMDS_PER_LINE 6 /* max number of commands per line */
-/* Register definitions. */
-#define REG_BLACK_HOLE 37
+/*
+ * Register definitions, see ui_day.c.
+ * Index 0-35 is used for '0'-'9' and 'a'-'z', see keys_get().
+ */
+#define REG_BLACK_HOLE 36
/* Size of the hash table the note garbage collector uses. */
#define NOTE_GC_HSIZE 1024
@@ -282,7 +290,6 @@ struct conf {
unsigned confirm_delete;
enum win default_panel;
unsigned compact_panels;
- unsigned system_dialogs;
unsigned multiple_days;
unsigned header_line;
unsigned event_separator;
@@ -296,9 +303,11 @@ struct conf {
int input_datefmt; /* format for reading date */
enum pos heading_pos; /* left/center/right for heading in appts panel */
char day_heading[BUFSIZ]; /* format for displaying heading in appts panel */
+ char timefmt[BUFSIZ]; /* format for displaying time in appts panel*/
};
#define EMPTY_DAY_DEFAULT "--"
+#define EMPTY_EVENT_DESC_DEFAULT _("(empty description)")
/* Daemon-related configuration. */
struct dmon_conf {
@@ -328,6 +337,9 @@ enum datefmt {
/* Day heading default format. */
#define DAY_HEADING_DEFAULT "%B %e, %Y"
+/* Appointment time default format. */
+#define APPT_TIME_DEFAULT "%H:%M"
+
/*
* Calcurse representation of the date of a day in the calendar.
* When time_t is a 32-bit signed integer, the year range is 1902 - 2037.
@@ -376,40 +388,57 @@ struct excp {
};
enum recur_type {
- RECUR_NO,
RECUR_DAILY,
RECUR_WEEKLY,
RECUR_MONTHLY,
RECUR_YEARLY,
- RECUR_TYPES
+ NBRECUR
};
-/* To describe an item's repetition. */
+/*
+ * Recurrence rule according to RFC5545; used
+ * - in each recurrent appointment/event instance
+ * - in passing parameters as a single function argument
+ */
struct rpt {
- enum recur_type type; /* repetition type */
- int freq; /* repetition frequency */
- time_t until; /* ending date for repeated event */
+ enum recur_type type; /* FREQ */
+ int freq; /* INTERVAL */
+ time_t until; /* UNTIL */
+ llist_t bymonth; /* BYMONTH list */
+ llist_t bywday; /* BY(WEEK)DAY list */
+ llist_t bymonthday; /* BYMONTHDAY list */
+ llist_t exc; /* EXDATE's */
};
+/* Types of integers in rrule lists. */
+typedef enum {
+ BYMONTH,
+ BYDAY_W,
+ BYDAY_M,
+ BYDAY_Y,
+ BYMONTHDAY,
+ NOLL
+} int_list_t;
+
/* Recurrent appointment definition. */
struct recur_apoint {
- struct rpt *rpt; /* information about repetition */
- llist_t exc; /* days when the item should not be repeated */
- time_t start; /* beggining of the appointment */
- long dur; /* duration of the appointment */
- char state; /* 8 bits to store item state */
- char *mesg; /* appointment description */
- char *note; /* note attached to appointment */
+ struct rpt *rpt; /* recurrence rule */
+ llist_t exc; /* recurrence exceptions (NOT rpt->exc) */
+ time_t start; /* start time */
+ long dur; /* duration */
+ char state; /* item state */
+ char *mesg; /* description */
+ char *note; /* attached note */
};
-/* Reccurent event definition. */
+/* Recurrent event definition. */
struct recur_event {
- struct rpt *rpt; /* information about repetition */
- llist_t exc; /* days when the item should not be repeated */
+ struct rpt *rpt; /* recurrence rule */
+ llist_t exc; /* recurrence exceptions (NOT rpt->exc) */
int id; /* event type */
- time_t day; /* day at which event occurs */
- char *mesg; /* event description */
- char *note; /* note attached to event */
+ time_t day; /* day of the event */
+ char *mesg; /* description */
+ char *note; /* attached note */
};
/* Generic pointer data type for appointments and events. */
@@ -485,11 +514,11 @@ struct notify_app {
struct io_file {
FILE *fd;
- char name[BUFSIZ];
+ char *name;
};
-/* Available keys. */
-enum key {
+/* Virtual keys. */
+enum vkey {
KEY_GENERIC_CANCEL,
KEY_GENERIC_SELECT,
KEY_GENERIC_CREDITS,
@@ -500,6 +529,7 @@ enum key {
KEY_GENERIC_COPY,
KEY_GENERIC_PASTE,
KEY_GENERIC_CHANGE_VIEW,
+ KEY_GENERIC_PREV_VIEW,
KEY_GENERIC_IMPORT,
KEY_GENERIC_EXPORT,
KEY_GENERIC_GOTO,
@@ -539,7 +569,7 @@ enum key {
KEY_RAISE_PRIORITY,
KEY_LOWER_PRIORITY,
- NBKEYS,
+ NBVKEYS,
KEY_UNDEF,
/* Non-configurable, context sensitive key bindings. */
@@ -644,7 +674,6 @@ struct nbar {
char datefmt[BUFSIZ]; /* format for displaying date */
char timefmt[BUFSIZ]; /* format for displaying time */
char cmd[BUFSIZ]; /* notification command */
- const char *shell; /* user shell to launch notif. cmd */
unsigned notify_all; /* notify all appointments */
pthread_mutex_t mutex;
};
@@ -759,7 +788,7 @@ void apoint_sec2str(struct apoint *, time_t, char *, char *);
char *apoint_tostr(struct apoint *);
char *apoint_hash(struct apoint *);
void apoint_write(struct apoint *, FILE *);
-struct apoint *apoint_scan(FILE *, struct tm, struct tm, char, char *,
+char *apoint_scan(FILE *, struct tm, struct tm, char, char *,
struct item_filter *);
void apoint_delete(struct apoint *);
struct notify_app *apoint_check_next(struct notify_app *, time_t);
@@ -783,7 +812,7 @@ void ui_calendar_set_current_date(void);
struct date *ui_calendar_get_today(void);
void ui_calendar_set_first_day_of_week(enum wday);
void ui_calendar_change_first_day_of_week(void);
-unsigned ui_calendar_week_begins_on_monday(void);
+int ui_calendar_get_wday_start(void);
void ui_calendar_store_current_date(struct date *);
void ui_calendar_init_slctd_day(void);
struct date *ui_calendar_get_slctd_day(void);
@@ -829,6 +858,7 @@ void day_display_item_date(struct day_item *, WINDOW *, int, time_t, int, int);
void day_display_item(struct day_item *, WINDOW *, int, int, int, int);
void day_write_stdout(time_t, const char *, const char *, const char *,
const char *, int *);
+void day_do_storage(int day_changed);
void day_popup_item(struct day_item *);
int day_check_if_item(struct date);
unsigned day_chk_busy_slices(struct date, int, int *);
@@ -857,7 +887,7 @@ unsigned event_inday(struct event *, time_t *);
char *event_tostr(struct event *);
char *event_hash(struct event *);
void event_write(struct event *, FILE *);
-struct event *event_scan(FILE *, struct tm, int, char *, struct item_filter *);
+char *event_scan(FILE *, struct tm, int, char *, struct item_filter *);
void event_delete(struct event *);
void event_paste_item(struct event *, time_t);
int event_dummy(struct day_item *);
@@ -873,9 +903,9 @@ int display_help(const char *);
int run_hook(const char *);
/* ical.c */
-void ical_import_data(FILE *, FILE *, unsigned *, unsigned *, unsigned *,
- unsigned *, unsigned *, const char *, const char *,
- const char *, const char *, const char *);
+void ical_import_data(const char *, FILE *, FILE *, unsigned *, unsigned *,
+ unsigned *, unsigned *, unsigned *, const char *,
+ const char *, const char *, const char *, const char *);
void ical_export_data(FILE *, int);
/* io.c */
@@ -898,9 +928,8 @@ unsigned io_dir_exists(const char *);
unsigned io_file_exists(const char *);
int io_check_file(const char *);
int io_check_data_files(void);
-void io_startup_screen(int);
void io_export_data(enum export_type, int);
-void io_import_data(enum import_type, const char *, const char *, const char *,
+int io_import_data(enum import_type, char *, const char *, const char *,
const char *, const char *, const char *);
struct io_file *io_log_init(void);
void io_log_print(struct io_file *, int, const char *);
@@ -912,7 +941,6 @@ void io_set_lock(void);
unsigned io_dump_pid(char *);
unsigned io_get_pid(char *);
int io_files_equal(const char *, const char *);
-int io_file_is_empty(char *);
int io_file_cp(const char *, const char *);
void io_unset_modified(void);
void io_set_modified(void);
@@ -922,24 +950,26 @@ int io_get_modified(void);
void keys_init(void);
void keys_free(void);
void keys_dump_defaults(char *);
-const char *keys_get_label(enum key);
-enum key keys_get_action(int);
+const char *keys_get_label(enum vkey);
+const char *keys_get_binding(enum vkey);
+enum vkey keys_get_action(int);
int keys_wgetch(WINDOW *);
void keys_wait_for_any_key(WINDOW *);
-enum key keys_get(WINDOW *, int *, int *);
-int keys_assign_binding(int, enum key);
-void keys_remove_binding(int, enum key);
+enum vkey keys_get(WINDOW * win, int *, int *);
+int keys_assign_binding(int, enum vkey);
+void keys_remove_binding(int, enum vkey);
int keys_str2int(const char *);
char *keys_int2str(int);
-int keys_action_count_keys(enum key);
-const char *keys_action_firstkey(enum key);
-const char *keys_action_nkey(enum key, int);
-char *keys_action_allkeys(enum key);
+int keys_action_count_keys(enum vkey);
+const char *keys_action_firstkey(enum vkey);
+const char *keys_action_nkey(enum vkey, int);
+char *keys_action_allkeys(enum vkey);
void keys_display_bindings_bar(WINDOW *, int *, int, int, int);
-void keys_popup_info(enum key);
+void keys_popup_info(enum vkey);
void keys_save_bindings(FILE *);
-int keys_check_missing_bindings(void);
-void keys_fill_missing(void);
+int keys_check_missing(void);
+int keys_check_undefined(void);
+int keys_fill_missing(void);
/* listbox.c */
void listbox_init(struct listbox *, int, int, int, int, const char *,
@@ -995,6 +1025,7 @@ void edit_note(char **, const char *);
void view_note(const char *, const char *);
void erase_note(char **);
void note_read(char *, FILE *);
+void note_read_contents(char *, size_t, FILE *);
void note_gc(void);
/* notify.c */
@@ -1026,7 +1057,11 @@ void pcal_export_data(FILE *);
/* recur.c */
extern llist_ts_t recur_alist_p;
extern llist_t recur_elist;
-int recur_update_exc(llist_t *, char *);
+void recur_free_int_list(llist_t *);
+void recur_int_list_dup(llist_t *, llist_t *);
+void recur_free_exc_list(llist_t *);
+void recur_exc_dup(llist_t *, llist_t *);
+int recur_str2exc(llist_t *, char *);
char *recur_exc2str(llist_t *);
struct recur_event *recur_event_dup(struct recur_event *);
struct recur_apoint *recur_apoint_dup(struct recur_apoint *);
@@ -1039,17 +1074,16 @@ void recur_event_llist_init(void);
void recur_apoint_llist_free(void);
void recur_event_llist_free(void);
struct recur_apoint *recur_apoint_new(char *, char *, time_t, long, char,
- int, int, time_t, llist_t *);
-struct recur_event *recur_event_new(char *, char *, time_t, int, int, int,
- time_t, llist_t *);
+ struct rpt *);
+struct recur_event *recur_event_new(char *, char *, time_t, int,
+ struct rpt *);
char recur_def2char(enum recur_type);
int recur_char2def(char);
-struct recur_apoint *recur_apoint_scan(FILE *, struct tm, struct tm,
- char, int, struct tm, char *,
- llist_t *, char, struct item_filter *);
-struct recur_event *recur_event_scan(FILE *, struct tm, int, char,
- int, struct tm, char *, llist_t *,
- struct item_filter *);
+char *recur_apoint_scan(FILE *, struct tm, struct tm, char,
+ char *, struct item_filter *,
+ struct rpt *);
+char *recur_event_scan(FILE *, struct tm, int, char *,
+ struct item_filter *, struct rpt *);
char *recur_apoint_tostr(struct recur_apoint *);
char *recur_apoint_hash(struct recur_apoint *);
void recur_apoint_write(struct recur_apoint *, FILE *);
@@ -1057,22 +1091,29 @@ char *recur_event_tostr(struct recur_event *);
char *recur_event_hash(struct recur_event *);
void recur_event_write(struct recur_event *, FILE *);
void recur_save_data(FILE *);
-unsigned recur_item_find_occurrence(time_t, long, llist_t *, int,
- int, time_t, time_t, time_t *);
+unsigned recur_item_find_occurrence(time_t, long, struct rpt *, llist_t *,
+ time_t, time_t *);
unsigned recur_apoint_find_occurrence(struct recur_apoint *, time_t, time_t *);
unsigned recur_event_find_occurrence(struct recur_event *, time_t, time_t *);
-unsigned recur_item_inday(time_t, long, llist_t *, int, int, time_t, time_t);
+unsigned recur_item_inday(time_t, long, struct rpt *, llist_t *, time_t);
unsigned recur_apoint_inday(struct recur_apoint *, time_t *);
unsigned recur_event_inday(struct recur_event *, time_t *);
void recur_event_add_exc(struct recur_event *, time_t);
void recur_apoint_add_exc(struct recur_apoint *, time_t);
void recur_event_erase(struct recur_event *);
void recur_apoint_erase(struct recur_apoint *);
+void recur_bymonth(llist_t *, FILE *);
+void recur_bywday(enum recur_type, llist_t *, FILE *);
+void recur_bymonthday(llist_t *, FILE *);
void recur_exc_scan(llist_t *, FILE *);
void recur_apoint_check_next(struct notify_app *, time_t, time_t);
void recur_apoint_switch_notify(struct recur_apoint *);
void recur_event_paste_item(struct recur_event *, time_t);
void recur_apoint_paste_item(struct recur_apoint *, time_t);
+int recur_next_occurrence(time_t, long, struct rpt *, llist_t *, time_t, time_t *);
+int recur_nth_occurrence(time_t, long, struct rpt *, llist_t *, int, time_t *);
+int recur_prev_occurrence(time_t, long, struct rpt *, llist_t *, time_t, time_t *);
+
/* sigs.c */
void sigs_init(void);
@@ -1115,6 +1156,7 @@ void ui_day_item_delete(unsigned);
void ui_day_item_edit(void);
void ui_day_item_pipe(void);
void ui_day_item_repeat(void);
+void ui_day_item_cut(unsigned);
void ui_day_item_cut_free(unsigned);
void ui_day_item_copy(unsigned);
void ui_day_item_paste(unsigned);
@@ -1184,7 +1226,7 @@ int get_item_min(time_t);
struct tm date2tm(struct date, unsigned, unsigned);
time_t date2sec(struct date, unsigned, unsigned);
struct date sec2date(time_t);
-time_t utcdate2sec(struct date, unsigned, unsigned);
+time_t tzdate2sec(struct date, unsigned, unsigned, char *);
int date_cmp(struct date *, struct date *);
int date_cmp_day(time_t, time_t);
char *date_sec2date_str(time_t, const char *);
@@ -1194,6 +1236,8 @@ time_t date_sec_change(time_t, int, int);
time_t update_time_in_date(time_t, unsigned, unsigned);
time_t get_sec_date(struct date);
long min2sec(unsigned);
+int modify_wday(int,int);
+char *get_wday_default_string(int);
void draw_scrollbar(struct scrollwin *, int);
void item_in_popup(const char *, const char *, const char *, const char *);
time_t get_today(void);
@@ -1210,13 +1254,13 @@ int check_sec(time_t *);
int check_time(unsigned, unsigned);
int parse_time(const char *, unsigned *, unsigned *);
int parse_duration(const char *, unsigned *, time_t);
-int parse_date_duration(const char *, unsigned *, time_t);
+int parse_date_increment(const char *, unsigned *, time_t);
int parse_datetime(const char *, time_t *, time_t);
void file_close(FILE *, const char *);
void psleep(unsigned);
-int fork_exec(int *, int *, const char *, const char *const *);
-int shell_exec(int *, int *, const char *, const char *const *);
-int child_wait(int *, int *, int);
+int fork_exec(int *, int *, int *, int, const char *, const char *const *);
+int shell_exec(int *, int *, int *, int, const char *, const char *const *);
+int child_wait(int *, int *, int *, int);
void press_any_key(void);
void print_apoint(const char *, time_t, struct apoint *);
void print_event(const char *, time_t, struct event *);
@@ -1228,9 +1272,12 @@ int asprintf(char **, const char *, ...);
int starts_with(const char *, const char *);
int starts_with_ci(const char *, const char *);
int hash_matches(const char *, const char *);
-int show_dialogs(void);
long overflow_add(long, long, long *);
long overflow_mul(long, long, long *);
+time_t next_wday(time_t, int);
+int wday_per_year(int, int);
+int wday_per_month(int, int, int);
+char *day_ins(char **, time_t);
/* vars.c */
extern int col, row;
@@ -1286,6 +1333,7 @@ void wins_sbar_wdec(void);
enum win wins_slctd(void);
void wins_slctd_set(enum win);
void wins_slctd_next(void);
+void wins_slctd_prev(void);
void wins_init(void);
void wins_scrollwin_init(struct scrollwin *, int, int, int, int, const char *);
void wins_scrollwin_resize(struct scrollwin *, int, int, int, int);
diff --git a/src/config.c b/src/config.c
index c6914f5..4e0f7db 100644
--- a/src/config.c
+++ b/src/config.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,6 +36,8 @@
#include <ctype.h>
#include <unistd.h>
+#include <string.h>
+#include <strings.h>
#include "calcurse.h"
@@ -109,6 +111,7 @@ static const struct confvar confmap[] = {
{"format.inputdate", config_parse_input_datefmt, config_serialize_input_datefmt, NULL},
{"format.notifydate", CONFIG_HANDLER_STR(nbar.datefmt)},
{"format.notifytime", CONFIG_HANDLER_STR(nbar.timefmt)},
+ {"format.appointmenttime", CONFIG_HANDLER_STR(conf.timefmt)},
{"format.outputdate", config_parse_output_datefmt, config_serialize_output_datefmt, NULL},
{"format.dayheading", CONFIG_HANDLER_STR(conf.day_heading)},
{"general.autogc", CONFIG_HANDLER_BOOL(conf.auto_gc)},
@@ -119,7 +122,6 @@ static const struct confvar confmap[] = {
{"general.multipledays", CONFIG_HANDLER_BOOL(conf.multiple_days)},
{"general.periodicsave", CONFIG_HANDLER_UNSIGNED(conf.periodic_save)},
{"general.systemevents", CONFIG_HANDLER_BOOL(conf.systemevents)},
- {"general.systemdialogs", CONFIG_HANDLER_BOOL(conf.system_dialogs)},
{"notification.command", CONFIG_HANDLER_STR(nbar.cmd)},
{"notification.notifyall", config_parse_notifyall, config_serialize_notifyall, NULL},
{"notification.warning", CONFIG_HANDLER_INT(nbar.cntdwn)}
@@ -261,14 +263,16 @@ static int config_parse_default_panel(void *dummy, const char *val)
static int config_parse_first_day_of_week(void *dummy, const char *val)
{
- if (!strcmp(val, "monday"))
- ui_calendar_set_first_day_of_week(MONDAY);
- else if (!strcmp(val, "sunday"))
- ui_calendar_set_first_day_of_week(SUNDAY);
- else
- return 0;
+ int i;
- return 1;
+ for (i = 0; i < WEEKINDAYS; i++) {
+ if(!strcasecmp(val, get_wday_default_string(i))) {
+ ui_calendar_set_first_day_of_week(i);
+ return 1;
+ }
+ }
+
+ return 0;
}
static int config_parse_color_theme(void *dummy, const char *val)
@@ -468,10 +472,9 @@ static int config_serialize_default_panel(char **buf, void *dummy)
static int config_serialize_first_day_of_week(char **buf, void *dummy)
{
- if (ui_calendar_week_begins_on_monday())
- *buf = mem_strdup("monday");
- else
- *buf = mem_strdup("sunday");
+ *buf = mem_strdup(get_wday_default_string(ui_calendar_get_wday_start()));
+ /* now stores string with uppercase first letter, changing to lower */
+ **buf = tolower(**buf);
return 1;
}
@@ -615,7 +618,8 @@ config_file_walk(config_fn_walk_cb_t fn_cb,
* Backwards compatibility for removed configuration options:
* ignored on load, omitted on save.
*/
- if (strcmp(key, "general.progressbar") == 0)
+ if (strcmp(key, "general.progressbar") == 0 ||
+ strcmp(key, "general.systemdialogs") == 0)
continue;
if (value && (*value == '\0' || *value == '\n')) {
diff --git a/src/custom.c b/src/custom.c
index dafb801..2cd385c 100644
--- a/src/custom.c
+++ b/src/custom.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -38,6 +38,7 @@
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
+#include <langinfo.h>
#include "calcurse.h"
@@ -540,12 +541,12 @@ enum {
SYSTEM_EVENTS,
CONFIRM_QUIT,
CONFIRM_DELETE,
- SYSTEM_DIAGS,
FIRST_DAY_OF_WEEK,
OUTPUT_DATE_FMT,
INPUT_DATE_FMT,
HEADING_POS,
DAY_HEADING_FMT,
+ APPOINTMENT_TIME_FMT,
NB_OPTIONS
};
@@ -570,12 +571,12 @@ static void print_general_option(int i, WINDOW *win, int y, int hilt, void *cb_d
"general.systemevents = ",
"general.confirmquit = ",
"general.confirmdelete = ",
- "general.systemdialogs = ",
"general.firstdayofweek = ",
"format.outputdate = ",
"format.inputdate = ",
"appearance.headingposition = ",
- "format.dayheading = "
+ "format.dayheading = ",
+ "format.appointmenttime = "
};
const char *panel;
const char *position;
@@ -699,18 +700,10 @@ static void print_general_option(int i, WINDOW *win, int y, int hilt, void *cb_d
_("(if set to YES, confirmation is required "
"before deleting an event)"));
break;
- case SYSTEM_DIAGS:
- print_bool_option_incolor(win, conf.system_dialogs, y,
- XPOS + strlen(opt[SYSTEM_DIAGS]));
- mvwaddstr(win, y + 1, XPOS,
- _("(if set to YES, messages about loaded "
- "and saved data will be displayed)"));
- break;
case FIRST_DAY_OF_WEEK:
custom_apply_attr(win, ATTR_HIGHEST);
mvwaddstr(win, y, XPOS + strlen(opt[FIRST_DAY_OF_WEEK]),
- ui_calendar_week_begins_on_monday()? _("Monday") :
- _("Sunday"));
+ nl_langinfo(DAY_1 + ui_calendar_get_wday_start()));
custom_remove_attr(win, ATTR_HIGHEST);
mvwaddstr(win, y + 1, XPOS,
_("(specifies the first day of week in the calendar view)"));
@@ -755,6 +748,14 @@ static void print_general_option(int i, WINDOW *win, int y, int hilt, void *cb_d
mvwaddstr(win, y + 1, XPOS,
_("(Format of the date displayed in the appointments panel)"));
break;
+ case APPOINTMENT_TIME_FMT:
+ custom_apply_attr(win, ATTR_HIGHEST);
+ mvwaddstr(win, y, XPOS + strlen(opt[APPOINTMENT_TIME_FMT]),
+ conf.timefmt);
+ custom_remove_attr(win, ATTR_HIGHEST);
+ mvwaddstr(win, y + 1, XPOS,
+ _("(Format of the time displayed in the appointments panel)"));
+ break;
}
if (hilt)
@@ -780,6 +781,8 @@ static void general_option_edit(int i)
_("Enter a text string (an empty string for the default text)");
const char *output_datefmt_str =
_("Enter the date format (see 'man 3 strftime' for possible formats) ");
+ const char *output_timefmt_str =
+ _("Enter the time format (see 'man 3 strftime' for possible formats) ");
const char *input_datefmt_prefix = _("Enter the date format: ");
const char *periodic_save_str =
_("Enter the delay, in minutes, between automatic saves (0 to disable) ");
@@ -873,9 +876,6 @@ static void general_option_edit(int i)
case CONFIRM_DELETE:
conf.confirm_delete = !conf.confirm_delete;
break;
- case SYSTEM_DIAGS:
- conf.system_dialogs = !conf.system_dialogs;
- break;
case FIRST_DAY_OF_WEEK:
ui_calendar_change_first_day_of_week();
ui_calendar_monthly_view_cache_set_invalid();
@@ -905,6 +905,15 @@ static void general_option_edit(int i)
conf.day_heading[BUFSIZ - 1] = '\0';
}
break;
+ case APPOINTMENT_TIME_FMT:
+ status_mesg(output_timefmt_str, "");
+ strncpy(buf, conf.timefmt, BUFSIZ);
+ buf[BUFSIZ - 1] = '\0';
+ if (updatestring(win[STA].p, &buf, 0, 1) == 0) {
+ strncpy(conf.timefmt, buf, BUFSIZ);
+ conf.timefmt[BUFSIZ - 1] = '\0';
+ }
+ break;
}
mem_free(buf);
@@ -987,10 +996,11 @@ print_keys_bindings(WINDOW * win, int selected_row, int selected_elm,
const int XPOS = 1;
const int EQUALPOS = 23;
const int KEYPOS = 25;
- int noelm, action, y;
+ int noelm, action, y, pos;
+ const char *key = NULL;
noelm = y = 0;
- for (action = 0; action < NBKEYS; action++) {
+ for (action = 0; action < NBVKEYS; action++) {
char *actionstr;
int nbkeys;
@@ -1002,18 +1012,15 @@ print_keys_bindings(WINDOW * win, int selected_row, int selected_elm,
mem_free(actionstr);
mvwaddstr(win, y, EQUALPOS, "=");
if (nbkeys == 0)
- mvwaddstr(win, y, KEYPOS, _("undefined"));
+ mvwaddstr(win, y, KEYPOS, _("UNDEFINED"));
if (action == selected_row)
custom_remove_attr(win, ATTR_HIGHEST);
if (nbkeys > 0) {
if (action == selected_row) {
- const char *key;
- int pos;
-
+ /* Elements may have been added or deleted. */
+ wclrtoeol(win);
pos = KEYPOS;
- while ((key =
- keys_action_nkey(action,
- noelm)) != NULL) {
+ while ((key = keys_action_nkey(action, noelm))) {
if (noelm == selected_elm)
print_key_incolor(win, key,
y, pos);
@@ -1024,8 +1031,9 @@ print_keys_bindings(WINDOW * win, int selected_row, int selected_elm,
pos += utf8_strwidth((char *)key) + 1;
}
} else {
- mvwaddstr(win, y, KEYPOS,
- keys_action_allkeys(action));
+ key = keys_action_allkeys(action);
+ mvwaddstr(win, y, KEYPOS, key);
+ mem_free((char *)key);
}
}
y += yoff;
@@ -1057,9 +1065,11 @@ void custom_keys_config(void)
const int LABELLINES = 3;
clear();
- nbdisplayed = ((notify_bar() ? row - 3 : row - 2) - LABELLINES) / LINESPERKEY;
- wins_scrollwin_init(&kwin, 0, 0, notify_bar() ? row - 3 : row - 2, col, _("keys configuration"));
- wins_scrollwin_set_pad(&kwin, NBKEYS * LINESPERKEY);
+ nbdisplayed = ((notify_bar() ? row - 3 : row - 2) -
+ LABELLINES) / LINESPERKEY;
+ wins_scrollwin_init(&kwin, 0, 0, notify_bar() ? row - 3 : row - 2, col,
+ _("keys configuration"));
+ wins_scrollwin_set_pad(&kwin, NBVKEYS * LINESPERKEY);
wins_scrollwin_draw_deco(&kwin, 0);
custom_keys_config_bar();
selrow = selelm = 0;
@@ -1084,7 +1094,7 @@ void custom_keys_config(void)
}
break;
case KEY_MOVE_DOWN:
- if (selrow < NBKEYS - 1) {
+ if (selrow < NBVKEYS - 1) {
selrow++;
selelm = 0;
if (selrow == lastrow) {
@@ -1115,7 +1125,7 @@ void custom_keys_config(void)
keys_get_label(selrow), 0);
for (;;) {
ch = keys_wgetch(grabwin);
- enum key action = keys_get_action(ch);
+ enum vkey action = keys_get_action(ch);
/* Is the key already used by this action? */
if (action == selrow)
break;
@@ -1154,10 +1164,8 @@ void custom_keys_config(void)
selelm--;
break;
case KEY_GENERIC_QUIT:
- if (keys_check_missing_bindings() != 0) {
- WARN_MSG(_("Some actions do not have any associated "
- "key bindings!"));
- }
+ if (keys_check_undefined())
+ WARN_MSG(_("Some actions are left undefined!"));
wins_scrollwin_delete(&kwin);
return;
}
@@ -1213,7 +1221,10 @@ void custom_config_main(void)
wmove(win[STA].p, 0, 0);
wins_doupdate();
- while ((ch = keys_wgetch(win[KEY].p)) != 'q') {
+ while (1) {
+ ch = keys_wgetch(win[KEY].p);
+ if (keys_get_action(ch) == KEY_GENERIC_QUIT)
+ break;
switch (ch) {
case 'C':
case 'c':
@@ -1231,7 +1242,7 @@ void custom_config_main(void)
old_layout = wins_layout();
custom_layout_config();
if (wins_layout() != old_layout)
- wins_reset();
+ wins_resize();
break;
case 'G':
case 'g':
@@ -1257,7 +1268,11 @@ void custom_config_main(void)
resize = 0;
wins_reset();
}
-
+
+ /* needed to update app list */
+ day_do_storage(0);
+
+ /* wins_update(FLAG_ALL), but with custom bindings */
wins_set_bindings(bindings, ARRAY_SIZE(bindings));
wins_update_border(FLAG_ALL);
wins_update_panels(FLAG_ALL);
diff --git a/src/day.c b/src/day.c
index a8ee736..78f4acf 100644
--- a/src/day.c
+++ b/src/day.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -58,7 +58,7 @@ static struct day_item sel_data = { 0, 0, 0, {NULL}};
/*
* Save the item to become the selected APP item.
- * Public function used to override the setting in do_storage().
+ * Public function used to override the setting in day_do_storage().
*/
int day_set_sel_data(struct day_item *d)
{
@@ -100,7 +100,7 @@ int day_sel_index(void)
/* If still not found, stay on the same day. */
VECTOR_FOREACH(&day_items, i) {
p = VECTOR_NTH(&day_items, i);
- if (p->order == update_time_in_date(sel_data.order, 0, 0))
+ if (p->order == DAY(sel_data.order))
return i;
}
return -1;
@@ -198,7 +198,8 @@ static void day_add_item(int type, time_t start, time_t order, union aptev_ptr i
/* Get the message of an item. */
char *day_item_get_mesg(struct day_item *day)
{
- switch (day->type) {
+ switch (day->type)
+ {
case APPT:
return day->item.apt->mesg;
case EVNT:
@@ -212,6 +213,15 @@ char *day_item_get_mesg(struct day_item *day)
}
}
+/* Get the display message of an item. */
+char *day_item_get_display_mesg(struct day_item *day)
+{
+ char *msg = day_item_get_mesg(day);
+ if (msg[0] == '\0')
+ return EMPTY_EVENT_DESC_DEFAULT;
+ return msg;
+}
+
/* Get the note attached to an item. */
char *day_item_get_note(struct day_item *day)
{
@@ -360,7 +370,7 @@ static int day_store_recur_events(time_t date)
p.rev = rev;
time_t occurrence;
if (recur_event_find_occurrence(rev, date, &occurrence)) {
- day_add_item(RECUR_EVNT, rev->day, occurrence, p);
+ day_add_item(RECUR_EVNT, occurrence, occurrence, p);
e_nb++;
}
}
@@ -529,7 +539,7 @@ day_display_item(struct day_item *day, WINDOW *win, int incolor, int width,
if (width <= 0)
return;
- char *mesg = day_item_get_mesg(day);
+ char *mesg = day_item_get_display_mesg(day);
ch_recur = (day->type == RECUR_EVNT) ? '*' : ' ';
ch_note = day_item_get_note(day) ? '>' : ' ';
@@ -578,12 +588,66 @@ void day_write_stdout(time_t date, const char *fmt_apt, const char *fmt_rapt,
}
}
+/*
+ * Store events and appointments for a range of days in the day vector -
+ * beginning with the selected day - and load them into the APP listbox. If no
+ * day-change occurs, reset the selected APP item and with it the selected day,
+ * thereby storing and loading the same range of days.
+ */
+void day_do_storage(int day_changed)
+{
+ int pre_sel;
+ /*
+ * Save the selected item before rebuilding the day vector -
+ * unless a preselection is already set.
+ */
+ if(!(pre_sel = day_check_sel_data()))
+ day_set_sel_data(ui_day_get_sel());
+
+ if (!day_changed)
+ ui_day_sel_reset();
+
+ /* The day_items vector. */
+ day_store_items(get_slctd_day(), 1, day_get_days());
+ /* The APP listbox. */
+ ui_day_load_items();
+
+ if (day_changed && !pre_sel)
+ ui_day_sel_reset();
+ else
+ ui_day_find_sel();
+
+ day_set_sel_data(&empty_day);
+}
+
/* Display an item inside a popup window. */
void day_popup_item(struct day_item *day)
{
+ const char *note_heading = _("Note:");
+ size_t note_size = 3500;
+
if (day->type == EVNT || day->type == RECUR_EVNT) {
- item_in_popup(NULL, NULL, day_item_get_mesg(day),
- _("Event:"));
+ if (day_item_get_note(day)) {
+ char note[note_size];
+ char *notepath, *msg;
+ FILE *fp;
+
+ asprintf(&notepath, "%s%s", path_notes, day_item_get_note(day));
+ fp = fopen(notepath, "r");
+ if (fp == NULL) {
+ item_in_popup(NULL, NULL, day_item_get_mesg(day), _("Event:"));
+ return;
+ }
+ note_read_contents(note, note_size, fp);
+ fclose(fp);
+ mem_free(notepath);
+
+ asprintf(&msg, "%s\n\n%s\n%s", day_item_get_display_mesg(day), note_heading, note);
+ item_in_popup(NULL, NULL, msg, _("Event:"));
+ mem_free(msg);
+ } else {
+ item_in_popup(NULL, NULL, day_item_get_display_mesg(day), _("Event:"));
+ }
} else if (day->type == APPT || day->type == RECUR_APPT) {
char a_st[100], a_end[100];
@@ -593,8 +657,28 @@ void day_popup_item(struct day_item *day)
apt_tmp.start = day->start;
apt_tmp.dur = day_item_get_duration(day);
apoint_sec2str(&apt_tmp, ui_day_sel_date(), a_st, a_end);
- item_in_popup(a_st, a_end, day_item_get_mesg(day),
- _("Appointment:"));
+
+ if (day_item_get_note(day)) {
+ char note[note_size];
+ char *notepath, *msg;
+ FILE *fp;
+
+ asprintf(&notepath, "%s%s", path_notes, day_item_get_note(day));
+ fp = fopen(notepath, "r");
+ if (fp == NULL) {
+ item_in_popup(a_st, a_end, day_item_get_mesg(day), _("Appointment:"));
+ return;
+ }
+ note_read_contents(note, note_size, fp);
+ fclose(fp);
+ mem_free(notepath);
+
+ asprintf(&msg, "%s\n\n%s\n%s", day_item_get_display_mesg(day), note_heading, note);
+ item_in_popup(a_st, a_end, msg, _("Appointment:"));
+ mem_free(msg);
+ } else {
+ item_in_popup(a_st, a_end, day_item_get_display_mesg(day), _("Appointment:"));
+ }
} else {
EXIT(_("unknown item type"));
/* NOTREACHED */
@@ -798,7 +882,7 @@ int day_paste_item(struct day_item *p, time_t date)
/* wanted: until = shift + old_until */
if (p->item.rapt->rpt->until &&
overflow_add(
- date - update_time_in_date(p->item.rapt->start, 0, 0),
+ date - DAY(p->item.rapt->start),
p->item.rapt->rpt->until,
&until)
)
diff --git a/src/dmon.c b/src/dmon.c
index 0772394..cb51de7 100644
--- a/src/dmon.c
+++ b/src/dmon.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,7 +34,7 @@
*
*/
-#include <sys/types.h>
+#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>
#include <paths.h>
@@ -54,7 +54,7 @@
#define DMON_ABRT(...) do { \
DMON_LOG (__VA_ARGS__); \
- if (kill (getpid (), SIGINT) < 0) \
+ if (kill (getpid (), SIGINT) == -1) \
{ \
DMON_LOG (_("Could not stop daemon properly: %s\n"), \
strerror (errno)); \
@@ -143,8 +143,7 @@ static unsigned daemonize(int status)
|| !sigs_set_hdlr(SIGTERM, dmon_sigs_hdlr)
|| !sigs_set_hdlr(SIGALRM, dmon_sigs_hdlr)
|| !sigs_set_hdlr(SIGQUIT, dmon_sigs_hdlr)
- || !sigs_set_hdlr(SIGUSR1, dmon_sigs_hdlr)
- || !sigs_set_hdlr(SIGCHLD, SIG_IGN))
+ || !sigs_set_hdlr(SIGUSR1, dmon_sigs_hdlr))
return 0;
return 1;
@@ -203,6 +202,9 @@ void dmon_start(int parent_exit_status)
DMON_SLEEP_TIME);
psleep(DMON_SLEEP_TIME);
DMON_LOG(_("awakened at %s\n"), nowstr());
+ /* Reap the user-defined notifications. */
+ while (waitpid(0, NULL, WNOHANG) > 0)
+ ;
}
}
diff --git a/src/event.c b/src/event.c
index c16ca4e..7c371e4 100644
--- a/src/event.c
+++ b/src/event.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -149,7 +149,7 @@ void event_write(struct event *o, FILE * f)
}
/* Load the events from file */
-struct event *event_scan(FILE * f, struct tm start, int id, char *note,
+char *event_scan(FILE * f, struct tm start, int id, char *note,
struct item_filter *filter)
{
char buf[BUFSIZ], *nl;
@@ -157,13 +157,13 @@ struct event *event_scan(FILE * f, struct tm start, int id, char *note,
struct event *ev = NULL;
int cond;
- EXIT_IF(!check_date(start.tm_year, start.tm_mon, start.tm_mday) ||
- !check_time(start.tm_hour, start.tm_min),
- _("date error in event"));
+ if (!check_date(start.tm_year, start.tm_mon, start.tm_mday) ||
+ !check_time(start.tm_hour, start.tm_min))
+ return _("illegal date in event");
/* Read the event description */
if (!fgets(buf, sizeof buf, f))
- return NULL;
+ return _("error in appointment description");
nl = strchr(buf, '\n');
if (nl) {
@@ -177,8 +177,9 @@ struct event *event_scan(FILE * f, struct tm start, int id, char *note,
start.tm_mon--;
tstart = mktime(&start);
- EXIT_IF(tstart == -1, _("date error in the event\n"));
- tend = tstart + DAYINSEC - 1;
+ if (tstart == -1)
+ return _("date error in event\n");
+ tend = ENDOFDAY(tstart);
/* Filter item. */
if (filter) {
@@ -205,8 +206,7 @@ struct event *event_scan(FILE * f, struct tm start, int id, char *note,
}
if (!ev)
ev = event_new(buf, note, tstart, id);
-
- return ev;
+ return NULL;
}
/* Delete an event from the list. */
diff --git a/src/getstring.c b/src/getstring.c
index 526e9ba..8ea5df5 100644
--- a/src/getstring.c
+++ b/src/getstring.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -241,9 +241,11 @@ enum getstr getstring(WINDOW * win, char *str, int l, int x, int y)
st.len = st.pos;
break;
case CTRL('A'): /* go to beginning of string */
+ case KEY_HOME:
st.pos = 0;
break;
case CTRL('E'): /* go to end of string */
+ case KEY_END:
st.pos = st.len;
break;
case KEY_LEFT: /* move one char backward */
diff --git a/src/help.c b/src/help.c
index 1d6c366..3f2c94f 100644
--- a/src/help.c
+++ b/src/help.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -105,7 +105,7 @@ int display_help(const char *topic)
if (!io_file_exists(path)) {
int ch = keys_str2int(topic);
- enum key action = keys_get_action(ch);
+ enum vkey action = keys_get_action(ch);
if (ch > 0 && action > 0 && action != KEY_UNDEF) {
topic = keys_get_label(action);
mem_free(path);
@@ -134,6 +134,8 @@ int display_help(const char *topic)
topic = "copy-paste";
else if (!strcmp(topic, "generic-change-view"))
topic = "tab";
+ else if (!strcmp(topic, "generic-prev-view"))
+ topic = "tab";
else if (!strcmp(topic, "generic-import"))
topic = "import";
else if (!strcmp(topic, "generic-export"))
diff --git a/src/hooks.c b/src/hooks.c
index b34313c..f649076 100644
--- a/src/hooks.c
+++ b/src/hooks.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,35 +35,38 @@
*/
#include <stddef.h>
+#include <sys/wait.h>
#include "calcurse.h"
int run_hook(const char *name)
{
- char *hook_path = NULL;
+ char *hook_path = NULL, *mesg;
+ int pid, pin, pout, perr, ret = -127;
char const *arg[2];
- int pid, ret = -127;
- int prepare_wins = (ui_mode == UI_CURSES);
asprintf(&hook_path, "%s/%s", path_hooks, name);
- arg[0] = hook_path;
- arg[1] = NULL;
-
if (!io_file_exists(hook_path))
goto cleanup;
+ arg[0] = hook_path;
+ arg[1] = NULL;
- if (prepare_wins)
- wins_prepare_external();
-
- if ((pid = shell_exec(NULL, NULL, *arg, arg))) {
- ret = child_wait(NULL, NULL, pid);
- if (ret)
- press_any_key();
+ if ((pid = shell_exec(&pin, &pout, &perr, 1, *arg, arg))) {
+ ret = child_wait(&pin, &pout, &perr, pid);
+ if (ret > 0 && WIFEXITED(ret)) {
+ asprintf(&mesg, "%s hook: exit status %d",
+ name,
+ WEXITSTATUS(ret));
+ que_ins(mesg, now(), 3);
+ mem_free(mesg);
+ } else if (ret != 0) {
+ asprintf(&mesg, "%s hook: abnormal termination",
+ name);
+ que_ins(mesg, now(), 4);
+ mem_free(mesg);
+ }
}
- if (prepare_wins)
- wins_unprepare_external();
-
cleanup:
mem_free(hook_path);
return ret;
diff --git a/src/htable.h b/src/htable.h
index 93f65b3..92be6e2 100644
--- a/src/htable.h
+++ b/src/htable.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/src/ical.c b/src/ical.c
index 95489a0..a8ce0a4 100644
--- a/src/ical.c
+++ b/src/ical.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,11 +36,14 @@
#include <strings.h>
#include <sys/types.h>
+#include <ctype.h>
#include "calcurse.h"
#define ICALDATEFMT "%Y%m%d"
#define ICALDATETIMEFMT "%Y%m%dT%H%M%S"
+#define SEPARATOR "-- \n"
+#define INDENT " "
typedef enum {
ICAL_VEVENT,
@@ -54,12 +57,13 @@ typedef enum {
EVENT
} ical_vevent_e;
-typedef struct {
- enum recur_type type;
- int freq;
- long until;
- unsigned count;
-} ical_rpt_t;
+typedef enum {
+ NO_PROPERTY,
+ SUMMARY,
+ DESCRIPTION,
+ LOCATION,
+ COMMENT
+} ical_property_e;
static void ical_export_header(FILE *);
static void ical_export_recur_events(FILE *, int);
@@ -69,8 +73,36 @@ static void ical_export_apoints(FILE *, int);
static void ical_export_todo(FILE *, int);
static void ical_export_footer(FILE *);
-static const char *ical_recur_type[RECUR_TYPES] =
- { "", "DAILY", "WEEKLY", "MONTHLY", "YEARLY" };
+static const char *ical_recur_type[NBRECUR] =
+ { "DAILY", "WEEKLY", "MONTHLY", "YEARLY" };
+
+static const char *ical_wday[] =
+ {"SU", "MO", "TU", "WE", "TH", "FR", "SA"};
+
+/*
+ * Encode a string as a property value of type TEXT (RFC 5545, 3.3.11).
+ */
+static void ical_format_line(FILE *stream, char *property, char *msg)
+{
+ char * p;
+
+ fputs(property, stream);
+ for (p = msg; *p; p++) {
+ switch (*p) {
+ case '\n':
+ fprintf(stream, "\\%c", 'n');
+ break;
+ case ',':
+ case ';':
+ case '\\':
+ fprintf(stream, "\\%c", *p);
+ break;
+ default:
+ fputc(*p, stream);
+ }
+ }
+ fputc('\n', stream);
+}
/* iCal alarm notification. */
static void ical_export_valarm(FILE * stream)
@@ -83,12 +115,157 @@ static void ical_export_valarm(FILE * stream)
fputs("END:VALARM\n", stream);
}
+static void ical_export_rrule(FILE *stream, struct rpt *rpt, ical_vevent_e item,
+ char *buf)
+{
+ llist_item_t *j;
+ int d;
+ char *fmt = item == EVENT ? ICALDATEFMT :
+ item == APPOINTMENT ? ICALDATETIMEFMT :
+ NULL;
+
+ fprintf(stream, "RRULE:FREQ=%s", ical_recur_type[rpt->type]);
+ if (rpt->freq > 1)
+ fprintf(stream, ";INTERVAL=%d", rpt->freq);
+ if (rpt->until) {
+ date_sec2date_fmt(rpt->until, fmt, buf);
+ fprintf(stream, ";UNTIL=%s", buf);
+ }
+ if (LLIST_FIRST(&rpt->bymonth)) {
+ fputs(";BYMONTH=", stream);
+ LLIST_FOREACH(&rpt->bymonth, j) {
+ d = *(int *)LLIST_GET_DATA(j);
+ fprintf(stream, "%d", d);
+ if (LLIST_NEXT(j))
+ fputc(',', stream);
+ }
+ }
+ if (LLIST_FIRST(&rpt->bywday)) {
+ int ord;
+ char sign;
+
+ fputs(";BYDAY=", stream);
+ LLIST_FOREACH(&rpt->bywday, j) {
+ d = *(int *)LLIST_GET_DATA(j);
+ sign = d < 0 ? '-' : '+';
+ d = abs(d);
+ ord = d / 7;
+ d = d % 7;
+ if (ord == 0)
+ fprintf(stream, "%s", ical_wday[d]);
+ else
+ fprintf(stream, "%c%d%s", sign, ord, ical_wday[d]);
+ if (LLIST_NEXT(j))
+ fputc(',', stream);
+ }
+ }
+ if (LLIST_FIRST(&rpt->bymonthday)) {
+ fputs(";BYMONTHDAY=", stream);
+ LLIST_FOREACH(&rpt->bymonthday, j) {
+ d = *(int *)LLIST_GET_DATA(j);
+ fprintf(stream, "%d", d);
+ if (LLIST_NEXT(j))
+ fputc(',', stream);
+ }
+ }
+ fputc('\n', stream);
+}
+
+/*
+ * Copy the characters (lines) between "a" and "z" into an allocated string,
+ * un-indent it and return it. Note that the final character, a newline, is
+ * overwritten with '\0'.
+ */
+static char *ical_unindent(char *a, char *z)
+{
+ char *p, *q; int len;
+
+ len = z - a + 1;
+
+ p = mem_malloc(len);
+ strncpy(p, a, len);
+ p[len - 1] = '\0';
+ while ((q = strstr(p, "\n" INDENT))) {
+ while (*(q + 1 + strlen(INDENT))) {
+ *(q + 1) = *(q + 1 + strlen(INDENT));
+ q++;
+ }
+ *(q + 1) = '\0';
+ }
+ return p;
+}
+
+static void ical_export_note(FILE *stream, char *name)
+{
+ char *note_file, *p, *q, *r, *rest;
+ char *property[] = {
+ "Location: ",
+ "Comment: ",
+ NULL
+ };
+ char *PROPERTY[] = {
+ "LOCATION:",
+ "COMMENT:"
+ };
+ struct string note;
+ char lbuf[BUFSIZ];
+ FILE *fp;
+ int has_desc, has_prop, i;
+
+ asprintf(&note_file, "%s/%s", path_notes, name);
+ if (!(fp = fopen(note_file, "r")) || ungetc(getc(fp), fp) == EOF) {
+ if (fp)
+ fclose(fp);
+ return;
+ }
+ string_init(&note);
+ while (fgets(lbuf, BUFSIZ, fp))
+ string_catf(&note, "%s", lbuf);
+ fclose(fp);
+
+ has_desc = has_prop = 0;
+ rest = note.buf;
+ if ((p = strstr(note.buf, SEPARATOR))) {
+ has_prop = 1;
+ rest = p + strlen(SEPARATOR);
+ if (p != note.buf) {
+ has_desc = 1;
+ *(--p) = '\0';
+ }
+ } else {
+ has_desc = 1;
+ note.buf[strlen(note.buf) - 1] = '\0';
+ }
+
+ if (has_desc)
+ ical_format_line(stream, "DESCRIPTION:", note.buf);
+
+ if (!has_prop)
+ goto cleanup;
+ for (i = 0; property[i]; i++) {
+ if ((p = strstr(rest, property[i])))
+ p += strlen(property[i]);
+ else
+ continue;
+ /* Find end of property. */
+ for (q = p;
+ (q = strchr(q, '\n')) && starts_with(q + 1, INDENT);
+ q++) ;
+ /* Extract property line(s). */
+ r = ical_unindent(p, q);
+ ical_format_line(stream, PROPERTY[i], r);
+ mem_free(r);
+ }
+cleanup:
+ mem_free(note.buf);
+}
+
/* Export header. */
static void ical_export_header(FILE * stream)
{
fputs("BEGIN:VCALENDAR\n", stream);
- fprintf(stream, "PRODID:-//calcurse//NONSGML v%s//EN\n", VERSION);
fputs("VERSION:2.0\n", stream);
+ fprintf(stream, "PRODID:-//calcurse//NONSGML v%s//EN\n", VERSION);
}
/* Export footer. */
@@ -101,26 +278,21 @@ static void ical_export_footer(FILE * stream)
static void ical_export_recur_events(FILE * stream, int export_uid)
{
llist_item_t *i, *j;
- char ical_date[BUFSIZ];
+ char ical_date[BUFSIZ], *hash;
LLIST_FOREACH(&recur_elist, i) {
struct recur_event *rev = LLIST_GET_DATA(i);
- date_sec2date_fmt(rev->day, ICALDATEFMT, ical_date);
fputs("BEGIN:VEVENT\n", stream);
- fprintf(stream, "DTSTART:%s\n", ical_date);
- fprintf(stream, "RRULE:FREQ=%s;INTERVAL=%d",
- ical_recur_type[rev->rpt->type], rev->rpt->freq);
-
- if (rev->rpt->until != 0) {
- date_sec2date_fmt(rev->rpt->until, ICALDATEFMT,
- ical_date);
- fprintf(stream, ";UNTIL=%s\n", ical_date);
- } else {
- fputc('\n', stream);
+ if (export_uid) {
+ hash = recur_event_hash(rev);
+ fprintf(stream, "UID:%s\n", hash);
+ mem_free(hash);
}
-
+ date_sec2date_fmt(rev->day, ICALDATEFMT, ical_date);
+ fprintf(stream, "DTSTART;VALUE=DATE:%s\n", ical_date);
+ ical_export_rrule(stream, rev->rpt, EVENT, ical_date);
if (LLIST_FIRST(&rev->exc)) {
- fputs("EXDATE:", stream);
+ fputs("EXDATE;VALUE=DATE:", stream);
LLIST_FOREACH(&rev->exc, j) {
struct excp *exc = LLIST_GET_DATA(j);
date_sec2date_fmt(exc->st, ICALDATETIMEFMT,
@@ -129,15 +301,9 @@ static void ical_export_recur_events(FILE * stream, int export_uid)
fputc(LLIST_NEXT(j) ? ',' : '\n', stream);
}
}
-
- fprintf(stream, "SUMMARY:%s\n", rev->mesg);
-
- if (export_uid) {
- char *hash = recur_event_hash(rev);
- fprintf(stream, "UID:%s\n", hash);
- mem_free(hash);
- }
-
+ ical_format_line(stream, "SUMMARY:", rev->mesg);
+ if (rev->note)
+ ical_export_note(stream, rev->note);
fputs("END:VEVENT\n", stream);
}
}
@@ -146,21 +312,21 @@ static void ical_export_recur_events(FILE * stream, int export_uid)
static void ical_export_events(FILE * stream, int export_uid)
{
llist_item_t *i;
- char ical_date[BUFSIZ];
+ char ical_date[BUFSIZ], *hash;
LLIST_FOREACH(&eventlist, i) {
struct event *ev = LLIST_TS_GET_DATA(i);
- date_sec2date_fmt(ev->day, ICALDATEFMT, ical_date);
fputs("BEGIN:VEVENT\n", stream);
- fprintf(stream, "DTSTART;VALUE=DATE:%s\n", ical_date);
- fprintf(stream, "SUMMARY:%s\n", ev->mesg);
-
if (export_uid) {
- char *hash = event_hash(ev);
+ hash = event_hash(ev);
fprintf(stream, "UID:%s\n", hash);
mem_free(hash);
}
-
+ date_sec2date_fmt(ev->day, ICALDATEFMT, ical_date);
+ fprintf(stream, "DTSTART;VALUE=DATE:%s\n", ical_date);
+ ical_format_line(stream, "SUMMARY:", ev->mesg);
+ if (ev->note)
+ ical_export_note(stream, ev->note);
fputs("END:VEVENT\n", stream);
}
}
@@ -169,16 +335,30 @@ static void ical_export_events(FILE * stream, int export_uid)
static void ical_export_recur_apoints(FILE * stream, int export_uid)
{
llist_item_t *i, *j;
- char ical_datetime[BUFSIZ];
- char ical_date[BUFSIZ];
+ char ical_datetime[BUFSIZ], *hash;
+ time_t tod;
LLIST_TS_LOCK(&recur_alist_p);
LLIST_TS_FOREACH(&recur_alist_p, i) {
struct recur_apoint *rapt = LLIST_TS_GET_DATA(i);
+ /*
+ * Add time-of-day to UNTIL/EXDATE.
+ * In calcurse until/exception is a date (midnight), but in
+ * RFC 5545 UNTIL/EXDATE is a DATE-TIME value type by default.
+ */
+ tod = get_item_time(rapt->start);
+ if (rapt->rpt->until)
+ rapt->rpt->until += tod;
+
date_sec2date_fmt(rapt->start, ICALDATETIMEFMT,
ical_datetime);
fputs("BEGIN:VEVENT\n", stream);
+ if (export_uid) {
+ hash = recur_apoint_hash(rapt);
+ fprintf(stream, "UID:%s\n", hash);
+ mem_free(hash);
+ }
fprintf(stream, "DTSTART:%s\n", ical_datetime);
if (rapt->dur > 0) {
fprintf(stream, "DURATION:P%ldDT%ldH%ldM%ldS\n",
@@ -187,38 +367,22 @@ static void ical_export_recur_apoints(FILE * stream, int export_uid)
(rapt->dur / MININSEC) % HOURINMIN,
rapt->dur % MININSEC);
}
- fprintf(stream, "RRULE:FREQ=%s;INTERVAL=%d",
- ical_recur_type[rapt->rpt->type], rapt->rpt->freq);
-
- if (rapt->rpt->until != 0) {
- date_sec2date_fmt(rapt->rpt->until + HOURINSEC,
- ICALDATEFMT, ical_date);
- fprintf(stream, ";UNTIL=%s\n", ical_date);
- } else {
- fputc('\n', stream);
- }
-
+ ical_export_rrule(stream, rapt->rpt, APPOINTMENT, ical_datetime);
if (LLIST_FIRST(&rapt->exc)) {
fputs("EXDATE:", stream);
LLIST_FOREACH(&rapt->exc, j) {
struct excp *exc = LLIST_GET_DATA(j);
- date_sec2date_fmt(exc->st, ICALDATETIMEFMT,
- ical_date);
- fprintf(stream, "%s", ical_date);
+ date_sec2date_fmt(exc->st + tod, ICALDATETIMEFMT,
+ ical_datetime);
+ fprintf(stream, "%s", ical_datetime);
fputc(LLIST_NEXT(j) ? ',' : '\n', stream);
}
}
-
- fprintf(stream, "SUMMARY:%s\n", rapt->mesg);
+ ical_format_line(stream, "SUMMARY:", rapt->mesg);
+ if (rapt->note)
+ ical_export_note(stream, rapt->note);
if (rapt->state & APOINT_NOTIFY)
ical_export_valarm(stream);
-
- if (export_uid) {
- char *hash = recur_apoint_hash(rapt);
- fprintf(stream, "UID:%s\n", hash);
- mem_free(hash);
- }
-
fputs("END:VEVENT\n", stream);
}
LLIST_TS_UNLOCK(&recur_alist_p);
@@ -228,14 +392,19 @@ static void ical_export_recur_apoints(FILE * stream, int export_uid)
static void ical_export_apoints(FILE * stream, int export_uid)
{
llist_item_t *i;
- char ical_datetime[BUFSIZ];
+ char ical_datetime[BUFSIZ], *hash;
LLIST_TS_LOCK(&alist_p);
LLIST_TS_FOREACH(&alist_p, i) {
struct apoint *apt = LLIST_TS_GET_DATA(i);
+ fputs("BEGIN:VEVENT\n", stream);
+ if (export_uid) {
+ hash = apoint_hash(apt);
+ fprintf(stream, "UID:%s\n", hash);
+ mem_free(hash);
+ }
date_sec2date_fmt(apt->start, ICALDATETIMEFMT,
ical_datetime);
- fputs("BEGIN:VEVENT\n", stream);
fprintf(stream, "DTSTART:%s\n", ical_datetime);
if (apt->dur > 0) {
fprintf(stream, "DURATION:P%ldDT%ldH%ldM%ldS\n",
@@ -244,16 +413,11 @@ static void ical_export_apoints(FILE * stream, int export_uid)
(apt->dur / MININSEC) % HOURINMIN,
apt->dur % MININSEC);
}
- fprintf(stream, "SUMMARY:%s\n", apt->mesg);
+ ical_format_line(stream, "SUMMARY:", apt->mesg);
+ if (apt->note)
+ ical_export_note(stream, apt->note);
if (apt->state & APOINT_NOTIFY)
ical_export_valarm(stream);
-
- if (export_uid) {
- char *hash = apoint_hash(apt);
- fprintf(stream, "UID:%s\n", hash);
- mem_free(hash);
- }
-
fputs("END:VEVENT\n", stream);
}
LLIST_TS_UNLOCK(&alist_p);
@@ -263,47 +427,57 @@ static void ical_export_apoints(FILE * stream, int export_uid)
static void ical_export_todo(FILE * stream, int export_uid)
{
llist_item_t *i;
+ char *hash;
LLIST_FOREACH(&todolist, i) {
struct todo *todo = LLIST_TS_GET_DATA(i);
fputs("BEGIN:VTODO\n", stream);
- if (todo->completed)
- fprintf(stream, "STATUS:COMPLETED\n");
- fprintf(stream, "PRIORITY:%d\n", todo->id);
- fprintf(stream, "SUMMARY:%s\n", todo->mesg);
-
if (export_uid) {
- char *hash = todo_hash(todo);
+ hash = todo_hash(todo);
fprintf(stream, "UID:%s\n", hash);
mem_free(hash);
}
-
+ fprintf(stream, "PRIORITY:%d\n", todo->id);
+ ical_format_line(stream, "SUMMARY:", todo->mesg);
+ if (todo->note)
+ ical_export_note(stream, todo->note);
+ if (todo->completed)
+ fprintf(stream, "STATUS:COMPLETED\n");
fputs("END:VTODO\n", stream);
}
}
/* Print a header to describe import log report format. */
-static void ical_log_init(FILE * log, int major, int minor)
+static void ical_log_init(const char *file, FILE * log, int major, int minor)
{
const char *header =
"+-------------------------------------------------------------------+\n"
"| Calcurse icalendar import log. |\n"
"| |\n"
- "| Items imported from icalendar file, version %d.%d |\n"
- "| Some items could not be imported, they are described hereafter. |\n"
+ "| Import from icalendar file |\n"
+ "| %-60s|\n"
+ "| version %d.%d at %s. |\n"
+ "| |\n"
+ "| Items which could not be imported are described below. |\n"
"| The log line format is as follows: |\n"
"| |\n"
"| TYPE [LINE]: DESCRIPTION |\n"
"| |\n"
"| where: |\n"
- "| * TYPE represents the item type ('VEVENT' or 'VTODO') |\n"
- "| * LINE is the line in the input stream at which this item begins |\n"
- "| * DESCRIPTION indicates why the item could not be imported |\n"
+ "| * TYPE is the item type, 'VEVENT' or 'VTODO' |\n"
+ "| * LINE is the line in the import file where the item begins |\n"
+ "| * DESCRIPTION explains why the item could not be imported |\n"
"+-------------------------------------------------------------------+\n\n";
+ char *date, *fmt;
+
+ asprintf(&fmt, "%s %s", DATEFMT(conf.input_datefmt), "%H:%M");
+ date = date_sec2date_str(now(), fmt);
if (log)
- fprintf(log, header, major, minor);
+ fprintf(log, header, file, major, minor, date);
+ mem_free(fmt);
+ mem_free(date);
}
/*
@@ -334,25 +508,37 @@ static void ical_store_todo(int priority, int completed, char *mesg,
erase_note(&note);
}
+/*
+ * Calcurse limitation: events are one-day (all-day), and all multi-day events
+ * are turned into one-day events; a note has been added by ical_read_event().
+ */
static void
-ical_store_event(char *mesg, char *note, long day, long end,
- ical_rpt_t * rpt, llist_t * exc, const char *fmt_ev,
+ical_store_event(char *mesg, char *note, time_t day, time_t end,
+ struct rpt *rpt, llist_t *exc, const char *fmt_ev,
const char *fmt_rev)
{
const int EVENTID = 1;
struct event *ev;
struct recur_event *rev;
+ if (!mesg)
+ mesg = mem_strdup(_("(empty)"));
+ EXIT_IF(!mesg, _("ical_store_event: out of memory"));
+
+ /*
+ * Repeating event. The end day is ignored, and the event becomes
+ * one-day even if multi-day.
+ */
if (rpt) {
- rev = recur_event_new(mesg, note, day, EVENTID, rpt->type,
- rpt->freq, rpt->until, exc);
- mem_free(rpt);
+ rpt->exc = *exc;
+ rev = recur_event_new(mesg, note, day, EVENTID, rpt);
if (fmt_rev)
print_recur_event(fmt_rev, day, rev);
goto cleanup;
}
- if (end == 0 || end - day <= DAYINSEC) {
+ /* Ordinary one-day event. */
+ if (end - day <= DAYINSEC) {
ev = event_new(mesg, note, day, EVENTID);
if (fmt_ev)
print_event(fmt_ev, day, ev);
@@ -360,21 +546,19 @@ ical_store_event(char *mesg, char *note, long day, long end,
}
/*
- * Here we have an event that spans over several days.
- *
- * In iCal, the end specifies when the event is supposed to end, in
- * calcurse, the end specifies the time that the last occurrence of the
- * event starts, so we need to do some conversion here.
+ * Ordinary multi-day event. The event is turned into a daily repeating
+ * event until the day before the end. In iCal, the end day is
+ * exclusive, the until day inclusive.
*/
- end = day + ((end - day - 1) / DAYINSEC) * DAYINSEC;
- rpt = mem_malloc(sizeof(ical_rpt_t));
- rpt->type = RECUR_DAILY;
- rpt->freq = 1;
- rpt->count = 0;
- rpt->until = end;
- rev = recur_event_new(mesg, note, day, EVENTID, rpt->type,
- rpt->freq, rpt->until, exc);
- mem_free(rpt);
+ struct rpt tmp;
+ tmp.type = RECUR_DAILY;
+ tmp.freq = 1;
+ tmp.until = day + ((end - day - 1) / DAYINSEC) * DAYINSEC;
+ LLIST_INIT(&tmp.bymonth);
+ LLIST_INIT(&tmp.bywday);
+ LLIST_INIT(&tmp.bymonthday);
+ tmp.exc = *exc;
+ rev = recur_event_new(mesg, note, day, EVENTID, &tmp);
if (fmt_rev)
print_recur_event(fmt_rev, day, rev);
@@ -384,20 +568,41 @@ cleanup:
}
static void
-ical_store_apoint(char *mesg, char *note, long start, long dur,
- ical_rpt_t * rpt, llist_t * exc, int has_alarm,
+ical_store_apoint(char *mesg, char *note, time_t start, long dur,
+ struct rpt *rpt, llist_t *exc, int has_alarm,
const char *fmt_apt, const char *fmt_rapt)
{
char state = 0L;
struct apoint *apt;
struct recur_apoint *rapt;
+ time_t day;
+
+ if (!mesg)
+ mesg = mem_strdup(_("(empty)"));
+ EXIT_IF(!mesg, _("ical_store_event: out of memory"));
if (has_alarm)
state |= APOINT_NOTIFY;
if (rpt) {
- rapt = recur_apoint_new(mesg, note, start, dur, state,
- rpt->type, rpt->freq, rpt->until, exc);
- mem_free(rpt);
+ /*
+ * In calcurse, "until" is interpreted as a day (DATE) - hours,
+ * minutes and seconds are ignored - whereas in iCal the full
+ * DATE-TIME value of "until" is taken into account. It follows
+ * that if the event in calcurse has an occurrence on the until
+ * day, and the start time is after the until value, the
+ * calcurse until day must be changed to the day before.
+ */
+ if (rpt->until) {
+ day = DAY(rpt->until);
+ if (recur_item_find_occurrence(start, dur, rpt, NULL,
+ day, NULL) &&
+ get_item_time(rpt->until) < get_item_time(start))
+ rpt->until = date_sec_change(day, 0, -1);
+ else
+ rpt->until = day;
+ }
+ rpt->exc = *exc;
+ rapt = recur_apoint_new(mesg, note, start, dur, state, rpt);
if (fmt_rapt)
print_recur_apoint(fmt_rapt, start, rapt->start, rapt);
} else {
@@ -410,10 +615,12 @@ ical_store_apoint(char *mesg, char *note, long start, long dur,
}
/*
- * Returns an allocated string representing the string given in argument once
- * unformatted.
+ * Return an allocated string containing the decoded 'line' or NULL on error.
+ * The last arguments are used to format a note file entry.
+ * The line is assumed to be the value part of a content line of type TEXT or
+ * INTEGER (RFC 5545, 3.3.11 and 3.3.8) without list or field separators (3.1.1).
*/
-static char *ical_unformat_line(char *line)
+static char *ical_unformat_line(char *line, int eol, int indentation)
{
struct string s;
char *p;
@@ -423,30 +630,37 @@ static char *ical_unformat_line(char *line)
switch (*p) {
case '\\':
switch (*(p + 1)) {
+ case 'N':
case 'n':
string_catf(&s, "%c", '\n');
+ if (indentation)
+ string_catf(&s, "%s", INDENT);
p++;
break;
- case 't':
- string_catf(&s, "%c", '\t');
- p++;
- break;
+ case '\\':
case ';':
- case ':':
case ',':
string_catf(&s, "%c", *(p + 1));
p++;
break;
default:
- string_catf(&s, "%c", *p);
- break;
+ mem_free(s.buf);
+ return NULL;
}
break;
+ case ',':
+ case ';':
+ /* No list or field separator allowed. */
+ mem_free(s.buf);
+ return NULL;
default:
string_catf(&s, "%c", *p);
break;
}
}
+ /* Add the final EOL removed by ical_readline(). */
+ if (eol)
+ string_catf(&s, "\n");
return string_buf(&s);
}
@@ -458,13 +672,13 @@ ical_readline_init(FILE * fdi, char *buf, char *lstore, unsigned *ln)
*buf = *lstore = '\0';
if (fgets(lstore, BUFSIZ, fdi)) {
+ (*ln)++;
if ((eol = strchr(lstore, '\n')) != NULL) {
if (*(eol - 1) == '\r')
*(eol - 1) = '\0';
else
*eol = '\0';
}
- (*ln)++;
}
}
@@ -473,11 +687,11 @@ static int ical_readline(FILE * fdi, char *buf, char *lstore, unsigned *ln)
char *eol;
strncpy(buf, lstore, BUFSIZ);
- (*ln)++;
while (fgets(lstore, BUFSIZ, fdi) != NULL) {
+ (*ln)++;
if ((eol = strchr(lstore, '\n')) != NULL) {
- if (*(eol - 1) == '\r')
+ if (strlen(lstore) > 1 && *(eol - 1) == '\r')
*(eol - 1) = '\0';
else
*eol = '\0';
@@ -485,7 +699,6 @@ static int ical_readline(FILE * fdi, char *buf, char *lstore, unsigned *ln)
if (*lstore != SPACE && *lstore != TAB)
break;
strncat(buf, lstore + 1, BUFSIZ - strlen(buf) - 1);
- (*ln)++;
}
if (feof(fdi)) {
@@ -516,39 +729,83 @@ ical_chk_header(FILE * fd, char *buf, char *lstore, unsigned *lineno,
}
/*
+ * Return the TZID property parameter value from a DTSTART/DTEND/EXDATE property
+ * in an allocated string. The value may be any text string not containing the
+ * characters '"', ';', ':' and ',' (RFC 5545, sections 3.2.19 and 3.1).
+ */
+static char *ical_get_tzid(char *p)
+{
+ const char param[] = ";TZID=";
+ char *q;
+ int s;
+
+ if (!(p = strstr(p, param)))
+ return NULL;
+ p += sizeof(param) - 1;
+ if (*p == '"')
+ return NULL;
+
+ q = strpbrk(p, ":;");
+ s = q - p + 1;
+ q = mem_malloc(s);
+ strncpy(q, p, s);
+ q[s - 1] = '\0';
+
+ return q;
+}
+
+/*
+ * Return event type from a DTSTART/DTEND/EXDATE property.
+ */
+static ical_vevent_e ical_get_type(char *c_line)
+{
+ const char vparam[] = ";VALUE=DATE";
+ char *p;
+
+ if ((p = strstr(c_line, vparam))) {
+ p += sizeof(vparam) - 1;
+ if (*p == ':' || *p == ';')
+ return EVENT;
+ }
+
+ return APPOINTMENT;
+}
+
+/*
* iCalendar date-time format is based on the ISO 8601 complete
* representation. It should be something like : DATE 'T' TIME
* where DATE is 'YYYYMMDD' and TIME is 'HHMMSS'.
* The time and 'T' separator are optional (in the case of an day-long event).
*
- * Optionally, if the type pointer is given, specify if it is an event
- * (no time is given, meaning it is an all-day event), or an appointment
- * (time is given).
- *
- * The timezone is not yet handled by calcurse.
+ * The type argument is either APPOINTMENT or EVENT, and the time format must
+ * match (either DATE-TIME or DATE). The time zone identifier is ignored in an
+ * EVENT or in an APPOINTMENT with UTC time.
*/
-static time_t ical_datetime2time_t(char *datestr, ical_vevent_e * type)
+static time_t ical_datetime2time_t(char *datestr, char *tzid, ical_vevent_e type)
{
- const int FORMAT_DATE = 3, FORMAT_DATETIME = 6, FORMAT_DATETIMEZ = 7;
+ const int INVALID = 0, DATE = 3, DATETIME = 6, DATETIMEZ = 7;
struct date date;
unsigned hour, min, sec;
- char c;
+ char c, UTC[] = "";
int format;
+ EXIT_IF(type == UNDEFINED, "event type not set");
+
format = sscanf(datestr, "%04u%02u%02uT%02u%02u%02u%c",
&date.yyyy, &date.mm, &date.dd, &hour, &min, &sec, &c);
- if (format == FORMAT_DATE) {
- if (type)
- *type = EVENT;
+
+ if (format == DATE && strlen(datestr) > 8)
+ format = INVALID;
+ if (format == DATETIMEZ && c != 'Z')
+ format = DATETIME;
+
+ if (format == DATE && type == EVENT)
return date2sec(date, 0, 0);
- } else if (format == FORMAT_DATETIME || format == FORMAT_DATETIMEZ) {
- if (type)
- *type = APPOINTMENT;
- if (format == FORMAT_DATETIMEZ && c == 'Z')
- return utcdate2sec(date, hour, min);
- else
- return date2sec(date, hour, min);
- }
+ else if (format == DATETIME && type == APPOINTMENT)
+ return tzdate2sec(date, hour, min, tzid);
+ else if (format == DATETIMEZ && type == APPOINTMENT)
+ return tzdate2sec(date, hour, min, UTC);
+
return 0;
}
@@ -582,15 +839,22 @@ static long ical_durtime2long(char *timestr)
}
/*
- * Extract from RFC2445:
+ * Extract from RFC2445 section 3.8.2.5:
+ *
+ * Property Name: DURATION
+ *
+ * Purpose: This property specifies a positive duration of time.
+ *
+ * Value Type: DURATION
+ *
+ * and section 3.3.6:
*
* Value Name: DURATION
*
* Purpose: This value type is used to identify properties that contain
- * duration of time.
+ * a duration of time.
*
- * Formal Definition: The value type is defined by the following
- * notation:
+ * Format Definition: The value type is defined by the following notation:
*
* dur-value = (["+"] / "-") "P" (dur-date / dur-time / dur-week)
* dur-date = dur-day [dur-time]
@@ -601,73 +865,41 @@ static long ical_durtime2long(char *timestr)
* dur-second = 1*DIGIT "S"
* dur-day = 1*DIGIT "D"
*
+ * For events, duration must be days or weeks.
* Example: A duration of 15 days, 5 hours and 20 seconds would be:
* P15DT5H0M20S
* A duration of 7 weeks would be:
* P7W
*/
-static long ical_dur2long(char *durstr)
+static long ical_dur2long(char *durstr, ical_vevent_e type)
{
- char *p;
+ char *p = durstr, c;
int bytes_read;
- struct {
- unsigned week, day;
- } date;
-
- memset(&date, 0, sizeof date);
-
- p = strchr(durstr, 'P');
- if (!p)
- return -1;
- p++;
+ unsigned week, day;
if (*p == '-')
- return -1;
+ return 0;
if (*p == '+')
p++;
+ if (*p != 'P')
+ return 0;
- if (*p == 'T') {
+ p++;
+ if (*p == 'T' && type == APPOINTMENT)
/* dur-time */
return ical_durtime2long(p);
- } else if (strchr(p, 'W')) {
+ else if (sscanf(p, "%u%c", &week, &c) == 2 && c == 'W')
/* dur-week */
- if (sscanf(p, "%u", &date.week) == 1)
- return date.week * WEEKINDAYS * DAYINSEC;
- } else if (strchr(p, 'D')) {
+ return week * WEEKINDAYS * DAYINSEC;
+ else if (sscanf(p, "%u%c%n", &day, &c, &bytes_read) == 2 && c == 'D') {
/* dur-date */
- if (sscanf(p, "%uD%n", &date.day, &bytes_read) == 1) {
- p += bytes_read;
- return date.day * DAYINSEC + ical_durtime2long(p);
- }
+ p += bytes_read;
+ return day * DAYINSEC + (*p == 'T' && type == APPOINTMENT ?
+ ical_durtime2long(p) :
+ 0);
}
- return -1;
-}
-
-/*
- * Compute the vevent repetition end date from the repetition count.
- *
- * Extract from RFC2445:
- * The COUNT rule part defines the number of occurrences at which to
- * range-bound the recurrence. The "DTSTART" property value, if specified,
- * counts as the first occurrence.
- */
-static long ical_compute_rpt_until(long start, ical_rpt_t * rpt)
-{
- switch (rpt->type) {
- case RECUR_DAILY:
- return date_sec_change(start, 0, rpt->freq * (rpt->count - 1));
- case RECUR_WEEKLY:
- return date_sec_change(start, 0,
- rpt->freq * WEEKINDAYS * (rpt->count - 1));
- case RECUR_MONTHLY:
- return date_sec_change(start, rpt->freq * (rpt->count - 1), 0);
- case RECUR_YEARLY:
- return date_sec_change(start,
- rpt->freq * 12 * (rpt->count - 1), 0);
- default:
- return 0;
- }
+ return 0;
}
/*
@@ -675,10 +907,12 @@ static long ical_compute_rpt_until(long start, ical_rpt_t * rpt)
*/
static char *ical_get_value(char *p)
{
+ if (!(p && *p))
+ return NULL;
for (; *p != ':'; p++) {
if (*p == '"')
- for (p++; *p != '"' && *p != '\0'; p++);
- if (*p == '\0')
+ for (p++; *p && *p != '"'; p++);
+ if (!*p)
return NULL;
}
@@ -686,125 +920,304 @@ static char *ical_get_value(char *p)
}
/*
+ * Fill in the bymonth linked list from a comma-separated list of
+ * unsigned integers terminated by a space or end of string.
+ */
+static int ical_bymonth(llist_t *ll, char *cl)
+{
+ unsigned mon;
+ int *i, n;
+
+ while (!(*cl == ' ' || *cl == '\0')) {
+ if (!(sscanf(cl, "%u%n", &mon, &n) == 1))
+ return 0;
+ i = mem_malloc(sizeof(int));
+ *i = mon;
+ LLIST_ADD(ll, i);
+ cl += n;
+ cl += (*cl == ',');
+ }
+ return 1;
+}
+
+/*
+ * Fill in the bymonthday linked list from a comma-separated list of
+ * (signed) integers terminated by a space or end of string.
+ */
+static int ical_bymonthday(llist_t *ll, char *cl)
+{
+ int mday;
+ int *i, n;
+
+ while (!(*cl == ' ' || *cl == '\0')) {
+ if (!(sscanf(cl, "%d%n", &mday, &n) == 1))
+ return 0;
+ i = mem_malloc(sizeof(int));
+ *i = mday;
+ LLIST_ADD(ll, i);
+ cl += n;
+ cl += (*cl == ',');
+ }
+ return 1;
+}
+
+/*
+ * Fill in the bywday linked list from a comma-separated list of (ordered)
+ * weekday names (+1SU, MO, -5SA, 25TU, etc.) terminated by a space or end of
+ * string.
+ */
+static int ical_bywday(llist_t *ll, char *cl)
+{
+ int sign, order, wday, n, *i;
+ char *owd;
+
+ while (!(*cl == ' ' || *cl == '\0')) {
+ /* find list separator */
+ for (owd = cl; !(*cl == ',' || *cl == ' ' || *cl == '\0'); cl++)
+ ;
+ cl += (*cl == ',');
+
+ if (!(sscanf(owd, "%d%n", &order, &n) == 1))
+ order = n = 0;
+ sign = (order < 0) ? -1 : 1;
+ order *= sign;
+ owd += n;
+ if (starts_with(owd, "SU"))
+ wday = 0;
+ else if (starts_with(owd, "MO"))
+ wday = 1;
+ else if (starts_with(owd, "TU"))
+ wday = 2;
+ else if (starts_with(owd, "WE"))
+ wday = 3;
+ else if (starts_with(owd, "TH"))
+ wday = 4;
+ else if (starts_with(owd, "FR"))
+ wday = 5;
+ else if (starts_with(owd, "SA"))
+ wday = 6;
+ else
+ return 0;
+
+ wday = sign * (wday + order * WEEKINDAYS);
+ i = mem_malloc(sizeof(int));
+ *i = wday;
+ LLIST_ADD(ll, i);
+ }
+ return 1;
+}
+
+/*
* Read a recurrence rule from an iCalendar RRULE string.
*
+ * RFC 5545, section 3.8.5.3:
+ *
+ * Property Name: RRULE
+ *
+ * Purpose: This property defines a rule or repeating pattern for
+ * recurring events, to-dos, journal entries, or time zone definitions.
+ *
+ * Value Type: RECUR
+ *
+ * RFC 5545, section 3.3.10:
+ *
* Value Name: RECUR
*
* Purpose: This value type is used to identify properties that contain
* a recurrence rule specification.
*
- * Formal Definition: The value type is defined by the following
+ * Format Definition: The value type is defined by the following
* notation:
*
- * recur = "FREQ"=freq *(
- *
- * ; either UNTIL or COUNT may appear in a 'recur',
- * ; but UNTIL and COUNT MUST NOT occur in the same 'recur'
- *
- * ( ";" "UNTIL" "=" enddate ) /
- * ( ";" "COUNT" "=" 1*DIGIT ) /
+ * recur = recur-rule-part *( ";" recur-rule-part )
+ * ;
+ * ; The rule parts are not ordered in any particular sequence.
+ * ;
+ * ; The FREQ rule part is REQUIRED,
+ * ; but MUST NOT occur more than once.
+ * ;
+ * ; The UNTIL or COUNT rule parts are OPTIONAL,
+ * ; but they MUST NOT occur in the same 'recur'.
+ * ;
+ * ; The other rule parts are OPTIONAL,
+ * ; but MUST NOT occur more than once.
*
- * ; the rest of these keywords are optional,
- * ; but MUST NOT occur more than
- * ; once
- *
- * ( ";" "INTERVAL" "=" 1*DIGIT ) /
- * ( ";" "BYSECOND" "=" byseclist ) /
- * ( ";" "BYMINUTE" "=" byminlist ) /
- * ( ";" "BYHOUR" "=" byhrlist ) /
- * ( ";" "BYDAY" "=" bywdaylist ) /
- * ( ";" "BYMONTHDAY" "=" bymodaylist ) /
- * ( ";" "BYYEARDAY" "=" byyrdaylist ) /
- * ( ";" "BYWEEKNO" "=" bywknolist ) /
- * ( ";" "BYMONTH" "=" bymolist ) /
- * ( ";" "BYSETPOS" "=" bysplist ) /
- * ( ";" "WKST" "=" weekday ) /
- * ( ";" x-name "=" text )
- * )
-*/
-static ical_rpt_t *ical_read_rrule(FILE * log, char *rrulestr,
- unsigned *noskipped, const int itemline)
+ * recur-rule-part = ( "FREQ"=freq )
+ * / ( "UNTIL" "=" enddate )
+ * / ( "COUNT" "=" 1*DIGIT )
+ * / ( "INTERVAL" "=" 1*DIGIT )
+ * / ( "BYSECOND" "=" byseclist )
+ * / ( "BYMINUTE" "=" byminlist )
+ * / ( "BYHOUR" "=" byhrlist )
+ * / ( "BYDAY" "=" bywdaylist )
+ * / ( "BYMONTHDAY" "=" bymodaylist )
+ * / ( "BYYEARDAY" "=" byyrdaylist )
+ * / ( "BYWEEKNO" "=" bywknolist )
+ * / ( "BYMONTH" "=" bymolist )
+ * / ( "BYSETPOS" "=" bysplist )
+ * / ( "WKST" "=" weekday )
+ */
+static struct rpt *ical_read_rrule(FILE *log, char *rrulestr,
+ unsigned *noskipped,
+ const int itemline,
+ ical_vevent_e type,
+ time_t start,
+ int *count)
{
- const char count[] = "COUNT=";
- const char interv[] = "INTERVAL=";
- char freqstr[BUFSIZ];
- unsigned interval;
- ical_rpt_t *rpt;
- char *p;
+ char freqstr[8], datestr[17];
+ struct rpt *rpt;
+ char *p, *q;
+
+ if (type == UNDEFINED) {
+ ical_log(log, ICAL_VEVENT, itemline,
+ _("need DTSTART to determine event type."));
+ return NULL;
+ }
p = ical_get_value(rrulestr);
if (!p) {
ical_log(log, ICAL_VEVENT, itemline,
- _("recurrence rule malformed."));
+ _("malformed recurrence line."));
(*noskipped)++;
return NULL;
}
-
- rpt = mem_malloc(sizeof(ical_rpt_t));
- memset(rpt, 0, sizeof(ical_rpt_t));
- if (sscanf(p, "FREQ=%s", freqstr) != 1) {
+ /* Prepare for scanf(): replace semicolons by spaces. */
+ for (q = p; (q = strchr(q, ';')); *q = ' ', q++)
+ ;
+
+ rpt = mem_malloc(sizeof(struct rpt));
+ memset(rpt, 0, sizeof(struct rpt));
+ LLIST_INIT(&rpt->bymonth);
+ LLIST_INIT(&rpt->bywday);
+ LLIST_INIT(&rpt->bymonthday);
+
+ /* FREQ rule part */
+ if ((p = strstr(rrulestr, "FREQ="))) {
+ if (sscanf(p, "FREQ=%7s", freqstr) != 1) {
+ ical_log(log, ICAL_VEVENT, itemline,
+ _("frequency not set in rrule."));
+ (*noskipped)++;
+ mem_free(rpt);
+ return NULL;
+ }
+ } else {
ical_log(log, ICAL_VEVENT, itemline,
- _("recurrence frequency not found."));
+ _("frequency absent in rrule."));
(*noskipped)++;
mem_free(rpt);
return NULL;
}
- if (starts_with(freqstr, "DAILY")) {
+ if (!strcmp(freqstr, "DAILY"))
rpt->type = RECUR_DAILY;
- } else if (starts_with(freqstr, "WEEKLY")) {
+ else if (!strcmp(freqstr, "WEEKLY"))
rpt->type = RECUR_WEEKLY;
- } else if (starts_with(freqstr, "MONTHLY")) {
+ else if (!strcmp(freqstr, "MONTHLY"))
rpt->type = RECUR_MONTHLY;
- } else if (starts_with(freqstr, "YEARLY")) {
+ else if (!strcmp(freqstr, "YEARLY"))
rpt->type = RECUR_YEARLY;
- } else {
+ else {
ical_log(log, ICAL_VEVENT, itemline,
- _("recurrence frequency not recognized."));
+ _("rrule frequency not supported."));
(*noskipped)++;
mem_free(rpt);
return NULL;
}
+ /* INTERVAL rule part */
+ rpt->freq = 1;
+ if ((p = strstr(rrulestr, "INTERVAL="))) {
+ if (sscanf(p, "INTERVAL=%d", &rpt->freq) != 1) {
+ ical_log(log, ICAL_VEVENT, itemline, _("invalid interval."));
+ (*noskipped)++;
+ mem_free(rpt);
+ return NULL;
+ }
+ }
+
+ /* UNTIL and COUNT rule parts */
+ if (strstr(rrulestr, "UNTIL=") && strstr(rrulestr, "COUNT=")) {
+ ical_log(log, ICAL_VEVENT, itemline,
+ _("either until or count."));
+ (*noskipped)++;
+ mem_free(rpt);
+ return NULL;
+ }
+
+ if ((p = strstr(rrulestr, "UNTIL="))) {
+ if (sscanf(p, "UNTIL=%16s", datestr) != 1) {
+ ical_log(log, ICAL_VEVENT, itemline,
+ _("missing until value."));
+ (*noskipped)++;
+ mem_free(rpt);
+ return NULL;
+ }
+ rpt->until = ical_datetime2time_t(datestr, NULL, type);
+ if (!rpt->until) {
+ ical_log(log, ICAL_VEVENT, itemline,
+ _("invalid until format."));
+ (*noskipped)++;
+ mem_free(rpt);
+ return NULL;
+ }
+ }
+
/*
- * The UNTIL rule part defines a date-time value which bounds the
- * recurrence rule in an inclusive manner. If not present, and the
- * COUNT rule part is also not present, the RRULE is considered to
- * repeat forever.
-
- * The COUNT rule part defines the number of occurrences at which to
- * range-bound the recurrence. The "DTSTART" property value, if
- * specified, counts as the first occurrence.
+ * COUNT is converted to UNTIL in ical_read_event() once all recurrence
+ * parameters are known.
*/
- if ((p = strstr(rrulestr, "UNTIL")) != NULL) {
- rpt->until = ical_datetime2time_t(strchr(p, '=') + 1, NULL);
- } else {
- unsigned cnt;
- char *countstr;
-
- rpt->until = 0;
- if ((countstr = strstr(rrulestr, count))) {
- countstr += sizeof(count) - 1;
- if (sscanf(countstr, "%u", &cnt) == 1)
- rpt->count = cnt;
+ if ((p = strstr(rrulestr, "COUNT="))) {
+ p = strchr(p, '=') + 1;
+ if (!(sscanf(p, "%d", count) == 1 && *count)) {
+ ical_log(log, ICAL_VEVENT, itemline,
+ _("invalid count value."));
+ (*noskipped)++;
+ mem_free(rpt);
+ return NULL;
}
}
- rpt->freq = 1;
- if ((p = strstr(rrulestr, interv))) {
- p += sizeof(interv) - 1;
- if (sscanf(p, "%u", &interval) == 1)
- rpt->freq = interval;
+ /* BYMONTH rule part */
+ if ((p = strstr(rrulestr, "BYMONTH="))) {
+ p = strchr(p, '=') + 1;
+ if (!ical_bymonth(&rpt->bymonth, p)) {
+ ical_log(log, ICAL_VEVENT, itemline,
+ _("invalid bymonth list."));
+ (*noskipped)++;
+ mem_free(rpt);
+ return NULL;
+ }
+ }
+
+ /* BYMONTHDAY rule part */
+ if ((p = strstr(rrulestr, "BYMONTHDAY="))) {
+ p = strchr(p, '=') + 1;
+ if (!ical_bymonthday(&rpt->bymonthday, p)) {
+ ical_log(log, ICAL_VEVENT, itemline,
+ _("invalid bymonthday list."));
+ (*noskipped)++;
+ mem_free(rpt);
+ return NULL;
+ }
+ }
+
+ /* BYDAY rule part */
+ if ((p = strstr(rrulestr, "BYDAY="))) {
+ p = strchr(p, '=') + 1;
+ if (!ical_bywday(&rpt->bywday, p)) {
+ ical_log(log, ICAL_VEVENT, itemline,
+ _("invalid byday list."));
+ (*noskipped)++;
+ mem_free(rpt);
+ return NULL;
+ }
}
return rpt;
}
-static void ical_add_exc(llist_t * exc_head, long date)
+static void ical_add_exc(llist_t * exc_head, time_t date)
{
- if (date == 0)
- return;
-
struct excp *exc = mem_malloc(sizeof(struct excp));
exc->st = date;
@@ -812,83 +1225,125 @@ static void ical_add_exc(llist_t * exc_head, long date)
}
/*
- * This property defines the list of date/time exceptions for a
+ * This property defines a comma-separated list of date/time exceptions for a
* recurring calendar component.
*/
-static void
-ical_read_exdate(llist_t * exc, FILE * log, char *exstr,
- unsigned *noskipped, const int itemline)
+static int
+ical_read_exdate(llist_t * exc, FILE * log, char *exstr, unsigned *noskipped,
+ const int itemline, ical_vevent_e type)
{
- char *p, *q;
+ char *p, *q, *tzid = NULL;
+ time_t t;
+ int n;
+ if (type != ical_get_type(exstr)) {
+ ical_log(log, ICAL_VEVENT, itemline,
+ _("invalid exception date value type."));
+ goto cleanup;
+ }
p = ical_get_value(exstr);
if (!p) {
ical_log(log, ICAL_VEVENT, itemline,
- _("recurrence exception dates malformed."));
- (*noskipped)++;
- return;
+ _("malformed exceptions line."));
+ goto cleanup;
}
-
- while ((q = strchr(p, ',')) != NULL) {
- char buf[BUFSIZ];
- const int buflen = q - p;
-
- strncpy(buf, p, buflen);
- buf[buflen] = '\0';
- ical_add_exc(exc, ical_datetime2time_t(buf, NULL));
- p = ++q;
+ tzid = ical_get_tzid(exstr);
+ /* Count the exceptions and replace commas by zeroes */
+ for (q = p, n = 1; (q = strchr(q, ',')); *q = '\0', q++, n++)
+ ;
+ while (n) {
+ if (!(t = ical_datetime2time_t(p, tzid, type))) {
+ ical_log(log, ICAL_VEVENT, itemline,
+ _("invalid exception."));
+ goto cleanup;
+ }
+ ical_add_exc(exc, t);
+ p = strchr(p, '\0') + 1;
+ n--;
}
- ical_add_exc(exc, ical_datetime2time_t(p, NULL));
+ return 1;
+
+cleanup:
+ (*noskipped)++;
+ if (tzid)
+ mem_free(tzid);
+ return 0;
}
-/* Return an allocated string containing the name of the newly created note. */
-static char *ical_read_note(char *line, unsigned *noskipped,
+/*
+ * Return an allocated string containing a property value to be written in a
+ * note file or NULL on error.
+ */
+static char *ical_read_note(char *line, ical_property_e property, unsigned *noskipped,
ical_types_e item_type, const int itemline,
FILE * log)
{
- char *p, *notestr, *note;
+ const int EOL = 1,
+ IND = (property != DESCRIPTION);
+ char *p, *pname, *notestr;
+
+ switch (property) {
+ case DESCRIPTION:
+ pname = "description";
+ break;
+ case LOCATION:
+ pname = "location";
+ break;
+ case COMMENT:
+ pname = "comment";
+ break;
+ default:
+ pname = "no property";
+ }
p = ical_get_value(line);
if (!p) {
- ical_log(log, item_type, itemline,
- _("description malformed."));
+ asprintf(&p, _("malformed %s line."), pname);
+ ical_log(log, item_type, itemline, p);
+ mem_free(p);
(*noskipped)++;
- return NULL;
+ notestr = NULL;
+ goto leave;
}
- notestr = ical_unformat_line(p);
- if (notestr == NULL) {
- ical_log(log, item_type, itemline,
- _("could not get entire item description."));
+ notestr = ical_unformat_line(p, EOL, IND);
+ if (!notestr) {
+ asprintf(&p, _("malformed %s."), pname);
+ ical_log(log, item_type, itemline, p);
+ mem_free(p);
(*noskipped)++;
- return NULL;
- } else if (strlen(notestr) == 0) {
- mem_free(notestr);
- return NULL;
- } else {
- note = generate_note(notestr);
- mem_free(notestr);
- return note;
}
+ leave:
+ return notestr;
}
/* Returns an allocated string containing the ical item summary. */
-static char *ical_read_summary(char *line)
+static char *ical_read_summary(char *line, unsigned *noskipped,
+ ical_types_e item_type, const int itemline,
+ FILE * log)
{
- char *p, *summary;
+ const int EOL = 0, IND = 0;
+ char *p, *summary = NULL;
p = ical_get_value(line);
- if (!p)
- return NULL;
-
- summary = ical_unformat_line(p);
- if (!summary)
- return NULL;
+ if (!p) {
+ ical_log(log, item_type, itemline, _("malformed summary line."));
+ (*noskipped)++;
+ goto leave;
+ }
- /* Event summaries must not contain newlines. */
- for (p = strchr(summary, '\n'); p; p = strchr(p, '\n'))
- *p = ' ';
+ summary = ical_unformat_line(p, EOL, IND);
+ if (!summary) {
+ ical_log(log, item_type, itemline, _("malformed summary."));
+ (*noskipped)++;
+ goto leave;
+ }
+ /* An event summary is one line only. */
+ for (p = summary; *p; p++)
+ if (*p == '\n')
+ *p = ' ';
+ leave:
return summary;
}
@@ -898,23 +1353,31 @@ ical_read_event(FILE * fdi, FILE * log, unsigned *noevents,
char *lstore, unsigned *lineno, const char *fmt_ev,
const char *fmt_rev, const char *fmt_apt, const char *fmt_rapt)
{
- const int ITEMLINE = *lineno;
+ const int ITEMLINE = *lineno - !feof(fdi);
ical_vevent_e vevent_type;
- char *p;
+ ical_property_e property;
+ char *p, *note, *tzid;
+ char *dtstart, *dtend, *duration, *rrule;
+ struct string s, exdate;
struct {
llist_t exc;
- ical_rpt_t *rpt;
- char *mesg, *note;
- long start, end, dur;
+ struct rpt *rpt;
+ int count;
+ char *mesg, *desc, *loc, *comm, *imp, *note;
+ time_t start, end;
+ long dur;
int has_alarm;
} vevent;
- int skip_alarm;
+ int skip_alarm, has_note, separator, has_exdate;
vevent_type = UNDEFINED;
memset(&vevent, 0, sizeof vevent);
LLIST_INIT(&vevent.exc);
- skip_alarm = 0;
+ note = dtstart = dtend = duration = rrule = NULL;
+ skip_alarm = has_note = separator = has_exdate =0;
while (ical_readline(fdi, buf, lstore, lineno)) {
+ note = NULL;
+ property = NO_PROPERTY;
if (skip_alarm) {
/*
* Need to skip VALARM properties because some keywords
@@ -924,145 +1387,355 @@ ical_read_event(FILE * fdi, FILE * log, unsigned *noevents,
skip_alarm = 0;
continue;
}
-
if (starts_with_ci(buf, "END:VEVENT")) {
- if (!vevent.mesg) {
+ /* DTSTART and related properties (picked up earlier). */
+ if (!dtstart) {
ical_log(log, ICAL_VEVENT, ITEMLINE,
- _("could not retrieve item summary."));
- goto cleanup;
+ _("item start date not defined."));
+ goto skip;
+ }
+ vevent_type = ical_get_type(dtstart);
+ if ((tzid = ical_get_tzid(dtstart)) &&
+ vevent_type == APPOINTMENT) {
+ if (vevent.imp) {
+ asprintf(&p, "%s, TZID=%s",
+ vevent.imp, tzid);
+ mem_free(vevent.imp);
+ vevent.imp = p;
+ } else
+ asprintf(&vevent.imp, "TZID=%s", tzid);
+ has_note = separator = 1;
+ }
+ p = ical_get_value(dtstart);
+ if (!p) {
+ ical_log(log, ICAL_VEVENT, ITEMLINE,
+ _("malformed start time line."));
+ goto skip;
+ }
+ vevent.start = ical_datetime2time_t(p, tzid, vevent_type);
+ if (tzid) {
+ mem_free(tzid);
+ tzid = NULL;
+ }
+ if (!vevent.start) {
+ ical_log(log, ICAL_VEVENT, ITEMLINE,
+ _("invalid or malformed event "
+ "start time."));
+ goto skip;
}
- if (vevent.start == 0) {
+ /* DTEND */
+ if (!dtend)
+ goto duration;
+ if (vevent_type != ical_get_type(dtend)) {
ical_log(log, ICAL_VEVENT, ITEMLINE,
- _("item start date is not defined."));
+ _("invalid end time value type."));
+ goto skip;
+ }
+ tzid = ical_get_tzid(dtend);
+ p = ical_get_value(dtend);
+ if (!p) {
+ ical_log(log, ICAL_VEVENT, ITEMLINE,
+ _("malformed end time line."));
+ goto skip;
+ }
+ vevent.end = ical_datetime2time_t(p, tzid, vevent_type);
+ if (tzid) {
+ mem_free(tzid);
+ tzid = NULL;
+ }
+ if (!vevent.end) {
+ ical_log(log, ICAL_VEVENT, ITEMLINE,
+ _("malformed event end time."));
+ goto skip;
+ }
+ if (vevent.end <= vevent.start) {
+ ical_log(log, ICAL_VEVENT, ITEMLINE,
+ _("end must be later than start."));
+ goto skip;
+ }
+ duration:
+ if (!duration)
+ goto rrule;
+ if (vevent.end) {
+ ical_log(log, ICAL_VEVENT, ITEMLINE,
+ _("either end or duration."));
+ goto skip;
+ }
+ p = ical_get_value(duration);
+ if (!p) {
+ ical_log(log, ICAL_VEVENT, ITEMLINE,
+ _("malformed duration line."));
+ goto skip;
+ }
+ vevent.dur = ical_dur2long(p, vevent_type);
+ if (!vevent.dur) {
+ ical_log(log, ICAL_VEVENT, ITEMLINE,
+ _("invalid duration."));
+ goto skip;
+ }
+ rrule:
+ if (!rrule)
+ goto exdate;
+ vevent.rpt = ical_read_rrule(log, rrule, noskipped,
+ ITEMLINE, vevent_type, vevent.start,
+ &vevent.count);
+ if (!vevent.rpt)
goto cleanup;
+ exdate:
+ if (!has_exdate)
+ goto duration_end;
+ if (!rrule) {
+ ical_log(log, ICAL_VEVENT, ITEMLINE,
+ _("exception date, but no recurrence "
+ "rule."));
+ goto skip;
}
-
- if (vevent_type == APPOINTMENT && vevent.dur == 0) {
- if (vevent.end != 0) {
- vevent.dur = vevent.end - vevent.start;
+ if (!ical_read_exdate(&vevent.exc, log, exdate.buf,
+ noskipped, ITEMLINE, vevent_type))
+ goto cleanup;
+ duration_end:
+ /* An APPOINTMENT must always have a duration. */
+ if (vevent_type == APPOINTMENT && !vevent.dur) {
+ vevent.dur = vevent.end ?
+ vevent.end - vevent.start :
+ 0;
+ }
+ /* An EVENT must always have an end. */
+ if (vevent_type == EVENT) {
+ if (!vevent.end)
+ vevent.end = vevent.start + vevent.dur;
+ vevent.dur = vevent.end - vevent.start;
+ if (vevent.dur > DAYINSEC) {
+ /* Add note on multi-day events. */
+ char *md = _("multi-day event changed "
+ "to one-day event");
+ if (vevent.imp) {
+ asprintf(&p, "%s, %s",
+ vevent.imp, md);
+ mem_free(vevent.imp);
+ vevent.imp = p;
+ } else
+ asprintf(&vevent.imp, "%s", md);
+ has_note = separator = 1;
}
-
- if (vevent.dur < 0) {
- ical_log(log, ICAL_VEVENT, ITEMLINE,
- _("item has a negative duration."));
- goto cleanup;
+ }
+ if (has_note) {
+ /* Construct string with note file contents. */
+ string_init(&s);
+ if (vevent.desc) {
+ string_catf(&s, "%s", vevent.desc);
+ mem_free(vevent.desc);
+ vevent.desc = NULL;
+ }
+ if (separator)
+ string_catf(&s, SEPARATOR);
+ if (vevent.loc) {
+ string_catf(&s, _("Location: %s"),
+ vevent.loc);
+ mem_free(vevent.loc);
+ vevent.loc = NULL;
+ }
+ if (vevent.comm) {
+ string_catf(&s, _("Comment: %s"),
+ vevent.comm);
+ mem_free(vevent.comm);
+ vevent.comm = NULL;
+ }
+ if (vevent.imp) {
+ string_catf(&s, ("Import: %s\n"),
+ vevent.imp);
+ mem_free(vevent.imp);
+ vevent.imp = NULL;
}
+ vevent.note = generate_note(string_buf(&s));
+ mem_free(s.buf);
}
-
- if (vevent.rpt && vevent.rpt->count) {
- vevent.rpt->until =
- ical_compute_rpt_until(vevent.start,
- vevent.rpt);
+ if (vevent.rpt) {
+ time_t day, until;
+ long dur;
+ char *msg;
+
+ dur = vevent_type == EVENT ? -1 : vevent.dur;
+ day = DAY(vevent.start);
+ msg = _("rrule does not match start day (%s).");
+
+ if (vevent.count) {
+ recur_nth_occurrence(vevent.start,
+ dur,
+ vevent.rpt,
+ &vevent.exc,
+ vevent.count,
+ &until);
+ vevent.rpt->until = until;
+ }
+ if (!recur_item_find_occurrence(vevent.start,
+ dur,
+ vevent.rpt,
+ NULL,
+ day,
+ NULL)) {
+ char *l = day_ins(&msg, vevent.start);
+ ical_log(log, ICAL_VEVENT, ITEMLINE, l);
+ mem_free(l);
+ goto skip;
+ }
}
-
switch (vevent_type) {
case APPOINTMENT:
ical_store_apoint(vevent.mesg, vevent.note,
- vevent.start, vevent.dur,
- vevent.rpt, &vevent.exc,
- vevent.has_alarm, fmt_apt,
- fmt_rapt);
+ vevent.start, vevent.dur,
+ vevent.rpt, &vevent.exc,
+ vevent.has_alarm,
+ fmt_apt, fmt_rapt);
(*noapoints)++;
break;
case EVENT:
ical_store_event(vevent.mesg, vevent.note,
- vevent.start, vevent.end,
- vevent.rpt, &vevent.exc,
- fmt_ev, fmt_rev);
+ vevent.start, vevent.end,
+ vevent.rpt, &vevent.exc,
+ fmt_ev, fmt_rev);
(*noevents)++;
break;
case UNDEFINED:
ical_log(log, ICAL_VEVENT, ITEMLINE,
_("item could not be identified."));
- goto cleanup;
+ goto skip;
break;
}
-
return;
}
-
if (starts_with_ci(buf, "DTSTART")) {
- p = ical_get_value(buf);
- if (!p) {
- ical_log(log, ICAL_VEVENT, ITEMLINE,
- _("event start time malformed."));
- goto cleanup;
- }
-
- vevent.start = ical_datetime2time_t(p, &vevent_type);
- if (!vevent.start) {
- ical_log(log, ICAL_VEVENT, ITEMLINE,
- _("could not retrieve event start time."));
- goto cleanup;
- }
+ /*
+ * DTSTART has a value type: either DATE-TIME or DATE.
+ * In calcurse DATE-TIME implies an appointment, DATE an
+ * event.
+ * Properties DTEND, DURATION and EXDATE and rrule part
+ * UNTIL must match the DTSTART value type.
+ */
+ asprintf(&dtstart, "%s", buf);
} else if (starts_with_ci(buf, "DTEND")) {
- p = ical_get_value(buf);
- if (!p) {
- ical_log(log, ICAL_VEVENT, ITEMLINE,
- _("event end time malformed."));
- goto cleanup;
- }
-
- vevent.end = ical_datetime2time_t(p, &vevent_type);
- if (!vevent.end) {
- ical_log(log, ICAL_VEVENT, ITEMLINE,
- _("could not retrieve event end time."));
- goto cleanup;
- }
+ asprintf(&dtend, "%s", buf);
} else if (starts_with_ci(buf, "DURATION")) {
- vevent.dur = ical_dur2long(buf);
- if (vevent.dur <= 0) {
- ical_log(log, ICAL_VEVENT, ITEMLINE,
- _("item duration malformed."));
- goto cleanup;
- }
+ asprintf(&duration, "%s", buf);
} else if (starts_with_ci(buf, "RRULE")) {
- vevent.rpt = ical_read_rrule(log, buf, noskipped,
- ITEMLINE);
+ asprintf(&rrule, "%s", buf);
} else if (starts_with_ci(buf, "EXDATE")) {
- ical_read_exdate(&vevent.exc, log, buf, noskipped,
- ITEMLINE);
+ if (!has_exdate) {
+ has_exdate = 1;
+ string_init(&exdate);
+ string_catf(&exdate, "%s", buf);
+ } else {
+ p = ical_get_value(buf);
+ string_catf(&exdate, ",%s", p);
+ }
} else if (starts_with_ci(buf, "SUMMARY")) {
- vevent.mesg = ical_read_summary(buf);
+ vevent.mesg = ical_read_summary(buf, noskipped,
+ ICAL_VEVENT, ITEMLINE, log);
+ if (!vevent.mesg)
+ goto cleanup;
} else if (starts_with_ci(buf, "BEGIN:VALARM")) {
skip_alarm = vevent.has_alarm = 1;
} else if (starts_with_ci(buf, "DESCRIPTION")) {
- vevent.note = ical_read_note(buf, noskipped,
- ICAL_VEVENT, ITEMLINE, log);
+ property = DESCRIPTION;
+ } else if (starts_with_ci(buf, "LOCATION")) {
+ property = LOCATION;
+ } else if (starts_with_ci(buf, "COMMENT")) {
+ property = COMMENT;
+ }
+ if (property) {
+ note = ical_read_note(buf, property, noskipped,
+ ICAL_VEVENT, ITEMLINE, log);
+ if (!note)
+ goto cleanup;
+ if (!separator)
+ separator = (property != DESCRIPTION);
+ has_note = 1;
+ }
+ switch (property) {
+ case DESCRIPTION:
+ if (vevent.desc) {
+ ical_log(log, ICAL_VEVENT, ITEMLINE,
+ _("only one description allowed."));
+ goto skip;
+ }
+ vevent.desc = note;
+ break;
+ case LOCATION:
+ if (vevent.loc) {
+ ical_log(log, ICAL_VEVENT, ITEMLINE,
+ _("only one location allowed."));
+ goto skip;
+ }
+ vevent.loc = note;
+ break;
+ case COMMENT:
+ /* There may be more than one. */
+ if (vevent.comm) {
+ asprintf(&p, "%sComment: %s",
+ vevent.comm, note);
+ mem_free(vevent.comm);
+ vevent.comm = p;
+ } else
+ vevent.comm = note;
+ break;
+ default:
+ break;
}
}
-
ical_log(log, ICAL_VEVENT, ITEMLINE,
_("The ical file seems to be malformed. "
"The end of item was not found."));
-
+ skip:
+ (*noskipped)++;
cleanup:
-
- if (vevent.note)
- mem_free(vevent.note);
+ if (dtstart)
+ mem_free(dtstart);
+ if (dtend)
+ mem_free(dtend);
+ if (duration)
+ mem_free(duration);
+ if (rrule)
+ mem_free(rrule);
+ if (has_exdate)
+ mem_free(exdate.buf);
+ if (note)
+ mem_free(note);
+ if (vevent.desc)
+ mem_free(vevent.desc);
+ if (vevent.loc)
+ mem_free(vevent.loc);
+ if (vevent.comm)
+ mem_free(vevent.comm);
+ if (vevent.imp)
+ mem_free(vevent.imp);
if (vevent.mesg)
mem_free(vevent.mesg);
if (vevent.rpt)
mem_free(vevent.rpt);
LLIST_FREE(&vevent.exc);
- (*noskipped)++;
}
static void
ical_read_todo(FILE * fdi, FILE * log, unsigned *notodos, unsigned *noskipped,
char *buf, char *lstore, unsigned *lineno, const char *fmt_todo)
{
- const int ITEMLINE = *lineno;
+ const int ITEMLINE = *lineno - !feof(fdi);
+ ical_property_e property;
+ char *p, *note;
+ struct string s;
struct {
- char *mesg, *note;
+ char *mesg, *desc, *loc, *comm, *note;
int priority;
int completed;
} vtodo;
- int skip_alarm;
+ int skip_alarm, has_note, separator;
memset(&vtodo, 0, sizeof vtodo);
- skip_alarm = 0;
+ note = NULL;
+ skip_alarm = has_note = separator = 0;
while (ical_readline(fdi, buf, lstore, lineno)) {
+ note = NULL;
+ property = NO_PROPERTY;
if (skip_alarm) {
/*
* Need to skip VALARM properties because some keywords
@@ -1072,54 +1745,128 @@ ical_read_todo(FILE * fdi, FILE * log, unsigned *notodos, unsigned *noskipped,
skip_alarm = 0;
continue;
}
-
if (starts_with_ci(buf, "END:VTODO")) {
if (!vtodo.mesg) {
ical_log(log, ICAL_VTODO, ITEMLINE,
_("could not retrieve item summary."));
goto cleanup;
}
-
+ if (has_note) {
+ /* Construct string with note file contents. */
+ string_init(&s);
+ if (vtodo.desc) {
+ string_catf(&s, "%s", vtodo.desc);
+ mem_free(vtodo.desc);
+ vtodo.desc = NULL;
+ }
+ if (separator)
+ string_catf(&s, SEPARATOR);
+ if (vtodo.loc) {
+ string_catf(&s, _("Location: %s"),
+ vtodo.loc);
+ mem_free(vtodo.loc);
+ vtodo.loc = NULL;
+ }
+ if (vtodo.comm) {
+ string_catf(&s, _("Comment: %s"),
+ vtodo.comm);
+ mem_free(vtodo.comm);
+ vtodo.comm = NULL;
+ }
+ vtodo.note = generate_note(string_buf(&s));
+ mem_free(s.buf);
+ }
ical_store_todo(vtodo.priority, vtodo.completed,
vtodo.mesg, vtodo.note, fmt_todo);
(*notodos)++;
return;
}
-
if (starts_with_ci(buf, "PRIORITY:")) {
sscanf(buf, "PRIORITY:%d\n", &vtodo.priority);
if (vtodo.priority < 0 || vtodo.priority > 9) {
ical_log(log, ICAL_VTODO, ITEMLINE,
_("item priority is invalid "
"(must be between 0 and 9)."));
+ goto skip;
}
} else if (starts_with_ci(buf, "STATUS:COMPLETED")) {
vtodo.completed = 1;
} else if (starts_with_ci(buf, "SUMMARY")) {
- vtodo.mesg = ical_read_summary(buf);
+ vtodo.mesg =
+ ical_read_summary(buf, noskipped, ICAL_VTODO,
+ ITEMLINE, log);
+ if (!vtodo.mesg)
+ goto cleanup;
} else if (starts_with_ci(buf, "BEGIN:VALARM")) {
skip_alarm = 1;
} else if (starts_with_ci(buf, "DESCRIPTION")) {
- vtodo.note = ical_read_note(buf, noskipped, ICAL_VTODO,
- ITEMLINE, log);
+ property = DESCRIPTION;
+ } else if (starts_with_ci(buf, "LOCATION")) {
+ property = LOCATION;
+ } else if (starts_with_ci(buf, "COMMENT")) {
+ property = COMMENT;
+ }
+ if (property) {
+ note = ical_read_note(buf, property, noskipped,
+ ICAL_VTODO, ITEMLINE, log);
+ if (!note)
+ goto cleanup;
+ if (!separator)
+ separator = (property != DESCRIPTION);
+ has_note = 1;
+ }
+ switch (property) {
+ case DESCRIPTION:
+ if (vtodo.desc) {
+ ical_log(log, ICAL_VTODO, ITEMLINE,
+ _("only one description allowed."));
+ goto skip;
+ }
+ vtodo.desc = note;
+ break;
+ case LOCATION:
+ if (vtodo.loc) {
+ ical_log(log, ICAL_VTODO, ITEMLINE,
+ _("only one location allowed."));
+ goto skip;
+ }
+ vtodo.loc = note;
+ break;
+ case COMMENT:
+ /* There may be more than one. */
+ if (vtodo.comm) {
+ asprintf(&p, "%sComment: %s",
+ vtodo.comm, note);
+ mem_free(vtodo.comm);
+ vtodo.comm = p;
+ } else
+ vtodo.comm = note;
+ break;
+ default:
+ break;
}
}
-
ical_log(log, ICAL_VTODO, ITEMLINE,
_("The ical file seems to be malformed. "
"The end of item was not found."));
-
+ skip:
+ (*noskipped)++;
cleanup:
- if (vtodo.note)
- mem_free(vtodo.note);
+ if (note)
+ mem_free(note);
+ if (vtodo.desc)
+ mem_free(vtodo.desc);
+ if (vtodo.loc)
+ mem_free(vtodo.loc);
+ if (vtodo.comm)
+ mem_free(vtodo.comm);
if (vtodo.mesg)
mem_free(vtodo.mesg);
- (*noskipped)++;
}
/* Import calcurse data. */
void
-ical_import_data(FILE * stream, FILE * log, unsigned *events,
+ical_import_data(const char *file, FILE * stream, FILE * log, unsigned *events,
unsigned *apoints, unsigned *todos, unsigned *lines,
unsigned *skipped, const char *fmt_ev, const char *fmt_rev,
const char *fmt_apt, const char *fmt_rapt,
@@ -1134,10 +1881,9 @@ ical_import_data(FILE * stream, FILE * log, unsigned *events,
_("Warning: ical header malformed or wrong version number. "
"Aborting..."));
- ical_log_init(log, major, minor);
+ ical_log_init(file, log, major, minor);
while (ical_readline(stream, buf, lstore, lines)) {
- (*lines)++;
if (starts_with_ci(buf, "BEGIN:VEVENT")) {
ical_read_event(stream, log, events, apoints,
skipped, buf, lstore, lines, fmt_ev,
diff --git a/src/io.c b/src/io.c
index 76d4490..d596aab 100644
--- a/src/io.c
+++ b/src/io.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -50,8 +50,8 @@
struct ht_keybindings_s {
const char *label;
- enum key key;
- HTABLE_ENTRY(ht_keybindings_s);
+ enum vkey key;
+ HTABLE_ENTRY(ht_keybindings_s);
};
static void load_keys_ht_getkey(struct ht_keybindings_s *, const char **,
@@ -237,25 +237,25 @@ void io_dump_apts(const char *fmt_apt, const char *fmt_rapt,
LLIST_FOREACH(&recur_elist, i) {
struct recur_event *rev = LLIST_GET_DATA(i);
- time_t day = update_time_in_date(rev->day, 0, 0);
+ time_t day = DAY(rev->day);
print_recur_event(fmt_rev, day, rev);
}
LLIST_TS_FOREACH(&recur_alist_p, i) {
struct recur_apoint *rapt = LLIST_GET_DATA(i);
- time_t day = update_time_in_date(rapt->start, 0, 0);
+ time_t day = DAY(rapt->start);
print_recur_apoint(fmt_rapt, day, rapt->start, rapt);
}
LLIST_TS_FOREACH(&alist_p, i) {
struct apoint *apt = LLIST_TS_GET_DATA(i);
- time_t day = update_time_in_date(apt->start, 0, 0);
+ time_t day = DAY(apt->start);
print_apoint(fmt_apt, day, apt);
}
LLIST_FOREACH(&eventlist, i) {
struct event *ev = LLIST_TS_GET_DATA(i);
- time_t day = update_time_in_date(ev->day, 0, 0);
+ time_t day = DAY(ev->day);
print_event(fmt_ev, day, ev);
}
}
@@ -553,13 +553,13 @@ void io_load_app(struct item_filter *filter)
FILE *data_file;
int c, is_appointment, is_event, is_recursive;
struct tm start, end, until, lt;
- llist_t exc;
+ struct rpt rpt;
time_t t;
int id = 0;
- int freq;
char type, state = 0L;
char note[MAX_NOTESIZ + 1], *notep;
unsigned line = 0;
+ char *scan_error;
t = time(NULL);
localtime_r(&t, &lt);
@@ -572,9 +572,10 @@ void io_load_app(struct item_filter *filter)
rewind(data_file);
for (;;) {
- LLIST_INIT(&exc);
is_appointment = is_event = is_recursive = 0;
line++;
+ scan_error = NULL;
+
c = getc(data_file);
if (c == EOF)
break;
@@ -630,102 +631,113 @@ void io_load_app(struct item_filter *filter)
if (c == '{') {
is_recursive = 1;
- if (fscanf(data_file, " %d%c ", &freq, &type) != 2)
+ if (fscanf(data_file, " %d%c ", &rpt.freq, &type) != 2)
io_load_error(path_apts, line,
_("syntax error in item repetition"));
-
+ else
+ rpt.type = recur_char2def(type);
c = getc(data_file);
- if (c == '}') { /* endless recurrent item */
- until.tm_year = 0;
- while ((c = getc(data_file)) == ' ') ;
- ungetc(c, data_file);
- } else if (c == '-' && getc(data_file) == '>') {
+ /* Optional until date */
+ if (c == '-' && getc(data_file) == '>') {
if (fscanf
(data_file, " %d / %d / %d ",
&until.tm_mon, &until.tm_mday,
&until.tm_year) != 3)
io_load_error(path_apts, line,
- _("syntax error in item repetition"));
+ _("syntax error in until date"));
+ if (!check_date(until.tm_year, until.tm_mon,
+ until.tm_mday))
+ io_load_error(path_apts, line,
+ _("until date error"));
+ until.tm_hour = 0;
+ until.tm_min = 0;
+ until.tm_sec = 0;
+ until.tm_isdst = -1;
+ until.tm_year -= 1900;
+ until.tm_mon--;
+ rpt.until = mktime(&until);
c = getc(data_file);
- if (c == '!') {
- ungetc(c, data_file);
- recur_exc_scan(&exc, data_file);
- while ((c =
- getc(data_file)) == ' ') ;
- ungetc(c, data_file);
- } else if (c == '}') {
- while ((c =
- getc(data_file)) == ' ') ;
- ungetc(c, data_file);
- } else {
+ } else
+ rpt.until = 0;
+ /* Optional bymonthday list */
+ if (c == 'd') {
+ if (rpt.type == RECUR_WEEKLY)
io_load_error(path_apts, line,
- _("syntax error in item repetition"));
- }
- } else if (c == '!') { /* endless item with exceptions */
+ _("BYMONTHDAY illegal with WEEKLY"));
ungetc(c, data_file);
- recur_exc_scan(&exc, data_file);
- while ((c = getc(data_file)) == ' ') ;
+ recur_bymonthday(&rpt.bymonthday, data_file);
+ c = getc(data_file);
+ } else
+ LLIST_INIT(&rpt.bymonthday);
+ /* Optional bywday list */
+ if (c == 'w') {
ungetc(c, data_file);
- until.tm_year = 0;
- } else {
+ recur_bywday(rpt.type, &rpt.bywday, data_file);
+ c = getc(data_file);
+ } else
+ LLIST_INIT(&rpt.bywday);
+ /* Optional bymonth list */
+ if (c == 'm') {
+ ungetc(c, data_file);
+ recur_bymonth(&rpt.bymonth, data_file);
+ c = getc(data_file);
+ } else
+ LLIST_INIT(&rpt.bymonth);
+ /* Optional exception dates */
+ if (c == '!') {
+ ungetc(c, data_file);
+ recur_exc_scan(&rpt.exc, data_file);
+ c = getc(data_file);
+ } else
+ LLIST_INIT(&rpt.exc);
+ /* End of recurrence rule */
+ if (c != '}')
io_load_error(path_apts, line,
- _("wrong format in the appointment or event"));
- /* NOTREACHED */
- }
- } else {
- ungetc(c, data_file);
+ _("missing end of recurrence"));
+ while ((c = getc(data_file)) == ' ') ;
}
/* Check if a note is attached to the item. */
- c = getc(data_file);
if (c == '>') {
note_read(note, data_file);
+ c = getc(data_file);
notep = note;
- } else {
+ } else
notep = NULL;
- ungetc(c, data_file);
- }
/*
* Last: read the item description and load it into its
* corresponding linked list, depending on the item type.
*/
if (is_appointment) {
- c = getc(data_file);
- if (c == '!') {
+ if (c == '!')
state |= APOINT_NOTIFY;
- while ((c = getc(data_file)) == ' ') ;
- ungetc(c, data_file);
- } else if (c == '|') {
+ else if (c == '|')
state = 0L;
- while ((c = getc(data_file)) == ' ') ;
- ungetc(c, data_file);
- } else {
+ else
io_load_error(path_apts, line,
- _("syntax error in item repetition"));
- }
- if (is_recursive) {
- recur_apoint_scan(data_file, start, end,
- type, freq, until, notep,
- &exc, state, filter);
- } else {
- apoint_scan(data_file, start, end, state,
+ _("syntax error in item state"));
+
+ if (is_recursive)
+ scan_error = recur_apoint_scan(data_file, start, end, state,
+ notep, filter, &rpt);
+ else
+ scan_error = apoint_scan(data_file, start, end, state,
notep, filter);
- }
} else if (is_event) {
- if (is_recursive) {
- recur_event_scan(data_file, start, id,
- type, freq, until, notep,
- &exc, filter);
- } else {
- event_scan(data_file, start, id, notep,
- filter);
- }
+ ungetc(c, data_file);
+ if (is_recursive)
+ scan_error = recur_event_scan(data_file, start, id, notep,
+ filter, &rpt);
+ else
+ scan_error = event_scan(data_file, start, id, notep, filter);
} else {
io_load_error(path_apts, line,
_("wrong format in the appointment or event"));
/* NOTREACHED */
}
+ if (scan_error)
+ io_load_error(path_apts, line, scan_error);
}
file_close(data_file, __FILE_POS__);
}
@@ -928,16 +940,6 @@ load_keys_ht_compare(struct ht_keybindings_s *data1,
}
/*
- * isblank(3) is protected by the __BSD_VISIBLE macro and this fails to be
- * visible in some specific cases. Thus replace it by the following is_blank()
- * function.
- */
-static int is_blank(int c)
-{
- return c == ' ' || c == '\t';
-}
-
-/*
* Load user-definable keys from file.
* A hash table is used to speed up loading process in avoiding string
* comparisons.
@@ -946,21 +948,21 @@ static int is_blank(int c)
*/
void io_load_keys(const char *pager)
{
- struct ht_keybindings_s keys[NBKEYS];
+ struct ht_keybindings_s virt_keys[NBVKEYS], *ht_elm, ht_entry;
FILE *keyfp;
- char buf[BUFSIZ];
+ char buf[BUFSIZ], key_label[BUFSIZ], key_str[BUFSIZ];
+ char *p, *msg;
struct io_file *log;
- int i, skipped, loaded, line;
- const int MAX_ERRORS = 5;
+ int i, n, skipped, loaded, line, assigned, undefined, key;
keys_init();
struct ht_keybindings ht_keys = HTABLE_INITIALIZER(&ht_keys);
- for (i = 0; i < NBKEYS; i++) {
- keys[i].key = (enum key)i;
- keys[i].label = keys_get_label((enum key)i);
- HTABLE_INSERT(ht_keybindings, &ht_keys, &keys[i]);
+ for (i = 0; i < NBVKEYS; i++) {
+ virt_keys[i].key = (enum vkey)i;
+ virt_keys[i].label = keys_get_label((enum vkey)i);
+ HTABLE_INSERT(ht_keybindings, &ht_keys, &virt_keys[i]);
}
keyfp = fopen(path_keys, "r");
@@ -969,111 +971,97 @@ void io_load_keys(const char *pager)
log = io_log_init();
skipped = loaded = line = 0;
while (fgets(buf, BUFSIZ, keyfp) != NULL) {
- char key_label[BUFSIZ], *p;
- struct ht_keybindings_s *ht_elm, ht_entry;
- const int AWAITED = 1;
- int assigned;
-
line++;
- if (skipped > MAX_ERRORS) {
- const char *too_many =
- _("\nToo many errors while reading configuration file!\n"
- "Please backup your keys file, remove it from directory, "
- "and launch calcurse again.\n");
-
- io_log_print(log, line, too_many);
- break;
- }
- for (p = buf; is_blank((int)*p); p++) ;
- if (p != buf)
- memmove(buf, p, strlen(p));
- if (buf[0] == '#' || buf[0] == '\n')
+ p = buf;
+ while (*p == ' ' || *p == '\t') p++;
+ if (*p == '#' || *p == '\n')
continue;
- if (sscanf(buf, "%s", key_label) != AWAITED) {
+ /* Find the virtual key by key label. */
+ if (sscanf(p, "%s", key_label) != 1) {
skipped++;
io_log_print(log, line,
_("Could not read key label"));
continue;
}
-
- /* Skip legacy entries. */
- if (strcmp(key_label, "generic-cut") == 0)
- continue;
-
+ p += strlen(key_label);
ht_entry.label = key_label;
- p = buf + strlen(key_label) + 1;
- ht_elm =
- HTABLE_LOOKUP(ht_keybindings, &ht_keys, &ht_entry);
+ ht_elm = HTABLE_LOOKUP(ht_keybindings, &ht_keys, &ht_entry);
if (!ht_elm) {
skipped++;
- io_log_print(log, line,
- _("Key label not recognized"));
+ asprintf(&msg,
+ _("Key label not recognized: \"%s\""),
+ key_label);
+ io_log_print(log, line, msg);
+ mem_free(msg);
continue;
}
- assigned = 0;
- for (;;) {
- char key_ch[BUFSIZ], tmpbuf[BUFSIZ];
-
- while (*p == ' ')
- p++;
- (void)strncpy(tmpbuf, p, BUFSIZ);
- tmpbuf[BUFSIZ - 1] = '\0';
- if (sscanf(tmpbuf, "%s", key_ch) == AWAITED) {
- int ch;
-
- if ((ch = keys_str2int(key_ch)) < 0) {
- char *unknown_key;
+ /* Assign keyboard keys to the virtual key. */
+ assigned = undefined = 0;
+ for (;;) {
+ if (sscanf(p, "%s%n", key_str, &n) != 1) {
+ if (assigned || undefined)
+ loaded++;
+ else {
skipped++;
- asprintf(&unknown_key,
- _("Error reading key: \"%s\""),
- key_ch);
- io_log_print(log, line, unknown_key);
- mem_free(unknown_key);
- } else {
- int used;
-
- used =
- keys_assign_binding(ch,
- ht_elm->
- key);
- if (used) {
- char *already_assigned;
-
- skipped++;
- asprintf(&already_assigned,
- _("\"%s\" assigned multiple times!"),
- key_ch);
- io_log_print(log, line,
- already_assigned);
- mem_free(already_assigned);
- } else {
- assigned++;
- }
+ asprintf(&msg,
+ _("No keys assigned to "
+ "\"%s\"."),
+ key_label);
+ io_log_print(log, line, msg);
+ mem_free(msg);
}
- p += strlen(key_ch) + 1;
- } else {
- if (assigned)
- loaded++;
break;
}
+ p += n;
+ if (!strcmp(key_str, "UNDEFINED")) {
+ undefined++;
+ keys_assign_binding(-1, ht_elm->key);
+ } else if ((key = keys_str2int(key_str)) < 0) {
+ skipped++;
+ asprintf(&msg,
+ _("Keyname not recognized: \"%s\""),
+ key_str);
+ io_log_print(log, line, msg);
+ mem_free(msg);
+ } else if (keys_assign_binding(key, ht_elm->key)) {
+ skipped++;
+ asprintf(&msg,
+ _("\"%s\" assigned twice: \"%s\"."),
+ key_str, key_label);
+ io_log_print(log, line, msg);
+ mem_free(msg);
+ } else
+ assigned++;
}
}
file_close(keyfp, __FILE_POS__);
+ if (loaded < NBVKEYS && (i = keys_fill_missing()) < 1) {
+ skipped++;
+ strcpy(key_label, keys_get_label((enum vkey)(-i)));
+ strcpy(key_str, keys_get_binding((enum vkey)(-i)));
+ asprintf(&msg, _("Action \"%s\" absent, but default key \"%s\" "
+ "assigned to another action."),
+ key_label, key_str);
+ io_log_print(log, line, msg);
+ mem_free(msg);
+ }
file_close(log->fd, __FILE_POS__);
if (skipped > 0) {
- const char *view_log =
- _("There were some errors when loading keys file.");
- io_log_display(log, view_log, pager);
+ msg = _("Errors in the keys file.");
+ io_log_display(log, msg, pager);
+ WARN_MSG(_("Remove offending line(s) from the keys file, "
+ "aborting..."));
+ exit_calcurse(EXIT_FAILURE);
}
io_log_free(log);
- EXIT_IF(skipped > MAX_ERRORS,
- _("Too many errors while reading keys file, aborting..."));
- if (loaded < NBKEYS)
- keys_fill_missing();
- if (keys_check_missing_bindings())
- WARN_MSG(_("Some actions do not have any associated key bindings!"));
+ /* Default keys were inserted. */
+ if (loaded < NBVKEYS)
+ io_save_keys();
+ /* Should never occur. */
+ EXIT_IF(keys_check_missing(),
+ _("Some actions do not have any associated key bindings!"));
}
int io_check_dir(const char *dir)
@@ -1195,21 +1183,6 @@ int io_check_data_files(void)
return missing;
}
-/* Draw the startup screen */
-void io_startup_screen(int no_data_file)
-{
- const char *enter = _("Press [ENTER] to continue");
-
- if (no_data_file)
- status_mesg(_("Welcome to Calcurse. Missing data files were created."),
- enter);
- else
- status_mesg(_("Data files found. Data will be loaded now."),
- enter);
-
- keys_wait_for_any_key(win[KEY].p);
-}
-
/* Export calcurse data. */
void io_export_data(enum export_type type, int export_uid)
{
@@ -1240,38 +1213,36 @@ void io_export_data(enum export_type type, int export_uid)
else if (type == IO_EXPORT_PCAL)
pcal_export_data(stream);
- if (show_dialogs() && ui_mode == UI_CURSES) {
+ if (!quiet && ui_mode == UI_CURSES) {
fclose(stream);
status_mesg(success, enter);
keys_wait_for_any_key(win[KEY].p);
}
}
-static FILE *get_import_stream(enum import_type type)
+static FILE *get_import_stream(enum import_type type, char **stream_name)
{
FILE *stream = NULL;
- char *stream_name;
const char *ask_fname =
_("Enter the file name to import data from:");
const char *wrong_file =
_("The file cannot be accessed, please enter another file name.");
const char *press_enter = _("Press [ENTER] to continue.");
- stream_name = mem_malloc(BUFSIZ);
- memset(stream_name, 0, BUFSIZ);
+ *stream_name = mem_malloc(BUFSIZ);
+ memset(*stream_name, 0, BUFSIZ);
while (stream == NULL) {
status_mesg(ask_fname, "");
- if (updatestring(win[STA].p, &stream_name, 0, 1)) {
- mem_free(stream_name);
+ if (updatestring(win[STA].p, stream_name, 0, 1)) {
+ mem_free(*stream_name);
return NULL;
}
- stream = fopen(stream_name, "r");
+ stream = fopen(*stream_name, "r");
if (stream == NULL) {
status_mesg(wrong_file, press_enter);
keys_wait_for_any_key(win[KEY].p);
}
}
- mem_free(stream_name);
return stream;
}
@@ -1282,7 +1253,7 @@ static FILE *get_import_stream(enum import_type type)
* A temporary log file is created in /tmp to store the import process report,
* and is cleared at the end.
*/
-void io_import_data(enum import_type type, const char *stream_name,
+int io_import_data(enum import_type type, char *stream_name,
const char *fmt_ev, const char *fmt_rev,
const char *fmt_apt, const char *fmt_rapt,
const char *fmt_todo)
@@ -1309,7 +1280,7 @@ void io_import_data(enum import_type type, const char *stream_name,
"Aborting..."));
break;
case UI_CURSES:
- stream = get_import_stream(type);
+ stream = get_import_stream(type, &stream_name);
break;
default:
EXIT(_("FATAL ERROR: wrong import mode"));
@@ -1317,7 +1288,7 @@ void io_import_data(enum import_type type, const char *stream_name,
}
if (stream == NULL)
- return;
+ return 0;
memset(&stats, 0, sizeof stats);
@@ -1325,11 +1296,11 @@ void io_import_data(enum import_type type, const char *stream_name,
if (log == NULL) {
if (stream != stdin)
file_close(stream, __FILE_POS__);
- return;
+ return 0;
}
if (type == IO_IMPORT_ICAL)
- ical_import_data(stream, log->fd, &stats.events,
+ ical_import_data(stream_name, stream, log->fd, &stats.events,
&stats.apoints, &stats.todos,
&stats.lines, &stats.skipped, fmt_ev, fmt_rev,
fmt_apt, fmt_rapt, fmt_todo);
@@ -1350,7 +1321,7 @@ void io_import_data(enum import_type type, const char *stream_name,
stats.todos);
asprintf(&stats_str[3], _("%d skipped"), stats.skipped);
- if (ui_mode == UI_CURSES && show_dialogs()) {
+ if (ui_mode == UI_CURSES && !quiet) {
char *read, *stat;
asprintf(&read, proc_report, stats.lines);
@@ -1361,7 +1332,7 @@ void io_import_data(enum import_type type, const char *stream_name,
mem_free(read);
mem_free(stat);
keys_wait_for_any_key(win[KEY].p);
- } else if (ui_mode == UI_CMDLINE && show_dialogs()) {
+ } else if (ui_mode == UI_CMDLINE && !quiet) {
printf(proc_report, stats.lines);
printf("\n%s / %s / %s / %s\n", stats_str[0], stats_str[1],
stats_str[2], stats_str[3]);
@@ -1380,7 +1351,13 @@ void io_import_data(enum import_type type, const char *stream_name,
mem_free(stats_str[1]);
mem_free(stats_str[2]);
mem_free(stats_str[3]);
- io_log_free(log);
+ if (ui_mode == UI_CURSES)
+ mem_free(stream_name);
+ if (!stats.skipped) {
+ io_log_free(log);
+ return 1;
+ } else
+ return 0;
}
struct io_file *io_log_init(void)
@@ -1398,7 +1375,7 @@ struct io_file *io_log_init(void)
ERROR_MSG(_("Warning: could not create temporary log file, Aborting..."));
goto error;
}
- strncpy(log->name, logname, sizeof(log->name));
+ log->name = mem_strdup(logname);
log->fd = fopen(log->name, "w");
if (log->fd == NULL) {
ERROR_MSG(_("Warning: could not open temporary log file, Aborting..."));
@@ -1448,6 +1425,7 @@ void io_log_free(struct io_file *log)
EXIT_IF(unlink(log->name) != 0,
_("Warning: could not erase temporary log file %s, Aborting..."),
log->name);
+ mem_free(log->name);
mem_free(log);
}
@@ -1456,7 +1434,8 @@ static void *io_psave_thread(void *arg)
{
int delay = conf.periodic_save;
EXIT_IF(delay < 0, _("Invalid delay"));
- char *mesg = _("Periodic save: data files have changed. Save cancelled.");
+ char *mesg = _("Periodic save cancelled. Data files have changed. "
+ "Save and merge interactively");
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
for (;;) {
@@ -1576,22 +1555,6 @@ unsigned io_get_pid(char *file)
}
/*
- * Check whether a file is empty.
- */
-int io_file_is_empty(char *file)
-{
- FILE *fp;
- int ret = -1;
-
- if (file && (fp = fopen(file, "r"))) {
- ret = (fgetc(fp) == '\n' && fgetc(fp) == EOF) || feof(fp);
- fclose(fp);
- }
-
- return ret;
-}
-
-/*
* Check whether two files are equal.
*/
int io_files_equal(const char *file1, const char *file2)
diff --git a/src/keys.c b/src/keys.c
index b48aade..a5e9470 100644
--- a/src/keys.c
+++ b/src/keys.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -39,26 +39,73 @@
#include "calcurse.h"
-#define MAXKEYVAL KEY_MAX /* ncurses defines KEY_MAX as maximum key value */
-
-struct keydef_s {
- const char *label;
- const char *binding;
- const char *sb_label;
-};
+/*
+ * The interactive calcurse interface is controlled by "virtual keys", aka
+ * actions or commands. The virtual keys are defined by the type 'enum vkey',
+ * see calcurse.h. To each virtual key is assigned (or bound) zero or more
+ * keyboard keys/characters. A character (generated by a keyboard key) may be
+ * either an ordinary character or a pseudo-character. [An ordinary character
+ * is either a singlebyte ASCII character or a multibyte, UTF-8 encoded
+ * character; a pseudo-character (as supported by curses) is an escape sequence
+ * generated by a key.] A keyboard key/character is uniquely identified by its
+ * keyname (a character string) or by an integer (the Unicode code point of the
+ * character with a slight modification to accomodate the range of curses
+ * pseudo-characters). Mapping between the two forms is performed by the
+ * functions keys_str2int() and keys_int2str().
+ */
-static llist_t keys[NBKEYS];
-static enum key actions[MAXKEYVAL];
+/*
+ * Assignment of keys to virtual keys is held in the tabel keys[]. The entry for
+ * each virtual key is a linked list of keyboard keys (bindings); each list
+ * element is the keyname as returned by keys_int2str().
+ *
+ * At the very first run default keys are assigned to all virtual keys from a
+ * built-in table keydef[] and saved to disk in the calcurse config directory.
+ * Later the user may edit the key configuration and change the key bindings by
+ * adding/removing keys. If all keys are removed, the virtual key is left
+ * undefined. This state is also saved in the configuration file. The linked
+ * list for an undefined virtual key contains a single element with a null
+ * pointer as data.
+ */
+static llist_t keys[NBVKEYS];
+/*
+ * To cater for the other direction (which virtual key is a keyboard key
+ * assigned to), two constructions are needed: a table actions[] for the
+ * keyboard keys in the curses range, and a linked list actions_ext for
+ * multi-byte UTF-8 encoded keyboard characters.
+ *
+ * For each keyboard key (integer) in the curses key range, the virtual key
+ * (action) it is assigned to or, if not assigned, KEY_UNDEF.
+ */
+static enum vkey actions[KEY_MAX];
+/*
+ * For the millions of possible keyboard keys above the curses range, a linked
+ * list of keys which are actually bound to a virtual key.
+ * Each list element is a key_ext structure.
+ */
+llist_t actions_ext;
struct key_ext {
- int ch;
- enum key action;
+ int key;
+ enum vkey action;
};
-llist_t actions_ext;
+/*
+ * Assigning a keyboard key to a virtual key is accomplished by
+ * 1) either inserting the virtual key in the actions[] entry for the keyboard key
+ * or adding the pair (key, virtual key) to the list actions_ext
+ * 2) adding it in keys[] to the list for the virtual key
+ * See keys_assign_binding() below.
+ */
+/* The default key bindings for the virtual keys. */
+struct keydef_s {
+ const char *label; /* Name of the virtual key (action). */
+ const char *binding; /* String of space-separated keynames bound to it. */
+ const char *sb_label; /* Display name in the status bar menu. */
+};
#define gettext_noop(s) s
-static struct keydef_s keydef[NBKEYS] = {
+static struct keydef_s keydef[NBVKEYS] = {
{ "generic-cancel", "ESC", gettext_noop("Cancel") },
{ "generic-select", "SPC", gettext_noop("Select") },
{ "generic-credits", "@", gettext_noop("Credits") },
@@ -69,6 +116,7 @@ static struct keydef_s keydef[NBKEYS] = {
{ "generic-copy", "c", gettext_noop("Copy") },
{ "generic-paste", "p ^V", gettext_noop("Paste") },
{ "generic-change-view", "TAB", gettext_noop("Chg Win") },
+ { "generic-prev-view", "KEY_BTAB", gettext_noop("Prev Win") },
{ "generic-import", "i I", gettext_noop("Import") },
{ "generic-export", "x X", gettext_noop("Export") },
{ "generic-goto", "g G", gettext_noop("Go to") },
@@ -114,6 +162,47 @@ static struct keydef_s keydef[NBKEYS] = {
*/
static char *keynames[KEY_MAX];
+/* Maps a key code to a custom key name */
+struct custom_keyname_s {
+ int keycode;
+ char* keyname;
+};
+
+#define CUSTOM_KEYS 26
+
+/*
+ * Customized key names with calcurse short forms
+ */
+static struct custom_keyname_s custom_keynames[CUSTOM_KEYS] = {
+ { TAB, "TAB" },
+ { RETURN, "RET" },
+ { ESCAPE, "ESC" },
+ { SPACE, "SPC" },
+ { KEY_UP, "UP" },
+ { KEY_DOWN, "DWN" },
+ { KEY_LEFT, "LFT" },
+ { KEY_RIGHT, "RGT" },
+ { KEY_HOME, "HOM" },
+ { KEY_END, "END" },
+ { KEY_NPAGE, "PgD" },
+ { KEY_PPAGE, "PgU" },
+ { KEY_IC, "INS" },
+ { KEY_DC, "DEL" },
+ { KEY_F(1), "F1" },
+ { KEY_F(2), "F2" },
+ { KEY_F(3), "F3" },
+ { KEY_F(4), "F4" },
+ { KEY_F(5), "F5" },
+ { KEY_F(6), "F6" },
+ { KEY_F(7), "F7" },
+ { KEY_F(8), "F8" },
+ { KEY_F(9), "F9" },
+ { KEY_F(10), "F10" },
+ { KEY_F(11), "F11" },
+ { KEY_F(12), "F12" },
+};
+
+
static void dump_intro(FILE * fd)
{
const char *intro =
@@ -127,15 +216,26 @@ static void dump_intro(FILE * fd)
fprintf(fd, "%s\n", intro);
}
+static bool is_customized(int c) {
+ int i;
+
+ for (i = 0; i < CUSTOM_KEYS; i++)
+ if (c == custom_keynames[i].keycode)
+ return true;
+
+ return false;
+}
+
void keys_init(void)
{
int i;
const char *cp;
- for (i = 0; i < MAXKEYVAL; i++)
+ /* All keys unassigned. */
+ for (i = 0; i < KEY_MAX; i++)
actions[i] = KEY_UNDEF;
LLIST_INIT(&actions_ext);
- for (i = 0; i < NBKEYS; i++)
+ for (i = 0; i < NBVKEYS; i++)
LLIST_INIT(&keys[i]);
/* Initialization of the keynames table. */
@@ -144,40 +244,20 @@ void keys_init(void)
/* Insertion of ncurses names in the ASCII range ... */
for (i = 1; i < 128; i++)
- if ((cp = keyname(i)))
- keynames[i] = mem_strdup(cp);
- /* ... and for the ncurses escape keys (pseudokeys). */
+ if (!is_customized(i))
+ if ((cp = keyname(i)))
+ keynames[i] = mem_strdup(cp);
+
+ /* ... and for the ncurses pseudo-characters. */
for (i = KEY_MIN; i < KEY_MAX; i++)
- if ((cp = keyname(i)))
- keynames[i] = mem_strdup(cp);
+ if (!is_customized(i))
+ if ((cp = keyname(i)))
+ keynames[i] = mem_strdup(cp);
/* Replace some with calcurse short forms. */
- keynames[TAB] = "TAB";
- keynames[RETURN] = "RET";
- keynames[ESCAPE] = "ESC";
- keynames[SPACE] = "SPC";
- keynames[KEY_UP] = "UP";
- keynames[KEY_DOWN] = "DWN";
- keynames[KEY_LEFT] = "LFT";
- keynames[KEY_RIGHT] = "RGT";
- keynames[KEY_HOME] = "HOM";
- keynames[KEY_END] = "END";
- keynames[KEY_NPAGE] = "PgD";
- keynames[KEY_PPAGE] = "PgU";
- keynames[KEY_IC] = "INS";
- keynames[KEY_DC] = "DEL";
- keynames[KEY_F(1)] = "F1";
- keynames[KEY_F(2)] = "F2";
- keynames[KEY_F(3)] = "F3";
- keynames[KEY_F(4)] = "F4";
- keynames[KEY_F(5)] = "F5";
- keynames[KEY_F(6)] = "F6";
- keynames[KEY_F(7)] = "F7";
- keynames[KEY_F(8)] = "F8";
- keynames[KEY_F(9)] = "F9";
- keynames[KEY_F(10)] = "F10";
- keynames[KEY_F(11)] = "F11";
- keynames[KEY_F(12)] = "F12";
+ for (i = 0; i < CUSTOM_KEYS; i++) {
+ keynames[custom_keynames[i].keycode] = custom_keynames[i].keyname;
+ }
}
static void key_free(char *s)
@@ -189,7 +269,7 @@ void keys_free(void)
{
int i;
- for (i = 0; i < NBKEYS; i++) {
+ for (i = 0; i < NBVKEYS; i++) {
LLIST_FREE_INNER(&keys[i], key_free);
LLIST_FREE(&keys[i]);
}
@@ -205,31 +285,40 @@ void keys_dump_defaults(char *file)
_("FATAL ERROR: could not create default keys file."));
dump_intro(fd);
- for (i = 0; i < NBKEYS; i++)
+ for (i = 0; i < NBVKEYS; i++)
fprintf(fd, "%s %s\n", keydef[i].label,
keydef[i].binding);
file_close(fd, __FILE_POS__);
}
-const char *keys_get_label(enum key key)
+const char *keys_get_label(enum vkey key)
{
EXIT_IF(key < 0
- || key > NBKEYS,
+ || key > NBVKEYS,
_("FATAL ERROR: key value out of bounds"));
return keydef[key].label;
}
+const char *keys_get_binding(enum vkey key)
+{
+ EXIT_IF(key < 0
+ || key > NBVKEYS,
+ _("FATAL ERROR: key value out of bounds"));
+
+ return keydef[key].binding;
+}
+
static int key_ext_hasch(struct key_ext *k, void *cbdata)
{
- return (k->ch == *((int *)cbdata));
+ return (k->key == *((int *)cbdata));
}
-enum key keys_get_action(int pressed)
+enum vkey keys_get_action(int pressed)
{
if (pressed < 0) {
return -1;
- } else if (pressed > MAXKEYVAL) {
+ } else if (pressed > KEY_MAX) {
llist_item_t *i = LLIST_FIND_FIRST(&actions_ext, &pressed,
key_ext_hasch);
if (!i)
@@ -274,7 +363,7 @@ void keys_wait_for_any_key(WINDOW *win)
keys_wgetch(win);
}
-enum key keys_get(WINDOW *win, int *count, int *reg)
+enum vkey keys_get(WINDOW *win, int *count, int *reg)
{
int ch = '0';
@@ -297,8 +386,6 @@ enum key keys_get(WINDOW *win, int *count, int *reg)
*reg = ch - '1' + 1;
} else if (ch >= 'a' && ch <= 'z') {
*reg = ch - 'a' + 10;
- } else if (ch == '_') {
- *reg = REG_BLACK_HOLE;
}
ch = keys_wgetch(win);
}
@@ -314,60 +401,89 @@ enum key keys_get(WINDOW *win, int *count, int *reg)
}
}
-static void add_key_str(enum key action, int key)
+static void add_if_undefined(enum vkey action)
{
- if (action > NBKEYS)
- return;
+ /* If list is empty, mark action as UNDEFINED. */
+ if (!keys[action].head)
+ LLIST_ADD(&keys[action], NULL);
+}
- LLIST_ADD(&keys[action], keys_int2str(key));
+static void del_if_undefined(enum vkey action)
+{
+ /* Action UNDEFINED? */
+ if (!LLIST_GET_DATA(LLIST_FIRST(&keys[action])))
+ LLIST_REMOVE(&keys[action], keys[action].head);
}
-int keys_assign_binding(int key, enum key action)
+static void free_key_str(char *str)
{
- if (key < 0)
- return 1;
- if (key > KEY_MAX) {
- llist_item_t *i = LLIST_FIND_FIRST(&actions_ext, &key, key_ext_hasch);
- if (i)
- return 1;
- struct key_ext *k = mem_malloc(sizeof(struct key_ext));
- k->ch = key;
- k->action = action;
- LLIST_ADD(&actions_ext, k);
- } else {
- if (actions[key] != KEY_UNDEF)
- return 1;
- actions[key] = action;
- }
- add_key_str(action, key);
- return 0;
+ mem_free(str);
}
-static void del_key_str(enum key action, int key)
+static void add_key_str(enum vkey action, int key)
+{
+ if (action > NBVKEYS)
+ return;
+
+ del_if_undefined(action);
+ LLIST_ADD(&keys[action], keys_int2str(key));
+}
+
+static void del_key_str(enum vkey action, int key)
{
llist_item_t *i;
- char *oldstr = keys_int2str(key);;
+ char *oldstr = keys_int2str(key), *j;
- if (action > NBKEYS)
+ if (action > NBVKEYS)
return;
LLIST_FOREACH(&keys[action], i) {
- if (strcmp(LLIST_GET_DATA(i), oldstr) == 0) {
+ if (strcmp((j = LLIST_GET_DATA(i)), oldstr) == 0) {
LLIST_REMOVE(&keys[action], i);
+ free_key_str(j);
goto cleanup;
}
}
cleanup:
+ add_if_undefined(action);
mem_free(oldstr);
}
-void keys_remove_binding(int key, enum key action)
+/*
+ * Assign keyboard key "key" to virtual key "action" by
+ *
+ * - marking keyboard key "key" as used for virtual key "actual"
+ * - adding "key" to the list of assigned keys for "action" in the tabel keys[]
+ *
+ * The former is done by either inserting "action" in the "key" entry of tabel
+ * actions[], or for keys above the curses range, inserting (key, action) in the
+ * list actions_ext.
+ */
+int keys_assign_binding(int key, enum vkey action)
+{
+ if (key > KEY_MAX) {
+ if (LLIST_FIND_FIRST(&actions_ext, &key, key_ext_hasch))
+ return 1;
+ struct key_ext *k = mem_malloc(sizeof(struct key_ext));
+ k->key = key;
+ k->action = action;
+ LLIST_ADD(&actions_ext, k);
+ } else if (key > -1) {
+ if (actions[key] != KEY_UNDEF)
+ return 1;
+ actions[key] = action;
+ }
+ add_key_str(action, key);
+ return 0;
+}
+
+void keys_remove_binding(int key, enum vkey action)
{
if (key < 0)
return;
- if (key <= MAXKEYVAL) {
+ if (key <= KEY_MAX) {
actions[key] = KEY_UNDEF;
} else {
llist_item_t *i = LLIST_FIND_FIRST(&actions_ext, &key,
@@ -412,6 +528,8 @@ char *keys_int2str(int key)
{
char *res;
+ if (key == -1)
+ return NULL;
if (key < KEY_MAX) {
if (strcmp(keynames[key], "") == 0)
return NULL;
@@ -423,50 +541,44 @@ char *keys_int2str(int key)
}
}
-int keys_action_count_keys(enum key action)
+int keys_action_count_keys(enum vkey action)
{
llist_item_t *i;
int n = 0;
+ /* Action UNDEFINED? */
+ if (!LLIST_GET_DATA(LLIST_FIRST(&keys[action])))
+ return 0;
+
LLIST_FOREACH(&keys[action], i)
- n++;
+ n++;
return n;
}
-const char *keys_action_firstkey(enum key action)
+const char *keys_action_firstkey(enum vkey action)
{
const char *s = LLIST_GET_DATA(LLIST_FIRST(&keys[action]));
return (s != NULL) ? s : "XXX";
}
-const char *keys_action_nkey(enum key action, int keynum)
+const char *keys_action_nkey(enum vkey action, int keynum)
{
return LLIST_GET_DATA(LLIST_NTH(&keys[action], keynum));
}
-char *keys_action_allkeys(enum key action)
+char *keys_action_allkeys(enum vkey action)
{
llist_item_t *i;
- static char keystr[BUFSIZ];
- int keystrlen = 0;
- int entrylen;
-
- if (!LLIST_FIRST(&keys[action]))
- return NULL;
-
- keystr[0] = '\0';
- LLIST_FOREACH(&keys[action], i) {
- entrylen = strlen(LLIST_GET_DATA(i)) + 1;
- if (keystrlen + entrylen >= BUFSIZ)
- break;
- memcpy(keystr + keystrlen, LLIST_GET_DATA(i), entrylen - 1);
- keystr[keystrlen + entrylen - 1] = ' ';
- keystrlen += entrylen;
- }
-
- keystr[keystrlen] = '\0';
- return keystr;
+ struct string keystr;
+
+ string_init(&keystr);
+ if (!LLIST_GET_DATA(LLIST_FIRST(&keys[action])))
+ string_catf(&keystr, "%s", "UNDEFINED");
+ else
+ LLIST_FOREACH(&keys[action], i)
+ string_catf(&keystr, "%s ", LLIST_GET_DATA(i));
+ return string_buf(&keystr);
}
/* Need this to display keys properly inside status bar. */
@@ -511,7 +623,7 @@ keys_display_bindings_bar(WINDOW * win, int *bindings, int count,
const char *label;
- if (binding_key < NBKEYS) {
+ if (binding_key < NBVKEYS) {
strncpy(key, keys_action_firstkey(binding_key), UTF8_MAXLEN);
key[UTF8_MAXLEN] = '\0';
label = gettext(keydef[binding_key].sb_label);
@@ -563,9 +675,9 @@ keys_display_bindings_bar(WINDOW * win, int *bindings, int count,
* Display information about the given key.
* (could not add the keys descriptions to keydef variable, because of i18n).
*/
-void keys_popup_info(enum key key)
+void keys_popup_info(enum vkey key)
{
- char *info[NBKEYS];
+ char *info[NBVKEYS];
WINDOW *infowin;
info[KEY_GENERIC_CANCEL] = _("Cancel the ongoing action.");
@@ -584,6 +696,8 @@ void keys_popup_info(enum key key)
_("Paste an item at the current position.");
info[KEY_GENERIC_CHANGE_VIEW] =
_("Select next panel in calcurse main screen.");
+ info[KEY_GENERIC_PREV_VIEW] =
+ _("Select previous panel in calcurse main screen.");
info[KEY_GENERIC_IMPORT] = _("Import data from an external file.");
info[KEY_GENERIC_EXPORT] = _("Export data to a new file format.");
info[KEY_GENERIC_GOTO] = _("Select the day to go to.");
@@ -653,7 +767,7 @@ void keys_popup_info(enum key key)
info[KEY_LOWER_PRIORITY] =
_("Lower a task priority inside the todo panel.");
- if (key > NBKEYS)
+ if (key > NBVKEYS)
return;
#define WINROW 10
@@ -670,59 +784,75 @@ void keys_popup_info(enum key key)
void keys_save_bindings(FILE * fd)
{
int i;
- char *action;
+ char *keys;
EXIT_IF(fd == NULL, _("FATAL ERROR: null file pointer."));
dump_intro(fd);
- for (i = 0; i < NBKEYS; i++) {
- action = keys_action_allkeys(i);
- if (action)
- fprintf(fd, "%s %s\n", keydef[i].label, action);
+ for (i = 0; i < NBVKEYS; i++) {
+ if ((keys = keys_action_allkeys(i)))
+ fprintf(fd, "%s %s\n", keydef[i].label, keys);
}
+ mem_free(keys);
}
-int keys_check_missing_bindings(void)
+int keys_check_undefined(void)
{
int i;
- for (i = 0; i < NBKEYS; i++) {
- if (!LLIST_FIRST(&keys[i]))
+ for (i = 0; i < NBVKEYS; i++) {
+ if (!LLIST_GET_DATA(LLIST_FIRST(&keys[i])))
return 1;
}
return 0;
}
-void keys_fill_missing(void)
+int keys_check_missing(void)
{
int i;
- for (i = 0; i < NBKEYS; i++) {
- if (!LLIST_FIRST(&keys[i])) {
- char *p, tmpbuf[BUFSIZ];
-
- strncpy(tmpbuf, keydef[i].binding, BUFSIZ);
- tmpbuf[BUFSIZ - 1] = '\0';
- p = tmpbuf;
- for (;;) {
- char key_ch[BUFSIZ];
-
- while (*p == ' ')
- p++;
- if (sscanf(p, "%s", key_ch) == 1) {
- int ch, used;
-
- ch = keys_str2int(key_ch);
- used = keys_assign_binding(ch, i);
- if (used)
- WARN_MSG(_("When adding default key for \"%s\", "
- "\"%s\" was already assigned!"),
- keydef[i].label,
- key_ch);
- p += strlen(key_ch);
- } else {
- break;
- }
- }
+ for (i = 0; i < NBVKEYS; i++) {
+ if (!LLIST_FIRST(&keys[i]))
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Insert default keybindings for missing actions.
+ * Return either the number of actions assigned to (on success) or, if default
+ * keys could not be assigned, the negative index into the keydef[] table of the
+ * failing action.
+ */
+int keys_fill_missing(void)
+{
+ int i, ch, assign, assigned;
+ char *p, key_ch[BUFSIZ];
+
+ for (i = assigned = 0; i < NBVKEYS; i++) {
+ if (LLIST_FIRST(&keys[i]))
+ continue;
+
+ p = (char *)keydef[i].binding;
+ for (assign = 0;;) {
+ while (*p == ' ')
+ p++;
+ if (sscanf(p, "%s", key_ch) == 1) {
+ ch = keys_str2int(key_ch);
+ if (keys_assign_binding(ch, i))
+ return -i;
+ else
+ assign = 1;
+ p += strlen(key_ch);
+ } else
+ break;
}
+ assigned += assign;
+ }
+
+ if (assigned) {
+ p = (assigned == 1) ? "": "s";
+ WARN_MSG(_("Default key(s) assigned to %d action%s."),
+ assigned, p);
}
+ return assigned;
}
diff --git a/src/listbox.c b/src/listbox.c
index 12c45cc..d86f540 100644
--- a/src/listbox.c
+++ b/src/listbox.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/src/llist.c b/src/llist.c
index 2248dc7..d31f004 100644
--- a/src/llist.c
+++ b/src/llist.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -109,6 +109,34 @@ llist_item_t *llist_next(llist_item_t * i)
}
/*
+ * Return the predecessor of a list item or, if head, the list item itself,
+ * or if not in the list, NULL.
+ * The list item may be supplied either directly (i) or as a pointer to
+ * the contents (data); the first case takes precedence.
+ */
+static llist_item_t *llist_prev(llist_t *l, llist_item_t *i, void *data)
+{
+ llist_item_t *j;
+
+ if (!i && !data)
+ return NULL;
+
+ if (l->head == i || l->head->data == data)
+ return l->head;
+
+ if (i) {
+ for (j = l->head; j; j = j->next)
+ if (j->next == i)
+ return j;
+ } else {
+ for (j = l->head; j && j->next; j = j->next)
+ if (j->next->data == data)
+ return j;
+ }
+ return NULL;
+}
+
+/*
* Return the successor of a list item if it is matched by some filter
* callback. Return NULL otherwise.
*/
@@ -150,34 +178,94 @@ void llist_add(llist_t * l, void *data)
}
/*
+ * Insert an existing item in a sorted list.
+ */
+static void llist_relink(llist_t *l, llist_item_t *i, llist_fn_cmp_t fn_cmp)
+{
+ llist_item_t *j;
+
+ if (!i)
+ return;
+
+ i->next = NULL;
+ if (!l->head) {
+ l->head = l->tail = i;
+ } else if (fn_cmp(i->data, l->tail->data) >= 0) {
+ l->tail->next = i;
+ l->tail = i;
+ } else if (fn_cmp(i->data, l->head->data) < 0) {
+ i->next = l->head;
+ l->head = i;
+ } else {
+ j = l->head;
+ while (j->next && fn_cmp(i->data, j->next->data) >= 0)
+ j = j->next;
+ i->next = j->next;
+ j->next = i;
+ }
+}
+
+/*
+ * Unlink an item from a list and return it.
+ */
+static llist_item_t *llist_unlink(llist_t *l, llist_item_t *i)
+{
+ llist_item_t *p;
+
+ if (!i)
+ return NULL;
+
+ p = llist_prev(l, i, NULL);
+ if (!p)
+ return NULL;
+
+ if (i == l->tail)
+ l->tail = (i == l->head) ? NULL : p;
+ if (i == l->head)
+ l->head = i->next;
+ else
+ p->next = i->next;
+ i->next = NULL;
+ return i;
+}
+
+/*
+ * Find an item matched by some filter callback; start from a specified item.
+ */
+static llist_item_t *llist_find_from(llist_item_t *i, void *data,
+ llist_fn_match_t fn_match)
+{
+ if (!i)
+ return NULL;
+
+ if (fn_match) {
+ for (; i; i = i->next) {
+ if (fn_match(i->data, data))
+ return i;
+ }
+ } else {
+ for (; i; i = i->next) {
+ if (i->data == data)
+ return i;
+ }
+ }
+
+ return NULL;
+}
+
+/*
* Add an item to a sorted list.
*/
void llist_add_sorted(llist_t * l, void *data, llist_fn_cmp_t fn_cmp)
{
llist_item_t *o = mem_malloc(sizeof(llist_item_t));
- llist_item_t *i;
if (o) {
o->data = data;
o->next = NULL;
-
- if (!l->head) {
- l->head = l->tail = o;
- } else if (fn_cmp(o->data, l->tail->data) >= 0) {
- l->tail->next = o;
- l->tail = o;
- } else if (fn_cmp(o->data, l->head->data) < 0) {
- o->next = l->head;
- l->head = o;
- } else {
- i = l->head;
- while (i->next
- && fn_cmp(o->data, i->next->data) >= 0)
- i = i->next;
- o->next = i->next;
- i->next = o;
- }
}
+
+ llist_relink(l, o, fn_cmp);
}
/*
@@ -209,21 +297,7 @@ void llist_remove(llist_t * l, llist_item_t * i)
llist_item_t *llist_find_first(llist_t * l, void *data,
llist_fn_match_t fn_match)
{
- llist_item_t *i;
-
- if (fn_match) {
- for (i = l->head; i; i = i->next) {
- if (fn_match(i->data, data))
- return i;
- }
- } else {
- for (i = l->head; i; i = i->next) {
- if (i->data == data)
- return i;
- }
- }
-
- return NULL;
+ return l ? llist_find_from(l->head, data, fn_match) : NULL;
}
/*
@@ -232,22 +306,7 @@ llist_item_t *llist_find_first(llist_t * l, void *data,
llist_item_t *llist_find_next(llist_item_t * i, void *data,
llist_fn_match_t fn_match)
{
- if (i) {
- i = i->next;
- if (fn_match) {
- for (; i; i = i->next) {
- if (fn_match(i->data, data))
- return i;
- }
- } else {
- for (; i; i = i->next) {
- if (i->data == data)
- return i;
- }
- }
- }
-
- return NULL;
+ return i ? llist_find_from(i->next, data, fn_match) : NULL;
}
/*
@@ -261,17 +320,42 @@ llist_item_t *llist_find_nth(llist_t * l, int n, void *data,
if (n < 0)
return NULL;
- if (fn_match) {
- for (i = l->head; i; i = i->next) {
- if (fn_match(i->data, data) && (n-- == 0))
- return i;
- }
- } else {
- for (i = l->head; i; i = i->next) {
- if ((i->data == data) && (n-- == 0))
- return i;
- }
+ for (i = l->head; i; i = i->next, n--) {
+ i = llist_find_from(i, data, fn_match);
+ if (!i || !n)
+ return i;
}
return NULL;
}
+
+/*
+ * Reorder a sorted linked list when an item has changed.
+ */
+void llist_reorder(llist_t *l, void *data, llist_fn_cmp_t fn_cmp)
+{
+ llist_item_t *o, *p;
+
+ if (!(p = llist_prev(l, NULL, data)))
+ return;
+
+ /* List head? */
+ if (p->data == data)
+ o = p;
+ else
+ o = p->next;
+
+ /* Sorted already?
+ * Note: p is either the previous element or o itself.
+ */
+ if (o->next &&
+ fn_cmp(p->data, o->data) <= 0 &&
+ fn_cmp(o->data, o->next->data) <= 0)
+ return;
+ if (!o->next &&
+ fn_cmp(p->data, o->data) <= 0)
+ return;
+
+ /* Link manipulation only. */
+ llist_relink(l, llist_unlink(l, o), fn_cmp);
+}
diff --git a/src/llist.h b/src/llist.h
index c9a6bc6..0dd15bf 100644
--- a/src/llist.h
+++ b/src/llist.h
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -99,8 +99,11 @@ void *llist_get_data(llist_item_t *);
void llist_add(llist_t *, void *);
void llist_add_sorted(llist_t *, void *, llist_fn_cmp_t);
void llist_remove(llist_t *, llist_item_t *);
+void llist_reorder(llist_t *, void *, llist_fn_cmp_t);
#define LLIST_ADD(l, data) llist_add(l, data)
#define LLIST_ADD_SORTED(l, data, fn_cmp) \
llist_add_sorted(l, data, (llist_fn_cmp_t)fn_cmp)
#define LLIST_REMOVE(l, i) llist_remove(l, i)
+#define LLIST_REORDER(l, data, fn_cmp) \
+ llist_reorder(l, data, (llist_fn_cmp_t)fn_cmp)
diff --git a/src/llist_ts.h b/src/llist_ts.h
index 4ca33df..a4b6184 100644
--- a/src/llist_ts.h
+++ b/src/llist_ts.h
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -90,3 +90,5 @@ struct llist_ts {
#define LLIST_TS_REMOVE(l_ts, i) llist_remove ((llist_t *)l_ts, i)
#define LLIST_TS_ADD_SORTED(l_ts, data, fn_cmp) \
llist_add_sorted ((llist_t *)l_ts, data, (llist_fn_cmp_t)fn_cmp)
+#define LLIST_TS_REORDER(l_ts, data, fn_cmp) \
+ llist_reorder((llist_t *)l_ts, data, (llist_fn_cmp_t)fn_cmp)
diff --git a/src/mem.c b/src/mem.c
index 043dfde..ce3cf80 100644
--- a/src/mem.c
+++ b/src/mem.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/src/note.c b/src/note.c
index 8d5d09a..655ad89 100644
--- a/src/note.c
+++ b/src/note.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -94,9 +94,7 @@ void edit_note(char **note, const char *editor)
const char *arg[] = { editor, tmppath, NULL };
wins_launch_external(arg);
- if (io_file_is_empty(tmppath) > 0) {
- erase_note(note);
- } else if ((fp = fopen(tmppath, "r"))) {
+ if ((fp = fopen(tmppath, "r"))) {
sha1_stream(fp, sha1);
fclose(fp);
*note = sha1;
@@ -155,6 +153,17 @@ void note_read(char *buffer, FILE * fp)
buffer[MAX_NOTESIZ] = '\0';
}
+/* Read the contents of a note file */
+void note_read_contents(char *buffer, size_t buffer_len, FILE * fp)
+{
+ size_t read_count = fread(buffer, 1, buffer_len, fp);
+ if (read_count != buffer_len)
+ buffer[read_count] = '\0';
+ else
+ memcpy(&buffer[buffer_len - 4], "...\0", 4);
+}
+
+
static void
note_gc_extract_key(struct note_gc_hash *data, const char **key, int *len)
{
diff --git a/src/notify.c b/src/notify.c
index 549a2be..6eda361 100644
--- a/src/notify.c
+++ b/src/notify.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,7 @@
*
*/
+#include <sys/wait.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
@@ -136,9 +137,6 @@ void notify_init_vars(void)
strncpy(nbar.cmd, cmd, BUFSIZ);
nbar.cmd[BUFSIZ - 1] = '\0';
- if ((nbar.shell = getenv("SHELL")) == NULL)
- nbar.shell = "/bin/sh";
-
nbar.notify_all = 0;
pthread_attr_init(&detached_thread_attr);
@@ -215,26 +213,18 @@ void notify_reinit_bar(void)
/* Launch user defined command as a notification. */
unsigned notify_launch_cmd(void)
{
- int pid;
+ char const *arg[2] = { nbar.cmd, NULL };
+ int pid, pin, pout, perr;
if (notify_app.state & APOINT_NOTIFIED)
return 1;
notify_app.state |= APOINT_NOTIFIED;
- pid = fork();
-
- if (pid < 0) {
- ERROR_MSG(_("error while launching command: could not fork"));
- return 0;
- } else if (pid == 0) {
- /* Child: launch user defined command */
- if (execlp(nbar.shell, nbar.shell, "-c", nbar.cmd, NULL) <
- 0) {
- ERROR_MSG(_("error while launching command"));
- _exit(1);
- }
- _exit(0);
+ if ((pid = shell_exec(&pin, &pout, &perr, 1, *arg, arg))) {
+ close(pin);
+ close(pout);
+ close(perr);
}
return 1;
@@ -358,6 +348,9 @@ static void *notify_main_thread(void *arg)
pthread_mutex_unlock(&notify.mutex);
notify_update_bar();
psleep(thread_sleep);
+ /* Reap the user-defined notifications. */
+ while (waitpid(0, NULL, WNOHANG) > 0)
+ ;
elapse += thread_sleep;
if (elapse >= check_app) {
elapse = 0;
@@ -505,8 +498,7 @@ void notify_check_repeated(struct recur_apoint *i)
current_time = time(NULL);
pthread_mutex_lock(&notify_app.mutex);
if (recur_item_find_occurrence
- (i->start, i->dur, &i->exc, i->rpt->type, i->rpt->freq,
- i->rpt->until, get_today(), &real_app_time)) {
+ (i->start, i->dur, i->rpt, &i->exc, get_today(), &real_app_time)) {
if (!notify_app.got_app) {
if (real_app_time - current_time <= DAYINSEC)
update_notify = 1;
@@ -547,12 +539,10 @@ int notify_same_recur_item(struct recur_apoint *i)
time_t item_start;
/* Tomorrow? */
- recur_item_find_occurrence(i->start, i->dur, &i->exc, i->rpt->type,
- i->rpt->freq, i->rpt->until,
+ recur_item_find_occurrence(i->start, i->dur, i->rpt, &i->exc,
NEXTDAY(get_today()), &item_start);
/* Today? */
- recur_item_find_occurrence(i->start, i->dur, &i->exc, i->rpt->type,
- i->rpt->freq, i->rpt->until,
+ recur_item_find_occurrence(i->start, i->dur, i->rpt, &i->exc,
get_today(), &item_start);
pthread_mutex_lock(&notify_app.mutex);
if (notify_app.got_app && item_start == notify_app.time)
diff --git a/src/pcal.c b/src/pcal.c
index 27d1616..435656a 100644
--- a/src/pcal.c
+++ b/src/pcal.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -56,24 +56,22 @@ typedef void (*cb_dump_t) (FILE *, long, long, char *);
*/
static void
foreach_date_dump(const long date_end, struct rpt *rpt, llist_t * exc,
- long item_first_date, long item_dur, char *item_mesg,
+ long item_start, long item_dur, char *item_mesg,
cb_dump_t cb_dump, FILE * stream)
{
long date, item_time;
struct tm lt;
time_t t;
- t = item_first_date;
+ t = item_start;
localtime_r(&t, &lt);
lt.tm_hour = lt.tm_min = lt.tm_sec = 0;
lt.tm_isdst = -1;
date = mktime(&lt);
- item_time = item_first_date - date;
+ item_time = item_start - date;
while (date <= date_end && date <= rpt->until) {
- if (recur_item_inday
- (item_first_date, item_dur, exc, rpt->type, rpt->freq,
- rpt->until, date)) {
+ if (recur_item_inday(item_start, item_dur, rpt, exc, date)) {
(*cb_dump) (stream, date + item_time, item_dur,
item_mesg);
}
@@ -104,8 +102,8 @@ static void pcal_export_header(FILE * stream)
{
fputs("# calcurse pcal export\n", stream);
fputs("\n# =======\n# options\n# =======\n", stream);
- fprintf(stream, "opt -A -K -l -m -F %s\n",
- ui_calendar_week_begins_on_monday()? "Monday" : "Sunday");
+ fprintf(stream, "opt -A -K -l -m -F %s\n", get_wday_default_string(
+ ui_calendar_get_wday_start()));
fputs("# Display week number (i.e. 1-52) on every Monday\n",
stream);
fprintf(stream, "all monday in all week %%w\n");
diff --git a/src/queue.c b/src/queue.c
index f68e969..41cb69b 100644
--- a/src/queue.c
+++ b/src/queue.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2018 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/src/recur.c b/src/recur.c
index 7376536..10523ad 100644
--- a/src/recur.c
+++ b/src/recur.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -46,12 +46,45 @@
llist_ts_t recur_alist_p;
llist_t recur_elist;
+static void free_int(int *i)
+{
+ mem_free(i);
+}
+
+void recur_free_int_list(llist_t *ilist)
+{
+ LLIST_FREE_INNER(ilist, free_int);
+ LLIST_FREE(ilist);
+}
+
+void recur_int_list_dup(llist_t *l, llist_t *ilist)
+{
+ llist_item_t *i;
+ int *o, *p;
+
+ LLIST_INIT(l);
+
+ if (ilist->head) {
+ LLIST_FOREACH(ilist, i) {
+ p = LLIST_GET_DATA(i);
+ o = mem_malloc(sizeof(int));
+ *o = *p;
+ LLIST_ADD(l, o);
+ }
+ }
+}
+
+static int int_cmp(int *list, int *i)
+{
+ return *list == *i;
+}
+
static void free_exc(struct excp *exc)
{
mem_free(exc);
}
-static void free_exc_list(llist_t * exc)
+void recur_free_exc_list(llist_t * exc)
{
LLIST_FREE_INNER(exc, free_exc);
LLIST_FREE(exc);
@@ -62,6 +95,11 @@ static int exc_cmp_day(struct excp *a, struct excp *b)
return a->st < b->st ? -1 : (a->st == b->st ? 0 : 1);
}
+static int exc_inday(struct excp *exc, time_t *day_start)
+{
+ return (date_cmp_day(exc->st, *day_start) == 0);
+}
+
static void recur_add_exc(llist_t * exc, time_t day)
{
struct excp *o = mem_malloc(sizeof(struct excp));
@@ -70,7 +108,7 @@ static void recur_add_exc(llist_t * exc, time_t day)
LLIST_ADD_SORTED(exc, o, exc_cmp_day);
}
-static void exc_dup(llist_t * in, llist_t * exc)
+void recur_exc_dup(llist_t * in, llist_t * exc)
{
llist_item_t *i;
@@ -103,10 +141,10 @@ char *recur_exc2str(llist_t *exc)
}
/*
- * Update the list of exceptions from a string of days. Any positive number of
+ * Update a list of exceptions from a string of days. Any positive number of
* spaces are allowed before, between and after the days.
*/
-int recur_update_exc(llist_t *exc, char *days)
+int recur_str2exc(llist_t *exc, char *days)
{
int updated = 0;
char *d;
@@ -130,11 +168,11 @@ int recur_update_exc(llist_t *exc, char *days)
else
break;
}
- free_exc_list(exc);
- exc_dup(exc, &nexc);
+ recur_free_exc_list(exc);
+ recur_exc_dup(exc, &nexc);
updated = 1;
cleanup:
- free_exc_list(&nexc);
+ recur_free_exc_list(&nexc);
return updated;
}
@@ -149,11 +187,16 @@ struct recur_event *recur_event_dup(struct recur_event *in)
rev->mesg = mem_strdup(in->mesg);
rev->rpt = mem_malloc(sizeof(struct rpt));
+ /* Note. The linked lists are NOT copied and no memory allocated. */
rev->rpt->type = in->rpt->type;
rev->rpt->freq = in->rpt->freq;
rev->rpt->until = in->rpt->until;
+ LLIST_INIT(&rev->rpt->bymonth);
+ LLIST_INIT(&rev->rpt->bywday);
+ LLIST_INIT(&rev->rpt->bymonthday);
+ LLIST_INIT(&rev->rpt->exc);
- exc_dup(&rev->exc, &in->exc);
+ recur_exc_dup(&rev->exc, &in->exc);
if (in->note)
rev->note = mem_strdup(in->note);
@@ -176,11 +219,16 @@ struct recur_apoint *recur_apoint_dup(struct recur_apoint *in)
rapt->mesg = mem_strdup(in->mesg);
rapt->rpt = mem_malloc(sizeof(struct rpt));
+ /* Note. The linked lists are NOT copied and no memory allocated. */
rapt->rpt->type = in->rpt->type;
rapt->rpt->freq = in->rpt->freq;
rapt->rpt->until = in->rpt->until;
+ LLIST_INIT(&rapt->rpt->bymonth);
+ LLIST_INIT(&rapt->rpt->bywday);
+ LLIST_INIT(&rapt->rpt->bymonthday);
+ LLIST_INIT(&rapt->rpt->exc);
- exc_dup(&rapt->exc, &in->exc);
+ recur_exc_dup(&rapt->exc, &in->exc);
if (in->note)
rapt->note = mem_strdup(in->note);
@@ -205,9 +253,14 @@ void recur_apoint_free(struct recur_apoint *rapt)
mem_free(rapt->mesg);
if (rapt->note)
mem_free(rapt->note);
- if (rapt->rpt)
+ if (rapt->rpt) {
+ recur_free_exc_list(&rapt->rpt->exc);
+ recur_free_int_list(&rapt->rpt->bywday);
+ recur_free_int_list(&rapt->rpt->bymonth);
+ recur_free_int_list(&rapt->rpt->bymonthday);
mem_free(rapt->rpt);
- free_exc_list(&rapt->exc);
+ }
+ recur_free_exc_list(&rapt->exc);
mem_free(rapt);
}
@@ -216,9 +269,14 @@ void recur_event_free(struct recur_event *rev)
mem_free(rev->mesg);
if (rev->note)
mem_free(rev->note);
- if (rev->rpt)
+ if (rev->rpt) {
+ recur_free_exc_list(&rev->rpt->exc);
+ recur_free_int_list(&rev->rpt->bywday);
+ recur_free_int_list(&rev->rpt->bymonth);
+ recur_free_int_list(&rev->rpt->bymonthday);
mem_free(rev->rpt);
- free_exc_list(&rev->exc);
+ }
+ recur_free_exc_list(&rev->exc);
mem_free(rev);
}
@@ -261,28 +319,31 @@ static int recur_event_cmp(struct recur_event *a, struct recur_event *b)
/* Insert a new recursive appointment in the general linked list */
struct recur_apoint *recur_apoint_new(char *mesg, char *note, time_t start,
- long dur, char state, int type,
- int freq, time_t until,
- llist_t * except)
+ long dur, char state, struct rpt *rpt)
{
struct recur_apoint *rapt =
mem_malloc(sizeof(struct recur_apoint));
- rapt->rpt = mem_malloc(sizeof(struct rpt));
rapt->mesg = mem_strdup(mesg);
rapt->note = (note != NULL) ? mem_strdup(note) : 0;
rapt->start = start;
- rapt->state = state;
rapt->dur = dur;
- rapt->rpt->type = type;
- rapt->rpt->freq = freq;
- rapt->rpt->until = until;
- if (except) {
- exc_dup(&rapt->exc, except);
- free_exc_list(except);
- } else {
- LLIST_INIT(&rapt->exc);
- }
+ rapt->state = state;
+ rapt->rpt = mem_malloc(sizeof(struct rpt));
+ *rapt->rpt = *rpt;
+ recur_int_list_dup(&rapt->rpt->bymonth, &rpt->bymonth);
+ recur_free_int_list(&rpt->bymonth);
+ recur_int_list_dup(&rapt->rpt->bywday, &rpt->bywday);
+ recur_free_int_list(&rpt->bywday);
+ recur_int_list_dup(&rapt->rpt->bymonthday, &rpt->bymonthday);
+ recur_free_int_list(&rpt->bymonthday);
+ /*
+ * Note. The exception dates are in the list rapt->exc.
+ * The (empty) list rapt->rpt->exc is not used.
+ */
+ recur_exc_dup(&rapt->exc, &rpt->exc);
+ recur_free_exc_list(&rpt->exc);
+ LLIST_INIT(&rapt->rpt->exc);
LLIST_TS_LOCK(&recur_alist_p);
LLIST_TS_ADD_SORTED(&recur_alist_p, rapt, recur_apoint_cmp);
@@ -293,25 +354,26 @@ struct recur_apoint *recur_apoint_new(char *mesg, char *note, time_t start,
/* Insert a new recursive event in the general linked list */
struct recur_event *recur_event_new(char *mesg, char *note, time_t day,
- int id, int type, int freq, time_t until,
- llist_t * except)
+ int id, struct rpt *rpt)
{
struct recur_event *rev = mem_malloc(sizeof(struct recur_event));
- rev->rpt = mem_malloc(sizeof(struct rpt));
rev->mesg = mem_strdup(mesg);
rev->note = (note != NULL) ? mem_strdup(note) : 0;
rev->day = day;
rev->id = id;
- rev->rpt->type = type;
- rev->rpt->freq = freq;
- rev->rpt->until = until;
- if (except) {
- exc_dup(&rev->exc, except);
- free_exc_list(except);
- } else {
- LLIST_INIT(&rev->exc);
- }
+ rev->rpt = mem_malloc(sizeof(struct rpt));
+ *rev->rpt = *rpt;
+ recur_int_list_dup(&rev->rpt->bymonth, &rpt->bymonth);
+ recur_free_int_list(&rpt->bymonth);
+ recur_int_list_dup(&rev->rpt->bywday, &rpt->bywday);
+ recur_free_int_list(&rpt->bywday);
+ recur_int_list_dup(&rev->rpt->bymonthday, &rpt->bymonthday);
+ recur_free_int_list(&rpt->bymonthday);
+ /* Similarly as for recurrent appointment. */
+ recur_exc_dup(&rev->exc, &rpt->exc);
+ recur_free_exc_list(&rpt->exc);
+ LLIST_INIT(&rev->rpt->exc);
LLIST_ADD_SORTED(&recur_elist, rev, recur_event_cmp);
@@ -340,8 +402,7 @@ char recur_def2char(enum recur_type define)
recur_char = 'Y';
break;
default:
- EXIT(_("unknown repetition type"));
- return 0;
+ recur_char = 0;
}
return recur_char;
@@ -375,6 +436,39 @@ int recur_char2def(char type)
return recur_def;
}
+/* Write the bymonthday list. */
+static void bymonthday_append(struct string *s, llist_t *l)
+{
+ llist_item_t *i;
+
+ LLIST_FOREACH(l, i) {
+ int *day = LLIST_GET_DATA(i);
+ string_catf(s, " d%d", *day);
+ }
+}
+
+/* Write the bywday list. */
+static void bywday_append(struct string *s, llist_t *l)
+{
+ llist_item_t *i;
+
+ LLIST_FOREACH(l, i) {
+ int *wday = LLIST_GET_DATA(i);
+ string_catf(s, " w%d", *wday);
+ }
+}
+
+/* Write the bymonth list. */
+static void bymonth_append(struct string *s, llist_t *l)
+{
+ llist_item_t *i;
+
+ LLIST_FOREACH(l, i) {
+ int *mon = LLIST_GET_DATA(i);
+ string_catf(s, " m%d", *mon);
+ }
+}
+
/* Write days for which recurrent items should not be repeated. */
static void recur_exc_append(struct string *s, llist_t *lexc)
{
@@ -395,29 +489,25 @@ static void recur_exc_append(struct string *s, llist_t *lexc)
}
/* Load the recursive appointment description */
-struct recur_apoint *recur_apoint_scan(FILE * f, struct tm start,
- struct tm end, char type, int freq,
- struct tm until, char *note,
- llist_t * exc, char state,
- struct item_filter *filter)
+char *recur_apoint_scan(FILE *f, struct tm start, struct tm end,
+ char state, char *note,
+ struct item_filter *filter,
+ struct rpt *rpt)
{
char buf[BUFSIZ], *nl;
- time_t tstart, tend, tuntil;
+ time_t tstart, tend;
struct recur_apoint *rapt = NULL;
int cond;
- EXIT_IF(!check_date(start.tm_year, start.tm_mon, start.tm_mday) ||
- !check_date(end.tm_year, end.tm_mon, end.tm_mday) ||
- !check_time(start.tm_hour, start.tm_min) ||
- !check_time(end.tm_hour, end.tm_min) ||
- (until.tm_year != 0
- && !check_date(until.tm_year, until.tm_mon,
- until.tm_mday)),
- _("date error in appointment"));
+ if (!check_date(start.tm_year, start.tm_mon, start.tm_mday) ||
+ !check_date(end.tm_year, end.tm_mon, end.tm_mday) ||
+ !check_time(start.tm_hour, start.tm_min) ||
+ !check_time(end.tm_hour, end.tm_min))
+ return _("illegal date in appointment");
/* Read the appointment description */
if (!fgets(buf, sizeof buf, f))
- return NULL;
+ return _("error in appointment description");
nl = strchr(buf, '\n');
if (nl) {
@@ -432,19 +522,15 @@ struct recur_apoint *recur_apoint_scan(FILE * f, struct tm start,
tstart = mktime(&start);
tend = mktime(&end);
- if (until.tm_year != 0) {
- until.tm_hour = 0;
- until.tm_min = 0;
- until.tm_sec = 0;
- until.tm_isdst = -1;
- until.tm_year -= 1900;
- until.tm_mon--;
- tuntil = mktime(&until);
- } else {
- tuntil = 0;
+ if (tstart == -1 || tend == -1 || tstart > tend)
+ return _("date error in appointment");
+
+ /* Does it occur on the start day? */
+ if (!recur_item_find_occurrence(tstart, tend - tstart, rpt, NULL,
+ DAY(tstart), NULL)) {
+ char *fmt = _("recurrence error: not on start day (%s)");
+ return day_ins(&fmt, tstart);
}
- EXIT_IF(tstart == -1 || tend == -1 || tstart > tend
- || tuntil == -1, _("date error in appointment"));
/* Filter item. */
if (filter) {
@@ -458,9 +544,8 @@ struct recur_apoint *recur_apoint_scan(FILE * f, struct tm start,
);
if (filter->hash) {
rapt = recur_apoint_new(buf, note, tstart,
- tend - tstart, state,
- recur_char2def(type),
- freq, tuntil, exc);
+ tend - tstart, state,
+ rpt);
char *hash = recur_apoint_hash(rapt);
cond = cond || !hash_matches(filter->hash, hash);
mem_free(hash);
@@ -473,54 +558,51 @@ struct recur_apoint *recur_apoint_scan(FILE * f, struct tm start,
}
}
if (!rapt)
- rapt = recur_apoint_new(buf, note, tstart, tend - tstart,
- state, recur_char2def(type), freq,
- tuntil, exc);
-
- return rapt;
+ rapt = recur_apoint_new(buf, note, tstart, tend - tstart, state,
+ rpt);
+ return NULL;
}
/* Load the recursive events from file */
-struct recur_event *recur_event_scan(FILE * f, struct tm start, int id,
- char type, int freq, struct tm until,
- char *note, llist_t * exc,
- struct item_filter *filter)
+char *recur_event_scan(FILE * f, struct tm start, int id,
+ char *note, struct item_filter *filter,
+ struct rpt *rpt)
{
char buf[BUFSIZ], *nl;
- time_t tstart, tend, tuntil;
+ time_t tstart, tend;
struct recur_event *rev = NULL;
int cond;
- EXIT_IF(!check_date(start.tm_year, start.tm_mon, start.tm_mday) ||
- !check_time(start.tm_hour, start.tm_min) ||
- (until.tm_year != 0
- && !check_date(until.tm_year, until.tm_mon,
- until.tm_mday)), _("date error in event"));
+ if (!check_date(start.tm_year, start.tm_mon, start.tm_mday) ||
+ !check_time(start.tm_hour, start.tm_min))
+ return _("illegel date in event");
/* Read the event description */
if (!fgets(buf, sizeof buf, f))
- return NULL;
+ return _("error in appointment description");
nl = strchr(buf, '\n');
if (nl) {
*nl = '\0';
}
- start.tm_hour = until.tm_hour = 0;
- start.tm_min = until.tm_min = 0;
- start.tm_sec = until.tm_sec = 0;
- start.tm_isdst = until.tm_isdst = -1;
+ start.tm_hour = 0;
+ start.tm_min = 0;
+ start.tm_sec = 0;
+ start.tm_isdst = -1;
start.tm_year -= 1900;
start.tm_mon--;
- if (until.tm_year != 0) {
- until.tm_year -= 1900;
- until.tm_mon--;
- tuntil = mktime(&until);
- } else {
- tuntil = 0;
- }
+
tstart = mktime(&start);
- EXIT_IF(tstart == -1 || tuntil == -1, _("date error in event"));
- tend = tstart + DAYINSEC - 1;
+ if (tstart == -1)
+ return _("date error in event");
+ tend = ENDOFDAY(tstart);
+
+ /* Does it occur on the start day? */
+ if (!recur_item_find_occurrence(tstart, -1, rpt, NULL,
+ DAY(tstart), NULL)) {
+ char *fmt = _("recurrence error: not on start day (%s)");
+ return day_ins(&fmt, tstart);
+ }
/* Filter item. */
if (filter) {
@@ -534,8 +616,7 @@ struct recur_event *recur_event_scan(FILE * f, struct tm start, int id,
);
if (filter->hash) {
rev = recur_event_new(buf, note, tstart, id,
- recur_char2def(type),
- freq, tuntil, exc);
+ rpt);
char *hash = recur_event_hash(rev);
cond = cond || !hash_matches(filter->hash, hash);
mem_free(hash);
@@ -548,11 +629,8 @@ struct recur_event *recur_event_scan(FILE * f, struct tm start, int id,
}
}
if (!rev)
- rev = recur_event_new(buf, note, tstart, id,
- recur_char2def(type),
- freq, tuntil, exc);
-
- return rev;
+ rev = recur_event_new(buf, note, tstart, id, rpt);
+ return NULL;
}
char *recur_apoint_tostr(struct recur_apoint *o)
@@ -584,6 +662,9 @@ char *recur_apoint_tostr(struct recur_apoint *o)
recur_def2char(o->rpt->type), lt.tm_mon + 1,
lt.tm_mday, 1900 + lt.tm_year);
}
+ bymonthday_append(&s, &o->rpt->bymonthday);
+ bywday_append(&s, &o->rpt->bywday);
+ bymonth_append(&s, &o->rpt->bymonth);
recur_exc_append(&s, &o->exc);
string_catf(&s, "} ");
if (o->note)
@@ -645,6 +726,9 @@ char *recur_event_tostr(struct recur_event *o)
recur_def2char(o->rpt->type), end_mon, end_day,
end_year);
}
+ bymonthday_append(&s, &o->rpt->bymonthday);
+ bywday_append(&s, &o->rpt->bywday);
+ bymonth_append(&s, &o->rpt->bymonth);
recur_exc_append(&s, &o->exc);
string_catf(&s, "} ");
if (o->note)
@@ -690,6 +774,20 @@ void recur_save_data(FILE * f)
}
/*
+ * Return the month day counted from the opposite end of the month.
+ */
+static int opp_mday(int year, int month, int day)
+{
+ EXIT_IF(day == 0, _("month day is zero"));
+
+ int m_days = days[month - 1] + (month == 2 && ISLEAP(year));
+ if (day > 0)
+ return day - 1 - m_days;
+ else
+ return day + 1 + m_days;
+}
+
+/*
* The two following defines together with the diff_days, diff_months and
* diff_years functions were provided by Lukas Fleischer to correct the wrong
* calculation of recurrent dates after a turn of year.
@@ -740,169 +838,739 @@ static long diff_years(struct tm lt_start, struct tm lt_end)
return lt_end.tm_year - lt_start.tm_year;
}
-static int exc_inday(struct excp *exc, time_t *day_start)
+/*
+ * Return true if 'mon' and 'mday' is month and day of t
+ * (after a call of mktime()).
+ */
+static int date_chk(time_t t, int mon, int mday)
{
- return (date_cmp_day(exc->st, *day_start) == 0);
+ struct tm tm;
+
+ localtime_r(&t, &tm);
+
+ return tm.tm_mon == mon && tm.tm_mday == mday;
}
/*
- * Check if the recurrent item belongs to the selected day, and if yes, store
- * the start date of the occurrence that belongs to the day in a buffer.
- *
- * This function was improved thanks to Tony's patch.
- * Thanks also to youshe for reporting daylight saving time related problems.
- * And finally thanks to Lukas for providing a patch to correct the wrong
- * calculation of recurrent dates after a turn of years.
+ * Return true if the rrule (start, dur, rpt, exc) has an occurrence on the
+ * given day. If so, save that occurrence in a (dynamic or static) buffer.
*/
-unsigned
-recur_item_find_occurrence(time_t item_start, long item_dur,
- llist_t * item_exc, int rpt_type, int rpt_freq,
- time_t rpt_until, time_t day_start,
- time_t *occurrence)
+static int find_occurrence(time_t start, long dur, struct rpt *rpt, llist_t *exc,
+ time_t day, time_t *occurrence)
{
-/*
- * Function-internal duration
- * 1) To avoid an item ending on midnight (which belongs to the next day),
- * duration is always diminished by 1 second.
- * 2) An event has no explicit duration, but lasts for an entire day, which
- * in turn depends on DST.
- */
-#define ITEM_DUR(d) ((item_dur == -1 ? DAYLEN(d) : item_dur) - 1)
+ /*
+ * Duration-on-day-d fix.
+ * An item cannot end on midnight or else it is counted towards the next day.
+ * An event (dur == -1) has no explicit duration, but is considered to last for
+ * the entire day (d) which depends on DST.
+ */
+#define DUR(d) (dur == -1 ? DAYLEN((d)) - 1 : dur - 1)
long diff;
- struct tm lt_day, lt_item, lt_item_day;
- time_t occ, item_day_start;
-
- item_day_start = update_time_in_date(item_start, 0, 0);
+ struct tm lt_day, lt_start, lt_occur;
+ time_t t;
+ int mday, order, pwday, nwday, mon;
- if (day_start < item_day_start)
+ /* Is the given day before the day of the first occurence? */
+ if (date_cmp_day(day, start) < 0)
return 0;
- if (rpt_until && day_start >=
- rpt_until + (item_start - item_day_start) + ITEM_DUR(rpt_until))
+ /*
+ * - or after the day of the last occurrence (which may stretch beyond
+ * the until date)? Extraneous days are eliminated later.
+ */
+ if (rpt->until &&
+ date_cmp_day(NEXTDAY(rpt->until) + DUR(rpt->until), day) < 0)
return 0;
- localtime_r(&day_start, &lt_day); /* selected day */
- localtime_r(&item_start, &lt_item); /* first occurrence */
- lt_item_day = lt_item; /* recent occurrence */
+ localtime_r(&day, &lt_day); /* Given day. */
+ localtime_r(&start, &lt_start); /* Original item. */
+ lt_occur = lt_start; /* First occurence. */
/*
* Update to the most recent occurrence before or on the selected day.
*/
- switch (rpt_type) {
+ switch (rpt->type) {
case RECUR_DAILY:
- diff = diff_days(lt_item_day, lt_day) % rpt_freq;
- lt_item_day.tm_mday = lt_day.tm_mday - diff;
- lt_item_day.tm_mon = lt_day.tm_mon;
- lt_item_day.tm_year = lt_day.tm_year;
+ /* Number of days since the most recent occurrence. */
+ diff = diff_days(lt_occur, lt_day) % rpt->freq;
+ lt_occur.tm_mday = lt_day.tm_mday - diff;
+ lt_occur.tm_mon = lt_day.tm_mon;
+ lt_occur.tm_year = lt_day.tm_year;
break;
case RECUR_WEEKLY:
- diff = diff_days(lt_item_day, lt_day) %
- (rpt_freq * WEEKINDAYS);
- lt_item_day.tm_mday = lt_day.tm_mday - diff;
- lt_item_day.tm_mon = lt_day.tm_mon;
- lt_item_day.tm_year = lt_day.tm_year;
+ diff = diff_days(lt_occur, lt_day) %
+ (rpt->freq * WEEKINDAYS);
+ lt_occur.tm_mday = lt_day.tm_mday - diff;
+ lt_occur.tm_mon = lt_day.tm_mon;
+ lt_occur.tm_year = lt_day.tm_year;
break;
case RECUR_MONTHLY:
- diff = diff_months(lt_item_day, lt_day) % rpt_freq;
- if (!diff && lt_day.tm_mday < lt_item_day.tm_mday)
- diff += rpt_freq;
- lt_item_day.tm_mon = lt_day.tm_mon - diff;
- lt_item_day.tm_year = lt_day.tm_year;
+ diff = diff_months(lt_occur, lt_day) % rpt->freq;
+ if (!diff && lt_day.tm_mday < lt_occur.tm_mday)
+ diff += rpt->freq;
+ lt_occur.tm_mon = lt_day.tm_mon - diff;
+ lt_occur.tm_year = lt_day.tm_year;
break;
case RECUR_YEARLY:
- diff = diff_years(lt_item_day, lt_day) % rpt_freq;
+ diff = diff_years(lt_occur, lt_day) % rpt->freq;
if (!diff &&
- (lt_day.tm_mon < lt_item_day.tm_mon ||
- (lt_day.tm_mon == lt_item_day.tm_mon &&
- lt_day.tm_mday < lt_item_day.tm_mday)))
- diff += rpt_freq;
- lt_item_day.tm_year = lt_day.tm_year - diff;
+ (lt_day.tm_mon < lt_occur.tm_mon ||
+ (lt_day.tm_mon == lt_occur.tm_mon &&
+ lt_day.tm_mday < lt_occur.tm_mday)))
+ diff += rpt->freq;
+ lt_occur.tm_year = lt_day.tm_year - diff;
break;
default:
EXIT(_("unknown item type"));
}
/* Switch to calendar (Unix) time. */
- lt_item_day.tm_isdst = -1;
- occ = mktime(&lt_item_day);
+ lt_occur.tm_isdst = -1;
+ t = mktime(&lt_occur);
/*
* Impossible dates must be ignored (according to RFC 5545). Changing
* only the year or the month may lead to dates like 29 February in
* non-leap years or 31 November.
*/
- if (rpt_type == RECUR_MONTHLY || rpt_type == RECUR_YEARLY) {
- localtime_r(&occ, &lt_item_day);
- if (lt_item_day.tm_mday != lt_item.tm_mday)
+ if ((rpt->type == RECUR_MONTHLY || rpt->type == RECUR_YEARLY) &&
+ !date_chk(t, lt_occur.tm_mon, lt_start.tm_mday))
+ return 0;
+
+ /*
+ * BYMONTHDAY reduction
+ * A month day has two possible list forms.
+ */
+ mday = opp_mday(lt_occur.tm_year + 1900, lt_occur.tm_mon + 1,
+ lt_occur.tm_mday);
+ if (rpt->bymonthday.head &&
+ rpt->type == RECUR_DAILY &&
+ !LLIST_FIND_FIRST(&rpt->bymonthday, &lt_occur.tm_mday, int_cmp) &&
+ !LLIST_FIND_FIRST(&rpt->bymonthday, &mday, int_cmp))
+ return 0;
+
+ /* BYDAY reduction for DAILY */
+ if (rpt->bywday.head && rpt->type == RECUR_DAILY &&
+ !LLIST_FIND_FIRST(&rpt->bywday, &lt_occur.tm_wday, int_cmp))
+ return 0;
+
+ /*
+ * BYDAY reduction for MONTHLY
+ * A weekday has three possible list forms.
+ */
+ if (rpt->bywday.head &&
+ rpt->type == RECUR_MONTHLY && rpt->bymonthday.head) {
+ /* positive order */
+ order = (lt_occur.tm_mday + 6) / WEEKINDAYS;
+ pwday = order * WEEKINDAYS + lt_occur.tm_wday;
+ /* negative order */
+ order = order
+ - wday_per_month(lt_occur.tm_mon + 1,
+ lt_occur.tm_year + 1900,
+ lt_occur.tm_wday)
+ - 1;
+ nwday = order * WEEKINDAYS - lt_occur.tm_wday;
+ if (!LLIST_FIND_FIRST(&rpt->bywday, &lt_occur.tm_wday, int_cmp) &&
+ !LLIST_FIND_FIRST(&rpt->bywday, &pwday, int_cmp) &&
+ !LLIST_FIND_FIRST(&rpt->bywday, &nwday, int_cmp))
return 0;
}
+ /*
+ * BYDAY reduction for YEARLY
+ * A weekday has three possible list forms.
+ */
+ if (rpt->bywday.head &&
+ rpt->type == RECUR_YEARLY && rpt->bymonthday.head) {
+ /* positive order */
+ order = lt_occur.tm_yday / WEEKINDAYS;
+ pwday = order * WEEKINDAYS + lt_occur.tm_wday;
+ /* negative order */
+ order = order
+ - wday_per_year(lt_occur.tm_year + 1900,
+ lt_occur.tm_wday)
+ - 1;
+ nwday = order * WEEKINDAYS - lt_occur.tm_wday;
+ if (!LLIST_FIND_FIRST(&rpt->bywday, &lt_occur.tm_wday, int_cmp) &&
+ !LLIST_FIND_FIRST(&rpt->bywday, &pwday, int_cmp) &&
+ !LLIST_FIND_FIRST(&rpt->bywday, &nwday, int_cmp))
+ return 0;
+ }
+
+ /* BYMONTH reduction */
+ mon = lt_occur.tm_mon + 1;
+ if (rpt->bymonth.head &&
+ rpt->type != RECUR_YEARLY &&
+ !LLIST_FIND_FIRST(&rpt->bymonth, &mon, int_cmp))
+ return 0;
+
/* Exception day? */
- if (LLIST_FIND_FIRST(item_exc, &occ, exc_inday))
+ if (exc && LLIST_FIND_FIRST(exc, &t, exc_inday))
return 0;
- /* After until day? */
- if (rpt_until && occ >= NEXTDAY(rpt_until))
+ /* Extraneous day? */
+ if (rpt->until && t >= NEXTDAY(rpt->until))
return 0;
- /* Does it span the selected day? */
- if (occ + ITEM_DUR(occ) < day_start)
+ /* Does it span the given day?
+ *
+ * NOTE: An appointment ending at 00:00 is not considered to span the
+ * given day, unless the appointment is an appointment without
+ * specified end time, which is internally treated as appointment with
+ * duration 0.
+ */
+ if (t + DUR(t) >= day || (t == day && dur == 0)) {
+ if (occurrence)
+ *occurrence = t;
+ return 1;
+ } else {
return 0;
+ }
+}
+#undef DUR
- if (occurrence)
- *occurrence = occ;
+/*
+ * Return true if the rrule (s, d, r, e) has an occurrence, depending
+ * on the frequency, in the year, month or week of day.
+ */
+static int freq_chk(time_t day, time_t s, long d, struct rpt *r, llist_t *e)
+{
+ if (r->type == RECUR_DAILY)
+ EXIT(_("no daily frequency check"));
+
+ struct tm tm_start, tm_day;
+ struct rpt fc_rpt;
+ time_t fc_day, fc_s;
+
+ localtime_r(&s, &tm_start);
+ localtime_r(&day, &tm_day);
+
+ if (r->type == RECUR_WEEKLY) {
+ /* Set day to the weekly occurrence. */
+ fc_day = date_sec_change(
+ day,
+ 0,
+ WDAY(tm_start.tm_wday) - WDAY(tm_day.tm_wday)
+ );
+ fc_s = s;
+ } else {
+ /* The start day may be invalid in some months. */
+ tm_day.tm_mday = tm_start.tm_mday = 1;
+ if (r->type == RECUR_YEARLY)
+ tm_day.tm_mon = tm_start.tm_mon;
+ tm_day.tm_isdst = tm_start.tm_isdst = -1;
+ fc_day = mktime(&tm_day);
+ fc_s = mktime(&tm_start);
+ }
+ /* Turn all reductions off. */
+ fc_rpt = *r;
+ fc_rpt.until = 0;
+ fc_rpt.bymonth.head = fc_rpt.bywday.head = fc_rpt.bymonthday.head = NULL;
- return 1;
-#undef ITEM_DUR
+ return find_occurrence(fc_s, d, &fc_rpt, e, fc_day, NULL);
}
+/*
+ * Return true if the rrule (s, d, r, e) has an occurrence on 'day' after
+ * 'first'; if so, return it in occurrence.
+ */
+static int test_occurrence(time_t s, long d, struct rpt *r, llist_t *e,
+ time_t first, time_t day, time_t *occurrence)
+{
+ time_t occ;
+
+ if (find_occurrence(s, d, r, e, day, &occ)) {
+ if (occ < first)
+ return 0;
+ if (occurrence)
+ *occurrence = occ;
+ return 1;
+ }
+ return 0;
+}
+
+#define NO_EXPANSION -1
+static int expand_weekly(time_t start, long dur, struct rpt *rpt, llist_t *exc,
+ time_t day, time_t *occurrence)
+{
+ struct tm tm_start;
+ llist_item_t *i;
+ int *w;
+ time_t w_start;
+
+ localtime_r(&start, &tm_start);
+
+ /* BYDAY expansion */
+ if (rpt->bywday.head) {
+ LLIST_FOREACH(&rpt->bywday, i) {
+ w = LLIST_GET_DATA(i);
+ if (*w < 0 || *w > 6)
+ continue;
+ /*
+ * Modify rrule start with a new day in the same week as
+ * start - taking first day of the week into account.
+ */
+ w_start = date_sec_change(
+ start,
+ 0,
+ WDAY(*w) - WDAY(tm_start.tm_wday)
+ );
+ if (test_occurrence(w_start, dur, rpt, exc,
+ start, day, occurrence))
+ return 1;
+ }
+ } else
+ return NO_EXPANSION;
+
+ /* No occurrence */
+ return 0;
+}
+
+static int expand_monthly(time_t start, long dur, struct rpt *rpt, llist_t *exc,
+ time_t day, time_t *occurrence)
+{
+ struct tm tm_start, tm_day;
+ llist_item_t *i;
+ int *w, mday, mon, valid;
+ time_t nstart;
+ struct rpt r = *rpt;
+
+ localtime_r(&day, &tm_day);
+
+ /*
+ * The following three conditional alternatives are mutually exclusive
+ * and cover all four cases of two booleans.
+ */
+
+ /* BYMONTHDAY expansion */
+ if (rpt->bymonthday.head) {
+ LLIST_FOREACH(&rpt->bymonthday, i) {
+ mday = *(int *)LLIST_GET_DATA(i);
+
+ if (mday < 0)
+ mday = opp_mday(tm_day.tm_year + 1900,
+ tm_day.tm_mon + 1, mday);
+ /*
+ * Modify rrule start with a new monthday.
+ * If it is invalid (29, 30 or 31) in the start month,
+ * the month is changed to an earlier one matching the
+ * frequency.
+ */
+ localtime_r(&start, &tm_start);
+ mon = tm_start.tm_mon;
+
+ tm_start.tm_mday = mday;
+ tm_start.tm_isdst = -1;
+ nstart = mktime(&tm_start);
+ valid = date_chk(nstart, mon, mday);
+ /* Never valid? */
+ if (!valid && !(rpt->freq % 12))
+ return 0;
+ /* Note. The loop will terminate! */
+ while (!valid) {
+ localtime_r(&start, &tm_start);
+ mon -= rpt->freq;
+ tm_start.tm_mon = mon;
+ tm_start.tm_mday = mday;
+ tm_start.tm_isdst = -1;
+ nstart = mktime(&tm_start);
+ valid = date_chk(nstart, (mon + 12) % 12, mday);
+ }
+ if (test_occurrence(nstart, dur, rpt, exc,
+ start, day, occurrence))
+ return 1;
+ }
+ }
+ /* BYDAY special expansion for MONTHLY */
+ else if (rpt->bywday.head) {
+ /* The frequency is modified later. */
+ if (!freq_chk(day, start, dur, rpt, exc))
+ return 0;
+
+ LLIST_FOREACH(&rpt->bywday, i) {
+ w = LLIST_GET_DATA(i);
+
+ int order, wday, nbwd;
+
+ localtime_r(&start, &tm_start);
+ /*
+ * Construct a weekly rrule; BYMONTH-reduction in
+ * find_occurrence() will reduce to the bymonth list.
+ */
+ r.type = RECUR_WEEKLY;
+ if (*w > 6) {
+ /*
+ * A single occurrence counting forwards from
+ * the start of the month.
+ */
+ order = *w / WEEKINDAYS;
+ wday = *w % WEEKINDAYS;
+ nbwd = wday_per_month(tm_day.tm_mon + 1,
+ tm_day.tm_year + 1900,
+ wday);
+ if (nbwd < order)
+ return 0;
+ r.freq = order;
+ tm_start.tm_mday = 1;
+ tm_start.tm_mon = tm_day.tm_mon;
+ tm_start.tm_year = tm_day.tm_year;
+ tm_start.tm_isdst = -1;
+ /* Start in the week before the month. */
+ nstart = date_sec_change(
+ next_wday(mktime(&tm_start), wday),
+ 0,
+ -WEEKINDAYS
+ );
+ r.until = date_sec_change(
+ DAY(nstart),
+ 0,
+ r.freq * WEEKINDAYS
+ );
+ if (rpt->until && r.until > rpt->until)
+ return 0;
+ } else if (*w > -1) {
+ /* Expansion to each week. */
+ wday = *w % WEEKINDAYS;
+ r.freq = 1;
+ nstart = next_wday(start, wday);
+ } else if (*w < -6) {
+ /*
+ * A single ocurrence counting backwards from
+ * the end of the month.
+ */
+ order = -(*w) / WEEKINDAYS;
+ wday = -(*w) % WEEKINDAYS;
+ nbwd = wday_per_month(tm_day.tm_mon + 1,
+ tm_day.tm_year + 1900,
+ wday);
+ if (nbwd < order)
+ return 0;
+ r.freq = nbwd - order + 1;
+ tm_start.tm_mday = 1;
+ tm_start.tm_mon = tm_day.tm_mon;
+ tm_start.tm_year = tm_day.tm_year;
+ tm_start.tm_isdst = -1;
+ nstart = date_sec_change(
+ next_wday(mktime(&tm_start), wday),
+ 0,
+ -WEEKINDAYS
+ );
+ r.until = date_sec_change(
+ DAY(nstart),
+ 0,
+ r.freq * WEEKINDAYS
+ );
+ if (rpt->until && r.until > rpt->until)
+ return 0;
+ } else
+ EXIT(_("illegal BYDAY value"));
+
+ if (test_occurrence(nstart, dur, &r, exc,
+ start, day, occurrence))
+ return 1;
+ }
+ }
+ else
+ return NO_EXPANSION;
+
+ /* No occurrence */
+ return 0;
+}
+
+static int expand_yearly(time_t start, long dur, struct rpt *rpt, llist_t *exc,
+ time_t day, time_t *occurrence)
+{
+ struct tm tm_start, tm_day;
+ llist_item_t *i, *j;
+ int *m, *w, mday, wday, order, nbwd;
+ time_t nstart;
+ struct rpt r;
+
+ localtime_r(&day, &tm_day);
+ /*
+ * The following five conditional alternatives are mutually exclusive
+ * and cover all eight cases of three booleans.
+ */
+ /* BYMONTH expansion */
+ if (rpt->bymonth.head && !rpt->bymonthday.head && !rpt->bywday.head) {
+ LLIST_FOREACH(&rpt->bymonth, i) {
+ m = LLIST_GET_DATA(i);
+
+ /* Modify rrule start with new month. */
+ localtime_r(&start, &tm_start);
+ tm_start.tm_mon = *m - 1;
+ tm_start.tm_isdst = -1;
+ nstart = mktime(&tm_start);
+ if (!date_chk(nstart, *m - 1, tm_start.tm_mday))
+ continue;
+ if (find_occurrence(nstart, dur, rpt, exc, day,
+ occurrence))
+ return 1;
+ }
+ } else
+ /* BYDAY special expansion for MONTHLY or YEARLY */
+ if (!rpt->bymonthday.head && rpt->bywday.head) {
+ /* Check needed because frequency is modified later. */
+ if (!freq_chk(day, start, dur, rpt, exc))
+ return 0;
+
+ LLIST_FOREACH(&rpt->bywday, i) {
+ w = LLIST_GET_DATA(i);
+
+ localtime_r(&start, &tm_start);
+ /*
+ * Construct a suitable weekly rrule. BYMONTH
+ * reduction in find_occurrence() will limit
+ * occurrences if needed.
+ */
+ r = *rpt;
+ r.type = RECUR_WEEKLY;
+ if (*w > 6) {
+ /*
+ * Special expand: A single ocurrence counting
+ * forward from the start of the month/year.
+ * Start in the week before with a frequency
+ * that matches the ordered weekday and with
+ * until day that allows only one occurrence.
+ */
+ order = *w / WEEKINDAYS;
+ wday = *w % WEEKINDAYS;
+ if (rpt->bymonth.head)
+ nbwd = wday_per_month(
+ tm_day.tm_mon + 1,
+ tm_day.tm_year + 1900,
+ wday
+ );
+ else
+ nbwd = wday_per_year(
+ tm_day.tm_year + 1900,
+ wday
+ );
+ if (nbwd < order)
+ return 0;
+ r.freq = order;
+ tm_start.tm_mday = 1;
+ if (rpt->bymonth.head)
+ tm_start.tm_mon = tm_day.tm_mon;
+ else
+ tm_start.tm_mon = 0;
+ tm_start.tm_year = tm_day.tm_year;
+ tm_start.tm_isdst = -1;
+ nstart = date_sec_change(
+ next_wday(mktime(&tm_start), wday),
+ 0,
+ -WEEKINDAYS
+ );
+ r.until = date_sec_change(
+ DAY(nstart),
+ 0,
+ r.freq * WEEKINDAYS
+ );
+ if (rpt->until && r.until > rpt->until)
+ return 0;
+ } else if (*w > -1) {
+ /* Expand to each week of the month/year. */
+ wday = *w % WEEKINDAYS;
+ r.freq = 1;
+ nstart = next_wday(start, wday);
+ } else if (*w < -6) {
+ /*
+ * Special expand: A single ocurrence counting
+ * backward from the end of the month/year.
+ */
+ order = -(*w) / WEEKINDAYS;
+ wday = -(*w) % WEEKINDAYS;
+ if (rpt->bymonth.head)
+ nbwd = wday_per_month(
+ tm_day.tm_mon + 1,
+ tm_day.tm_year + 1900,
+ wday
+ );
+ else
+ nbwd = wday_per_year(
+ tm_day.tm_year + 1900,
+ wday
+ );
+ if (nbwd < order)
+ return 0;
+ r.freq = nbwd - order + 1;
+ tm_start.tm_mday = 1;
+ if (rpt->bymonth.head)
+ tm_start.tm_mon = tm_day.tm_mon;
+ else
+ tm_start.tm_mon = 0;
+ tm_start.tm_year = tm_day.tm_year;
+ tm_start.tm_isdst = -1;
+ nstart = date_sec_change(
+ next_wday(mktime(&tm_start), wday),
+ 0,
+ -WEEKINDAYS
+ );
+ r.until = date_sec_change(
+ DAY(nstart),
+ 0,
+ r.freq * WEEKINDAYS
+ );
+ if (rpt->until && r.until > rpt->until)
+ return 0;
+ } else
+ EXIT(_("illegal BYDAY value"));
+
+ if (test_occurrence(nstart, dur, &r, exc,
+ start, day, occurrence))
+ return 1;
+ }
+ } else
+ /* BYMONTHDAY expansion */
+ if (!rpt->bymonth.head && rpt->bymonthday.head) {
+ LLIST_FOREACH(&rpt->bymonthday, i) {
+ mday = *(int *)LLIST_GET_DATA(i);
+ if (mday < 0)
+ mday = opp_mday(
+ tm_day.tm_year + 1900,
+ tm_day.tm_mon + 1, mday
+ );
+ /* Modify rrule start with new monthday. */
+ localtime_r(&start, &tm_start);
+ tm_start.tm_mday = mday;
+ tm_start.tm_isdst = -1;
+ nstart = mktime(&tm_start);
+ if (!date_chk(nstart, tm_start.tm_mon, mday))
+ continue;
+ if (find_occurrence(nstart, dur, rpt, exc, day,
+ occurrence))
+ return 1;
+ }
+ } else
+ /* BYMONTH and BYMONTHDAY expansion */
+ if (rpt->bymonth.head && rpt->bymonthday.head) {
+ LLIST_FOREACH(&rpt->bymonth, i) {
+ m = LLIST_GET_DATA(i);
+
+ LLIST_FOREACH(&rpt->bymonthday, j) {
+ mday = *(int *)LLIST_GET_DATA(j);
+ if (mday < 0)
+ mday = opp_mday(
+ tm_day.tm_year + 1900,
+ tm_day.tm_mon + 1, mday
+ );
+ /* Modify start with new monthday and month. */
+ localtime_r(&start, &tm_start);
+ /* Number of days in February! */
+ if (*m == 2 && mday == 29 &&
+ !ISLEAP(tm_start.tm_year + 1900) &&
+ rpt->freq % 4) {
+ if (!freq_chk(day, start, dur, rpt, exc))
+ return 0;
+ tm_start.tm_year -= tm_start.tm_year % 4;
+ }
+ tm_start.tm_mday = mday;
+ tm_start.tm_mon = *m - 1;
+ tm_start.tm_isdst = -1;
+ nstart = mktime(&tm_start);
+ if (!date_chk(nstart, *m - 1, mday))
+ continue;
+ if (find_occurrence(nstart, dur, rpt, exc, day,
+ occurrence))
+ return 1;
+ }
+ }
+ } else
+ return NO_EXPANSION;
+
+ /* No occurrence */
+ return 0;
+}
+
+/*
+ * Membership test for the recurrence set of the rrule (start, dur, rpt, exc).
+ *
+ * Return true if day belongs to the set. If so, the occurrence is saved in a
+ * buffer. A positive result is always the outcome of find_occurrence(), whereas
+ * a negative result may be arrived at in other ways.
+ *
+ * The basic (type, frequency)-check is in find_occurrence(). When recurrence
+ * set expansion and/or reduction (RFC 5545) is needed, expansion is done before
+ * call of find_occurrence(), while reduction takes place in find_occurrence().
+ *
+ * Recurrence set expansion is accomplished by a combination of calls of
+ * find_occurrence(), possibly with change of type, frequency and start.
+ */
+unsigned
+recur_item_find_occurrence(time_t start, long dur, struct rpt *rpt, llist_t *exc,
+ time_t day, time_t *occurrence)
+{
+ int res;
+
+ /* To make it possible to set an earlier start without expanding the
+ * recurrence set. */
+ if (date_cmp_day(day, start) < 0)
+ return 0;
+
+ switch (rpt->type) {
+ case RECUR_DAILY:
+ res = NO_EXPANSION;
+ break;
+ case RECUR_WEEKLY:
+ res = expand_weekly(start, dur, rpt, exc, day, occurrence);
+ break;
+ case RECUR_MONTHLY:
+ res = expand_monthly(start, dur, rpt, exc, day, occurrence);
+ break;
+ case RECUR_YEARLY:
+ res = expand_yearly(start, dur, rpt, exc, day, occurrence);
+ break;
+ default:
+ res = 0;
+ }
+
+ if (res == NO_EXPANSION)
+ return find_occurrence(start, dur, rpt, exc, day, occurrence);
+
+ /* The result of find_occurrence() is passed on. */
+ return res;
+}
+#undef NO_EXPANSION
+
unsigned
recur_apoint_find_occurrence(struct recur_apoint *rapt, time_t day_start,
time_t *occurrence)
{
- return recur_item_find_occurrence(rapt->start, rapt->dur,
- &rapt->exc, rapt->rpt->type,
- rapt->rpt->freq,
- rapt->rpt->until, day_start,
- occurrence);
+ return recur_item_find_occurrence(rapt->start, rapt->dur, rapt->rpt,
+ &rapt->exc, day_start, occurrence);
}
unsigned
recur_event_find_occurrence(struct recur_event *rev, time_t day_start,
time_t *occurrence)
{
- return recur_item_find_occurrence(rev->day, -1, &rev->exc,
- rev->rpt->type, rev->rpt->freq,
- rev->rpt->until, day_start,
- occurrence);
+ return recur_item_find_occurrence(rev->day, -1, rev->rpt, &rev->exc,
+ day_start, occurrence);
}
/* Check if a recurrent item belongs to the selected day. */
unsigned
-recur_item_inday(time_t item_start, long item_dur, llist_t * item_exc,
- int rpt_type, int rpt_freq, time_t rpt_until,
+recur_item_inday(time_t start, long dur,
+ struct rpt *rpt, llist_t * exc,
time_t day_start)
{
/* We do not need the (real) start time of the occurrence here, so just
* ignore the buffer. */
- return recur_item_find_occurrence(item_start, item_dur, item_exc,
- rpt_type, rpt_freq, rpt_until,
+ return recur_item_find_occurrence(start, dur, rpt, exc,
day_start, NULL);
}
unsigned recur_apoint_inday(struct recur_apoint *rapt, time_t *day_start)
{
- return recur_item_inday(rapt->start, rapt->dur, &rapt->exc,
- rapt->rpt->type, rapt->rpt->freq,
- rapt->rpt->until, *day_start);
+ return recur_item_inday(rapt->start, rapt->dur, rapt->rpt, &rapt->exc,
+ *day_start);
}
unsigned recur_event_inday(struct recur_event *rev, time_t *day_start)
{
- return recur_item_inday(rev->day, -1, &rev->exc,
- rev->rpt->type, rev->rpt->freq,
- rev->rpt->until, *day_start);
+ return recur_item_inday(rev->day, -1, rev->rpt, &rev->exc,
+ *day_start);
}
/* Add an exception to a recurrent event. */
@@ -960,6 +1628,62 @@ void recur_apoint_erase(struct recur_apoint *rapt)
LLIST_TS_UNLOCK(&recur_alist_p);
}
+/* Read monthday list. */
+void recur_bymonthday(llist_t *l, FILE *data_file)
+{
+ int c = 0, d;
+
+ LLIST_INIT(l);
+ while ((c = getc(data_file)) == 'd') {
+ ungetc(c, data_file);
+ if (fscanf(data_file, "d%d ", &d) != 1)
+ EXIT(_("syntax error in bymonthday"));
+ int *i = mem_malloc(sizeof(int));
+ *i = d;
+ LLIST_ADD(l, i);
+ }
+ ungetc(c, data_file);
+}
+
+/* Read weekday list. */
+void recur_bywday(enum recur_type type, llist_t *l, FILE *data_file)
+{
+ int c = 0, w;
+
+ type = !(type == RECUR_MONTHLY || type == RECUR_YEARLY);
+
+ LLIST_INIT(l);
+ while ((c = getc(data_file)) == 'w') {
+ ungetc(c, data_file);
+ if (fscanf(data_file, "w%d ", &w) != 1)
+ EXIT(_("syntax error in bywday"));
+ if (type && (w < 0 || w > 6))
+ EXIT(_("illegal BYDAY value"));
+ int *i = mem_malloc(sizeof(int));
+ *i = w;
+ LLIST_ADD(l, i);
+ }
+ ungetc(c, data_file);
+}
+
+/* Read month list. */
+void recur_bymonth(llist_t *l, FILE *data_file)
+{
+ int c = 0, m;
+
+ LLIST_INIT(l);
+ while ((c = getc(data_file)) == 'm') {
+ ungetc(c, data_file);
+ if (fscanf(data_file, "m%d ", &m) != 1)
+ EXIT(_("syntax error in bymonth"));
+ EXIT_IF(m < 1 || m > 12, _("illegal bymonth value"));
+ int *i = mem_malloc(sizeof(int));
+ *i = m;
+ LLIST_ADD(l, i);
+ }
+ ungetc(c, data_file);
+}
+
/*
* Read days for which recurrent items must not be repeated
* (such days are called exceptions).
@@ -989,6 +1713,7 @@ void recur_exc_scan(llist_t * lexc, FILE * data_file)
exc->st = mktime(&day);
LLIST_ADD(lexc, exc);
}
+ ungetc(c, data_file);
}
/*
@@ -1088,3 +1813,75 @@ void recur_apoint_paste_item(struct recur_apoint *rapt, time_t date)
if (notify_bar())
notify_check_repeated(rapt);
}
+
+/*
+ * Finds the next occurrence of a recurrent item and returns it in the provided
+ * buffer. Useful for test of a repeated item.
+ */
+int recur_next_occurrence(time_t s, long d, struct rpt *r, llist_t *e,
+ time_t day, time_t *next)
+{
+ int ret = 0;
+
+ if (r->until && r->until <= day)
+ return ret;
+
+ while (!r->until || day < r->until) {
+ day = NEXTDAY(day);
+ if (!check_sec(&day))
+ break;
+ if (recur_item_find_occurrence(s, d, r, e, day, next)) {
+ /* Multi-day appointment. */
+ if (*next < day)
+ continue;
+ ret = 1;
+ break;
+ }
+ }
+ return ret;
+}
+
+/*
+ * Finds the nth occurrence (incl. start) of a recurrence rule (s, d, r, e)
+ * and returns it in the provided buffer.
+ */
+int recur_nth_occurrence(time_t s, long d, struct rpt *r, llist_t *e, int n,
+ time_t *nth)
+{
+ time_t day;
+
+ if (n <= 0)
+ return 0;
+
+ for (n--, *nth = s; n > 0; n--) {
+ day = DAY(*nth);
+ if (!recur_next_occurrence(s, d, r, e, day, nth))
+ break;
+ }
+ return !n;
+}
+
+/*
+ * Finds the previous occurrence - the most recent before day - and returns it
+ * in the provided buffer.
+ */
+int recur_prev_occurrence(time_t s, long d, struct rpt *r, llist_t *e,
+ time_t day, time_t *prev)
+{
+ int ret = 0;
+
+ if (day <= DAY(s))
+ return ret;
+
+ while (DAY(s) < day) {
+ day = PREVDAY(day);
+ if (recur_item_find_occurrence(s, d, r, e, day, prev)) {
+ /* Multi-day appointment. */
+ if (d != -1 && *prev < day && day < *prev + d)
+ continue;
+ ret = 1;
+ break;
+ }
+ }
+ return ret;
+}
diff --git a/src/sha1.c b/src/sha1.c
index 109dacc..6ab63f8 100644
--- a/src/sha1.c
+++ b/src/sha1.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -43,6 +43,7 @@
#include <stdlib.h>
#include <string.h>
+#include "config.h"
#include "sha1.h"
#define rol(val, n) (((val) << (n)) | ((val) >> (32 - (n))))
diff --git a/src/sha1.h b/src/sha1.h
index cb3953c..25d60b9 100644
--- a/src/sha1.h
+++ b/src/sha1.h
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -52,6 +52,6 @@ typedef struct {
void sha1_init(sha1_ctx_t *);
void sha1_update(sha1_ctx_t *, const uint8_t *, unsigned int);
-void sha1_final(sha1_ctx_t *, uint8_t *);
+void sha1_final(sha1_ctx_t *, uint8_t[SHA1_DIGESTLEN]);
void sha1_digest(const char *, char *);
void sha1_stream(FILE *, char *);
diff --git a/src/sigs.c b/src/sigs.c
index af1766e..9320652 100644
--- a/src/sigs.c
+++ b/src/sigs.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -68,27 +68,18 @@
/*
* General signal handling routine.
- * Catch return values from children (user-defined notification commands).
- * This is needed to avoid zombie processes running on system.
- * Also catch CTRL-C (SIGINT), and SIGWINCH to resize screen automatically.
+ * Catch SIGWINCH to resize screen automatically.
*/
static void generic_hdlr(int sig)
{
switch (sig) {
- case SIGCHLD:
- while (waitpid(WAIT_MYPGRP, NULL, WNOHANG) > 0) ;
- break;
case SIGWINCH:
resize = 1;
clearok(curscr, TRUE);
ungetch(KEY_RESIZE);
break;
case SIGTERM:
- if (unlink(path_cpid) != 0) {
- EXIT(_("Could not remove calcurse lock file: %s\n"),
- strerror(errno));
- }
- exit(EXIT_SUCCESS);
+ exit_calcurse(EXIT_SUCCESS);
break;
case SIGUSR1:
want_reload = 1;
@@ -117,12 +108,11 @@ unsigned sigs_set_hdlr(int sig, void (*handler) (int))
/* Signal handling init. */
void sigs_init()
{
- if (!sigs_set_hdlr(SIGCHLD, generic_hdlr)
- || !sigs_set_hdlr(SIGWINCH, generic_hdlr)
+ if (!sigs_set_hdlr(SIGWINCH, generic_hdlr)
|| !sigs_set_hdlr(SIGTERM, generic_hdlr)
|| !sigs_set_hdlr(SIGUSR1, generic_hdlr)
|| !sigs_set_hdlr(SIGINT, SIG_IGN))
- exit_calcurse(1);
+ exit_calcurse(EXIT_FAILURE);
}
/* Ignore SIGWINCH and SIGTERM signals. */
diff --git a/src/strings.c b/src/strings.c
index a84f836..ed90bc7 100644
--- a/src/strings.c
+++ b/src/strings.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -85,6 +85,7 @@ int string_vcatf(struct string *sb, const char *format, va_list ap)
ap2);
}
sb->len += n;
+ va_end(ap2);
return n;
}
diff --git a/src/todo.c b/src/todo.c
index ede3b50..9bd8f8a 100644
--- a/src/todo.c
+++ b/src/todo.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -158,9 +158,7 @@ void todo_delete(struct todo *todo)
*/
void todo_resort(struct todo *t)
{
- llist_item_t *i = LLIST_FIND_FIRST(&todolist, t, NULL);
- LLIST_REMOVE(&todolist, i);
- LLIST_ADD_SORTED(&todolist, t, todo_cmp);
+ LLIST_REORDER(&todolist, t, todo_cmp);
}
/* Flag a todo item. */
diff --git a/src/ui-calendar.c b/src/ui-calendar.c
index 6d301e6..c1719d8 100644
--- a/src/ui-calendar.c
+++ b/src/ui-calendar.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -45,14 +45,14 @@
#include "calcurse.h"
static struct date today, slctd_day;
-static unsigned ui_calendar_view, week_begins_on_monday;
+static unsigned ui_calendar_view;
+static int wday_start; /* this is used in signed arithmetic */
static pthread_mutex_t date_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
-static void draw_monthly_view(struct scrollwin *, struct date *, unsigned);
-static void draw_weekly_view(struct scrollwin *, struct date *, unsigned);
-static void (*draw_calendar[CAL_VIEWS]) (struct scrollwin *, struct date *,
- unsigned) = {
-draw_monthly_view, draw_weekly_view};
+static void draw_monthly_view(struct scrollwin *, struct date *);
+static void draw_weekly_view(struct scrollwin *, struct date *);
+static void (*draw_calendar[CAL_VIEWS]) (struct scrollwin *,
+ struct date *) = {draw_monthly_view, draw_weekly_view};
/* Six weeks cover a month. */
static int monthly_view_cache[WEEKINDAYS * 6];
@@ -148,30 +148,26 @@ struct date *ui_calendar_get_today(void)
/* Needed to display sunday or monday as the first day of week in calendar. */
void ui_calendar_set_first_day_of_week(enum wday first_day)
{
- switch (first_day) {
- case SUNDAY:
- week_begins_on_monday = 0;
- break;
- case MONDAY:
- week_begins_on_monday = 1;
- break;
- default:
+ if (first_day >= 0 && first_day <= 6)
+ wday_start = first_day;
+ else {
ERROR_MSG(_("ERROR setting first day of week"));
- week_begins_on_monday = 0;
- /* NOTREACHED */
+ wday_start = 0;
}
}
/* Swap first day of week in calendar. */
void ui_calendar_change_first_day_of_week(void)
{
- week_begins_on_monday = !week_begins_on_monday;
+ wday_start++;
+ if(wday_start >= WEEKINDAYS)
+ wday_start = 0;
}
/* Return 1 if week begins on monday, 0 otherwise. */
-unsigned ui_calendar_week_begins_on_monday(void)
+int ui_calendar_get_wday_start(void)
{
- return week_begins_on_monday;
+ return wday_start;
}
/* Fill in the given variable with the current date. */
@@ -219,18 +215,14 @@ void ui_calendar_monthly_view_cache_set_invalid(void)
monthly_view_cache_valid = 0;
}
-static int weeknum(const struct tm *t, int firstweekday)
+static int weeknum(const struct tm *t, int wday_start)
{
int wday, wnum;
wday = t->tm_wday;
- if (firstweekday == MONDAY) {
- if (wday == SUNDAY)
- wday = 6;
- else
- wday--;
- }
- wnum = ((t->tm_yday + WEEKINDAYS - wday) / WEEKINDAYS);
+ wnum = ((t->tm_yday + WEEKINDAYS + -modify_wday(wday, -wday_start))
+ / WEEKINDAYS);
+
if (wnum < 0)
wnum = 0;
@@ -296,7 +288,7 @@ static int ISO8601weeknum(const struct tm *t)
* Return the tm structure for the first day of the first week
* (containing a day) of the selected month.
*/
-static struct tm get_first_day(unsigned sunday_first)
+static struct tm get_first_day(int wday_start)
{
struct tm t;
struct date d;
@@ -308,26 +300,20 @@ static struct tm get_first_day(unsigned sunday_first)
t = date2tm(d, 0, 0);
mktime(&t);
/* get the first day of the week */
- date_change(&t, 0,
- -(sunday_first ?
- t.tm_wday :
- (t.tm_wday + WEEKINDAYS - 1) % WEEKINDAYS));
+ date_change(&t, 0, -modify_wday(t.tm_wday, -wday_start));
+
return t;
}
-static struct tm get_first_weekday(unsigned sunday_first)
+static struct tm get_first_weekday(int wday_start)
{
- int c_wday, days_to_remove;
+ int c_wday;
struct tm t;
c_wday = ui_calendar_get_wday(&slctd_day);
- if (sunday_first)
- days_to_remove = c_wday;
- else
- days_to_remove = c_wday == 0 ? WEEKINDAYS - 1 : c_wday - 1;
-
t = date2tm(slctd_day, 0, 0);
- date_change(&t, 0, -days_to_remove);
+
+ date_change(&t, 0, -modify_wday(c_wday, -wday_start));
return t;
}
@@ -346,8 +332,7 @@ static void draw_week_number(struct scrollwin *sw, struct tm t)
/* Draw the monthly view inside calendar panel. */
static void
-draw_monthly_view(struct scrollwin *sw, struct date *current_day,
- unsigned sunday_first)
+draw_monthly_view(struct scrollwin *sw, struct date *current_day)
{
struct date c_day;
int slctd, w_day, numdays, j, week = 0;
@@ -373,7 +358,7 @@ draw_monthly_view(struct scrollwin *sw, struct date *current_day,
* Step forward by week until past the last day of the month.
* The first day of the first week may belong to the previous month.
*/
- t = t_first = get_first_day(sunday_first);
+ t = t_first = get_first_day(wday_start);
t.tm_mday += WEEKINDAYS;
mktime(&t);
last_day += WEEKINDAYS;
@@ -423,7 +408,7 @@ draw_monthly_view(struct scrollwin *sw, struct date *current_day,
custom_apply_attr(sw->inner, ATTR_HIGHEST);
for (j = 0; j < WEEKINDAYS; j++) {
mvwaddstr(sw->inner, ofs_y, ofs_x + weekw + 4 * j,
- nl_langinfo(ABDAY_1 + (1 + j - sunday_first) % WEEKINDAYS));
+ nl_langinfo(ABDAY_1 + modify_wday(j, wday_start)));
}
custom_remove_attr(sw->inner, ATTR_HIGHEST);
WINS_CALENDAR_UNLOCK;
@@ -449,11 +434,9 @@ draw_monthly_view(struct scrollwin *sw, struct date *current_day,
if (j == first_day ||
(mo == 1 && j == WEEKINDAYS) ||
(mo == 12 && j >= 4 * WEEKINDAYS)) {
- if (sunday_first)
- date_change(&t, 0, 1);
+ date_change(&t, 0, WDAY(MONDAY));
week = ISO8601weeknum(&t);
- if (sunday_first)
- date_change(&t, 0, -1);
+ date_change(&t, 0, -WDAY(MONDAY));
} else
week++;
}
@@ -506,8 +489,7 @@ draw_monthly_view(struct scrollwin *sw, struct date *current_day,
/* Draw the weekly view inside calendar panel. */
static void
-draw_weekly_view(struct scrollwin *sw, struct date *current_day,
- unsigned sunday_first)
+draw_weekly_view(struct scrollwin *sw, struct date *current_day)
{
#define DAYSLICESNO 6
const int WCALWIDTH = 28;
@@ -520,14 +502,14 @@ draw_weekly_view(struct scrollwin *sw, struct date *current_day,
OFFX = (wins_sbar_width() - 2 - WCALWIDTH) / 2;
/* Print the week number, calculated from monday. */
- t = get_first_weekday(0);
+ t = get_first_weekday(MONDAY);
draw_week_number(sw, t);
/* Now draw calendar view. */
for (j = 0; j < WEEKINDAYS; j++) {
/* get next day */
if (j == 0)
- t = get_first_weekday(sunday_first);
+ t = get_first_weekday(wday_start);
else
date_change(&t, 0, 1);
@@ -538,7 +520,7 @@ draw_weekly_view(struct scrollwin *sw, struct date *current_day,
/* print the day names, with regards to the first day of the week */
custom_apply_attr(sw->inner, ATTR_HIGHEST);
mvwaddstr(sw->inner, OFFY, OFFX + 4 * j,
- nl_langinfo(ABDAY_1 + (1 + j - sunday_first) % WEEKINDAYS));
+ nl_langinfo(ABDAY_1 + modify_wday(j, wday_start)));
custom_remove_attr(sw->inner, ATTR_HIGHEST);
/* Check if the day to be printed has an item or not. */
@@ -578,9 +560,8 @@ draw_weekly_view(struct scrollwin *sw, struct date *current_day,
if (j != WEEKINDAYS - 1
&& i != DAYSLICESNO - 1) {
WINS_CALENDAR_LOCK;
- mvwhline(sw->inner, OFFY + 2 + i,
- OFFX + 3 + 4 * j, ACS_S9,
- 2);
+ mvwaddstr(sw->inner, OFFY + 2 + i,
+ OFFX + 3 + 4 * j, "__");
WINS_CALENDAR_UNLOCK;
}
if (slices[i]) {
@@ -611,9 +592,9 @@ draw_weekly_view(struct scrollwin *sw, struct date *current_day,
/* Draw marks to indicate midday on the sides of the calendar. */
WINS_CALENDAR_LOCK;
custom_apply_attr(sw->inner, ATTR_HIGHEST);
- mvwhline(sw->inner, OFFY + 1 + DAYSLICESNO / 2, OFFX, ACS_S9, 1);
- mvwhline(sw->inner, OFFY + 1 + DAYSLICESNO / 2,
- OFFX + WCALWIDTH - 1, ACS_S9, 1);
+ mvwaddch(sw->inner, OFFY + 1 + DAYSLICESNO / 2, OFFX, '<');
+ mvwaddch(sw->inner, OFFY + 1 + DAYSLICESNO / 2,
+ OFFX + WCALWIDTH - 1, '>');
custom_remove_attr(sw->inner, ATTR_HIGHEST);
WINS_CALENDAR_UNLOCK;
@@ -624,11 +605,9 @@ draw_weekly_view(struct scrollwin *sw, struct date *current_day,
void ui_calendar_update_panel(void)
{
struct date current_day;
- unsigned sunday_first;
ui_calendar_store_current_date(&current_day);
- sunday_first = !ui_calendar_week_begins_on_monday();
- draw_calendar[ui_calendar_view] (&sw_cal, &current_day, sunday_first);
+ draw_calendar[ui_calendar_view] (&sw_cal, &current_day);
wins_scrollwin_display(&sw_cal, NOHILT);
}
@@ -728,28 +707,14 @@ void ui_calendar_move(enum move move, int count)
ret = date_change(&t, count * YEARINMONTHS, 0);
break;
case WEEK_START:
- /* Normalize struct tm to get week day number. */
mktime(&t);
- if (ui_calendar_week_begins_on_monday())
- days_to_remove =
- ((t.tm_wday ==
- 0) ? WEEKINDAYS - 1 : t.tm_wday - 1);
- else
- days_to_remove =
- ((t.tm_wday == 0) ? 0 : t.tm_wday);
+ days_to_remove = WDAY(t.tm_wday);
days_to_remove += (count - 1) * WEEKINDAYS;
ret = date_change(&t, 0, -days_to_remove);
break;
case WEEK_END:
mktime(&t);
- if (ui_calendar_week_begins_on_monday())
- days_to_add =
- ((t.tm_wday ==
- 0) ? 0 : WEEKINDAYS - t.tm_wday);
- else
- days_to_add = ((t.tm_wday == 0) ?
- WEEKINDAYS - 1 : WEEKINDAYS - 1 -
- t.tm_wday);
+ days_to_add = modify_wday(-t.tm_wday, wday_start - 1);
days_to_add += (count - 1) * WEEKINDAYS;
ret = date_change(&t, 0, days_to_add);
break;
diff --git a/src/ui-day.c b/src/ui-day.c
index e0e306b..6a038fa 100644
--- a/src/ui-day.c
+++ b/src/ui-day.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,9 +34,12 @@
*
*/
+#include <limits.h>
+#include <langinfo.h>
#include "calcurse.h"
-struct day_item day_cut[38] = { {0, 0, 0, {NULL}} };
+/* Cut & paste registers. */
+static struct day_item day_cut[REG_BLACK_HOLE + 1];
/*
* Set the selected day in the calendar from the selected item in the APP panel.
@@ -76,7 +79,7 @@ void ui_day_find_sel(void)
*/
time_t ui_day_sel_date(void)
{
- return update_time_in_date(ui_day_get_sel()->order, 0, 0);
+ return DAY(ui_day_get_sel()->order);
}
/*
@@ -162,32 +165,44 @@ static time_t day_edit_time(time_t start, long duration, int move)
/*
* Change start time or move an item.
* Input/output: start and dur.
+ * For recurrent items the new start time must match the repetition pattern.
* If move = 0, end time is fixed, and the new duration is calculated
* when the new start time is known.
* If move = 1, duration is fixed, but passed on for validation of new end time.
*/
-static void update_start_time(time_t *start, long *dur, int move)
+static void update_start_time(time_t *start, long *dur, struct rpt *rpt, int move)
{
time_t newtime;
const char *msg_wrong_time =
_("Invalid time: start time must come before end time!");
+ char *msg_match =
+ _("Repetition must begin on start day (%s).");
const char *msg_enter = _("Press [Enter] to continue");
+ char *msg;
for (;;) {
newtime = day_edit_time(*start, *dur, move);
if (!newtime)
break;
- if (move) {
- *start = newtime;
- break;
+ if (rpt && !recur_item_find_occurrence(newtime, *dur, rpt, NULL,
+ DAY(newtime),
+ NULL)) {
+ msg = day_ins(&msg_match, newtime);
+ status_mesg(msg, msg_enter);
+ mem_free(msg);
} else {
- if (newtime <= *start + *dur) {
- *dur -= (newtime - *start);
+ if (move) {
*start = newtime;
break;
+ } else {
+ if (newtime <= *start + *dur) {
+ *dur -= (newtime - *start);
+ *start = newtime;
+ break;
+ }
}
+ status_mesg(msg_wrong_time, msg_enter);
}
- status_mesg(msg_wrong_time, msg_enter);
keys_wgetch(win[KEY].p);
}
return;
@@ -272,8 +287,8 @@ static void update_desc(char **desc)
updatestring(win[STA].p, desc, 0, 1);
}
-/* Edit the list of exception days for a recurrent item. */
-static int update_exc(llist_t *exc)
+/* Edit a list of exception days for a recurrent item. */
+static int edit_exc(llist_t *exc)
{
int updated = 0;
@@ -287,7 +302,7 @@ static int update_exc(llist_t *exc)
while (1) {
ret = updatestring(win[STA].p, &days, 0, 1);
if (ret == GETSTRING_VALID || ret == GETSTRING_RET) {
- if (recur_update_exc(exc, days)) {
+ if (recur_str2exc(exc, days)) {
updated = 1;
break;
} else {
@@ -303,97 +318,446 @@ static int update_exc(llist_t *exc)
return updated;
}
-static void update_rept(struct rpt **rpt, const time_t start, llist_t *exc)
+/*
+ * Decode an integer representing a weekday or ordered weekday.
+ * The return value is the (abbreviated) localized day name.
+ * The order is returned in the second argument.
+ */
+static char *int2wday(int i, int *ord, int_list_t type)
{
- /* Pointers to dynamically allocated memory. */
- char *msg_rpt_current = NULL;
- char *msg_rpt_asktype = NULL;
+ if (type == BYDAY_W ||
+ ((type == BYDAY_M || type == BYDAY_Y) && -1 < i && i < 7))
+ *ord = 0;
+ else if ((type == BYDAY_M && 6 < i && i < 42) ||
+ (type == BYDAY_Y && 6 < i && i < 378))
+ *ord = i / 7;
+ else if ((type == BYDAY_M && -42 < i && i < -6) ||
+ (type == BYDAY_Y && -378 < i && i < -6)) {
+ i = -i;
+ *ord = -(i / 7);
+ } else
+ return NULL;
+
+ return nl_langinfo(ABDAY_1 + i % 7);
+}
+
+/*
+ * Given a (linked) list of integers representing weekdays, monthdays or months.
+ * Return a string containing the weekdays or integers separated by spaces.
+ */
+static char *int2str(llist_t *il, int_list_t type)
+{
+ llist_item_t *i;
+ int *p, ord = 0;
+ char *wday;
+ struct string s;
+
+ string_init(&s);
+ LLIST_FOREACH(il, i) {
+ p = LLIST_GET_DATA(i);
+ wday = int2wday(*p, &ord, type);
+ if (wday)
+ string_catf(&s, ord ? "%d%s " : "%.0d%s ", ord, wday);
+ else
+ string_catf(&s, "%i ", *p);
+ }
+
+ return string_buf(&s);
+}
+
+/*
+ * Encode a weekday or ordered weekday as an integer.
+ */
+static int wday2int(char *s)
+{
+ int i, ord;
+ char *tail;
+
+ i = strtol(s, &tail, 10);
+ if (!i && tail == s)
+ ord = 0;
+ else
+ ord = i > 0 ? i : -i;
+
+ if (!strcmp(tail, nl_langinfo(ABDAY_1)))
+ return (i < 0 ? -1 : 1) * (ord * 7 + 0);
+ else if (!strcmp(tail, nl_langinfo(ABDAY_2)))
+ return (i < 0 ? -1 : 1) * (ord * 7 + 1);
+ else if (!strcmp(tail, nl_langinfo(ABDAY_3)))
+ return (i < 0 ? -1 : 1) * (ord * 7 + 2);
+ else if (!strcmp(tail, nl_langinfo(ABDAY_4)))
+ return (i < 0 ? -1 : 1) * (ord * 7 + 3);
+ else if (!strcmp(tail, nl_langinfo(ABDAY_5)))
+ return (i < 0 ? -1 : 1) * (ord * 7 + 4);
+ else if (!strcmp(tail, nl_langinfo(ABDAY_6)))
+ return (i < 0 ? -1 : 1) * (ord * 7 + 5);
+ else if (!strcmp(tail, nl_langinfo(ABDAY_7)))
+ return (i < 0 ? -1 : 1) * (ord * 7 + 6);
+ else
+ return -1;
+}
+
+/*
+ * Parse an integer or weekday string. Valid values depend on type.
+ * On success the integer or integer code is returned in *i.
+ */
+static int parse_int(char *s, long *i, int_list_t type)
+{
+ char *eos;
+
+ if (type == BYDAY_W || type == BYDAY_M || type == BYDAY_Y) {
+ *i = wday2int(s);
+ if (*i == -1)
+ return 0;
+ } else {
+ *i = strtol(s, &eos, 10);
+ if (*eos || *i > INT_MAX)
+ return 0;
+ }
+
+ switch (type) {
+ case BYMONTH:
+ /* 1,..,12 */
+ if (0 < *i && *i < 13)
+ return 1;
+ break;
+ case BYDAY_W:
+ /* 0,..,6 */
+ if (-1 < *i && *i < 7)
+ return 1;
+ break;
+ case BYDAY_M:
+ /* 0,..,6 or 7,..,41 or -7,..,-41 */
+ /* 41 = 5*7 + 6, i.e. fifth Saturday of the month */
+ if ((-42 < *i && *i < -6) || (-1 < *i && *i < 42))
+ return 1;
+ break;
+ case BYDAY_Y:
+ /* 0,..,6 or 7,..,377 or -7,..,-377 */
+ /* 377 = 53*7 + 6, i.e. 53th Saturday of the year */
+ if ((-378 < *i && *i < -6) || (-1 < *i && *i < 378))
+ return 1;
+ break;
+ case BYMONTHDAY:
+ /* 1,..,31 or -1,..,-31 */
+ if ((0 < *i && *i < 32) || (-32 < *i && *i < 0))
+ return 1;
+ break;
+ default:
+ return 0;
+ }
+ return 0;
+}
+
+/*
+ * Update a (linked) list of integer values from a string of such values. Any
+ * positive number of spaces are allowed before, between and after the values.
+ */
+static int str2int(llist_t *l, char *s, int type) {
+ int *j, updated = 0;
+ char *c;
+ long i;
+ llist_t nl;
+ LLIST_INIT(&nl);
+
+ while (1) {
+ while (*s == ' ')
+ s++;
+ if ((c = strchr(s, ' ')))
+ *c = '\0';
+ else if (!strlen(s))
+ break;
+ if (parse_int(s, &i, type)) {
+ j = mem_malloc(sizeof(int));
+ *j = i;
+ LLIST_ADD(&nl, j);
+ } else
+ goto cleanup;
+ if (c)
+ s = c + 1;
+ else
+ break;
+ }
+ recur_free_int_list(l);
+ recur_int_list_dup(l, &nl);
+ updated = 1;
+cleanup:
+ recur_free_int_list(&nl);
+ return updated;
+}
+
+static void help_ilist(int_list_t list, int rule)
+{
+ char *msg1 = "";
+ char *msg2 = "";
+ char *byday_w_d = _("Limit repetition to listed days.");
+ char *byday_w_w = _("Expand repetition to listed days.");
+ char *byday_m_m_1 =
+ _("Expand repetition to listed days, either all or 1st, 2nd, ... of month.");
+ char *byday_m_m_2 =
+ _("Note: limit to monthdays, if any.");
+ char *byday_y_y_1 =
+ _("Expand repetition to listed days, either all or 1st, 2nd, ... of year.");
+ char *byday_y_y_2 =
+ _("Note: expand to listed months, if any; limit to monthdays, if any.");
+ char *bymonth_dwm =
+ _("Limit repetition to listed months.");
+ char *bymonth_y =
+ _("Expand repetition to listed months.");
+ char *bymonthday_d = _("Limit repetition to listed days of month.");
+ char *bymonthday_my = _("Expand repetition to listed days of month.");
+
+
+ switch (list) {
+ case BYDAY_W:
+ switch (rule) {
+ case RECUR_DAILY:
+ msg1 = byday_w_d;
+ msg2 = "";
+ break;
+ case RECUR_WEEKLY:
+ msg1 = byday_w_w;
+ msg2 = "";
+ break;
+ default:
+ EXIT("internal inconsistency");
+ }
+ break;
+ case BYDAY_M:
+ switch (rule) {
+ case RECUR_MONTHLY:
+ msg1 = byday_m_m_1;
+ msg2 = byday_m_m_2;
+ break;
+ default:
+ EXIT("internal inconsistency");
+ }
+ break;
+ case BYDAY_Y:
+ switch (rule) {
+ case RECUR_YEARLY:
+ msg1 = byday_y_y_1;
+ msg2 = byday_y_y_2;
+ break;
+ default:
+ EXIT("internal inconsistency");
+ }
+ break;
+ case BYMONTH:
+ switch (rule) {
+ case RECUR_DAILY:
+ case RECUR_WEEKLY:
+ case RECUR_MONTHLY:
+ msg1 = bymonth_dwm;
+ msg2 = "";
+ break;
+ case RECUR_YEARLY:
+ msg1 = bymonth_y;
+ msg2 = "";
+ break;
+ default:
+ break;
+ }
+ break;
+ case BYMONTHDAY:
+ switch (rule) {
+ case RECUR_DAILY:
+ msg1 = bymonthday_d;
+ msg2 = "";
+ break;
+ case RECUR_MONTHLY:
+ case RECUR_YEARLY:
+ msg1 = bymonthday_my;
+ msg2 = "";
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ status_mesg(msg1, msg2);
+ keys_wgetch(win[KEY].p);
+}
+
+/* Edit an rrule (linked) list of integers. */
+static int edit_ilist(llist_t *ilist, int_list_t list_type, int rule_type)
+{
+ char *msg;
+ char *wday = NULL;
+ char *wday_w = _("Weekdays %s|..|%s, space-separated list, '?' for help:");
+ char *wday_m =
+ _("Weekdays [n]%s|..|[n]%s, space-separated list, n=1,-1,..,5,-5, '?' for help:");
+ char *wday_y =
+ _("Weekdays [n]%s|..|[n]%s, space-separated list, n=1,-1,..,53,-53, '?' for help:");
+ char *month = _("Months 1|..|12, space-separated list, '?' for help:");
+ char *mday = _("Monthdays 1|..|31 or -1|..|-31, space-separated list, '?' for help:");
+ char *invalid = _("Invalid format - try again.");
+ char *cont = _("Press any key to continue.");
+ int updated = 0;
+
+ if (list_type == NOLL)
+ return !updated;
+ char *istr;
+ enum getstr ret;
+
+ switch (list_type) {
+ case BYDAY_W:
+ asprintf(&wday, wday_w,
+ nl_langinfo(ABDAY_2), nl_langinfo(ABDAY_1));
+ msg = wday;
+ break;
+ case BYDAY_M:
+ asprintf(&wday, wday_m,
+ nl_langinfo(ABDAY_2), nl_langinfo(ABDAY_1));
+ msg = wday;
+ break;
+ case BYDAY_Y:
+ asprintf(&wday, wday_y,
+ nl_langinfo(ABDAY_2), nl_langinfo(ABDAY_1));
+ msg = wday;
+ break;
+ case BYMONTH:
+ msg = month;
+ break;
+ case BYMONTHDAY:
+ msg = mday;
+ break;
+ default:
+ msg = NULL;
+ break;
+ }
+ status_mesg(msg, "");
+ istr = int2str(ilist, list_type);
+ while (1) {
+ ret = updatestring(win[STA].p, &istr, 0, 1);
+ if (ret == GETSTRING_VALID || ret == GETSTRING_RET) {
+ if (*(istr + strlen(istr) - 1) == '?')
+ help_ilist(list_type, rule_type);
+ else if (str2int(ilist, istr, list_type)) {
+ updated = 1;
+ break;
+ } else {
+ status_mesg(invalid, cont);
+ keys_wgetch(win[KEY].p);
+ }
+ mem_free(istr);
+ status_mesg(msg, "");
+ istr = int2str(ilist, list_type);
+ } else if (ret == GETSTRING_ESC)
+ break;
+ }
+ mem_free(istr);
+ mem_free(wday);
+
+ return updated;
+}
+
+static int update_rept(time_t start, long dur, struct rpt **rpt, llist_t *exc,
+ int simple)
+{
+ int updated = 0, count;
+ struct rpt nrpt;
+ time_t until;
+ char *types = NULL;
char *freqstr = NULL;
char *timstr = NULL;
char *outstr = NULL;
+ const char *msg_cont = _("Press any key to continue.");
- /* Update repetition type. */
- int newtype;
- const char *msg_rpt_prefix = _("Enter the new repetition type:");
- const char *msg_rpt_daily = _("(d)aily");
- const char *msg_rpt_weekly = _("(w)eekly");
- const char *msg_rpt_monthly = _("(m)onthly");
- const char *msg_rpt_yearly = _("(y)early");
+ LLIST_INIT(&nrpt.exc);
+ LLIST_INIT(&nrpt.bywday);
+ LLIST_INIT(&nrpt.bymonth);
+ LLIST_INIT(&nrpt.bymonthday);
+
+ /* Edit repetition type. */
+ const char *msg_prefix = _("Base period:");
+ const char *daily = _("day");
+ const char *weekly = _("week");
+ const char *monthly = _("month");
+ const char *yearly = _("year");
+ const char *dwmy = _("[dwmy]");
/* Find the current repetition type. */
- const char *rpt_current;
+ const char *current;
switch (recur_def2char((*rpt)->type)) {
case 'D':
- rpt_current = msg_rpt_daily;
+ current = daily;
break;
case 'W':
- rpt_current = msg_rpt_weekly;
+ current = weekly;
break;
case 'M':
- rpt_current = msg_rpt_monthly;
+ current = monthly;
break;
case 'Y':
- rpt_current = msg_rpt_yearly;
+ current = yearly;
break;
default:
- /* NOTREACHED, but makes the compiler happier. */
- rpt_current = msg_rpt_daily;
+ /* New item. */
+ current = "";
}
- asprintf(&msg_rpt_current, _("(currently using %s)"), rpt_current);
- asprintf(&msg_rpt_asktype, "%s %s, %s, %s, %s? %s", msg_rpt_prefix,
- msg_rpt_daily, msg_rpt_weekly, msg_rpt_monthly,
- msg_rpt_yearly, msg_rpt_current);
- const char *msg_rpt_choice = _("[dwmy]");
- switch (status_ask_choice(msg_rpt_asktype, msg_rpt_choice, 4)) {
+ asprintf(&types, "%s %s/%s/%s/%s?",
+ msg_prefix, daily, weekly, monthly, yearly);
+ if (current[0])
+ asprintf(&types, "%s [%s]", types, current);
+ switch (status_ask_choice(types, dwmy, 4)) {
case 1:
- newtype = 'D';
+ nrpt.type = recur_char2def('D');
break;
case 2:
- newtype = 'W';
+ nrpt.type = recur_char2def('W');
break;
case 3:
- newtype = 'M';
+ nrpt.type = recur_char2def('M');
break;
case 4:
- newtype = 'Y';
+ nrpt.type = recur_char2def('Y');
break;
+ case -2: /* user typed RETURN */
+ if (current[0]) {
+ nrpt.type = (*rpt)->type;
+ break;
+ }
default:
goto cleanup;
}
- /* Update frequency. */
- int newfreq;
- const char *msg_wrong_freq = _("Invalid frequency.");
- const char *msg_enter = _("Press [Enter] to continue");
+ /* Edit frequency. */
+ const char *msg_freq = _("Frequency:");
+ const char *msg_inv_freq = _("Invalid frequency.");
do {
- status_mesg(_("Enter the repetition frequency:"), "");
+ status_mesg(msg_freq, "");
mem_free(freqstr);
asprintf(&freqstr, "%d", (*rpt)->freq);
if (updatestring(win[STA].p, &freqstr, 0, 1) !=
GETSTRING_VALID) {
goto cleanup;
}
- newfreq = atoi(freqstr);
- if (newfreq == 0) {
- status_mesg(msg_wrong_freq, msg_enter);
+ nrpt.freq = atoi(freqstr);
+ if (nrpt.freq <= 0) {
+ status_mesg(msg_inv_freq, msg_cont);
keys_wait_for_any_key(win[KEY].p);
}
}
- while (newfreq == 0);
+ while (nrpt.freq <= 0);
- /* Update end date. */
- time_t newuntil;
+ /* Edit until date. */
const char *msg_until_1 =
- _("Enter end date or duration ('?' for input formats):");
+ _("Until date, increment or repeat count ('?' for input formats):");
const char *msg_help_1 =
- _("Date: %s (year or month may be omitted). Endless duration: 0.");
+ _("Date: %s (year, month may be omitted, endless: 0).");
const char *msg_help_2 =
- _("Duration in days: +dd. Duration in weeks and days: +??w??d.");
- const char *msg_wrong_time =
- _("Invalid date: end date must come after start date (%s).");
- const char *msg_wrong_date = _("Invalid date.");
+ _("Increment: +?? (days) or: +??w??d (weeks). "
+ "Repeat count: #?? (number).");
+ const char *msg_inv_until =
+ _("Invalid date: until date must come after start date (%s).");
+ const char *msg_inv_date = _("Invalid date.");
+ const char *msg_count = _("Repeat count is too big.");
for (;;) {
+ count = 0;
mem_free(timstr);
if ((*rpt)->until)
timstr = date_sec2date_str((*rpt)->until, DATEFMT(conf.input_datefmt));
@@ -403,7 +767,7 @@ static void update_rept(struct rpt **rpt, const time_t start, llist_t *exc)
if (updatestring(win[STA].p, &timstr, 0, 1) == GETSTRING_ESC)
goto cleanup;
if (strcmp(timstr, "") == 0 || strcmp(timstr, "0") == 0) {
- newuntil = 0;
+ nrpt.until = 0;
break;
}
if (*(timstr + strlen(timstr) - 1) == '?') {
@@ -415,56 +779,160 @@ static void update_rept(struct rpt **rpt, const time_t start, llist_t *exc)
}
if (*timstr == '+') {
unsigned days;
- if (!parse_date_duration(timstr + 1, &days, start)) {
- status_mesg(msg_wrong_date, msg_enter);
+ if (!parse_date_increment(timstr + 1, &days, start)) {
+ status_mesg(msg_inv_date, msg_cont);
keys_wgetch(win[KEY].p);
continue;
}
/* Until is midnight of the day. */
- newuntil = date_sec_change(
- update_time_in_date(start, 0, 0),
- 0, days
- );
+ nrpt.until = date_sec_change(DAY(start), 0, days);
+ } else if (*timstr == '#') {
+ char *eos;
+ count = strtol(timstr + 1, &eos, 10);
+ if (*eos || !(count > 0))
+ continue;
+ nrpt.until = 0;
+ if (!recur_nth_occurrence(start, dur, &nrpt, exc,
+ count, &until)) {
+ status_mesg(msg_count, msg_cont);
+ keys_wgetch(win[KEY].p);
+ continue;
+ }
+ nrpt.until = DAY(until);
+ break;
} else {
int year, month, day;
if (!parse_date(timstr, conf.input_datefmt, &year,
&month, &day, ui_calendar_get_slctd_day())) {
- status_mesg(msg_wrong_date, msg_enter);
+ status_mesg(msg_inv_date, msg_cont);
keys_wgetch(win[KEY].p);
continue;
}
struct date d = { day, month, year };
- newuntil = date2sec(d, 0, 0);
+ nrpt.until = date2sec(d, 0, 0);
}
/* Conmpare days (midnights) - until-day may equal start day. */
- if (newuntil >= update_time_in_date(start, 0, 0))
+ if (nrpt.until >= DAY(start))
break;
mem_free(timstr);
mem_free(outstr);
timstr = date_sec2date_str(start, DATEFMT(conf.input_datefmt));
- asprintf(&outstr, msg_wrong_time, timstr);
- status_mesg(outstr, msg_enter);
+ asprintf(&outstr, msg_inv_until, timstr);
+ status_mesg(outstr, msg_cont);
keys_wgetch(win[KEY].p);
}
- /* Update exception list. */
- if (!update_exc(exc))
+ if (simple) {
+ (*rpt)->type = nrpt.type;
+ (*rpt)->freq = nrpt.freq;
+ (*rpt)->until = nrpt.until;
+ updated = 1;
goto cleanup;
+ }
+
+ /* Edit exception list. */
+ recur_exc_dup(&nrpt.exc, exc);
+ if (!edit_exc(&nrpt.exc))
+ goto cleanup;
+
+ /* Edit BYDAY list. */
+ int_list_t byday_type;
+ switch (nrpt.type) {
+ case RECUR_DAILY:
+ byday_type = BYDAY_W;
+ break;
+ case RECUR_WEEKLY:
+ byday_type = BYDAY_W;
+ break;
+ case RECUR_MONTHLY:
+ byday_type = BYDAY_M;
+ break;
+ case RECUR_YEARLY:
+ byday_type = BYDAY_Y;
+ break;
+ default:
+ byday_type = NOLL;
+ break;
+ }
+ recur_int_list_dup(&nrpt.bywday, &(*rpt)->bywday);
+ if (!edit_ilist(&nrpt.bywday, byday_type, nrpt.type))
+ goto cleanup;
+
+ /* Edit BYMONTH list. */
+ recur_int_list_dup(&nrpt.bymonth, &(*rpt)->bymonth);
+ if (!edit_ilist(&nrpt.bymonth, BYMONTH, nrpt.type))
+ goto cleanup;
+
+ /* Edit BYMONTHDAY list. */
+ if (nrpt.type != RECUR_WEEKLY) {
+ recur_int_list_dup(&nrpt.bymonthday, &(*rpt)->bymonthday);
+ if (!edit_ilist(&nrpt.bymonthday, BYMONTHDAY, nrpt.type))
+ goto cleanup;
+ }
+
+ /* The new until may no longer be valid. */
+ if (count) {
+ nrpt.until = 0;
+ if (!recur_nth_occurrence(start, dur, &nrpt, exc,
+ count, &until)) {
+ status_mesg(msg_count, msg_cont);
+ keys_wgetch(win[KEY].p);
+ goto cleanup;
+ }
+ nrpt.until = DAY(until);
+ }
+ /*
+ * Check whether the start occurrence matches the recurrence rule, in
+ * other words, does it occur on the start day? This is required by
+ * RFC5545 and ensures that the recurrence set is non-empty (unless it
+ * is an exception day).
+ */
+ char *msg_match =
+ _("Repetition must begin on start day (%s); "
+ "any change discarded.");
+ if (!recur_item_find_occurrence(start, dur, &nrpt, NULL, DAY(start),
+ NULL)) {
+ mem_free(outstr);
+ outstr = day_ins(&msg_match, start);
+ status_mesg(outstr, msg_cont);
+ keys_wgetch(win[KEY].p);
+ goto cleanup;
+ }
+
+ /* Update all recurrence parameters. */
+ (*rpt)->type = nrpt.type;
+ (*rpt)->freq = nrpt.freq;
+ (*rpt)->until = nrpt.until;
+
+ recur_free_exc_list(exc);
+ recur_exc_dup(exc, &nrpt.exc);
+
+ recur_free_int_list(&(*rpt)->bywday);
+ recur_int_list_dup(&(*rpt)->bywday, &nrpt.bywday);
+
+ recur_free_int_list(&(*rpt)->bymonth);
+ recur_int_list_dup(&(*rpt)->bymonth, &nrpt.bymonth);
- (*rpt)->type = recur_char2def(newtype);
- (*rpt)->freq = newfreq;
- (*rpt)->until = newuntil;
+ recur_free_int_list(&(*rpt)->bymonthday);
+ recur_int_list_dup(&(*rpt)->bymonthday, &nrpt.bymonthday);
+ updated = 1;
cleanup:
- mem_free(msg_rpt_current);
- mem_free(msg_rpt_asktype);
+ mem_free(types);
mem_free(freqstr);
mem_free(timstr);
mem_free(outstr);
+ recur_free_exc_list(&nrpt.exc);
+ recur_free_int_list(&nrpt.bywday);
+ recur_free_int_list(&nrpt.bymonth);
+ recur_free_int_list(&nrpt.bymonthday);
+
+ return updated;
}
/* Edit an already existing item. */
+#define ADVANCED 0
void ui_day_item_edit(void)
{
struct recur_event *re;
@@ -481,7 +949,7 @@ void ui_day_item_edit(void)
switch (p->type) {
case RECUR_EVNT:
re = p->item.rev;
- const char *choice_recur_evnt[2] = {
+ const char *choice_recur_evnt[] = {
_("Description"),
_("Repetition")
};
@@ -489,11 +957,9 @@ void ui_day_item_edit(void)
(_("Edit: "), choice_recur_evnt, 2)) {
case 1:
update_desc(&re->mesg);
- io_set_modified();
break;
case 2:
- update_rept(&re->rpt, re->day, &re->exc);
- io_set_modified();
+ update_rept(re->day, -1, &re->rpt, &re->exc, ADVANCED);
break;
default:
return;
@@ -502,7 +968,6 @@ void ui_day_item_edit(void)
case EVNT:
e = p->item.ev;
update_desc(&e->mesg);
- io_set_modified();
break;
case RECUR_APPT:
ra = p->item.rapt;
@@ -517,29 +982,25 @@ void ui_day_item_edit(void)
(_("Edit: "), choice_recur_appt, 5)) {
case 1:
need_check_notify = 1;
- update_start_time(&ra->start, &ra->dur, ra->dur == 0);
- io_set_modified();
+ update_start_time(&ra->start, &ra->dur, ra->rpt, ra->dur == 0);
break;
case 2:
update_duration(&ra->start, &ra->dur);
- io_set_modified();
break;
case 3:
if (notify_bar())
need_check_notify =
notify_same_recur_item(ra);
update_desc(&ra->mesg);
- io_set_modified();
break;
case 4:
need_check_notify = 1;
- update_rept(&ra->rpt, ra->start, &ra->exc);
- io_set_modified();
+ update_rept(ra->start, ra->dur, &ra->rpt, &ra->exc,
+ ADVANCED);
break;
case 5:
need_check_notify = 1;
- update_start_time(&ra->start, &ra->dur, 1);
- io_set_modified();
+ update_start_time(&ra->start, &ra->dur, ra->rpt, 1);
break;
default:
return;
@@ -557,24 +1018,20 @@ void ui_day_item_edit(void)
(_("Edit: "), choice_appt, 4)) {
case 1:
need_check_notify = 1;
- update_start_time(&a->start, &a->dur, a->dur == 0);
- io_set_modified();
+ update_start_time(&a->start, &a->dur, NULL, a->dur == 0);
break;
case 2:
update_duration(&a->start, &a->dur);
- io_set_modified();
break;
case 3:
if (notify_bar())
need_check_notify =
notify_same_item(a->start);
update_desc(&a->mesg);
- io_set_modified();
break;
case 4:
need_check_notify = 1;
- update_start_time(&a->start, &a->dur, 1);
- io_set_modified();
+ update_start_time(&a->start, &a->dur, NULL, 1);
break;
default:
return;
@@ -583,12 +1040,13 @@ void ui_day_item_edit(void)
default:
break;
}
-
+ io_set_modified();
ui_calendar_monthly_view_cache_set_invalid();
if (need_check_notify)
notify_check_next_app(1);
}
+#undef ADVANCED
/* Pipe an appointment or event to an external program. */
void ui_day_item_pipe(void)
@@ -609,7 +1067,7 @@ void ui_day_item_pipe(void)
return;
wins_prepare_external();
- if ((pid = shell_exec(NULL, &pout, *arg, arg))) {
+ if ((pid = shell_exec(NULL, &pout, NULL, 0, *arg, arg))) {
fpout = fdopen(pout, "w");
switch (p->type) {
@@ -630,7 +1088,7 @@ void ui_day_item_pipe(void)
}
fclose(fpout);
- child_wait(NULL, &pout, pid);
+ child_wait(NULL, &pout, NULL, pid);
press_any_key();
}
wins_unprepare_external();
@@ -766,81 +1224,85 @@ void ui_day_item_add(void)
/* Delete an item from the appointment list. */
void ui_day_item_delete(unsigned reg)
{
- const char *del_app_str =
- _("Do you really want to delete this item?");
-
- const char *erase_warning =
- _("This item is recurrent. "
- "Delete (a)ll occurences or just this (o)ne?");
- const char *erase_choices = _("[ao]");
- const int nb_erase_choices = 2;
-
- const char *note_warning =
- _("This item has a note attached to it. "
- "Delete (i)tem or just its (n)ote?");
- const char *note_choices = _("[in]");
- const int nb_note_choices = 2;
+ const char *msg, *choices;
+ int nb_choices;
+
time_t occurrence;
if (day_item_count(0) <= 0)
return;
struct day_item *p = ui_day_get_sel();
-
- if (conf.confirm_delete) {
- if (status_ask_bool(del_app_str) != 1) {
- wins_erase_status_bar();
- return;
- }
+ int has_note = (day_item_get_note(p) != NULL);
+ int is_recur = (p->type == RECUR_EVNT || p->type == RECUR_APPT);
+
+ if (has_note && is_recur) {
+ msg = _("This item is recurrent and has a note attached to it. "
+ "Delete (s)elected occurrence, (a)ll occurrences, "
+ "or just its (n)ote?");
+ choices = _("[san]");
+ nb_choices = 3;
+ } else if (has_note) {
+ msg = _("This item has a note attached to it. "
+ "Delete (s)elected occurrence or just its (n)ote?");
+ choices = _("[sn]");
+ nb_choices = 2;
+ } else if (is_recur) {
+ msg = _("This item is recurrent. "
+ "Delete (s)elected occurrence or (a)ll occurrences?");
+ choices = _("[sa]");
+ nb_choices = 2;
+ } else {
+ msg = _("Confirm deletion. "
+ "Delete (s)elected occurrence? Press (s) to confirm.");
+ choices = _("[s]");
+ nb_choices = 1;
}
- if (day_item_get_note(p)) {
- switch (status_ask_choice
- (note_warning, note_choices, nb_note_choices)) {
- case 1:
- break;
- case 2:
- day_item_erase_note(p);
- io_set_modified();
- return;
- default: /* User escaped */
- return;
- }
+ int answer = 1;
+ if (nb_choices > 1 || conf.confirm_delete) {
+ answer = status_ask_choice(msg, choices, nb_choices);
}
- if (p->type == RECUR_EVNT || p->type == RECUR_APPT) {
- switch (status_ask_choice
- (erase_warning, erase_choices, nb_erase_choices)) {
- case 1:
- break;
- case 2:
- if (p->type == RECUR_EVNT) {
- day_item_add_exc(p, ui_day_sel_date());
- } else {
- recur_apoint_find_occurrence(p->item.rapt,
- ui_day_sel_date(),
- &occurrence);
- day_item_add_exc(p, occurrence);
- }
+ /* Always map "all occurrences" to 2 and "note" to 3. */
+ if (has_note && !is_recur && answer == 2)
+ answer = 3;
+ /*
+ * The option "selected occurrence" should be treated like "all
+ * occurrences" for a non-recurrent item (delete the whole item).
+ */
+ if (!is_recur && answer == 1)
+ answer = 2;
- io_set_modified();
- ui_calendar_monthly_view_cache_set_invalid();
- /* Keep the selection on the same day. */
- day_set_sel_data(
- day_get_item(listbox_get_sel(&lb_apt) - 1)
- );
- return;
- default:
- return;
+ switch (answer) {
+ case 1:
+ /* Delete selected occurrence (of a recurrent item) only. */
+ if (p->type == RECUR_EVNT) {
+ day_item_add_exc(p, ui_day_sel_date());
+ } else {
+ recur_apoint_find_occurrence(p->item.rapt,
+ ui_day_sel_date(),
+ &occurrence);
+ day_item_add_exc(p, occurrence);
}
+ /* Keep the selection on the same day. */
+ day_set_sel_data(day_get_item(listbox_get_sel(&lb_apt) - 1));
+ break;
+ case 2:
+ /* Delete all occurrences (or a non-recurrent item). */
+ ui_day_item_cut(reg);
+ /* Keep the selection on the same day. */
+ day_set_sel_data(day_get_item(listbox_get_sel(&lb_apt) - 1));
+ break;
+ case 3:
+ /* Delete note. */
+ day_item_erase_note(p);
+ break;
+ default:
+ /* User escaped, do nothing. */
+ return;
}
- ui_day_item_cut_free(reg);
- p = day_cut_item(listbox_get_sel(&lb_apt));
- day_cut[reg].type = p->type;
- day_cut[reg].item = p->item;
- /* Keep the selection on the same day. */
- day_set_sel_data(day_get_item(listbox_get_sel(&lb_apt) - 1));
io_set_modified();
ui_calendar_monthly_view_cache_set_invalid();
}
@@ -854,163 +1316,88 @@ void ui_day_item_delete(unsigned reg)
*/
void ui_day_item_repeat(void)
{
- char user_input[BUFSIZ] = "";
- const char *msg_rpt_prefix = _("Enter the repetition type:");
- const char *msg_rpt_daily = _("(d)aily");
- const char *msg_rpt_weekly = _("(w)eekly");
- const char *msg_rpt_monthly = _("(m)onthly");
- const char *msg_rpt_yearly = _("(y)early");
- const char *msg_type_choice = _("[dwmy]");
- const char *mesg_freq_1 = _("Enter the repetition frequency:");
- const char *mesg_wrong_freq = _("Invalid frequency.");
- const char *mesg_until_1 = _("Enter end date or duration ('?' for input formats):");
- const char *mesg_help_1 = _("Date: %s (year or month may be omitted). Endless duration: '0'.");
- const char *mesg_help_2 = _("Duration in days: +dd. Duration in weeks and days: +??w??d.");
- const char *mesg_wrong_1 = _("Invalid date.");
- const char *mesg_wrong_2 = _("Press [ENTER] to continue.");
- const char *wrong_type_1 = _("This item is already a repeated one.");
- const char *wrong_type_2 = _("Press [ENTER] to continue.");
- const char *mesg_older = _("Invalid date: end date must come after start date (%s).");
-
- char *msg_asktype;
- asprintf(&msg_asktype, "%s %s, %s, %s, %s", msg_rpt_prefix,
- msg_rpt_daily, msg_rpt_weekly, msg_rpt_monthly,
- msg_rpt_yearly);
-
- int type = 0, freq = 0;
- int item_nb;
+ int item_nb, simple;
struct day_item *p;
- struct recur_apoint *ra;
- time_t until;
- unsigned days;
+ long dur;
+ struct rpt rpt, *r;
+ const char *already = _("Already repeated.");
+ const char *cont = _("Press any key to continue.");
+ const char *repetition = _("A (s)imple or (a)dvanced repetition?");
+ const char *sa = _("[sa]");
if (day_item_count(0) <= 0)
- goto cleanup;
+ return;
item_nb = listbox_get_sel(&lb_apt);
p = day_get_item(item_nb);
if (p->type != APPT && p->type != EVNT) {
- status_mesg(wrong_type_1, wrong_type_2);
+ status_mesg(already, cont);
keys_wait_for_any_key(win[KEY].p);
- goto cleanup;
+ return;
}
- switch (status_ask_choice(msg_asktype, msg_type_choice, 4)) {
+ switch (status_ask_choice(repetition, sa, 2)) {
case 1:
- type = RECUR_DAILY;
+ simple = 1;
break;
case 2:
- type = RECUR_WEEKLY;
- break;
- case 3:
- type = RECUR_MONTHLY;
- break;
- case 4:
- type = RECUR_YEARLY;
+ simple = 0;
break;
default:
- goto cleanup;
- }
-
- while (freq == 0) {
- status_mesg(mesg_freq_1, "");
- if (getstring(win[STA].p, user_input, BUFSIZ, 0, 1) !=
- GETSTRING_VALID)
- goto cleanup;
- freq = atoi(user_input);
- if (freq == 0) {
- status_mesg(mesg_wrong_freq, wrong_type_2);
- keys_wait_for_any_key(win[KEY].p);
- }
- user_input[0] = '\0';
+ return;
}
- char *outstr, *datestr;
- for (;;) {
- status_mesg(mesg_until_1, "");
- if (getstring(win[STA].p, user_input, BUFSIZ, 0, 1) == GETSTRING_ESC)
- goto cleanup;
- if (strcmp(user_input, "") == 0 || strcmp(user_input, "0") == 0) {
- until = 0;
- break;
- }
- if (*user_input == '?') {
- user_input[0] = '\0';
- asprintf(&outstr, mesg_help_1, DATEFMT_DESC(conf.input_datefmt));
- status_mesg(outstr, mesg_help_2);
- mem_free(outstr);
- wgetch(win[KEY].p);
- continue;
- }
- if (*user_input == '+') {
- if (!parse_date_duration(user_input + 1, &days, p->start)) {
- status_mesg(mesg_wrong_1, mesg_wrong_2);
- keys_wgetch(win[KEY].p);
- continue;
- }
- /* Until is midnight of the day. */
- until = date_sec_change(
- update_time_in_date(p->start, 0, 0),
- 0, days
- );
- } else {
- int year, month, day;
- if (!parse_date(user_input, conf.input_datefmt,
- &year, &month, &day, ui_calendar_get_slctd_day())) {
- status_mesg(mesg_wrong_1, mesg_wrong_2);
- keys_wgetch(win[KEY].p);
- continue;
- }
- struct date d = { day, month, year };
- until = date2sec(d, 0, 0);
- }
- /* Compare days (midnights) - until-day may equal start day. */
- if (until >= get_slctd_day())
- break;
-
- datestr = date_sec2date_str(p->start, DATEFMT(conf.input_datefmt));
- asprintf(&outstr, mesg_older, datestr);
- status_mesg(outstr, wrong_type_2);
- mem_free(datestr);
- mem_free(outstr);
- keys_wgetch(win[KEY].p);
- }
+ if (p->type == APPT)
+ dur = p->item.apt->dur;
+ else
+ dur = -1;
+ rpt.type = -1;
+ rpt.freq = 1;
+ rpt.until = 0;
+ LLIST_INIT(&rpt.bymonth);
+ LLIST_INIT(&rpt.bywday);
+ LLIST_INIT(&rpt.bymonthday);
+ LLIST_INIT(&rpt.exc);
+ r = &rpt;
+ if (!update_rept(p->start, dur, &r, &rpt.exc, simple))
+ return;
- /* Set the selected APP item. */
struct day_item d = empty_day;
if (p->type == EVNT) {
struct event *ev = p->item.ev;
d.item.rev = recur_event_new(ev->mesg, ev->note, ev->day,
- ev->id, type, freq, until, NULL);
- } else if (p->type == APPT) {
+ ev->id, &rpt);
+ } else {
struct apoint *apt = p->item.apt;
- d.item.rapt = ra = recur_apoint_new(apt->mesg, apt->note,
+ d.item.rapt = recur_apoint_new(apt->mesg, apt->note,
apt->start, apt->dur,
- apt->state, type, freq,
- until, NULL);
+ apt->state, &rpt);
if (notify_bar())
- notify_check_repeated(ra);
- } else {
- EXIT(_("wrong item type"));
- /* NOTREACHED */
+ notify_check_repeated(d.item.rapt);
}
+ ui_day_item_cut(REG_BLACK_HOLE);
day_set_sel_data(&d);
-
- ui_day_item_cut_free(REG_BLACK_HOLE);
- p = day_cut_item(item_nb);
- day_cut[REG_BLACK_HOLE].type = p->type;
- day_cut[REG_BLACK_HOLE].item = p->item;
io_set_modified();
-
ui_calendar_monthly_view_cache_set_invalid();
+}
-cleanup:
- mem_free(msg_asktype);
+/* Delete an item and save it in a register. */
+void ui_day_item_cut(unsigned reg)
+{
+ struct day_item *p;
+
+ ui_day_item_cut_free(reg);
+
+ p = day_cut_item(listbox_get_sel(&lb_apt));
+ day_cut[reg].type = p->type;
+ day_cut[reg].item = p->item;
}
/* Free the current cut item, if any. */
void ui_day_item_cut_free(unsigned reg)
{
+ EXIT_IF(reg > REG_BLACK_HOLE, "illegal register");
+
if (!day_cut[reg].type) {
/* No previously cut item, don't free anything. */
return;
@@ -1133,7 +1520,7 @@ void ui_day_draw(int n, WINDOW *win, int y, int hilt, void *cb_data)
{
struct day_item *item = day_get_item(n);
/* The item order always indicates the date. */
- time_t date = update_time_in_date(item->order, 0, 0);
+ time_t date = DAY(item->order);
int width = lb_apt.sw.w - 2, is_slctd;
hilt = hilt && (wins_slctd() == APP);
diff --git a/src/ui-todo.c b/src/ui-todo.c
index 8834e39..46933b3 100644
--- a/src/ui-todo.c
+++ b/src/ui-todo.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -158,11 +158,11 @@ void ui_todo_pipe(void)
return;
wins_prepare_external();
- if ((pid = shell_exec(NULL, &pout, *arg, arg))) {
+ if ((pid = shell_exec(NULL, &pout, NULL, 0, *arg, arg))) {
fpout = fdopen(pout, "w");
todo_write(item, fpout);
fclose(fpout);
- child_wait(NULL, &pout, pid);
+ child_wait(NULL, &pout, NULL, pid);
press_any_key();
}
wins_unprepare_external();
@@ -207,14 +207,16 @@ void ui_todo_draw(int n, WINDOW *win, int y, int hilt, void *cb_data)
if (hilt)
custom_apply_attr(win, ATTR_HIGHEST);
- if (utf8_strwidth(todo->mesg) < width) {
- mesg = todo->mesg;
- } else {
+ mesg = todo->mesg;
+ if (mesg[0] == '\0')
+ mesg = EMPTY_EVENT_DESC_DEFAULT;
+
+ if (utf8_strwidth(mesg) >= width) {
width -= 3;
- for (j = 0; todo->mesg[j] && width > 0; j++) {
- if (!UTF8_ISCONT(todo->mesg[j]))
- width -= utf8_width(&todo->mesg[j]);
- buf[j] = todo->mesg[j];
+ for (j = 0; mesg[j] && width > 0; j++) {
+ if (!UTF8_ISCONT(mesg[j]))
+ width -= utf8_width(&mesg[j]);
+ buf[j] = mesg[j];
}
if (j) {
buf[j - 1] = '.';
@@ -314,7 +316,32 @@ void ui_todo_popup_item(void)
if (!item)
return;
- item_in_popup(NULL, NULL, item->mesg, _("TODO:"));
+ if (item->note) {
+ /* Assign a sane default note size that will cleanly
+ * truncate long notes */
+ const char *note_heading = _("Note:");
+ size_t note_size = 3500;
+ char note[note_size];
+ char *notepath, *msg;
+ FILE *fp;
+
+ asprintf(&notepath, "%s%s", path_notes, item->note);
+ fp = fopen(notepath, "r");
+ if (fp == NULL) {
+ item_in_popup(NULL, NULL, item->mesg, _("TODO:"));
+ return;
+ }
+
+ note_read_contents(note, note_size, fp);
+ fclose(fp);
+ mem_free(notepath);
+
+ asprintf(&msg, "%s\n\n%s\n%s", item->mesg, note_heading, note);
+ item_in_popup(NULL, NULL, msg, _("TODO:"));
+ mem_free(msg);
+ } else {
+ item_in_popup(NULL, NULL, item->mesg, _("TODO:"));
+ }
}
void ui_todo_flag(void)
diff --git a/src/utf8.c b/src/utf8.c
index b1976af..997a4fa 100644
--- a/src/utf8.c
+++ b/src/utf8.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/src/utils.c b/src/utils.c
index a9a9e68..2d30bfc 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -112,7 +112,7 @@ void free_user_data(void)
apoint_llist_free();
recur_apoint_llist_free();
recur_event_llist_free();
- for (i = 0; i <= 37; i++)
+ for (i = 0; i <= REG_BLACK_HOLE; i++)
ui_day_item_cut_free(i);
todo_free_list();
notify_free_app();
@@ -235,6 +235,8 @@ int status_ask_choice(const char *message, const char choice[],
return i + 1;
if (ch == ESCAPE)
return (-1);
+ if (ch == RETURN)
+ return (-2);
if (resize) {
resize = 0;
wins_reset();
@@ -421,22 +423,25 @@ struct date sec2date(time_t t)
return d;
}
-time_t utcdate2sec(struct date day, unsigned hour, unsigned min)
+time_t tzdate2sec(struct date day, unsigned hour, unsigned min, char *tznew)
{
- char *tz;
+ char *tzold;
time_t t;
- tz = getenv("TZ");
- if (tz)
- tz = mem_strdup(tz);
- setenv("TZ", "", 1);
+ if (!tznew)
+ return date2sec(day, hour, min);
+
+ tzold = getenv("TZ");
+ if (tzold)
+ tzold = mem_strdup(tzold);
+ setenv("TZ", tznew, 1);
tzset();
t = date2sec(day, hour, min);
- if (tz) {
- setenv("TZ", tz, 1);
- mem_free(tz);
+ if (tzold) {
+ setenv("TZ", tzold, 1);
+ mem_free(tzold);
} else {
unsetenv("TZ");
}
@@ -621,6 +626,42 @@ long min2sec(unsigned minutes)
return minutes * MININSEC;
}
+int modify_wday(int wday, int shift)
+{
+ return (WEEKINDAYS + wday + shift) % WEEKINDAYS;
+}
+
+/* returns char* representing a wday, used for internal functions */
+char *get_wday_default_string(int wday)
+{
+ switch(wday) {
+ case MONDAY:
+ return "Monday";
+ break;
+ case TUESDAY:
+ return "Tuesday";
+ break;
+ case WEDNESDAY:
+ return "Wednesday";
+ break;
+ case THURSDAY:
+ return "Thursday";
+ break;
+ case FRIDAY:
+ return "Friday";
+ break;
+ case SATURDAY:
+ return "Saturday";
+ break;
+ case SUNDAY:
+ return "Sunday";
+ break;
+ default:
+ return "Sunday";
+ break;
+ }
+}
+
/*
* Display a scroll bar when there are so many items that they
* can not be displayed inside the corresponding panel.
@@ -985,11 +1026,11 @@ parse_date_interactive(const char *datestr, int *year, int *month, int *day)
}
/*
- * Convert a date duration string into a number of days.
+ * Convert a date increment string into a number of days.
* If start is non-zero, the final end time is validated.
*
* Allowed formats in lenient BNF:
- * <duration> ::= <days> | <period>
+ * <increment>::= <days> | <period>
* <period> ::= [ <weeks>w ][ <days>d ]
* Notes:
* <days> and <weeks> are any integer >= 0.
@@ -997,7 +1038,7 @@ parse_date_interactive(const char *datestr, int *year, int *month, int *day)
*
* Returns 1 on success and 0 on failure.
*/
-int parse_date_duration(const char *string, unsigned *days, time_t start)
+int parse_date_increment(const char *string, unsigned *days, time_t start)
{
enum {
STATE_INITIAL,
@@ -1007,7 +1048,7 @@ int parse_date_duration(const char *string, unsigned *days, time_t start)
const char *p;
unsigned in = 0, frac = 0, denom = 1;
- unsigned dur = 0;
+ unsigned incr = 0;
if (!string || *string == '\0')
return 0;
@@ -1028,10 +1069,10 @@ int parse_date_duration(const char *string, unsigned *days, time_t start)
switch (state) {
case STATE_INITIAL:
if (*p == 'w') {
- dur += in * WEEKINDAYS / denom;
+ incr += in * WEEKINDAYS / denom;
state = STATE_WWDD_DD;
} else if (*p == 'd') {
- dur += in / denom;
+ incr += in / denom;
state = STATE_DONE;
} else {
return 0;
@@ -1039,7 +1080,7 @@ int parse_date_duration(const char *string, unsigned *days, time_t start)
break;
case STATE_WWDD_DD:
if (*p == 'd') {
- dur += in / denom;
+ incr += in / denom;
state = STATE_DONE;
} else {
return 0;
@@ -1055,18 +1096,18 @@ int parse_date_duration(const char *string, unsigned *days, time_t start)
}
if (state == STATE_DONE && in > 0)
return 0;
- dur += in;
+ incr += in;
if (start) {
- /* wanted: start = start + dur * DAYINSEC */
+ /* wanted: start = start + incr * DAYINSEC */
long p;
- if (overflow_mul(dur, DAYINSEC, &p))
+ if (overflow_mul(incr, DAYINSEC, &p))
return 0;
if (overflow_add(start, p, &start))
return 0;
if (!check_sec(&start))
return 0;
}
- *days = dur;
+ *days = incr;
return 1;
}
@@ -1312,21 +1353,32 @@ void psleep(unsigned secs)
/*
* Fork and execute an external process.
*
- * If pfdin and/or pfdout point to a valid address, a pipe is created and the
- * appropriate file descriptors are written to pfdin/pfdout.
+ * If pfdin/pfdout/pfderr point to a valid address, a pipe is created and the
+ * appropriate file descriptors are written to pfdin/pfdout/pfderr.
+ *
+ * If new_session is non-zero, setsid() is called after forking.
*/
-int fork_exec(int *pfdin, int *pfdout, const char *path,
- const char *const *arg)
+int fork_exec(int *pfdin, int *pfdout, int *pfderr, int new_session,
+ const char *path, const char *const *arg)
{
- int pin[2], pout[2];
+ int pin[2], pout[2], perr[2];
int pid;
if (pfdin && (pipe(pin) == -1))
return 0;
if (pfdout && (pipe(pout) == -1))
return 0;
+ if (pfderr && (pipe(perr) == -1))
+ return 0;
if ((pid = fork()) == 0) {
+ if (pfderr) {
+ if (dup2(perr[0], STDERR_FILENO) < 0)
+ _exit(127);
+ close(perr[0]);
+ close(perr[1]);
+ }
+
if (pfdout) {
if (dup2(pout[0], STDIN_FILENO) < 0)
_exit(127);
@@ -1341,6 +1393,11 @@ int fork_exec(int *pfdin, int *pfdout, const char *path,
close(pin[1]);
}
+ if (new_session) {
+ if ((setsid() < 0))
+ _exit(127);
+ }
+
execvp(path, (char *const *)arg);
_exit(127);
} else {
@@ -1348,6 +1405,8 @@ int fork_exec(int *pfdin, int *pfdout, const char *path,
close(pin[1]);
if (pfdout)
close(pout[0]);
+ if (pfderr)
+ close(perr[0]);
if (pid > 0) {
if (pfdin) {
@@ -1358,11 +1417,17 @@ int fork_exec(int *pfdin, int *pfdout, const char *path,
fcntl(pout[1], F_SETFD, FD_CLOEXEC);
*pfdout = pout[1];
}
+ if (pfderr) {
+ fcntl(perr[1], F_SETFD, FD_CLOEXEC);
+ *pfderr = perr[1];
+ }
} else {
if (pfdin)
close(pin[0]);
if (pfdout)
close(pout[1]);
+ if (pfderr)
+ close(perr[1]);
return 0;
}
}
@@ -1371,8 +1436,8 @@ int fork_exec(int *pfdin, int *pfdout, const char *path,
/* Execute an external program in a shell. */
int
-shell_exec(int *pfdin, int *pfdout, const char *path,
- const char *const *arg)
+shell_exec(int *pfdin, int *pfdout, int *pfderr, int new_session,
+ const char *path, const char *const *arg)
{
int argc, i;
const char **narg;
@@ -1401,7 +1466,7 @@ shell_exec(int *pfdin, int *pfdout, const char *path,
narg[3] = NULL;
}
- ret = fork_exec(pfdin, pfdout, *narg, narg);
+ ret = fork_exec(pfdin, pfdout, pfderr, new_session, *narg, narg);
if (arg0)
mem_free(arg0);
@@ -1411,7 +1476,7 @@ shell_exec(int *pfdin, int *pfdout, const char *path,
}
/* Wait for a child process to terminate. */
-int child_wait(int *pfdin, int *pfdout, int pid)
+int child_wait(int *pfdin, int *pfdout, int *pfderr, int pid)
{
int stat;
@@ -1419,9 +1484,13 @@ int child_wait(int *pfdin, int *pfdout, int pid)
close(*pfdin);
if (pfdout)
close(*pfdout);
+ if (pfderr)
+ close(*pfderr);
- waitpid(pid, &stat, 0);
- return stat;
+ if (waitpid(pid, &stat, 0) == pid)
+ return stat;
+ else
+ return -1;
}
/* Display "Press any key to continue..." and wait for a key press. */
@@ -1636,7 +1705,7 @@ static void print_date(time_t date, time_t day, const char *extformat)
if (!strcmp(extformat, "epoch")) {
printf("%ld", (long)date);
} else {
- time_t day_start = update_time_in_date(day, 0, 0);
+ time_t day_start = DAY(day);
time_t day_end = date_sec_change(day_start, 0, 1);
struct tm lt;
@@ -1971,11 +2040,6 @@ int hash_matches(const char *pattern, const char *hash)
return (starts_with(hash, pattern) != invert);
}
-int show_dialogs(void)
-{
- return (!quiet) && conf.system_dialogs;
-}
-
/*
* Overflow check for addition with positive second term.
*/
@@ -2009,3 +2073,76 @@ long overflow_mul(long x, long y, long *z)
*z = x * y;
return 0;
}
+
+/*
+ * Return the upcoming weekday from day (possibly day itself).
+ */
+time_t next_wday(time_t day, int weekday)
+{
+ struct tm tm;
+
+ localtime_r(&day, &tm);
+ return date_sec_change(
+ day, 0, (weekday - tm.tm_wday + WEEKINDAYS) % WEEKINDAYS
+ );
+
+}
+
+/*
+ * Return the number of weekdays of the year.
+ */
+int wday_per_year(int year, int weekday)
+{
+ struct tm y_end;
+ struct date day;
+ int last_wday;
+
+ /* Find weekday and yearday of the last day of the year. */
+ day.dd = 31;
+ day.mm = 12;
+ day.yyyy = year;
+ y_end = date2tm(day, 0, 0);
+ mktime(&y_end);
+
+ /* Find date of the last weekday of the year. */
+ last_wday = (y_end.tm_yday + 1) - (y_end.tm_wday - weekday + 7) % 7;
+
+ return last_wday / 7 + (last_wday % 7 > 0);
+}
+
+/*
+ * Return the number of weekdays in month of year.
+ */
+int wday_per_month(int month, int year, int weekday)
+{
+ struct tm m_end;
+ struct date day;
+ int last_wday, m_days = days[month - 1] + (month == 2 && ISLEAP(year) ? 1 : 0);
+
+ /* Find weekday of the last day of the month. */
+ day.dd = m_days;
+ day.mm = month;
+ day.yyyy = year;
+ m_end = date2tm(day, 0, 0);
+ mktime(&m_end);
+
+ /* Find date of the last weekday of the month. */
+ last_wday = m_days - (m_end.tm_wday - weekday + 7) % 7;
+
+ return last_wday / 7 + (last_wday % 7 > 0);
+}
+
+/*
+ * Return allocated string with day of 't' inserted in 'template' in the user's
+ * preferred format; template must be a "printf" template with exactly one
+ * string conversion (%s).
+ */
+char *day_ins(char **template, time_t t)
+{
+ char *day, *msg;
+
+ day = date_sec2date_str(DAY(t), DATEFMT(conf.input_datefmt));
+ asprintf(&msg, *template, day);
+ mem_free(day);
+ return msg;
+}
diff --git a/src/vars.c b/src/vars.c
index ae690d1..c8508e2 100644
--- a/src/vars.c
+++ b/src/vars.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -61,7 +61,7 @@ enum ui_mode ui_mode = UI_CMDLINE;
/* Don't save anything if this is set. */
int read_only = 0;
-/* Hide system dialogs if set. */
+/* Hide import/export message if set. */
int quiet = 0;
/* Applications can trigger a reload by sending SIGUSR1. */
@@ -136,11 +136,11 @@ void vars_init(void)
conf.systemevents = 1;
conf.default_panel = CAL;
conf.compact_panels = 0;
- conf.system_dialogs = 1;
strncpy(conf.output_datefmt, "%D", 3);
conf.input_datefmt = 1;
conf.heading_pos = RIGHT;
strcpy(conf.day_heading, DAY_HEADING_DEFAULT);
+ strcpy(conf.timefmt, APPT_TIME_DEFAULT);
datefmt_str[0] = _("mm/dd/yyyy");
datefmt_str[1] = _("dd/mm/yyyy");
diff --git a/src/vector.c b/src/vector.c
index 5ea893a..796ef8e 100644
--- a/src/vector.c
+++ b/src/vector.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/src/vector.h b/src/vector.h
index 0013545..7648df2 100644
--- a/src/vector.h
+++ b/src/vector.h
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/src/wins.c b/src/wins.c
index 51d8072..46ac98e 100644
--- a/src/wins.c
+++ b/src/wins.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -63,7 +63,7 @@ static int layout;
/*
* The screen_mutex mutex and wins_refresh(), wins_wrefresh(), wins_doupdate()
* functions are used to prevent concurrent updates of the screen.
- * It was observed that the display could get screwed up when mulitple threads
+ * It was observed that the display could get screwed up when multiple threads
* tried to refresh the screen at the same time.
*
* Note (2010-03-21):
@@ -229,7 +229,7 @@ void wins_sbar_winc(void)
void wins_sbar_wdec(void)
{
- if (sbarwidth_perc > 0)
+ if (col * sbarwidth_perc / 100 > SBARMINWIDTH)
sbarwidth_perc--;
}
@@ -254,6 +254,15 @@ void wins_slctd_next(void)
slctd_win++;
}
+/* Shift-TAB key was hit in the interface, need to select previous window. */
+void wins_slctd_prev(void)
+{
+ if (slctd_win == CAL)
+ slctd_win = TOD;
+ else
+ slctd_win--;
+}
+
static void wins_init_panels(void)
{
wins_scrollwin_init(&sw_cal, win[CAL].y, win[CAL].x,
@@ -593,8 +602,6 @@ void wins_prepare_external(void)
{
if (notify_bar())
notify_stop_main_thread();
- if (conf.periodic_save > 0)
- io_stop_psave_thread();
def_prog_mode();
ui_mode = UI_CMDLINE;
clear();
@@ -615,8 +622,6 @@ void wins_unprepare_external(void)
wins_resize();
if (notify_bar())
notify_start_main_thread();
- if (conf.periodic_save > 0)
- io_start_psave_thread();
}
/*
@@ -628,8 +633,8 @@ void wins_launch_external(const char *arg[])
int pid;
wins_prepare_external();
- if ((pid = shell_exec(NULL, NULL, *arg, arg)))
- child_wait(NULL, NULL, pid);
+ if ((pid = shell_exec(NULL, NULL, NULL, 0, *arg, arg)))
+ child_wait(NULL, NULL, NULL, pid);
wins_unprepare_external();
}
@@ -655,6 +660,7 @@ void wins_update_bindings(void)
static int bindings_cal[] = {
KEY_GENERIC_HELP, KEY_GENERIC_QUIT, KEY_GENERIC_SAVE,
KEY_GENERIC_RELOAD, KEY_GENERIC_CHANGE_VIEW,
+ KEY_GENERIC_PREV_VIEW,
KEY_GENERIC_SCROLL_DOWN, KEY_GENERIC_SCROLL_UP, KEY_MOVE_UP,
KEY_MOVE_DOWN, KEY_MOVE_LEFT, KEY_MOVE_RIGHT, KEY_GENERIC_GOTO,
KEY_GENERIC_IMPORT, KEY_GENERIC_EXPORT, KEY_START_OF_WEEK,
@@ -670,6 +676,7 @@ void wins_update_bindings(void)
static int bindings_apoint[] = {
KEY_GENERIC_HELP, KEY_GENERIC_QUIT, KEY_GENERIC_SAVE,
KEY_GENERIC_RELOAD, KEY_GENERIC_CHANGE_VIEW,
+ KEY_GENERIC_PREV_VIEW,
KEY_GENERIC_IMPORT, KEY_GENERIC_EXPORT, KEY_ADD_ITEM,
KEY_DEL_ITEM, KEY_EDIT_ITEM, KEY_VIEW_ITEM, KEY_PIPE_ITEM,
KEY_GENERIC_REDRAW, KEY_REPEAT_ITEM, KEY_FLAG_ITEM,
@@ -686,6 +693,7 @@ void wins_update_bindings(void)
static int bindings_todo[] = {
KEY_GENERIC_HELP, KEY_GENERIC_QUIT, KEY_GENERIC_SAVE,
KEY_GENERIC_RELOAD, KEY_GENERIC_CHANGE_VIEW,
+ KEY_GENERIC_PREV_VIEW,
KEY_GENERIC_SCROLL_DOWN, KEY_GENERIC_SCROLL_UP,
KEY_GENERIC_IMPORT, KEY_GENERIC_EXPORT, KEY_ADD_ITEM,
KEY_DEL_ITEM, KEY_EDIT_ITEM, KEY_VIEW_ITEM, KEY_PIPE_ITEM,
diff --git a/test/Makefile.am b/test/Makefile.am
index d896dc3..daa6e77 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -56,6 +56,12 @@ TESTS = \
ical-006.sh \
ical-007.sh \
ical-008.sh \
+ ical-009.sh \
+ ical-010.sh \
+ ical-011.sh \
+ ical-012.sh \
+ ical-013.sh \
+ ical-014.sh \
next-001.sh \
next-002.sh \
next-003.sh \
@@ -69,7 +75,9 @@ TESTS = \
recur-005.sh \
recur-006.sh \
recur-007.sh \
- recur-008.sh
+ recur-008.sh \
+ recur-009.sh \
+ recur-010.sh
TESTS_ENVIRONMENT = \
TEST_INIT='$(top_srcdir)/test/test-init.sh' \
@@ -117,6 +125,7 @@ EXTRA_DIST = \
data/apts-event-004 \
data/apts-event-005 \
data/apts-event-006 \
+ data/apts-export \
data/apts-filter-001 \
data/apts-recur \
data/apts-regress-001 \
@@ -129,4 +138,9 @@ EXTRA_DIST = \
data/ical-006.ical \
data/ical-007.ical \
data/ical-008.ical \
- data/todo
+ data/ical-009.ical \
+ data/ical-012.ical \
+ data/rfc5545.ical \
+ data/rfc5545 \
+ data/todo \
+ data/todo-export
diff --git a/test/data/apts-export b/test/data/apts-export
new file mode 100644
index 0000000..65fbbc4
--- /dev/null
+++ b/test/data/apts-export
@@ -0,0 +1,2 @@
+02/26/2020 @ 07:09 -> 02/26/2020 @ 07:10|Exported, escaped characters in SUMMARY: ,(comma), ;(semicolon) , and \(escape).
+02/26/2020 [1] Exported, escaped characters in SUMMARY: ,(comma), ;(semicolon) , and \(escape).
diff --git a/test/data/ical-002.ical b/test/data/ical-002.ical
index 915b84e..b9f6538 100644
--- a/test/data/ical-002.ical
+++ b/test/data/ical-002.ical
@@ -8,12 +8,12 @@ END:VEVENT
BEGIN:VEVENT
DTSTART:20000101T000000
DURATION:P1DT1H1M1S
-SUMMARY:One day, one hour, one minute and one second
+SUMMARY:One day\, one hour\, one minute and one second
END:VEVENT
BEGIN:VEVENT
DTSTART:20000101T000000
DURATION:PT1H1M1S
-SUMMARY:One hour, one minute and one second
+SUMMARY:One hour\, one minute and one second
END:VEVENT
BEGIN:VEVENT
DTSTART:20000101T000000
diff --git a/test/data/ical-003.ical b/test/data/ical-003.ical
index 599d24f..5645705 100644
--- a/test/data/ical-003.ical
+++ b/test/data/ical-003.ical
@@ -22,4 +22,49 @@ EXDATE:20000215T000000
EXDATE:20000223T000000
SUMMARY:Recurring appointment
END:VEVENT
+BEGIN:VEVENT
+DTSTART:20200526T120000
+DURATION:PT1H17M0S
+RRULE:FREQ=DAILY;UNTIL=20200529T130000
+SUMMARY: until May 29 2020\, 13:00
+END:VEVENT
+BEGIN:VEVENT
+DTSTART:20200526T120000
+DURATION:PT1H17M0S
+RRULE:FREQ=DAILY;UNTIL=20200529T110000
+SUMMARY: until May 29 2020\, 11:00
+END:VEVENT
+BEGIN:VEVENT
+DTSTART:20200531T214500
+DURATION:PT15M0S
+RRULE:FREQ=MONTHLY;COUNT=10
+EXDATE:20200731T214500,20210131T214500
+SUMMARY:monthly on 31th\, count 10\, exceptions 31/7/2020 and 31/1/2021
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;VALUE=DATE:20200502
+DTEND;VALUE=DATE:20200504
+DESCRIPTION:The first weekend in May is a two-day event.\nNon-repeating event.
+SUMMARY:First weekend in May
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;VALUE=DATE:20200502
+DTEND;VALUE=DATE:20200504
+DESCRIPTION:First weekend in May is a two-day event!\nRepeating event\, three years.
+SUMMARY:First weekend in May
+RRULE:FREQ=YEARLY;BYDAY=1SA;BYMONTH=5;COUNT=3
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART:20200502T000000
+DTEND:20200504T000000
+DESCRIPTION:First weekend in May is a two-day event!\nRepeating appointment.
+SUMMARY:First weekend in May
+RRULE:FREQ=YEARLY;BYDAY=1SA;BYMONTH=5;COUNT=3
+END:VEVENT
END:VCALENDAR
diff --git a/test/data/ical-005.ical b/test/data/ical-005.ical
index 5f20f48..e417779 100644
--- a/test/data/ical-005.ical
+++ b/test/data/ical-005.ical
@@ -18,6 +18,6 @@ TRANSP:TRANSPARENT
END:VEVENT
BEGIN:VEVENT
SUMMARY:On day 2
-DTSTART;VALUE=DATE:20131003
+DTSTART;VALUE=DATE:20131004
END:VEVENT
END:VCALENDAR
diff --git a/test/data/ical-006.ical b/test/data/ical-006.ical
index 374ac2d..96c0b2c 100644
--- a/test/data/ical-006.ical
+++ b/test/data/ical-006.ical
@@ -56,7 +56,7 @@ DTSTART:20120601T150000
DURATION:PT5H10S
END:VEVENT
BEGIN:VEVENT
-SUMMARY:5 hours, 30 minutes and 10 seconds
+SUMMARY:5 hours\, 30 minutes and 10 seconds
DTSTART:20120601T150000
DURATION:PT5H30M10S
END:VEVENT
diff --git a/test/data/ical-007.ical b/test/data/ical-007.ical
index e46c3fb..a7dfdd5 100644
--- a/test/data/ical-007.ical
+++ b/test/data/ical-007.ical
@@ -10,4 +10,9 @@ SUMMARY:UTC
DTSTART:20150223T110000Z
DURATION:PT1H
END:VEVENT
+BEGIN:VEVENT
+SUMMARY:CET
+DTSTART;TZID=CET:20150223T110000
+DURATION:PT1H
+END:VEVENT
END:VCALENDAR
diff --git a/test/data/ical-008.ical b/test/data/ical-008.ical
index 51625d5..7789734 100644
--- a/test/data/ical-008.ical
+++ b/test/data/ical-008.ical
@@ -1,8 +1,8 @@
BEGIN:VCALENDAR
VERSION:2.0
BEGIN:VEVENT
-DTSTART;TZID="(UTC+01:00) Amsterdam, Berlin, Bern, Rom, Stockholm, Wien":19800101T000100
-DURATION:P1DT9H17M0S
+DTSTART:19800101T000100
+DURATION;TESTPARAM="Quoted string with colon(:), semicolon(;) and comma(,)":P1DT9H17M0S
SUMMARY:Calibrator's
END:VEVENT
BEGIN:VTODO
diff --git a/test/data/ical-009.ical b/test/data/ical-009.ical
new file mode 100644
index 0000000..14bf4eb
--- /dev/null
+++ b/test/data/ical-009.ical
@@ -0,0 +1,131 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+BEGIN:VEVENT
+DURATION:PT1H30M0S
+SUMMARY:A simple appointment
+DTSTART:20200318T084100
+END:VEVENT
+BEGIN:VTODO
+PRIORITY:1
+SUMMARY:A simple todo
+END:VTODO
+BEGIN:VEVENT
+DTSTART:
+DURATION:PT1H30M0S
+SUMMARY:invalid start time
+END:VEVENT
+BEGIN:VEVENT
+DURATION:PT1H30M0S
+SUMMARY:missing start time
+END:VEVENT
+BEGIN:VEVENT
+DTSTART:20200318T084100
+DURATION:PT1H30M0S
+RRULE:FREQ=HOURLY;INTERVAL=2;UNTIL=20200401T000000
+SUMMARY:unsupported frequency
+END:VEVENT
+BEGIN:VEVENT
+DTSTART:20200318T084100
+DURATION:PT1H30M0S
+SUMMARY malformed summary line
+END:VEVENT
+BEGIN:VTODO
+PRIORITY:10
+SUMMARY:invalid priority
+END:VTODO
+BEGIN:VEVENT
+DTSTART:20200318T084100
+DURATION:PT1H30M0S
+RRULE:FREQ=DAILY;INTERVAL=2;UNTIL=20200401T000000
+EXDATE 20200324T084100
+SUMMARY:malformed exceptions line
+END:VEVENT
+BEGIN:VEVENT
+DTSTART:20200318T084100
+DURATION:PT1H30M0S
+EXDATE:20200324T084100
+SUMMARY:exdate\, missing rrule
+END:VEVENT
+BEGIN:VEVENT
+DTSTART:20200318T084100
+DURATION:PT1H30M0S
+SUMMARY:Summary with more than\none line
+END:VEVENT
+BEGIN:VEVENT
+DTSTART:20200318T084100
+DURATION:PT1H30M0S
+SUMMARY:malformed description line
+DESCRIPTION something is missing
+END:VEVENT
+BEGIN:VEVENT
+DTSTART:20200318T084100
+DURATION:PT1H30M0S
+SUMMARY:malformed description
+DESCRIPTION:description with an unescaped semicolon (;)
+END:VEVENT
+BEGIN:VEVENT
+DTSTART:20200318T084100
+DURATION:PT1H30M0S
+SUMMARY:empty DESCRIPTION
+DESCRIPTION:
+END:VEVENT
+BEGIN:VTODO
+PRIORITY:1
+SUMMARY:an unescaped comma: ,
+END:VTODO
+BEGIN:VEVENT
+DTSTART:20200406T221300
+DURATION:PT0H15M0S
+SUMMARY:LOCATION twice
+LOCATION:first
+LOCATION:second
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20200406
+DURATION:PT0H15M0S
+SUMMARY:Invalid duration (must be days or weeks)
+END:VEVENT
+BEGIN:VEVENT
+DTSTART:20200406
+DURATION:P1D
+SUMMARY:Invalid DTSTART value type
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20200406
+SUMMARY:Invalid DTEND value type
+DTEND:20200407
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20200406
+DURATION:P1D
+RRULE:FREQ=MONTHLY;UNTIL=20201030T120000Z
+SUMMARY:Invalid UNTIL value
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20200406
+DURATION:P1D
+RRULE:FREQ=MONTHLY;UNTIL=20201030
+EXDATE:20200606
+SUMMARY:Invalid EXDATE value type
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20200406
+DURATION:P1D
+RRULE:FREQ=MONTHLY;UNTIL=20201030
+EXDATE;VALUE=DATE:20200606T120000Z
+SUMMARY:Invalid EXDATE value
+END:VEVENT
+BEGIN:VEVENT
+DTSTART:20200527T163000
+DTEND:20200528T163000
+DURATION:P1D
+SUMMARY:Both end time and duration
+END:VEVENT
+BEGIN:VEVENT
+DTSTART:20200527T163000
+DTEND:20200526T163000
+SUMMARY:End time before start
+END:VEVENT
+BEGIN:VTODO
+SUMMARY:finally\, missing end of item
+END:VCALENDAR
diff --git a/test/data/ical-012.ical b/test/data/ical-012.ical
new file mode 100644
index 0000000..05604af
--- /dev/null
+++ b/test/data/ical-012.ical
@@ -0,0 +1,89 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+
+BEGIN:VEVENT
+DTSTART:20200404T204500
+DURATION:PT1H30M0S
+SUMMARY:event with one-line description
+DESCRIPTION:event with one-line description
+END:VEVENT
+
+BEGIN:VEVENT
+DTSTART:20200404T204500
+DURATION:PT1H30M0S
+SUMMARY:description and location
+DESCRIPTION:event with description\nand location
+LOCATION: Right here
+END:VEVENT
+
+BEGIN:VEVENT
+DTSTART:20200404T084100
+DURATION:PT1H30M0S
+SUMMARY:no description\, but comment
+COMMENT:Event without description: a comment\nstreching over\nthree lines
+END:VEVENT
+
+BEGIN:VEVENT
+DTSTART:20200404T084100
+DURATION:PT1H30M0S
+SUMMARY:Empty description
+DESCRIPTION:
+END:VEVENT
+
+BEGIN:VEVENT
+DTSTART:20200404T084100
+DURATION:PT1H30M0S
+SUMMARY:Empty description\, but comment
+DESCRIPTION:
+COMMENT:event with empty description
+END:VEVENT
+
+BEGIN:VEVENT
+DTSTART:20200404T204500
+DURATION:PT1H30M0S
+SUMMARY:description\, comment and location
+DESCRIPTION:event with\ndescription\ncomment\nand location
+LOCATION: Right here
+COMMENT:just a repetition of description:\nevent with\ndescription\ncomment\nand location
+END:VEVENT
+
+BEGIN:VTODO
+PRIORITY:2
+SUMMARY:todo with one-line description
+DESCRIPTION:todo with one-line description
+END:VTODO
+
+BEGIN:VTODO
+PRIORITY:3
+SUMMARY:description and location
+DESCRIPTION:todo with description\nand location
+LOCATION: Right here
+END:VTODO
+
+BEGIN:VTODO
+PRIORITY:4
+SUMMARY:no description\, but comment
+COMMENT:Todo without description. A comment\nstreching over\nthree lines
+END:VTODO
+
+BEGIN:VTODO
+PRIORITY:5
+SUMMARY:Empty description
+DESCRIPTION:
+END:VTODO
+
+BEGIN:VTODO
+PRIORITY:6
+SUMMARY:Empty description
+DESCRIPTION:
+END:VTODO
+
+BEGIN:VTODO
+SUMMARY:todo with description\, comment and location
+DESCRIPTION:todo with\ndescription\ncomment\nand location\,\nbut no priority
+LOCATION: Right here
+COMMENT:mostly a repetition of description:\ntodo with\ndescription\ncomment\nand location
+STATUS:COMPLETED
+END:VTODO
+
+END:VCALENDAR
diff --git a/test/data/ical-014.ical b/test/data/ical-014.ical
new file mode 100644
index 0000000..19076bc
--- /dev/null
+++ b/test/data/ical-014.ical
@@ -0,0 +1,106 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+
+BEGIN:VEVENT
+DTSTART:20200404T204500
+DURATION:PT1H30M0S
+SUMMARY:event with one-line description
+DESCRIPTION:event with one-line description
+END:VEVENT
+
+BEGIN:VEVENT
+DTSTART:20200404T204500
+DURATION:PT1H30M0S
+SUMMARY:description and location
+DESCRIPTION:event with description\nand location
+LOCATION:Right here
+END:VEVENT
+
+BEGIN:VEVENT
+DTSTART:20200404T084100
+DURATION:PT1H30M0S
+SUMMARY:no description\, but comment
+COMMENT:Event without description: a comment\nstreching over\nthree lines
+END:VEVENT
+
+BEGIN:VEVENT
+DTSTART:20200404T084100
+DURATION:PT1H30M0S
+SUMMARY:Empty description
+DESCRIPTION:
+END:VEVENT
+
+BEGIN:VEVENT
+DTSTART:20200404T084100
+DURATION:PT1H30M0S
+SUMMARY:Empty description\, but comment
+DESCRIPTION:
+COMMENT:event with empty description
+END:VEVENT
+
+BEGIN:VEVENT
+DTSTART:20200404T204500
+DURATION:PT1H30M0S
+SUMMARY:description\, comment and location
+DESCRIPTION:event with\ndescription\ncomment\nand location
+LOCATION:Right here
+COMMENT:just a repetition of description:\nevent with\ndescription\ncomment\nand location
+END:VEVENT
+
+BEGIN:VTODO
+PRIORITY:2
+SUMMARY:todo with one-line description
+DESCRIPTION:todo with one-line description
+END:VTODO
+
+BEGIN:VTODO
+PRIORITY:3
+SUMMARY:description and location
+DESCRIPTION:todo with description\nand location
+LOCATION:Right here
+END:VTODO
+
+BEGIN:VTODO
+PRIORITY:4
+SUMMARY:no description\, but comment
+COMMENT:Todo without description. A comment\nstreching over\nthree lines
+END:VTODO
+
+BEGIN:VTODO
+PRIORITY:5
+SUMMARY:Empty description
+DESCRIPTION:
+END:VTODO
+
+BEGIN:VTODO
+PRIORITY:6
+SUMMARY:Empty description
+DESCRIPTION:
+END:VTODO
+
+BEGIN:VTODO
+SUMMARY:todo with description\, comment and location
+DESCRIPTION:todo with\ndescription\ncomment\nand location\,\nbut no priority
+LOCATION:Right here
+COMMENT:mostly a repetition of description:\ntodo with\ndescription\ncomment\nand location
+STATUS:COMPLETED
+END:VTODO
+
+BEGIN:VEVENT
+SUMMARY:Five days
+DESCRIPTION:A five-day event turned into a recurring one-day event
+COMMENT:Note file has Comment: and Import:
+DTSTART;VALUE=DATE:20200819
+DTEND;VALUE=DATE:20200824
+END:VEVENT
+
+BEGIN:VEVENT
+SUMMARY:CET
+DESCRIPTION:Date with local time and time zone reference
+LOCATION:Central Europe
+COMMENT:\nCET\n\n
+DTSTART;TZID=CET:20150223T110000
+DURATION:PT1H
+END:VEVENT
+
+END:VCALENDAR
diff --git a/test/data/rfc5545 b/test/data/rfc5545
new file mode 100644
index 0000000..d9863ce
--- /dev/null
+++ b/test/data/rfc5545
@@ -0,0 +1,28 @@
+01/05/1997 @ 08:30 -> 01/05/1997 @ 08:30 {2Y w0 m1} |page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+01/01/1998 @ 09:00 -> 01/01/1998 @ 09:00 {1Y -> 01/31/2000 w0 w1 w2 w3 w4 w5 w6 m1} |page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+01/01/1998 @ 09:00 -> 01/01/1998 @ 09:00 {1D -> 01/31/2000 m1} |page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+09/02/1997 @ 09:00 -> 09/02/1997 @ 09:00 {1W -> 10/02/1997 w2 w4} |page 125(1): Weekly on Tuesday and Thursday for five weeks (FREQ=WEEKLY;UNTIL=19971002T000000Z;BYDAY=TU,TH)
+09/01/1997 @ 09:00 -> 09/01/1997 @ 09:00 {2W -> 12/24/1997 w1 w3 w5} |page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+09/05/1997 @ 09:00 -> 09/05/1997 @ 09:00 {1M -> 06/05/1998 w12} |page 126: Monthly on the first Friday for 10 occurrences (FREQ=MONTHLY;COUNT=10;BYDAY=1FR)
+09/07/1997 @ 09:00 -> 09/07/1997 @ 09:00 {2M -> 05/31/1998 w7 w-7} |page 126: Every other month on the first and last Sunday of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU)
+09/22/1997 @ 09:00 -> 09/22/1997 @ 09:00 {1M -> 02/28/1998 w-15} |page 126: Monthly on the second-to-last Monday of the month for 6 months (RRULE:FREQ=MONTHLY;COUNT=6;BYDAY=-2MO)
+09/28/1997 [1] {1M d-3} page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+09/02/1997 @ 09:00 -> 09/02/1997 @ 09:00 {1M -> 02/01/1998 d2 d15} |Page 127: Monthly on the 2nd and 15th of month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15)
+09/30/1997 @ 09:00 -> 09/30/1997 @ 09:00 {1M -> 02/01/1998 d1 d-1} |page 127: Monthly on the first and last day of the month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1)
+09/10/1997 @ 09:00 -> 09/10/1997 @ 09:00 {18M -> 03/13/1999 d10 d11 d12 d13 d14 d15} |page 127: Every 18 months on the 10th thru 15th of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15)
+09/02/1997 @ 09:00 -> 09/02/1997 @ 09:00 {2M w2} |page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+06/10/1997 @ 09:00 -> 06/10/1997 @ 09:00 {1Y -> 07/10/2001 m6 m7} |page 128: Yearly in June and July for 10 occurrences (RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7)
+03/10/1997 @ 09:00 -> 03/10/1997 @ 09:00 {2Y -> 03/10/2003 m1 m2 m3} |page 128: Every other year in January, February and March for 10 occurrences (RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3)
+05/19/1997 [1] {1Y w141} page 128: Every 20th Monday of the year, forever (RRULE:FREQ=YEARLY;BYDAY=20MO)
+03/13/1997 @ 09:00 -> 03/13/1997 @ 09:00 {1Y w4 m3} |page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+06/05/1997 @ 09:00 -> 06/05/1997 @ 09:00 {1Y w4 m6 m7 m8} |page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+02/13/1998 [1] {1M d13 w5} page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+09/13/1997 [1] {1M d7 d8 d9 d10 d11 d12 d13 w6} page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+11/05/1996 [1] {4Y d2 d3 d4 d5 d6 d7 d8 w2 m11} page 130: Every 4 years, the first Tuesday after a Monday in November, forever (U.S. Presidential Election day) (RRULE:FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8)
+08/05/1997 @ 09:00 -> 08/05/1997 @ 09:00 {2W -> 08/31/1997 w0 w2} |page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+01/15/2007 [1] {1M -> 03/30/2007 d15 d30} page 132: An example where an invalid date (i.e. February 30) is ignored (RRULE:FREQ=MONTHLY;BYMONTHDAY=15,30;COUNT=5)
+03/30/1997 @ 09:00 -> 03/30/1997 @ 09:00 {1Y w-7 m3} |Last Sunday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU)
+12/25/1997 [1] {3Y w-11} Last Thursday of the year every third year, forever (FREQ=YEARLY;INTERVAL=3;BYDAY=-1TH)
+06/22/1997 [1] {2Y w0 w1} Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+02/01/1997 [1] {1Y -> 01/31/2005 d1 d29 m2} Every year on February 1 and 29 for eight years (RRULE:FREQ=YEARLY;UNTIL=20050131T000000Z;BYMONTH=2;BYMONTHDAY=1,29)
+08/01/2020 @ 08:41 -> 08/01/2020 @ 10:11 {1M w-41} |negative ordered weekday may not exist
diff --git a/test/data/rfc5545.ical b/test/data/rfc5545.ical
new file mode 100644
index 0000000..3f51388
--- /dev/null
+++ b/test/data/rfc5545.ical
@@ -0,0 +1,238 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970901T090000
+SUMMARY:Every other week on Monday\, Wednesday\, and Friday until December 24\, 1997\, starting on Monday\, September 1\, 1997
+RRULE:FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;WKST=SU;BYDAY=MO,WE,FR
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970902T090000
+SUMMARY:Every other week on Tuesday and Thursday\, for 8 occurrences
+RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=8;WKST=SU;BYDAY=TU,TH
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970905T090000
+SUMMARY:Monthly on the first Friday for 10 occurrences
+RRULE:FREQ=MONTHLY;COUNT=10;BYDAY=1FR
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970905T090000
+SUMMARY:Monthly on the first Friday until December 24\, 1997
+RRULE:FREQ=MONTHLY;UNTIL=19971224T000000Z;BYDAY=1FR
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970907T090000
+SUMMARY:Every other month on the first and last Sunday of the month for 10 occurrences
+RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970922T090000
+SUMMARY:Monthly on the second-to-last Monday of the month for 6 months
+RRULE:FREQ=MONTHLY;COUNT=6;BYDAY=-2MO
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970928T090000
+SUMMARY:Monthly on the third-to-the-last day of the month\, forever
+RRULE:FREQ=MONTHLY;BYMONTHDAY=-3
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970902T090000
+SUMMARY:Monthly on the 2nd and 15th of the month for 10 occurrences
+RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970930T090000
+SUMMARY:Monthly on the first and last day of the month for 10 occurrences
+RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970910T090000
+SUMMARY:Every 18 months on the 10th thru 15th of the month for 10 occurrences
+RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970902T090000
+DURATION:PT1H
+SUMMARY:Daily for 10 occurrences
+RRULE:FREQ=DAILY;COUNT=10
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970902T090000
+SUMMARY:Every Tuesday\, every other month
+RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970610T090000
+SUMMARY:Yearly in June and July for 10 occurrences
+RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970310T090000
+SUMMARY:Every other year on January\, February\, and March for 10 occurrences
+RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970519T090000
+SUMMARY:Every 20th Monday of the year\, forever
+RRULE:FREQ=YEARLY;BYDAY=20MO
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970313T090000
+SUMMARY:Every Thursday in March\, forever
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970605T090000
+SUMMARY:Every Thursday\, but only during June\, July\, and August\, forever
+RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19980213T090000
+SUMMARY:Every Friday the 13th\, forever
+RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970913T090000
+SUMMARY:The first Saturday that follows the first Sunday of the month\, forever
+RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19961105T090000
+SUMMARY:Every 4 years\, the first Tuesday after a Monday in November\, forever (U.S. Presidential Election day)
+RRULE:FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970805T090000
+SUMMARY:An example where the days generated makes a difference because of WKST
+RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=MO
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970805T090000
+SUMMARY:changing only WKST from MO to SU\, yields different results...
+RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=SU
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970902T090000
+DURATION:PT30M
+SUMMARY:Daily until December 24\, 1997
+RRULE:FREQ=DAILY;UNTIL=19971224T000000Z
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:20070115T090000
+SUMMARY:An example where an invalid date (i.e.\, February 30) is ignored
+RRULE:FREQ=MONTHLY;BYMONTHDAY=15,30;COUNT=5
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970902T090000
+DURATION:PT5M
+SUMMARY:Every other day - forever
+RRULE:FREQ=DAILY;INTERVAL=2
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970902T090000
+SUMMARY:Every 10 days\, 5 occurrences:
+RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19980101T090000
+SUMMARY:(1) Every day in January\, for 3 years:
+RRULE:FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19980101T090000
+SUMMARY:(2) Every day in January\, for 3 years:
+RRULE:FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970902T090000
+SUMMARY:Weekly for 10 occurrences
+RRULE:FREQ=WEEKLY;COUNT=10
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970902T090000
+SUMMARY:Weekly until December 24\, 1997
+RRULE:FREQ=WEEKLY;UNTIL=19971224T000000Z
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970902T090000
+SUMMARY:Every other week - forever
+RRULE:FREQ=WEEKLY;INTERVAL=2;WKST=SU
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970902T090000
+SUMMARY:Weekly on Tuesday and Thursday for five weeks (UNTIL)
+RRULE:FREQ=WEEKLY;UNTIL=19971007T000000Z;WKST=SU;BYDAY=TU,TH
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:
+UID:
+DTSTART;TZID=America/New_York:19970902T090000
+SUMMARY:Weekly on Tuesday and Thursday for five weeks (COUNT)
+RRULE:FREQ=WEEKLY;COUNT=10;WKST=SU;BYDAY=TU,TH
+END:VEVENT
+END:VCALENDAR
diff --git a/test/data/todo-export b/test/data/todo-export
new file mode 100644
index 0000000..b7cfc23
--- /dev/null
+++ b/test/data/todo-export
@@ -0,0 +1 @@
+[1] Exported, escaped characters in SUMMARY: ,(comma), ;(semicolon) , and \(escape).
diff --git a/test/ical-001.sh b/test/ical-001.sh
index ff5b9ce..c8005a7 100755
--- a/test/ical-001.sh
+++ b/test/ical-001.sh
@@ -3,15 +3,15 @@
. "${TEST_INIT:-./test-init.sh}"
if [ "$1" = 'actual' ]; then
- mkdir .calcurse || exit 1
- cp "$DATA_DIR/conf" .calcurse || exit 1
- "$CALCURSE" -D "$PWD/.calcurse" -i "$DATA_DIR/ical-001.ical"
- "$CALCURSE" -D "$PWD/.calcurse" -s01/01/1980 -r2
- "$CALCURSE" -D "$PWD/.calcurse" -t
- rm -rf .calcurse || exit 1
+ tmpdir=$(mktemp -d)
+ cp "$DATA_DIR/conf" "$tmpdir" || exit 1
+ "$CALCURSE" -D "$tmpdir" -i "$DATA_DIR/ical-001.ical"
+ "$CALCURSE" -D "$tmpdir" -s01/01/1980 -r2
+ "$CALCURSE" -D "$tmpdir" -t
+ rm -rf "$tmpdir" || exit 1
elif [ "$1" = 'expected' ]; then
cat <<EOD
-Import process report: 0017 lines read
+Import process report: 0012 lines read
1 app / 0 events / 1 todo / 0 skipped
01/01/80:
- 00:01 -> ..:..
diff --git a/test/ical-002.sh b/test/ical-002.sh
index 81ed1f1..eeecab4 100755
--- a/test/ical-002.sh
+++ b/test/ical-002.sh
@@ -3,14 +3,14 @@
. "${TEST_INIT:-./test-init.sh}"
if [ "$1" = 'actual' ]; then
- mkdir .calcurse || exit 1
- cp "$DATA_DIR/conf" .calcurse || exit 1
- "$CALCURSE" -D "$PWD/.calcurse" -i "$DATA_DIR/ical-002.ical"
- "$CALCURSE" -D "$PWD/.calcurse" -s01/01/2000 -r2
- rm -rf .calcurse || exit 1
+ tmpdir=$(mktemp -d)
+ cp "$DATA_DIR/conf" "$tmpdir" || exit 1
+ "$CALCURSE" -D "$tmpdir" -i "$DATA_DIR/ical-002.ical"
+ "$CALCURSE" -D "$tmpdir" -s01/01/2000 -r2
+ rm -rf "$tmpdir" || exit 1
elif [ "$1" = 'expected' ]; then
cat <<EOD
-Import process report: 0036 lines read
+Import process report: 0028 lines read
5 apps / 0 events / 0 todos / 0 skipped
01/01/00:
- 00:00 -> 00:00
diff --git a/test/ical-003.sh b/test/ical-003.sh
index 244a6d5..ace0165 100755
--- a/test/ical-003.sh
+++ b/test/ical-003.sh
@@ -1,17 +1,20 @@
#!/bin/sh
+# Recurrence rules.
. "${TEST_INIT:-./test-init.sh}"
if [ "$1" = 'actual' ]; then
- mkdir .calcurse || exit 1
- cp "$DATA_DIR/conf" .calcurse || exit 1
- "$CALCURSE" -D "$PWD/.calcurse" -i "$DATA_DIR/ical-003.ical"
- "$CALCURSE" -D "$PWD/.calcurse" -s01/01/2000 -r365
- rm -rf .calcurse || exit 1
+ tmpdir=$(mktemp -d)
+ cp "$DATA_DIR/conf" "$tmpdir" || exit 1
+ "$CALCURSE" -D "$tmpdir" -i "$DATA_DIR/ical-003.ical"
+ "$CALCURSE" -D "$tmpdir" -s01/01/2000 -r365
+ "$CALCURSE" -D "$tmpdir" -s05/01/2020 --to 01/01/2023
+ cat "$tmpdir/notes"/*
+ rm -rf "$tmpdir" || exit 1
elif [ "$1" = 'expected' ]; then
cat <<EOD
-Import process report: 0031 lines read
-3 apps / 0 events / 0 todos / 0 skipped
+Import process report: 0070 lines read
+7 apps / 2 events / 0 todos / 0 skipped
01/01/00:
- 00:00 -> 01:30
Recurring appointment
@@ -131,6 +134,106 @@ Import process report: 0031 lines read
02/29/00:
- 00:00 -> 01:30
Recurring appointment
+05/02/20:
+ * First weekend in May
+ * First weekend in May
+ - 00:00 -> ..:..
+ First weekend in May
+
+05/03/20:
+ * First weekend in May
+ - ..:.. -> 00:00
+ First weekend in May
+
+05/26/20:
+ - 12:00 -> 13:17
+ until May 29 2020, 11:00
+ - 12:00 -> 13:17
+ until May 29 2020, 13:00
+
+05/27/20:
+ - 12:00 -> 13:17
+ until May 29 2020, 11:00
+ - 12:00 -> 13:17
+ until May 29 2020, 13:00
+
+05/28/20:
+ - 12:00 -> 13:17
+ until May 29 2020, 11:00
+ - 12:00 -> 13:17
+ until May 29 2020, 13:00
+
+05/29/20:
+ - 12:00 -> 13:17
+ until May 29 2020, 13:00
+
+05/31/20:
+ - 21:45 -> 22:00
+ monthly on 31th, count 10, exceptions 31/7/2020 and 31/1/2021
+
+08/31/20:
+ - 21:45 -> 22:00
+ monthly on 31th, count 10, exceptions 31/7/2020 and 31/1/2021
+
+10/31/20:
+ - 21:45 -> 22:00
+ monthly on 31th, count 10, exceptions 31/7/2020 and 31/1/2021
+
+12/31/20:
+ - 21:45 -> 22:00
+ monthly on 31th, count 10, exceptions 31/7/2020 and 31/1/2021
+
+03/31/21:
+ - 21:45 -> 22:00
+ monthly on 31th, count 10, exceptions 31/7/2020 and 31/1/2021
+
+05/01/21:
+ * First weekend in May
+ - 00:00 -> ..:..
+ First weekend in May
+
+05/02/21:
+ - ..:.. -> 00:00
+ First weekend in May
+
+05/31/21:
+ - 21:45 -> 22:00
+ monthly on 31th, count 10, exceptions 31/7/2020 and 31/1/2021
+
+07/31/21:
+ - 21:45 -> 22:00
+ monthly on 31th, count 10, exceptions 31/7/2020 and 31/1/2021
+
+08/31/21:
+ - 21:45 -> 22:00
+ monthly on 31th, count 10, exceptions 31/7/2020 and 31/1/2021
+
+10/31/21:
+ - 21:45 -> 22:00
+ monthly on 31th, count 10, exceptions 31/7/2020 and 31/1/2021
+
+12/31/21:
+ - 21:45 -> 22:00
+ monthly on 31th, count 10, exceptions 31/7/2020 and 31/1/2021
+
+05/07/22:
+ * First weekend in May
+ - 00:00 -> ..:..
+ First weekend in May
+
+05/08/22:
+ - ..:.. -> 00:00
+ First weekend in May
+First weekend in May is a two-day event!
+Repeating appointment.
+The first weekend in May is a two-day event.
+Non-repeating event.
+--
+Import: multi-day event changed to one-day event
+First weekend in May is a two-day event!
+Repeating event, three years.
+--
+Import: multi-day event changed to one-day event
EOD
else
./run-test "$0"
diff --git a/test/ical-004.sh b/test/ical-004.sh
index 1819791..1d19d73 100755
--- a/test/ical-004.sh
+++ b/test/ical-004.sh
@@ -3,15 +3,15 @@
. "${TEST_INIT:-./test-init.sh}"
if [ "$1" = 'actual' ]; then
- mkdir .calcurse || exit 1
- cp "$DATA_DIR/conf" .calcurse || exit 1
- "$CALCURSE" -D "$PWD/.calcurse" -i "$DATA_DIR/ical-004.ical"
- "$CALCURSE" -D "$PWD/.calcurse" -s01/01/1980 -r2
- "$CALCURSE" -D "$PWD/.calcurse" -t
- rm -rf .calcurse || exit 1
+ tmpdir=$(mktemp -d)
+ cp "$DATA_DIR/conf" "$tmpdir" || exit 1
+ "$CALCURSE" -D "$tmpdir" -i "$DATA_DIR/ical-004.ical"
+ "$CALCURSE" -D "$tmpdir" -s01/01/1980 -r2
+ "$CALCURSE" -D "$tmpdir" -t
+ rm -rf "$tmpdir" || exit 1
elif [ "$1" = 'expected' ]; then
cat <<EOD
-Import process report: 0017 lines read
+Import process report: 0012 lines read
1 app / 0 events / 1 todo / 0 skipped
01/01/80:
- 00:01 -> ..:..
diff --git a/test/ical-005.sh b/test/ical-005.sh
index 5e9796b..47891ee 100755
--- a/test/ical-005.sh
+++ b/test/ical-005.sh
@@ -3,23 +3,26 @@
. "${TEST_INIT:-./test-init.sh}"
if [ "$1" = 'actual' ]; then
- mkdir .calcurse || exit 1
- cp "$DATA_DIR/conf" .calcurse || exit 1
- "$CALCURSE" -D "$PWD/.calcurse" -i "$DATA_DIR/ical-005.ical"
- "$CALCURSE" -D "$PWD/.calcurse" -s10/03/2013 -r3
- rm -rf .calcurse || exit 1
+ tmpdir=$(mktemp -d)
+ cp "$DATA_DIR/conf" "$tmpdir" || exit 1
+ "$CALCURSE" -D "$tmpdir" -i "$DATA_DIR/ical-005.ical"
+ "$CALCURSE" -D "$tmpdir" -s10/03/2013 -r3
+ cat "$tmpdir/notes"/*
+ rm -rf "$tmpdir" || exit 1
elif [ "$1" = 'expected' ]; then
cat <<EOD
-Import process report: 0030 lines read
+Import process report: 0023 lines read
0 apps / 4 events / 0 todos / 0 skipped
10/03/13:
* All day
* On day 1
- * On day 2
* Two days
10/04/13:
+ * On day 2
* Two days
+--
+Import: multi-day event changed to one-day event
EOD
else
./run-test "$0"
diff --git a/test/ical-006.sh b/test/ical-006.sh
index 1d9359a..b923712 100755
--- a/test/ical-006.sh
+++ b/test/ical-006.sh
@@ -3,14 +3,14 @@
. "${TEST_INIT:-./test-init.sh}"
if [ "$1" = 'actual' ]; then
- mkdir .calcurse || exit 1
- cp "$DATA_DIR/conf" .calcurse || exit 1
- "$CALCURSE" -D "$PWD/.calcurse" -i "$DATA_DIR/ical-006.ical"
- "$CALCURSE" -D "$PWD/.calcurse" -s06/01/2012 -r2
- rm -rf .calcurse || exit 1
+ tmpdir=$(mktemp -d)
+ cp "$DATA_DIR/conf" "$tmpdir" || exit 1
+ "$CALCURSE" -D "$tmpdir" -i "$DATA_DIR/ical-006.ical"
+ "$CALCURSE" -D "$tmpdir" -s06/01/2012 -r2
+ rm -rf "$tmpdir" || exit 1
elif [ "$1" = 'expected' ]; then
cat <<EOD
-Import process report: 0078 lines read
+Import process report: 0063 lines read
12 apps / 0 events / 0 todos / 0 skipped
06/01/12:
- 15:00 -> 15:30
diff --git a/test/ical-007.sh b/test/ical-007.sh
index 4c43a4e..82405c9 100755
--- a/test/ical-007.sh
+++ b/test/ical-007.sh
@@ -3,21 +3,26 @@
. "${TEST_INIT:-./test-init.sh}"
if [ "$1" = 'actual' ]; then
- mkdir .calcurse || exit 1
- cp "$DATA_DIR/conf" .calcurse || exit 1
- TZ="America/New_York" "$CALCURSE" -D "$PWD/.calcurse" \
+ tmpdir=$(mktemp -d)
+ cp "$DATA_DIR/conf" "$tmpdir" || exit 1
+ TZ="America/New_York" "$CALCURSE" -D "$tmpdir" \
-i "$DATA_DIR/ical-007.ical"
- "$CALCURSE" -D "$PWD/.calcurse" -s02/23/2015
- rm -rf .calcurse || exit 1
+ "$CALCURSE" -D "$tmpdir" -s02/23/2015
+ cat "$tmpdir/notes/"*
+ rm -rf "$tmpdir" || exit 1
elif [ "$1" = 'expected' ]; then
cat <<EOD
Import process report: 0018 lines read
-2 apps / 0 events / 0 todos / 0 skipped
+3 apps / 0 events / 0 todos / 0 skipped
02/23/15:
+ - 05:00 -> 06:00
+ CET
- 06:00 -> 07:00
UTC
- 11:00 -> 12:00
Local time
+--
+Import: TZID=CET
EOD
else
./run-test "$0"
diff --git a/test/ical-008.sh b/test/ical-008.sh
index bc59e56..344fa8a 100755
--- a/test/ical-008.sh
+++ b/test/ical-008.sh
@@ -3,15 +3,15 @@
. "${TEST_INIT:-./test-init.sh}"
if [ "$1" = 'actual' ]; then
- mkdir .calcurse || exit 1
- cp "$DATA_DIR/conf" .calcurse || exit 1
- "$CALCURSE" -D "$PWD/.calcurse" -i "$DATA_DIR/ical-008.ical"
- "$CALCURSE" -D "$PWD/.calcurse" -s01/01/1980 -r2
- "$CALCURSE" -D "$PWD/.calcurse" -t
- rm -rf .calcurse || exit 1
+ tmpdir=$(mktemp -d)
+ cp "$DATA_DIR/conf" "$tmpdir" || exit 1
+ "$CALCURSE" -D "$tmpdir" -i "$DATA_DIR/ical-008.ical"
+ "$CALCURSE" -D "$tmpdir" -s01/01/1980 -r2
+ "$CALCURSE" -D "$tmpdir" -t
+ rm -rf "$tmpdir" || exit 1
elif [ "$1" = 'expected' ]; then
cat <<EOD
-Import process report: 0017 lines read
+Import process report: 0012 lines read
1 app / 0 events / 1 todo / 0 skipped
01/01/80:
- 00:01 -> ..:..
diff --git a/test/ical-009.sh b/test/ical-009.sh
new file mode 100755
index 0000000..6c1a0d4
--- /dev/null
+++ b/test/ical-009.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+# Import with skipped items.
+
+. "${TEST_INIT:-./test-init.sh}"
+
+if [ "$1" = 'actual' ]; then
+ tmpdir=$(mktemp -d)
+ cp "$DATA_DIR/conf" "$tmpdir" || exit 1
+ out=$("$CALCURSE" -D "$tmpdir" -i "$DATA_DIR/ical-009.ical" 2>&1)
+ # Print the import report (stdout).
+ echo "$out" | awk '$1 == "Import"; $2 == "apps"'
+ # Find the log file and print the log messages (stderr).
+ logfile=$(echo "$out" | awk '$1 == "See" { print $2 }')
+ sed '1,18d' "$logfile"
+ # One empty note file.
+ cat "$tmpdir/notes"/* | wc | awk '{ print $1 $2 $3 }'
+ rm -rf "$tmpdir" || exit 1
+elif [ "$1" = 'expected' ]; then
+ cat <<EOD
+Import process report: 0131 lines read
+3 apps / 0 events / 1 todo / 20 skipped
+VEVENT [12]: invalid or malformed event start time.
+VEVENT [17]: item start date not defined.
+VEVENT [21]: rrule frequency not supported.
+VEVENT [27]: malformed summary line.
+VTODO [32]: item priority is invalid (must be between 0 and 9).
+VEVENT [36]: malformed exceptions line.
+VEVENT [43]: exception date, but no recurrence rule.
+VEVENT [54]: malformed description line.
+VEVENT [60]: malformed description.
+VTODO [72]: malformed summary.
+VEVENT [76]: only one location allowed.
+VEVENT [83]: invalid duration.
+VEVENT [88]: invalid or malformed event start time.
+VEVENT [93]: invalid end time value type.
+VEVENT [98]: invalid until format.
+VEVENT [104]: invalid exception date value type.
+VEVENT [111]: invalid exception.
+VEVENT [118]: either end or duration.
+VEVENT [124]: end must be later than start.
+VTODO [129]: The ical file seems to be malformed. The end of item was not found.
+101
+EOD
+else
+ ./run-test "$0"
+fi
diff --git a/test/ical-010.sh b/test/ical-010.sh
new file mode 100755
index 0000000..e66538c
--- /dev/null
+++ b/test/ical-010.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+# ical export: encoded summary TEXT (escaped characters).
+
+. "${TEST_INIT:-./test-init.sh}"
+
+if [ "$1" = 'actual' ]; then
+ tmpdir=$(mktemp -d)
+ cp "$DATA_DIR/conf" "$tmpdir" || exit 1
+ cp "$DATA_DIR/apts-export" "$tmpdir"/apts || exit 1
+ cp "$DATA_DIR/todo-export" "$tmpdir"/todo || exit 1
+ "$CALCURSE" -D "$tmpdir" --export=ical | sed '/^PRODID/d'
+ rm -rf "$tmpdir" || exit 1
+elif [ "$1" = 'expected' ]; then
+ cat <<EOD
+BEGIN:VCALENDAR
+VERSION:2.0
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20200226
+SUMMARY:Exported\, escaped characters in SUMMARY: \,(comma)\, \;(semicolon) \, and \\\\(escape).
+END:VEVENT
+BEGIN:VEVENT
+DTSTART:20200226T070900
+DURATION:P0DT0H1M0S
+SUMMARY:Exported\, escaped characters in SUMMARY: \,(comma)\, \;(semicolon) \, and \\\\(escape).
+END:VEVENT
+BEGIN:VTODO
+PRIORITY:1
+SUMMARY:Exported\, escaped characters in SUMMARY: \,(comma)\, \;(semicolon) \, and \\\\(escape).
+END:VTODO
+END:VCALENDAR
+EOD
+else
+ ./run-test "$0"
+fi
diff --git a/test/ical-011.sh b/test/ical-011.sh
new file mode 100755
index 0000000..1b76e6d
--- /dev/null
+++ b/test/ical-011.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+# encoded summary TEXT (escaped charaters): export, then import and compare.
+
+. "${TEST_INIT:-./test-init.sh}"
+
+tmpdir=$(mktemp -d)
+cp "$DATA_DIR/conf" "$tmpdir" || exit 1
+cp "$DATA_DIR/apts-export" "$tmpdir"/apts || exit 1
+cp "$DATA_DIR/todo-export" "$tmpdir"/todo || exit 1
+
+"$CALCURSE" -D "$tmpdir" --export=ical >"$tmpdir"/export.ical &&
+(cd "$tmpdir"; mv apts apts-export; mv todo todo-export) &&
+"$CALCURSE" -D "$tmpdir" --quiet --import "$tmpdir"/export.ical &&
+(cd "$tmpdir"; cmp -s apts-export apts) &&
+(cd "$tmpdir"; cmp -s todo-export todo) &&
+status=0 || status=1
+
+rm -rf "$tmpdir" || exit 1
+exit $status
diff --git a/test/ical-012.sh b/test/ical-012.sh
new file mode 100755
index 0000000..38ae673
--- /dev/null
+++ b/test/ical-012.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+# Note file creation. Eleven note files are created for 6 apps and 6 todos.
+# To produce a fixed, predictable directory listing it is necessary that the
+# notes are of different sizes (except for the vevent and vtodo empty note which
+# is shared).
+
+. "${TEST_INIT:-./test-init.sh}"
+
+if [ "$1" = 'actual' ]; then
+ tmpdir=$(mktemp -d)
+ cp "$DATA_DIR/conf" "$tmpdir" || exit 1
+ "$CALCURSE" -D "$tmpdir" -i "$DATA_DIR/ical-012.ical"
+ (cd "$tmpdir/notes/"; cat $(ls -S1))
+ rm -rf "$tmpdir" || exit 1
+elif [ "$1" = 'expected' ]; then
+ cat <<EOD
+Import process report: 0089 lines read
+6 apps / 0 events / 6 todos / 0 skipped
+todo with
+description
+comment
+and location,
+but no priority
+--
+Location: Right here
+Comment: mostly a repetition of description:
+ todo with
+ description
+ comment
+ and location
+event with
+description
+comment
+and location
+--
+Location: Right here
+Comment: just a repetition of description:
+ event with
+ description
+ comment
+ and location
+--
+Comment: Event without description: a comment
+ streching over
+ three lines
+--
+Comment: Todo without description. A comment
+ streching over
+ three lines
+event with description
+and location
+--
+Location: Right here
+todo with description
+and location
+--
+Location: Right here
+
+--
+Comment: event with empty description
+event with one-line description
+todo with one-line description
+
+EOD
+else
+ ./run-test "$0"
+fi
diff --git a/test/ical-013.sh b/test/ical-013.sh
new file mode 100755
index 0000000..6509996
--- /dev/null
+++ b/test/ical-013.sh
@@ -0,0 +1,1800 @@
+#!/bin/sh
+# Advanced recurrence rules. All the examples from RFC 5545 which are suppported.
+
+. "${TEST_INIT:-./test-init.sh}"
+
+if [ "$1" = 'actual' ]; then
+ tmpdir=$(mktemp -d)
+ cp "$DATA_DIR/conf" "$tmpdir" || exit 1
+ TZ=America/New_York "$CALCURSE" -D "$tmpdir" -i "$DATA_DIR/rfc5545.ical"
+ "$CALCURSE" -D "$tmpdir" -s09/01/1997 -r365
+ rm -rf "$tmpdir" || exit 1
+elif [ "$1" = 'expected' ]; then
+ cat <<EOD
+Import process report: 0238 lines read
+33 apps / 0 events / 0 todos / 0 skipped
+09/01/97:
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+
+09/02/97:
+ - 09:00 -> 10:00
+ Daily for 10 occurrences
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every 10 days, 5 occurrences:
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+ - 09:00 -> 09:00
+ Every other week on Tuesday and Thursday, for 8 occurrences
+ - 09:00 -> 09:00
+ Monthly on the 2nd and 15th of the month for 10 occurrences
+ - 09:00 -> 09:00
+ Weekly for 10 occurrences
+ - 09:00 -> 09:00
+ Weekly on Tuesday and Thursday for five weeks (COUNT)
+ - 09:00 -> 09:00
+ Weekly on Tuesday and Thursday for five weeks (UNTIL)
+ - 09:00 -> 09:00
+ Weekly until December 24, 1997
+
+09/03/97:
+ - 09:00 -> 10:00
+ Daily for 10 occurrences
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+
+09/04/97:
+ - 09:00 -> 10:00
+ Daily for 10 occurrences
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week on Tuesday and Thursday, for 8 occurrences
+ - 09:00 -> 09:00
+ Weekly on Tuesday and Thursday for five weeks (COUNT)
+ - 09:00 -> 09:00
+ Weekly on Tuesday and Thursday for five weeks (UNTIL)
+
+09/05/97:
+ - 09:00 -> 10:00
+ Daily for 10 occurrences
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+ - 09:00 -> 09:00
+ Monthly on the first Friday for 10 occurrences
+ - 09:00 -> 09:00
+ Monthly on the first Friday until December 24, 1997
+
+09/06/97:
+ - 09:00 -> 10:00
+ Daily for 10 occurrences
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+09/07/97:
+ - 09:00 -> 10:00
+ Daily for 10 occurrences
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other month on the first and last Sunday of the month for 10 occurrences
+
+09/08/97:
+ - 09:00 -> 10:00
+ Daily for 10 occurrences
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+09/09/97:
+ - 09:00 -> 10:00
+ Daily for 10 occurrences
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+ - 09:00 -> 09:00
+ Weekly for 10 occurrences
+ - 09:00 -> 09:00
+ Weekly on Tuesday and Thursday for five weeks (COUNT)
+ - 09:00 -> 09:00
+ Weekly on Tuesday and Thursday for five weeks (UNTIL)
+ - 09:00 -> 09:00
+ Weekly until December 24, 1997
+
+09/10/97:
+ - 09:00 -> 10:00
+ Daily for 10 occurrences
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every 18 months on the 10th thru 15th of the month for 10 occurrences
+ - 09:00 -> 09:05
+ Every other day - forever
+
+09/11/97:
+ - 09:00 -> 10:00
+ Daily for 10 occurrences
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every 18 months on the 10th thru 15th of the month for 10 occurrences
+ - 09:00 -> 09:00
+ Weekly on Tuesday and Thursday for five weeks (COUNT)
+ - 09:00 -> 09:00
+ Weekly on Tuesday and Thursday for five weeks (UNTIL)
+
+09/12/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every 10 days, 5 occurrences:
+ - 09:00 -> 09:00
+ Every 18 months on the 10th thru 15th of the month for 10 occurrences
+ - 09:00 -> 09:05
+ Every other day - forever
+
+09/13/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every 18 months on the 10th thru 15th of the month for 10 occurrences
+ - 09:00 -> 09:00
+ The first Saturday that follows the first Sunday of the month, forever
+
+09/14/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every 18 months on the 10th thru 15th of the month for 10 occurrences
+ - 09:00 -> 09:05
+ Every other day - forever
+
+09/15/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every 18 months on the 10th thru 15th of the month for 10 occurrences
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+ - 09:00 -> 09:00
+ Monthly on the 2nd and 15th of the month for 10 occurrences
+
+09/16/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+ - 09:00 -> 09:00
+ Every other week on Tuesday and Thursday, for 8 occurrences
+ - 09:00 -> 09:00
+ Weekly for 10 occurrences
+ - 09:00 -> 09:00
+ Weekly on Tuesday and Thursday for five weeks (COUNT)
+ - 09:00 -> 09:00
+ Weekly on Tuesday and Thursday for five weeks (UNTIL)
+ - 09:00 -> 09:00
+ Weekly until December 24, 1997
+
+09/17/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+
+09/18/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week on Tuesday and Thursday, for 8 occurrences
+ - 09:00 -> 09:00
+ Weekly on Tuesday and Thursday for five weeks (COUNT)
+ - 09:00 -> 09:00
+ Weekly on Tuesday and Thursday for five weeks (UNTIL)
+
+09/19/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+
+09/20/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+09/21/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+
+09/22/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every 10 days, 5 occurrences:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Monthly on the second-to-last Monday of the month for 6 months
+
+09/23/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+ - 09:00 -> 09:00
+ Weekly for 10 occurrences
+ - 09:00 -> 09:00
+ Weekly on Tuesday and Thursday for five weeks (COUNT)
+ - 09:00 -> 09:00
+ Weekly on Tuesday and Thursday for five weeks (UNTIL)
+ - 09:00 -> 09:00
+ Weekly until December 24, 1997
+
+09/24/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+09/25/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Weekly on Tuesday and Thursday for five weeks (COUNT)
+ - 09:00 -> 09:00
+ Weekly on Tuesday and Thursday for five weeks (UNTIL)
+
+09/26/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+09/27/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+
+09/28/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other month on the first and last Sunday of the month for 10 occurrences
+ - 09:00 -> 09:00
+ Monthly on the third-to-the-last day of the month, forever
+
+09/29/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+
+09/30/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+ - 09:00 -> 09:00
+ Every other week on Tuesday and Thursday, for 8 occurrences
+ - 09:00 -> 09:00
+ Monthly on the first and last day of the month for 10 occurrences
+ - 09:00 -> 09:00
+ Weekly for 10 occurrences
+ - 09:00 -> 09:00
+ Weekly on Tuesday and Thursday for five weeks (COUNT)
+ - 09:00 -> 09:00
+ Weekly on Tuesday and Thursday for five weeks (UNTIL)
+ - 09:00 -> 09:00
+ Weekly until December 24, 1997
+
+10/01/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+ - 09:00 -> 09:00
+ Monthly on the first and last day of the month for 10 occurrences
+
+10/02/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every 10 days, 5 occurrences:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week on Tuesday and Thursday, for 8 occurrences
+ - 09:00 -> 09:00
+ Monthly on the 2nd and 15th of the month for 10 occurrences
+ - 09:00 -> 09:00
+ Weekly on Tuesday and Thursday for five weeks (COUNT)
+ - 09:00 -> 09:00
+ Weekly on Tuesday and Thursday for five weeks (UNTIL)
+
+10/03/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+ - 09:00 -> 09:00
+ Monthly on the first Friday for 10 occurrences
+ - 09:00 -> 09:00
+ Monthly on the first Friday until December 24, 1997
+
+10/04/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+10/05/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+
+10/06/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+10/07/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Weekly for 10 occurrences
+ - 09:00 -> 09:00
+ Weekly until December 24, 1997
+
+10/08/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+10/09/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+
+10/10/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+10/11/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ The first Saturday that follows the first Sunday of the month, forever
+
+10/12/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every 10 days, 5 occurrences:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+10/13/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+
+10/14/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+ - 09:00 -> 09:00
+ Every other week on Tuesday and Thursday, for 8 occurrences
+ - 09:00 -> 09:00
+ Weekly for 10 occurrences
+ - 09:00 -> 09:00
+ Weekly until December 24, 1997
+
+10/15/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+ - 09:00 -> 09:00
+ Monthly on the 2nd and 15th of the month for 10 occurrences
+
+10/16/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week on Tuesday and Thursday, for 8 occurrences
+
+10/17/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+
+10/18/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+10/19/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+
+10/20/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Monthly on the second-to-last Monday of the month for 6 months
+
+10/21/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Weekly for 10 occurrences
+ - 09:00 -> 09:00
+ Weekly until December 24, 1997
+
+10/22/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+10/23/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+
+10/24/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+10/25/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+
+10/26/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+10/27/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+
+10/28/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+ - 09:00 -> 09:00
+ Weekly for 10 occurrences
+ - 09:00 -> 09:00
+ Weekly until December 24, 1997
+
+10/29/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+ - 09:00 -> 09:00
+ Monthly on the third-to-the-last day of the month, forever
+
+10/30/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+10/31/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+ - 09:00 -> 09:00
+ Monthly on the first and last day of the month for 10 occurrences
+
+11/01/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Monthly on the first and last day of the month for 10 occurrences
+
+11/02/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other month on the first and last Sunday of the month for 10 occurrences
+ - 09:00 -> 09:00
+ Monthly on the 2nd and 15th of the month for 10 occurrences
+
+11/03/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+11/04/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+ - 09:00 -> 09:00
+ Weekly for 10 occurrences
+ - 09:00 -> 09:00
+ Weekly until December 24, 1997
+
+11/05/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+11/06/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+
+11/07/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Monthly on the first Friday for 10 occurrences
+ - 09:00 -> 09:00
+ Monthly on the first Friday until December 24, 1997
+
+11/08/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ The first Saturday that follows the first Sunday of the month, forever
+
+11/09/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+11/10/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+
+11/11/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+ - 09:00 -> 09:00
+ Weekly until December 24, 1997
+
+11/12/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+
+11/13/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+11/14/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+
+11/15/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Monthly on the 2nd and 15th of the month for 10 occurrences
+
+11/16/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+
+11/17/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Monthly on the second-to-last Monday of the month for 6 months
+
+11/18/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+ - 09:00 -> 09:00
+ Weekly until December 24, 1997
+
+11/19/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+11/20/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+
+11/21/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+11/22/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+
+11/23/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+11/24/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+
+11/25/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+ - 09:00 -> 09:00
+ Weekly until December 24, 1997
+
+11/26/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+
+11/27/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+11/28/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+ - 09:00 -> 09:00
+ Monthly on the third-to-the-last day of the month, forever
+
+11/29/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+11/30/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other month on the first and last Sunday of the month for 10 occurrences
+ - 09:00 -> 09:00
+ Monthly on the first and last day of the month for 10 occurrences
+
+12/01/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Monthly on the first and last day of the month for 10 occurrences
+
+12/02/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Monthly on the 2nd and 15th of the month for 10 occurrences
+ - 09:00 -> 09:00
+ Weekly until December 24, 1997
+
+12/03/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+12/04/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+
+12/05/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Monthly on the first Friday for 10 occurrences
+ - 09:00 -> 09:00
+ Monthly on the first Friday until December 24, 1997
+
+12/06/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+
+12/07/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+12/08/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+
+12/09/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+ - 09:00 -> 09:00
+ Weekly until December 24, 1997
+
+12/10/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+
+12/11/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+12/12/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+
+12/13/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ The first Saturday that follows the first Sunday of the month, forever
+
+12/14/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+
+12/15/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Monthly on the 2nd and 15th of the month for 10 occurrences
+
+12/16/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Weekly until December 24, 1997
+
+12/17/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+12/18/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+
+12/19/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+12/20/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+
+12/21/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+
+12/22/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:00
+ Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997
+ - 09:00 -> 09:00
+ Monthly on the second-to-last Monday of the month for 6 months
+
+12/23/97:
+ - 09:00 -> 09:30
+ Daily until December 24, 1997
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+ - 09:00 -> 09:00
+ Weekly until December 24, 1997
+
+12/25/97:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+12/27/97:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+12/29/97:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Monthly on the third-to-the-last day of the month, forever
+
+12/31/97:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Monthly on the first and last day of the month for 10 occurrences
+
+01/01/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ Monthly on the first and last day of the month for 10 occurrences
+
+01/02/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Monthly on the 2nd and 15th of the month for 10 occurrences
+ - 09:00 -> 09:00
+ Monthly on the first Friday for 10 occurrences
+
+01/03/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+
+01/04/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other month on the first and last Sunday of the month for 10 occurrences
+
+01/05/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+
+01/06/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+
+01/07/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+
+01/08/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+01/09/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+
+01/10/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ The first Saturday that follows the first Sunday of the month, forever
+
+01/11/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+
+01/12/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+01/13/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+
+01/14/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+01/15/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ Monthly on the 2nd and 15th of the month for 10 occurrences
+
+01/16/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+01/17/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+
+01/18/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+01/19/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ Monthly on the second-to-last Monday of the month for 6 months
+
+01/20/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+
+01/21/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+
+01/22/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+01/23/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+
+01/24/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+01/25/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ Every other month on the first and last Sunday of the month for 10 occurrences
+
+01/26/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+01/27/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+
+01/28/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+01/29/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ Monthly on the third-to-the-last day of the month, forever
+
+01/30/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+01/31/98:
+ - 09:00 -> 09:00
+ (1) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ (2) Every day in January, for 3 years:
+ - 09:00 -> 09:00
+ Monthly on the first and last day of the month for 10 occurrences
+
+02/01/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Monthly on the first and last day of the month for 10 occurrences
+
+02/03/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+
+02/05/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+02/06/98:
+ - 09:00 -> 09:00
+ Monthly on the first Friday for 10 occurrences
+
+02/07/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ The first Saturday that follows the first Sunday of the month, forever
+
+02/09/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+02/11/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+02/13/98:
+ - 09:00 -> 09:00
+ Every Friday the 13th, forever
+ - 09:00 -> 09:05
+ Every other day - forever
+
+02/15/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+02/16/98:
+ - 09:00 -> 09:00
+ Monthly on the second-to-last Monday of the month for 6 months
+
+02/17/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+
+02/19/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+02/21/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+02/23/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+02/25/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+02/26/98:
+ - 09:00 -> 09:00
+ Monthly on the third-to-the-last day of the month, forever
+
+02/27/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+03/01/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other month on the first and last Sunday of the month for 10 occurrences
+
+03/03/98:
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+
+03/05/98:
+ - 09:00 -> 09:00
+ Every Thursday in March, forever
+ - 09:00 -> 09:05
+ Every other day - forever
+
+03/06/98:
+ - 09:00 -> 09:00
+ Monthly on the first Friday for 10 occurrences
+
+03/07/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ The first Saturday that follows the first Sunday of the month, forever
+
+03/09/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+03/10/98:
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+
+03/11/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+03/12/98:
+ - 09:00 -> 09:00
+ Every Thursday in March, forever
+
+03/13/98:
+ - 09:00 -> 09:00
+ Every Friday the 13th, forever
+ - 09:00 -> 09:05
+ Every other day - forever
+
+03/15/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+03/17/98:
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+
+03/19/98:
+ - 09:00 -> 09:00
+ Every Thursday in March, forever
+ - 09:00 -> 09:05
+ Every other day - forever
+
+03/21/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+03/23/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+03/24/98:
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+
+03/25/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+03/26/98:
+ - 09:00 -> 09:00
+ Every Thursday in March, forever
+
+03/27/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+03/29/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other month on the first and last Sunday of the month for 10 occurrences
+ - 09:00 -> 09:00
+ Monthly on the third-to-the-last day of the month, forever
+
+03/31/98:
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+
+04/02/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+04/03/98:
+ - 09:00 -> 09:00
+ Monthly on the first Friday for 10 occurrences
+
+04/04/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+04/06/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+04/08/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+04/10/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+04/11/98:
+ - 09:00 -> 09:00
+ The first Saturday that follows the first Sunday of the month, forever
+
+04/12/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+04/14/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+
+04/16/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+04/18/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+04/20/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+04/22/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+04/24/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+04/26/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+04/28/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+ - 09:00 -> 09:00
+ Monthly on the third-to-the-last day of the month, forever
+
+04/30/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+05/01/98:
+ - 09:00 -> 09:00
+ Monthly on the first Friday for 10 occurrences
+
+05/02/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+05/03/98:
+ - 09:00 -> 09:00
+ Every other month on the first and last Sunday of the month for 10 occurrences
+
+05/04/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+05/05/98:
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+
+05/06/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+05/08/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+05/09/98:
+ - 09:00 -> 09:00
+ The first Saturday that follows the first Sunday of the month, forever
+
+05/10/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+05/12/98:
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+
+05/14/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+05/16/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+05/18/98:
+ - 09:00 -> 09:00
+ Every 20th Monday of the year, forever
+ - 09:00 -> 09:05
+ Every other day - forever
+
+05/19/98:
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+
+05/20/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+05/22/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+05/24/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+05/26/98:
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+
+05/28/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+05/29/98:
+ - 09:00 -> 09:00
+ Monthly on the third-to-the-last day of the month, forever
+
+05/30/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+05/31/98:
+ - 09:00 -> 09:00
+ Every other month on the first and last Sunday of the month for 10 occurrences
+
+06/01/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+06/03/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+06/04/98:
+ - 09:00 -> 09:00
+ Every Thursday, but only during June, July, and August, forever
+
+06/05/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Monthly on the first Friday for 10 occurrences
+
+06/07/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+06/09/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+
+06/10/98:
+ - 09:00 -> 09:00
+ Yearly in June and July for 10 occurrences
+
+06/11/98:
+ - 09:00 -> 09:00
+ Every Thursday, but only during June, July, and August, forever
+ - 09:00 -> 09:05
+ Every other day - forever
+
+06/13/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ The first Saturday that follows the first Sunday of the month, forever
+
+06/15/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+06/17/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+06/18/98:
+ - 09:00 -> 09:00
+ Every Thursday, but only during June, July, and August, forever
+
+06/19/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+06/21/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+06/23/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+
+06/25/98:
+ - 09:00 -> 09:00
+ Every Thursday, but only during June, July, and August, forever
+ - 09:00 -> 09:05
+ Every other day - forever
+
+06/27/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+06/28/98:
+ - 09:00 -> 09:00
+ Monthly on the third-to-the-last day of the month, forever
+
+06/29/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+07/01/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+07/02/98:
+ - 09:00 -> 09:00
+ Every Thursday, but only during June, July, and August, forever
+
+07/03/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+07/05/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+07/07/98:
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+
+07/09/98:
+ - 09:00 -> 09:00
+ Every Thursday, but only during June, July, and August, forever
+ - 09:00 -> 09:05
+ Every other day - forever
+
+07/10/98:
+ - 09:00 -> 09:00
+ Yearly in June and July for 10 occurrences
+
+07/11/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ The first Saturday that follows the first Sunday of the month, forever
+
+07/13/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+07/14/98:
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+
+07/15/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+07/16/98:
+ - 09:00 -> 09:00
+ Every Thursday, but only during June, July, and August, forever
+
+07/17/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+07/19/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+07/21/98:
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+
+07/23/98:
+ - 09:00 -> 09:00
+ Every Thursday, but only during June, July, and August, forever
+ - 09:00 -> 09:05
+ Every other day - forever
+
+07/25/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+07/27/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+07/28/98:
+ - 09:00 -> 09:00
+ Every Tuesday, every other month
+
+07/29/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Monthly on the third-to-the-last day of the month, forever
+
+07/30/98:
+ - 09:00 -> 09:00
+ Every Thursday, but only during June, July, and August, forever
+
+07/31/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+08/02/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+08/04/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+
+08/06/98:
+ - 09:00 -> 09:00
+ Every Thursday, but only during June, July, and August, forever
+ - 09:00 -> 09:05
+ Every other day - forever
+
+08/08/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ The first Saturday that follows the first Sunday of the month, forever
+
+08/10/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+08/12/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+08/13/98:
+ - 09:00 -> 09:00
+ Every Thursday, but only during June, July, and August, forever
+
+08/14/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+08/16/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+08/18/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+ - 09:00 -> 09:00
+ Every other week - forever
+
+08/20/98:
+ - 09:00 -> 09:00
+ Every Thursday, but only during June, July, and August, forever
+ - 09:00 -> 09:05
+ Every other day - forever
+
+08/22/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+08/24/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+08/26/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+08/27/98:
+ - 09:00 -> 09:00
+ Every Thursday, but only during June, July, and August, forever
+
+08/28/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+
+08/29/98:
+ - 09:00 -> 09:00
+ Monthly on the third-to-the-last day of the month, forever
+
+08/30/98:
+ - 09:00 -> 09:05
+ Every other day - forever
+EOD
+else
+ ./run-test "$0"
+fi
diff --git a/test/ical-014.sh b/test/ical-014.sh
new file mode 100755
index 0000000..18134bf
--- /dev/null
+++ b/test/ical-014.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+# Import followed by export and comparison
+
+. "${TEST_INIT:-./test-init.sh}"
+
+if [ "$1" = 'actual' ]; then
+ tmpdir=$(mktemp -d)
+ cp "$DATA_DIR/conf" "$tmpdir" || exit 1
+ "$CALCURSE" -q -D "$tmpdir" -i "$DATA_DIR/ical-014.ical"
+ "$CALCURSE" -D "$tmpdir" -x |
+ sed -n '
+ /DESCRIPTION/p
+ /LOCATION/p
+ /COMMENT/p
+ ' |
+ sort
+ rm -rf "$tmpdir" || exit 1
+elif [ "$1" = 'expected' ]; then
+ cat "$DATA_DIR/ical-014.ical" |
+ sed -n '
+ /DESCRIPTION/p
+ /LOCATION/p
+ /COMMENT/p
+ ' |
+ sort
+else
+ ./run-test "$0"
+fi
diff --git a/test/io-005.sh b/test/io-005.sh
index c5ebcc7..6b03908 100755
--- a/test/io-005.sh
+++ b/test/io-005.sh
@@ -3,7 +3,6 @@
. "${TEST_INIT:-./test-init.sh}"
home=$(mktemp -d)
-CALCURSE=$(readlink -f "$CALCURSE")
(unset -v XDG_DATA_HOME XDG_CONFIG_HOME; HOME="$home" "$CALCURSE" -a)
[ -f "$home/.local/share/calcurse/apts" ] && [ -f "$home/.config/calcurse/conf" ] && failed=0 || failed=1
diff --git a/test/io-006.sh b/test/io-006.sh
index 4184d9f..babcfcd 100755
--- a/test/io-006.sh
+++ b/test/io-006.sh
@@ -3,7 +3,6 @@
. "${TEST_INIT:-./test-init.sh}"
dir=$(mktemp -d)
-CALCURSE=$(readlink -f "$CALCURSE")
cd "$dir"
(unset -v HOME XDG_DATA_HOME XDG_CONFIG_HOME; "$CALCURSE" -a)
[ -f "$dir/.calcurse/apts" ] && [ -f "$dir/.calcurse/conf" ] && failed=0 || failed=1
diff --git a/test/recur-008.sh b/test/recur-008.sh
index c66bf12..75e4f5a 100755
--- a/test/recur-008.sh
+++ b/test/recur-008.sh
@@ -4,7 +4,7 @@
if [ "$1" = 'actual' ]; then
TZ='Europe/Copenhagen' "$CALCURSE" --read-only -D "$DATA_DIR"/ -c "$DATA_DIR/apts-dst" \
- -Q --from 03/24/2019 --to 03/31/2020 --filter-type recur-apt
+ -Q --from 03/24/2019 --to 03/31/2020 --filter-type recur-apt
elif [ "$1" = 'expected' ]; then
cat <<EOD
03/24/19:
diff --git a/test/recur-009.sh b/test/recur-009.sh
new file mode 100755
index 0000000..8cfe896
--- /dev/null
+++ b/test/recur-009.sh
@@ -0,0 +1,5342 @@
+#!/bin/sh
+# Support of selected RFC5545 recurrence rules.
+
+. "${TEST_INIT:-./test-init.sh}"
+
+if [ "$1" = 'actual' ]; then
+ "$CALCURSE" --read-only -D "$DATA_DIR"/ -c "$DATA_DIR/rfc5545" \
+ -Q --from 1/1/1996 --to 12/31/2007 --filter-type recur
+ echo ""
+ echo "Floating point exception?"
+ "$CALCURSE" --read-only -D "$DATA_DIR"/ -c "$DATA_DIR/rfc5545" \
+ -Q --day 8/1/2020 --filter-type recur &&
+ "$CALCURSE" --read-only -D "$DATA_DIR"/ -c "$DATA_DIR/rfc5545" \
+ -Q --day 11/1/2020 --filter-type recur &&
+ echo "No Floating point exception on November 1, 2020"
+elif [ "$1" = 'expected' ]; then
+ cat <<EOD
+11/05/96:
+ * page 130: Every 4 years, the first Tuesday after a Monday in November, forever (U.S. Presidential Election day) (RRULE:FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8)
+
+01/05/97:
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/12/97:
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/19/97:
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/26/97:
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+02/01/97:
+ * Every year on February 1 and 29 for eight years (RRULE:FREQ=YEARLY;UNTIL=20050131T000000Z;BYMONTH=2;BYMONTHDAY=1,29)
+
+03/10/97:
+ - 09:00 -> 09:00
+ page 128: Every other year in January, February and March for 10 occurrences (RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3)
+
+03/13/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/20/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/27/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/30/97:
+ - 09:00 -> 09:00
+ Last Sunday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU)
+
+05/19/97:
+ * page 128: Every 20th Monday of the year, forever (RRULE:FREQ=YEARLY;BYDAY=20MO)
+
+06/05/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/10/97:
+ - 09:00 -> 09:00
+ page 128: Yearly in June and July for 10 occurrences (RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7)
+
+06/12/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/19/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/22/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/23/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/26/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/29/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/30/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/03/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/06/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/07/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/10/97:
+ - 09:00 -> 09:00
+ page 128: Yearly in June and July for 10 occurrences (RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7)
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/13/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/14/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/17/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/20/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/21/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/24/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/27/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/28/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/31/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/03/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/04/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/05/97:
+ - 09:00 -> 09:00
+ page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+
+08/07/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/10/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+
+08/11/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/14/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/17/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/18/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/19/97:
+ - 09:00 -> 09:00
+ page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+
+08/21/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/24/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+
+08/25/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/28/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/31/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/01/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+09/02/97:
+ - 09:00 -> 09:00
+ Page 127: Monthly on the 2nd and 15th of month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15)
+ - 09:00 -> 09:00
+ page 125(1): Weekly on Tuesday and Thursday for five weeks (FREQ=WEEKLY;UNTIL=19971002T000000Z;BYDAY=TU,TH)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/03/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+09/04/97:
+ - 09:00 -> 09:00
+ page 125(1): Weekly on Tuesday and Thursday for five weeks (FREQ=WEEKLY;UNTIL=19971002T000000Z;BYDAY=TU,TH)
+
+09/05/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+ - 09:00 -> 09:00
+ page 126: Monthly on the first Friday for 10 occurrences (FREQ=MONTHLY;COUNT=10;BYDAY=1FR)
+
+09/07/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 126: Every other month on the first and last Sunday of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU)
+
+09/08/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/09/97:
+ - 09:00 -> 09:00
+ page 125(1): Weekly on Tuesday and Thursday for five weeks (FREQ=WEEKLY;UNTIL=19971002T000000Z;BYDAY=TU,TH)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/10/97:
+ - 09:00 -> 09:00
+ page 127: Every 18 months on the 10th thru 15th of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15)
+
+09/11/97:
+ - 09:00 -> 09:00
+ page 125(1): Weekly on Tuesday and Thursday for five weeks (FREQ=WEEKLY;UNTIL=19971002T000000Z;BYDAY=TU,TH)
+ - 09:00 -> 09:00
+ page 127: Every 18 months on the 10th thru 15th of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15)
+
+09/12/97:
+ - 09:00 -> 09:00
+ page 127: Every 18 months on the 10th thru 15th of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15)
+
+09/13/97:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+ - 09:00 -> 09:00
+ page 127: Every 18 months on the 10th thru 15th of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15)
+
+09/14/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 127: Every 18 months on the 10th thru 15th of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15)
+
+09/15/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ Page 127: Monthly on the 2nd and 15th of month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15)
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+ - 09:00 -> 09:00
+ page 127: Every 18 months on the 10th thru 15th of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15)
+
+09/16/97:
+ - 09:00 -> 09:00
+ page 125(1): Weekly on Tuesday and Thursday for five weeks (FREQ=WEEKLY;UNTIL=19971002T000000Z;BYDAY=TU,TH)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/17/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+09/18/97:
+ - 09:00 -> 09:00
+ page 125(1): Weekly on Tuesday and Thursday for five weeks (FREQ=WEEKLY;UNTIL=19971002T000000Z;BYDAY=TU,TH)
+
+09/19/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+09/21/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/22/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 126: Monthly on the second-to-last Monday of the month for 6 months (RRULE:FREQ=MONTHLY;COUNT=6;BYDAY=-2MO)
+
+09/23/97:
+ - 09:00 -> 09:00
+ page 125(1): Weekly on Tuesday and Thursday for five weeks (FREQ=WEEKLY;UNTIL=19971002T000000Z;BYDAY=TU,TH)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/25/97:
+ - 09:00 -> 09:00
+ page 125(1): Weekly on Tuesday and Thursday for five weeks (FREQ=WEEKLY;UNTIL=19971002T000000Z;BYDAY=TU,TH)
+
+09/28/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 126: Every other month on the first and last Sunday of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU)
+
+09/29/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+09/30/97:
+ - 09:00 -> 09:00
+ page 125(1): Weekly on Tuesday and Thursday for five weeks (FREQ=WEEKLY;UNTIL=19971002T000000Z;BYDAY=TU,TH)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+ - 09:00 -> 09:00
+ page 127: Monthly on the first and last day of the month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1)
+
+10/01/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+ - 09:00 -> 09:00
+ page 127: Monthly on the first and last day of the month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1)
+
+10/02/97:
+ - 09:00 -> 09:00
+ Page 127: Monthly on the 2nd and 15th of month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15)
+ - 09:00 -> 09:00
+ page 125(1): Weekly on Tuesday and Thursday for five weeks (FREQ=WEEKLY;UNTIL=19971002T000000Z;BYDAY=TU,TH)
+
+10/03/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+ - 09:00 -> 09:00
+ page 126: Monthly on the first Friday for 10 occurrences (FREQ=MONTHLY;COUNT=10;BYDAY=1FR)
+
+10/05/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/06/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/11/97:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+10/12/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/13/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+10/15/97:
+ - 09:00 -> 09:00
+ Page 127: Monthly on the 2nd and 15th of month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15)
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+10/17/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+10/19/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/20/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 126: Monthly on the second-to-last Monday of the month for 6 months (RRULE:FREQ=MONTHLY;COUNT=6;BYDAY=-2MO)
+
+10/26/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/27/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+10/29/97:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+10/31/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+ - 09:00 -> 09:00
+ page 127: Monthly on the first and last day of the month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1)
+
+11/01/97:
+ - 09:00 -> 09:00
+ page 127: Monthly on the first and last day of the month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1)
+
+11/02/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ Page 127: Monthly on the 2nd and 15th of month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15)
+ - 09:00 -> 09:00
+ page 126: Every other month on the first and last Sunday of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU)
+
+11/03/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/04/97:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/07/97:
+ - 09:00 -> 09:00
+ page 126: Monthly on the first Friday for 10 occurrences (FREQ=MONTHLY;COUNT=10;BYDAY=1FR)
+
+11/08/97:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+11/09/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/10/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+11/11/97:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/12/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+11/14/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+11/15/97:
+ - 09:00 -> 09:00
+ Page 127: Monthly on the 2nd and 15th of month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15)
+
+11/16/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/17/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 126: Monthly on the second-to-last Monday of the month for 6 months (RRULE:FREQ=MONTHLY;COUNT=6;BYDAY=-2MO)
+
+11/18/97:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/23/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/24/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+11/25/97:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/26/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+11/28/97:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+11/30/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 126: Every other month on the first and last Sunday of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU)
+ - 09:00 -> 09:00
+ page 127: Monthly on the first and last day of the month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1)
+
+12/01/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 127: Monthly on the first and last day of the month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1)
+
+12/02/97:
+ - 09:00 -> 09:00
+ Page 127: Monthly on the 2nd and 15th of month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15)
+
+12/05/97:
+ - 09:00 -> 09:00
+ page 126: Monthly on the first Friday for 10 occurrences (FREQ=MONTHLY;COUNT=10;BYDAY=1FR)
+
+12/07/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/08/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+12/10/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+12/12/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+12/13/97:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+12/14/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/15/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ Page 127: Monthly on the 2nd and 15th of month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15)
+
+12/21/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/22/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+ - 09:00 -> 09:00
+ page 126: Monthly on the second-to-last Monday of the month for 6 months (RRULE:FREQ=MONTHLY;COUNT=6;BYDAY=-2MO)
+
+12/24/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+12/25/97:
+ * Last Thursday of the year every third year, forever (FREQ=YEARLY;INTERVAL=3;BYDAY=-1TH)
+
+12/28/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/29/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+12/31/97:
+ - 09:00 -> 09:00
+ page 127: Monthly on the first and last day of the month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1)
+
+01/01/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Monthly on the first and last day of the month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1)
+
+01/02/98:
+ - 09:00 -> 09:00
+ Page 127: Monthly on the 2nd and 15th of month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 126: Monthly on the first Friday for 10 occurrences (FREQ=MONTHLY;COUNT=10;BYDAY=1FR)
+
+01/03/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/04/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 126: Every other month on the first and last Sunday of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU)
+
+01/05/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/06/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/07/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/08/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/09/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/10/98:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/11/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/12/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/13/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/14/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/15/98:
+ - 09:00 -> 09:00
+ Page 127: Monthly on the 2nd and 15th of month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/16/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/17/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/18/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/19/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 126: Monthly on the second-to-last Monday of the month for 6 months (RRULE:FREQ=MONTHLY;COUNT=6;BYDAY=-2MO)
+
+01/20/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/21/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/22/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/23/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/24/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/25/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 126: Every other month on the first and last Sunday of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU)
+
+01/26/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/27/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/28/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/29/98:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/30/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/31/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Monthly on the first and last day of the month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1)
+
+02/01/98:
+ * Every year on February 1 and 29 for eight years (RRULE:FREQ=YEARLY;UNTIL=20050131T000000Z;BYMONTH=2;BYMONTHDAY=1,29)
+ - 09:00 -> 09:00
+ page 127: Monthly on the first and last day of the month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1)
+
+02/06/98:
+ - 09:00 -> 09:00
+ page 126: Monthly on the first Friday for 10 occurrences (FREQ=MONTHLY;COUNT=10;BYDAY=1FR)
+
+02/07/98:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+02/13/98:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+02/16/98:
+ - 09:00 -> 09:00
+ page 126: Monthly on the second-to-last Monday of the month for 6 months (RRULE:FREQ=MONTHLY;COUNT=6;BYDAY=-2MO)
+
+02/26/98:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+03/01/98:
+ - 09:00 -> 09:00
+ page 126: Every other month on the first and last Sunday of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU)
+
+03/03/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/05/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/06/98:
+ - 09:00 -> 09:00
+ page 126: Monthly on the first Friday for 10 occurrences (FREQ=MONTHLY;COUNT=10;BYDAY=1FR)
+
+03/07/98:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+03/10/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/12/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/13/98:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+03/17/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/19/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/24/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/26/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/29/98:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ Last Sunday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU)
+ - 09:00 -> 09:00
+ page 126: Every other month on the first and last Sunday of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU)
+
+03/31/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+04/03/98:
+ - 09:00 -> 09:00
+ page 126: Monthly on the first Friday for 10 occurrences (FREQ=MONTHLY;COUNT=10;BYDAY=1FR)
+
+04/11/98:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+04/28/98:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/01/98:
+ - 09:00 -> 09:00
+ page 126: Monthly on the first Friday for 10 occurrences (FREQ=MONTHLY;COUNT=10;BYDAY=1FR)
+
+05/03/98:
+ - 09:00 -> 09:00
+ page 126: Every other month on the first and last Sunday of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU)
+
+05/05/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/09/98:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+05/12/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/18/98:
+ * page 128: Every 20th Monday of the year, forever (RRULE:FREQ=YEARLY;BYDAY=20MO)
+
+05/19/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/26/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/29/98:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/31/98:
+ - 09:00 -> 09:00
+ page 126: Every other month on the first and last Sunday of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU)
+
+06/04/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/05/98:
+ - 09:00 -> 09:00
+ page 126: Monthly on the first Friday for 10 occurrences (FREQ=MONTHLY;COUNT=10;BYDAY=1FR)
+
+06/10/98:
+ - 09:00 -> 09:00
+ page 128: Yearly in June and July for 10 occurrences (RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7)
+
+06/11/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/13/98:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+06/18/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/25/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/28/98:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+07/02/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/07/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/09/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/10/98:
+ - 09:00 -> 09:00
+ page 128: Yearly in June and July for 10 occurrences (RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7)
+
+07/11/98:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+07/14/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/16/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/21/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/23/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/28/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/29/98:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+07/30/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/06/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/08/98:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+08/13/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/20/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/27/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/29/98:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+09/01/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/08/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/12/98:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+09/15/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/22/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/28/98:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+09/29/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+10/10/98:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+10/29/98:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+11/03/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/07/98:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+11/10/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/13/98:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+11/17/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/24/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/28/98:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+12/12/98:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+12/29/98:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+01/01/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/02/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/03/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/04/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/05/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/06/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/07/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/08/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/09/99:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/10/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 128: Every other year in January, February and March for 10 occurrences (RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3)
+
+01/11/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/12/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/13/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/14/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/15/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/16/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/17/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/18/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/19/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/20/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/21/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/22/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/23/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/24/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/25/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/26/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/27/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/28/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/29/99:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/30/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/31/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+02/01/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * Every year on February 1 and 29 for eight years (RRULE:FREQ=YEARLY;UNTIL=20050131T000000Z;BYMONTH=2;BYMONTHDAY=1,29)
+
+02/07/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/08/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/10/99:
+ - 09:00 -> 09:00
+ page 128: Every other year in January, February and March for 10 occurrences (RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3)
+
+02/13/99:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+02/14/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/15/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/21/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/22/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/26/99:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+02/28/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/01/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/02/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/04/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/07/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/08/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/09/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/10/99:
+ - 09:00 -> 09:00
+ page 127: Every 18 months on the 10th thru 15th of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15)
+ - 09:00 -> 09:00
+ page 128: Every other year in January, February and March for 10 occurrences (RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3)
+
+03/11/99:
+ - 09:00 -> 09:00
+ page 127: Every 18 months on the 10th thru 15th of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15)
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/12/99:
+ - 09:00 -> 09:00
+ page 127: Every 18 months on the 10th thru 15th of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15)
+
+03/13/99:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+ - 09:00 -> 09:00
+ page 127: Every 18 months on the 10th thru 15th of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15)
+
+03/14/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/15/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/16/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/18/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/21/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/22/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/23/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/25/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/28/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ Last Sunday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU)
+
+03/29/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+03/30/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+04/04/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/05/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/10/99:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+04/11/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/12/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/18/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/19/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/25/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/26/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/28/99:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/02/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/03/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/04/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/08/99:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+05/09/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/10/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/11/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/16/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/17/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 128: Every 20th Monday of the year, forever (RRULE:FREQ=YEARLY;BYDAY=20MO)
+
+05/18/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/23/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/24/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/25/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/29/99:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/30/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/31/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/03/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/06/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/07/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/10/99:
+ - 09:00 -> 09:00
+ page 128: Yearly in June and July for 10 occurrences (RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7)
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/12/99:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+06/13/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/14/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/17/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/20/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/21/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/24/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/27/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/28/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+07/01/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/04/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/05/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/06/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/08/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/10/99:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+ - 09:00 -> 09:00
+ page 128: Yearly in June and July for 10 occurrences (RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7)
+
+07/11/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/12/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/13/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/15/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/18/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/19/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/20/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/22/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/25/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/26/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/27/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/29/99:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/01/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/02/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/05/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/07/99:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+08/08/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/09/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/12/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/13/99:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+08/15/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/16/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/19/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/22/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/23/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/26/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/29/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+08/30/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/05/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/06/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/07/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/11/99:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+09/12/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/13/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/14/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/19/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/20/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/21/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/26/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/27/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/28/99:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+10/03/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/04/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/09/99:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+10/10/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/11/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/17/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/18/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/24/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/25/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/29/99:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+10/31/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/01/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/02/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/07/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/08/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/09/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/13/99:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+11/14/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/15/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/16/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/21/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/22/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/23/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/28/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+11/29/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/30/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+12/05/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/06/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/11/99:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+12/12/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/13/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/19/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/20/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/26/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/27/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/29/99:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+01/01/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/02/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/03/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/04/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/05/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/06/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/07/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/08/00:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/09/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/10/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/11/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/12/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/13/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/14/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/15/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/16/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/17/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/18/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/19/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/20/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/21/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/22/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/23/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/24/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/25/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/26/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/27/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/28/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/29/00:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/30/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/31/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+02/01/00:
+ * Every year on February 1 and 29 for eight years (RRULE:FREQ=YEARLY;UNTIL=20050131T000000Z;BYMONTH=2;BYMONTHDAY=1,29)
+
+02/12/00:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+02/27/00:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+02/29/00:
+ * Every year on February 1 and 29 for eight years (RRULE:FREQ=YEARLY;UNTIL=20050131T000000Z;BYMONTH=2;BYMONTHDAY=1,29)
+
+03/02/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/07/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/09/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/11/00:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+03/14/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/16/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/21/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/23/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/26/00:
+ - 09:00 -> 09:00
+ Last Sunday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU)
+
+03/28/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/29/00:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+03/30/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+04/08/00:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+04/28/00:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/02/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/09/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/13/00:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+05/15/00:
+ * page 128: Every 20th Monday of the year, forever (RRULE:FREQ=YEARLY;BYDAY=20MO)
+
+05/16/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/23/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/29/00:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/30/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+06/01/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/08/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/10/00:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+ - 09:00 -> 09:00
+ page 128: Yearly in June and July for 10 occurrences (RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7)
+
+06/15/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/22/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/28/00:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+06/29/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/04/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/06/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/08/00:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+07/10/00:
+ - 09:00 -> 09:00
+ page 128: Yearly in June and July for 10 occurrences (RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7)
+
+07/11/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/13/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/18/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/20/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/25/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/27/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/29/00:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+08/03/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/10/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/12/00:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+08/17/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/24/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/29/00:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+08/31/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+09/05/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/09/00:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+09/12/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/19/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/26/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/28/00:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+10/07/00:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+10/13/00:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+10/29/00:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+11/07/00:
+ * page 130: Every 4 years, the first Tuesday after a Monday in November, forever (U.S. Presidential Election day) (RRULE:FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/11/00:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+11/14/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/21/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/28/00:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+12/09/00:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+12/28/00:
+ * Last Thursday of the year every third year, forever (FREQ=YEARLY;INTERVAL=3;BYDAY=-1TH)
+
+12/29/00:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+01/01/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/02/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/07/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/08/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/09/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/10/01:
+ - 09:00 -> 09:00
+ page 128: Every other year in January, February and March for 10 occurrences (RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3)
+
+01/13/01:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+01/14/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/15/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/16/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/21/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/22/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/23/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/28/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/29/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+01/30/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+02/01/01:
+ * Every year on February 1 and 29 for eight years (RRULE:FREQ=YEARLY;UNTIL=20050131T000000Z;BYMONTH=2;BYMONTHDAY=1,29)
+
+02/04/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/05/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/10/01:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+ - 09:00 -> 09:00
+ page 128: Every other year in January, February and March for 10 occurrences (RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3)
+
+02/11/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/12/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/18/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/19/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/25/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/26/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+03/01/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/04/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/05/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/06/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/08/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/10/01:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+ - 09:00 -> 09:00
+ page 128: Every other year in January, February and March for 10 occurrences (RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3)
+
+03/11/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/12/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/13/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/15/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/18/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/19/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/20/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/22/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/25/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ Last Sunday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU)
+
+03/26/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/27/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/29/01:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+04/01/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/02/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/07/01:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+04/08/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/09/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/13/01:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+04/15/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/16/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/22/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/23/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/28/01:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+04/29/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/30/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/01/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/06/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/07/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/08/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/12/01:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+05/13/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/14/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 128: Every 20th Monday of the year, forever (RRULE:FREQ=YEARLY;BYDAY=20MO)
+
+05/15/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/20/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/21/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/22/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/27/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/28/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/29/01:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+06/03/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/04/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/07/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/09/01:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+06/10/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 128: Yearly in June and July for 10 occurrences (RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7)
+
+06/11/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/14/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/17/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/18/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/21/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/24/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/25/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/28/01:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/01/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/02/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/03/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/05/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/07/01:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+07/08/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/09/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/10/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+ - 09:00 -> 09:00
+ page 128: Yearly in June and July for 10 occurrences (RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7)
+
+07/12/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/13/01:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+07/15/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/16/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/17/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/19/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/22/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/23/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/24/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/26/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/29/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+07/30/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/31/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+08/02/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/05/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/06/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/09/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/11/01:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+08/12/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/13/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/16/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/19/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/20/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/23/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/26/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/27/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/29/01:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+08/30/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+09/02/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/03/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/04/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/08/01:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+09/09/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/10/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/11/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/16/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/17/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/18/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/23/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/24/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/25/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/28/01:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+09/30/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/01/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/07/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/08/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/13/01:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+10/14/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/15/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/21/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/22/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/28/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/29/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+11/04/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/05/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/06/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/10/01:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+11/11/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/12/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/13/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/18/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/19/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/20/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/25/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/26/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/27/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/28/01:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+12/02/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/03/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/08/01:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+12/09/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/10/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/16/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/17/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/23/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/24/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/29/01:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+12/30/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/31/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/01/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/08/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/12/02:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+01/15/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/22/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/29/02:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+02/01/02:
+ * Every year on February 1 and 29 for eight years (RRULE:FREQ=YEARLY;UNTIL=20050131T000000Z;BYMONTH=2;BYMONTHDAY=1,29)
+
+02/09/02:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+02/26/02:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+03/05/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/07/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/09/02:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+03/12/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/14/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/19/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/21/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/26/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/28/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/29/02:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+03/31/02:
+ - 09:00 -> 09:00
+ Last Sunday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU)
+
+04/13/02:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+04/28/02:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/07/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/11/02:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+05/14/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/20/02:
+ * page 128: Every 20th Monday of the year, forever (RRULE:FREQ=YEARLY;BYDAY=20MO)
+
+05/21/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/28/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/29/02:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+06/06/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/08/02:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+06/13/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/20/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/27/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/28/02:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+07/02/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/04/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/09/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/11/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/13/02:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+07/16/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/18/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/23/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/25/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/29/02:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+07/30/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+08/01/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/08/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/10/02:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+08/15/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/22/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/29/02:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+09/03/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/07/02:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+09/10/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/13/02:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+09/17/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/24/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/28/02:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+10/12/02:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+10/29/02:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+11/05/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/09/02:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+11/12/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/19/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/26/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/28/02:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+12/07/02:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+12/13/02:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+12/29/02:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+01/05/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/06/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/07/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/10/03:
+ - 09:00 -> 09:00
+ page 128: Every other year in January, February and March for 10 occurrences (RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3)
+
+01/11/03:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+01/12/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/13/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/14/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/19/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/20/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/21/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/26/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/27/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/28/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/29/03:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+02/01/03:
+ * Every year on February 1 and 29 for eight years (RRULE:FREQ=YEARLY;UNTIL=20050131T000000Z;BYMONTH=2;BYMONTHDAY=1,29)
+
+02/02/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/03/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/08/03:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+02/09/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/10/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 128: Every other year in January, February and March for 10 occurrences (RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3)
+
+02/16/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/17/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/23/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/24/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/26/03:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+03/02/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/03/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/04/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/06/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/08/03:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+03/09/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/10/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 128: Every other year in January, February and March for 10 occurrences (RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3)
+
+03/11/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/13/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/16/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/17/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/18/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/20/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/23/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/24/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/25/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/27/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/29/03:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+03/30/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ Last Sunday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU)
+
+03/31/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/06/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/07/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/12/03:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+04/13/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/14/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/20/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/21/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/27/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/28/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/04/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/05/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/06/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/10/03:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+05/11/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/12/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/13/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/18/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/19/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 128: Every 20th Monday of the year, forever (RRULE:FREQ=YEARLY;BYDAY=20MO)
+
+05/20/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/25/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/26/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/27/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/29/03:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+06/01/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/02/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/05/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/07/03:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+06/08/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/09/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/12/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/13/03:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+06/15/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/16/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/19/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/22/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/23/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/26/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/28/03:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+06/29/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/30/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/01/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/03/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/06/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/07/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/08/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/10/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/12/03:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+07/13/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/14/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/15/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/17/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/20/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/21/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/22/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/24/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/27/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/28/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/29/03:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/31/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/03/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/04/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/07/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/09/03:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+08/10/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/11/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/14/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/17/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/18/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/21/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/24/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/25/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/28/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/29/03:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+08/31/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/01/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/02/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/07/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/08/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/09/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/13/03:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+09/14/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/15/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/16/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/21/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/22/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/23/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/28/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+09/29/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/30/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+10/05/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/06/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/11/03:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+10/12/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/13/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/19/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/20/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/26/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/27/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/29/03:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+11/02/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/03/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/04/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/08/03:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+11/09/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/10/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/11/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/16/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/17/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/18/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/23/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/24/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/25/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/28/03:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+11/30/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/01/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/07/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/08/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/13/03:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+12/14/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/15/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/21/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/22/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/25/03:
+ * Last Thursday of the year every third year, forever (FREQ=YEARLY;INTERVAL=3;BYDAY=-1TH)
+
+12/28/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/29/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+01/06/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/10/04:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+01/13/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/20/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/27/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/29/04:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+02/01/04:
+ * Every year on February 1 and 29 for eight years (RRULE:FREQ=YEARLY;UNTIL=20050131T000000Z;BYMONTH=2;BYMONTHDAY=1,29)
+
+02/07/04:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+02/13/04:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+02/27/04:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+02/29/04:
+ * Every year on February 1 and 29 for eight years (RRULE:FREQ=YEARLY;UNTIL=20050131T000000Z;BYMONTH=2;BYMONTHDAY=1,29)
+
+03/02/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/04/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/09/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/11/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/13/04:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+03/16/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/18/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/23/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/25/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/28/04:
+ - 09:00 -> 09:00
+ Last Sunday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU)
+
+03/29/04:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+03/30/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+04/10/04:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+04/28/04:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/04/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/08/04:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+05/11/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/17/04:
+ * page 128: Every 20th Monday of the year, forever (RRULE:FREQ=YEARLY;BYDAY=20MO)
+
+05/18/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/25/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/29/04:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+06/03/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/10/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/12/04:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+06/17/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/24/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/28/04:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+07/01/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/06/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/08/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/10/04:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+07/13/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/15/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/20/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/22/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/27/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/29/04:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/05/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/07/04:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+08/12/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/13/04:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+08/19/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/26/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/29/04:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+09/07/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/11/04:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+09/14/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/21/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/28/04:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+10/09/04:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+10/29/04:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+11/02/04:
+ * page 130: Every 4 years, the first Tuesday after a Monday in November, forever (U.S. Presidential Election day) (RRULE:FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/09/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/13/04:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+11/16/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/23/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/28/04:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+11/30/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+12/11/04:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+12/29/04:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+01/02/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/03/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/04/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/08/05:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+01/09/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/10/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/11/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/16/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/17/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/18/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/23/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/24/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/25/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/29/05:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+01/30/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/31/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/06/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/07/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/12/05:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+02/13/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/14/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/20/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/21/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/26/05:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+02/27/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/28/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/01/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/03/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/06/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/07/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/08/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/10/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/12/05:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+03/13/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/14/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/15/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/17/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/20/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/21/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/22/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/24/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/27/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ Last Sunday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU)
+
+03/28/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/29/05:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/31/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+04/03/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/04/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/09/05:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+04/10/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/11/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/17/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/18/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/24/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/25/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/28/05:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/01/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/02/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/03/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/07/05:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+05/08/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/09/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/10/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/13/05:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+05/15/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/16/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 128: Every 20th Monday of the year, forever (RRULE:FREQ=YEARLY;BYDAY=20MO)
+
+05/17/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/22/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/23/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/24/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/29/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/30/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/31/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+06/02/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/05/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/06/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/09/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/11/05:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+06/12/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/13/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/16/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/19/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/20/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/23/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/26/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/27/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/28/05:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+06/30/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/03/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/04/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/05/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/07/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/09/05:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+07/10/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/11/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/12/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/14/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/17/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/18/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/19/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/21/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/24/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/25/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/26/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/28/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/29/05:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+07/31/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/01/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/04/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/07/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/08/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/11/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/13/05:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+08/14/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/15/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/18/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/21/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/22/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/25/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/28/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/29/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+09/04/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/05/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/06/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/10/05:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+09/11/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/12/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/13/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/18/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/19/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/20/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/25/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/26/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/27/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/28/05:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+10/02/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/03/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/08/05:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+10/09/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/10/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/16/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/17/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/23/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/24/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/29/05:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+10/30/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/31/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/01/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/06/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/07/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/08/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/12/05:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+11/13/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/14/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/15/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/20/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/21/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/22/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/27/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/28/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+11/29/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+12/04/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/05/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/10/05:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+12/11/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/12/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/18/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/19/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/25/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/26/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/29/05:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+01/03/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/07/06:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+01/10/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/13/06:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+01/17/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/24/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/29/06:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+01/31/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+02/11/06:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+02/26/06:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+03/02/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/07/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/09/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/11/06:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+03/14/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/16/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/21/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/23/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/26/06:
+ - 09:00 -> 09:00
+ Last Sunday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU)
+
+03/28/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/29/06:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+03/30/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+04/08/06:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+04/28/06:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/02/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/09/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/13/06:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+05/15/06:
+ * page 128: Every 20th Monday of the year, forever (RRULE:FREQ=YEARLY;BYDAY=20MO)
+
+05/16/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/23/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/29/06:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/30/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+06/01/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/08/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/10/06:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+06/15/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/22/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/28/06:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+06/29/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/04/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/06/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/08/06:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+07/11/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/13/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/18/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/20/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/25/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/27/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/29/06:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+08/03/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/10/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/12/06:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+08/17/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/24/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/29/06:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+08/31/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+09/05/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/09/06:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+09/12/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/19/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/26/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/28/06:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+10/07/06:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+10/13/06:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+10/29/06:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+11/07/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/11/06:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+11/14/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/21/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/28/06:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+12/09/06:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+12/28/06:
+ * Last Thursday of the year every third year, forever (FREQ=YEARLY;INTERVAL=3;BYDAY=-1TH)
+
+12/29/06:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+01/01/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/02/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/07/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/08/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/09/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/13/07:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+01/14/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/15/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 132: An example where an invalid date (i.e. February 30) is ignored (RRULE:FREQ=MONTHLY;BYMONTHDAY=15,30;COUNT=5)
+
+01/16/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/21/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/22/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/23/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/28/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/29/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+01/30/07:
+ * page 132: An example where an invalid date (i.e. February 30) is ignored (RRULE:FREQ=MONTHLY;BYMONTHDAY=15,30;COUNT=5)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+02/04/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/05/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/10/07:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+02/11/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/12/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/15/07:
+ * page 132: An example where an invalid date (i.e. February 30) is ignored (RRULE:FREQ=MONTHLY;BYMONTHDAY=15,30;COUNT=5)
+
+02/18/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/19/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/25/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/26/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+03/01/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/04/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/05/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/06/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/08/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/10/07:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+03/11/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/12/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/13/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/15/07:
+ * page 132: An example where an invalid date (i.e. February 30) is ignored (RRULE:FREQ=MONTHLY;BYMONTHDAY=15,30;COUNT=5)
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/18/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/19/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/20/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/22/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/25/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ Last Sunday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU)
+
+03/26/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/27/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/29/07:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/30/07:
+ * page 132: An example where an invalid date (i.e. February 30) is ignored (RRULE:FREQ=MONTHLY;BYMONTHDAY=15,30;COUNT=5)
+
+04/01/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/02/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/07/07:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+04/08/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/09/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/13/07:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+04/15/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/16/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/22/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/23/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/28/07:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+04/29/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/30/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/01/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/06/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/07/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/08/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/12/07:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+05/13/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/14/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 128: Every 20th Monday of the year, forever (RRULE:FREQ=YEARLY;BYDAY=20MO)
+
+05/15/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/20/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/21/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/22/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/27/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/28/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/29/07:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+06/03/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/04/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/07/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/09/07:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+06/10/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/11/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/14/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/17/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/18/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/21/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/24/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/25/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/28/07:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/01/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/02/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/03/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/05/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/07/07:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+07/08/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/09/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/10/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/12/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/13/07:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+07/15/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/16/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/17/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/19/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/22/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/23/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/24/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/26/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/29/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+07/30/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/31/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+08/02/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/05/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/06/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/09/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/11/07:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+08/12/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/13/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/16/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/19/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/20/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/23/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/26/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/27/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/29/07:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+08/30/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+09/02/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/03/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/04/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/08/07:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+09/09/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/10/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/11/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/16/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/17/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/18/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/23/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/24/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/25/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/28/07:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+09/30/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/01/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/07/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/08/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/13/07:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+10/14/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/15/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/21/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/22/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/28/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/29/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+11/04/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/05/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/06/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/10/07:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+11/11/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/12/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/13/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/18/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/19/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/20/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/25/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/26/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/27/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/28/07:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+12/02/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/03/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/08/07:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+12/09/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/10/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/16/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/17/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/23/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/24/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/29/07:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+12/30/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/31/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+Floating point exception?
+08/01/20:
+ - 08:41 -> 10:11
+ negative ordered weekday may not exist
+No Floating point exception on November 1, 2020
+EOD
+else
+ ./run-test "$0"
+fi
diff --git a/test/recur-010.sh b/test/recur-010.sh
new file mode 100755
index 0000000..84cc581
--- /dev/null
+++ b/test/recur-010.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+# Calcurse support of recurrence rules does not include the rule part WKST (weekstart),
+# but calcurse configuration does allow a choice between Monday and Sunday.
+
+. "${TEST_INIT:-./test-init.sh}"
+
+if [ "$1" = 'actual' ]; then
+ tmpdir=$(mktemp -d)
+ grep 'page 131' "$DATA_DIR"/rfc5545 >"$tmpdir"/apts
+ cp "$DATA_DIR"/conf "$DATA_DIR"/todo "$tmpdir"
+ "$CALCURSE" --read-only -D "$tmpdir" -Q --filter-type cal \
+ --startday=08/01/1997 --range=31
+ rm -rf "$tmpdir"
+
+ tmpdir=$(mktemp -d)
+ grep 'page 131' "$DATA_DIR"/rfc5545 >"$tmpdir"/apts
+ cp "$DATA_DIR"/todo "$tmpdir"
+ sed 's/general.firstdayofweek=monday/general.firstdayofweek=sunday/' \
+ "$DATA_DIR"/conf >"$tmpdir"/conf
+ "$CALCURSE" --read-only -D "$tmpdir" -Q --filter-type cal \
+ --startday=08/01/1997 --range=31
+ rm -rf "$tmpdir"
+elif [ "$1" = 'expected' ]; then
+ cat <<EOD
+08/05/97:
+ - 09:00 -> 09:00
+ page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+
+08/10/97:
+ - 09:00 -> 09:00
+ page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+
+08/19/97:
+ - 09:00 -> 09:00
+ page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+
+08/24/97:
+ - 09:00 -> 09:00
+ page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+08/05/97:
+ - 09:00 -> 09:00
+ page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+
+08/17/97:
+ - 09:00 -> 09:00
+ page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+
+08/19/97:
+ - 09:00 -> 09:00
+ page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+
+08/31/97:
+ - 09:00 -> 09:00
+ page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+EOD
+else
+ ./run-test "$0"
+fi
diff --git a/test/run-test.c b/test/run-test.c
index 69cde23..41d55ad 100644
--- a/test/run-test.c
+++ b/test/run-test.c
@@ -1,7 +1,7 @@
/*
* Calcurse - text-based organizer
*
- * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org>
+ * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/test/test-init.sh b/test/test-init.sh
index c95c884..92ad779 100644
--- a/test/test-init.sh
+++ b/test/test-init.sh
@@ -2,3 +2,8 @@
CALCURSE=${CALCURSE:-../src/calcurse}
DATA_DIR=${DATA_DIR:-data/}
+
+case "$CALCURSE" in
+ /*) ;;
+ *) CALCURSE="${PWD}/${CALCURSE}" ;;
+esac