summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/AddingOrModifyingComponents.txt23
-rw-r--r--doc/CMakeLists.txt3
-rw-r--r--doc/Makefile.am1
-rw-r--r--doc/Makefile.in419
-rw-r--r--doc/UsingLibical.txt1378
5 files changed, 1824 insertions, 0 deletions
diff --git a/doc/AddingOrModifyingComponents.txt b/doc/AddingOrModifyingComponents.txt
new file mode 100644
index 00000000..e9f46c27
--- /dev/null
+++ b/doc/AddingOrModifyingComponents.txt
@@ -0,0 +1,23 @@
+
+How to add or change Components, Properties, Values or Parameters
+
+
+Adding or modifying values
+---------------------------
+
+You may have to modify these files or data structures
+
+file design-data/value-c-types.txt
+file design-data/prop-to-val.txt
+table parameter_map[] in icalenums.c
+enum icalvalue_kind in icalenum.h
+table value_map[] in icalenums.c
+enum icalparameter_value in icalenum.h
+table propval_map[] in icalenums.c
+function icalvalue_as_ical_string() in icalvalue.c
+function icalvalue_new_from_string_with_error() in icalvalue.c
+
+When you are done, if you changed any files in the design-data
+directory, regnerate derived datatypes in src/libical with "make
+derived" or "make icalvalue"
+
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
new file mode 100644
index 00000000..0b7b3433
--- /dev/null
+++ b/doc/CMakeLists.txt
@@ -0,0 +1,3 @@
+
+########### install files ###############
+
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 00000000..a2914c37
--- /dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1 @@
+EXTRA_DIST = UsingLibical.txt
diff --git a/doc/Makefile.in b/doc/Makefile.in
new file mode 100644
index 00000000..6a54cfb4
--- /dev/null
+++ b/doc/Makefile.in
@@ -0,0 +1,419 @@
+# Makefile.in generated by automake 1.12.2 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2012 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = doc
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(top_srcdir)/mkinstalldirs
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BDB_DIR = @BDB_DIR@
+BDB_DIR_INCLUDE = @BDB_DIR_INCLUDE@
+BDB_DIR_LIB = @BDB_DIR_LIB@
+BDB_LIB = @BDB_LIB@
+BDB_VERSION = @BDB_VERSION@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JAR = @JAR@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+JAVAH = @JAVAH@
+JAVA_PLATFORM = @JAVA_PLATFORM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+PY_CFLAGS = @PY_CFLAGS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+ZONE_INFO = @ZONE_INFO@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+swig_val = @swig_val@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = UsingLibical.txt
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu doc/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+cscope cscopelist:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ distclean distclean-generic distclean-libtool distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/doc/UsingLibical.txt b/doc/UsingLibical.txt
new file mode 100644
index 00000000..fb4b07ec
--- /dev/null
+++ b/doc/UsingLibical.txt
@@ -0,0 +1,1378 @@
+
+
+Using Libical
+
+Eric Busboom (eric@softwarestudio.org)
+
+January 2001
+
+
+
+1 Introduction
+
+Libical is an Open Source implementation of the iCalendar protocols
+and protocol data units. The iCalendar specification describes how
+calendar clients can communicate with calendar servers so users can
+store their calendar data and arrange meetings with other users.
+
+Libical implements RFC2445, RFC2446 and some of RFC2447.
+
+This documentation assumes that you are familiar with the iCalendar
+standards RFC2445 and RFC2446. these specifications are online on
+the CALSCH webpage at:
+
+http://www.imc.org/ietf-calendar/
+
+1.1 The libical project
+
+This code is under active development. If you would like to contribute
+to the project, visit http://freeassociation.sourceforge.net
+
+1.2 License
+
+The code and datafiles in this distribution are licensed under the
+Mozilla Public License. See http://www.mozilla.org/NPL/MPL-1.0.html
+for a copy of the license. Alternately, you may use libical under
+the terms of the GNU Library General Public License. See
+http://www.fsf.org/copyleft/lesser.html for a copy of the LGPL.
+
+This dual license ensures that the library can be incorporated into
+both proprietary code and GPL'd programs, and will benefit from improvements
+made by programmers in both realms. I will only accept changes into
+my version of the library if they are similarly dual-licensed.
+
+1.3 Example Code
+
+A lot of the documentation for this library is in the form of example
+code. These examples are in the "examples" directory of the distribution.
+Also look in "src/test" for additional annotated examples.
+
+2 Building the Library
+
+Libical uses autoconf to generate makefiles. It should built with no
+adjustments on Linux, FreeBSD and Solaris under gcc. Some version
+have been successfully been build on MacOS, Solaris, UnixWare, And
+Tru64 UNIX without gcc, but you may run into problems with a particular
+later version.
+
+For a more complete guide to building the library, see the README file
+in the distribution.
+
+3 Structure
+
+The iCalendar data model is based on four types of objects: components,
+properties, values and parameters.
+
+Properties are the fundamental unit of information in iCalendar, and they
+work a bit like a hash entry, with a constant key and a variable value.
+Properties may also have modifiers, called parameters. In the iCal
+content line
+
+ORGANIZER;ROLE=CHAIR:MAILTO:mrbig@host.com
+
+The property name is "ORGANIZER," the value of the property is "mrbig@host.com"
+and the "ROLE" parameter specifies that Mr Big is the chair of the
+meetings associated with this property.
+
+Components are groups of properties that represent the core objects
+of a calendar system, such as events or timezones. Components are
+delimited by "BEGIN" and "END" tags.
+
+When a component is sent across a network, if it is un-encrypted, it
+will look something like:
+
+BEGIN:VCALENDAR
+
+METHOD:REQUEST
+
+PRODID: -//hacksw/handcal//NONSGML v1.0//EN
+
+BEGIN:VEVENT
+
+DTSTAMP:19980309T231000Z
+
+UID:guid-1.host1.com
+
+ORGANIZER;ROLE=CHAIR:MAILTO:mrbig@host.com
+
+ATTENDEE;RSVP=TRUE;ROLE=REQ-PARTICIPANT;CUTYPE=GROUP:
+
+ MAILTO:employee-A@host.com
+
+DESCRIPTION:Project XYZ Review Meeting
+
+CATEGORIES:MEETING
+
+CLASS:PUBLIC
+
+CREATED:19980309T130000Z
+
+SUMMARY:XYZ Project Review
+
+DTSTART;TZID=US-Eastern:19980312T083000
+
+DTEND;TZID=US-Eastern:19980312T093000
+
+LOCATION:1CP Conference Room 4350
+
+END:VEVENT
+
+END:VCALENDAR
+
+Note that components can be nested; this example has both a VCALENDAR
+and a VEVENT component, one nested inside the other.
+
+3.1 Core iCal classes
+
+Libical is an object-based, data-oriented library. Nearly all of the
+routines in the library are associated with an opaque data types and
+perform some operation on that data type. Although the library does
+not actually have classes, we will use those terms since the behavior
+of these associations of data and routines is very similar to a class.
+
+3.1.1 Properties
+
+Properties are represented with the icalproperty class and its many
+"derived" classes with on "derived" class per property type in RFC2445.
+Again, there is no actual inheritance relations, but there are clusters
+of routines that make this term useful. A property is a container
+for a single value and a set of parameters.
+
+3.1.2 Components
+
+In libical, components are represented with the icalcomponent class.
+Icalcomponent is a container for a set of other components and properties.
+
+3.1.3 Values
+
+Values are represented in a similar way to properties; a base class
+and many "derived " classes. A value is essentially a abstract handle
+on a single fundamental type, a structure or a union.
+
+3.1.4 Parameters
+
+Parameters are represented in a similar way to properties, except that
+they contain only one value
+
+3.2 Other elements of libical
+
+In addition to the core iCal classes, libical has many other types,
+structures, classes that aid in creating and using iCal components.
+
+3.2.1 Enumerations and types
+
+Libical is strongly typed, so every component, property, parameter,
+and value type has an enumeration, and some have an associated structure
+or union.
+
+3.2.2 The parser
+
+The libical parser offers a variety of ways to convert RFC2445 text
+into a libical internal component structure. the parser can parse
+blocks of text as a string, or it can parse line-by-line.
+
+3.2.3 Error objects
+
+Libical has a substantial error reporting system for both programming
+errors and component usage errors.
+
+3.2.4 Memory Management
+
+Since many of libicals interfaces return strings, the library has its
+own memory management system to elimiate the need to free every string
+returned from the library.
+
+3.2.5 Storage classes
+
+The library also offers several classes to store components to flies,
+memory or databases.
+
+4 Differences From RFCs
+
+Libical has been designed to follow the standards as closely as possible,
+so that the key objects in the standards are also key objects in the
+library. However, there are a few areas where the specifications are
+(arguably) irregular, and following them exactly would result in an
+unfriendly interface. These deviations make libical easier to use
+by maintaining a self-similar interface.
+
+4.1 Pseudo Components
+
+Libical defines components for groups of properties that look and act
+like components, but are not defined as components in the specification.
+XDAYLIGHT and XSTANDARD are notable examples. These pseudo components
+group properties within the VTIMEZONE components. For instanace, the
+timezone properties associated with daylight savings time starts with
+"BEGIN:DAYLIGHT" and ends with "END:DAYLIGHT, just like other components,
+but is not defined as a component in RFC2445 (see RFC2445, page
+61). In Libical,this grouping is represented by the XDAYLIGHT component.
+Standard iCAL components all start with the letter "V," while pseudo
+components start with"X."
+
+There are also pseudo components that are conceptually derived classes
+of VALARM. RFC2446 defines what properties may be included in each
+component, and for VALARM, the set of properties it may have depends
+on the value of the ACTION property.
+
+For instance, if a VALARM component has an ACTION property with the
+value of "AUDIO," the component must also have an "ATTACH" property.
+However, if the ACTION value is "DISPLAY," the component must have
+a DESCRIPTION property.
+
+To handle these various, complex restrictions, libical has pseudo components
+for each type of alarm: XAUDIOALARM, XDISPLAYALARM, XEMAILALARM and
+XPROCEDUREALARM.
+
+4.2 Combined Values
+
+Many values can take more than one type. TRIGGER, for instance, can
+have a value type of with DURATION or of DATE-TIME. These multiple
+types make it difficult to create routines to return the value associated
+with a property.
+
+It is natural to have interfaces that would return the value of a property,
+but it is cumbersome for a single routine to return multiple types.
+So, in libical, properties that can have multiple types are given
+a single type that is the union of their RFC2445 types. For instance,
+in libical, the value of the TRIGGER property resolves to struct icaltriggertype.
+This type is a union of a DURATION and a DATE-TIME.
+
+4.3 Multi-Valued Properties
+
+Some properties, such as CATEGORIES have only one value type, but each
+CATEGORIES property can have multiple value instances. This also results
+in a cumbersome interface -- CATEGORIES accessors would have to return
+a list while all other accessors returned a single value. In libical,
+all properties have a single value, and multi-valued properties are
+broken down into multiple single valued properties during parsing.
+That is, an input line like,
+
+CATEGORIES: work, home
+
+becomes in libical's internal representation
+
+CATEGORIES: work
+
+CATEGORIES: home
+
+Oddly, RFC2445 allows some multi-valued properties (like FREEBUSY)
+to exist as both a multi-values property and as multiple single
+value properties, while others (like CATEGORIES) can only exist
+as single multi-valued properties. This makes the internal representation
+for CATEGORIES illegal. However when you convert a component to a
+string, the library will collect all of the CATEGORIES properties
+into one.
+
+5 Using libical
+
+5.1 Creating Components
+
+There are three ways to create components in Libical: creating individual
+objects and assembling them, building entire objects in massive vaargs
+calls, and parsing a text file containing iCalendar data.
+
+5.1.1 Constructor Interfaces
+
+Using constructor interfaces, you create each of the objects separately
+and then assemble them in to components:
+
+icalcomponent *event;
+
+icalproperty *prop;
+
+icalparameter *param;
+
+struct icaltimetype atime;
+
+event = icalcomponent_new(ICAL_VEVENT_COMPONENT);
+
+prop = icalproperty_new_dtstamp(atime) ;
+
+icalcomponent_add_property(event, prop);
+
+prop = icalproperty_new_uid(''guid-1.host1.com'');
+
+icalcomponent_add_property(event,prop);
+
+prop=icalproperty_new_organizer(''mrbig@host.com'');
+
+param = icalparameter_new_role(ICAL_ROLE_CHAIR)
+
+icalproperty_add_parameter(prop, param);
+
+icalcomponent_add_property(event,prop);
+
+Notice that libical uses a semi-object-oriented style of interface.
+Most things you work with are objects, that are instantiated with
+a constructor that has "new" in the name. Also note that, other than
+the object reference, most structure data is passed in to libical
+routines by value. Libical has some complex but very regular memory
+handling rules. These are detailed in section [sec:memory].
+
+If any of the constructors fail, they will return 0. If you try to
+insert 0 into a property or component, or use a zero-valued object
+reference, libical will either silently ignore the error or will abort
+with an error message. This behavior is controlled by a compile time
+flag (ICAL_ERRORS_ARE_FATAL), and will abort by default.
+
+5.1.2 vaargs Constructors
+
+There is another way to create complex components, which is arguably
+more elegant, if you are not horrified by varargs. The varargs constructor
+interface allows you to create intricate components in a single block
+of code. Here is the previous examples in the vaargs style.
+
+ calendar =
+
+ icalcomponent_vanew(
+
+ ICAL_VCALENDAR_COMPONENT,
+
+ icalproperty_new_version(''2.0''),
+
+ icalproperty_new_prodid(
+
+ ''-//RDU Software//NONSGML HandCal//EN''),
+
+ icalcomponent_vanew(
+
+ ICAL_VEVENT_COMPONENT,
+
+ icalproperty_new_dtstamp(atime),
+
+ icalproperty_new_uid(''guid-1.host1.com''),
+
+ icalproperty_vanew_organizer(
+
+ ''mrbig@host.com''),
+
+ icalparameter_new_role(ICAL_ROLE_CHAIR),
+
+ 0
+
+ ),
+
+ icalproperty_vanew_attendee(
+
+ ''employee-A@host.com'',
+
+ icalparameter_new_role(
+
+ ICAL_ROLE_REQPARTICIPANT),
+
+ icalparameter_new_rsvp(1),
+
+ icalparameter_new_cutype(ICAL_CUTYPE_GROUP),
+
+ 0
+
+ ),
+
+ icalproperty_new_location(
+
+ "1CP Conference Room 4350"),
+
+ 0
+
+ ),
+
+ 0
+
+ );
+
+This form is similar to the constructor form , except that the constructors
+have "vanew" instead of "new" in the name. The arguments are similar
+too, except that the component constructor can have a list of properties,
+and the property constructor can have a list of parameters. Be sure
+to terminate every list with a '0', or your code will crash, if you
+are lucky.
+
+5.1.3 Parsing Text Files
+
+The final way to create components will probably be the most common;
+you can create components from RFC2445 compliant text. If you have
+the string in memory, use
+
+icalcomponent* icalparser_parse_string(char* str);
+
+If the string contains only one component, the parser will return the
+component in libical form. If the string contains multiple components,
+the multiple components will be returned as the children of an ICAL_XROOT_COMPONENT
+component.
+
+Parsing a whole string may seem wasteful if you want to pull a large
+component off of the network or from a file; you may prefer to parse
+the component line by line. This is possible too by using:
+
+icalparser* icalparser_new();
+
+void icalparser_free(icalparser* parser);
+
+icalparser_get_line(parser,read_stream);
+
+icalparser_add_line(parser,line);
+
+icalparser_set_gen_data(parser,stream)
+
+These routines will construct a parser object to which you can add
+lines of input and retrieve any components that the parser creates
+from the input. These routines work by specifing an adaptor routine
+to get string data from a source. For an example:
+
+char* read_stream(char *s, size_t size, void *d)
+
+{
+
+ char *c = fgets(s,size, (FILE*)d);
+
+ return c;
+
+}
+
+main() {
+
+ char* line;
+
+ icalcomponent *c;
+
+ icalparser *parser = icalparser_new();
+
+ FILE* stream = fopen(argv[1],"r");
+
+ icalparser_set_gen_data(parser,stream);
+
+ do{
+
+ line = icalparser_get_line(parser,read_stream);
+
+ c = icalparser_add_line(parser,line);
+
+ if (c != 0){
+
+ printf("%s",icalcomponent_as_ical_string(c));
+
+ icalparser_claim(parser);
+
+ printf("\n---------------\n");
+
+ icalcomponent_free(c);
+
+ }
+
+ } while ( line != 0);
+
+}
+
+The parser object parameterizes the routine used to get input lines
+with icalparser_set_gen_data() and icalparser_get_line(). In this
+example, the routine read_stream() will fetch the next line from a
+stream, with the stream passed in as the void* parameter d. The parser
+calls read_stream() from icalparser_get_line(), but it also needs
+to know what stream to use. This is set by the call to icalparser_set_gen_data().
+By using a different routine for read_stream or passing in different
+data with icalparser_set_gen_data, you can connect to any data source.
+
+Using the same mechanism, other implementations could read from memory
+buffers, sockets or other interfaces.
+
+Since the example code is a very common way to use the parser, there
+is a convenience routine;
+
+icalcomponent* icalparser_parse(icalparser *parser,
+
+ char* (*line_gen_func)(char *s, size_t size, void*
+d))
+
+To use this routine, you still must construct the parser object and
+pass in a reference to a line reading routine. If the parser can create
+a single component from the input, it will return a pointer to the
+newly constructed component. If the parser can construct multiple
+components from the input, it will return a reference to an XROOT
+component ( of type ICAL_XROOT_COMPONENT.) This XROOT component will
+hold all of the components constructed from the input as children.
+
+5.2 Accessing Components
+
+Given a reference to a component, you probably will want to access
+the properties, parameters and values inside. Libical interfaces let
+you find sub-component, add and remove sub-components, and do the
+same three operations on properties.
+
+5.2.1 Finding Components
+
+To find a sub-component of a component, use:
+
+icalcomponent* icalcomponent_get_first_component(
+
+ icalcomponent* component,
+
+ icalcomponent_kind kind);
+
+This routine will return a reference to the first component of the
+type 'kind.' The key kind values, listed in icalenums.h are:
+
+ICAL_ANY_COMPONENT
+
+ICAL_VEVENT_COMPONENT
+
+ICAL_VTODO_COMPONENT
+
+ICAL_VJOURNAL_COMPONENT
+
+ICAL_VCALENDAR_COMPONENT
+
+ICAL_VFREEBUSY_COMPONENT
+
+ICAL_VALARM_COMPONENT
+
+These are only the most common components; there are many more listed
+in icalenums.h.
+
+As you might guess, if there is more than one subcomponent of the type
+you have chosen, this routine will return only the first. to get at
+the others, you need to iterate through the component.
+
+5.2.2 Iterating Through Components
+
+Iteration requires a second routine to get the next subcomponent after
+the first:
+
+icalcomponent* icalcomponent_get_next_component(
+
+ icalcomponent* component,
+
+ icalcomponent_kind kind);
+
+With the 'first' and 'next' routines, you can create a for loop to
+iterate through all of a components subcomponents
+
+ for(c = icalcomponent_get_first_component(comp,ICAL_ANY_COMPONENT);
+
+ c != 0;
+
+ c = icalcomponent_get_next_component(comp,ICAL_ANY_COMPONENT))
+
+{
+
+ do_something(c);
+
+}
+
+This code bit wil iterate through all of the subcomponents in 'comp'
+but you can select a specific type of component by changing ICAL_ANY_COMPONENT
+to another component type.
+
+5.2.3 Using Component Iterators
+
+The iteration model in the previous section requires the component
+to keep the state of the iteration. So, you could not use this model
+to perform a sorting operations, since you'd need two iterators and
+there is only space for one. If you ever call icalcomponent_get_first_component()
+when an iteration is in progress, the pointer will be reset to the
+beginning.
+
+To solve this problem, there are also external iterators for components.
+The routines associated with these external iterators are:
+
+icalcompiter icalcomponent_begin_component(icalcomponent* component,
+icalcomponent_kind kind);
+
+icalcompiter icalcomponent_end_component(icalcomponent* component,
+icalcomponent_kind kind);
+
+icalcomponent* icalcompiter_next(icalcompiter* i);
+
+icalcomponent* icalcompiter_prior(icalcompiter* i);
+
+icalcomponent* icalcompiter_deref(icalcompiter* i);
+
+The _begin_() and _end_() routines return a new iterator that points
+to the beginning and ending of the list of subcomponent for the given
+component, and the kind argument works like the kind argument for
+internal iterators.
+
+After creating an iterators, use _next_() and _prior_() to step forward
+and backward through the list and get the component that the iterator
+points to, and use _deref() to return the component that the iterator
+points to without moving the iterator. All routines will return 0
+when they move to point off the end of the list.
+
+Here is an example of a loop using these routines:
+
+for(
+
+ i = icalcomponent_begin_component(impl->cluster,ICAL_ANY_COMPONENT);
+
+ icalcompiter_deref(&i)!= 0;
+
+ icalcompiter_next(&i)
+
+) {
+
+ icalcomponent *this = icalcompiter_deref(&i);
+
+}
+
+5.2.4 Removing Components
+
+Removing an element from a list while iterating through the list with
+the internal iterators can cause problems, since you will probably
+be removing the element that the internal iterator points to. The
+_remove() routine will keep the iterator valid by moving it to the
+next component, but in a normal loop, this will result in two advances
+per iteration, and you will remove only every other component. To
+avoid the problem, you will need to step the iterator ahead of the
+element you are going to remove, like this:
+
+for(c = icalcomponent_get_first_component(parent_comp,ICAL_ANY_COMPONENT);
+
+ c != 0;
+
+ c = next
+
+{
+
+ next = icalcomponent_get_next_component(parent_comp,ICAL_ANY_COMPONENT);
+
+ icalcomponent_remove_component(parent_comp,c);
+
+}
+
+Another way to remove components is to rely on the side effect of icalcomponent_remove_component:
+if component iterator in the parent component is pointing to the child
+that will be removed, it will move the iterator to the component after
+the child. The following code will exploit this behavior:
+
+icalcomponent_get_first_component(parent_comp,ICAL_VEVENT_COMPONENT);
+
+while((c=icalcomponent_get_current_component(c)) != 0 ){
+
+ if(icalcomponent_isa(c) == ICAL_VEVENT_COMPONENT){
+
+ icalcomponent_remove_component(parent_comp,inner);
+
+ } else {
+
+ icalcomponent_get_next_component(parent_comp,ICAL_VEVENT_COMPONENT);
+
+ }
+
+}
+
+5.2.5 Working with properties and parameters
+
+Finding, iterating and removing properties works the same as it does
+for components, using the property-specific or parameter-specific
+interfaces:
+
+icalproperty* icalcomponent_get_first_property(
+
+ icalcomponent* component,
+
+ icalproperty_kind kind);
+
+icalproperty* icalcomponent_get_next_property(
+
+ icalcomponent* component,
+
+ icalproperty_kind kind);
+
+void icalcomponent_add_property(
+
+ icalcomponent* component,
+
+ icalproperty* property);
+
+void icalcomponent_remove_property(
+
+ icalcomponent* component,
+
+ icalproperty* property);
+
+For parameters:
+
+icalparameter* icalproperty_get_first_parameter(
+
+ icalproperty* prop,
+
+ icalparameter_kind kind);
+
+icalparameter* icalproperty_get_next_parameter(
+
+ icalproperty* prop,
+
+ icalparameter_kind kind);
+
+void icalproperty_add_parameter(
+
+ icalproperty* prop,
+
+ icalparameter* parameter);
+
+void icalproperty_remove_parameter(
+
+ icalproperty* prop,
+
+ icalparameter_kind kind);
+
+Note that since there should be only one parameter of each type in
+a property, you will rarely need to use icalparameter_get_nect_paameter.
+
+5.2.6 Working with values
+
+Values are typically part of a property, although they can exist on
+their own. You can manipulate them either as part of the property
+or independently.
+
+The most common way to work with values to is to manipulate them from
+they properties that contain them. This involves fewer routine calls
+and intermediate variables than working with them independently, and
+it is type-safe.
+
+For each property, there are a _get_ and a _set_ routine that access
+the internal value. For instanace, for the UID property, the routines
+are:
+
+void icalproperty_set_uid(icalproperty* prop, const char* v)
+
+const char* icalproperty_get_uid(icalproperty* prop)
+
+For multi-valued properties, like ATTACH, the value type is usually
+a struct or union that holds both possible types.
+
+If you want to work with the underlying value object, you can get and
+set it with:
+
+icalvalue* icalproperty_get_value (icalproperty* prop)
+
+void icalproperty_set_value(icalproperty* prop, icalvalue* value);
+
+Icalproperty_get_value() will return a reference that you can manipulate
+with other icalvalue routines. Most of the time, you will have to
+know what the type of the value is. For instance, if you know that
+the value is a DATETIME type, you can manipulate it with:
+
+struct icaltimetype icalvalue_get_datetime(icalvalue* value);
+
+void icalvalue_set_datetime(icalvalue* value, struct icaltimetype v);
+
+When working with an extension property or value (and X-PROPERTY or
+a property that has the parameter VALUE=x-name ) the value type is
+always a string. To get and set the value, use:
+
+void icalproperty_set_x(icalproperty* prop, char* v);
+
+char* icalproperty_get_x(icalproperty* prop);
+
+All X properties have the type of ICAL_X_PROPERTY, so you will need
+these routines to get and set the name of the property:
+
+char* icalproperty_get_x_name(icalproperty* prop)
+
+void icalproperty_set_x_name(icalproperty* prop, char* name);
+
+5.2.7 Checking Component Validity
+
+RFC 2446 defines rules for what properties must exist in a component
+to be used for transferring scheduling data. Most of these rules relate
+to the existence of properties relative to the METHOD property, which
+declares what operation a remote receiver should use to process a
+component. For instance, if the METHOD is REQUEST and the component
+is a VEVENT, the sender is probably asking the receiver to join in
+a meeting. In this case, RFC2446 says that the component must specify
+a start time (DTSTART) and list the receiver as an attendee (ATTENDEE).
+
+Libical can check these restrictions with the routine:
+
+int icalrestriction_check(icalcomponent* comp);
+
+This routine returns 0 if the component does not pass RFC2446 restrictions,
+or if the component is malformed. The component you pass in must be
+a VCALENDAR, with one or more children, like the examples in RFC2446.
+
+When this routine runs, it will insert new properties into the component
+to indicate any errors it finds. See section 6.5.3, X-LIC-ERROR for
+more information about these error properties.
+
+5.2.8 Converting Components to Text
+
+To create an RFC2445 compliant text representation of an object, use
+one of the *_as_ical_string() routines:
+
+char* icalcomponent_as_ical_string (icalcomponent* component)
+
+char* icalproperty_as_ical_string (icalproperty* property)
+
+char* icalparameter_as_ical_string (icalparameter* parameter)
+
+char* icalvalue_as_ical_string (icalvalue* value)
+
+In most cases, you will only use icalcomponent_as_ical_string (), since
+it will cascade and convert all of the parameters, properties and
+values that are attached to the root component.
+
+Icalproperty_as_ical_string() will terminate each line with the RFC2445
+specified line terminator "\\n" However, if you compile with the symbol
+ICAL_UNIX_NEWLINE undefined, ( it is defined by default) it will terminate
+lines with "\\n\\r"
+
+Remember that the string returned by these routines is owned by the
+library, and will eventually be re-written. You should copy it if
+you want to preserve it.
+
+5.3 Time
+
+5.3.1 Time structure
+
+LIbical defines it's own time structure for storing all dates and times.
+It would have been nice to re-use the C library's struct tm, but that
+structure does not differentiate between dates and times, and between
+local time and UTC. The libical structure is:
+
+struct icaltimetype {
+
+ int year;
+
+ int month;
+
+ int day;
+
+ int hour;
+
+ int minute;
+
+ int second;
+
+ int is_utc; /* 1-> time is in UTC timezone */
+
+ int is_date; /* 1 -> interpret this as date. */ };
+
+The year, month, day, hour, minute and second fields hold the broken-out
+time values. The is_utc field distinguishes between times in UTC and
+a local time zone. The is_date field indicates if the time should
+be interpreted only as a date. If it is a date, the hour, minute and
+second fields are assumed to be zero, regardless of their actual vaules.
+
+5.3.2 Creating time structures
+
+There are several ways to create a new icaltimetype structure:
+
+struct icaltimetype icaltime_from_string(const char* str);
+
+struct icaltimetype icaltime_from_timet(time_t v, int is_date);
+
+struct icaltimetype icaltime_from_int(int v, int is_date, int is_utc);
+
+Icaltime_from_string takes any RFC2445 compliant time string:
+
+struct icaltimetype tt = icaltime_from_string("19970101T103000");
+
+Icaltime_from_timet takes a timet value, representing seconds past
+the POSIX epoch, and a flag to indicate if the time is a date. Dates
+have an identical structure to a time, but the time portion ( hours,
+minuts and seconds ) is always 00:00:00. Dates act differently in
+sorting an comparision, and they have a different string representation
+in RFC2445.
+
+The icaltime_from_int is like icaltime_from_timet, but with an arbitrary
+epoch. This routine was a mistake and is deprecated.
+
+5.3.3 Time manipulating routines
+
+The null time value is used to indicate that the data in the structure
+is not a valid time.
+
+struct icaltimetype icaltime_null_time(void);
+
+int icaltime_is_null_time(struct icaltimetype t);
+
+It is sensible for the broken-out time fields to contain values that
+are not permitted in an ISO compliant time string. For instance, the
+seconds field can hold values greater than 59, and the hours field
+can hold values larger than 24. The excessive values will be rolled
+over into the next larger field when the structure is normalized.
+
+struct icaltimetype icaltime_normalize(struct icaltimetype t);
+
+Normalizing allows you to do arithmetic operations on time values.
+
+struct icaltimetype tt = icaltime_from_string("19970101T103000");
+
+tt.days +=3
+
+tt.second += 70;
+
+tt = icaltime_normalize(tt);
+
+There are several routines to get the day of the week or month, etc,
+from a time structure.
+
+short icaltime_day_of_year(struct icaltimetype t);
+
+struct icaltimetype icaltime_from_day_of_year(short doy, short year);
+
+short icaltime_day_of_week(struct icaltimetype t);
+
+short icaltime_start_doy_of_week(struct icaltimetype t);
+
+short icaltime_week_number(short day_of_month, short month, short year);
+
+struct icaltimetype icaltime_from_week_number(short week_number, short
+year);
+
+short icaltime_days_in_month(short month,short year);
+
+Two routines convert time structures to and from the number of seconds
+since the POSIX epoch. The is_date field indicates whether or not
+the hour, minute and second fields should be used in the conversion.
+
+struct icaltimetype icaltime_from_timet(time_t v, int is_date);
+
+time_t icaltime_as_timet(struct icaltimetype);
+
+The compare routine works exactly like strcmp, but on time structures.
+
+int icaltime_compare(struct icaltimetype a,struct icaltimetype b);
+
+The following routines convert between UTC and a named timezone. The
+tzid field must be a timezone name from the Olsen database, such as
+"America/Los_Angeles."
+
+The utc_offset routine returns the offset of the named time zone from
+UTC, in seconds.
+
+The tt parameter in the following routines indicates the date on which
+the conversion should be made. The tt parameter is necessary because
+timezones have many different rules for when daylight savings time
+is used, and these rules can change over time. So, for a single timezone
+one year may have daylight savings time on March 15, but for other
+years March 15 may be standard time, and some years may have standard
+time all year.
+
+int icaltime_utc_offset(struct icaltimetype tt, char* tzid);
+
+int icaltime_local_utc_offset();
+
+struct icaltimetype icaltime_as_utc(struct icaltimetype tt,char* tzid);
+
+struct icaltimetype icaltime_as_zone(struct icaltimetype tt,char* tzid);
+
+struct icaltimetype icaltime_as_local(struct icaltimetype tt);
+
+5.4 Storing Objects
+
+The libical distribution includes a separate library, libicalss, that
+allows you to store iCal component data to disk in a variety of ways.
+
+The file storage routines are organized in an inheritance heirarchy
+that is rooted in icalset, with the derived class icalfileset and
+icaldirset. Icalfileset stores components to a file, while icaldirset
+stores components to multiple files, one per month based on DTSTAMP.
+Other storages classess, for storage to a heap or a mysql database
+for example, could be added in the future.
+
+All of the icalset derived classes have the same interface:
+
+icaldirset* icaldirset_new(const char* path);
+
+void icaldirset_free(icaldirset* store);
+
+const char* icaldirset_path(icaldirset* store);
+
+void icaldirset_mark(icaldirset* store);
+
+icalerrorenum icaldirset_commit(icaldirset* store);
+
+icalerrorenum icaldirset_add_component(icaldirset* store, icalcomponent*
+comp);
+
+icalerrorenum icaldirset_remove_component(icaldirset* store, icalcomponent*
+comp);
+
+int icaldirset_count_components(icaldirset* store, icalcomponent_kind
+kind);
+
+icalerrorenum icaldirset_select(icaldirset* store, icalcomponent* gauge);
+
+void icaldirset_clear(icaldirset* store);
+
+icalcomponent* icaldirset_fetch(icaldirset* store, const char* uid);
+
+int icaldirset_has_uid(icaldirset* store, const char* uid);
+
+icalcomponent* icaldirset_fetch_match(icaldirset* set, icalcomponent
+*c);
+
+icalerrorenum icaldirset_modify(icaldirset* store, icalcomponent *oldc,
+icalcomponent *newc);
+
+icalcomponent* icaldirset_get_current_component(icaldirset* store);
+
+icalcomponent* icaldirset_get_first_component(icaldirset* store);
+
+icalcomponent* icaldirset_get_next_component(icaldirset* store);
+
+5.4.1 Creating a new set
+
+You can create a new set from either the base class or the direved
+class. From the base class use one of:
+
+icalset* icalset_new_file(const char* path);
+
+icalset* icalset_new_dir(const char* path);
+
+icalset* icalset_new_heap(void);
+
+icalset* icalset_new_mysql(const char* path);
+
+You can also create a new set based on the derived class, For instance,
+with icalfileset:
+
+icalfileset* icalfileset_new(const char* path);
+
+icalfileset* icalfileset_new_open(const char* path, int flags, mode_t
+mode);
+
+icalset_new_file is identical to icalfileset_new. Both routines will
+open an existing file for readinga and writing, or create a new file
+if it does not exist. Icalfilset_new_open takes the same arguments
+as the open() system routine and behaves in the same way.
+
+The icalset and icalfilset objects are somewhat interchangable -- you
+can use an icalfileset* as an argument to any of the icalset routines.
+
+The following examples will all use icalfileset routines; using the
+other icalset derived classess will be similar.
+
+5.4.2 Adding, Finding and Removing Components
+
+To add components to a set, use:
+
+icalerrorenum icalfileset_add_component(icalfileset* cluster, icalcomponent*
+child);
+
+The fileset keeps an inmemory copy of the components, and this set
+must be written back to the file ocassionally. There are two routines
+to manage this:
+
+void icalfileset_mark(icalfileset* cluster);
+
+icalerrorenum icalfileset_commit(icalfileset* cluster);
+
+icalfileset_mark indicates that the in-memory components have changed.
+Calling the _add_component routine will call _mark automatically,
+but you may need to call it yourself if you have made a change to
+an existing component. The _commit routine writes the data base to
+disk, but only if it is marked. The _commit routine is called automatically
+when the icalfileset is freed.
+
+To iterate through the components in a set, use:
+
+icalcomponent* icalfileset_get_first_component(icalfileset* cluster);
+
+icalcomponent* icalfileset_get_next_component(icalfileset* cluster);
+
+icalcomponent* icalfileset_get_current_component (icalfileset* cluster);
+
+These routines work like the corresponding routines from icalcomponent,
+except that their output is filtered through a gauge. A gauge is a
+test for the properties within a components; only components that
+pass the test are returned. A gauge can be constructed from a MINSQL
+string with:
+
+icalgauge* icalgauge_new_from_sql(char* sql);
+
+Then, you can add the gauge to the set with :
+
+icalerrorenum icalfileset_select(icalfileset* store, icalgauge* gauge);
+
+Here is an example that puts all of these routines together:
+
+void test_fileset()
+
+{
+
+ icalfileset *fs;
+
+ icalcomponent *c;
+
+ int i;
+
+ char *path = "test_fileset.ics";
+
+ icalgauge *g = icalgauge_new_from_sql(
+
+ "SELECT * FROM VEVENT WHERE DTSTART > '20000103T120000Z' AND
+DTSTART <= '20000106T120000Z'");
+
+
+
+ fs = icalfileset_new(path);
+
+
+
+ for (i = 0; i!= 10; i++){
+
+ c = make_component(i); /* Make a new component where DTSTART
+has month of i */
+
+ icalfileset_add_component(fs,c);
+
+ }
+
+ icalfileset_commit(fs); /* Write to disk */
+
+ icalfileset_select(fs,g); /* Set the gauge to filter components
+*/
+
+
+
+ for (c = icalfileset_get_first_component(fs);
+
+ c != 0;
+
+ c = icalfileset_get_next_component(fs)){
+
+ struct icaltimetype t = icalcomponent_get_dtstart(c);
+
+
+
+ printf("%s\n",icaltime_as_ctime(t));
+
+ }
+
+ icalfileset_free(fs);
+
+}
+
+5.4.3 Other routines
+
+There are several other routines in the icalset interface, but they
+not fully implemented yet.
+
+5.5 Memory Management
+
+Libical relies heavily on dynamic allocation for both the core objects
+and for the strings used to hold values. Some of this memory the library
+caller owns and must free, and some of the memory is managed by the
+library. Here is a summary of the memory rules.
+
+1) If the function name has "new" in it, the caller gets control
+ of the memory. ( such as icalcomponent_new(), or icalproperty_new_clone()
+ )
+
+2) If you got the memory from a routine with new in it, you must
+ call the corresponding *_free routine to free the memory. ( Use
+ icalcomponent_free() to free objects created with icalcomponent_new())
+
+3) If the function name has "add" in it, the caller is transferring
+ control of the memory to the routine. ( icalproperty_add_parameter() )
+
+4) If the function name has "remove" in it, the caller passes in
+ a pointer to an object and after the call returns, the caller owns
+ the object. So, before you call icalcomponent_remove_property(comp,foo),
+ you do not own "foo" and after the call returns, you do.
+
+5) If the routine returns a string and its name does NOT end in "_r",
+ libical owns the memory and will put it on a ring buffer to reclaim
+ later. For example, icalcomponent_as_ical_string(). You'd better
+ strdup() it if you want to keep it, and you don't have to delete it.
+
+6) If the routine returns a string and its name *does* end in "_r", the
+ caller gets control of the memory and is responsible for freeing it.
+ For example, icalcomponent_as_ical_string_r() does the same thing as
+ icalcomponent_as_ical_string(), except you now have control of the
+ string buffer it returns.
+
+5.6 Error Handling
+
+Libical has several error handling mechanisms for the various types
+of programming, semantic and syntactic errors you may encounter.
+
+5.6.1 Return values
+
+Many library routines signal errors through their return values. All
+routines that return a pointer, such as icalcomponent_new(), will
+return 0 ( zero ) on a fatal error. Some routines will return a value
+of enum icalerrorenum.
+
+5.6.2 icalerrno
+
+Most routines will set the global error value icalerrno on errors.
+This variable is an enumeration; permissible values can be found in
+libical/icalerror.h. If the routine returns an enum icalerrorenum,
+then the return value will be the same as icalerrno. You can use icalerror_strerror()
+to get a string that describes the error. The enumerations are:
+
+* ICAL_BADARG_ERROR -- One of the argument to a routine was bad. Typically
+ for a null pointer.
+
+* ICAL_NEWFAILED_ERROR -- A new() or malloc() failed
+
+* ICAL_MALFORMEDDATA_ERROR -- An input string was not in the correct
+ format
+
+* ICAL_PARSE_ERROR -- The parser failed to parse an incomming component
+
+* ICAL_INTERNAL_ERROR -- Largely equivalent to an assert
+
+* ICAL_FILE_ERROR -- A file operation failed. Check errno for more
+ detail.
+
+* ICAL_ALLOCATION_ERROR -- ?
+
+* ICAL_USAGE_ERROR -- ?
+
+* ICAL_NO_ERROR -- No error
+
+* ICAL_MULTIPLEINCLUSION_ERROR -- ?
+
+* ICAL_TIMEDOUT_ERROR -- For CSTP and acquiring locks
+
+* ICAL_UNKNOWN_ERROR -- ?
+
+5.6.3 X-LIC-ERROR and X-LIC-INVALID-COMPONENT
+
+The library handles semantic and syntactic errors in components by
+inserting errors properties into the components. If the parser cannot
+parse incoming text ( a syntactic error ) or if the icalrestriction_check()
+routine indicates that the component does not meet the requirements
+of RFC2446 ( a semantic error) the library will insert properties
+of the type X-LIC-ERROR to describe the error. Here is an example
+of the error property:
+
+X-LIC-ERROR;X-LIC-ERRORTYPE=INVALID_ITIP :Failed iTIP restrictions
+for property DTSTART.
+
+Expected 1 instances of the property and got 0
+
+This error resulted from a call to icalrestriction_check(), which discovered
+that the component does not have a DTSTART property, as required by
+RFC2445.
+
+There are a few routines to manipulate error properties:
+
+[ The following data is supposed to be in a table. It looks OK in LyX,
+but does not format propertly in output. ]
+
++-------------------------------------+---------------------------------------------------------+
+| Routine | Purpose |
++-------------------------------------+---------------------------------------------------------+
+| void icalrestriction_check() | Check a component against RFC2446 and insert |
++-------------------------------------+---------------------------------------------------------+
+| | error properties to indicate non compliance |
++-------------------------------------+---------------------------------------------------------+
+| int icalcomponent_count_errors() | Return the number of error properties |
++-------------------------------------+---------------------------------------------------------+
+| | in a component |
++-------------------------------------+---------------------------------------------------------+
+| void icalcomponent_strip_errors() | Remove all error properties in as |
++-------------------------------------+---------------------------------------------------------+
+| | component |
++-------------------------------------+---------------------------------------------------------+
+| void icalcomponent_convert_errors() | Convert some error properties into |
++-------------------------------------+---------------------------------------------------------+
+| | REQUESTS-STATUS proprties to indicate the inability to |
++-------------------------------------+---------------------------------------------------------+
+| | process the component as an iTIP request. |
++-------------------------------------+---------------------------------------------------------+
+
+
+The types of errors are listed in icalerror.h. They are:
+
+ICAL_XLICERRORTYPE_COMPONENTPARSEERROR
+
+ICAL_XLICERRORTYPE_PARAMETERVALUEPARSEERROR
+
+ICAL_XLICERRORTYPE_PARAMETERNAMEPARSEERROR
+
+ICAL_XLICERRORTYPE_PROPERTYPARSEERROR
+
+ICAL_XLICERRORTYPE_VALUEPARSEERROR
+
+ICAL_XLICERRORTYPE_UNKVCALPROP
+
+ICAL_XLICERRORTYPE_INVALIDITIP
+
+The libical parser will generate the error that end in PARSEERROR when
+it encounters garbage in the input steam. ICAL_XLICERRORTYPE_INVALIDITIP
+is inserted by icalrestriction_check(), and ICAL_XLICERRORTYPE_UNKVCALPROP
+is generated by icalvcal_convert() when it encounters a vCal property
+that it cannot convert or does not know about.
+
+Icalcomponent_convert_errors() converts some of the error properties
+in a component into REQUEST-STATUS properties that indicate a failure.
+As of libical version0.18, this routine only convert *PARSEERROR errors
+and it always generates a 3.x ( failure ) code. This makes it more
+of a good idea than a really useful bit of code.
+
+5.6.4 ICAL_ERRORS_ARE_FATAL and icalerror_errors_are_fatal
+
+If the global variable icalerror_errors_are_fatal is set to 1, then
+any error condition will cause the program to abort. The abort occurs
+in icalerror_set_errno(), and is done with an assert(0) if NDEBUG
+is undefined, and with icalerror_crash_here if NDEBUG is defined.
+The default value of icalerror_errors_are_fatal is 1 when ICAL_ERRORS_ARE_FATAL
+is defined, and 0 otherwise. Since ICAL_ERRORS_ARE_FATAL is defined
+by default, icalerror_errors_are_fatal is also defined by default.
+
+5.7 Naming Standard
+
+Structures that you access with the "struct" keyword, such as "struct
+icaltimetype" are things that you are allowed to see inside and poke
+at.
+
+Structures that you access though a typedef, such as "icalcomponent"
+are things where all of the data is hidden.
+
+Component names that start with "V" are part of RFC 2445 or another
+iCal standard. Component names that start with "X" are also part of
+the spec, but they are not actually components in the spec. However,
+they look and act like components, so they are components in libical.
+Names that start with "XLIC" or "X-LIC" are not part of any iCal spec.
+They are used internally by libical.
+
+Enums that identify a component, property, value or parameter end with
+"_COMPONENT," "_PROPERTY," "_VALUE," or "_PARAMETER"s
+
+Enums that identify a parameter value have the name of the parameter
+as the second word. For instance: ICAL_ROLE_REQPARTICIPANT or ICAL_PARTSTAT_ACCEPTED.
+
+The enums for the parts of a recurarance rule and request statuses
+are irregular.
+
+6 Hacks and Bugs
+
+There are a lot of hacks in the library -- bits of code that I am not
+proud of and should probably be changed. These are marked with the
+comment string "HACK."
+
+7 Library Reference
+
+7.1 Manipulating struct icaltimetype
+
+7.1.1 Struct icaltimetype
+
+struct icaltimetype
+
+{
+
+ int year;
+
+ int month;
+
+ int day;
+
+ int hour;
+
+ int minute;
+
+ int second;
+
+ int is_utc;
+
+ int is_date;
+
+ const char* zone;
+
+};