aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--GPL340
-rw-r--r--Makefile5
-rw-r--r--README353
-rw-r--r--connection.el169
-rwxr-xr-xdeb/README.debian14
-rwxr-xr-xdeb/changelog158
-rwxr-xr-xdeb/control18
-rwxr-xr-xdeb/copyright13
-rwxr-xr-xdeb/dirs5
-rwxr-xr-xdeb/install.debian30
-rwxr-xr-xdeb/postinst6
-rwxr-xr-xdeb/prerm5
-rwxr-xr-xdeb/remove.debian17
-rwxr-xr-xdeb/rules53
-rwxr-xr-xdictionary-init.el24
-rw-r--r--dictionary.el844
-rwxr-xr-xinstall-package.el7
-rw-r--r--link.el120
-rw-r--r--lpath.el4
19 files changed, 2185 insertions, 0 deletions
diff --git a/GPL b/GPL
new file mode 100644
index 0000000..60549be
--- /dev/null
+++ b/GPL
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library 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) 19yy <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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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) 19yy 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 Library General
+Public License instead of this License.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..05f9096
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,5 @@
+EMACS=emacs
+
+all:
+ $(EMACS) -q -no-site-file -no-init-file -batch -l lpath.el \
+ -f batch-byte-compile dictionary.el link.el connection.el
diff --git a/README b/README
new file mode 100644
index 0000000..32904eb
--- /dev/null
+++ b/README
@@ -0,0 +1,353 @@
+Emacs package for talking to a dictionary server
+
+Introduction
+
+Recently I installed the dictd server, which can be used to access several
+dictionaries using a simple protocol as defined in RFC 2229 (Text Version).
+
+As my primary working environment is XEmacs 20.4, I decided to write an
+Emacs-Lisp package for accessing this dictionary server. The older
+webster.el didn't worked with the newer protocol. After starting the
+implementation I was pointed to an already existing implementation, but this
+was basically a wrapper to the dict client program and didn't have all the
+features I wanted.
+
+If you didn't received this file from its original location you can visit it
+at http://www.in-berlin.de/User/myrkr/dictionary.html
+
+Features
+
+The dictionary mode provides the following features:
+
+ * looking up word definitions in all dictionaries
+ * search for matching word
+ * words/phrases marked with { } in the dictionary definitions are
+ recognized as hyper links and browseable
+ * easy selection of dictionary and search strategy
+ * backward moving through the visited definitions
+
+Here is a sample screenshot showing the dictionary mode in action within a
+XEmacs buffer:
+
+[Image]
+
+This buffer shows the result of searching the definition for Emacs. Two
+entries have been found. The bold text on the top are buttons for selecting
+action using the mouse or keyboard, the blue words are hyper links that
+points to the definitions of these words.
+
+Installation
+
+Download and Requirements
+
+I have tested the package with a native GNU Emacs 19.34.1 and XEmacs 20.4. I
+implemented some hacks to work with the very very old custom.el file in the
+above GNU Emacs. Please update to the current version whenever possible.
+
+ * Current version (1.2.1) of this package
+ * Version 1.1 of this package
+ * Version 1.0 of this package
+
+I you want to know more about the differences please look at the ChangeLog.
+
+You will need the custom package to use this package. For full support
+please check if your system knows the defface function, if not please
+download the current version.
+
+For best usuability I suggest using the mouse, but it provide good keyboard
+support as well.
+
+Unpacking the archive
+
+The package is distributed as tar.gz file. You unpack it using:
+
+gunzip dictionary-1.2.1.tar.gz | tar xf -
+
+or
+
+tar -xzf dictionary-1.2.1.tar.gz
+
+(with the version number subject to change) depending on whether you are
+using GNU tar which support the z flag for compression. After unpacking the
+archive a directory dictionary-1.2.1 has been created containing the
+necessary files.
+
+Byte compiling
+
+For faster loading and executing of the package I strongly suggest that you
+bytecompile the files. Emacs user please call make within the create
+subdirectory, XEmacs user has to specifiy there favorite tool using make
+EMACS=xemacs. If your custom package is not up-to-date expect some warnings
+about free variables.
+
+Installing the files
+
+To install the files into your GNU Emacs/XEmacs installation please copy the
+*.elc files into a directory being in your load-path variable. On most
+installations /usr/lib/emacs/site-lisp or /usr/local/lib/emacs/site-lisp are
+suitable locations.
+
+Loading the package
+
+You have to insert some instructions into your .emacs file to load the
+dictionary package whenever needed. I suggest using the following lines:
+
+(autoload 'dictionary-search "dictionary"
+ "Ask for a word and search it in all dictionaries" t)
+(autoload 'dictionary-match-words "dictionary"
+ "Ask for a word and search all matching words in the dictionaries" t)
+(autoload 'dictionary "dictionary"
+ "Create a new dictionary buffer" t)
+
+In addition, some keybindings for faster access can be useful. I use the
+following ones in my installation:
+
+(global-set-key [(control c) ?s] 'dictionary-search)
+(global-set-key [(control c) ?m] 'dictionary-match-words)
+
+I will describe the user-callable functions and the keybindings within
+dictionary mode later in this document.
+
+Using the package
+
+Glossary
+
+Before I start describing how you use this package, please let me explain
+some words as they are used in this text:
+
+word
+ This is a word you want to lookup in the dictionaries verbatim.
+pattern
+ This is used for looking up matching words. A pattern can be as simple
+ as a single word but also as complex as a POSIX regular expression. The
+ meaning of a pattern depends on the strategy used for matching words.
+dictionary
+ The server can handle serveral distinct dictionaries. You can select
+ specific dictionaries or ask the server to search in all dictionaries
+ or until matches or definitions are found. To search in all
+ dictionaries the special name * is used, the special name ! requests to
+ search until definitions are found. For more details please take a look
+ at the standards definition.
+definition
+ A dictionary entry that can be the result of a word search.
+search
+ The operation of looking up a word in the dictionaries.
+match
+ The operation of comparing a pattern to all words in the dictionary.
+strategy
+ While matching in a dictionary serveral methods for comparing words can
+ be used. These methods are named strategies and include exact match,
+ regualare expression match, and soundex match. The available strategies
+ depends on the server, but a special name . can be used to denote a
+ server-default strategy.
+
+Invoking
+
+There are four different (documented) ways of invoking the package. By
+calling dictionary you can start a new dictionary buffer waiting for your
+commands. If you want to create multiple buffers for searching the
+dictionary, you can run this function muliple times. dictionary-search will
+ask for a word a search defaulting to the word at point and present all
+definitions found.
+
+If you want to lookup the word near the point without further confirmation
+use the dictionary-lookup-definition function. The last one is
+dictionary-match-words which will ask for a pattern and display all matching
+words.
+
+If you get an error message that the server could not be contacted, please
+check the values of the variables dictionary-server and dictionary-port. The
+port should usually be 2628, the default server as distributed is dict.org.
+
+You can have multiple independent dictionary buffer. If the above functions
+are called from within dictionary mode they reuse the existing buffer.
+Otherwise they create a new buffer.
+
+If you encounter emacs blocking forever while searching an entry and you are
+using MULE you should check the value of the connection-broken-end-of-line
+variable, which can be set to t in this case.
+
+Quitting
+
+Once a dictionary buffer is created you can close it by simply typing q
+(dictionary-close). Another, more cruel, way is to use the kill-buffer
+function which is handled correctly.
+
+The dictionary mode save the window configuration on startup and try to
+reestablish it when the buffer is being closed.
+
+Using the buffer
+
+After a successful search the buffer is devided into two sections. The first
+one is the button area at the top, the other one is the text buffer
+displaying the result. By pressing the buttons you can select some functions
+that are otherwise inaccessible with the mouse.
+
+In the text are each definition is introduced by the name of the database
+that contains it. In the default configuration this text is in italic face.
+The definition itself can contains hyperlinks that are marked using blue
+foreground and both sensitive to clicking with the mouse and pressing return
+while being within the link.
+
+Each link selection or otherwise selected new search or match will create a
+new buffer showing the new result. You can use the Back button on the top or
+the l key (dictionary-previous) to return the previous buffer contents.
+
+Pressing Meta while clicking on a link to start the search will extent the
+search to all dictionaries (dictionary-default-dictionary to be more
+precisly).
+
+If you prefer using the keyboard it can be very frustrating to use the
+cursor key to position the point before pressing return to visit the link is
+possible. Therefore, I defined the Tab and the n keys to jump to the next
+link (dictionary-next-link) and the Shift-Tab and p keys to jump to the
+previous one (dictionary-prev-link).
+
+Searching
+
+The search operation can be invoked by using the Search Definition button on
+the top or by pressing s (dictionary-search). It will ask for a word to
+search and will default to the word near point. This allows you to edit the
+word before starting the search. The found definitions will be displayed
+inside the buffer. If no entries could not be found an error message will be
+displayed.
+
+If you want to quickly lookup the word at the point without further
+confirmation use the d key (dictionary-lookup-definition). Except for not
+allowing to edit the search word before asking the server it behaves the
+same way as the normal search operation.
+
+Matching
+
+The match operation is started upon pressing the Matching Words button or
+pressing the m key (dictionary-match-words). It will use the current
+database and the current strategy and list matching words for the one you
+entered at the prompt. The output is grouped by dictionary and each found
+word can be looked up by clicking the word or pressing return. Please note
+that in some cases not only the requested definition but some similiar
+definitions are shown. This behaviour is caused by the keyword lookup in the
+server. E.g., when you ask for the definition of from in Webster you will
+presented with the definitions of from and Thrust, the latter includes the
+phrase To thrust away or from which causes the display.
+
+Selecting dictionary
+
+By default all dictionaries (special name is "*") are searched for a word
+definition or for matching words. You can select a specific word for both
+modi by pressing the Select Default Dictionary button or the D key
+(dictionary-select-dictionary). You will get a message about successful
+selection.
+
+If you hold Meta while selecting a dictionary you will get more information
+displayed instead.
+
+If you want to restore the original behaviour select All dictionaries. The
+first matching dictionary is a special dictionary (named "!") where the
+search will stop at the first dictionary with found definitions or matching
+words.
+
+Selection search strategy
+
+While searching matching words to the pattern you entered the server can use
+different comparison algorithm (aka search strategy). Every server provides
+a default strategy which is internally known as ".".
+
+After pressing the Select Match Strategy button or pressing the M key
+(dictionary-select-strategy) all available strategies on this server are
+presented. As in the "select dictionary" mode you can select it by pressing
+the mouse button 2 or typing return.
+
+Going backward
+
+If you visited a link and want to go back to the previous definition, simply
+choose the Back button or press the l key (dictionary-previous). The buffer
+contents and cursor position will be restored. If you intented to go beyond
+the first definition an error message will appear.
+
+Getting Help
+
+If you are totally confused what all the keys do in your dictionary buffer
+some help will displayed by pressing the h key. Press q to make the help go
+away. This help buffer will display the default key bindings only as I had
+problems with displaying multiple bindings for a single function (e.g., both
+button2 and return select a link). Any suggestions are welcome.
+
+Customizing
+
+If you have an sufficient recent custom version installed (e.g., the one
+provided in XEmacs 20.4) you can use the customize-group with the dictionary
+group to customize this package. For using the customize buffer please refer
+to its online help.
+
+Of course you can set all the variables and hooks you want in the startup
+file. Here is a little example that I use for selecting the server on my
+local machine and for binding some function to the user-reserved keys
+starting from C-c a to C-c z.
+
+(global-set-key [(control c) ?s] 'dictionary-search)
+(global-set-key [(control c) ?m] 'dictionary-match-words)
+(setq dictionary-server "localhost")
+
+Thanks
+
+I want to thank Sam Steingold, Baoqiu Cui, and Bruce Ravel for their
+valuable suggestions (including patches) for improving this package.
+
+License
+
+This file 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, or (at your option) any later
+version.
+
+This file 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 version 2
+along with this package; see the file GPL.
+
+ChangeLogs
+
+Version 1.2 - 1.2.1
+
+ * Corrected dictionary command to draw the button bar.
+ * Improved documentation on dictionary to explicitly mention the use of
+ multiple buffers.
+
+Version 1.1.1 - 1.2
+
+ * Some users reported problems with GNU Emacs 20.3 and MULE. So I
+ introduced a new variable connection-broken-end-of-line which controls
+ whether a line is ended by \n or by \r\n. You can use the
+ customize-group command on dictionary to change the setting of the
+ variable.
+
+Version 1.1 - 1.1.1
+
+ * dictionary-search now allows editing the word to search for
+ * dictionary-search-word-near-point has been removed, you can use
+ dictionary-lookup-definition instead. It behaves like dictionary-search
+ but don't allow the search word to be edited (to speed up looking up
+ words).
+
+Version 1.0 - 1.1
+
+ * all dictionary buffers now share a single connection
+ * added kill-all-local-variables
+ * use cons instead of list where possible
+ * dictionary-search now:
+ o use word as point as default (implementing
+ dictionary-search-word-near-point too)
+ o asks for dictionary with prefix argument
+ * added help-echo tags which are used in XEmacs
+ * mark has been replaced by generic marker
+ * added messages for communications to the dictionary server that may
+ take a while
+ * fixed bug with going to the previous link
+ * replaced word-at-point by current-word
+
+ ------------------------------------------------------------------------
+Torsten Hilbrich
+Last modified: Sun May 7 11:06:16 CEST 2000
diff --git a/connection.el b/connection.el
new file mode 100644
index 0000000..c83be81
--- /dev/null
+++ b/connection.el
@@ -0,0 +1,169 @@
+;;; connection.el -- handling a tcp based connection
+
+;; Author: Torsten Hilbrich <Torsten.Hilbrich@gmx.net>
+;; Keywords: network
+;; $Id: connection.el,v 1.6 2000/04/16 08:45:21 torsten Exp $
+
+;; This file 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, or (at your option)
+;; any later version.
+
+;; This file 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 GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+(eval-when-compile
+ (require 'cl))
+
+(defcustom connection-broken-end-of-line
+ nil
+ "Set to t (on) if you use a MULE Emacsen and have problems while connecting.
+Usually for the dict protocol, the end of line characters are \\r\\n.
+However, some users reported problems with using Emacs 20.3 and MULE
+which seems to convert the \\r\\n to \\n while inserting the text into
+the buffer. If you encounter these problems please set the value to t
+and try again.
+"
+ :group 'dictionary
+ :type 'boolean)
+
+(defmacro connection-p (connection)
+ "Returns non-nil if `connection' is a connection object"
+ (list 'get connection ''connection))
+
+(defmacro connection-read-point (connection)
+ "Return the read point of the connection object."
+ (list 'get connection ''connection-read-point))
+
+(defmacro connection-process (connection)
+ "Return the process of the connection object."
+ (list 'get connection ''connection-process))
+
+(defmacro connection-buffer (connection)
+ "Return the buffer of the connection object."
+ (list 'get connection ''connection-buffer))
+
+(defmacro connection-set-read-point (connection point)
+ "Set the read-point for `connection' to `point'."
+ (list 'put connection ''connection-read-point point))
+
+(defmacro connection-set-process (connection process)
+ "Set the process for `connection' to `process'."
+ (list 'put connection ''connection-process process))
+
+(defmacro connection-set-buffer (connection buffer)
+ "Set the buffer for `connection' to `buffer'."
+ (list 'put connection ''connection-buffer buffer))
+
+(defun connection-create-data (buffer process point)
+ "Create a new connection data based on `buffer', `process', and `point'."
+ (let ((connection (make-symbol "connection")))
+ (put connection 'connection t)
+ (connection-set-read-point connection point)
+ (connection-set-process connection process)
+ (connection-set-buffer connection buffer)
+ connection))
+
+(defun connection-open (server port)
+ "Open a connection to `server' and `port'.
+A data structure identifing the connection is returned"
+
+ (let ((process-buffer (generate-new-buffer (format " connection to %s:%s"
+ server
+ port)))
+ (process))
+ (save-excursion
+ (set-buffer process-buffer)
+ (setq process (open-network-stream "connection" process-buffer
+ server port))
+ (connection-create-data process-buffer process (point-min)))))
+
+(defun connection-status (connection)
+ "Return the status of the connection.
+Possible return values are the symbols:
+nil: argument is no connection object
+'none: argument has no connection
+'up: connection is open and buffer is existing
+'down: connection is closed
+'alone: connection is not associated with a buffer"
+ (if (connection-p connection)
+ (let ((process (connection-process connection))
+ (buffer (connection-buffer connection)))
+ (if (not process)
+ 'none
+ (if (not (buffer-live-p buffer))
+ 'alone
+ (if (not (eq (process-status process) 'open))
+ 'down
+ 'up))))
+ nil))
+
+(defun connection-close (connection)
+ "Force closing of the connection."
+ (if (connection-p connection)
+ (progn
+ (let ((buffer (connection-buffer connection))
+ (process (connection-process connection)))
+ (if process
+ (delete-process process))
+ (if buffer
+ (kill-buffer buffer))
+
+ (connection-set-process connection nil)
+ (connection-set-buffer connection nil)))))
+
+(defun connection-send (connection data)
+ "Send `data' to the process."
+ (unless (eq (connection-status connection) 'up)
+ (error "Connection is not up"))
+ (save-excursion
+ (set-buffer (connection-buffer connection))
+ (goto-char (point-max))
+ (connection-set-read-point connection (point))
+ (process-send-string (connection-process connection) data)))
+
+(defun connection-send-crlf (connection data)
+ "Send `data' together with CRLF to the process."
+ (connection-send connection (concat data "\r\n")))
+
+(defun connection-read (connection delimiter)
+ "Read data until `delimiter' is found inside the buffer."
+ (unless (eq (connection-status connection) 'up)
+ (error "Connection is not up"))
+ (let ((case-fold-search nil)
+ match-end)
+ (save-excursion
+ (set-buffer (connection-buffer connection))
+ (goto-char (connection-read-point connection))
+ ;; Wait until there is enough data
+ (while (not (search-forward delimiter nil t))
+ (accept-process-output (connection-process connection) 3)
+ (goto-char (connection-read-point connection)))
+ (setq match-end (point))
+ ;; Return the result
+ (let ((result (buffer-substring (connection-read-point connection)
+ match-end)))
+ (connection-set-read-point connection match-end)
+ result))))
+
+(defun connection-read-crlf (connection)
+ "Read until a line is completedx with CRLF"
+ (connection-read connection (if connection-broken-end-of-line
+ "\n"
+ "\r\n")))
+
+(defun connection-read-to-point (connection)
+ "Read until a line is consisting of a single point"
+ (connection-read connection (if connection-broken-end-of-line
+ "\n.\n"
+ "\r\n.\r\n")))
+
+
+(provide 'connection) \ No newline at end of file
diff --git a/deb/README.debian b/deb/README.debian
new file mode 100755
index 0000000..d5bf0de
--- /dev/null
+++ b/deb/README.debian
@@ -0,0 +1,14 @@
+dictionary for Debian
+----------------------
+
+This is an unofficial debian package for the dictionary client found
+at http://www.myrkr.in-berlin.de/dictionary.html.
+
+A official package named 'dictionary-el' is now maintained by Aaron
+M. Ucko <ucko@debian.org>, as debian user you probably should use this
+package.
+
+Instructions on using this package can be found in the
+/usr/share/doc/dictionary/README.gz file or in the above location.
+
+Torsten Hilbrich <dictionary@myrkr.in-berlin.de>, Sun, 13 May 2001 09:55:20 +0200
diff --git a/deb/changelog b/deb/changelog
new file mode 100755
index 0000000..2c6d6d2
--- /dev/null
+++ b/deb/changelog
@@ -0,0 +1,158 @@
+dictionary (1.8.7-1) unstable; urgency=low
+
+ * fixed decoding problem when selecting dictionary (problem reported by
+ Kuno Strassmann)
+
+ -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Sat, 2 Oct 2004 08:05:37 +0200
+
+dictionary (1.8.6-1) unstable; urgency=low
+
+ * added patch fixing the wrong display of dictionary description
+ (provided by Sergei Pokrovsky)
+ * added dictionary-description-open-delimiter and
+ dictionary-description-close-delimiter (suggested by Sergei Pokrovsky)
+
+ -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Sat, 25 Sep 2004 17:05:51 +0200
+
+dictionary (1.8.5-1) unstable; urgency=low
+
+ * added variable dictionary-use-single-buffer to allow selecting
+ between single/multiple buffers for dictionary access
+ * added tooltip support for XEmacs based on balloon-help
+
+ -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Sat, 21 Jun 2003 18:55:54 +0200
+
+dictionary (1.8.4-1) unstable; urgency=low
+
+ * install-pkg was missing in the last tarball
+
+ -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Sat, 12 Oct 2002 11:58:32 +0200
+
+dictionary (1.8.3-1) unstable; urgency=low
+
+ * Fixed multiple defined function in dictionary.el
+
+ -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Fri, 20 Sep 2002 22:19:06 +0200
+
+dictionary (1.8.2-1) unstable; urgency=low
+
+ * fixed Makefile
+
+ -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Fri, 14 Jun 2002 19:31:53 +0200
+
+dictionary (1.8-1) unstable; urgency=low
+
+ * added search for similiar words when the searched word is not found.
+
+ -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Wed, 20 Mar 2002 21:27:54 +0100
+
+dictionary (1.7.4-1) unstable; urgency=low
+
+ * dictionary.el (dictionary-do-matching): removed quotes around
+ dictionary name and match strategy
+
+ * dictionary.el (dictionary-do-search): removed quotes around dictionary
+ name
+
+ * dictionary.el (dictionary-display-more-info): removed quotes around
+ dictionary name
+
+ This problem (occurring with jdictd) was reported by E C Vijil
+
+ -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Fri, 15 Mar 2002 21:19:23 +0100
+
+dictionary (1.7.3-1) unstable; urgency=low
+
+ * dictionary.el (dictionary-default-popup-strategy): added this
+ variable and changed dictionary-popup-matching-words to use
+ this as matching strategy (suggested by Renaud Pons)
+
+ -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Tue, 29 Jan 2002 10:27:49 +0100
+
+dictionary (1.7.2-1) unstable; urgency=low
+
+ * link.el (link-initialize-keymap): fixed keybinding bug (reported by
+ David A. Panariti)
+
+ -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Fri, 21 Dec 2001 18:50:20 +0100
+
+dictionary (1.7.1-1) unstable; urgency=low
+
+ * Fixed bug in dictionary-coding-system, the detection of non-mule
+ Emacsen was not correct
+
+ -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Sat, 15 Dec 2001 14:29:29 +0100
+
+dictionary (1.7-1) unstable; urgency=low
+
+ * Added first support for dictionaries with different encodings than
+ utf-8.
+
+ -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Sun, 9 Dec 2001 14:21:57 +0100
+
+dictionary (1.6-1) unstable; urgency=low
+
+ * added HTTP proxy support using the CONNECT request type
+
+ -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Tue, 4 Dec 2001 20:22:03 +0100
+
+dictionary (1.5.3-1) unstable; urgency=low
+
+ * changed name of "select dictionary" button
+ * "select dictionary" and "select matching strategie" now has a better
+ feedback (by returning to the previous state)
+ * added support for non-colored display, the links are surrounded by
+ braces
+
+ -- Torsten Hilbrich <Torsten.Hilbrich@gmx.net> Sun, 14 Oct 2001 16:08:12 +0200
+
+dictionary (1.5.2-1) unstable; urgency=low
+
+ * popup menu now correctly records the selected window
+
+ -- Torsten Hilbrich <Torsten.Hilbrich@gmx.net> Sun, 2 Sep 2001 10:40:59 +0200
+
+dictionary (1.5.1-1) unstable; urgency=low
+
+ * corrected bug with dictionary-previous (found by Rui Zhu)
+ * corrected key bindings in link.el
+
+ -- Torsten Hilbrich <Torsten.Hilbrich@gmx.net> Tue, 17 Jul 2001 20:47:58 +0200
+
+dictionary (1.5-1) unstable; urgency=low
+
+ * added tooltip support for emacs
+
+ -- Torsten Hilbrich <Torsten.Hilbrich@gmx.net> Sun, 8 Jul 2001 21:01:12 +0200
+
+dictionary (1.4.1-1) unstable; urgency=low
+
+ * changed recognition of utf-8 support (suggested by Enrico Scholz)
+
+ -- Torsten Hilbrich <Torsten.Hilbrich@gmx.net> Fri, 6 Jul 2001 23:08:48 +0200
+
+dictionary (1.4-1) unstable; urgency=low
+
+ * support for popup menus
+
+ -- Torsten Hilbrich <Torsten.Hilbrich@gmx.net> Fri, 6 Jul 2001 19:54:54 +0200
+
+dictionary (1.3.3-1) unstable; urgency=low
+
+ * added support for xemacs 21 packages (no changes for debian)
+
+ -- Torsten Hilbrich <Torsten.Hilbrich@gmx.net> Wed, 27 Jun 2001 17:56:44 +0200
+
+dictionary (1.3.2-1) unstable; urgency=low
+
+ * removed use of set-text-properties in link.el
+
+ -- Torsten Hilbrich <Torsten.Hilbrich@gmx.net> Fri, 22 Jun 2001 21:39:47 +0200
+
+dictionary (1.3.1-1) unstable; urgency=low
+
+ * Initial release.
+
+ -- Torsten Hilbrich <Torsten.Hilbrich@gmx.net> Sun, 13 May 2001 09:55:20 +0200
+
+
diff --git a/deb/control b/deb/control
new file mode 100755
index 0000000..fed4dd5
--- /dev/null
+++ b/deb/control
@@ -0,0 +1,18 @@
+Source: dictionary
+Section: unofficial
+Priority: optional
+Maintainer: Torsten Hilbrich <dictionary@myrkr.in-berlin.de>
+Build-Depends: dpkg-dev, debmake
+Standards-Version: 3.2.1
+
+Package: dictionary
+Architecture: all
+Depends: emacsen
+Description: dictionary client for emacs
+ This dictionary client provides access to a dictionary server
+ (as defined in RFC 2229) from within Emacs or XEmacs.
+ .
+ It supports utf-8 (currently available in Emacs 21) and allows
+ to follow links (marked by {braces}) within the definitions.
+ .
+ This is an unofficial debian package.
diff --git a/deb/copyright b/deb/copyright
new file mode 100755
index 0000000..b82cc97
--- /dev/null
+++ b/deb/copyright
@@ -0,0 +1,13 @@
+This package was debianized by Torsten Hilbrich <dictionary@myrkr.in-berlin.de> on Sun, 13 May 2001 09:55:20 +0200.
+
+It was downloaded from http://www.myrkr.in-berlin.de/dictionary.html
+
+Copyright:
+
+dictionary is licensed under the GNU General Public License version 2 or
+higher.
+
+On Debian systems the full text of this licence can be found
+in /usr/share/common-licenses/GPL.
+
+
diff --git a/deb/dirs b/deb/dirs
new file mode 100755
index 0000000..9d129ef
--- /dev/null
+++ b/deb/dirs
@@ -0,0 +1,5 @@
+usr/lib/emacsen-common/packages/install
+usr/lib/emacsen-common/packages/remove
+usr/share/doc/dictionary
+usr/share/emacs/site-lisp
+
diff --git a/deb/install.debian b/deb/install.debian
new file mode 100755
index 0000000..ad76efb
--- /dev/null
+++ b/deb/install.debian
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+PACKAGE=dictionary
+FLAVOUR=$1
+ELDIR=/usr/share/emacs/site-lisp/
+ELCDIR=/usr/share/$FLAVOUR/site-lisp/
+EFLAGS="-batch -q -l lpath.el -f batch-byte-compile"
+CONFFILE=${ELDIR}/${PACKAGE}-init.el
+CONFDIR=/etc/$FLAVOUR/site-start.d/
+
+SOURCES="dictionary.el connection.el link.el"
+
+case "$FLAVOUR" in
+ emacs) echo "install/$PACKAGE: Ignoring emacs";;
+ *) echo -n "install/$PACKAGE: Byte-compiling for $FLAVOUR..."
+ install -m 755 -d $ELCDIR
+ for i in $SOURCES; do cp $ELDIR/$i $ELCDIR; done
+ (cd $ELCDIR && \
+ echo '(setq load-path (cons "." load-path))' > lpath.el
+ $FLAVOUR $EFLAGS $SOURCES 2>/dev/null
+ rm lpath.el )
+ cp ${CONFFILE} ${CONFDIR}/50${PACKAGE}.el
+ cd $ELCDIR
+ for i in $SOURCES; do rm -f $ELCDIR/*.el; done
+ echo " done."
+ ;;
+esac
+
+
+
diff --git a/deb/postinst b/deb/postinst
new file mode 100755
index 0000000..2333df3
--- /dev/null
+++ b/deb/postinst
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+PACKAGE=dictionary
+
+/usr/lib/emacsen-common/emacs-package-install $PACKAGE
+
diff --git a/deb/prerm b/deb/prerm
new file mode 100755
index 0000000..bc7ec08
--- /dev/null
+++ b/deb/prerm
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+PACKAGE=dictionary
+
+/usr/lib/emacsen-common/emacs-package-remove $PACKAGE
diff --git a/deb/remove.debian b/deb/remove.debian
new file mode 100755
index 0000000..991d208
--- /dev/null
+++ b/deb/remove.debian
@@ -0,0 +1,17 @@
+#!/bin/sh
+PACKAGE=dictionary
+FLAVOUR=$1
+ELCDIR=/usr/share/$FLAVOUR/site-lisp/
+
+SOURCE="connection.el dictionary.el link.el"
+CONFFILE=/etc/$FLAVOUR/site-start.d/50${PACKAGE}.el
+
+case "$FLAVOUR" in
+ emacs) echo "install/$PACKAGE: Ignoring emacs";;
+ *) echo -n "remove/$PACKAGE: Removing for $FLAVOUR..."
+ cd $ELCDIR
+ for i in $SOURCE; do rm -f ${i}c; done
+ rm ${CONFFILE}
+ echo " done."
+ ;;
+esac
diff --git a/deb/rules b/deb/rules
new file mode 100755
index 0000000..1a67696
--- /dev/null
+++ b/deb/rules
@@ -0,0 +1,53 @@
+#!/usr/bin/make -f
+# Made with the aid of debmake, by Christoph Lameter,
+# based on the sample debian/rules file for GNU hello by Ian Jackson.
+
+package=dictionary
+
+build:
+ $(checkdir)
+
+ touch build
+
+clean:
+ $(checkdir)
+ -rm -f build
+ -rm -f `find . -name "*~"`
+ -rm -rf debian/tmp debian/files* core debian/substvars
+
+binary-indep: checkroot build
+ $(checkdir)
+# There are no architecture-independent files to be uploaded
+# generated by this package. If there were any they would be
+# made here.
+
+binary-arch: checkroot build
+ $(checkdir)
+ -rm -rf debian/tmp
+ install -d debian/tmp
+ cd debian/tmp && install -d `cat ../dirs`
+
+ cp dictionary.el connection.el link.el dictionary-init.el \
+ debian/tmp/usr/share/emacs/site-lisp
+ cp debian/install.debian debian/tmp/usr/lib/emacsen-common/packages/install/dictionary
+ chmod 755 debian/tmp/usr/lib/emacsen-common/packages/install/dictionary
+ cp debian/remove.debian debian/tmp/usr/lib/emacsen-common/packages/remove/dictionary
+ chmod 755 debian/tmp/usr/lib/emacsen-common/packages/remove/dictionary
+
+ debstd README
+ dpkg-gencontrol -isp
+ chown -R root.root debian/tmp
+ chmod -R go=rX debian/tmp
+ dpkg --build debian/tmp ..
+
+define checkdir
+ test -f debian/rules
+endef
+
+binary: binary-indep binary-arch
+
+checkroot:
+ $(checkdir)
+ test root = "`whoami`"
+
+.PHONY: binary binary-arch binary-indep clean checkroot
diff --git a/dictionary-init.el b/dictionary-init.el
new file mode 100755
index 0000000..540dfc3
--- /dev/null
+++ b/dictionary-init.el
@@ -0,0 +1,24 @@
+;; $Id: dictionary-init.el,v 1.7 2003/06/21 17:55:15 torsten Exp $
+;; This file contains the autoload definitions that are used by the
+;; debian package and can also be used in a standalone installation
+;; The XEmacs package has some other means to create the autoload
+;; information.
+
+(autoload 'dictionary-search "dictionary"
+ "Ask for a word and search it in all dictionaries" t)
+(autoload 'dictionary-match-words "dictionary"
+ "Ask for a word and search all matching words in the dictionaries" t)
+(autoload 'dictionary-lookup-definition "dictionary"
+ "Unconditionally lookup the word at point." t)
+(autoload 'dictionary "dictionary"
+ "Create a new dictionary buffer" t)
+(autoload 'dictionary-mouse-popup-matching-words "dictionary"
+ "Display entries matching the word at the cursor" t)
+(autoload 'dictionary-popup-matching-words "dictionary"
+ "Display entries matching the word at the point" t)
+(autoload 'dictionary-tooltip-mode "dictionary"
+ "Display tooltips for the current word" t)
+(unless (boundp 'running-xemacs)
+ (autoload 'global-dictionary-tooltip-mode "dictionary"
+ "Enable/disable dictionary-tooltip-mode for all buffers" t))
+
diff --git a/dictionary.el b/dictionary.el
new file mode 100644
index 0000000..7fba27e
--- /dev/null
+++ b/dictionary.el
@@ -0,0 +1,844 @@
+;; dictionary.el -- an interface to RFC 2229 dictionary server
+
+;; Author: Torsten Hilbrich <Torsten.Hilbrich@gmx.net>
+;; Keywords: interface, dictionary
+;; $Id: dictionary.el,v 1.16 2000/05/07 08:56:50 torsten Exp $
+
+;; This file 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, or (at your option)
+;; any later version.
+
+;; This file 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 GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+(eval-when-compile
+ (require 'cl))
+
+(require 'custom)
+(require 'connection)
+(require 'link)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Stuff for customizing.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(eval-when-compile
+ (unless (fboundp 'defface)
+ (message "Please update your custom.el file: %s"
+ "http://www.dina.kvl.dk/~abraham/custom/"))
+
+ (unless (fboundp 'defgroup)
+ (defmacro defgroup (&rest ignored))
+ (defmacro defcustom (var value doc &rest ignored)
+ (list 'defvar var value doc))))
+
+(defgroup dictionary nil
+ "Client for accessing the dictd server based dictionaries"
+ :group 'help
+ :group 'hypermedia)
+
+(defcustom dictionary-server
+ "dict.org"
+ "This server is contacted for searching the dictionary"
+ :group 'dictionary
+ :type 'string)
+
+(defcustom dictionary-port
+ 2628
+ "The port of the dictionary server.
+This port is propably always 2628 so there should be no need to modify it."
+ :group 'dictionary
+ :type 'number)
+
+(defcustom dictionary-identification
+ "dictionary.el emacs lisp dictionary client"
+ "This is the identification string that will be send to the server."
+ :group 'dictionary
+ :type 'number)
+
+(defcustom dictionary-default-dictionary
+ "*"
+ "The dictionary which is used for searching definitions and matching.
+* and ! have a special meaning, * search all dictionaries, ! search until
+one dictionary yields matches."
+ :group 'dictionary
+ :type 'string)
+
+(defcustom dictionary-default-strategy
+ "."
+ "The default strategy for listing matching words."
+ :group 'dictionary
+ :type 'string)
+
+(defcustom dictionary-create-buttons
+ t
+ "Create some clickable buttons on top of the window if non-nil"
+ :group 'dictionary
+ :type 'boolean)
+
+(defcustom dictionary-mode-hook
+ nil
+ "Hook run in dictionary mode buffers."
+ :group 'dictionary
+ :type 'hook)
+
+(if (fboundp 'defface)
+ (progn
+
+(defface dictionary-word-entry-face
+ '((((type x))
+ (:italic t))
+ (((type tty) (class color))
+ (:foreground "green"))
+ (t
+ (:inverse t)))
+ "The face that is used for displaying the initial word entry line."
+ :group 'dictionary)
+
+(defface dictionary-button-face
+ '((t
+ (:bold t)))
+ "The face that is used for displaying buttons."
+ :group 'dictionary)
+
+(defface dictionary-reference-face
+ '((((type x)
+ (class color)
+ (background dark))
+ (:foreground "yellow"))
+ (((type tty)
+ (class color)
+ (background dark))
+ (:foreground "brightyellow"))
+ (((class color)
+ (background light))
+ (:foreground "blue"))
+ (t
+ (:underline t)))
+
+ "The face that is used for displaying a reference word."
+ :group 'dictionary)
+
+)
+
+;; else
+(copy-face 'italic 'dictionary-word-entry-face)
+(copy-face 'bold 'dictionary-button-face)
+(copy-face 'default 'dictionary-reference-face)
+(set-face-foreground 'dictionary-reference-face "blue"))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Buffer local variables for storing the current state
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar dictionary-window-configuration
+ nil
+ "The window configuration to be restored upon closing the buffer")
+
+(defvar dictionary-position-stack
+ nil
+ "The history buffer for point and window position")
+
+(defvar dictionary-data-stack
+ nil
+ "The history buffer for functions and arguments")
+
+(defvar dictionary-positions
+ nil
+ "The current positions")
+
+(defvar dictionary-current-data
+ nil
+ "The item that will be placed on stack next time")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Global variables
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defvar dictionary-mode-map
+ nil
+ "Keymap for dictionary mode")
+
+(defvar dictionary-connection
+ nil
+ "The current network connection")
+
+(defvar dictionary-instances
+ 0
+ "The number of open dictionary buffers")
+
+(defvar dictionary-marker
+ nil
+ "Stores the point position while buffer display.")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Basic function providing startup actions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun dictionary-mode ()
+ "This is a mode for searching a dictionary server implementing
+the protocol defined in RFC 2229.
+
+This is a quick reference to this mode describing the default key bindings:
+
+* q close the dictionary buffer
+* h display this help information
+* s ask for a new word to search
+* d search the word at point
+* n or Tab place point to the next link
+* p or S-Tab place point to the prev link
+
+* m ask for a pattern and list all matching words.
+* D select the default dictionary
+* M select the default search strategy
+
+* Return or Button2 visit that link
+* M-Return or M-Button2 search the word beneath link in all dictionaries
+"
+
+ (unless (eq major-mode 'dictionary-mode)
+ (incf dictionary-instances))
+
+ (kill-all-local-variables)
+ (buffer-disable-undo)
+ (use-local-map dictionary-mode-map)
+ (setq major-mode 'dictionary-mode)
+ (setq mode-name "Dictionary")
+
+ (make-local-variable 'dictionary-data-stack)
+ (setq dictionary-data-stack nil)
+ (make-local-variable 'dictionary-position-stack)
+ (setq dictionary-position-stack nil)
+
+ (make-local-variable 'dictionary-current-data)
+ (make-local-variable 'dictionary-positions)
+
+ (make-local-variable 'dictionary-default-dictionary)
+ (make-local-variable 'dictionary-default-strategy)
+
+ (make-local-hook 'kill-buffer-hook)
+ (add-hook 'kill-buffer-hook 'dictionary-close t t)
+ (run-hooks 'dictionary-mode-hook))
+
+(defun dictionary ()
+ "Create a new dictonary buffer and install dictionary-mode"
+ (interactive)
+
+ (let ((buffer (generate-new-buffer "*Dictionary buffer*"))
+ (window-configuration (current-window-configuration)))
+ (switch-to-buffer-other-window buffer)
+ (dictionary-mode)
+
+ (make-local-variable 'dictionary-window-configuration)
+ (setq dictionary-window-configuration window-configuration)
+ (dictionary-check-connection)
+ (dictionary-pre-buffer)
+ (dictionary-post-buffer)))
+
+(unless dictionary-mode-map
+ (setq dictionary-mode-map (make-sparse-keymap))
+ (suppress-keymap dictionary-mode-map)
+
+ (define-key dictionary-mode-map "q" 'dictionary-close)
+ (define-key dictionary-mode-map "h" 'dictionary-help)
+ (define-key dictionary-mode-map "s" 'dictionary-search)
+ (define-key dictionary-mode-map "d" 'dictionary-lookup-definition)
+ (define-key dictionary-mode-map "D" 'dictionary-select-dictionary)
+ (define-key dictionary-mode-map "M" 'dictionary-select-strategy)
+ (define-key dictionary-mode-map "m" 'dictionary-match-words)
+ (define-key dictionary-mode-map "l" 'dictionary-previous)
+
+ (define-key dictionary-mode-map [tab] 'dictionary-next-link)
+ (define-key dictionary-mode-map "n" 'dictionary-next-link)
+ (define-key dictionary-mode-map [(shift tab)] 'dictionary-prev-link)
+ (define-key dictionary-mode-map "p" 'dictionary-prev-link)
+
+ (define-key dictionary-mode-map " " 'scroll-up)
+ (define-key dictionary-mode-map [(meta space)] 'scroll-down)
+
+ (link-initialize-keymap dictionary-mode-map))
+
+(defun dictionary-check-connection ()
+ "Check if there is already a connection open"
+ (if (not (and dictionary-connection
+ (eq (connection-status dictionary-connection) 'up)))
+ (progn
+ (message "Opening connection to %s:%s" dictionary-server
+ dictionary-port)
+ (connection-close dictionary-connection)
+ (setq dictionary-connection
+ (connection-open dictionary-server dictionary-port))
+ (dictionary-check-initial-reply)
+ (dictionary-send-command (concat "client " dictionary-identification))
+ (let ((reply (dictionary-read-reply-and-split)))
+ (message nil)
+ (unless (dictionary-check-reply reply 250)
+ (error "Unknown server answer: %s" (dictionary-reply reply)))))))
+(defun dictionary-mode-p ()
+ "Return non-nil if current buffer has dictionary-mode"
+ (eq major-mode 'dictionary-mode))
+
+(defun dictionary-ensure-buffer ()
+ "If current buffer is not a dictionary buffer, create a new one."
+ (unless (dictionary-mode-p)
+ (dictionary)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Dealing with closing the buffer
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun dictionary-close ()
+ "Close the current dictionary buffer and its connection"
+ (interactive)
+ (if (eq major-mode 'dictionary-mode)
+ (progn
+ (setq major-mode nil)
+ (if (<= (decf dictionary-instances) 0)
+ (connection-close dictionary-connection))
+ (let ((configuration dictionary-window-configuration))
+ (kill-buffer (current-buffer))
+ (set-window-configuration configuration)))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Helpful functions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun dictionary-send-command (string)
+ "Send the command `string' to the network connection."
+ (dictionary-check-connection)
+ (connection-send-crlf dictionary-connection string))
+
+(defun dictionary-read-reply ()
+ "Read the reply line from the server"
+ (let ((answer (connection-read-crlf dictionary-connection)))
+ (if (string-match "\r" answer)
+ (substring answer 0 (match-beginning 0))
+ answer)))
+
+(defun dictionary-split-string (string)
+ "Split the `string' constiting of space separated words into elements.
+This function knows about the special meaning of quotes (\")"
+ (let ((list))
+ (while (and string (> (length string) 0))
+ (let ((search "\\(\\s-+\\)")
+ (start 0))
+ (if (= (aref string 0) ?\")
+ (setq search "\\(\"\\)\\s-*"
+ start 1))
+ (if (string-match search string start)
+ (progn
+ (setq list (cons (substring string start (- (match-end 1) 1)) list)
+ string (substring string (match-end 0))))
+ (setq list (cons string list)
+ string nil))))
+ (nreverse list)))
+
+(defun dictionary-read-reply-and-split ()
+ "Read the reply, split it into words and return it"
+ (let ((answer (make-symbol "reply-data"))
+ (reply (dictionary-read-reply)))
+ (let ((reply-list (dictionary-split-string reply)))
+ (put answer 'reply reply)
+ (put answer 'reply-list reply-list)
+ (put answer 'reply-code (string-to-number (car reply-list)))
+ answer)))
+
+(defmacro dictionary-reply-code (reply)
+ "Return the reply code stored in `reply'."
+ (list 'get reply ''reply-code))
+
+(defmacro dictionary-reply (reply)
+ "Return the string reply stored in `reply'."
+ (list 'get reply ''reply))
+
+(defmacro dictionary-reply-list (reply)
+ "Return the reply list stored in `reply'."
+ (list 'get reply ''reply-list))
+
+(defun dictionary-read-answer ()
+ "Read an answer delimited by a . on a single line"
+ (let ((answer (connection-read-to-point dictionary-connection))
+ (start 0))
+ (while (string-match "^\\." answer start)
+ (setq answer (replace-match "" t t answer))
+ (setq start (match-end 0)))
+ (setq start 0)
+ (while (string-match "\r\n" answer start)
+ (setq answer (replace-match "\n" t t answer))
+ (setq start (1- (match-end 0))))
+ answer))
+
+(defun dictionary-check-reply (reply code)
+ "Check if the reply in `reply' has the `code'."
+ (let ((number (dictionary-reply-code reply)))
+ (and (numberp number)
+ (= number code))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Communication functions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun dictionary-check-initial-reply ()
+ "Read the first reply from server and check it."
+ (let ((reply (dictionary-read-reply-and-split)))
+ (unless (dictionary-check-reply reply 220)
+ (connection-close dictionary-connection)
+ (error "Server returned: %s" (dictionary-reply reply)))))
+
+;; Store the current state
+(defun dictionary-store-state (function data)
+ "Stores the current state of operation for later restore."
+
+ (if dictionary-current-data
+ (progn
+ (push dictionary-current-data dictionary-data-stack)
+ (unless dictionary-positions
+ (error "dictionary-store-state called before dictionary-store-positions"))
+ (push dictionary-positions dictionary-position-stack)))
+ (setq dictionary-current-data
+ (cons function data)))
+
+(defun dictionary-store-positions ()
+ "Stores the current positions for later restore."
+
+ (setq dictionary-positions (cons (point) (window-start))))
+
+;; Restore the previous state
+(defun dictionary-restore-state (&rest ignored)
+ "Restore the state just before the last operation"
+ (let ((position (pop dictionary-position-stack))
+ (data (pop dictionary-data-stack)))
+ (unless position
+ (error "Already at begin of history"))
+ (apply (car data) (cdr data))
+ (set-window-start (selected-window) (cdr position))
+ (goto-char (car position))
+ (setq dictionary-current-data data)))
+
+
+;; The normal search
+
+(defun dictionary-new-search (args &optional all)
+ "Save the current state and start a new search"
+ (dictionary-store-positions)
+ (dictionary-ensure-buffer)
+ (let ((word (car args))
+ (dictionary (cdr args)))
+
+ (if all
+ (setq dictionary dictionary-default-dictionary))
+ (dictionary-do-search word dictionary)
+ (dictionary-store-state 'dictionary-do-search (list word dictionary))))
+
+(defun dictionary-do-search (word dictionary)
+ "The workhorse for doing the search"
+
+ (message "Searching for %s in %s" word dictionary)
+ (dictionary-send-command (concat "define \"" dictionary "\" \""
+ word "\""))
+ (message nil)
+ (dictionary-pre-buffer)
+ (let ((reply (dictionary-read-reply-and-split)))
+ (if (dictionary-check-reply reply 552)
+ (error "Word \"%s\" in dictionary \"%s\" not found"
+ word dictionary)
+ (if (dictionary-check-reply reply 550)
+ (error "Dictionary \"%s\" is unknown, please select an existing one."
+ dictionary)
+ (unless (dictionary-check-reply reply 150)
+ (error "Unknown server answer: %s" (dictionary-reply reply)))
+ (dictionary-display-search-result reply)))))
+
+(defun dictionary-pre-buffer ()
+ "These commands are executed at the begin of a new buffer"
+ (toggle-read-only 0)
+ (erase-buffer)
+ (if dictionary-create-buttons
+ (progn
+ (link-insert-link "[Back]" 'dictionary-button-face
+ 'dictionary-restore-state nil
+ "Mouse-2 to go backwards in history")
+ (insert " ")
+ (link-insert-link "[Search Definition]"
+ 'dictionary-button-face
+ 'dictionary-search nil
+ "Mouse-2 to look up a new word")
+
+ (insert " ")
+ (link-insert-link "[Matching words]"
+ 'dictionary-button-face
+ 'dictionary-match-words nil
+ "Mouse-2 to find matches for a pattern")
+ (insert "\n ")
+ (link-insert-link "[Select Default Dictionary]"
+ 'dictionary-button-face
+ 'dictionary-select-dictionary nil
+ "Mouse-2 to select dictionary for future searches")
+ (insert " ")
+ (link-insert-link "[Select Match Strategy]"
+ 'dictionary-button-face
+ 'dictionary-select-strategy nil
+ "Mouse-2 to select matching algorithm")
+ (insert "\n\n")))
+ (setq dictionary-marker (point-marker)))
+
+(defun dictionary-post-buffer ()
+ "These commands are executed at the end of a new buffer"
+ (goto-char dictionary-marker)
+ (set-buffer-modified-p nil)
+ (toggle-read-only 1))
+
+(defun dictionary-display-search-result (reply)
+ "This function starts displaying the result starting with the `reply'."
+
+ (let ((number (nth 1 (dictionary-reply-list reply))))
+ (insert number (if (equal number "1")
+ " definition"
+ " definitions")
+ " found\n\n")
+ (setq reply (dictionary-read-reply-and-split))
+ (while (dictionary-check-reply reply 151)
+ (let* ((reply-list (dictionary-reply-list reply))
+ (dictionary (nth 2 reply-list))
+ (description (nth 3 reply-list))
+ (word (nth 1 reply-list)))
+ (dictionary-display-word-entry word dictionary description)
+ (setq reply (dictionary-read-answer))
+ (dictionary-display-word-definition reply word dictionary)
+ (setq reply (dictionary-read-reply-and-split))))
+ (dictionary-post-buffer)))
+
+(defun dictionary-display-word-entry (word dictionary description)
+ "Insert an explanation for the current definition."
+ (let ((start (point)))
+ (insert "From " description "[" dictionary "]:\n\n")
+ (put-text-property start (point) 'face 'dictionary-word-entry-face)))
+
+(defun dictionary-display-word-definition (reply word dictionary)
+ "Insert the definition for the current word"
+ (let ((start (point)))
+ (insert reply)
+ (let ((regexp "\\({+\\)\\([^}]+\\)\\(}+\\)"))
+ (goto-char start)
+ (while (< (point) (point-max))
+ (if (search-forward-regexp regexp nil t)
+ (progn
+ (replace-match "\\2")
+ ;; Compensate for the replacement
+ (let* ((brace-match-length (- (match-end 1)
+ (match-beginning 1)))
+ (match-start (- (match-beginning 2)
+ brace-match-length))
+ (match-end (- (match-end 2)
+ brace-match-length)))
+ (dictionary-mark-reference match-start match-end
+ 'dictionary-new-search
+ word dictionary)))
+ (goto-char (point-max)))))))
+
+(defun dictionary-mark-reference (start end call displayed-word dictionary)
+ "Format the area from `start' to `end' as link calling `call'.
+The word is taken from the buffer, the `dictionary' is given as argument."
+ (let ((word (buffer-substring-no-properties start end)))
+ (while (string-match "\n\\s-*" word)
+ (setq word (replace-match " " t t word)))
+ (while (string-match "[*\"]" word)
+ (setq word (replace-match "" t t word)))
+
+ (unless (equal word displayed-word)
+ (link-create-link start end 'dictionary-reference-face
+ call (cons word dictionary)
+ (concat "Press Mouse-2 to lookup \""
+ word "\" in \"" dictionary "\"")))))
+
+(defun dictionary-select-dictionary (&rest ignored)
+ "Save the current state and start a dictionary selection"
+ (interactive)
+ (dictionary-ensure-buffer)
+ (dictionary-store-positions)
+ (dictionary-do-select-dictionary)
+ (dictionary-store-state 'dictionary-do-select-dictionary nil))
+
+(defun dictionary-do-select-dictionary (&rest ignored)
+ "The workhorse for doing the dictionary selection."
+
+ (message "Looking up databases and descriptions")
+ (dictionary-send-command "show db")
+
+ (let ((reply (dictionary-read-reply-and-split)))
+ (message nil)
+ (if (dictionary-check-reply reply 554)
+ (error "No dictionary present")
+ (unless (dictionary-check-reply reply 110)
+ (error "Unknown server answer: %s"
+ (dictionary-reply reply)))
+ (dictionary-display-dictionarys reply))))
+
+(defun dictionary-simple-split-string (string &optional pattern)
+ "Return a list of substrings of STRING which are separated by PATTERN.
+If PATTERN is omitted, it defaults to \"[ \\f\\t\\n\\r\\v]+\"."
+ (or pattern
+ (setq pattern "[ \f\t\n\r\v]+"))
+ ;; The FSF version of this function takes care not to cons in case
+ ;; of infloop. Maybe we should synch?
+ (let (parts (start 0))
+ (while (string-match pattern string start)
+ (setq parts (cons (substring string start (match-beginning 0)) parts)
+ start (match-end 0)))
+ (nreverse (cons (substring string start) parts))))
+
+(defun dictionary-display-dictionarys (reply)
+ "Handle the display of all dictionaries existing on the server"
+ (dictionary-pre-buffer)
+ (insert "Please select your default dictionary:\n\n")
+ (dictionary-display-dictionary-line "* \"All dictionaries\"")
+ (dictionary-display-dictionary-line "! \"The first matching dictionary\"")
+ (let* ((reply (dictionary-read-answer))
+ (list (dictionary-simple-split-string reply "\n+")))
+ (mapcar 'dictionary-display-dictionary-line list))
+ (dictionary-post-buffer))
+
+(defun dictionary-display-dictionary-line (string)
+ "Display a single dictionary"
+ (let* ((list (dictionary-split-string string))
+ (dictionary (car list))
+ (description (cadr list)))
+ (if dictionary
+ (progn
+ (link-insert-link description 'dictionary-reference-face
+ 'dictionary-set-dictionary
+ (cons dictionary description)
+ "Mouse-2 to select this dictionary")
+ (insert "\n")))))
+
+(defun dictionary-set-dictionary (param &optional more)
+ "Select this dictionary as new default"
+
+ (if more
+ (dictionary-display-more-info param)
+ (let ((dictionary (car param)))
+ (setq dictionary-default-dictionary dictionary)
+ (message "Dictionary %s has been selected" dictionary))))
+
+(defun dictionary-display-more-info (param)
+ "Display the available information on the dictionary"
+
+ (let ((dictionary (car param))
+ (description (cdr param)))
+ (unless (or (equal dictionary "*")
+ (equal dictionary "!"))
+ (dictionary-store-positions)
+ (message "Requesting more information on %s" dictionary)
+ (dictionary-send-command (concat "show info \"" dictionary "\""))
+ (let ((reply (dictionary-read-reply-and-split)))
+ (message nil)
+ (if (dictionary-check-reply reply 550)
+ (error "Dictionary \"%s\" not existing" dictionary)
+ (unless (dictionary-check-reply reply 112)
+ (error "Unknown server answer: %s" (dictionary-reply reply)))
+ (dictionary-pre-buffer)
+ (insert "Information on dictionary: ")
+ (link-insert-link description 'dictionary-reference-face
+ 'dictionary-set-dictionary
+ (cons dictionary description)
+ "Mouse-2 to select this dictionary")
+ (insert "\n\n")
+ (setq reply (dictionary-read-answer))
+ (insert reply)
+ (dictionary-post-buffer)))
+
+ (dictionary-store-state 'dictionary-display-more-info dictionary))))
+
+(defun dictionary-select-strategy (&rest ignored)
+ "Save the current state and start a strategy selection"
+ (interactive)
+ (dictionary-ensure-buffer)
+ (dictionary-store-positions)
+ (dictionary-do-select-strategy)
+ (dictionary-store-state 'dictionary-do-select-strategy nil))
+
+(defun dictionary-do-select-strategy ()
+ "The workhorse for doing the strategy selection."
+
+ (message "Request existing matching algorithm")
+ (dictionary-send-command "show strat")
+
+ (let ((reply (dictionary-read-reply-and-split)))
+ (message nil)
+ (if (dictionary-check-reply reply 555)
+ (error "No strategies available")
+ (unless (dictionary-check-reply reply 111)
+ (error "Unknown server answer: %s"
+ (dictionary-reply reply)))
+ (dictionary-display-strategies reply))))
+
+(defun dictionary-display-strategies (reply)
+ "Handle the display of all strategies existing on the server"
+ (dictionary-pre-buffer)
+ (insert "Please select your default search strategy:\n\n")
+ (dictionary-display-strategy-line ". \"The servers default\"")
+ (let* ((reply (dictionary-read-answer))
+ (list (dictionary-simple-split-string reply "\n+")))
+ (mapcar 'dictionary-display-strategy-line list))
+ (dictionary-post-buffer))
+
+(defun dictionary-display-strategy-line (string)
+ "Display a single strategy"
+ (let* ((list (dictionary-split-string string))
+ (strategy (car list))
+ (description (cadr list)))
+ (if strategy
+ (progn
+ (link-insert-link description 'dictionary-reference-face
+ 'dictionary-set-strategy strategy
+ "Mouse-2 to select this matching algorithm")
+ (insert "\n")))))
+
+(defun dictionary-set-strategy (strategy &rest ignored)
+ "Select this strategy as new default"
+ (setq dictionary-default-strategy strategy)
+ (message "Strategy %s has been selected" strategy))
+
+(defun dictionary-new-matching (word)
+ "Run a new matching search on `word'."
+ (dictionary-ensure-buffer)
+ (dictionary-store-positions)
+ (dictionary-do-matching word dictionary-default-dictionary
+ dictionary-default-strategy)
+ (dictionary-store-state 'dictionary-do-matching
+ (list word dictionary-default-dictionary
+ dictionary-default-strategy)))
+
+(defun dictionary-do-matching (word dictionary strategy)
+ "Ask the server about matches to `word' and display it."
+
+ (message "Lookup matching words for %s in %s using %s"
+ word dictionary strategy)
+ (dictionary-send-command
+ (concat "match \"" dictionary "\" \""
+ strategy "\" \"" word "\""))
+ (let ((reply (dictionary-read-reply-and-split)))
+ (message nil)
+ (if (dictionary-check-reply reply 550)
+ (error "Dictionary \"%s\" is invalid" dictionary))
+ (if (dictionary-check-reply reply 551)
+ (error "Strategy \"%s\" is invalid" strategy))
+ (if (dictionary-check-reply reply 552)
+ (error (concat
+ "No match for \"%s\" with strategy \"%s\" in "
+ "dictionary \"%s\".")
+ word strategy dictionary))
+ (unless (dictionary-check-reply reply 152)
+ (error "Unknown server answer: %s" (dictionary-reply reply)))
+ (dictionary-display-match-result reply)))
+
+(defun dictionary-display-match-result (reply)
+ "Display the results from the current matches."
+ (dictionary-pre-buffer)
+
+ (let ((number (nth 1 (dictionary-reply-list reply)))
+ (list (dictionary-simple-split-string (dictionary-read-answer) "\n+")))
+ (insert number " matching word" (if (equal number "1") "" "s")
+ " found\n\n")
+ (let ((result nil))
+ (mapcar (lambda (item)
+ (let* ((list (dictionary-split-string item))
+ (dictionary (car list))
+ (word (cadr list))
+ (hash (assoc dictionary result)))
+ (if dictionary
+ (if hash
+ (setcdr hash (cons word (cdr hash)))
+ (setq result (cons
+ (cons dictionary (list word))
+ result))))))
+ list)
+ (dictionary-display-match-lines (reverse result))))
+ (dictionary-post-buffer))
+
+(defun dictionary-display-match-lines (list)
+ "Display the match lines."
+ (mapcar (lambda (item)
+ (let ((dictionary (car item))
+ (word-list (cdr item)))
+ (insert "Matches from " dictionary ":\n")
+ (mapcar (lambda (word)
+ (insert " ")
+ (link-insert-link word 'dictionary-reference-face
+ 'dictionary-new-search
+ (cons word dictionary)
+ "Mouse-2 to lookup word")
+ (insert "\n")) (reverse word-list))
+ (insert "\n")))
+ list))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; User callable commands
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun dictionary-search (word &optional dictionary)
+ "Search the `word' in `dictionary' if given or in all if nil.
+It presents the word at point as default input and allows editing it."
+ (interactive
+ (list (read-string "Search word: " (current-word))
+ (if current-prefix-arg
+ (read-string "Dictionary: " dictionary-default-dictionary)
+ dictionary-default-dictionary)))
+
+ ;; if called by pressing the button
+ (unless word
+ (setq word (read-string "Search word: ")))
+ ;; just in case non-interactivly called
+ (unless dictionary
+ (setq dictionary dictionary-default-dictionary))
+ (dictionary-new-search (cons word dictionary)))
+
+(defun dictionary-lookup-definition ()
+ "Unconditionally lookup the word at point."
+ (interactive)
+ (dictionary-new-search (cons (current-word) dictionary-default-dictionary)))
+
+(defun dictionary-previous ()
+ "Go to the previous location in the current buffer"
+ (interactive)
+ (unless (dictionary-mode-p)
+ (error "Current buffer is no dictionary buffer"))
+ (dictionary-restore-state))
+
+(defun dictionary-next-link ()
+ "Place the cursor to the next link."
+ (interactive)
+ (let ((pos (link-next-link)))
+ (if pos
+ (goto-char pos)
+ (error "There is no next link"))))
+
+(defun dictionary-prev-link ()
+ "Place the cursor to the previous link."
+ (interactive)
+ (let ((pos (link-prev-link)))
+ (if pos
+ (goto-char pos)
+ (error "There is no previous link"))))
+
+(defun dictionary-help ()
+ "Display a little help"
+ (interactive)
+ (describe-function 'dictionary-mode))
+
+(defun dictionary-match-words (&optional pattern &rest ignored)
+ "Search `pattern' in current default dictionary using default strategy."
+ (interactive)
+ ;; can't use interactive because of mouse events
+ (or pattern
+ (setq pattern (read-string "Search pattern: ")))
+ (dictionary-new-matching pattern))
+
+(provide 'dictionary) \ No newline at end of file
diff --git a/install-package.el b/install-package.el
new file mode 100755
index 0000000..5b0474e
--- /dev/null
+++ b/install-package.el
@@ -0,0 +1,7 @@
+(defun install-package ()
+ (interactive)
+ (let ((filename (apply 'concat command-line-args-left)))
+ (message (concat "Installing package " filename))
+ (package-admin-add-binary-package filename)
+ (set-buffer "*Package Output*")
+ (message (buffer-substring (point-min) (point-max)))))
diff --git a/link.el b/link.el
new file mode 100644
index 0000000..cea9f13
--- /dev/null
+++ b/link.el
@@ -0,0 +1,120 @@
+;;; link.el -- putting clickable links into the buffer
+
+;; Author: Torsten Hilbrich <Torsten.Hilbrich@gmx.net>
+;; Keywords: interface, hypermedia
+;; $Id: link.el,v 1.5 1999/01/08 18:36:50 torsten Exp $
+
+;; This file 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, or (at your option)
+;; any later version.
+
+;; This file 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 GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;; Commentary:
+
+;; This file contains functions for using links in buffers. A link is
+;; a part of the buffer marked with a special face, beeing
+;; hightlighted while the mouse points to it and beeing activated when
+;; pressing return or clicking the button2.
+
+;; Which each link a function and some data are associated. Upon
+;; clicking the function is called with the data as only argument.
+
+(eval-when-compile
+ (require 'cl))
+
+(defun link-create-link (start end face function &optional data help)
+ "Create a link in the current buffer starting from `start' going to `end'.
+The `face' is used for displaying, the `data' are stored together with the
+link. Upon clicking the `function' is called with `data' as argument."
+ (let ((properties `(face ,face
+ mouse-face highlight
+ link t
+ link-data ,data
+ help-echo ,help
+ link-function ,function)))
+ (set-text-properties start end properties)))
+
+(defun link-insert-link (text face function &optional data help)
+ "Insert the `text' at point to be formatted as link.
+The `face' is used for displaying, the `data' are stored together with the
+link. Upon clicking the `function' is called with `data' as argument."
+ (let ((start (point)))
+ (insert text)
+ (link-create-link start (point) face function data help)))
+
+(defun link-selected (&optional all)
+ "Is called upon clicking or otherwise visiting the link."
+ (interactive)
+
+ (let* ((properties (text-properties-at (point)))
+ (function (plist-get properties 'link-function))
+ (data (plist-get properties 'link-data)))
+ (if function
+ (funcall function data all))))
+
+(defun link-selected-all ()
+ "Called for meta clicking the link"
+ (interactive)
+ (link-selected 'all))
+
+(defun link-mouse-click (event &optional all)
+ "Is called upon clicking the link."
+ (interactive "@e")
+
+ (mouse-set-point event)
+ (link-selected))
+
+(defun link-mouse-click-all (event)
+ "Is called upon meta clicking the link."
+ (interactive "@e")
+
+ (mouse-set-point event)
+ (link-selected-all))
+
+(defun link-next-link ()
+ "Return the position of the next link or nil if there is none"
+ (let* ((pos (point))
+ (pos (next-single-property-change pos 'link)))
+ (if pos
+ (if (text-property-any pos (min (1+ pos) (point-max)) 'link t)
+ pos
+ (next-single-property-change pos 'link))
+ nil)))
+
+
+(defun link-prev-link ()
+ "Return the position of the previous link or nil if there is none"
+ (let* ((pos (point))
+ (pos (previous-single-property-change pos 'link)))
+ (if pos
+ (if (text-property-any pos (1+ pos) 'link t)
+ pos
+ (let ((val (previous-single-property-change pos 'link)))
+ (if val
+ val
+ (text-property-any (point-min) (1+ (point-min)) 'link t))))
+ nil)))
+
+(defun link-initialize-keymap (keymap)
+ "Defines the necessary bindings inside keymap"
+
+ (if (and (boundp 'running-xemacs) running-xemacs)
+ (progn
+ (define-key keymap [button2] 'link-mouse-click)
+ (define-key keymap [(meta button2)] 'link-mouse-click-all))
+ (define-key keymap [mouse-2] 'link-mouse-click)
+ (define-key keymap [M-mouse-2] 'link-mouse-click-all))
+ (define-key keymap [return] 'link-selected)
+ (define-key keymap [(meta return)] 'link-selected-all))
+
+(provide 'link) \ No newline at end of file
diff --git a/lpath.el b/lpath.el
new file mode 100644
index 0000000..858179f
--- /dev/null
+++ b/lpath.el
@@ -0,0 +1,4 @@
+;; Shut up.
+
+(setq load-path (cons "." load-path))
+