emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/rt-liberation 5de9af6 01/72: import for initial Savanna


From: Stefan Monnier
Subject: [elpa] externals/rt-liberation 5de9af6 01/72: import for initial Savannah tree
Date: Wed, 5 Aug 2020 11:57:31 -0400 (EDT)

branch: externals/rt-liberation
commit 5de9af64f18301ca1943ed1e362255f050424fcd
Author: Johnathan Rabkin <yonirabkin@member.fsf.org>
Commit: Johnathan Rabkin <yonirabkin@member.fsf.org>

    import for initial Savannah tree
---
 COPYING                         |  339 +++++++++++
 COPYINGv3                       |  674 +++++++++++++++++++++
 doc/Makefile                    |   10 +
 doc/fdl.texi                    |  451 ++++++++++++++
 doc/gpl.texi                    |  725 ++++++++++++++++++++++
 doc/rt-liberation.texinfo       | 1006 ++++++++++++++++++++++++++++++
 etc/logo/rt-liberation-logo.svg |  126 ++++
 etc/rt-dot-el-design            |   60 ++
 rt-liberation-gnus.el           |  230 +++++++
 rt-liberation-multi.el          |  113 ++++
 rt-liberation-storage.el        |  110 ++++
 rt-liberation-update.el         |  106 ++++
 rt-liberation.el                | 1276 +++++++++++++++++++++++++++++++++++++++
 13 files changed, 5226 insertions(+)

diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..d511905
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/COPYINGv3 b/COPYINGv3
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/COPYINGv3
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
index 0000000..dd20ede
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,10 @@
+# Don't delete if make is interrupted
+.PRECIOUS: %.info %.html
+
+all: rt-liberation.info
+
+%.info: %.texinfo
+       makeinfo --no-split $<
+
+%.html: %.texinfo
+       makeinfo --html --no-split $<
diff --git a/doc/fdl.texi b/doc/fdl.texi
new file mode 100644
index 0000000..1276677
--- /dev/null
+++ b/doc/fdl.texi
@@ -0,0 +1,451 @@
+@node The GNU FDL, Concept Index, Copying, Top
+@chapter GNU Free Documentation License
+
+@cindex FDL, GNU Free Documentation License
+@center Version 1.2, November 2002
+
+@display
+Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc.
+51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+@end display
+
+@enumerate 0
+@item
+PREAMBLE
+
+The purpose of this License is to make a manual, textbook, or other
+functional and useful document @dfn{free} in the sense of freedom: to
+assure everyone the effective freedom to copy and redistribute it,
+with or without modifying it, either commercially or noncommercially.
+Secondarily, this License preserves for the author and publisher a way
+to get credit for their work, while not being considered responsible
+for modifications made by others.
+
+This License is a kind of ``copyleft'', which means that derivative
+works of the document must themselves be free in the same sense.  It
+complements the GNU General Public License, which is a copyleft
+license designed for free software.
+
+We have designed this License in order to use it for manuals for free
+software, because free software needs free documentation: a free
+program should come with manuals providing the same freedoms that the
+software does.  But this License is not limited to software manuals;
+it can be used for any textual work, regardless of subject matter or
+whether it is published as a printed book.  We recommend this License
+principally for works whose purpose is instruction or reference.
+
+@item
+APPLICABILITY AND DEFINITIONS
+
+This License applies to any manual or other work, in any medium, that
+contains a notice placed by the copyright holder saying it can be
+distributed under the terms of this License.  Such a notice grants a
+world-wide, royalty-free license, unlimited in duration, to use that
+work under the conditions stated herein.  The ``Document'', below,
+refers to any such manual or work.  Any member of the public is a
+licensee, and is addressed as ``you''.  You accept the license if you
+copy, modify or distribute the work in a way requiring permission
+under copyright law.
+
+A ``Modified Version'' of the Document means any work containing the
+Document or a portion of it, either copied verbatim, or with
+modifications and/or translated into another language.
+
+A ``Secondary Section'' is a named appendix or a front-matter section
+of the Document that deals exclusively with the relationship of the
+publishers or authors of the Document to the Document's overall
+subject (or to related matters) and contains nothing that could fall
+directly within that overall subject.  (Thus, if the Document is in
+part a textbook of mathematics, a Secondary Section may not explain
+any mathematics.)  The relationship could be a matter of historical
+connection with the subject or with related matters, or of legal,
+commercial, philosophical, ethical or political position regarding
+them.
+
+The ``Invariant Sections'' are certain Secondary Sections whose titles
+are designated, as being those of Invariant Sections, in the notice
+that says that the Document is released under this License.  If a
+section does not fit the above definition of Secondary then it is not
+allowed to be designated as Invariant.  The Document may contain zero
+Invariant Sections.  If the Document does not identify any Invariant
+Sections then there are none.
+
+The ``Cover Texts'' are certain short passages of text that are listed,
+as Front-Cover Texts or Back-Cover Texts, in the notice that says that
+the Document is released under this License.  A Front-Cover Text may
+be at most 5 words, and a Back-Cover Text may be at most 25 words.
+
+A ``Transparent'' copy of the Document means a machine-readable copy,
+represented in a format whose specification is available to the
+general public, that is suitable for revising the document
+straightforwardly with generic text editors or (for images composed of
+pixels) generic paint programs or (for drawings) some widely available
+drawing editor, and that is suitable for input to text formatters or
+for automatic translation to a variety of formats suitable for input
+to text formatters.  A copy made in an otherwise Transparent file
+format whose markup, or absence of markup, has been arranged to thwart
+or discourage subsequent modification by readers is not Transparent.
+An image format is not Transparent if used for any substantial amount
+of text.  A copy that is not ``Transparent'' is called ``Opaque''.
+
+Examples of suitable formats for Transparent copies include plain
+@sc{ascii} without markup, Texinfo input format, La@TeX{} input
+format, @acronym{SGML} or @acronym{XML} using a publicly available
+@acronym{DTD}, and standard-conforming simple @acronym{HTML},
+PostScript or @acronym{PDF} designed for human modification.  Examples
+of transparent image formats include @acronym{PNG}, @acronym{XCF} and
+@acronym{JPG}.  Opaque formats include proprietary formats that can be
+read and edited only by proprietary word processors, @acronym{SGML} or
+@acronym{XML} for which the @acronym{DTD} and/or processing tools are
+not generally available, and the machine-generated @acronym{HTML},
+PostScript or @acronym{PDF} produced by some word processors for
+output purposes only.
+
+The ``Title Page'' means, for a printed book, the title page itself,
+plus such following pages as are needed to hold, legibly, the material
+this License requires to appear in the title page.  For works in
+formats which do not have any title page as such, ``Title Page'' means
+the text near the most prominent appearance of the work's title,
+preceding the beginning of the body of the text.
+
+A section ``Entitled XYZ'' means a named subunit of the Document whose
+title either is precisely XYZ or contains XYZ in parentheses following
+text that translates XYZ in another language.  (Here XYZ stands for a
+specific section name mentioned below, such as ``Acknowledgements'',
+``Dedications'', ``Endorsements'', or ``History''.)  To ``Preserve the Title''
+of such a section when you modify the Document means that it remains a
+section ``Entitled XYZ'' according to this definition.
+
+The Document may include Warranty Disclaimers next to the notice which
+states that this License applies to the Document.  These Warranty
+Disclaimers are considered to be included by reference in this
+License, but only as regards disclaiming warranties: any other
+implication that these Warranty Disclaimers may have is void and has
+no effect on the meaning of this License.
+
+@item
+VERBATIM COPYING
+
+You may copy and distribute the Document in any medium, either
+commercially or noncommercially, provided that this License, the
+copyright notices, and the license notice saying this License applies
+to the Document are reproduced in all copies, and that you add no other
+conditions whatsoever to those of this License.  You may not use
+technical measures to obstruct or control the reading or further
+copying of the copies you make or distribute.  However, you may accept
+compensation in exchange for copies.  If you distribute a large enough
+number of copies you must also follow the conditions in section 3.
+
+You may also lend copies, under the same conditions stated above, and
+you may publicly display copies.
+
+@item
+COPYING IN QUANTITY
+
+If you publish printed copies (or copies in media that commonly have
+printed covers) of the Document, numbering more than 100, and the
+Document's license notice requires Cover Texts, you must enclose the
+copies in covers that carry, clearly and legibly, all these Cover
+Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
+the back cover.  Both covers must also clearly and legibly identify
+you as the publisher of these copies.  The front cover must present
+the full title with all words of the title equally prominent and
+visible.  You may add other material on the covers in addition.
+Copying with changes limited to the covers, as long as they preserve
+the title of the Document and satisfy these conditions, can be treated
+as verbatim copying in other respects.
+
+If the required texts for either cover are too voluminous to fit
+legibly, you should put the first ones listed (as many as fit
+reasonably) on the actual cover, and continue the rest onto adjacent
+pages.
+
+If you publish or distribute Opaque copies of the Document numbering
+more than 100, you must either include a machine-readable Transparent
+copy along with each Opaque copy, or state in or with each Opaque copy
+a computer-network location from which the general network-using
+public has access to download using public-standard network protocols
+a complete Transparent copy of the Document, free of added material.
+If you use the latter option, you must take reasonably prudent steps,
+when you begin distribution of Opaque copies in quantity, to ensure
+that this Transparent copy will remain thus accessible at the stated
+location until at least one year after the last time you distribute an
+Opaque copy (directly or through your agents or retailers) of that
+edition to the public.
+
+It is requested, but not required, that you contact the authors of the
+Document well before redistributing any large number of copies, to give
+them a chance to provide you with an updated version of the Document.
+
+@item
+MODIFICATIONS
+
+You may copy and distribute a Modified Version of the Document under
+the conditions of sections 2 and 3 above, provided that you release
+the Modified Version under precisely this License, with the Modified
+Version filling the role of the Document, thus licensing distribution
+and modification of the Modified Version to whoever possesses a copy
+of it.  In addition, you must do these things in the Modified Version:
+
+@enumerate A
+@item
+Use in the Title Page (and on the covers, if any) a title distinct
+from that of the Document, and from those of previous versions
+(which should, if there were any, be listed in the History section
+of the Document).  You may use the same title as a previous version
+if the original publisher of that version gives permission.
+
+@item
+List on the Title Page, as authors, one or more persons or entities
+responsible for authorship of the modifications in the Modified
+Version, together with at least five of the principal authors of the
+Document (all of its principal authors, if it has fewer than five),
+unless they release you from this requirement.
+
+@item
+State on the Title page the name of the publisher of the
+Modified Version, as the publisher.
+
+@item
+Preserve all the copyright notices of the Document.
+
+@item
+Add an appropriate copyright notice for your modifications
+adjacent to the other copyright notices.
+
+@item
+Include, immediately after the copyright notices, a license notice
+giving the public permission to use the Modified Version under the
+terms of this License, in the form shown in the Addendum below.
+
+@item
+Preserve in that license notice the full lists of Invariant Sections
+and required Cover Texts given in the Document's license notice.
+
+@item
+Include an unaltered copy of this License.
+
+@item
+Preserve the section Entitled ``History'', Preserve its Title, and add
+to it an item stating at least the title, year, new authors, and
+publisher of the Modified Version as given on the Title Page.  If
+there is no section Entitled ``History'' in the Document, create one
+stating the title, year, authors, and publisher of the Document as
+given on its Title Page, then add an item describing the Modified
+Version as stated in the previous sentence.
+
+@item
+Preserve the network location, if any, given in the Document for
+public access to a Transparent copy of the Document, and likewise
+the network locations given in the Document for previous versions
+it was based on.  These may be placed in the ``History'' section.
+You may omit a network location for a work that was published at
+least four years before the Document itself, or if the original
+publisher of the version it refers to gives permission.
+
+@item
+For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve
+the Title of the section, and preserve in the section all the
+substance and tone of each of the contributor acknowledgements and/or
+dedications given therein.
+
+@item
+Preserve all the Invariant Sections of the Document,
+unaltered in their text and in their titles.  Section numbers
+or the equivalent are not considered part of the section titles.
+
+@item
+Delete any section Entitled ``Endorsements''.  Such a section
+may not be included in the Modified Version.
+
+@item
+Do not retitle any existing section to be Entitled ``Endorsements'' or
+to conflict in title with any Invariant Section.
+
+@item
+Preserve any Warranty Disclaimers.
+@end enumerate
+
+If the Modified Version includes new front-matter sections or
+appendices that qualify as Secondary Sections and contain no material
+copied from the Document, you may at your option designate some or all
+of these sections as invariant.  To do this, add their titles to the
+list of Invariant Sections in the Modified Version's license notice.
+These titles must be distinct from any other section titles.
+
+You may add a section Entitled ``Endorsements'', provided it contains
+nothing but endorsements of your Modified Version by various
+parties---for example, statements of peer review or that the text has
+been approved by an organization as the authoritative definition of a
+standard.
+
+You may add a passage of up to five words as a Front-Cover Text, and a
+passage of up to 25 words as a Back-Cover Text, to the end of the list
+of Cover Texts in the Modified Version.  Only one passage of
+Front-Cover Text and one of Back-Cover Text may be added by (or
+through arrangements made by) any one entity.  If the Document already
+includes a cover text for the same cover, previously added by you or
+by arrangement made by the same entity you are acting on behalf of,
+you may not add another; but you may replace the old one, on explicit
+permission from the previous publisher that added the old one.
+
+The author(s) and publisher(s) of the Document do not by this License
+give permission to use their names for publicity for or to assert or
+imply endorsement of any Modified Version.
+
+@item
+COMBINING DOCUMENTS
+
+You may combine the Document with other documents released under this
+License, under the terms defined in section 4 above for modified
+versions, provided that you include in the combination all of the
+Invariant Sections of all of the original documents, unmodified, and
+list them all as Invariant Sections of your combined work in its
+license notice, and that you preserve all their Warranty Disclaimers.
+
+The combined work need only contain one copy of this License, and
+multiple identical Invariant Sections may be replaced with a single
+copy.  If there are multiple Invariant Sections with the same name but
+different contents, make the title of each such section unique by
+adding at the end of it, in parentheses, the name of the original
+author or publisher of that section if known, or else a unique number.
+Make the same adjustment to the section titles in the list of
+Invariant Sections in the license notice of the combined work.
+
+In the combination, you must combine any sections Entitled ``History''
+in the various original documents, forming one section Entitled
+``History''; likewise combine any sections Entitled ``Acknowledgements'',
+and any sections Entitled ``Dedications''.  You must delete all
+sections Entitled ``Endorsements.''
+
+@item
+COLLECTIONS OF DOCUMENTS
+
+You may make a collection consisting of the Document and other documents
+released under this License, and replace the individual copies of this
+License in the various documents with a single copy that is included in
+the collection, provided that you follow the rules of this License for
+verbatim copying of each of the documents in all other respects.
+
+You may extract a single document from such a collection, and distribute
+it individually under this License, provided you insert a copy of this
+License into the extracted document, and follow this License in all
+other respects regarding verbatim copying of that document.
+
+@item
+AGGREGATION WITH INDEPENDENT WORKS
+
+A compilation of the Document or its derivatives with other separate
+and independent documents or works, in or on a volume of a storage or
+distribution medium, is called an ``aggregate'' if the copyright
+resulting from the compilation is not used to limit the legal rights
+of the compilation's users beyond what the individual works permit.
+When the Document is included in an aggregate, this License does not
+apply to the other works in the aggregate which are not themselves
+derivative works of the Document.
+
+If the Cover Text requirement of section 3 is applicable to these
+copies of the Document, then if the Document is less than one half of
+the entire aggregate, the Document's Cover Texts may be placed on
+covers that bracket the Document within the aggregate, or the
+electronic equivalent of covers if the Document is in electronic form.
+Otherwise they must appear on printed covers that bracket the whole
+aggregate.
+
+@item
+TRANSLATION
+
+Translation is considered a kind of modification, so you may
+distribute translations of the Document under the terms of section 4.
+Replacing Invariant Sections with translations requires special
+permission from their copyright holders, but you may include
+translations of some or all Invariant Sections in addition to the
+original versions of these Invariant Sections.  You may include a
+translation of this License, and all the license notices in the
+Document, and any Warranty Disclaimers, provided that you also include
+the original English version of this License and the original versions
+of those notices and disclaimers.  In case of a disagreement between
+the translation and the original version of this License or a notice
+or disclaimer, the original version will prevail.
+
+If a section in the Document is Entitled ``Acknowledgements'',
+``Dedications'', or ``History'', the requirement (section 4) to Preserve
+its Title (section 1) will typically require changing the actual
+title.
+
+@item
+TERMINATION
+
+You may not copy, modify, sublicense, or distribute the Document except
+as expressly provided for under this License.  Any other attempt to
+copy, modify, sublicense or distribute the Document is void, and will
+automatically terminate your rights under this License.  However,
+parties who have received copies, or rights, from you under this
+License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+@item
+FUTURE REVISIONS OF THIS LICENSE
+
+The Free Software Foundation may publish new, revised versions
+of the GNU Free Documentation License from time to time.  Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.  See
+@uref{http://www.gnu.org/copyleft/}.
+
+Each version of the License is given a distinguishing version number.
+If the Document specifies that a particular numbered version of this
+License ``or any later version'' applies to it, you have the option of
+following the terms and conditions either of that specified version or
+of any later version that has been published (not as a draft) by the
+Free Software Foundation.  If the Document does not specify a version
+number of this License, you may choose any version ever published (not
+as a draft) by the Free Software Foundation.
+@end enumerate
+
+@page
+@section ADDENDUM: How to use this License for your documents
+
+To use this License in a document you have written, include a copy of
+the License in the document and put the following copyright and
+license notices just after the title page:
+
+@smallexample
+@group
+  Copyright (C)  @var{year}  @var{your name}.
+  Permission is granted to copy, distribute and/or modify this document
+  under the terms of the GNU Free Documentation License, Version 1.2
+  or any later version published by the Free Software Foundation;
+  with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+  Texts.  A copy of the license is included in the section entitled ``GNU
+  Free Documentation License''.
+@end group
+@end smallexample
+
+If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
+replace the ``with...Texts.'' line with this:
+
+@smallexample
+@group
+    with the Invariant Sections being @var{list their titles}, with
+    the Front-Cover Texts being @var{list}, and with the Back-Cover Texts
+    being @var{list}.
+@end group
+@end smallexample
+
+If you have Invariant Sections without Cover Texts, or some other
+combination of the three, merge those two alternatives to suit the
+situation.
+
+If your document contains nontrivial examples of program code, we
+recommend releasing these examples in parallel under your choice of
+free software license, such as the GNU General Public License,
+to permit their use in free software.
+
+@c Local Variables:
+@c ispell-local-pdict: "ispell-dict"
+@c End:
+
diff --git a/doc/gpl.texi b/doc/gpl.texi
new file mode 100644
index 0000000..978c40d
--- /dev/null
+++ b/doc/gpl.texi
@@ -0,0 +1,725 @@
+@node Copying, The GNU FDL, Local Storage, Top
+
+@unnumbered GNU General Public License
+@center Version 3, 29 June 2007
+
+@c This file is intended to be included in another file.
+
+@display
+Copyright @copyright{} 2007 Free Software Foundation, Inc. 
@url{http://fsf.org/}
+
+Everyone is permitted to copy and distribute verbatim copies of this
+license document, but changing it is not allowed.
+@end display
+
+@unnumberedsec Preamble
+
+The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom
+to share and change all versions of a program--to make sure it remains
+free software for all its users.  We, the Free Software Foundation,
+use the GNU General Public License for most of our software; it
+applies also to any other work released this way by its authors.  You
+can apply it to your programs, too.
+
+When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you
+have certain responsibilities if you distribute copies of the
+software, or if you modify it: responsibilities to respect the freedom
+of others.
+
+For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too,
+receive or can get the source code.  And you must show them these
+terms so they know their rights.
+
+Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the
+manufacturer can do so.  This is fundamentally incompatible with the
+aim of protecting users' freedom to change the software.  The
+systematic pattern of such abuse occurs in the area of products for
+individuals to use, which is precisely where it is most unacceptable.
+Therefore, we have designed this version of the GPL to prohibit the
+practice for those products.  If such problems arise substantially in
+other domains, we stand ready to extend this provision to those
+domains in future versions of the GPL, as needed to protect the
+freedom of users.
+
+Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish
+to avoid the special danger that patents applied to a free program
+could make it effectively proprietary.  To prevent this, the GPL
+assures that patents cannot be used to render the program non-free.
+
+The precise terms and conditions for copying, distribution and
+modification follow.
+
+@iftex
+@unnumberedsec TERMS AND CONDITIONS
+@end iftex
+@ifinfo
+@center TERMS AND CONDITIONS
+@end ifinfo
+
+@enumerate 0
+@item Definitions.
+
+``This License'' refers to version 3 of the GNU General Public License.
+
+``Copyright'' also means copyright-like laws that apply to other kinds
+of works, such as semiconductor masks.
+
+``The Program'' refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as ``you''.  ``Licensees'' and
+``recipients'' may be individuals or organizations.
+
+To ``modify'' a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of
+an exact copy.  The resulting work is called a ``modified version'' of
+the earlier work or a work ``based on'' the earlier work.
+
+A ``covered work'' means either the unmodified Program or a work based
+on the Program.
+
+To ``propagate'' a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+To ``convey'' a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user
+through a computer network, with no transfer of a copy, is not
+conveying.
+
+An interactive user interface displays ``Appropriate Legal Notices'' to
+the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+@item Source Code.
+
+The ``source code'' for a work means the preferred form of the work for
+making modifications to it.  ``Object code'' means any non-source form
+of a work.
+
+A ``Standard Interface'' means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+The ``System Libraries'' of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+``Major Component'', in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+The ``Corresponding Source'' for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+The Corresponding Source need not include anything that users can
+regenerate automatically from other parts of the Corresponding Source.
+
+The Corresponding Source for a work in source code form is that same
+work.
+
+@item Basic Permissions.
+
+All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+You may make, run and propagate covered works that you do not convey,
+without conditions so long as your license otherwise remains in force.
+You may convey covered works to others for the sole purpose of having
+them make modifications exclusively for you, or provide you with
+facilities for running those works, provided that you comply with the
+terms of this License in conveying all material for which you do not
+control copyright.  Those thus making or running the covered works for
+you must do so exclusively on your behalf, under your direction and
+control, on terms that prohibit them from making any copies of your
+copyrighted material outside their relationship with you.
+
+Conveying under any other circumstances is permitted solely under the
+conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+@item Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such
+circumvention is effected by exercising rights under this License with
+respect to the covered work, and you disclaim any intention to limit
+operation or modification of the work as a means of enforcing, against
+the work's users, your or third parties' legal rights to forbid
+circumvention of technological measures.
+
+@item Conveying Verbatim Copies.
+
+You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+@item Conveying Modified Source Versions.
+
+You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these
+conditions:
+
+@enumerate a
+@item
+The work must carry prominent notices stating that you modified it,
+and giving a relevant date.
+
+@item
+The work must carry prominent notices stating that it is released
+under this License and any conditions added under section 7.  This
+requirement modifies the requirement in section 4 to ``keep intact all
+notices''.
+
+@item
+You must license the entire work, as a whole, under this License to
+anyone who comes into possession of a copy.  This License will
+therefore apply, along with any applicable section 7 additional terms,
+to the whole of the work, and all its parts, regardless of how they
+are packaged.  This License gives no permission to license the work in
+any other way, but it does not invalidate such permission if you have
+separately received it.
+
+@item
+If the work has interactive user interfaces, each must display
+Appropriate Legal Notices; however, if the Program has interactive
+interfaces that do not display Appropriate Legal Notices, your work
+need not make them do so.
+@end enumerate
+
+A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+``aggregate'' if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+@item  Conveying Non-Source Forms.
+
+You may convey a covered work in object code form under the terms of
+sections 4 and 5, provided that you also convey the machine-readable
+Corresponding Source under the terms of this License, in one of these
+ways:
+
+@enumerate a
+@item
+Convey the object code in, or embodied in, a physical product
+(including a physical distribution medium), accompanied by the
+Corresponding Source fixed on a durable physical medium customarily
+used for software interchange.
+
+@item
+Convey the object code in, or embodied in, a physical product
+(including a physical distribution medium), accompanied by a written
+offer, valid for at least three years and valid for as long as you
+offer spare parts or customer support for that product model, to give
+anyone who possesses the object code either (1) a copy of the
+Corresponding Source for all the software in the product that is
+covered by this License, on a durable physical medium customarily used
+for software interchange, for a price no more than your reasonable
+cost of physically performing this conveying of source, or (2) access
+to copy the Corresponding Source from a network server at no charge.
+
+@item
+Convey individual copies of the object code with a copy of the written
+offer to provide the Corresponding Source.  This alternative is
+allowed only occasionally and noncommercially, and only if you
+received the object code with such an offer, in accord with subsection
+6b.
+
+@item
+Convey the object code by offering access from a designated place
+(gratis or for a charge), and offer equivalent access to the
+Corresponding Source in the same way through the same place at no
+further charge.  You need not require recipients to copy the
+Corresponding Source along with the object code.  If the place to copy
+the object code is a network server, the Corresponding Source may be
+on a different server (operated by you or a third party) that supports
+equivalent copying facilities, provided you maintain clear directions
+next to the object code saying where to find the Corresponding Source.
+Regardless of what server hosts the Corresponding Source, you remain
+obligated to ensure that it is available for as long as needed to
+satisfy these requirements.
+
+@item
+Convey the object code using peer-to-peer transmission, provided you
+inform other peers where the object code and Corresponding Source of
+the work are being offered to the general public at no charge under
+subsection 6d.
+
+@end enumerate
+
+A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+A ``User Product'' is either (1) a ``consumer product'', which means any
+tangible personal property which is normally used for personal,
+family, or household purposes, or (2) anything designed or sold for
+incorporation into a dwelling.  In determining whether a product is a
+consumer product, doubtful cases shall be resolved in favor of
+coverage.  For a particular product received by a particular user,
+``normally used'' refers to a typical or common use of that class of
+product, regardless of the status of the particular user or of the way
+in which the particular user actually uses, or expects or is expected
+to use, the product.  A product is a consumer product regardless of
+whether the product has substantial commercial, industrial or
+non-consumer uses, unless such uses represent the only significant
+mode of use of the product.
+
+``Installation Information'' for a User Product means any methods,
+procedures, authorization keys, or other information required to
+install and execute modified versions of a covered work in that User
+Product from a modified version of its Corresponding Source.  The
+information must suffice to ensure that the continued functioning of
+the modified object code is in no case prevented or interfered with
+solely because modification has been made.
+
+If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or
+updates for a work that has been modified or installed by the
+recipient, or for the User Product in which it has been modified or
+installed.  Access to a network may be denied when the modification
+itself materially and adversely affects the operation of the network
+or violates the rules and protocols for communication across the
+network.
+
+Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+@item Additional Terms.
+
+``Additional permissions'' are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders
+of that material) supplement the terms of this License with terms:
+
+@enumerate a
+@item
+Disclaiming warranty or limiting liability differently from the terms
+of sections 15 and 16 of this License; or
+
+@item
+Requiring preservation of specified reasonable legal notices or author
+attributions in that material or in the Appropriate Legal Notices
+displayed by works containing it; or
+
+@item
+Prohibiting misrepresentation of the origin of that material, or
+requiring that modified versions of such material be marked in
+reasonable ways as different from the original version; or
+
+@item
+Limiting the use for publicity purposes of names of licensors or
+authors of the material; or
+
+@item
+Declining to grant rights under trademark law for use of some trade
+names, trademarks, or service marks; or
+
+@item
+Requiring indemnification of licensors and authors of that material by
+anyone who conveys the material (or modified versions of it) with
+contractual assumptions of liability to the recipient, for any
+liability that these contractual assumptions directly impose on those
+licensors and authors.
+@end enumerate
+
+All other non-permissive additional terms are considered ``further
+restrictions'' within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions; the
+above requirements apply either way.
+
+@item Termination.
+
+You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+However, if you cease all violation of this License, then your license
+from a particular copyright holder is reinstated (a) provisionally,
+unless and until the copyright holder explicitly and finally
+terminates your license, and (b) permanently, if the copyright holder
+fails to notify you of the violation by some reasonable means prior to
+60 days after the cessation.
+
+Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+@item Acceptance Not Required for Having Copies.
+
+You are not required to accept this License in order to receive or run
+a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+@item Automatic Licensing of Downstream Recipients.
+
+Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+An ``entity transaction'' is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+@item Patents.
+
+A ``contributor'' is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's ``contributor version''.
+
+A contributor's ``essential patent claims'' are all patent claims owned
+or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, ``control'' includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+In the following three paragraphs, a ``patent license'' is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To ``grant'' such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  ``Knowingly relying'' means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+A patent license is ``discriminatory'' if it does not include within the
+scope of its coverage, prohibits the exercise of, or is conditioned on
+the non-exercise of one or more of the rights that are specifically
+granted under this License.  You may not convey a covered work if you
+are a party to an arrangement with a third party that is in the
+business of distributing software, under which you make payment to the
+third party based on the extent of your activity of conveying the
+work, and under which the third party grants, to any of the parties
+who would receive the covered work from you, a discriminatory patent
+license (a) in connection with copies of the covered work conveyed by
+you (or copies made from those copies), or (b) primarily for and in
+connection with specific products or compilations that contain the
+covered work, unless you entered into that arrangement, or that patent
+license was granted, prior to 28 March 2007.
+
+Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+@item No Surrender of Others' Freedom.
+
+If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey
+a covered work so as to satisfy simultaneously your obligations under
+this License and any other pertinent obligations, then as a
+consequence you may not convey it at all.  For example, if you agree
+to terms that obligate you to collect a royalty for further conveying
+from those to whom you convey the Program, the only way you could
+satisfy both those terms and this License would be to refrain entirely
+from conveying the Program.
+
+@item Use with the GNU Affero General Public License.
+
+Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+@item Revised Versions of this License.
+
+The Free Software Foundation may publish revised and/or new versions
+of the GNU General Public License from time to time.  Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies that a certain numbered version of the GNU General Public
+License ``or any later version'' applies to it, you have the option of
+following the terms and conditions either of that numbered version or
+of any later version published by the Free Software Foundation.  If
+the Program does not specify a version number of the GNU General
+Public License, you may choose any version ever published by the Free
+Software Foundation.
+
+If the Program specifies that a proxy can decide which future versions
+of the GNU General Public License can be used, that proxy's public
+statement of acceptance of a version permanently authorizes you to
+choose that version for the Program.
+
+Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+@item Disclaimer of Warranty.
+
+THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM ``AS IS'' WITHOUT
+WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE PROGRAM PROVE
+DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
+CORRECTION.
+
+@item Limitation of Liability.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR
+CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT
+NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR
+LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM
+TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER
+PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+@item Interpretation of Sections 15 and 16.
+
+If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+@iftex
+@heading END OF TERMS AND CONDITIONS
+@end iftex
+@ifinfo
+@center END OF TERMS AND CONDITIONS
+@end ifinfo
+@unnumberedsec How to Apply These Terms to Your New Programs
+
+If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the ``copyright'' line and a pointer to where the full notice is found.
+@smallexample
+@var{one line to give the program's name and a brief idea of what it does.}
+Copyright (C) @var{year} @var{name of author}
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see @url{http://www.gnu.org/licenses/}.
+@end smallexample
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+@smallexample
+@var{program} Copyright (C) @var{year} @var{name of author}
+This program comes with ABSOLUTELY NO WARRANTY; for details type @samp{show w}.
+This is free software, and you are welcome to redistribute it under certain 
conditions; type @samp{show c} for details.
+@end smallexample
+
+The hypothetical commands @samp{show w} and @samp{show c} should show
+the appropriate parts of the General Public License.  Of course, your
+program's commands might be different; for a GUI interface, you would
+use an ``about box''.
+
+You should also get your employer (if you work as a programmer) or school,
+if any, to sign a ``copyright disclaimer'' for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+@url{http://www.gnu.org/licenses/}.
+
+The GNU General Public License does not permit incorporating your
+program into proprietary programs.  If your program is a subroutine
+library, you may consider it more useful to permit linking proprietary
+applications with the library.  If this is what you want to do, use
+the GNU Lesser General Public License instead of this License.  But
+first, please read @url{http://www.gnu.org/philosophy/why-not-lgpl.html}.
+
+@end enumerate
diff --git a/doc/rt-liberation.texinfo b/doc/rt-liberation.texinfo
new file mode 100644
index 0000000..59af59a
--- /dev/null
+++ b/doc/rt-liberation.texinfo
@@ -0,0 +1,1006 @@
+\input texinfo   @c -*-texinfo-*-
+@c %**start of header
+@setfilename rt-liberation.info
+@settitle The rt-liberation Manual
+@c %**end of header
+
+@c History: This manual was started on the 6th of April 2009.
+
+@dircategory Emacs
+@direntry
+* rt-liberation: (rt-liber).           rt-liberation
+@end direntry
+
+
+@copying
+ @copyright{} 2009
+   Yoni Rabkin yonirabkin@@member.fsf.org
+@quotation
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.1 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A
+copy of the license is included in the section entitled ``GNU Free
+Documentation License''.
+@end quotation
+@end copying
+
+
+@c For printed material
+@titlepage
+@title The rt-liberation Manual
+@page
+@vskip 0pt plus 1filll
+@insertcopying
+@end titlepage
+@contents
+@c END For printed material
+
+
+@ifnottex
+@node Top, Introduction, (dir), (dir)
+@top The rt-liberation Manual
+
+This is the Manual for the rt-liberation system
+
+@insertcopying
+
+@menu
+* Introduction::                Introduction to rt-liberation.
+* Dependencies::                Before you can use rt-liberation.
+* Installation::                Setup rt-liberation to work on the system.
+
+Using rt-liberation
+* Queries::                     Retrieve particular tickets from the server.
+* Ticket Browser::              Browse the query results.
+* Ticket Viewer::               Interface to query results.
+
+Extensions
+* Gnus Integration::            Sending email to the RT server via Gnus.
+* Tracking Updates::            Keeping up to date with ticket changes.
+* Batch Operations::            Performing operations on batches of tickets.
+* Local Storage::               Associate arbitrary data with tickets.
+
+Copying and license
+* Copying::                     The GNU General Public License gives you
+                               permission to redistribute rt-liberation
+                               on certain terms; it also explains that
+                               there is no warranty.
+
+* The GNU FDL::                 The license for this documentation.
+
+Indices
+* Concept Index::
+* Function Index::
+* Variable Index::
+* Keybinding Index::
+
+@detailmenu
+ --- The Detailed Node Listing ---
+
+Queries
+
+* Query Compiler::              Compiling Emacs Lisp to TicketSQL.
+* Query Language::              A description of the Sexp-based language.
+
+Ticket Browser
+
+* Ticket Browser Display::      How tickets are displayed in the browser.
+* Ticket Browser Sorting::      How tickets are sorted in the browser.
+* Ticket Browser Filtering::    How to filter tickets out of the browser.
+* Mutliple Ticket Browsers::    More than one ticket browser buffer.
+
+@end detailmenu
+@end menu
+
+@end ifnottex
+
+
+
+
+
+@c --------------------------------------------------
+
+@node Introduction
+@chapter Introduction
+
+@cindex introduction
+
+rt-liberation is a GNU/Emacs package for working with the Request
+Tracker (henceforth abbreviated as just ``RT'') software from Best
+Practical Solutions. RT has a Web interface and a command line
+interface (the ``RT CLI''). rt-liberation uses the RT CLI as a backend
+to communicate to the server.
+
+rt-liberation allows sending search queries to the RT server, browsing
+the resulting tickets, viewing the tickets' contents and performing
+operations on the ticket.
+
+
+
+
+
+@c --------------------------------------------------
+
+@node Dependencies
+@chapter Dependencies
+
+@cindex dependencies
+
+rt-liberation has been tested exclusively on GNU/Emacs, with very
+recent versions.
+
+Since rt-liberation uses the command line interface as a backend to
+communicate with the RT server it will need a local copy of the RT
+software on the machine running rt-liberation. RT is available at
+@uref{http://bestpractical.com/rt/download.html}
+
+At the time of writing the recommended version of RT to use as a
+backend for rt-liberation is 3.8.2. Version 3.8.2 will provide
+shorter response times and less calls out to the server.
+
+Please check that the RT CLI runs from the shell and can communicate
+with the server in question. If that doesn't work neither will
+rt-liberation.
+
+
+
+
+
+@c --------------------------------------------------
+
+@node Installation
+@chapter Installation
+
+@cindex installation
+
+rt-liberation can be configured in the ~/.emacs file.
+
+Place rt-liberation in the load path:
+
+@lisp
+(add-to-list 'load-path "/PATH/TO/rt-liberation/")
+@end lisp
+
+Tell GNU/Emacs to load the package with:
+
+@lisp
+(require 'rt-liberation)
+@end lisp
+
+Tell rt-liberation where to find the RT binary and which version is
+being used, for example:
+
+@lisp
+(setq rt-liber-rt-binary "~/src/rt-3.8.2/bin/rt"
+      rt-liber-rt-version "3.8.8")
+@end lisp
+
+rt-liberation can issue a command to ``take'' a ticket, that is,
+assign it to yourself. For this the variable @var{rt-liber-username}
+must be set:
+
+@lisp
+(setq rt-liber-username "someuser")
+@end lisp
+
+rt-liberation can also launch a Web browser to visit a ticket. For
+that to work the base URL needs to be set in
+@var{rt-liber-base-url}. For example:
+
+(setq rt-liber-base-url "https://rt.foo.org/";)
+
+@c --------------------------------------------------
+
+@node Queries
+@chapter Queries
+
+@cindex queries
+
+A typical RT server is meant to manage a large amount of tickets. Much
+more that would be convenient to view all at once. Instead queries are
+used to view only a subset of the tickets on the server.
+
+rt-liberation has its own Sexp-based query language which maps to RT's
+TicketSQL language.
+
+@menu
+* Query Compiler::              Compiling Emacs Lisp to TicketSQL.
+* Query Language::              A description of the Sexp-based language.
+@end menu
+
+
+
+
+
+@c --------------------------------------------------
+
+@node Query Compiler
+@section Query Compiler
+
+@cindex query compiler
+
+In order to browse and view tickets a list of needs to be requested
+from the RT server. Typically the tickets answer some kind of
+criteria, for example ``tickets no older than a week owned by me which
+have \``foobar\'' in their subject line''. In RT these criteria are
+formulated with ``TicketSQL'' queries; a structured query language
+specific to RT.
+
+rt-liberation provides a query compiler function to compile Emacs Lisp
+symbolic expressions into TicketSQL. The query compiler supports a
+number of TicketSQL tokens.
+
+
+
+
+
+@c --------------------------------------------------
+
+@node Query Language
+@section Query Language
+
+@cindex query language
+
+rt-liberation's Sexp-based query language covers a portion of the
+TicketSQL language. Here are some of the supported TicketSQL tokens:
+Boolean tokens as a means of combining query subsections: ``and'', ``or'',
+``not''. LIKE attribute tokens: ``subject'', ``content''.
+
+For example here is a query with both Boolean and LIKE tokens:
+
+@lisp
+(rt-liber-compile-query
+    (and (queue "bugs")
+        (content "gnu")))
+
+==> "Queue = 'bugs' AND Content LIKE 'gnu'"
+@end lisp
+
+We can also express negation (note that the compiler produces "!=" and
+"NOT LIKE" for negation depending on the context):
+
+@lisp
+(rt-liber-compile-query
+ (and (queue "bugs")
+      (not (owner "Nobody"))
+      (not (content "sprigz"))
+      (status "new")))
+
+==> "Queue = 'licensing' AND Owner != 'Nobody' \
+    AND Content NOT LIKE 'sprigz' AND Status = 'new'"
+@end lisp
+
+Attribute tokens which match an attribute to a specific field such as:
+``owner'', ``status'' and ``queue''. Temporal tokens which limit the search
+results to tickets within a certain time interval: ``created'' and
+``lastupdated''. Note that temporal keywords such as ``created'' always
+accept two arguments: BEFORE and AFTER. When either BEFORE or AFTER
+aren't needed, use NIL instead.
+
+One of the advantages of being able to express the TicketSQL queries
+as Emacs Lisp is to be able to express queries using Emacs Lisp
+functions.
+
+Here is a slightly more involved example to illustrate:
+
+@lisp
+(rt-liber-compile-query
+ (and (queue "bugs")
+      (owner "me@@myaddress.com")
+      (status "open")
+      (lastupdated nil
+                  (format-time-string
+                    "%Y-%m-%d"
+                    (seconds-to-time
+                     (- (time-to-seconds (current-time))
+                        (* 60 60 24 7)))))))
+
+==> "Queue = 'bugs' AND Owner = 'me@@myaddress.com' AND Status = 'open' AND 
LastUpdated > '2009-03-30'"
+@end lisp
+
+
+Here is an example of how the ticket browser and compiler can be used
+in function calls:
+
+@lisp
+(defun rt-liber-display-ticket (ticket-id)
+  "Display ticket with TICKET-ID in the ticket-browser."
+  (interactive "MTicket ID: ")
+  (rt-liber-browse-query
+   (rt-liber-compile-query
+    (and (queue "complaints")
+        (id ticket-id)))))
+@end lisp
+
+
+
+
+@c --------------------------------------------------
+
+@node Ticket Browser
+@chapter Ticket Browser
+
+@cindex ticket browser
+
+The ticket browser is a special buffer which provides a convenient
+interface to the results of a server query. The ticket browser can be
+started by invoking: (rt-liber-browse-query QUERY), where QUERY is a
+TicketSQL query. The TicketSQL query can be entered manually as a
+string or as the return value of the query compiler.
+
+@deffn Function rt-liber-browse-query QUERY &optional NEW
+Runs QUERY against the server and launches the browser.
+
+If NEW is non-nil then the query results will be displayed in a new
+buffer, otherwise the query results will override the contents of the
+existing ticket browser buffer. If NEW is a string then that will be
+the name of the new buffer.
+@end deffn
+
+The TicketSQL query can be the return value of the query compiler. For
+example:
+
+@lisp
+(rt-liber-browse-query
+ (rt-liber-compile-query
+     (and (queue "bugs")
+         (content "gnu")))
+@end lisp
+
+
+Sine the return value of the query compiler is just a TicketSQL
+string, the following is equivalent:
+
+@lisp
+(rt-liber-browse-query "Queue = 'bugs' AND Content LIKE 'gnu'")
+@end lisp
+
+The ticket browser defines a number of commands:
+
+@table @kbd
+@item q
+@kindex q (ticket browser)
+@findex rt-liber-browser-mode-quit
+Bury the ticket browser buffer.
+
+@item n
+@kindex n (ticket browser)
+@findex rt-liber-next-ticket-in-browser
+Move point to the next ticket.
+
+@item p
+@kindex p (ticket browser)
+@findex rt-liber-previous-ticket-in-browser
+Move point to the previous ticket.
+
+@item RET
+@kindex RET (ticket browser)
+@findex rt-liber-display-ticket-at-point
+Visit the ticket at point in the @xref{Ticket Viewer}.
+
+@item g
+@kindex g (ticket browser)
+@findex revert-buffer
+Refresh the contents of the browser buffer.
+
+@item G
+@kindex G (ticket browser)
+@findex rt-liber-browser-refresh-and-return
+Refresh the contents of the browser buffer. Return point to the
+current ticket after the refresh (if possible).
+
+@item s
+@kindex s (ticket browser)
+@findex rt-liber-browser-mark-as-spam
+Mark the ticket as spam.
+
+@item S
+@kindex S (ticket browser)
+@findex rt-liber-multi-delete-spam
+Delete marked tickets as spam (requires rt-liberation-multi package).
+
+@item a
+@kindex a (ticket browser)
+@findex rt-liber-browser-assign
+Assign the ticket to a user.
+
+@item r
+@kindex r (ticket browser)
+@findex rt-liber-browser-resolve
+Mark the ticket as ``resolved''.
+
+@item o
+@kindex o (ticket browser)
+@findex rt-liber-browser-open
+Mark the ticket as ``open''.
+
+@item t
+@kindex t (ticket browser)
+@findex rt-liber-browser-take-ticket-at-point
+Assign the ticket at point to @var{rt-liber-username}.
+
+@item SPC
+@kindex SPC (ticket browser)
+@findex scroll-up
+Scroll the text of the ticket browser upward.
+
+@item DEL
+@kindex DEL (ticket browser)
+@findex scroll-down
+Scroll the text of the ticket browser downward.
+
+@item m
+@kindex m (ticket browser)
+@findex rt-liber-browser-move
+Move the ticket to a different queue.
+
+@end table
+
+@menu
+* Ticket Browser Display::      How tickets are displayed in the browser.
+* Ticket Browser Sorting::      How tickets are sorted in the browser.
+* Ticket Browser Filtering::    How to filter tickets out of the browser.
+* Mutliple Ticket Browsers::    More than one ticket browser buffer.
+@end menu
+
+
+
+
+
+@c --------------------------------------------------
+
+@node Ticket Browser Display
+@section Ticket Browser Display
+
+@cindex ticket browser display function
+
+The ticket browser displays the tickets in the browser by calling
+@dfn{rt-liber-ticketlist-browser-redraw-f} which can be changed and
+customized. Any implementation of
+@dfn{rt-liber-ticketlist-browser-redraw-f} must leave point at the end
+of the ticket text.
+
+The ticket data itself can be displayed using rt-liberation ticket
+format string %-sequences:
+
+@table @asis
+@item %i
+ID number of the ticket in the RT database.
+@item %s
+Subject line.
+@item %c
+Ticket creation time.
+@item %S
+Ticket status (``open'', ``new'' etc.)
+@item %r
+Whether the ticket is resolved.
+@item %R
+Requestor/s
+@item %C
+Creator of the ticket.
+@item %o
+Owner of the ticket.
+@item %q
+The queue originating the ticket.
+@end table
+
+Here is an example implementation of
+@dfn{rt-liber-ticketlist-browser-redraw-f} showing the use of the
+%-sequences. Note the use of text properties to add color to ticket
+text. The use of text properties as opposed to font-locking is meant
+to ease customization because otherwise any change in ticket display
+would break the font-locking regular expressions.
+
+@lisp
+(defun rt-liber-ticketlist-browser-redraw-f (ticket)
+  "Display TICKET."
+  (insert (rt-liber-format "[%c] %i" ticket))
+  (add-text-properties (point-at-bol)
+                      (point-at-eol)
+                      '(face rt-liber-ticket-face))
+  (newline)
+  (insert (rt-liber-format "    [%S] %s" ticket))
+  (newline)
+  (insert (rt-liber-format "    %o <== %R" ticket)))
+@end lisp
+
+
+
+
+
+
+@c --------------------------------------------------
+
+@node Ticket Browser Sorting
+@section Ticket Browser Sorting
+
+@cindex ticket browser sorting
+
+The tickets in the browser are displayed by default in reverse
+chronological order. Ticket sorting is done by a call to
+@dfn{rt-liber-browser-default-sorting-function}.
+
+Other sorting orders can be used by binding
+@dfn{rt-liber-browser-default-sorting-function} to a different
+function. To ease writing such functions rt-liberation provides two
+predicate functions to perform comparisons between ticket objects:
+
+@defun rt-liber-lex-lessthan-p a b field
+Return true if A is lexicographically less than B in FIELD.
+
+Here is an example of sorting tickets lexicographically by owner name
+using @dfn{rt-liber-lex-lessthan-p} (note that you can feed
+@dfn{rt-liber-lex-lessthan-p} a date/time string and it will sort it
+just fine except that it wouldn't make any sense):
+
+@lisp
+(defun rt-liber-sort-by-owner (ticket-list)
+  "Sort TICKET-LIST lexicographically by owner."
+  (rt-liber-sort-ticket-list
+   ticket-list
+   #'(lambda (a b)
+       (rt-liber-lex-lessthan-p a b "Owner"))))
+@end lisp
+
+@end defun
+
+@defun rt-liber-time-lessthan-p a b field
+Return t if A is chronologically less than B in FIELD.
+
+Here is an example of sorting tickets lexicographically by owner name
+using @dfn{rt-liber-time-lessthan-p} (note that feeding
+@dfn{rt-liber-time-lessthan-p} anything but a date/time string, in
+this case ``Created'' contains a date, will result in an error being
+signaled).
+
+@lisp
+(defun rt-liber-sort-by-time-created (ticket-list)
+  "Sort TICKET-LIST in reverse chronological order."
+  (reverse
+   (rt-liber-sort-ticket-list
+    ticket-list
+    #'(lambda (a b)
+       (rt-liber-time-lessthan-p a b "Created")))))
+@end lisp
+
+@end defun
+
+@c -------------------------------------------------------------------
+
+@node Ticket Browser Filtering
+@section Ticket Browser Filtering
+
+@cindex ticket browser filtering filter
+
+The Ticket Browser can also filter out (that is, not display) certain
+tickets based on particular criteria. This probably shouldn't be used
+instead of a properly formed RT query, but when used in conjunction
+with correctly formulated queries it becomes a powerful tool.
+
+During ticket display processing the Ticket Browser will call the
+function pointed to by @var{rt-liber-browser-default-filter-function}
+on each ticket, passing the function the ticket alist as a single
+argument. The function is set by default to
+@dfn{rt-liber-default-filter-f}, which is a function which will
+display all tickets and filter none.
+
+If any tickets are filtered, the Ticket Browser will display the
+filtered ticket count at the bottom ticket listing.
+
+Here is a simple example of how to filter out all of the tickets which
+have a status of ``deleted''.
+
+First we define a custom filter function. Note how it accepts a single
+argument, which is the ticket alist, and returns nil if the ticket is
+to be filtered.
+
+@lisp
+(defun rt-liber-browser-deleted-filter (ticket)
+  (not
+   (and ticket
+       (string= (cdr (assoc "Status" ticket))
+                "deleted"))))
+@end lisp
+
+Then we assign that function to be our default filtering function:
+
+@lisp
+(setq rt-liber-browser-default-filter-function
+      'rt-liber-browser-deleted-filter)
+@end lisp
+
+@c -------------------------------------------------------------------
+
+
+@node Mutliple Ticket Browsers
+@section Mutliple Ticket Browsers
+
+@cindex ticket browser multiple buffer
+
+It is sometimes useful to rename the ticket browser buffer to
+something more informative than the default
+@var{rt-liber-browser-buffer-name}, especially if there are multiple
+ticket browsers.
+
+Changing a ticket browser's name can be done normally with
+`rename-buffer', but it is also possible to name the ticket browser
+when it is created. In the following example two ticket browser
+buffers will be created displaying the query results and named
+``*updated by supervisor*'' and ``*new tickets*'' respectively:
+
+@lisp
+(defun rt-liber-daily-rounds ()
+  (interactive)
+
+  (rt-liber-browse-query
+   (rt-liber-compile-query
+    (and (queue "complaints")
+        (owner "lem.e.tweakit")
+        (status "open")
+        (lastupdatedby "molly.manager")))
+   "*updated by supervisor*")
+
+  (rt-liber-browse-query
+   (rt-liber-compile-query
+    (and (queue "complaints")
+        (owner "Nobody")
+        (status "new")))
+   "*new tickets*"))
+@end lisp
+
+
+
+
+
+@c --------------------------------------------------
+
+@node Ticket Viewer
+@chapter Ticket Viewer
+
+@cindex ticket viewer
+
+The ticket viewer is an interface for viewing the contents of a
+ticket. It provides font-locking to make reading the contents easier
+via @var{rt-liber-viewer-font-lock-keywords} and a number of
+key-bindings.
+
+The ticket viewer provides key-bindings to help compose emails to send
+to the RT email interface. The key-bindings for composing email
+described below are generic, what actually happens when you invoke
+them depends on the email-backend system you have installed into
+rt-liberation. @file{rt-liberation-gnus.el} provides integrations with
+Gnus, @xref{Gnus Integration}.
+
+Setting @var{rt-liber-jump-to-latest} to `t' will cause the viewer to
+automatically scroll to the latest comment in a ticket when that
+ticket is visited. By default @var{rt-liber-jump-to-latest} is set to
+`nil'.
+
+When in the ticket viewer buffer, invoking
+@dfn{rt-liber-viewer-take-ticket} will ``take'' the ticket.
+
+@table @kbd
+
+@item q
+@kindex q (ticket viewer)
+@findex rt-liber-viewer-mode-quit
+Bury the ticket viewer buffer.
+
+@item n
+@kindex n (ticket viewer)
+@findex rt-liber-next-section-in-viewer
+Move point to the next section in ticket.
+
+@item N
+@kindex N (ticket viewer)
+@findex rt-liber-jump-to-latest-correspondence
+Move point to the newest correspondence section, if any.
+
+@item p
+@kindex p (ticket viewer)
+@findex rt-liber-previous-section-in-viewer
+Move point to the previous section in ticket.
+
+@item V
+@kindex V (ticket viewer)
+@findex rt-liber-viewer-visit-in-browser
+Visit the current ticket in a Web browser.
+
+@item m
+@kindex m (ticket viewer)
+@findex rt-liber-viewer-answer
+Compose an answer to the current ticket.
+
+@item M
+@kindex M (ticket viewer)
+@findex rt-liber-viewer-answer-this
+Compose an answer to the current ticket. The content section around
+point will be inserted into the email body and commented out.
+
+@item t
+@kindex t (ticket viewer)
+@findex rt-liber-viewer-answer-provisionally
+Compose a provisional answer to the current ticket.
+
+@item T
+@kindex t (ticket viewer)
+@findex rt-liber-viewer-answer-provisionally-this
+Compose a provisional answer to the current ticket. The content
+section around point will be inserted into the email body and
+commented out.
+
+@item F
+@kindex F (ticket viewer)
+@findex rt-liber-viewer-answer-verbatim-this
+Compose an answer to the current ticket. The content section around
+point will be inserted into the email body verbatim.
+
+@item c
+@kindex c (ticket viewer)
+@findex rt-liber-viewer-comment
+Compose a comment for the current ticket.
+
+@item C
+@kindex C (ticket viewer)
+@findex rt-liber-viewer-comment-this
+Comment on the ticket using the current context
+
+@item g
+@kindex g (ticket viewer)
+@findex revert-buffer
+Refresh and redisplay the current ticket.
+
+@item SPC
+@kindex SPC (ticket viewer)
+@findex scroll-up
+Scroll text of ticket viewer upward.
+
+@item DEL
+@kindex DEL (ticket viewer)
+@findex scroll-down
+Scroll text of ticket viewer downward.
+
+@item h
+@kindex h (ticket viewer)
+@findex rt-liber-viewer-show-ticket-browser
+Display the associated ticket in the ticket browser.
+
+@end table
+
+
+
+
+
+@c --------------------------------------------------
+
+@node Gnus Integration
+@chapter Gnus Integration
+
+@cindex Gnus Integration
+
+The file @file{rt-liberation-gnus.el} implements integration with Gnus
+for composing emails. To enable the feature, `require' it after
+loading rt-liberation:
+
+@lisp
+(require 'rt-liberation-gnus)
+@end lisp
+
+In order for rt-liberation-gnus to be useful a few variables need to
+be specialized. The following is example code which sets these
+variables followed by a more thorough description of the variables:
+
+@lisp
+(setq rt-liber-gnus-comment-address "our-rtserver-comment@@ourserver.org"
+      rt-liber-gnus-address         "our-rtserver@@ourserver.org"
+      rt-liber-gnus-subject-name    "ourserver.org"
+      rt-liber-gnus-answer-headers  '(("Gcc" . "nnml:Send-Mail")
+                                     ("X-Ethics" . "Use GNU"))
+      rt-liber-gnus-signature       "Kind Regards")
+@end lisp
+
+@defopt
+@var{rt-liber-gnus-address} is the email address which is configured
+in the RT server email interface for sending a response to the
+ticket's requestor.
+@end defopt
+@defopt
+@var{rt-liber-gnus-comment-address} is the email address which is
+configured in the RT server email interface for adding a comment under
+the ticket in question.
+@end defopt
+@defopt
+@var{rt-liber-gnus-subject-name} is a string, typically included at
+the beginning of the square brackets in the subject. The string is a
+part of the subject line which helps the RT server recognize the
+email.
+@end defopt
+@defopt
+@var{rt-liber-gnus-answer-headers} defines a list of dotted-pairs
+containing the header name and value for additional email headers.
+@end defopt
+@defopt
+A signature can be added automatically to the end of the email by
+setting @var{rt-liber-gnus-signature} to be some text. It is useful to
+include newlines in this text to make the signature format nicely.
+@end defopt
+
+Once rt-liberation-gnus is loaded and customized the key-bindings in
+the Viewer will be able to call into it, @xref{Ticket Viewer}.
+
+
+
+
+
+@c --------------------------------------------------
+
+@node Tracking Updates
+@chapter Tracking Updates
+
+@cindex Tracking Updates
+
+The functions in @file{rt-liberation-update.el} help keep up with
+updates to the ticket database. To enable the feature, `require' it
+after loading rt-liberation:
+
+@lisp
+(require 'rt-liberation-update)
+@end lisp
+
+Then set @var{rt-liber-update-default-queue} to be the name of the
+queue to watch for updates. For example:
+
+@lisp
+(setq rt-liber-update-default-queue "complaints")
+@end lisp
+
+@defun rt-liber-update &optional no-update
+@code{rt-liber-update} is an interactive function which runs a query
+against the RT server asking for the tickets which have been updated
+since the time @code{rt-liber-update} was last run (each time it runs,
+it leaves a time-stamp). If no time-stamp is found, for instance when
+you run @code{rt-liber-update} for the first time, today's date is
+used.
+
+With the NO-UPDATE prefix, @code{rt-liber-update} will not update the
+time-stamp so that the next invocation will produce the same result.
+@end defun
+
+
+
+
+@c --------------------------------------------------
+
+@node Batch Operations
+@chapter Batch Operations
+
+@cindex Batch Operations
+
+The extension @file{rt-liberation-multi.el} implements performing
+batch operations on groups of tickets. It works in two stages: First
+mark an arbitrary number of tickets within the same buffer then call a
+batch operation function on them. The batch operation functions work
+the same way as function which work on single tickets only that they
+iterate through all of the marked tickets.
+
+To enable batch operations first load @file{rt-liberation-multi.el}:
+
+@lisp
+(require 'rt-liberation-storage)
+@end lisp
+
+@table @kbd
+@item M
+@kindex M (ticket browser)
+@findex rt-liber-mark-ticket-at-point
+Mark the ticket at point for future action. If the ticket at point is
+already marked then unmark it.
+@end table
+
+@defun rt-liber-multi-set-status-open
+Set the status of all the marked tickets to ``open''.
+@end defun
+
+@defun rt-liber-multi-set-status-resolved
+Set the status of all the marked tickets to ``resolved.
+@end defun
+
+@defun rt-liber-multi-assign name
+Assign all of the marked tickets to NAME.
+@end defun
+
+@defun rt-liber-multi-flag-as-spam-and-delete
+Set the status of all the marked tickets to ``is-spam'' and delete.
+@end defun
+
+
+
+
+
+@c --------------------------------------------------
+
+@node Local Storage
+@chapter Local Storage
+
+@cindex Local Storage
+
+@file{rt-liberation-storage.el} implements associating arbitrary
+ancillary data with tickets. The data is stored locally and is not
+sent to the RT server.
+
+To enable local storage first load @file{rt-liberation-storage.el}:
+
+@lisp
+(require 'rt-liberation-storage)
+@end lisp
+
+Then enable the display of ancillary data with:
+
+@lisp
+(setq rt-liber-anc-p t)
+@end lisp
+
+The associated data is edited and displayed in the ticket browser with
+the following command key:
+
+@table @kbd
+@item A
+@kindex A (ticket browser)
+@findex rt-liber-browser-ancillary-text
+Associate text with the ticket at point. You will be prompted to enter
+a string of text.
+@end table
+
+Once text is associated with a ticket it will be displayed alongside
+that ticket in the ticket browser. This particular feature lends
+itself to creating private annotations about tickets.
+
+The implementation distributed with rt-liberation allows associating
+text with tickets but is not limited to text. The same implementation
+can be extended to associate any arbitrary data with any ticket.
+
+
+@c including the relevant licenses
+@include gpl.texi
+@include fdl.texi
+
+
+
+
+
+@c --------------------------------------------------
+
+@node Concept Index
+@unnumbered Concept Index
+@printindex cp
+
+
+
+
+@c --------------------------------------------------
+
+@node Function Index
+@unnumbered Function Index
+@printindex fn
+
+
+
+
+@c --------------------------------------------------
+
+@node Variable Index
+@unnumbered Variable Index
+@printindex vr
+
+
+
+
+@c --------------------------------------------------
+
+@node Keybinding Index
+@unnumbered Keybinding Index
+@printindex ky
+
+
+@bye
diff --git a/etc/logo/rt-liberation-logo.svg b/etc/logo/rt-liberation-logo.svg
new file mode 100644
index 0000000..6469400
--- /dev/null
+++ b/etc/logo/rt-liberation-logo.svg
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:cc="http://creativecommons.org/ns#";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:svg="http://www.w3.org/2000/svg";
+   xmlns="http://www.w3.org/2000/svg";
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd";
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape";
+   width="284.81235"
+   height="415.33957"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.48.3.1 r9886"
+   version="1.0"
+   sodipodi:docname="ryanlerch_Frigate_Bird.svg">
+  <defs
+     id="defs4" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1"
+     inkscape:cx="375"
+     inkscape:cy="240"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     inkscape:window-width="1280"
+     inkscape:window-height="781"
+     inkscape:window-x="0"
+     inkscape:window-y="19"
+     showgrid="false"
+     inkscape:window-maximized="0" />
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-93.47337,-145.6075)">
+    <path
+       style="fill:black"
+       d="M 168.91356,560.29545 C 167.95106,557.23004 167.1227,553.2316 
163.81184,535.66978 C 161.92548,525.66397 159.25316,514.18897 
157.87334,510.16978 C 155.6466,503.68366 154.92687,500.47434 
153.96862,492.75839 C 153.82492,491.60132 152.9593,489.51295 
152.04501,488.11758 C 151.13073,486.72221 149.43433,482.49391 
148.27523,478.72136 C 147.11613,474.9488 145.30564,469.16217 
144.25193,465.86217 C 140.87188,455.27661 139.28745,444.40281 
139.70635,434.66627 C 140.16918,423.90874 142.11743 [...]
+       id="path1886" />
+    <text
+       xml:space="preserve"
+       
style="font-size:154.69360352px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Monospace;-inkscape-font-specification:Monospace"
+       x="218.06105"
+       y="524.17487"
+       id="text3067"
+       sodipodi:linespacing="125%"
+       transform="scale(0.93947057,1.0644293)"><tspan
+         sodipodi:role="line"
+         id="tspan3069"
+         x="218.06105"
+         y="524.17487">RT</tspan></text>
+  </g>
+  <metadata
+     id="metadata3065">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/"; />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/";>
+            <dc:title>Open Clip Art Library</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title></dc:title>
+        <dc:date>2006-12-14T21:25:31</dc:date>
+        <dc:description>a frigate bird</dc:description>
+        
<dc:source>http://openclipart.org/detail/2101/frigate-bird-by-ryanlerch</dc:source>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>ryanlerch</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>bird</rdf:li>
+            <rdf:li>bird</rdf:li>
+            <rdf:li>clip art</rdf:li>
+            <rdf:li>clipart</rdf:li>
+            <rdf:li>fregatidae</rdf:li>
+            <rdf:li>fregatidae</rdf:li>
+            <rdf:li>frigate</rdf:li>
+            <rdf:li>frigate</rdf:li>
+            <rdf:li>frigate bird</rdf:li>
+            <rdf:li>frigate bird</rdf:li>
+            <rdf:li>fws</rdf:li>
+            <rdf:li>fws</rdf:li>
+            <rdf:li>fws lineart</rdf:li>
+            <rdf:li>fws lineart</rdf:li>
+            <rdf:li>image</rdf:li>
+            <rdf:li>line art</rdf:li>
+            <rdf:li>line art</rdf:li>
+            <rdf:li>media</rdf:li>
+            <rdf:li>png</rdf:li>
+            <rdf:li>public domain</rdf:li>
+            <rdf:li>remix</rdf:li>
+            <rdf:li>svg</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/";>
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction"; />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution"; />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks"; />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+</svg>
diff --git a/etc/rt-dot-el-design b/etc/rt-dot-el-design
new file mode 100644
index 0000000..01cc3c2
--- /dev/null
+++ b/etc/rt-dot-el-design
@@ -0,0 +1,60 @@
+-*- outline -*-
+
+This document outlines *a* design concept for an RT mode for
+GNU/Emacs.
+
+** Functional modules
+
+* Module "TicketSQL compiler": Symbolic expression domain specific 
+  language to TicketSQL query compiler. Accept as input a sexp
+  representing a query and output a query in TicketSQL format. For
+  example: [(:and (:owner "Ben Bitdiddle") (:status "open"))] =>
+  ["Owner='Ben Bitdiddle' and Status='open'"].
+
+* Module "TicketSQL runner": Run a TicketSQL query against the server
+  and return the result. Accept as input a TicketSQL query and return
+  a list of ticket-id ticket-subject pairs or nil if no matches were
+  found.
+
+* Module "ticket retriever": Retrieve all of the data related to a
+  particular ticket. Accept as input a ticket-id and return a string
+  containing all of the information and history corresponding to the
+  ticket with ticket-id.
+
+* Module "CLI command interface": Send ticket-modifying commands to
+  the server, receive and process the results.
+
+* Module "local storage": Store and retrieve arbitrary information
+  about tickets. The storage is keyed to the RT ticket number.
+
+** User interface modules
+
+* Module "ticket browser": (requires "TicketSQL runner") Interactive
+  interface to choose a ticket out of a list of tickets. The query
+  which generated the list is displayed at the top, followed by the
+  number of tickets listed, followed by a list of tickets. Tickets are
+  displayed according to a modular display function. The tickets are
+  sorted according to a default sorting function (reverse
+  chronological order).
+
+* Module "ticket viewer": (requires "TicketSQL retriever") Interactive
+  interface to display all of the information and history
+  corresponding to the ticket with ticket-id. Ticket display provides
+  a number of convinience functions. The buffer is read-only and
+  provides font-locking to easily identify section borders. The
+  keyboard space-bar invokes `scroll-up'. The "n" and "p" keys jump to
+  the next and previous section borders respectively.
+
+** Software interfaces
+
+* Module "rt-liber-Gnus": (requires "ticket viewer") Allows the user 
+  to open the current ticket in a Gnus mail buffer. Fills in the
+  "Subject:" and "To:" fields appropriately. Has the ability to import
+  the text of a certain section (automatically quoted). Optionally can
+  add a "sorry we are late" text if the ticket is old or other
+  greetings, salutations and signatures.
+
+* Module "command": (requires "CLI command interface") The user can 
+  send commands to the RT system to change the status of tickets via
+  this interface. The user interface is updated as needed to reflect
+  the change.
diff --git a/rt-liberation-gnus.el b/rt-liberation-gnus.el
new file mode 100644
index 0000000..48ed6a9
--- /dev/null
+++ b/rt-liberation-gnus.el
@@ -0,0 +1,230 @@
+;;; rt-liberation-gnus.el --- Gnus integration for rt-liberation
+
+;; Copyright (C) 2009, 2012 Yoni Rabkin
+;;
+;; Authors: Yoni Rabkin <yonirabkin@member.fsf.org>
+;;
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public
+;; License along with this program; if not, write to the Free
+;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+;; MA 02111-1307, USA.
+
+;;; Installation:
+;;
+;; For installation instructions and detailed help please see the
+;; wonderful rt-liberation manual located in the "doc/" directory of
+;; the rt-liberation distribution.
+
+(defgroup rt-liber-gnus nil
+  "*Gnus integration for rt-liberation."
+  :prefix "rt-liber-gnus-"
+  :group 'rt-liber-gnus)
+
+(defcustom rt-liber-gnus-comment-address "no comment address set"
+  "*Email address for adding a comment."
+  :type 'string
+  :group 'rt-liber-gnus)
+
+(defcustom rt-liber-gnus-address "no reply address set"
+  "*Email address for replying to requestor."
+  :type 'string
+  :group 'rt-liber-gnus)
+
+(defcustom rt-liber-gnus-subject-name "no subject name set"
+  "*Subject name to be included in email header."
+  :type 'string
+  :group 'rt-liber-gnus)
+
+(defcustom rt-liber-gnus-answer-headers nil
+  "*Alist of additional message headers."
+  :type 'list
+  :group 'rt-liber-gnus)
+
+(defcustom rt-liber-gnus-provisional-tag "PROVISIONAL"
+  "*Subject line text for a provisional response."
+  :type 'string
+  :group 'rt-liber-gnus)
+
+(defcustom rt-liber-gnus-delayed-response-text
+  "Please accept my apologies for the late reply."
+  "*Text for a belated reply."
+  :type 'string
+  :group 'rt-liber-gnus)
+
+(defcustom rt-liber-gnus-signature
+  "--
+   Regards."
+  "Signature to append to email."
+  :type 'string
+  :group 'rt-liber-gnus)
+
+(defcustom rt-liber-gnus-subject-regexp
+  ""
+  "Regular expression to capture the ticket number in the subject
+line of an email. For example: \\[company.com #\\([0-9].+?\\)\\]"
+  :type 'string
+  :group 'rt-liber-gnus)
+
+(require 'rt-liberation)
+
+(eval-when-compile (require 'gnus-msg))
+
+(defun rt-liber-gnus-compose (addr ticket-alist options)
+  "Create a Gnus *mail* buffer for the RT email interface.
+ADDR email address.
+TICKET-ALIST association list of ticket properties.
+OPTIONS association list of options.
+"
+  (let ((provisional      (cdr (assoc 'provisional options)))
+       (suppress-subject (cdr (assoc 'suppress-subject options)))
+       (top-matter       (cdr (assoc 'top-matter options)))
+       (contents         (cdr (assoc 'contents options)))
+       (no-comment       (cdr (assoc 'no-comment options))))
+    (gnus-setup-message 'message
+      (message-mail
+       addr
+       (format "[%s #%s] %s"
+              rt-liber-gnus-subject-name
+              (rt-liber-ticket-id-only ticket-alist)
+              (cond (suppress-subject "")
+                    (provisional rt-liber-gnus-provisional-tag)
+                    (t (rt-liber-format "Re: %s" ticket-alist))))
+       rt-liber-gnus-answer-headers
+       nil
+       'switch-to-buffer))
+    (goto-char (point-max))
+    (save-excursion
+      (when top-matter (insert top-matter))
+      (let ((start (point)))
+       (when contents (newline 2) (insert contents))
+       (when (not no-comment)
+         (comment-region start (point))))
+      (newline 2)
+      (insert rt-liber-gnus-signature)
+      (newline))))
+
+;; fixme: test against both versions of the RT CLI
+(defun rt-liber-gnus-content-to-string ()
+  "Return the current content section as a string"
+  (rt-liber-gnus-with-ticket-buffer
+   (goto-char (point-at-eol))
+   (when
+       (not
+       (or (re-search-backward rt-liber-content-regexp (point-min) t)
+           (re-search-forward rt-liber-content-regexp (point-max) t)))
+     (error "no content sections found"))
+   (goto-char (point-at-bol))
+   (re-search-forward "^Content: " (point-at-eol) nil)
+   (let ((start (point))
+        text)
+     (re-search-forward "^[[:alpha:]]+:" (point-max) t)
+     (forward-line -1)
+     (if (= (count-lines start (point)) 1)
+        (error "empty content section")
+       (setq text (buffer-substring-no-properties start (point)))
+       (with-temp-buffer
+        (insert text)
+        (goto-char (point-min))
+        (replace-regexp "^[ ]+" "")
+        (whitespace-cleanup)
+        (setq text (buffer-substring (point-min) (point-max)))))
+     text)))
+
+(defmacro rt-liber-gnus-with-ticket-buffer (&rest body)
+  `(progn
+     (when (not (boundp 'rt-liber-ticket-local))
+       (error "rt-liberation ticket view buffer not present"))
+     ,@body))
+
+(defun rt-liber-gnus-compose-reply-to-requestor ()
+  (interactive)
+  (rt-liber-gnus-with-ticket-buffer
+   (rt-liber-gnus-compose
+    rt-liber-gnus-address
+    rt-liber-ticket-local
+    nil)))
+
+(defun rt-liber-gnus-compose-reply-to-requestor-to-this ()
+  (interactive)
+  (rt-liber-gnus-with-ticket-buffer
+   (rt-liber-gnus-compose
+    rt-liber-gnus-address
+    rt-liber-ticket-local
+    `((contents . ,(rt-liber-gnus-content-to-string))
+      (top-matter . ,(if (rt-liber-ticket-old-p rt-liber-ticket-local)
+                        rt-liber-gnus-delayed-response-text
+                      nil))))))
+
+(defun rt-liber-gnus-compose-reply-to-requestor-verbatim-this ()
+  (interactive)
+  (rt-liber-gnus-with-ticket-buffer
+   (rt-liber-gnus-compose
+    rt-liber-gnus-address
+    rt-liber-ticket-local
+    `((contents . ,(rt-liber-gnus-content-to-string))
+      (no-comment . t)))))
+
+(defun rt-liber-gnus-compose-provisional ()
+  (interactive)
+  (rt-liber-gnus-with-ticket-buffer
+   (rt-liber-gnus-compose
+    rt-liber-gnus-comment-address
+    rt-liber-ticket-local
+    '((provisional . t)))))
+
+(defun rt-liber-gnus-compose-provisional-to-this ()
+  (interactive)
+  (rt-liber-gnus-with-ticket-buffer
+   (rt-liber-gnus-compose
+    rt-liber-gnus-comment-address
+    rt-liber-ticket-local
+    `((provisional . t)
+      (contents . ,(rt-liber-gnus-content-to-string))
+      (top-matter . ,(if (rt-liber-ticket-old-p rt-liber-ticket-local)
+                        rt-liber-gnus-delayed-response-text
+                      nil))))))
+
+(defun rt-liber-gnus-compose-comment ()
+  (interactive)
+  (rt-liber-gnus-with-ticket-buffer
+   (rt-liber-gnus-compose
+    rt-liber-gnus-comment-address
+    rt-liber-ticket-local
+    `((suppress-subject . t)
+      (no-comment       . t)
+      ))))
+
+(defun rt-liber-gnus-compose-comment-this ()
+  (interactive)
+  (rt-liber-gnus-with-ticket-buffer
+   (rt-liber-gnus-compose
+    rt-liber-gnus-comment-address
+    rt-liber-ticket-local
+    `((suppress-subject . t)
+      (contents . ,(rt-liber-gnus-content-to-string))
+      ))))
+
+(defun rt-liber-gnus-visit-ticket-at-point ()
+  "Call `rt-liber-display-ticket' on this ticket."
+  (interactive)
+  (save-excursion
+    (goto-char (point-at-bol))
+    (re-search-forward rt-liber-gnus-subject-regexp (point-at-eol) nil))
+  (let ((match (match-string-no-properties 1)))
+    (when (not match)
+      (error "no ticket number found in subject line"))
+    (rt-liber-display-ticket match)))
+
+(provide 'rt-liberation-gnus)
+
+;;; rt-liberation-gnus.el ends here.
diff --git a/rt-liberation-multi.el b/rt-liberation-multi.el
new file mode 100644
index 0000000..3e9c208
--- /dev/null
+++ b/rt-liberation-multi.el
@@ -0,0 +1,113 @@
+;;; rt-liberation-multi.el --- Free from RT
+
+;; Copyright (C) 2010 Yoni Rabkin
+;;
+;; Authors: Yoni Rabkin <yonirabkin@member.fsf.org>
+;;
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public
+;; License along with this program; if not, write to the Free
+;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+;; MA 02111-1307, USA.
+
+;;; Code:
+
+(require 'rt-liberation)
+
+(defface rt-liber-marked-ticket-face
+  '((((class color) (background dark))
+     (:foreground "Red"))
+    (((class color) (background light))
+     (:foreground "Red"))
+    (((type tty) (class mono))
+     (:inverse-video t))
+    (t (:background "Red")))
+  "Face for marked tickets in browser buffer.")
+
+(defvar rt-liber-marked-tickets nil
+  "Marked tickets (becomes ticket-browser buffer local).")
+
+(defun rt-liber-ticket-marked-p (ticket)
+  "Return a truth value if TICKET is marked, otherwise NIL."
+  (let ((ticket-id (rt-liber-ticket-id-only ticket)))
+    (member ticket-id rt-liber-marked-tickets)))
+
+(defun rt-liber-mark-ticket-at-point ()
+  "Mark/unmark the ticket at point for future action."
+  (interactive)
+  (let ((ticket (get-text-property (point) 'rt-ticket)))
+    (if ticket
+       (let ((ticket-id (rt-liber-ticket-id-only ticket))
+             (inhibit-read-only t))
+         (set (make-local-variable 'rt-liber-marked-tickets)
+              (if (rt-liber-ticket-marked-p ticket)
+                  (remove ticket-id rt-liber-marked-tickets)
+                (append (list ticket-id) rt-liber-marked-tickets)))
+         (let ((p (point)))
+           (rt-liber-ticketlist-browser-redraw
+            rt-liber-ticket-list
+            rt-liber-query)
+           (goto-char p)
+           (rt-liber-next-ticket-in-browser)
+           (recenter-top-bottom)))
+      (error "no ticket at point"))))
+
+(defun rt-liber-multi-set-status-open ()
+  "Set the status of all marked tickets to `open'."
+  (interactive)
+  (when (not rt-liber-marked-tickets)
+    (error "no marked tickets"))
+  (dolist (ticket-id rt-liber-marked-tickets)
+    (message "setting status for ticket #%s ..." ticket-id)
+    (rt-liber-command-set-status-open ticket-id)
+    (message "setting status for ticket #%s ...done" ticket-id))
+  (rt-liber-browser-refresh))
+
+(defun rt-liber-multi-set-status-resolved ()
+  "Set the status of all marked tickets to `resolve'."
+  (interactive)
+  (when (not rt-liber-marked-tickets)
+    (error "no marked tickets"))
+  (dolist (ticket-id rt-liber-marked-tickets)
+    ;; these are less for the user and more to leave a trail in the
+    ;; `*Messages*' buffer
+    (message "setting status for ticket #%s ..." ticket-id)
+    (rt-liber-command-set-status-resolved ticket-id))
+  (rt-liber-browser-refresh))
+
+(defun rt-liber-multi-assign (name)
+  "Assign marked tickets to a user NAME."
+  (interactive "sAssign to: ")
+  (when (not rt-liber-marked-tickets)
+    (error "no marked tickets"))
+  (dolist (ticket-id rt-liber-marked-tickets)
+    (message "setting status for ticket #%s ..." ticket-id)
+    (rt-liber-command-set-owner
+     ticket-id name))
+  (rt-liber-browser-refresh))
+
+(defun rt-liber-multi-flag-as-spam-and-delete ()
+  "Flag all marked tickets as spam, and delete them."
+  (interactive)
+  (when (not rt-liber-marked-tickets)
+    (error "no marked tickets"))
+  (dolist (ticket-id rt-liber-marked-tickets)
+    (rt-liber-command-set-cf
+     ticket-id
+     (rt-liber-command-get-custom-field-string
+      'cf-is-spam) "yes")
+    (rt-liber-command-set-status-deleted ticket-id))
+  (rt-liber-browser-refresh))
+
+(provide 'rt-liberation-multi)
+
+;;; rt-liberation-multi.el ends here.
diff --git a/rt-liberation-storage.el b/rt-liberation-storage.el
new file mode 100644
index 0000000..8bcb96b
--- /dev/null
+++ b/rt-liberation-storage.el
@@ -0,0 +1,110 @@
+;;; rt-liberation-storage.el --- Storage backend for rt-liberation
+
+;; Copyright (C) 2010  Yoni Rabkin
+;;
+;; Author: Yoni Rabkin <yonirabkin@member.fsf.org>
+;;
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public
+;; License along with this program; if not, write to the Free
+;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+;; MA 02111-1307, USA.
+
+;;; Code:
+
+(require 'rt-liberation)
+
+(defvar rt-liber-store nil
+  "In memory storage for ticket metadata.")
+
+(defvar rt-liber-store-file "ticket_metadata"
+  "File name for storing ticket metadata.")
+
+(defvar rt-liber-ancillary-format-f 'rt-liber-ancillary-format-f
+  "Default formatting function for ancillary data.")
+
+(defun rt-liber-store-write ()
+  "Write `rt-liber-store' to permanent storage."
+  (when (and (stringp rt-liber-directory)
+            (not (file-exists-p rt-liber-directory)))
+    (make-directory rt-liber-directory))
+  (when (hash-table-p rt-liber-store)
+    (with-temp-buffer
+      (insert (format "%s" rt-liber-store))
+      (insert "\n")
+      (write-file
+       (concat (file-name-as-directory rt-liber-directory)
+              rt-liber-store-file)))))
+
+(defun rt-liber-store-read ()
+  "Populate `rt-liber-store' from permanent storage."
+  (let ((file (concat (file-name-as-directory rt-liber-directory)
+                     rt-liber-store-file)))
+    (when (file-exists-p file)
+      (setq rt-liber-store
+           (with-temp-buffer
+             (insert-file-contents file)
+             (read (current-buffer)))))))
+
+(defun rt-liber-store-load ()
+  "Ensure that the store has been loaded."
+  (when (not (hash-table-p rt-liber-store))
+    (rt-liber-store-read)))
+
+(defun rt-liber-store-ticket-property (key value ticket-id)
+  "Relate KEY and VALUE to TICKET-ID."
+  (rt-liber-store-load)
+  (let ((existing (gethash ticket-id rt-liber-store)))
+    (when (not existing)
+      (setq existing (make-hash-table :test 'equal)))
+    (puthash key value existing)
+    (puthash ticket-id existing rt-liber-store)
+    (rt-liber-store-write)))
+
+
+;;; ------------------------------------------------------------------
+;;; Interface
+;;; ------------------------------------------------------------------
+
+(defun rt-liber-set-ancillary-text (text)
+  "Store ancillary string TEXT for the ticket at point."
+  (let ((id (rt-liber-browser-ticket-id-at-point))
+       (inhibit-read-only t)
+       message)
+    (rt-liber-store-ticket-property "text" text id)
+    (if (and rt-liber-ticket-list rt-liber-query)
+       (rt-liber-ticketlist-browser-redraw
+        rt-liber-ticket-list rt-liber-query)
+      (setq message " (refresh ticket-browser to see changes)"))
+    (rt-liber-browser-move-point-to-ticket id)
+    (minibuffer-message "stored text for ticket %s%s"
+                       id (or message ""))))
+
+(defun rt-liber-get-ancillary-text (ticket-id)
+  "Return the TEXT field for TICKET-ID or an empty string."
+  (rt-liber-store-load)
+  (let ((existing (gethash ticket-id rt-liber-store)))
+    (if existing
+       (or (gethash "text" existing) "")
+      "")))
+
+(defun rt-liber-ancillary-format-f (ticket-id)
+  "Default formatting function for ancillary data."
+  (rt-liber-get-ancillary-text ticket-id))
+
+(defun rt-liber-get-anc (ticket-id)
+  "Return formatted ancillary data string for ticket TICKET-ID."
+  (funcall rt-liber-ancillary-format-f ticket-id))
+
+(provide 'rt-liberation-storage)
+
+;;; rt-liberation-storage.el ends here.
diff --git a/rt-liberation-update.el b/rt-liberation-update.el
new file mode 100644
index 0000000..8c57bf8
--- /dev/null
+++ b/rt-liberation-update.el
@@ -0,0 +1,106 @@
+;;; rt-liberation-update.el --- check updated tickets
+
+;; Copyright (C) 2009 Yoni Rabkin
+;;
+;; Authors: Yoni Rabkin <yonirabkin@member.fsf.org>
+;;
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public
+;; License along with this program; if not, write to the Free
+;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+;; MA 02111-1307, USA.
+
+;;; Installation:
+;;
+;; For installation instructions and detailed help please see the
+;; wonderful rt-liberation manual located in the "doc/" directory of
+;; the rt-liberation distribution.
+
+;;; Usage:
+;;
+
+(require 'rt-liberation)
+
+(defgroup rt-liber-update nil
+  "*Check updates for rt-liberation."
+  :prefix "rt-liber-update-"
+  :group 'rt-liber-update)
+
+(defcustom rt-liber-update-file
+  (concat (file-name-as-directory rt-liber-directory) "update")
+  "*File to store update information."
+  :type 'string
+  :group 'rt-liber-update)
+
+(defcustom rt-liber-update-default-queue nil
+  "*Default queue to run queries against."
+  :type 'string
+  :group 'rt-liber-update)
+
+(defun rt-liber-update-timestamp ()
+  "Write the current time to disk as a time-stamp."
+  (rt-liber-update-write (format "%s" (current-time))))
+
+(defun rt-liber-update-write (str)
+  "Write STR to disk under the rt-liber directory."
+  (when (and (stringp rt-liber-directory)
+            (not (file-exists-p rt-liber-directory)))
+    (make-directory rt-liber-directory))
+  (when (stringp rt-liber-update-file)
+    (with-temp-buffer
+      (insert str)
+      (insert "\n")
+      (write-file rt-liber-update-file))))
+
+(defun rt-liber-update-read ()
+  "Return the time-stamp read from disk or the current time."
+  (when (file-exists-p rt-liber-update-file)
+    (let ((timestamp (current-time)))
+      (with-temp-buffer
+       (insert-file-contents rt-liber-update-file)
+       (setq timestamp (read (current-buffer))))
+      timestamp)))
+
+(defun rt-liber-update-run-query (query-queue timestamp)
+  "Run query on QUERY-QUEUE since TIMESTAMP."
+  (rt-liber-browse-query
+   (rt-liber-compile-query
+    (and (queue query-queue)
+        (lastupdated nil
+                     (format-time-string "%Y-%m-%d"
+                                         timestamp))))))
+
+(defun rt-liber-update (&optional no-update)
+  "Show tickets last updated since `rt-liber-update' last run.
+
+With the NO-UPDATE prefix, don't update the time-stamp on disk.
+
+If no time-stamp is found, for instance when you run this for the
+first time, today's date is used and then recorded as the
+time-stamp."
+  (interactive "P")
+  (when (not rt-liber-update-default-queue)
+    (error "`rt-liber-update-default-queue' is nil"))
+  (let ((timestamp (rt-liber-update-read)))
+    (rt-liber-update-run-query rt-liber-update-default-queue
+                              timestamp)
+    (when (not no-update)
+      (rt-liber-update-timestamp))
+    (message "showing tickets updated after: %s (time-stamp %s)"
+            (format-time-string "%Y-%m-%d" timestamp)
+            (if no-update
+                "not updated"
+              "updated"))))
+
+(provide 'rt-liberation-update)
+
+;;; rt-liberation-update.el ends here.
diff --git a/rt-liberation.el b/rt-liberation.el
new file mode 100644
index 0000000..6f31921
--- /dev/null
+++ b/rt-liberation.el
@@ -0,0 +1,1276 @@
+;;; rt-liberation.el --- Free from RT
+
+;; Copyright (C) 2008, 2009, 2010, 2011 Yoni Rabkin, Aaron S. Hawley,
+;; John Sullivan
+;;
+;; Authors: Yoni Rabkin <yonirabkin@member.fsf.org>, Aaron S. Hawley
+;; <aaron.s.hawley@gmail.com>, John Sullivan <johnsu01@wjsullivan.net>
+;;
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public
+;; License along with this program; if not, write to the Free
+;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+;; MA 02111-1307, USA.
+
+;;; Installation and Use:
+;;
+;; Detailed instructions for installation and use can be found in the
+;; rt-liberation manual, in the doc/ directory of the distribution.
+
+;;; History:
+;;
+;; Started near the end of 2008.
+
+;;; Code:
+
+(require 'browse-url)
+(require 'time-date)
+(require 'cl)
+
+(defgroup rt-liber nil
+  "*rt-liberation, the Emacs interface to RT"
+  :prefix "rt-liber-"
+  :group 'rt-liber)
+
+(defcustom rt-liber-directory "~/.emacs.d/rt-liber"
+  "*Directory to store persistent information."
+  :type 'string
+  :group 'rt-liber)
+
+(defvar rt-liber-created-string "Created"
+  "String representation of \"created\" query tag.")
+
+(defvar rt-liber-base-url ""
+  "Base url for ticket display.")
+
+(defvar rt-liber-lastupdated-string "LastUpdated"
+  "String representation of \"lastupdated\" query tag.")
+
+(defvar rt-liber-content-string "Content LIKE"
+  "String representation of \"content\" query tag.")
+
+(defvar rt-liber-subject-string "Subject LIKE"
+  "String representation of \"subject\" query tag.")
+
+(defvar rt-liber-email-address-string "Requestor.EmailAddress LIKE"
+  "String representation of \"Requestor.EmailAddress\" query tag.")
+
+(defvar rt-liber-content-not-string "Content NOT LIKE"
+  "String representation of \"content\" query tag.")
+
+(defvar rt-liber-subject-not-string "Subject NOT LIKE"
+  "String representation of \"subject\" query tag.")
+
+(defvar rt-liber-email-address-not-string "Requestor.EmailAddress NOT LIKE"
+  "String representation of \"Requestor.EmailAddress\" query tag.")
+
+(defvar rt-liber-content-regexp "^Content:.*$"
+  "Regular expression for section headers.")
+
+(defvar rt-liber-correspondence-regexp
+  "^Type: \\(EmailRecord\\|CommentEmailRecord\\|Correspond\\)"
+  "Regular expression for correspondence sections.")
+
+(defvar rt-liber-rt-binary "~/rt-3.8.1/bin/rt"
+  "Location of the RT CLI binary.")
+
+(defvar rt-liber-rt-version "3.8.1"
+  "Version of the RT CLI.")
+
+(defvar rt-liber-username nil
+  "Username for assigning ownership on the RT server.")
+
+(defvar rt-liber-browser-buffer-name "*ticket-browser*"
+  "Name of ticket browser buffer.")
+
+(defvar rt-liber-browser-buffer nil
+  "Ticket browser buffer.")
+
+(defvar rt-liber-browser-default-sorting-function
+  'rt-liber-sort-by-time-created
+  "Default sorting function.")
+
+(defvar rt-liber-browser-default-filter-function
+  'rt-liber-default-filter-f
+  "Default filtering function.
+
+This is a function which accepts the ticket alist as a single
+argument and returns nil if the ticket needs to be filtered out,
+dropped or ignored (however you wish to put it.), otherwise the
+function returns a truth value.")
+
+(defvar rt-liber-custom-ticket-redraw-function
+  'rt-liber-ticketlist-browser-redraw-f
+  "Default ticket redraw function.")
+
+(defvar rt-liber-ticket-old-threshold 30
+  "Age in days before a ticket is considered old.")
+
+(defvar rt-liber-jump-to-latest nil
+  "jump to the latest correspondence when viewing a ticket.")
+
+(defvar rt-liber-anc-p nil
+  "Display ancillary data for tickets.")
+
+(defvar rt-liber-ticket-list nil
+  "Ticket-list structure (becomes ticket-browser buffer local).")
+
+(defvar rt-liber-query nil
+  "Query structure (becomes ticket-browser buffer local).")
+
+(defface rt-liber-ticket-face
+  '((((class color) (background dark))
+     (:foreground "DarkSeaGreen"))
+    (((class color) (background light))
+     (:foreground "Blue"))
+    (((type tty) (class mono))
+     (:inverse-video t))
+    (t (:background "Blue")))
+  "Face for tickets in browser buffer.")
+
+(defconst rt-liber-viewer-font-lock-keywords
+  (let ((header-regexp (regexp-opt '("id: " "Ticket: " "TimeTaken: "
+                                    "Type: " "Field: " "OldValue: "
+                                    "NewValue: " "Data: "
+                                    "Description: " "Created: "
+                                    "Creator: " "Attachments: ") t)))
+    (list
+     (list (concat "^" header-regexp ".*$") 0
+          'font-lock-comment-face)))
+  "Expressions to font-lock for RT ticket viewer.")
+
+(defvar rt-liber-browser-do-refresh t
+  "When t, run `rt-liber-browser-refresh' otherwise disable it.")
+
+(defvar rt-liber-command-dictionary
+  '((comment . "comment")
+    (edit    . "edit"))
+  "Mapping between command symbols and command strings.
+
+The command symbols provide the programmer with a consistent way
+of referring to certain commands. The command strings are the
+specific strings which would produce the desired effect in the
+server.")
+
+(defvar rt-liber-status-dictionary
+  '((deleted  . "deleted")
+    (resolved . "resolved")
+    (open     . "open"))
+  "Mapping between status symbols and status strings.
+
+The status symbols provide the programmer with a consistent way
+of referring to certain statuses. The status strings are the
+server specific strings.")
+
+(defvar rt-liber-custom-field-dictionary
+  '((cf-is-spam  . "cf-is-spam"))
+  "Mapping between custom field symbols and custom field strings.
+
+The custom field symbols provide the programmer with a consistent
+way of referring to certain custom fields. The custom field
+strings are the server specific strings.")
+
+
+;;; --------------------------------------------------------
+;;; TicketSQL compiler
+;;; --------------------------------------------------------
+
+(defun rt-liber-bool-p (sym)
+  "Return t if SYM is a boolean operator, otherwise nil."
+  (member sym '(and or)))
+(defun rt-liber-attrib-p (sym)
+  "Return t if SYM is a ticket attribute, otherwise nil."
+  (member sym '(id owner status subject content queue lastupdatedby
+                  email-address)))
+(defun rt-liber-time-p (sym)
+  "Return t if SYM is a temporal attribute, otherwise nil."
+  (member sym '(created lastupdated)))
+(defun rt-liber-negation-p (sym)
+  (member sym '(not)))
+
+(defun rt-liber-reduce (op seq)
+  "Reduce-OP with SEQ to a string of \"s0 op s1 op s2..\"."
+  (if seq
+      (reduce
+       #'(lambda (a b)
+          (format "%s %s %s" a op b))
+       seq)
+    ""))
+
+(defun rt-liber-make-interval (pred before after)
+  "Return a formatted TicketSQL interval.
+PRED   temporal attribute predicate.
+BEFORE date before predicate.
+AFTER  date after predicate."
+  (when (string= before "") (setq before nil))
+  (when (string= after "") (setq after nil))
+  (concat
+   (if before (format "%s < '%s'" pred before) "")
+   (if (and before after) (format " AND ") "")
+   (if after (format "%s > '%s'" pred after) "")))
+
+(defmacro rt-liber-compile-query (query &optional n)
+  "Compile sexp-based QUERY into TicketSQL."
+  (cond ((null query) `"")
+       ((stringp query) `,query)
+       ((rt-liber-bool-p query) `,(upcase (format "%s" query)))
+       ;; attribute (positive)
+       ((and (rt-liber-attrib-p query)
+             (not n))
+        `,(cond ((equal query 'content) rt-liber-content-string)
+                ((equal query 'subject) rt-liber-subject-string)
+                ((equal query 'email-address) rt-liber-email-address-string)
+                (t (capitalize (format "%s =" query)))))
+       ;; attribute (negation)
+       ((and (rt-liber-attrib-p query)
+             n)
+        `,(cond ((equal query 'content) rt-liber-content-not-string)
+                ((equal query 'subject) rt-liber-subject-not-string)
+                ((equal query 'email-address) 
rt-liber-email-address-not-string)
+                (t (capitalize (format "%s !=" query)))))
+       ;; time
+       ((rt-liber-time-p query)
+        `,(cond ((equal query 'created) rt-liber-created-string)
+                ((equal query 'lastupdated) rt-liber-lastupdated-string)))
+       ((and (listp query)
+             (rt-liber-time-p (car query)))
+        `(rt-liber-make-interval
+          (rt-liber-compile-query ,(car query))
+          (rt-liber-compile-query ,(cadr query))
+          (rt-liber-compile-query ,(caddr query))))
+       ;; function (known at compile time?)
+       ((and query
+             (listp query)
+             (not (rt-liber-bool-p (car query)))
+             (not (rt-liber-negation-p (car query)))
+             (functionp (car query)))
+        `(format "%s" ,query))
+       ;; negation attribute pairs
+       ((and (listp query)
+             (rt-liber-negation-p (car query))
+             (rt-liber-attrib-p (caadr query)))
+        `(format "%s '%s'"
+                 (rt-liber-compile-query ,(caadr query) t) ; negate
+                 (rt-liber-compile-query ,(cadadr query))))
+       ;; attribute pairs
+       ((and (listp query)
+             (rt-liber-attrib-p (car query)))
+        `(format "%s '%s'"
+                 (rt-liber-compile-query ,(car query))
+                 (rt-liber-compile-query ,(cadr query))))
+       ;; splice boolean operators
+       ((and (listp query)
+             (rt-liber-bool-p (car query)))
+        `(rt-liber-reduce (rt-liber-compile-query ,(car query))
+                          (rt-liber-compile-query ,(cdr query))))
+       ;; compound statements
+       ((and (listp query)
+             (not (cdr query)))
+        `(list (rt-liber-compile-query ,(car query))))
+       ((listp query)
+        `(append
+          (list (rt-liber-compile-query ,(car query)))
+          (rt-liber-compile-query ,(cdr query))))
+       ;; free variable
+       ((and query
+             (symbolp query))
+        `(format "%s" ,query))
+       (t (error "cannot compile query %s" query))))
+
+
+;;; --------------------------------------------------------
+;;; Query runner
+;;; --------------------------------------------------------
+
+(defun rt-liber-query-runner (op query-string)
+  "Run OP query against the server with QUERY-STRING."
+  (message "started '%s' query at %s..." op (current-time-string))
+  (condition-case excep
+      (with-temp-buffer
+       (if (and (not (rt-liber-version-< rt-liber-rt-version
+                                         "3.8.2"))
+                (string= op "show"))
+           (call-process rt-liber-rt-binary nil t nil
+                         op "-l" query-string)
+         (call-process rt-liber-rt-binary nil t nil
+                       op query-string))
+       (message "query ended at %s" (current-time-string))
+       (buffer-string))
+    (file-error
+     (error "could not find the RT binary at: %s" rt-liber-rt-binary))
+    (error "an unhandled exception occured: %s" excep)))
+
+(defun rt-liber-parse-answer (answer-string parser-f)
+  "Operate on ANSWER-STRING with PARSER-F."
+  (with-temp-buffer
+    (insert answer-string)
+    (goto-char (point-min))
+    (funcall parser-f)))
+
+
+;;; --------------------------------------------------------
+;;; TicketSQL runner
+;;; --------------------------------------------------------
+
+(defun rt-liber-ticketsql-runner-parser-f ()
+  "Parser function for a textual list of tickets."
+  (let (idsub-list)
+    (while (or
+           (and (not (rt-liber-version-< rt-liber-rt-version
+                                         "3.8.2"))
+                (re-search-forward "^ *\\([0-9]+\\) *\\(.*\\)$"
+                                   (point-max) t))
+           (re-search-forward "^\\([0-9]+\\): \\(.*\\)$"
+                              (point-max) t))
+      (push (list (match-string-no-properties 1)
+                 (match-string-no-properties 2))
+           idsub-list))
+    idsub-list))
+
+(defun rt-liber-run-ls-query (query)
+  "Run an \"ls\" type query against the server with QUERY."
+  (rt-liber-parse-answer
+   (rt-liber-query-runner "ls" query)
+   'rt-liber-ticketsql-runner-parser-f))
+
+
+;;; --------------------------------------------------------
+;;; Ticket list retriever
+;;; --------------------------------------------------------
+
+(put 'rt-liber-no-result-from-query-error
+     'error-conditions
+     '(error rt-liber-errors rt-liber-no-result-from-query-error))
+
+(put 'rt-liber-no-result-from-query-error
+     'error-message
+     "No results from query")
+
+(defun rt-liber-ticket-base-retriever-parser-f ()
+  "Parser function for ticket list."
+  (let (ticketbase-list ticketbase (continue t))
+    (while (save-excursion
+            (re-search-forward "[A-Za-z]" (point-max) t)) ; really?
+      (while (and continue
+                 (re-search-forward
+                  "^\\(\\([\.{} #[:alpha:]]+\\): \\(.*\\)\\)$\\|^--$"
+                  (point-max) t))
+       (if (string= (match-string-no-properties 0) "--")
+           (setq continue nil)
+         (push (cons (match-string-no-properties 2)
+                     (match-string-no-properties 3))
+               ticketbase)))
+      (push (copy-seq ticketbase) ticketbase-list)
+      (setq ticketbase nil
+           continue t))
+    ticketbase-list))
+
+;; accept the output of `rt-liber-ticketsql-runner-parser-f' and
+;; return a string suitable for an RT "show" query
+(defun rt-liber-create-tickets-string (idsublist)
+  "Create a RT CLI ticket \"show\" string from IDSUBLIST."
+  (let ((ticket-list (mapcar #'(lambda (e) (car e)) idsublist)))
+    (if ticket-list
+       (concat "ticket/"
+               (if (= (length ticket-list) 1)
+                   (format "%s" (car ticket-list))
+                 (reduce
+                  #'(lambda (a b)
+                      (format "%s,%s" a b))
+                  ticket-list)))
+      (signal 'rt-liber-no-result-from-query-error nil))))
+
+(defun rt-liber-run-show-base-query (idsublist)
+  "Run \"show\" type query against the server with IDSUBLIST."
+  (rt-liber-parse-answer
+   (rt-liber-query-runner "show"
+                         (rt-liber-create-tickets-string idsublist))
+   #'rt-liber-ticket-base-retriever-parser-f))
+
+
+;;; --------------------------------------------------------
+;;; Ticket retriever
+;;; --------------------------------------------------------
+
+;; Implementation note: Working with 3.8.1 or 3.8.2 of the RT CLI
+;; makes a huge difference here. 3.8.1 returns a kind of listing of
+;; the history ID objects which requires further processing. 3.8.2 on
+;; the other hand returns the contents of all the ticket history
+;; objects in one fell swoop.
+
+(defun rt-liber-create-ticket-history-string (ticket-id)
+  "Create a query for TICKET-ID to retrieve all history objects."
+  (concat "ticket/" ticket-id "/history/id"))
+
+(defun rt-liber-create-ticket-histories-string (ticket-id subid-list)
+  "Create query for TICKET-ID to retrieve SUBID-LIST objects."
+  (concat "ticket/" ticket-id "/history/id/"
+         (reduce
+          #'(lambda (a b) (format "%s,%s" a b)) subid-list)))
+
+(defun rt-liber-run-ticket-history-base-query (ticket-id)
+  "Run history query against server for TICKET-ID."
+  (rt-liber-parse-answer
+   (rt-liber-query-runner "show"
+                         (rt-liber-create-ticket-history-string
+                          ticket-id))
+   (if (rt-liber-version-< rt-liber-rt-version "3.8.2")
+       #'(lambda ()
+          (let ((ticket-history-sublist nil))
+            (goto-char (point-min))
+            (while (re-search-forward "^\\([0-9]+\\): " (point-max) t)
+              (setq ticket-history-sublist
+                    (append (list (match-string-no-properties 1))
+                            ticket-history-sublist)))
+            (if ticket-history-sublist
+                (rt-liber-parse-answer
+                 (rt-liber-query-runner
+                  "show"
+                  (rt-liber-create-ticket-histories-string
+                   ticket-id
+                   ticket-history-sublist))
+                 #'(lambda () (buffer-substring (point-min)
+                                                (point-max))))
+              (error "an unhandled exceptions occurred"))))
+     #'(lambda () (buffer-substring (point-min) (point-max))))))
+
+
+;;; --------------------------------------------------------
+;;; Ticket utilities
+;;; --------------------------------------------------------
+
+(defun rt-liber-ticket-days-old (ticket-alist)
+  "Return the age of the ticket in positive days."
+  (days-between (format-time-string "%Y-%m-%dT%T%z" (current-time))
+               (cdr (assoc "Created" ticket-alist))))
+
+(defun rt-liber-ticket-old-p (ticket-alist)
+  (<= rt-liber-ticket-old-threshold
+      (rt-liber-ticket-days-old ticket-alist)))
+
+
+;;; --------------------------------------------------------
+;;; Ticket viewer
+;;; --------------------------------------------------------
+
+(defun rt-liber-jump-to-latest-correspondence ()
+  "Move point to the newest correspondence section."
+  (interactive)
+  (let (latest-point)
+    (save-excursion
+      (goto-char (point-max))
+      (when (re-search-backward rt-liber-correspondence-regexp
+                               (point-min) t)
+       (setq latest-point (point))))
+    (if latest-point
+       (progn
+         (goto-char latest-point)
+         (rt-liber-next-section-in-viewer))
+      (message "no correspondence found"))))
+
+(defun rt-liber-ticket-id-only (ticket-alist)
+  "Return numerical portion of ticket number from TICKET-ALIST."
+  (if ticket-alist
+      (substring (cdr (assoc "id" ticket-alist)) 7)
+    nil))
+
+(defun rt-liber-viewer-visit-in-browser ()
+  "Visit this ticket in the RT Web interface."
+  (interactive)
+  (let ((id (rt-liber-ticket-id-only rt-liber-ticket-local)))
+    (if id
+       (browse-url
+        (concat rt-liber-base-url "Ticket/Display.html?id=" id))
+      (error "no ticket currently in view"))))
+
+(defun rt-liber-viewer-mode-quit ()
+  "Bury the ticket viewer."
+  (interactive)
+  (bury-buffer))
+
+(defun rt-liber-viewer-show-ticket-browser ()
+  "Return to the ticket browser buffer."
+  (interactive)
+  (let ((id (rt-liber-ticket-id-only rt-liber-ticket-local)))
+    (if id
+       (let ((target-buffer
+              (if rt-liber-assoc-browser
+                  (buffer-name rt-liber-assoc-browser)
+                (buffer-name rt-liber-browser-buffer-name))))
+         (if target-buffer
+             (switch-to-buffer target-buffer)
+           (error "associated ticket browser buffer no longer exists"))
+         (rt-liber-browser-move-point-to-ticket id))
+      (error "no ticket currently in view"))))
+
+(defun rt-liber-next-section-in-viewer ()
+  "Move point to next section."
+  (interactive)
+  (forward-line 1)
+  (when (not (re-search-forward rt-liber-content-regexp (point-max) t))
+    (message "no next section"))
+  (goto-char (point-at-bol)))
+
+(defun rt-liber-previous-section-in-viewer ()
+  "Move point to previous section."
+  (interactive)
+  (forward-line -1)
+  (when (not (re-search-backward rt-liber-content-regexp (point-min) t))
+    (message "no previous section"))
+  (goto-char (point-at-bol)))
+
+(defconst rt-liber-viewer-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map (kbd "q") 'rt-liber-viewer-mode-quit)
+    (define-key map (kbd "n") 'rt-liber-next-section-in-viewer)
+    (define-key map (kbd "N") 'rt-liber-jump-to-latest-correspondence)
+    (define-key map (kbd "p") 'rt-liber-previous-section-in-viewer)
+    (define-key map (kbd "V") 'rt-liber-viewer-visit-in-browser)
+    (define-key map (kbd "m") 'rt-liber-viewer-answer)
+    (define-key map (kbd "M") 'rt-liber-viewer-answer-this)
+    (define-key map (kbd "t") 'rt-liber-viewer-answer-provisionally)
+    (define-key map (kbd "T") 'rt-liber-viewer-answer-provisionally-this)
+    (define-key map (kbd "F") 'rt-liber-viewer-answer-verbatim-this)
+    (define-key map (kbd "c") 'rt-liber-viewer-comment)
+    (define-key map (kbd "C") 'rt-liber-viewer-comment-this)
+    (define-key map (kbd "g") 'revert-buffer)
+    (define-key map (kbd "SPC") 'scroll-up)
+    (define-key map (kbd "DEL") 'scroll-down)
+    (define-key map (kbd "h") 'rt-liber-viewer-show-ticket-browser)
+    map)
+  "Key map for ticket viewer.")
+
+(define-derived-mode rt-liber-viewer-mode nil
+  "RT Liberation Viewer"
+  "Major Mode for viewing RT tickets.
+\\{rt-liber-viewer-mode-map}"
+  (set
+   (make-local-variable 'font-lock-defaults)
+   '((rt-liber-viewer-font-lock-keywords)))
+  (set (make-local-variable 'revert-buffer-function)
+       'rt-liber-refresh-ticket-history)
+  (set (make-local-variable 'buffer-stale-function)
+       (lambda (&optional noconfirm) 'slow))
+  (set (make-local-variable 'auto-revert-interval)
+       (* 15 60)) ;; 15 minutes
+  (when rt-liber-jump-to-latest
+    (rt-liber-jump-to-latest-correspondence))
+  (run-hooks 'rt-liber-viewer-hook))
+
+(defun rt-liber-display-ticket-history (ticket-alist &optional assoc-browser)
+  "Display history for ticket.
+
+TICKET-ALIST alist of ticket data.
+ASSOC-BROWSER if non-nil should be a ticket browser."
+  (let* ((ticket-id (rt-liber-ticket-id-only ticket-alist))
+        (contents (rt-liber-run-ticket-history-base-query ticket-id))
+        (new-ticket-buffer (get-buffer-create
+                            (concat "*RT Ticket #" ticket-id "*"))))
+    (with-current-buffer new-ticket-buffer
+      (let ((inhibit-read-only t))
+       (erase-buffer)
+       (insert contents)
+       (goto-char (point-min))
+       (rt-liber-viewer-mode)
+       (set
+        (make-local-variable 'rt-liber-ticket-local)
+        ticket-alist)
+       (when assoc-browser
+         (set
+          (make-local-variable 'rt-liber-assoc-browser)
+          assoc-browser))
+       (set-buffer-modified-p nil)
+       (setq buffer-read-only t)))
+    (switch-to-buffer new-ticket-buffer)))
+
+(defun rt-liber-refresh-ticket-history (&optional ignore-auto noconfirm)
+  (interactive)
+  (if rt-liber-ticket-local
+      (rt-liber-display-ticket-history rt-liber-ticket-local
+                                      rt-liber-assoc-browser)
+    (error "not viewing a ticket")))
+
+;; wrapper functions around specific functions provided by a backend
+
+(defun rt-liber-viewer-answer ()
+  "Answer the ticket."
+  (interactive)
+  (cond ((featurep 'rt-liberation-gnus)
+        (rt-liber-gnus-compose-reply-to-requestor))
+       (t (error "no function defined"))))
+
+(defun rt-liber-viewer-answer-this ()
+  "Answer the ticket using the current context."
+  (interactive)
+  (cond ((featurep 'rt-liberation-gnus)
+        (rt-liber-gnus-compose-reply-to-requestor-to-this))
+       (t (error "no function defined"))))
+
+(defun rt-liber-viewer-answer-verbatim-this ()
+  "Answer the ticket using the current context verbatim."
+  (interactive)
+  (cond ((featurep 'rt-liberation-gnus)
+        (rt-liber-gnus-compose-reply-to-requestor-verbatim-this))
+       (t (error "no function defined"))))
+
+(defun rt-liber-viewer-answer-provisionally ()
+  "Provisionally answer the ticket."
+  (interactive)
+  (cond ((featurep 'rt-liberation-gnus)
+        (rt-liber-gnus-compose-provisional))
+       (t (error "no function defined"))))
+
+(defun rt-liber-viewer-answer-provisionally-this ()
+  "Provisionally answer the ticket using the current context."
+  (interactive)
+  (cond ((featurep 'rt-liberation-gnus)
+        (rt-liber-gnus-compose-provisional-to-this))
+       (t (error "no function defined"))))
+
+(defun rt-liber-viewer-comment ()
+  "Comment on the ticket."
+  (interactive)
+  (cond ((featurep 'rt-liberation-gnus)
+        (rt-liber-gnus-compose-comment))
+       (t (error "no function defined"))))
+
+(defun rt-liber-viewer-comment-this ()
+  "Comment on the ticket using the current context."
+  (interactive)
+  (cond ((featurep 'rt-liberation-gnus)
+        (rt-liber-gnus-compose-comment-this))
+       (t (error "no function defined"))))
+
+
+;;; --------------------------------------------------------
+;;; Ticket browser
+;;; --------------------------------------------------------
+
+;; accept a ticket-alist object and return an alist mapping ticket
+;; properties to format characters for use in `rt-liber-format'.
+(defun rt-liber-format-function (ticket-alist)
+  "Return a pairing of TICKET-ALIST values to %-sequences."
+  (let* ((id (cdr (assoc "id" ticket-alist)))
+        (subject (cdr (assoc "Subject" ticket-alist)))
+        (status (cdr (assoc "Status" ticket-alist)))
+        (created (cdr (assoc "Created" ticket-alist)))
+        (resolved (cdr (assoc "Resolved" ticket-alist)))
+        (requestors (cdr (assoc "Requestors" ticket-alist)))
+        (creator (cdr (assoc "Creator" ticket-alist)))
+        (owner (cdr (assoc "Owner" ticket-alist)))
+        (queue (cdr (assoc "Queue" ticket-alist)))
+        (anc (if rt-liber-anc-p
+                 (rt-liber-get-ancillary-text
+                  (rt-liber-ticket-id-only ticket-alist))
+               "")))
+    (list (cons ?i (or id "N/A"))
+         (cons ?s (or subject "N/A"))
+         (cons ?c (or created "N/A"))
+         (cons ?S (or status "N/A"))
+         (cons ?r (or resolved "N/A"))
+         (cons ?R (or requestors "N/A"))
+         (cons ?C (or creator "N/A"))
+         (cons ?o (or owner "N/A"))
+         (cons ?q (or queue "N/A"))
+         (cons ?A (or anc "")))))
+
+(defun rt-liber-format (format ticket-alist)
+  "Substitute %-sequences in FORMAT."
+  (let ((alist (rt-liber-format-function ticket-alist)))
+    (replace-regexp-in-string
+     "%."
+     (lambda (str)
+       (let ((char (aref str 1)))
+        (if (eq char ?%) "%"
+          (or (cdr (assoc char alist)) ""))))
+     format t t)))
+
+(defun rt-liber-ticketlist-browser-redraw-f (ticket)
+  "Display TICKET."
+  (insert (rt-liber-format "[%c] %i" ticket))
+  (add-text-properties (point-at-bol)
+                      (point-at-eol)
+                      '(face rt-liber-ticket-face))
+  (newline)
+  (insert (rt-liber-format "    [%S] %s" ticket))
+  (let ((p (point)))
+    (insert (rt-liber-format "    %A" ticket))
+    (add-text-properties p (point)
+                        '(face font-lock-comment-face)))
+  (newline)
+  (insert (rt-liber-format "    %o <== %R" ticket)))
+
+(defun rt-liber-ticketlist-browser-redraw (ticketlist &optional query)
+  "Display TICKETLIST. Optionally display QUERY as well."
+  (erase-buffer)
+  (when query
+    (insert (format "Query: %s" query))
+    (newline)
+    (insert (format "%d tickets" (length ticketlist)))
+    (newline))
+  (when ticketlist
+    (let ((filtered-count 0))
+      (newline 2)
+      (dolist (ticket
+              (funcall rt-liber-browser-default-sorting-function
+                       ticketlist))
+       ;; skip filtered tickets, but count how many have been skipped
+       (if (funcall rt-liber-browser-default-filter-function ticket)
+           (progn
+             ;; assumes that rt-liber-ticketlist-browser-redraw-f leaves
+             ;; point at the end of the ticket drawn
+             (let ((start (point)))
+               (funcall rt-liber-custom-ticket-redraw-function ticket)
+               (add-text-properties start
+                                    (point)
+                                    (list 'rt-ticket ticket))
+               (when (and (featurep 'rt-liberation-multi)
+                          (rt-liber-ticket-marked-p ticket))
+                 (add-text-properties start
+                                      (point)
+                                      '(face rt-liber-marked-ticket-face))))
+             (newline))
+         (setq filtered-count (1+ filtered-count))))
+      (when (< 0 filtered-count)
+       (insert (format "%d tickets not shown (filtered)" filtered-count))))))
+
+(defun rt-liber-browser-refresh (&optional ignore-auto noconfirm)
+  (interactive)
+  (if rt-liber-query
+      (when (or rt-liber-browser-do-refresh
+               noconfirm)
+       ;; explicitly pass nil NEW to `rt-liber-browse-query'
+       (rt-liber-browse-query rt-liber-query nil))
+    (error "no buffer-local query")))
+
+(defun rt-liber-browser-refresh-and-return ()
+  (interactive)
+  (let ((id (rt-liber-browser-ticket-id-at-point)))
+    (rt-liber-browser-refresh)
+    (rt-liber-browser-move-point-to-ticket id)))
+
+;; This is just a special case of
+;; `rt-liber-browser-ticket-<PROPERTY>-at-point'
+(defun rt-liber-browser-ticket-id-at-point (&optional point)
+  "Return the ticket id for the ticket at buffer position.
+
+If POINT is nil then called on (point)."
+  (when (not point)
+    (setq point (point)))
+  (let ((value (rt-liber-ticket-id-only
+               (get-text-property point 'rt-ticket))))
+    (if value
+       value
+      (error "no such ticket property at point"))))
+
+(defun rt-liber-ticket-taken-p (ticket-alist)
+  "Return t if TICKET-ALIST is owned by Nobody."
+  (when (not ticket-alist)
+    (error "null argument"))
+  (let ((owner (cdr (assoc "Owner" ticket-alist))))
+    (if (string= owner "Nobody")
+       nil
+      t)))
+
+(defun rt-liber-next-ticket-in-browser ()
+  "Move point to the next ticket."
+  (interactive)
+  (let ((next (next-single-property-change (point) 'rt-ticket)))
+    (when next (goto-char next))))
+
+(defun rt-liber-previous-ticket-in-browser ()
+  "Move point to the previous ticket."
+  (interactive)
+  (let ((prev (previous-single-property-change (point) 'rt-ticket)))
+    (when prev (goto-char prev))))
+
+(defun rt-liber-display-ticket-at-point ()
+  "Display the contents of the ticket at point."
+  (interactive)
+  (let ((ticket-alist (get-text-property (point) 'rt-ticket)))
+    (rt-liber-display-ticket-history ticket-alist (current-buffer))))
+
+(defun rt-liber-browser-search (id)
+  "Return point where ticket with ID is displayed or nil."
+  (let ((p nil))
+    (save-excursion
+      (goto-char (point-min))
+      (let ((point-id (rt-liber-ticket-id-only
+                      (get-text-property (point) 'rt-ticket))))
+       (if
+           ;; (predicate) looks for the exceptional situation
+           (and point-id (string= id point-id))
+           ;; (consequent) we're done
+           (setq p (point))
+         ;; (alternative) continue looking
+         (while (and (not p)
+                     (rt-liber-next-ticket-in-browser))
+           (let ((point-id (rt-liber-ticket-id-only
+                            (get-text-property (point) 'rt-ticket))))
+             (when (string= id point-id)
+               (setq p (point))))))))
+    p))
+
+(defun rt-liber-browser-move-point-to-ticket (id)
+  "Move point to the beginning of ticket with ID."
+  (let ((p (rt-liber-browser-search id)))
+    (if p
+       (progn
+         (goto-char p)
+         (recenter-top-bottom))
+      (error "ticket #%s not found" id))))
+
+;;; --------------------------------------------------------
+;;; Ticket browser sorting
+;;; --------------------------------------------------------
+
+(defun rt-liber-lex-lessthan-p (a b field)
+  "Return t if A is lexicographically less than B in FIELD."
+  (let ((field-a (cdr (assoc field a)))
+       (field-b (cdr (assoc field b))))
+    (if (and field-a field-b)
+       (string-lessp field-a field-b)
+      (error "\"%s\" is not a valid ticket field" field))))
+
+(defun rt-liber-time-lessthan-p (a b field)
+  "Return t if A is chronologically less than B in FIELD."
+  (let ((field-a (cdr (assoc field a)))
+       (field-b (cdr (assoc field b))))
+    (if (and field-a field-b)
+       (time-less-p (date-to-time field-a)
+                    (date-to-time field-b))
+      (error "\"%s\" is not a valid ticket field" field))))
+
+(defun rt-liber-sort-ticket-list (ticket-list sort-f)
+  "Return a copy of TICKET-LIST sorted by SORT-F."
+  (let ((seq (copy-seq ticket-list)))
+    (sort seq sort-f)))
+
+(defun rt-liber-sort-by-owner (ticket-list)
+  "Sort TICKET-LIST lexicographically by owner."
+  (rt-liber-sort-ticket-list
+   ticket-list
+   #'(lambda (a b)
+       (rt-liber-lex-lessthan-p a b "Owner"))))
+
+(defun rt-liber-sort-by-time-created (ticket-list)
+  "Sort TICKET-LIST in reverse chronological order."
+  (reverse
+   (rt-liber-sort-ticket-list
+    ticket-list
+    #'(lambda (a b)
+       (rt-liber-time-lessthan-p a b "Created")))))
+
+;;; --------------------------------------------------------
+;;; Ticket browser filtering
+;;; --------------------------------------------------------
+
+;; See the fine manual for example code.
+
+(defun rt-liber-default-filter-f (ticket)
+  "The default filtering function for the ticket browser
+
+This function is really a placeholder for user custom functions,
+and as such always return t."
+  t)
+
+;;; --------------------------------------------------------
+;;; Version comparison functions
+;;; --------------------------------------------------------
+
+;; rt-liber-version-<: string * string -> t-or-nil
+(defun rt-liber-version-< (vnum1 vnum2)
+  "Test whehther version number VNUM1 is less than VNUM2.
+Arguments must be strings Lisp objects, and not numbers.
+
+Examples:
+  (rt-liber-version-< \"1.01\" \"1.11\")
+    => t
+
+  (rt-liber-version-< \"1.1\" \"1.0.1\")
+    => nil"
+  (rt-liber-version-<- (rt-liber-version-value
+                       (rt-liber-version-read vnum1))
+                      (rt-liber-version-value
+                       (rt-liber-version-read vnum2))))
+
+;; rt-liber-version-read: string -> list string
+(defun rt-liber-version-read (str)
+  "Tokenize version number STR whenever the syntax class changes.
+
+ Example:
+   \"1.043.0-1_=+\" \
+==> (\"1\" \".\" \"043\" \".\" \"0\" \"-\" \"1\" \"_=+\")"
+  (let ((tokens nil)
+       (start 0)
+       (re (mapconcat 'identity '("[[:digit:]]+" "[[:punct:]]+") "\\|")))
+    (while (and (string-match re (substring str start))
+               (> (length str) start))
+      (setq tokens (cons (match-string 0 (substring str start)) tokens))
+      (setq start (+ start (match-end 0))))
+    (if (< start (length str))
+       (error "Unknown character: %s" (substring str start (1+ start))))
+    (reverse tokens)))
+
+;; rt-liber-version-value: list string -> list number
+(defun rt-liber-version-value (tokens)
+  "Convert list of TOKENS to a comparable number list."
+  (mapcar #'(lambda (tk)
+             (if (string-match "^0+$" tk)
+                 1
+               (if (string-match "^[[:digit:]]+$" tk)
+                   (if (string-match "^0+" tk)
+                       (1+ (* (string-to-number tk)
+                              (expt 10
+                                    (- (length
+                                        (match-string 0 tk))))))
+                     (1+ (string-to-number tk)))
+                 (if (string-match "^[[:punct:]]+$" tk)
+                     0
+                   ;; else (string-match "[^[:digit:][:punct:]]" tk)
+                   -1))))
+         tokens))
+
+;; rt-liber-version-<-: list number -> t-or-nil
+(defun rt-liber-version-<- (vals1 vals2)
+  "Test whether version representation VALS1 is less than VALS2."
+  (if (and (null vals1) (null vals2))
+      nil
+    (if (null vals2)
+       nil
+      (if (null vals1)
+         t
+       (if (= (car vals1) (car vals2))
+           (rt-liber-version-<- (cdr vals1) (cdr vals2))
+         (if (< (car vals1) (car vals2))
+             t
+           nil))))))
+
+
+;;; --------------------------------------------------------
+;;; Entry points
+;;; --------------------------------------------------------
+
+(defun rt-liber-browse-query (query &optional new)
+  "Run QUERY against the server and launch the browser.
+
+NEW if non-nil create additional browser buffer. If NEW is a
+string then that will be the name of the new buffer."
+  (interactive "Mquery: ")
+  (condition-case excep
+      (rt-liber-browser-startup
+       (rt-liber-run-show-base-query
+       (rt-liber-run-ls-query query))
+       query new)
+    (rt-liber-no-result-from-query-error
+     (rt-liber-browser-with-message "no results from query"
+                                   query new))))
+
+
+;;; --------------------------------------------------------
+;;; Major mode definitions
+;;; --------------------------------------------------------
+
+(defun rt-liber-multi-delete-spam ()
+  "Delete marked tickets as spam."
+  (interactive)
+  (cond ((featurep 'rt-liberation-multi)
+        (when (y-or-n-p "Delete marked tickets as spam? ")
+          (rt-liber-multi-flag-as-spam-and-delete)))
+       (t (error "rt-liberation-multi isn't loaded"))))
+
+(defun rt-liber-browser-mode-quit ()
+  "Bury the ticket browser."
+  (interactive)
+  (bury-buffer))
+
+(defconst rt-liber-browser-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map (kbd "q") 'rt-liber-browser-mode-quit)
+    (define-key map (kbd "n") 'rt-liber-next-ticket-in-browser)
+    (define-key map (kbd "p") 'rt-liber-previous-ticket-in-browser)
+    (define-key map (kbd "RET") 'rt-liber-display-ticket-at-point)
+    (define-key map (kbd "g") 'revert-buffer)
+    (define-key map (kbd "G") 'rt-liber-browser-refresh-and-return)
+    (define-key map (kbd "s") 'rt-liber-browser-mark-as-spam)
+    (define-key map (kbd "S") 'rt-liber-multi-delete-spam)
+    (define-key map (kbd "a") 'rt-liber-browser-assign)
+    (define-key map (kbd "r") 'rt-liber-browser-resolve)
+    (define-key map (kbd "o") 'rt-liber-browser-open)
+    (define-key map (kbd "t") 'rt-liber-browser-take-ticket-at-point)
+    (define-key map (kbd "A") 'rt-liber-browser-ancillary-text)
+    (define-key map (kbd "SPC") 'scroll-up)
+    (define-key map (kbd "DEL") 'scroll-down)
+    (define-key map (kbd "m") 'rt-liber-browser-move)
+    (define-key map (kbd "M") 'rt-liber-mark-ticket-at-point)
+    map)
+  "Key map for ticket browser.")
+
+(define-derived-mode rt-liber-browser-mode nil
+  "RT Liberation Browser"
+  "Major Mode for browsing RT tickets.
+\\{rt-liber-browser-mode-map}"
+  (set (make-local-variable 'revert-buffer-function)
+       'rt-liber-browser-refresh)
+  (set (make-local-variable 'buffer-stale-function)
+       (lambda (&optional noconfirm) 'slow))
+  (set (make-local-variable 'auto-revert-interval)
+       (* 15 60)) ;; 15 minutes
+  (run-hooks 'rt-liber-browser-hook))
+
+(defun rt-liber-setup-browser-name (new)
+  (setq rt-liber-browser-buffer
+       (get-buffer-create
+        (if new
+            (generate-new-buffer-name
+             (if (stringp new)
+                 new
+               rt-liber-browser-buffer-name))
+          (if (and (boundp 'rt-liber-query)
+                   rt-liber-query)
+              (buffer-name)
+            rt-liber-browser-buffer-name)))))
+
+(defun rt-liber-browser-with-message (message &optional query new)
+  "Start the RT ticket browser and display MESSAGE."
+  (interactive)
+  (rt-liber-setup-browser-name new)
+  ;; setup stage (invisible to user)
+  (with-current-buffer rt-liber-browser-buffer
+    (let ((inhibit-read-only t))
+      (goto-char (point-min))
+      (rt-liber-ticketlist-browser-redraw nil query)
+      (newline 2)
+      (insert message)
+      (set (make-local-variable 'rt-liber-query) query)))
+  ;; display stage (user can see updates)
+  (switch-to-buffer rt-liber-browser-buffer)
+  (setq buffer-read-only t))
+
+(defun rt-liber-browser-startup (ticket-list &optional query new)
+  "Start the RT ticket browser."
+  (interactive)
+  (rt-liber-setup-browser-name new)
+  ;; setup stage (invisible to user)
+  (with-current-buffer rt-liber-browser-buffer
+    (let ((inhibit-read-only t))
+      (rt-liber-ticketlist-browser-redraw ticket-list query)
+      (goto-char (point-min))
+      (rt-liber-next-ticket-in-browser)
+      (rt-liber-browser-mode)
+      ;; store the ticket-list and the query which produced the buffer
+      ;; as buffer local variables
+      (set (make-local-variable 'rt-liber-ticket-list) ticket-list)
+      (set (make-local-variable 'rt-liber-query) query)))
+  ;; display stage (user can see updates)
+  (switch-to-buffer rt-liber-browser-buffer)
+  (setq buffer-read-only t))
+
+(defun rt-liber-browser-ancillary-text ()
+  "Wrapper function around storage backend."
+  (interactive)
+  (when (not (featurep 'rt-liberation-storage))
+    (error "rt-liberation-storage isn't loaded"))
+  (let ((initial-contents ""))
+    (rt-liber-set-ancillary-text
+     (read-from-minibuffer "Text: " initial-contents))))
+
+;;; --------------------------------------------------------
+;;; Command module
+;;; --------------------------------------------------------
+
+;; when this module is stable enough it should be documented in the
+;; manual -- yrk
+
+(defun rt-liber-command-get-dictionary-value (sym dic)
+  "Utility function for retrieving alist values."
+  (let ((value (cdr (assoc sym dic))))
+    (if value
+       value
+      (error "%s not a key in dictionary %s" sym dic))))
+
+(defun rt-liber-command-get-command-string (command-symbol)
+  "Return value associated with key COMMAND-SYMBOL."
+  (rt-liber-command-get-dictionary-value
+   command-symbol
+   rt-liber-command-dictionary))
+
+(defun rt-liber-command-get-status-string (status-symbol)
+  "Return value associated with key STATUS-SYMBOL."
+  (rt-liber-command-get-dictionary-value
+   status-symbol
+   rt-liber-status-dictionary))
+
+(defun rt-liber-command-get-custom-field-string (custom-field-symbol)
+  "Return value associated with key CUSTOM-FIELD-SYMBOL."
+  (rt-liber-command-get-dictionary-value
+   custom-field-symbol
+   rt-liber-custom-field-dictionary))
+
+(defun rt-liber-command-runner (op arg-string)
+  "Run OP command against the server with ARG-STRING."
+  (message "started '%s' command at %s..." op (current-time-string))
+  (condition-case excep
+      (with-temp-buffer
+       (call-process-shell-command rt-liber-rt-binary nil t nil
+                                   op arg-string)
+       (message "command ended at %s" (current-time-string))
+       (buffer-string))
+    (file-error
+     (error "could not find the RT binary at: %s" rt-liber-rt-binary))
+    (error "an unhandled exception occured: %s" excep)))
+
+;; the user might not see this but at the very least it will leave a
+;; trace in the *Messages* buffer -- yrk
+(defun rt-liber-command-runner-parser-f ()
+  "Display command return status from the server to the user."
+  (message (buffer-string)))
+
+(defun rt-liber-command-set-cf (id field value)
+  "Add custom field FIELD with VALUE to ID.
+If FIELD already exists, update to VALUE."
+  ;; TODO: This may not work with standard rt cli.
+  ;;
+  ;; works fine with the stock version 3.8.2 -- yrk
+
+  ;; TODO: Should probably bust comment out to its own function.
+  (let ((command (rt-liber-command-get-command-string 'comment))
+       (args
+        (format "-f %s=%s ticket/%s" field value id)))
+    (rt-liber-parse-answer
+     (rt-liber-command-runner command args)
+     'rt-liber-command-runner-parser-f)))
+
+(defun rt-liber-command-set-status (id status)
+  "Set ticket ID status to be STATUS."
+  ;; TODO: Sanity check status
+  ;; TODO: defmacro?
+  (let ((command (rt-liber-command-get-command-string 'edit))
+       (args
+        (format "ticket/%s set status=%s" id status)))
+    (rt-liber-parse-answer
+     (rt-liber-command-runner command args)
+     'rt-liber-command-runner-parser-f)))
+
+(defun rt-liber-command-set-status-deleted (id)
+  "Set the status of ticket ID to `deleted'."
+  (rt-liber-command-set-status
+   id (rt-liber-command-get-status-string 'deleted)))
+
+(defun rt-liber-command-set-status-resolved (id)
+  "Set the status of ticket ID to `resolved'."
+  (rt-liber-command-set-status
+   id (rt-liber-command-get-status-string 'resolved)))
+
+(defun rt-liber-command-set-status-open (id)
+  "Set the status of ticket ID to `open'."
+  (rt-liber-command-set-status
+   id (rt-liber-command-get-status-string 'open)))
+
+(defun rt-liber-command-set-owner (id owner)
+  "Set the owner of ticket ID to OWNER."
+  (let ((command (rt-liber-command-get-command-string 'edit))
+       (args
+        (format "ticket/%s set owner=%s" id owner)))
+    (rt-liber-parse-answer
+     (rt-liber-command-runner command args)
+     'rt-liber-command-runner-parser-f)))
+
+(defun rt-liber-command-set-queue (id queue)
+  "Set the queue of ticket ID to QUEUE."
+  (let ((command (rt-liber-command-get-command-string 'edit))
+       (args
+        (format "ticket/%s set queue=%s" id queue)))
+    (rt-liber-parse-answer
+     (rt-liber-command-runner command args)
+     'rt-liber-command-runner-parser-f)))
+
+(defun rt-liber-browser-assign (name)
+  "Assign current ticket to a user NAME."
+  (interactive "sAssign to: ")
+  (let ((taken-p (rt-liber-ticket-taken-p
+                 (get-text-property (point) 'rt-ticket))))
+    (when (or (not taken-p)
+             (and taken-p
+                  (y-or-n-p "Ticket already assigned! Are you sure?")))
+      (rt-liber-command-set-owner
+       (rt-liber-browser-ticket-id-at-point)
+       name)
+      (rt-liber-browser-refresh-and-return))))
+
+(defun rt-liber-browser-resolve ()
+  "Resolve the current ticket."
+  (interactive)
+  (rt-liber-command-set-status-resolved
+   (rt-liber-browser-ticket-id-at-point))
+  (rt-liber-browser-refresh-and-return))
+
+(defun rt-liber-browser-open ()
+  "Open the current ticket."
+  (interactive)
+  (rt-liber-command-set-status-open
+   (rt-liber-browser-ticket-id-at-point))
+  (rt-liber-browser-refresh-and-return))
+
+(defun rt-liber-browser-move (queue)
+  "Move the current ticket to a different queue."
+  (interactive "sQueue: ")
+  (rt-liber-command-set-queue
+   (rt-liber-browser-ticket-id-at-point)
+   queue)
+  (rt-liber-browser-refresh))
+
+(defun rt-liber-browser-mark-as-spam ()
+  "Mark the current ticket as spam, and delete it."
+  (interactive)
+  (if (y-or-n-p "Delete marked ticket as spam? ")
+      (let ((id (rt-liber-browser-ticket-id-at-point)))
+       (rt-liber-command-set-cf
+        id (rt-liber-command-get-custom-field-string 'cf-is-spam) "yes")
+       (rt-liber-command-set-status-deleted id)
+       (rt-liber-browser-refresh))
+    (message "aborted")))
+
+(defun rt-liber-browser-take-ticket-at-point ()
+  "Assign the ticket under point to `rt-liber-username'."
+  (interactive)
+  (when (not rt-liber-username)
+    (error "`rt-liber-username' is nil"))
+  (let ((taken-p (rt-liber-ticket-taken-p
+                 (get-text-property (point) 'rt-ticket))))
+    (when (or (not taken-p)
+             (and taken-p
+                  (y-or-n-p "Ticket already taken! Are you sure?")))
+      (rt-liber-command-set-owner
+       (rt-liber-browser-ticket-id-at-point)
+       rt-liber-username)
+      (rt-liber-browser-refresh))))
+
+(defun rt-liber-viewer-take-ticket ()
+  "Assign the current ticket to `rt-liber-username'."
+  (interactive)
+  (when (not rt-liber-username)
+    (error "`rt-liber-username' is nil"))
+  (let ((id (rt-liber-ticket-id-only rt-liber-ticket-local))
+       (taken-p (rt-liber-ticket-taken-p rt-liber-ticket-local)))
+    (if id
+       (progn
+         (when (or (not taken-p)
+                   (and taken-p
+                        (y-or-n-p "Ticket already taken! Are you sure?")))
+           (rt-liber-command-set-owner id rt-liber-username)
+           (rt-liber-refresh-ticket-history)))
+      (error "no ticket currently in view"))))
+
+(provide 'rt-liberation)
+
+;;; rt-liberation.el ends here.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]