summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron M. Ucko <ucko@debian.org>2013-05-21 22:33:25 -0400
committerAaron M. Ucko <ucko@debian.org>2013-05-21 22:33:25 -0400
commit85fb4a5ce34b02690a94e276daed220edeceea49 (patch)
treeaf4a0e37ac62f11d81162d9e04a7ea6eaeb8f54b
Import dictionary-el_1.10.orig.tar.gz
[dgit import orig dictionary-el_1.10.orig.tar.gz]
-rwxr-xr-xGPL340
-rwxr-xr-xMakefile106
-rwxr-xr-xREADME643
-rwxr-xr-xconnection.el151
-rw-r--r--deb/README.debian14
-rw-r--r--deb/changelog171
-rw-r--r--deb/compat1
-rw-r--r--deb/control18
-rw-r--r--deb/copyright13
-rw-r--r--deb/dictionary.install1
-rw-r--r--deb/install.debian30
-rw-r--r--deb/postinst6
-rw-r--r--deb/prerm5
-rw-r--r--deb/remove.debian17
-rw-r--r--deb/rules35
-rwxr-xr-xdictionary-init.el26
-rwxr-xr-xdictionary.el1327
-rwxr-xr-xinstall-package.el7
-rwxr-xr-xlink.el120
-rwxr-xr-xlpath.el4
20 files changed, 3035 insertions, 0 deletions
diff --git a/GPL b/GPL
new file mode 100755
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 100755
index 0000000..d84003f
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,106 @@
+# -*- Makefile -*-
+EMACS=emacs
+
+VERSION=1.10
+PACKAGE=dictionary
+TYPE=comm
+XEMACS-PACKAGE=$(PACKAGE)-$(VERSION)-pkg.tar.gz
+
+SOURCES=dictionary.el connection.el link.el
+COMPILED=dictionary.elc connection.elc link.elc
+
+# For make dist
+LISP_FILES=connection.el dictionary.el link.el lpath.el dictionary-init.el \
+ install-package.el
+DOC_FILES=README GPL Makefile
+DEB_FILES=README.debian control copyright install.debian postinst \
+ prerm remove.debian rules changelog dictionary.install \
+ compat
+DEB_DIR=deb
+
+.SUFFIXES: .elc .el
+
+.el.elc:
+ $(EMACS) -q -no-site-file -no-init-file -batch -l lpath.el \
+ -f batch-byte-compile $<
+
+.PHONY: all
+all: $(COMPILED)
+
+.PHONY: debian
+debian:
+ @[ -x debian ] || ln -s deb debian
+ @if [ -x /usr/bin/fakeroot ]; then \
+ dpkg-buildpackage -us -uc -rfakeroot; \
+ elif [ `id -u` -ne 0 ]; then \
+ echo "You are not root and fakeroot is not installed, aborting"; \
+ exit 1; \
+ else \
+ dpkg-buildpackage -us -uc; \
+ fi
+ @echo "You can now install the debian package, the previous output tells"
+ @echo "you its location (probably stored in ..)"
+ @echo
+ @echo "Please note, this debian package is unofficial, report bugs"
+ @echo "to me only, not to the Debian Bugtracking System."
+
+.PHONY: package
+package: $(XEMACS-PACKAGE)
+
+$(XEMACS-PACKAGE): $(COMPILED)
+ @case $(EMACS) in emacs*) printf "\aNote, packages work with XEmacs 21 only, hope you know what you are doing\n\n";; esac
+ @mkdir -p lisp/$(PACKAGE)
+ @mkdir -p pkginfo
+ @printf ";;;###autoload\n(package-provide '$(PACKAGE)\n:version $(VERSION)\n:type '$(TYPE))\n" > lisp/$(PACKAGE)/_pkg.el
+ @rm -f lisp/$(PACKAGE)/auto-autoloads.el lisp/$(PACKAGE)/custom-load.el
+ @cp $(SOURCES) $(COMPILED) lisp/$(PACKAGE)
+ @cd lisp && \
+ $(EMACS) -vanilla -batch -l autoload -f batch-update-directory $(PACKAGE) && \
+ $(EMACS) -vanilla -batch -l cus-dep -f Custom-make-dependencies $(PACKAGE) && \
+ $(EMACS) -vanilla -batch -f batch-byte-compile $(PACKAGE)/auto-autoloads.el $(PACKAGE)/custom-load.el
+ @touch pkginfo/MANIFEST.$(PACKAGE)
+ @find lisp pkginfo -type f > pkginfo/MANIFEST.$(PACKAGE)
+ @tar cf - pkginfo lisp | gzip -c > $(XEMACS-PACKAGE)
+
+.PHONY: package-install
+package-install: package
+ @if [ `id -u` -ne 0 ]; then printf "\aWarning, you are not root; the installation might fail\n\n"; fi
+ @$(EMACS) -vanilla -batch -l install-package.el -f install-package `pwd`/$(XEMACS-PACKAGE)
+
+.PHONY: view-info
+view-info: info
+ info doc/dictionary.info
+
+.PHONY: doc
+doc: info html
+
+.PHONY: info
+info: doc/dictionary.info
+
+doc/dictionary.info: doc/dictionary.texi
+ cd doc && makeinfo --output dictionary.info dictionary
+
+.PHONY: html
+html: doc/dictionary
+
+doc/dictionary: doc/dictionary.texi
+ cd doc && makeinfo --html dictionary
+
+.PHONY: dist
+dist:
+ @[ -x debian ] || ln -s deb debian; \
+ VERSION=$$(dpkg-parsechangelog | perl -n -e '/^Version: (.*)-/ && print "$$1\n"'); \
+ DIR=$$(mktemp -d); \
+ DESTDIR="$$DIR/dictionary-$$VERSION"; \
+ install -d $$DESTDIR; \
+ install $(LISP_FILES) $(DOC_FILES) $$DESTDIR; \
+ mkdir $$DESTDIR/$(DEB_DIR); \
+ cd $(DEB_DIR) && install -m 644 $(DEB_FILES) $$DESTDIR/$(DEB_DIR); \
+ tar czf $(CURDIR)/dictionary-$$VERSION.tar.gz -C $$DIR .; \
+ rm -r $$DIR; \
+ echo "dictionary-$$VERSION.tar.gz has been created"
+
+.PHONY: clean
+clean:
+ rm -f $(XEMACS-PACKAGE) $(COMPILED) build
+ rm -rf debian/tmp lisp pkginfo
diff --git a/README b/README
new file mode 100755
index 0000000..59f0e19
--- /dev/null
+++ b/README
@@ -0,0 +1,643 @@
+
+ Emacs package for talking to a dictionary server
+
+ Introduction
+
+ In December 1998 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 21, 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 and have now been implemented in this
+ dictionary client.
+
+ If you didn't received this file from its original location you can
+ visit it at http://www.myrkr.in-berlin.de/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
+ * in the latest versions of GNU Emacs and XEmacs you get support for
+ popup menus
+ * in GNU Emacs 21 you can lookup words by simply pointing the mouse
+ cursor to them (tool-tips)
+
+ Here are three sample screenshot showing the dictionary mode in action
+ within an Emacs 21 buffer:
+
+ This buffer shows the result of searching the definition for
+ distinguished. A lot of entries have been found, including translation
+ into german and russian language. The blue words are hyper-links that
+ points to the definitions of these words. The hyper-link with the
+ green background will be activated when pressing the middle mouse
+ button.
+
+ This buffer shows the result of looking for matching words to
+ possible. You can now select one of the found entries or ignore the
+ search by pressing any mouse button outside the menu.
+
+ This screenshot shows the tool-tips supported in GNU Emacs 21.
+ Whenever the mouse cursor stands still for a certain time (about one
+ second) the word at cursor is looked up in the configured dictionary.
+ This example shows the german translation for originally, in this
+ context not the right one, ursprünglich would be better.
+
+ 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. XEmacs 21 and Emacs 20 as well as Emacs 21
+ have been tested too.
+ * Current version (1.9) of this package
+ * Version 1.5.1 of this package
+ * Version 1.4.1 of this package
+ * Version 1.3.3 of this package
+ * Version 1.2.1 of this package
+ * Version 1.1 of this package
+ * Initial 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 usability 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:
+gzip -dc dictionary-1.9.tar.gz | tar xf -
+
+ or
+tar -xzf dictionary-1.9.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.9 has been created
+ containing the necessary files.
+
+ Installation
+
+Debian
+
+ If you are using a current Debian distribution (one that support the
+ emacsen package system) and have the dpkg-dev installed (for running
+ dpkg-buildpackage) you can use the supplied debian support.
+make debian
+
+ This will create a package named dictionary-1.9-1_i386.deb or
+ similiar in the parent directory of dictionary-1.9. You can now
+ install this package as root, it will automatically byte-compile
+ itself for all installed emacs versions and provide a startup-file
+ which autoloads this package. In the configuration example given below
+ you can omit the autoload lines.
+
+ If you no longer want to use this package, you can remove it using:
+dpkg -r dictionary
+
+XEmacs 21
+
+ The XEmacs version 21 support so called xemacs packages. These
+ packages are also supported, you can create them using:
+make EMACS=xemacs package
+
+ The created package will be named dictionary-1.5-pkg.tar.gz and stored
+ within the current directory. If you don't want to install this
+ package manually, you can use the following command, provided you have
+ sufficient privileges (if unsure, login as super user):
+make EMACS=xemacs package-install
+
+ If you have more than one XEmacs versions installed make sure the
+ EMACS argument to make points to the current binary.
+
+Manually
+
+ Byte compiling
+
+ For faster loading and executing of the package I strongly suggest
+ that you byte-compile the files. Emacs user please call make within
+ the create subdirectory, XEmacs user has to specify 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. If you installed this dictionary
+ package as Debian package or XEmacs package you don't need the
+ autoloads, they are already supplied. Other users 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-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)
+(autoload 'global-dictionary-tooltip-mode "dictionary"
+ "Enable/disable dictionary-tooltip-mode for all buffers" t)
+
+ In addition, some key bindings for faster access can be useful. I use
+ the following ones in my installation:
+;; key bindings
+(global-set-key "\C-cs" 'dictionary-search)
+(global-set-key "\C-cm" 'dictionary-match-words)
+
+ I will describe the user-callable functions and the key bindings
+ 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 several 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, regular 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 five 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 multiple 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.
+
+ You can also display a popup menu showing the definition for a certain
+ word. You just place the mouse cursor above the word you want to
+ lookup and press the assigned mouse button. The sample definition in
+ section Customizing binds this command to the right mouse button
+ in GNU Emacs and to ctrl + right mouse button in XEmacs. For mouse
+ invocation use dictionary-mouse-popup-matching-words, for assigning to
+ a key combination use the dictionary-popup-matching-words function.
+ The latter function search for the word located at point.
+
+ I have tested this feature in Emacs 21 and XEmacs 21. Emacs 20 do not
+ support this kind of popup menus (you will get an error message if you
+ try anyway), XEmacs 20 or prior has not been tested yet.
+
+ A new feature of version 1.5 is the tool-tip support. This will only
+ work in GNU Emacs 21, XEmacs uses a different mechanism (called
+ balloon help) which can not easily be adapted. Please note, the
+ tool-tip mode may slow down your Emacs, especially if you prefer using
+ the mouse.
+
+ First you have to define the dictionary for looking up words to
+ display in the tool-tip window. You could use * to search in all
+ dictionaries, however tool-tip window should be rather small. I use an
+ english to german dictionary for myself, which is called eng-deu (you
+ can find out the name if you look into contents of the square brackets
+ within the dictionary buffer; for example, the line From WordNet (r)
+ 1.6[wn]: tells you the name of this dictionary is wn).
+(setq dictionary-tooltip-dictionary "eng-deu")
+
+ Next you have to decide if you want tool-tip support in the current
+ buffer only or in all buffers. For the first use the
+ dictionary-tooltip-mode command, for the latter
+ global-dictionary-tooltip-mode.
+;; choose on of the following lines
+(global-dictionary-tooltip-mode 1)
+(dictionary-tooltip-mode 1)
+
+ To turn the tool-tip support off, call these functions with a numeric
+ argument of 0.
+
+ 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.
+
+Quitting
+
+ Once a dictionary buffer is created you can close it by simply typing
+ q (dictionary-close) or pressing the [Quit] button on the top.
+ 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 divided 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 hyper links 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 precisely).
+
+ 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). Please note that
+ the Shift-Tab key may be the same as the Tab key when running Emacs
+ within a tty (in contrast to a windowing system like X11). There is no
+ way for a application to differ Shift-Tab from Tab in this case,
+ please use the p key to visit the previous link if you run into this
+ problem.
+
+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. Within XEmacs
+ you can exit the help screen by pressing q, in GNU Emacs you have to
+ switch to the help window using C-x o (other-window) first. 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.
+
+Proxy support
+
+ Starting from version 1.6 (not officially released) the dictionary
+ client supports connections via HTTP proxies. It uses the CONNECT
+ method which is usually used to relay SSL connections through a proxy.
+ On most proxies the dictionary port (2628) must be configured to be
+ allowed to connect through the proxy server. You will get an error
+ message like:
+HTTP/1.0 500 WWWOFFLE Server Error
+
+ if this is not the case.
+
+ To enable proxy support, set the variable dictionary-use-http-proxy to
+ true. This can be done through the customize interface, there is a
+ sub-group named Dictionary Proxy of the Dictionary group. Other
+ settings you can modify are the name of the proxy server
+ (dictionary-proxy-server, Default proxy) and the port of the proxy
+ server (dictionary-proxy-port, Default 3128).
+
+Support for different encodings in dictionaries
+
+ Although the standard definition specifies UTF-8 as character encoding
+ to be used for the protocol there exists dictionaries encoding in
+ other encodings like koi8-r for the russian language. To support these
+ dictionaries there exists starting from version 1.7 a variable named
+ dictionary-coding-systems-for-dictionaries. This is a list of cons
+ cell containing the dictionary name (as string) and the coding system
+ to use (as symbol). For modifying the variable the customize interface
+ should be used, it helps you selecting a valid charset and keeping the
+ lisp structure intact.
+
+ If a dictionary is not specified in this list its encoding defaults to
+ UTF-8.
+
+ The default setting
+ '( ("mueller" . koi8-r))
+
+ specifies that the koi8-r encoding should be used for the
+ english-russian dictionary internally called mueller. The internal
+ dictionary name can be found in brackets within the dictionaries
+ output buffer after the long dictionary name (for example, the output
+ From WordNet (r) 1.6[wn] specifies the internal name of the Wordnet
+ dictionary being wn.
+
+ 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. It also shows how to
+ invoke popup menus (using the right button in GNU Emacs or ctrl+right
+ button in XEmacs) and installs the global tooltip-mode.
+(global-set-key "\C-cs" 'dictionary-search)
+(global-set-key "\C-cm" 'dictionary-match-words)
+(setq dictionary-server "localhost")
+
+;; Popup menu for GNU Emacs 21, and XEmacs 21
+(if (boundp 'running-xemacs)
+ (global-set-key [(control button3)] 'dictionary-mouse-popup-matching-words)
+ (global-set-key [mouse-3] 'dictionary-mouse-popup-matching-words))
+
+;; Tool-tip support for GNU Emacs 21
+(setq dictionary-tooltip-dictionary "eng-deu")
+(global-dictionary-tooltip-mode 1)
+
+ Thanks
+
+ I want to thank Sam Steingold, Baoqiu Cui, Bruce Ravel, Pavel Janík,
+ Sergei Pokrovsky, Jeff Mincy, Serge Boiko, Enrico Scholz, Reuben
+ Thomas, Rui Zhu, Eugene Morozov, and Robert Pluim 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.8.7 - 1.9
+
+ * Include some fixes for Emacs24 based on debian version.
+
+Version 1.8.6 - 1.8.7
+
+ * fixed decoding problem when selecting dictionary (problem reported by
+ Kuno Strassmann)
+
+Version 1.8.5 - 1.8.6
+
+ * 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)
+
+Version 1.8.4 - 1.8.5
+
+ * 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
+
+Version 1.8 - 1.8.4
+
+ * fixed Makefile
+ * Fixed multiple defined function in dictionary.el
+ * install-pkg was missing in the last tarball
+
+Version 1.7.4 - 1.8
+
+ * added search for similiar words when the searched word is not found.
+
+Version 1.7.3 - 1.7.4
+
+ * 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
+
+
+Version 1.7.2 - 1.7.3
+
+ * 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)
+
+Version 1.7.1 - 1.7.2
+
+ * link.el (link-initialize-keymap): fixed keybinding bug (reported
+ by David A. Panariti)
+
+Version 1.7 - 1.7.1
+
+ * fixed mule-detection in dictionary-coding-system (patch submitted
+ by Robert Pluim)
+
+Version 1.5.1 - 1.7
+
+ * added HTTP proxy support (using the CONNECT method)
+ * added support for dictionaries not encoded in utf-8 (suggested by
+ Eugene Morozov)
+
+Version 1.5 - 1.5.1
+
+ * fixed bug with non-working dictionary-previous (found by Rui Zhu)
+ * fixed key bindings in link.el
+
+Version 1.4.1 - 1.5
+
+ * tool-tip support for GNU Emacs 21
+
+Version 1.4 - 1.4.1
+
+ * changed recognition of utf-8 support (suggested by Enrico Scholz)
+
+Version 1.3.3 - 1.4
+
+ * added popup menu for easier lookup of words
+
+Version 1.3.2 - 1.3.3
+
+ * added support for XEmacs 21 packages to ease installation for
+ those users (suggested and reviewed by Enrico Scholz)
+
+Version 1.3.1 - 1.3.2
+
+ * replaced set-text-properties by remove-text-properties and
+ add-text-properties because this function is not recommended
+ within XEmacs (reported by Serge Boiko)
+
+Version 1.3 - 1.3.1
+
+ * small fix in dictionary function to check for availability of the
+ utf-8 encoding to prevent problems in certain xemacs versions
+ (reported by Jeff Mincy)
+ * added debian support (use dpkg-buildpackage to build a package)
+
+Version 1.2.1 - 1.3
+
+ * Implemented an automatic detection for line ends CR/LF and LF. The
+ variable connection-broken-end-of-line is no longer necessary and
+ its value ignored.
+ * Added utf-8 support, the native character set of the dictionary
+ protocol. Using ISO-8859-1 (aka latin-1) was just a necessary
+ work-around.
+
+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:
+ + use word as point as default (implementing
+ dictionary-search-word-near-point too)
+ + 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
+ _________________________________________________________________
+
+ E-Mail: dictionary@myrkr.in-berlin.de
+ Last modified: Fri Dec 21 18:51:23 CET 2001
diff --git a/connection.el b/connection.el
new file mode 100755
index 0000000..6df78d6
--- /dev/null
+++ b/connection.el
@@ -0,0 +1,151 @@
+;;; connection.el -- handling a tcp based connection
+
+;; Author: Torsten Hilbrich <dictionary@myrkr.in-berlin.de>
+;; Keywords: network
+
+;; 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))
+
+(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-regexp 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 "\015?\012"))
+
+(defun connection-read-to-point (connection)
+ "Read until a line is consisting of a single point"
+ (connection-read connection "\015?\012[.]\015?\012"))
+
+(provide 'connection)
diff --git a/deb/README.debian b/deb/README.debian
new file mode 100644
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 100644
index 0000000..3fde5e1
--- /dev/null
+++ b/deb/changelog
@@ -0,0 +1,171 @@
+dictionary (1.10-1) unstable; urgency=low
+
+ * Add some fixes sent by Reuben Thomas
+ * Fix link placement in dictionary-display-word-definition
+
+ -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Wed, 08 May 2013 20:21:21 +0200
+
+dictionary (1.9-1) unstable; urgency=low
+
+ * Include some fixes for Emacs24 based on debian version.
+
+ -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Mon, 02 Jul 2012 05:14:54 +0200
+
+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/compat b/deb/compat
new file mode 100644
index 0000000..ec63514
--- /dev/null
+++ b/deb/compat
@@ -0,0 +1 @@
+9
diff --git a/deb/control b/deb/control
new file mode 100644
index 0000000..b1010c1
--- /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
+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 100644
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/dictionary.install b/deb/dictionary.install
new file mode 100644
index 0000000..7468c82
--- /dev/null
+++ b/deb/dictionary.install
@@ -0,0 +1 @@
+dictionary.el connection.el link.el dictionary-init.el usr/share/emacs/site-lisp
diff --git a/deb/install.debian b/deb/install.debian
new file mode 100644
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 100644
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 100644
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 100644
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 100644
index 0000000..e20f052
--- /dev/null
+++ b/deb/rules
@@ -0,0 +1,35 @@
+#!/usr/bin/make -f
+
+package=dictionary
+DESTDIR=debian/$(package)
+
+build:
+ dh_testdir
+
+ touch build
+
+clean:
+ dh_testdir
+ dh_clean
+ rm -f build
+
+binary-arch: build
+ dh_testdir
+ dh_testroot
+
+ dh_install
+
+ install -m 755 -D debian/install.debian \
+ $(DESTDIR)/usr/lib/emacsen-common/packages/install/dictionary
+ install -m 755 -D debian/remove.debian \
+ $(DESTDIR)/usr/lib/emacsen-common/packages/remove/dictionary
+
+ dh_installdocs README
+ dh_installdeb
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-arch
+
+.PHONY: binary binary-arch clean
diff --git a/dictionary-init.el b/dictionary-init.el
new file mode 100755
index 0000000..7f430f2
--- /dev/null
+++ b/dictionary-init.el
@@ -0,0 +1,26 @@
+;; 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))
+
+;; Bypass custom-add-load to speed startup.
+(put 'dictionary 'custom-loads '(dictionary))
+(put 'dictionary-group 'custom-loads '(dictionary)) \ No newline at end of file
diff --git a/dictionary.el b/dictionary.el
new file mode 100755
index 0000000..a5885c3
--- /dev/null
+++ b/dictionary.el
@@ -0,0 +1,1327 @@
+;; dictionary.el -- an interface to RFC 2229 dictionary server
+
+;; Author: Torsten Hilbrich <dictionary@myrkr.in-berlin.de>
+;; Keywords: interface, dictionary
+
+;; 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 'easymenu)
+(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))))
+
+(defun dictionary-set-server-var (name value)
+ (if (and (boundp 'dictionary-connection)
+ dictionary-connection
+ (eq (connection-status dictionary-connection) 'up)
+ (y-or-n-p
+ (concat "Close existing connection to " dictionary-server "? ")))
+ (connection-close dictionary-connection))
+ (set-default name value))
+
+(defgroup dictionary nil
+ "Client for accessing the dictd server based dictionaries"
+ :group 'hypermedia)
+
+(defgroup dictionary-proxy nil
+ "Proxy configuration options for the dictionary client"
+ :group 'dictionary)
+
+(defcustom dictionary-server
+ "dict.org"
+ "This server is contacted for searching the dictionary"
+ :group 'dictionary
+ :set 'dictionary-set-server-var
+ :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
+ :set 'dictionary-set-server-var
+ :type 'number)
+
+(defcustom dictionary-identification
+ "dictionary.el emacs lisp dictionary client"
+ "This is the identification string that will be sent to the server."
+ :group 'dictionary
+ :type 'string)
+
+(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-default-popup-strategy
+ "exact"
+ "The default strategy for listing matching words within a popup window.
+
+The following algorithm (defined by the dictd server) are supported
+by the choice value:
+
+- Exact match
+
+ The found word exactly matches the searched word.
+
+- Similiar sounding
+
+ The found word sounds similiar to the searched word. For this match type
+ the soundex algorithm defined by Donald E. Knuth is used. It will only
+ works with english words and the algorithm is not very reliable (i.e.,
+ the soundex algorithm is quite simple).
+
+- Levenshtein distance one
+
+ The Levenshtein distance is defined as the number of insertions, deletions,
+ or replacements needed to get the searched word. This algorithm searches
+ for word where spelling mistakes are allowed. Levenshtein distance one
+ means there is either a deleted character, an inserted character, or a
+ modified one.
+
+- User choice
+
+ Here you can enter any matching algorithm supported by your
+ dictionary server.
+"
+ :group 'dictionary
+ :type '(choice (const :tag "Exact match" "exact")
+ (const :tag "Similiar sounding" "soundex")
+ (const :tag "Levenshtein distance one" "lev")
+ (string :tag "User choice")))
+
+(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)
+
+(defcustom dictionary-use-http-proxy
+ nil
+ "Connects via a HTTP proxy using the CONNECT command when not nil."
+ :group 'dictionary-proxy
+ :set 'dictionary-set-server-var
+ :type 'boolean)
+
+(defcustom dictionary-proxy-server
+ "proxy"
+ "The name of the HTTP proxy to use when dictionary-use-http-proxy is set."
+ :group 'dictionary-proxy
+ :set 'dictionary-set-server-var
+ :type 'string)
+
+(defcustom dictionary-proxy-port
+ 3128
+ "The port of the proxy server, used only when dictionary-use-http-proxy is set."
+ :group 'dictionary-proxy
+ :set 'dictionary-set-server-var
+ :type 'number)
+
+(defcustom dictionary-use-single-buffer
+ nil
+ "Should the dictionary command reuse previous dictionary buffers?"
+ :group 'dictionary
+ :type 'boolean)
+
+(defcustom dictionary-description-open-delimiter
+ ""
+ "The delimiter to display in front of the dictionaries description"
+ :group 'dictionary
+ :type 'string)
+
+(defcustom dictionary-description-close-delimiter
+ ""
+ "The delimiter to display after of the dictionaries description"
+ :group 'dictionary
+ :type 'string)
+
+;; Define only when coding-system-list is available
+(when (fboundp 'coding-system-list)
+ (defcustom dictionary-coding-systems-for-dictionaries
+ '( ("mueller" . koi8-r))
+ "Mapping of dictionaries to coding systems.
+ Each entry in this list defines the coding system to be used for that
+ dictionary. The default coding system for all other dictionaries
+ is utf-8"
+ :group 'dictionary
+ :type `(repeat (cons :tag "Association"
+ (string :tag "Dictionary name")
+ (choice :tag "Coding system"
+ :value 'utf-8
+ ,@(mapcar (lambda (x) (list 'const x))
+ (coding-system-list))
+ ))))
+
+ )
+
+(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 "cyan"))
+ (((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-selected-window
+ nil
+ "The currently selected window")
+
+(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.")
+
+(defvar dictionary-color-support
+ (condition-case nil
+ (x-display-color-p)
+ (error nil))
+ "Determines if the Emacs has support to display color")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Basic function providing startup actions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;;###autoload
+(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)
+
+ (if (featurep 'xemacs)
+ (make-local-hook 'kill-buffer-hook))
+ (add-hook 'kill-buffer-hook 'dictionary-close t t)
+ (run-hooks 'dictionary-mode-hook))
+
+;;;###autoload
+(defun dictionary ()
+ "Create a new dictonary buffer and install dictionary-mode"
+ (interactive)
+ (let ((buffer (or (and dictionary-use-single-buffer
+ (get-buffer "*Dictionary buffer*"))
+ (generate-new-buffer "*Dictionary buffer*")))
+ (window-configuration (current-window-configuration))
+ (selected-window (frame-selected-window)))
+
+ (switch-to-buffer-other-window buffer)
+ (dictionary-mode)
+
+ (make-local-variable 'dictionary-window-configuration)
+ (make-local-variable 'dictionary-selected-window)
+ (setq dictionary-window-configuration window-configuration)
+ (setq dictionary-selected-window selected-window)
+ (dictionary-check-connection)
+ (dictionary-new-buffer)
+ (dictionary-store-positions)
+ (dictionary-store-state 'dictionary-new-buffer nil)))
+
+(defun dictionary-new-buffer (&rest ignore)
+ "Create a new and clean buffer"
+
+ (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)
+
+ (if (and (string-match "GNU" (emacs-version))
+ (not window-system))
+ (define-key dictionary-mode-map [9] 'dictionary-next-link)
+ (define-key dictionary-mode-map [tab] 'dictionary-next-link))
+
+ ;; shift-tabs normally is supported on window systems only, but
+ ;; I do not enforce it
+ (define-key dictionary-mode-map [(shift tab)] 'dictionary-prev-link)
+
+ (define-key dictionary-mode-map "n" 'dictionary-next-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)))
+ (let ((wanted 'raw-text)
+ (coding-system nil))
+ (if (and (fboundp 'coding-system-list)
+ (member wanted (coding-system-list)))
+ (setq coding-system wanted))
+ (let ((coding-system-for-read coding-system)
+ (coding-system-for-write coding-system))
+ (message "Opening connection to %s:%s" dictionary-server
+ dictionary-port)
+ (connection-close dictionary-connection)
+ (setq dictionary-connection
+ (if dictionary-use-http-proxy
+ (connection-open dictionary-proxy-server
+ dictionary-proxy-port)
+ (connection-open dictionary-server dictionary-port)))
+ (process-kill-without-query
+ (connection-process dictionary-connection))
+
+ (when dictionary-use-http-proxy
+ (message "Proxy CONNECT to %s:%d"
+ dictionary-proxy-server
+ dictionary-proxy-port)
+ (dictionary-send-command (format "CONNECT %s:%d HTTP/1.1"
+ dictionary-server
+ dictionary-port))
+ ;; just a \r\n combination
+ (dictionary-send-command "")
+
+ ;; read first line of reply
+ (let* ((reply (dictionary-read-reply))
+ (reply-list (dictionary-split-string reply)))
+ ;; first item is protocol, second item is code
+ (unless (= (string-to-number (cadr reply-list)) 200)
+ (error "Bad reply from proxy server %s" reply))
+
+ ;; skip the following header lines until empty found
+ (while (not (equal reply ""))
+ (setq reply (dictionary-read-reply)))))
+
+ (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 (&rest ignore)
+ "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)
+ (selected-window dictionary-selected-window))
+ (kill-buffer (current-buffer))
+ (set-window-configuration configuration)
+ (select-window selected-window)))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 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?\n" 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 "\r\n" answer start)
+ (setq answer (replace-match "\n" t t answer))
+ (setq start (1- (match-end 0))))
+ (setq start 0)
+ (if (string-match "\n\\.\n.*" answer start)
+ (setq answer (replace-match "" t t answer)))
+ 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))))
+
+(defun dictionary-coding-system (dictionary)
+ "Select coding system to use for that dictionary"
+ (when (boundp 'dictionary-coding-systems-for-dictionaries)
+ (let ((coding-system
+ (or (cdr (assoc dictionary
+ dictionary-coding-systems-for-dictionaries))
+ 'utf-8)))
+ (if (member coding-system (coding-system-list))
+ coding-system
+ nil))))
+
+(defun dictionary-decode-charset (text dictionary)
+ "Convert the text from the charset defined by the dictionary given."
+ (let ((coding-system (dictionary-coding-system dictionary)))
+ (if coding-system
+ (decode-coding-string text coding-system)
+ text)))
+
+(defun dictionary-encode-charset (text dictionary)
+ "Convert the text to the charset defined by the dictionary given."
+ (let ((coding-system (dictionary-coding-system dictionary)))
+ (if coding-system
+ (encode-coding-string text coding-system)
+ text)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 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"
+ (interactive)
+ (dictionary-store-positions)
+ (let ((word (car args))
+ (dictionary (cdr args)))
+
+ (if all
+ (setq dictionary dictionary-default-dictionary))
+ (dictionary-ensure-buffer)
+ (dictionary-new-search-internal word dictionary 'dictionary-display-search-result)
+ (dictionary-store-state 'dictionary-new-search-internal
+ (list word dictionary 'dictionary-display-search-result))))
+
+(defun dictionary-new-search-internal (word dictionary function)
+ "Starts a new search after preparing the buffer"
+ (dictionary-pre-buffer)
+ (dictionary-do-search word dictionary function))
+
+(defun dictionary-do-search (word dictionary function &optional nomatching)
+ "The workhorse for doing the search"
+
+ (message "Searching for %s in %s" word dictionary)
+ (dictionary-send-command (concat "define "
+ (dictionary-encode-charset dictionary "")
+ " \""
+ (dictionary-encode-charset word dictionary)
+ "\""))
+
+ (message nil)
+ (let ((reply (dictionary-read-reply-and-split)))
+ (if (dictionary-check-reply reply 552)
+ (progn
+ (unless nomatching
+ (beep)
+ (insert "Word not found, maybe you are looking "
+ "for one of these words\n\n")
+ (dictionary-do-matching word
+ dictionary
+ "."
+ 'dictionary-display-only-match-result)
+ (dictionary-post-buffer)))
+ (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)))
+ (funcall function 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 " ")
+
+ (link-insert-link "[Quit]" 'dictionary-button-face
+ 'dictionary-close nil
+ "Mouse-2 to close this window")
+
+ (insert "\n ")
+
+ (link-insert-link "[Select 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 "
+ dictionary-description-open-delimiter
+ (dictionary-decode-charset description dictionary)
+ dictionary-description-close-delimiter
+ " [" (dictionary-decode-charset dictionary 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 (dictionary-decode-charset reply dictionary))
+ (insert "\n\n")
+ (let ((regexp "\\({+\\)\\([^ '\"][^}]*\\)\\(}+\\)"))
+ (goto-char start)
+ (while (< (point) (point-max))
+ (if (search-forward-regexp regexp nil t)
+ (let ((match-start (match-beginning 2))
+ (match-end (match-end 2)))
+ (if dictionary-color-support
+ ;; Compensate for the replacement
+ (let ((brace-match-length (- (match-end 1)
+ (match-beginning 1))))
+ (setq match-start (- (match-beginning 2)
+ brace-match-length))
+ (setq match-end (- (match-end 2)
+ brace-match-length))
+ (replace-match "\\2")))
+ (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))
+ (translated (dictionary-decode-charset description dictionary)))
+ (if dictionary
+ (if (equal dictionary "--exit--")
+ (insert "(end of default search list)\n")
+ (link-insert-link (concat dictionary ": " translated)
+ '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)
+ (dictionary-restore-state)
+ (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-encode-charset 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)
+ (dictionary-restore-state)
+ (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-display-match-result)
+ (dictionary-store-state 'dictionary-do-matching
+ (list word dictionary-default-dictionary
+ dictionary-default-strategy
+ 'dictionary-display-match-result)))
+
+(defun dictionary-do-matching (word dictionary strategy function)
+ "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-encode-charset dictionary "") " "
+ (dictionary-encode-charset strategy "") " \""
+ (dictionary-encode-charset 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)))
+ (funcall function reply)))
+
+(defun dictionary-display-only-match-result (reply)
+ "Display the results from the current matches without the headers."
+
+ (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)))))
+
+(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)
+ (setq word (dictionary-decode-charset word dictionary))
+ (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
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;;###autoload
+(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 (let ((default (current-word t)))
+ (read-string (if default
+ (format "Search word (%s): " default)
+ "Search word: ")
+ nil nil default))
+ (if current-prefix-arg
+ (read-string (if dictionary-default-dictionary
+ (format "Dictionary (%s): " dictionary-default-dictionary)
+ "Dictionary: ")
+ nil nil 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)))
+
+;;;###autoload
+(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))
+
+;;;###autoload
+(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))
+
+;;;###autoload
+(defun dictionary-mouse-popup-matching-words (event)
+ "Display entries matching the word at the cursor"
+ (interactive "e")
+ (let ((word (save-window-excursion
+ (save-excursion
+ (mouse-set-point event)
+ (current-word)))))
+ (selected-window)
+ (dictionary-popup-matching-words word)))
+
+;;;###autoload
+(defun dictionary-popup-matching-words (&optional word)
+ "Display entries matching the word at the point"
+ (interactive)
+ (unless (functionp 'popup-menu)
+ (error "Sorry, popup menus are not available in this emacs version"))
+ (dictionary-do-matching (or word (current-word))
+ dictionary-default-dictionary
+ dictionary-default-popup-strategy
+ 'dictionary-process-popup-replies))
+
+(defun dictionary-process-popup-replies (reply)
+ (let ((number (nth 1 (dictionary-reply-list reply)))
+ (list (dictionary-simple-split-string (dictionary-read-answer) "\n+")))
+
+ (let ((result (mapcar (lambda (item)
+ (let* ((list (dictionary-split-string item))
+ (dictionary (car list))
+ (word (dictionary-decode-charset
+ (cadr list) dictionary)))
+ (message word)
+ (if (equal word "")
+ [ "-" nil nil]
+ (vector (concat "[" dictionary "] " word)
+ `(dictionary-new-search
+ '(,word . ,dictionary))
+ t ))))
+
+ list)))
+ (let ((menu (make-sparse-keymap 'dictionary-popup)))
+
+ (easy-menu-define dictionary-mode-map-menu dictionary-mode-map
+ "Menu used for displaying dictionary popup"
+ (cons "Matching words"
+ `(,@result)))
+ (popup-menu dictionary-mode-map-menu)))))
+
+;;; Tooltip support
+
+;; Common to GNU Emacs and XEmacs
+
+;; Add a mode indicater named "Dict"
+(defvar dictionary-tooltip-mode
+ nil
+ "Indicates wheather the dictionary tooltip mode is active")
+(nconc minor-mode-alist '((dictionary-tooltip-mode " Dict")))
+
+(defcustom dictionary-tooltip-dictionary
+ nil
+ "This dictionary to lookup words for tooltips"
+ :group 'dictionary
+ :type 'string)
+
+(defun dictionary-definition (word &optional dictionary)
+ (interactive)
+ (unwind-protect
+ (let ((dictionary (or dictionary dictionary-default-dictionary)))
+ (dictionary-do-search word dictionary 'dictionary-read-definition t))
+ nil))
+
+(defun dictionary-read-definition (reply)
+ (let ((list (dictionary-simple-split-string (dictionary-read-answer) "\n+")))
+ (mapconcat 'identity (cdr list) "\n")))
+
+(defconst dictionary-use-balloon-help
+ (eval-when-compile
+ (condition-case nil
+ (require 'balloon-help)
+ (error nil))))
+
+(if dictionary-use-balloon-help
+ (progn
+
+;; The following definition are only valid for XEmacs with balloon-help
+
+(defvar dictionary-balloon-help-position nil
+ "Current position to lookup word")
+
+(defun dictionary-balloon-help-store-position (event)
+ (setq dictionary-balloon-help-position (event-point event)))
+
+(defun dictionary-balloon-help-description (&rest extent)
+ "Get the word from the cursor and lookup it"
+ (if dictionary-balloon-help-position
+ (let ((word (save-window-excursion
+ (save-excursion
+ (goto-char dictionary-balloon-help-position)
+ (current-word)))))
+ (let ((definition
+ (dictionary-definition word dictionary-tooltip-dictionary)))
+ (if definition
+ (dictionary-decode-charset definition
+ dictionary-tooltip-dictionary)
+ nil)))))
+
+(defvar dictionary-balloon-help-extent nil
+ "The extent for activating the balloon help")
+
+(make-variable-buffer-local 'dictionary-balloon-help-extent)
+
+;;;###autoload
+(defun dictionary-tooltip-mode (&optional arg)
+ "Display tooltips for the current word"
+ (interactive "P")
+ (let* ((on (if arg
+ (> (prefix-numeric-value arg) 0)
+ (not dictionary-tooltip-mode))))
+ (make-local-variable 'dictionary-tooltip-mode)
+ (if on
+ ;; active mode
+ (progn
+ ;; remove old extend
+ (if dictionary-balloon-help-extent
+ (delete-extent dictionary-balloon-help-extent))
+ ;; create new one
+ (setq dictionary-balloon-help-extent (make-extent (point-min)
+ (point-max)))
+ (set-extent-property dictionary-balloon-help-extent
+ 'balloon-help
+ 'dictionary-balloon-help-description)
+ (set-extent-property dictionary-balloon-help-extent
+ 'start-open nil)
+ (set-extent-property dictionary-balloon-help-extent
+ 'end-open nil)
+ (add-hook 'mouse-motion-hook
+ 'dictionary-balloon-help-store-position))
+
+ ;; deactivate mode
+ (if dictionary-balloon-help-extent
+ (delete-extent dictionary-balloon-help-extent))
+ (remove-hook 'mouse-motion-hook
+ 'dictionary-balloon-help-store-position))
+ (setq dictionary-tooltip-mode on)
+ (balloon-help-minor-mode on)))
+
+) ;; end of XEmacs part
+
+(defvar global-dictionary-tooltip-mode
+ nil)
+
+;;; Tooltip support for GNU Emacs
+(defun dictionary-display-tooltip (event)
+ "Search the current word in the `dictionary-tooltip-dictionary'."
+ (interactive "e")
+ (if dictionary-tooltip-dictionary
+ (let ((word (save-window-excursion
+ (save-excursion
+ (mouse-set-point event)
+ (current-word)))))
+ (let ((definition
+ (dictionary-definition word dictionary-tooltip-dictionary)))
+ (if definition
+ (tooltip-show
+ (dictionary-decode-charset definition
+ dictionary-tooltip-dictionary)))
+ t))
+ nil))
+
+;;;###autoload
+(defun dictionary-tooltip-mode (&optional arg)
+ "Display tooltips for the current word"
+ (interactive "P")
+ (require 'tooltip)
+ (let ((on (if arg
+ (> (prefix-numeric-value arg) 0)
+ (not dictionary-tooltip-mode))))
+ (make-local-variable 'dictionary-tooltip-mode)
+ (setq dictionary-tooltip-mode on)
+ ;; make sure that tooltip is still (global available) even is on
+ ;; if nil
+ (tooltip-mode 1)
+ (add-hook 'tooltip-hook 'dictionary-display-tooltip)
+ (make-local-variable 'track-mouse)
+ (setq track-mouse on)))
+
+;;;###autoload
+(defun global-dictionary-tooltip-mode (&optional arg)
+ "Enable/disable dictionary-tooltip-mode for all buffers"
+ (interactive "P")
+ (require 'tooltip)
+ (let* ((on (if arg (> (prefix-numeric-value arg) 0)
+ (not global-dictionary-tooltip-mode)))
+ (hook-fn (if on 'add-hook 'remove-hook)))
+ (setq global-dictionary-tooltip-mode on)
+ (tooltip-mode 1)
+ (funcall hook-fn 'tooltip-hook 'dictionary-display-tooltip)
+ (setq-default dictionary-tooltip-mode on)
+ (setq-default track-mouse on)))
+
+) ;; end of GNU Emacs part
+
+(provide 'dictionary)
+
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 100755
index 0000000..97e03f3
--- /dev/null
+++ b/link.el
@@ -0,0 +1,120 @@
+;;; link.el -- putting clickable links into the buffer
+
+;; Author: Torsten Hilbrich <dictionary@myrkr.in-berlin.de>
+;; Keywords: interface, hypermedia
+
+;; 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)))
+ (remove-text-properties start end properties)
+ (add-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 "\r" 'link-selected)
+ (define-key keymap "\M-\r" 'link-selected-all))
+
+(provide 'link)
diff --git a/lpath.el b/lpath.el
new file mode 100755
index 0000000..858179f
--- /dev/null
+++ b/lpath.el
@@ -0,0 +1,4 @@
+;; Shut up.
+
+(setq load-path (cons "." load-path))
+