summaryrefslogtreecommitdiffstats
path: root/misc
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@cygnus.com>2000-06-16 07:49:23 +0000
committerUlrich Drepper <drepper@cygnus.com>2000-06-16 07:49:23 +0000
commit60d2084de5dc3b65e6657f695f0f26df24b0f565 (patch)
tree224f21c30351570d6d7f06a385e829d5ab320f67 /misc
downloadexternal_gettext-60d2084de5dc3b65e6657f695f0f26df24b0f565.zip
external_gettext-60d2084de5dc3b65e6657f695f0f26df24b0f565.tar.gz
external_gettext-60d2084de5dc3b65e6657f695f0f26df24b0f565.tar.bz2
Initial revision
Diffstat (limited to 'misc')
-rw-r--r--misc/Admin/alias.X11202
-rw-r--r--misc/ChangeLog699
-rw-r--r--misc/Makefile.am31
-rw-r--r--misc/Makefile.in307
-rw-r--r--misc/README-Tcl52
-rwxr-xr-xmisc/combine-sh141
-rwxr-xr-xmisc/elisp-comp42
-rw-r--r--misc/gettext-sh63
-rw-r--r--misc/gettext.perl86
-rw-r--r--misc/gettextize.in177
-rw-r--r--misc/locale.alias52
-rw-r--r--misc/magic.add9
-rw-r--r--misc/po-mode.el2602
-rw-r--r--misc/tcl_gettext.c165
14 files changed, 4628 insertions, 0 deletions
diff --git a/misc/Admin/alias.X11 b/misc/Admin/alias.X11
new file mode 100644
index 0000000..401d3bd
--- /dev/null
+++ b/misc/Admin/alias.X11
@@ -0,0 +1,202 @@
+# $XConsortium: locale.alias,v 1.9 94/08/23 18:12:18 kaleb Exp $
+#
+# This file contains alias name of locale.
+# Each alias name is described within one line.
+# The first word is the alias name (simplified locale name)
+# the second word is full locale name.
+#
+POSIX C
+POSIX-UTF2 C
+C.en C
+Cextend en_US.ISO8859-1
+Cextend.en en_US.ISO8859-1
+English_United-States.437 C
+#
+ar ar_AA.ISO8859-6
+ar_AA ar_AA.ISO8859-6
+bg bg_BG.ISO8859-5
+bg_BG bg_BG.ISO8859-5
+cs cs_CS.ISO8859-2
+cs_CS cs_CS.ISO8859-2
+cz cz_CZ.ISO8859-2
+cz_CZ cz_CZ.ISO8859-2
+da da_DK.ISO8859-1
+da_DK da_DK.ISO8859-1
+da_DK.88591 da_DK.ISO8859-1
+da_DK.88591.en da_DK.ISO8859-1
+de de_DE.ISO8859-1
+de_DE de_DE.ISO8859-1
+De_DE de_DE.ISO8859-1
+De_DE.IBM-850 de_DE.ISO8859-1
+de_DE.88591 de_DE.ISO8859-1
+de_DE.88591.en de_DE.ISO8859-1
+GER_DE.8859 de_DE.ISO8859-1
+GER_DE.8859.in de_DE.ISO8859-1
+de_AT de_AT.ISO8859-1
+de_CH de_CH.ISO8859-1
+Du_BE du_BE.ISO8859-1
+Du_NL du_NL.ISO8859-1
+el el_GR.ISO8859-7
+el_GR el_GR.ISO8859-7
+en en_US.ISO8859-1
+en_GB en_GB.ISO8859-1
+en_GB.88591 en_GB.ISO8859-1
+en_GB.88591.en en_GB.ISO8859-1
+ENG_GB.8859 en_GB.ISO8859-1
+ENG_GB.8859.in en_GB.ISO8859-1
+en_AU en_AU.ISO8859-1
+en_CA en_CA.ISO8859-1
+en_US en_US.ISO8859-1
+En_US en_US.ISO8859-1
+en_US.88591 en_US.ISO8859-1
+en_US.88591.en en_US.ISO8859-1
+en_US.437 en_US.ISO8859-1
+en_US.646 en_US.ISO8859-1
+en_US.850 en_US.ISO8859-1
+es es_ES.ISO8859-1
+es_ES es_ES.ISO8859-1
+Es_ES es_ES.ISO8859-1
+Sp_SP es_ES.ISO8859-1
+Es_ES.IBM-850 es_ES.ISO8859-1
+es_ES.88591 es_ES.ISO8859-1
+es_ES.88591.en es_ES.ISO8859-1
+fi fi_FI.ISO8859-1
+fi_FI fi_FI.ISO8859-1
+fi_FI.88591 fi_FI.ISO8859-1
+fi_FI.88591.en fi_FI.ISO8859-1
+fr fr_FR.ISO8859-1
+fr_BE fr_BE.ISO8859-1
+fr_BE.88591 fr_BE.ISO8859-1
+fr_BE.88591.en fr_BE.ISO8859-1
+fr_CA fr_CA.ISO8859-1
+Fr_CA fr_CA.ISO8859-1
+Fr_CF fr_CF.ISO8859-1
+Fr_CA.IBM-850 fr_CA.ISO8859-1
+fr_CA.88591 fr_CA.ISO8859-1
+fr_CA.88591.en fr_CA.ISO8859-1
+fr_CH fr_CH.ISO8859-1
+fr_CH.88591 fr_CH.ISO8859-1
+fr_CH.88591.en fr_CH.ISO8859-1
+fr_FR fr_FR.ISO8859-1
+fr_FR.88591 fr_FR.ISO8859-1
+fr_FR.88591.en fr_FR.ISO8859-1
+FRE_FR.8859 fr_FR.ISO8859-1
+FRE_FR.8859.in fr_FR.ISO8859-1
+Gr_GR el_GR.ISO8859-7
+hr hr_HR.ISO8859-2
+hr_HR hr_HR.ISO8859-2
+hu hu_HU.ISO8859-2
+hu_HU hu_HU.ISO8859-2
+is is_IS.ISO8859-1
+is_IS is_IS.ISO8859-1
+it it_IT.ISO8859-1
+it_IT it_IT.ISO8859-1
+it_IT.88591 it_IT.ISO8859-1
+it_IT.88591.en it_IT.ISO8859-1
+it_CH it_CH.ISO8859-1
+iw iw_IL.ISO8859-8
+iw_IL iw_IL.ISO8859-8
+ja ja_JP.eucJP
+ja_JP ja_JP.eucJP
+ja_JP.ujis ja_JP.eucJP
+ja_JP.eucJP ja_JP.eucJP
+Ja_JP ja_JP.eucJP
+Jp_JP ja_JP.eucJP
+Jp_JP.IBM-932 ja_JP.eucJP
+ja_JP.AJEC ja_JP.eucJP
+ja_JP.EUC ja_JP.eucJP
+ja_JP.ISO-2022-JP ja_JP.JIS7
+ja_JP.JIS ja_JP.JIS7
+ja_JP.jis7 ja_JP.JIS7
+ja_JP.mscode ja_JP.SJIS
+ja_JP.SJIS ja_JP.SJIS
+ko ko_KR.eucKR
+ko_KR ko_KR.eucKR
+ko_KR.EUC ko_KR.eucKR
+ko_KR.euc ko_KR.eucKR
+mk mk_MK.ISO8859-5
+mk_MK mk_MK.ISO8859-5
+nl nl_NL.ISO8859-1
+nl_BE nl_BE.ISO8859-1
+Nl_BE nl_BE.ISO8859-1
+Nl_BE.IBM-850 nl_BE.ISO8859-1
+nl_BE.88591 nl_BE.ISO8859-1
+nl_BE.88591.en nl_BE.ISO8859-1
+nl_NL nl_NL.ISO8859-1
+Nl_NL nl_NL.ISO8859-1
+Nl_NL.IBM-850 nl_NL.ISO8859-1
+nl_NL.88591 nl_NL.ISO8859-1
+nl_NL.88591.en nl_NL.ISO8859-1
+no no_NO.ISO8859-1
+no_NO no_NO.ISO8859-1
+no_NO.88591 no_NO.ISO8859-1
+no_NO.88591.en no_NO.ISO8859-1
+pl pl_PL.ISO8859-2
+pl_PL pl_PL.ISO8859-2
+pt pt_PT.ISO8859-1
+pt_PT pt_PT.ISO8859-1
+Pt_PT pt_PT.ISO8859-1
+Po_PO pt_PT.ISO8859-1
+Pt_PT.IBM-850 pt_PT.ISO8859-1
+pt_PT.88591 pt_PT.ISO8859-1
+pt_PT.88591.en pt_PT.ISO8859-1
+ro ro_RO.ISO8859-2
+ro_RO ro_RO.ISO8859-2
+ru ru_SU.ISO8859-5
+ru_SU ru_SU.ISO8859-5
+sh sh_YU.ISO8859-2
+sh_YU sh_YU.ISO8859-2
+sk sk_SK.ISO8859-2
+sk_SK sk_SK.ISO8859-2
+sl sl_CS.ISO8859-2
+sl_CS sl_CS.ISO8859-2
+sp sp_YU.ISO8859-5
+sp_YU sp_YU.ISO8859-5
+sv sv_SE.ISO8859-1
+sv_SE sv_SE.ISO8859-1
+Sv_SE sv_SE.ISO8859-1
+Sv_SV sv_SE.ISO8859-1
+Sv_SE.IBM-850 sv_SE.ISO8859-1
+sv_SE.88591 sv_SE.ISO8859-1
+sv_SE.88591.en sv_SE.ISO8859-1
+th_TH th_TH.TACTIS
+tr tr_TR.ISO8859-9
+tr_TR tr_TR.ISO8859-9
+zh zh_CN.eucCN
+zh_CN zh_CN.eucCN
+zh_CN.EUC zh_CN.eucCN
+zh_TW zh_TW.eucTW
+zh_TW.EUC zh_TW.eucTW
+arabic ar_AA.ISO8859-6
+bulgarian bg_BG.ISO8859-5
+chinese-s zh_CN.eucCN
+chinese-t zh_TW.eucTW
+croatian hr_HR.ISO8859-2
+czech cs_CS.ISO8859-2
+danish da_DK.ISO8859-1
+dutch nl_BE.ISO8859-1
+finnish fi_FI.ISO8859-1
+french fr_CH.ISO8859-1
+german de_CH.ISO8859-1
+greek el_GR.ISO8859-7
+hebrew iw_IL.ISO8859-8
+hungarian hu_HU.ISO8859-2
+icelandic is_IS.ISO8859-1
+iso_8859_1 en_US.ISO8859-1
+ISO8859-1 en_US.ISO8859-1
+italian it_CH.ISO8859-1
+japan ja_JP.eucJP
+japanese ja_JP.eucJP
+Japanese-EUC ja_JP.eucJP
+korean ko_KR.eucKR
+norwegian no_NO.ISO8859-1
+polish pl_PL.ISO8859-2
+portuguese pt_PT.ISO8859-1
+rumanian ro_RO.ISO8859-2
+russian ru_SU.ISO8859-5
+serbocroatian sh_YU.ISO8859-2
+slovak sk_SK.ISO8859-2
+slovene sl_CS.ISO8859-2
+spanish es_ES.ISO8859-1
+swedish sv_SE.ISO8859-1
+turkish tr_TR.ISO8859-9
diff --git a/misc/ChangeLog b/misc/ChangeLog
new file mode 100644
index 0000000..649f1ff
--- /dev/null
+++ b/misc/ChangeLog
@@ -0,0 +1,699 @@
+2000-05-06 Ulrich Drepper <drepper@redhat.com>
+
+ * gettextize.in: Remove code to test for version of the m4 files.
+
+ * po-mode.el: A few more changes by Fran^Áçois Pinard.
+
+1998-05-03 Fran^Áçois Pinard <pinard@iro.umontreal.ca>
+
+ * po-mode.el (po-create-overlay) [po-XEMACS]: No argument.
+ Reported by Ulrich Drepper.
+
+1997-10-18 Fran^Áçois Pinard <pinard@iro.umontreal.ca>
+
+ * po-mode.el (po-tags-search, po-mark-found-string): C++ as C.
+ (po-find-c-string): Skip C++ comments as well.
+
+1998-05-10 Fran^Áçois Pinard <pinard@iro.umontreal.ca>
+
+ * po-mode.el (po-mode) [po-XEMACS]: Explicitely add menus.
+ Reported by Hrvoje Niksic.
+
+ * po-mode.el (po-mode-menu-layout): Give real access to auxiliary
+ files through the menu, instead of leaving menu entries inactive.
+
+1998-05-15 Ulrich Drepper <drepper@cygnus.com>
+
+ * tcl_gettext.c (tcl_gettext): Replace illegal with invalid.
+
+1998-03-30 François Pinard <pinard@iro.umontreal.ca>
+
+ * po-mode.el (po-tags-search, po-mark-translatable,
+ po-select-mark-and-mark): Call interactive after the doc string,
+ instead of before.
+ Reported by Tom Tromey.
+
+1998-04-27 21:17 Ulrich Drepper <drepper@cygnus.com>
+
+ * po-mode.el: Update from most recent version.
+
+ * gettextize.in: Use aclocaldir from configuration.
+
+1997-09-04 François Pinard <pinard@iro.umontreal.ca>
+
+ * po-mode.el: Rename po-middle-of-entry to po-start-of-msgstr, add
+ variable po-start-of-msgid. Use it whenever appropriate.
+
+ * po-mode.el (po-find-file-coding-system): New function.
+ Reported by Ken'ichi Handa.
+
+ * po-mode.el: Normalise string= to string-equal.
+
+ * po-mode.el (po-send-mail): Allow for mailing to the team.
+ (po-guess-team-address): New function.
+
+1997-09-02 François Pinard <pinard@iro.umontreal.ca>
+
+ * po-mode.el (po-set-comment): Unused variable buffer.
+ (po-edit-string): Unused variables start, middle, end and obsolete.
+ (po-tags-search): Unused variable find-string.
+
+ * po-mode.el (po-check-lock): Create the work buffer as required, to
+ avoid diagnostics about selecting a deleted buffer, after a user
+ explicitly killed the work buffer instead of exiting it normally.
+ Reported by Hrvoje Niksic.
+
+ * po-mode.el: New variable po-mode-menu-layout.
+ (po-mode): Establish a bar mode menu if possible.
+ Reported by Nils Naumann.
+
+ * po-mode.el: Decide set-translation-domain before using it.
+ This avoids a byte-compilation warning.
+
+ * po-mode.el (po-set-comment): Rearrange wrong conditional flow.
+ Translator comments were duplicated, when contents were unchanged.
+ Reported by Enrique Melero.
+
+1997-09-01 François Pinard <pinard@iro.umontreal.ca>
+
+ * po-mode.el (po-highlight, po-dehighlight): New functions.
+ New globals: po-highlight-p, po-highlight-face and po-overlay.
+ (po-edit-msgstr): Highlight the msgid string while editing.
+ (po-tags-search): Highlight found string.
+ (po-mark-found-string): Unhilight string before replacing it.
+ Reported by Jim Meyering, Michel Robitaille and Ulrich Drepper.
+
+ * po-mode.el (po-set-field): Tells if buffer was modified.
+ (po-edit-msgstr): Never make fuzzy an entry which is unmodified.
+
+ * po-mode.el: Add M command, and variables po-compose-mail-function,
+ po-translation-project-address and po-gzip-uuencode-command.
+ (po-guess-archive-name, po-send-mail): New functions.
+ Reported by Karl Eichwalder.
+
+1997-08-31 François Pinard <pinard@iro.umontreal.ca>
+
+ * po-mode.el (po-replace-revision-date): Enforce ISO 8601 zones.
+ Reported by Enrique Melero Gómez, Karl Eichwalder, Max de
+ Mendizabal and Santiago Vila Doncel.
+
+ * po-mode.el (po-edit-string): Expand tabs while editing
+ translations. Reported by Göran Uddeborg.
+
+ * po-mode.el: Accept C-c C-k to abort recursive edits.
+ Reported by Göran Uddeborg and Hrvoje Niksic.
+
+1997-06-02 Ben Pfaff <pfaffben@pilot.msu.edu>
+
+ * po-mode.el (po-find-c-string, po-extract-unquoted): Process ANSI
+ string concatenation and K&R escaped newlines.
+
+1997-03-02 Hrvoje Niksic <hniksic@srce.hr>
+
+ * po-mode.el (po-help): To continue, also accept things like a
+ mouse press or an arrow key.
+
+1996-11-12 François Pinard <pinard@iro.umontreal.ca>
+
+ * po-mode.el: Alter po-font-lock-keywords to properly highlight C
+ formats, when using an upper case letter as formatting functor.
+
+ * po-mode.el: If available, prefer force-mode-line-update builtin.
+
+ * po-mode.el: Use our own buffer-substring, defining it as
+ buffer-substring-no-properties if available. Because of text
+ properties, buffer-substring does not always return a string.
+
+ * po-mode.el (po-consider-source-path): Ensure a trailing slash.
+
+1996-05-13 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * po-mode.el (po-eval-requoted, po-extract-unquoted): Correct
+ missing or spurious backslashes in some regexps.
+
+1997-08-01 15:49 Ulrich Drepper <drepper@cygnus.com>
+
+ * Makefile.am (AUTOMAKE_OPTIONS): Require version 1.2.
+
+1997-04-12 Hrvoje Niksic <hniksic@srce.hr>
+
+ * po-mode.el: Customize.
+
+1997-03-10 06:56 Ulrich Drepper <drepper@cygnus.com>
+
+ * elisp-comp: Use EMACS environment variable is available instead
+ of always executing emacs.
+
+1996-12-03 23:24 Ulrich Drepper <drepper@cygnus.com>
+
+ * gettextize.in: Update --help and --version texts.
+
+1996-11-22 04:45 Ulrich Drepper <drepper@cygnus.com>
+
+ * Makefile.am (EXTRA_DIST): Add locale.alias.
+
+1996-11-21 23:11 Ulrich Drepper <drepper@cygnus.com>
+
+ * Makefile.am: Remove rules for ELisp handling. Automake now
+ knows what to do.
+
+1996-10-28 23:09 Ulrich Drepper <drepper@cygnus.com>
+
+ * gettextize.in: Remove -v from help message. Change format of
+ --version text according to last GNU coding standard. Don't print
+ help message for unknown option. Instead print "Try `..."
+ message.
+
+1996-10-19 17:41 1996 Ulrich Drepper <drepper@cygnus.com>
+
+ * locale.alias: Language for czech entry must be cs.
+
+1996-09-18 00:29 François Pinard <pinard@progiciels-bpi.ca>
+
+ * po-mode.el (po-font-lock-keywords): Correct highlighting of
+ formats like %3d.
+
+1996-08-19 François Pinard <pinard@iro.umontreal.ca>
+
+ * po-mode.el: Restructured to avoid all byte-compilation warnings.
+ Highlighting using `hilit19' is being deprecated, font lock code
+ should now automatically be activated whenever available.
+
+1996-07-15 François Pinard <pinard@iro.umontreal.ca>
+
+ * po-mode.el: po-mode.el (po-kill-msgstr): Ensure po-entry-type is
+ always defined before decreasing counter.
+
+1996-07-15 01:08 Ulrich Drepper <drepper@cygnus.com>
+
+ * gettextize.in (gettext_dir): Remove warning that files will be
+ removed. It's not really necessary since the -f option is
+ necessary. Suggested by François Pinard.
+
+1996-06-26 18:40 Ulrich Drepper <drepper@cygnus.com>
+
+ * po-mode.el: Added ELisp support. Patch by François Pinard.
+
+1996-06-18 15:12 Ulrich Drepper <drepper@cygnus.com>
+
+ * gettextize.in (aclocal_version): new variable. Value determined
+ by configure. This finally makes the check of the aclocal.m4
+ version number correct because this number need not be the same as
+ the version number of the package.
+
+1996-06-06 02:02 Ulrich Drepper <drepper@cygnus.com>
+
+ * gettextize.in: Rewrite copying now that files are kept in
+ different directories and don't use funny prefixes anymore.
+
+1996-06-05 16:36 Ulrich Drepper <drepper@cygnus.com>
+
+ * Makefile.am (DISTCLEANFILES): Renamed from CLEANFILES and
+ changed $(lisp_DATA) to $(ELCFILES).
+
+1996-06-03 00:46 Ulrich Drepper <drepper@cygnus.com>
+
+ * Makefile.am (elc_DATA): Rename to elc_SCRIPTS so that
+ distribution wents smooth.
+
+1996-06-02 21:16 Ulrich Drepper <drepper@cygnus.com>
+
+ * Makefile.am (SUFFIXES): New variable. Automake wants it this
+ way to introduce new suffixes.
+
+ * Makefile.am: Initial revision.
+
+1996-06-01 18:20 Ulrich Drepper <drepper@cygnus.com>
+
+ * Makefile.in (default): Add default rule because AIX' make does
+ not understand multiple goals in default rule.
+
+ * Makefile.in (DISTFILES): Rename README-TCL to README-Tcl.
+
+ * gettextize.in: Implement test for correct aclocal.m4 version.
+
+1996-04-06 02:40 Ulrich Drepper <drepper@myware>
+
+ * po-mode.el: Apply François' patch for new default values of
+ configuration variables and new header entry format.
+
+1996-04-02 18:56 Ulrich Drepper <drepper@myware>
+
+ * Makefile.in (all-gettext): New goal. Same as all.
+
+1996-04-02 03:18 François Pinard <pinard@iro.umontreal.ca>
+
+ * po-mode.el: * Let po-show-source-context update
+ po-reference-cursor itself, and display to the minibuffer the
+ relative and maximum position of the shown reference in the list
+ of collected references. Callers adjusted accordingly.
+ . Do not generate tildes while reconstructing non-obsolete
+ comments.
+ . Do merge attributes on a single `#,' line. Using the non-regexp
+ version of the search was causing the generation of another one.
+ . Remove a spurious trailing comma while removing the last
+ attribute.
+ . Limit the search for source references to the msgstr line. This
+ does not correct any bug, but is more consistent.
+
+1996-03-31 23:32 François Pinard <pinard@iro.umontreal.ca>
+
+ * po-mode.el: * Small corrections to the help page. Reported by
+ Karl Eichwalder.
+
+ * Change po-edit-mode-map to po-subedit-mode-map and
+ po-mode-edit-hook to po-subedit-mode-hook. The previous names
+ were not consistent. Reported by Karl Eichwalder.
+
+ * Repair RET, completely broken for multi-lines, maybe showing a
+ regexp bug in Emacs(?). See the FIXME in po-extract-unquoted.
+ Reported by Karl Eichwalder.
+
+1996-03-31 22:36 Ulrich Drepper <drepper@myware>
+
+ * gettextize.in (prefix): Define from @prefix@. Is used in
+ gettext_dir definition. Reported by Jim Meyering.
+
+1996-03-28 19:11 Karl Eichwalder <ke@ke.Central.DE>
+
+ * gettextize.in (gettext_dir): Set to @datadir@/gettext.
+
+1996-03-26 21:27 Ulrich Drepper <drepper@myware>
+
+ * Makefile.in (datadir): Initialize from @datadir@. Reported by
+ Karl Eichwalder.
+
+1996-03-25 09:52 François Pinard <pinard@iro.umontreal.ca>
+
+ * po-mode.el: * Correct documentation mistakes in short help.
+
+ * Accept both # and #~ for obsolete comments, but use #~ when
+ generating them.
+
+ * Recognize \NNN octal notation for characters in PO file strings,
+ however, never produce such horror.
+
+1996-03-25 03:51 Ulrich Drepper <drepper@myware>
+
+ * po-mode.el: Some last minute changes by François Pinard.
+
+1996-03-24 18:51 Ulrich Drepper <drepper@myware>
+
+ * po-mode.el (po-confirm-and-quit): Recognize both #, and #! but
+ prefer producing #,.
+
+ * Rephrase messages about location stack contents
+ * Clear out message when user refuses quitting.
+
+1996-03-23 14:34 François Pinard <pinard@iro.umontreal.ca>
+
+ * Implement po-default-file-header.
+ Reported by Karl Eichwalder.
+
+ * Rename po-auto-select to po-auto-select-entry.
+
+ * Revise text of all disruptive questions, try to alleviate
+ them, avoid them if possible. Clear the message area sometimes.
+
+ * Correct a bug by which `#! fuzzy' was inserted before the
+ white line, instead of after, for PO files having no `#' line
+ of any kind.
+
+ * Correct the message count updating in po-kill-msgstr and
+ po-yank-msgstr.
+
+ * Allow for po-auto-edit-with-msgid to work, when
+ po-edit-msgstr was called on an untranslated immediately after
+ loading a PO file.
+
+ * po-quit may select all kind of not fully processed entries,
+ rather than just untranslate ones.
+
+ Rebound commands:
+ * TAB moves to LFD for po-msgid-to-msgstr.
+ * z moves to DEL for po-fade-out-entry.
+
+ New commands:
+ * TAB is po-unfuzzy.
+ * SPC is po-auto-select.
+ * t is po-next-translated entry.
+ * M-t is po-previous-translated-entry.
+ * E is po-edit-out-full.
+
+ Improved commands:
+ * DEL (po-fade-out-entry) makes the entry fuzzy as first step,
+ and request confirmation for some transitions.
+ * LFD (po-msgid-to-msgstr) requests confirmation if entry was
+ already translated.
+ * v (po-validate): Pass the -v flag to msgfmt.
+ * q (po-confirm-and-quit): Use milder confirmation.
+ * Implemented variables po-auto-edit-with-msgid,
+ po-auto-fuzzy-on-edit, po-auto-select-on-unfuzzy, and
+ po-auto-replace-revision-date.
+
+ PO header management:
+ * PO-Revision-Date might be automatically updated.
+ Reported by Karl Eichwalder.
+ * A normalized PO file header is automatically created if it
+ not exists. Any previous PO file header is kept, obsoleted.
+
+ Various internal cleanups:
+ * Revised the PO mode summary display.
+ * ...-hooks renamed ...-hook, per word of Richard Stallman.
+ * po-obsolete-flag replaced by more general po-entry-type.
+ * po-appropriate-counter, po-increase-appropriate-counter and
+ po-decrease-appropriate-counter are replaced by po-type-counter,
+ po-decrease-type-counter and po-increase-type-counter.
+ Overall counting logic revised and cleaned up.
+ * The concept of being after last entry disappears. Being
+ after last entry is equivalent to being on last entry. And
+ since there is at least the PO header entry, and an empty PO
+ file is not possible anymore: simplified code accordingly.
+ * po-add-attribute, po-delete-attribute: New functions.
+ * po-offer-validation disappears, as (buffer-modified-p) may
+ be used instead.
+
+1996-03-14 16:55 François Pinard <pinard@iro.umontreal.ca>
+
+ * po-mode.el: Inexact entries are now called fuzzy. Change
+ regular expression and function names.
+
+1996-03-14 11:38 François Pinard <pinard@iro.umontreal.ca>
+
+ * po-mode.el: Rename po-mode-hooks to po-mode-edit-hooks.
+
+ * po-mode.el: Suggest accepting .pot and embedded .po. as triggers
+ for PO editing mode, besides .po and .pox.
+ * PO mode help display has been revised to fit in 23 lines,
+ and present some more yet unimplemented commands. PO mode
+ initially suggests using `h' or `?' for documentation.
+ * Many variables and functions have been renamed for more
+ clarity and consistency, too numerous to be detailed here.
+ * Reorganization of key-bindings. This restores to M-w and M-y
+ their usual meaning, and free some keys for to-be-implemented
+ commands: the a/M-a/A/M-A series for auxiliary files, c/M-c
+ for compendium files, and l/M-l/L/M-L series for lexicon files.
+ . Commands u, v, o and q have been renamed U, V, O and Q
+ (po-undo, po-validate, po-other-window and po-quit).
+ . Command v replaces old command V (po-mode-version).
+ . u and SPC replace e (po-next-untranslated-entry).
+ M-u replaces M-e (po-previous-untranslated-entry).
+ . o replaces M-n and M-SPC (po-next-obsolete-entry).
+ M-o replaces M-p and M-DEL (po-previous-obsolete-entry).
+ . SPC, DEL, and M-RET are no more po-next-entry,
+ po-previous-entry and po-edit-comment.
+ . r replaces l (po-pop-location).
+ . s (po-cycle-source-reference) replaces c (po-cycle-reference).
+ M-s (po-select-source-reference) replaces M-c (po-select-reference).
+ S (po-consider-source-path) replaces d (po-add-path).
+ M-S (po-ignore-source-path) replaces M-d (po-delete-path).
+ . K, W and Y replace M-k, M-w and M-y (po-kill-comment,
+ po-kill-ring-save-comment and po-yank-comment).
+ * New command q (po-confirm-and-quit).
+
+1996-03-13 13:16 Karl Eichwalder <ke@ke.Central.DE>
+
+ * po-mode.el (po-edit-string): run hook `po-edit-hooks'.
+
+1996-03-09 12:39 Ulrich Drepper <drepper@myware>
+
+ * po-mode.el (po-keywords): Add N_.
+
+1996-01-15 02:58 François Pinard <pinard@iro.umontreal.ca>
+
+ * gettextize.in: Better message about aclocal.m4 change.
+
+1995-12-19 22:41 Ulrich Drepper <drepper@myware>
+
+ * README-TCL, tcl_gettext.c: Initial revision.
+
+ * Makefile.in (DISTFILES): Add tcl_gettext and README-TCL.
+
+1995-12-19 22:12 Ulrich Drepper <drepper@myware>
+
+ * Makefile.in (Makefile, gettextize): Explicitly use $(SHELL) for
+ running shell scripts.
+
+1995-12-16 15:31 Ulrich Drepper <drepper@myware>
+
+ * gettextize.in: Implement -c option: always copy files.
+ Requested by Roland McGrath.
+
+1995-12-05 11:41 Larry Schwimmer <rosebud@cyclone.stanford.edu>
+
+ * Makefile.in (install-data): Make sure $(localedir) exists.
+
+1995-11-27 02:50 Sakai Kiyotaka <ksakai@netwk.ntt-at.co.jp>
+
+ * locale.alias: New entry for Japanese.
+
+1995-11-24 23:53 Ulrich Drepper <drepper@myware>
+
+ * po-mode.el (po-quit): Always clear the message area after y-or-n-p.
+
+1995-11-11 16:30 Ulrich Drepper <drepper@myware>
+
+ * po-mode.el: Implement searching of inexact entries.
+
+ * po-mode.el: Implement po-version.
+
+1995-11-08 01:46 Ulrich Drepper <drepper@myware>
+
+ * po-mode.el:
+ Hilit file names and line numbers in #: with function-name face.
+
+ * po-mode.el: Add support for XEmacs' font-lock.el.
+
+ * po-mode.el:
+ Patches by Franc,ois: enable hilit, handle multi-line #: lines, and
+ don't pass -v argument to msgfmt.
+
+1995-11-06 15:52 Ulrich Drepper <drepper@myware>
+
+ * po-mode.el: msgfmt behaves now well again. Return to use
+ /dev/null as output file for verification.
+
+1995-11-05 19:39 Ulrich Drepper <drepper@myware>
+
+ * Makefile.in (dist-gettext): Make synonym for dist.
+
+1995-11-05 15:40 Ulrich Drepper <drepper@myware>
+
+ * Makefile.in (dist): Suppress error message when ln failed.
+ Get files from $(srcdir) explicitly.
+
+1995-11-01 10:39 Ulrich Drepper <drepper@myware>
+
+ * gettextize.in:
+ Don't use "!" as negation; not all versions of sh support it. Patch
+ by Tom Tromey.
+
+1995-10-31 20:46 Ulrich Drepper <drepper@myware>
+
+ * po-mode.el (po-msgfmt-program):
+ Variable which contains name of the msgfmt program.
+ (po-validate): Use above variable.
+
+1995-10-31 19:12 Tom Tromey <tromey@cambric.colorado.edu>
+
+ * gettextize.in: Don't use "!" as negation; not all versions of sh
+ support it.
+
+1995-10-30 22:22 Ulrich Drepper <drepper@myware>
+
+ * po-mode.el (po-validate):
+ Protect the previous value of compile-command.
+ Change by Franc,ois Pinard.
+
+1995-10-29 12:11 Ulrich Drepper <drepper@myware>
+
+ * gettextize.in:
+ Change text of trailing message about aclocal.m4 changing. Suggested
+ by Franc,ois Pinard.
+
+ * Makefile.in (INSTALL_PROGRAM): Not used anymore.
+ (INSTALL_SCRIPT): New variable,
+ (install-exec): Install gettextize using INSTALL_SCRIPT.
+
+ * po-mode.el (po-eval-requoted): Add space in description.
+
+ * Makefile.in: Remove Emacs local variable setting.
+
+1995-10-28 22:09 Ulrich Drepper <drepper@myware>
+
+ * Makefile.in (install-src): Move some rules from install-data.
+ (install-data): Add installation of locale.alias.
+
+ * locale.alias: Initial revision
+
+1995-10-28 18:08 Ulrich Drepper <drepper@myware>
+
+ * po-mode.el: Apply latest patch by Franc,ois.
+
+1995-09-23 14:34 Ulrich Drepper <drepper@myware>
+
+ * gettextize.in:
+ Run config.status shell script if this is exists and is selected. This
+ is always necessary if one updates the intl/ dir.
+
+1995-09-20 22:26 Ulrich Drepper <drepper@myware>
+
+ * gettextize.in:
+ Try to remove files in root and po/ dir before linking. If this is
+ not done re-linking to the same file will cause an error.
+
+1995-09-07 00:21 Ulrich Drepper <drepper@myware>
+
+ * gettext-sh: Protect IFS assignments.
+
+1995-08-22 22:12 Ulrich Drepper <drepper@myware>
+
+ * gettextize.in (usage):
+ Rearrange help message. Now describe -f option.
+ Reported by Franc,ois Pinard.
+
+1995-08-19 23:32 Ulrich Drepper <drepper@myware>
+
+ * gettextize.in: Add missing terminating quotes.
+
+ * Makefile.in (INSTALL_PROGRAM):
+ *Do* use -m 755. Autoconf does not set any mode.
+
+ * Makefile.in (install-src):
+ Make behave like install. I.e. really install
+ gettextize and the .elc files.
+
+1995-08-19 15:08 Ulrich Drepper <drepper@myware>
+
+ * gettextize.in:
+ Some nicety changes of shell programming by Franc,ois Pinard.
+
+ * po-mode.el (po-search-path): Extend by "../".
+
+ * gettextize.in: Protect against relative source paths.
+ Avoid exit an second level shell.
+
+ * gettext-sh: Better comments: By Franc,ois Pinard.
+
+ * Makefile.in (INSTALL_PRG): Don't define mode ourself.
+ (uninstall) Remove gettextize.
+
+ * gettextize.in:
+ intl/VERSION is now a real file and must not be generated here.
+
+1995-08-18 12:05 Ulrich Drepper <drepper@myware>
+
+ * gettext-sh: Use -s option for gettext instead of --shell-script.
+
+1995-08-15 10:49 Ulrich Drepper <drepper@myware>
+
+ * Makefile.in (all, check):
+ Add gettextize to dependencies, so that install need not
+ build anything.
+
+1995-08-15 07:13 Ulrich Drepper <drepper@myware>
+
+ * gettextize.in: Add intl/VERSION file.
+
+ * gettextize.in: Remove target file for root- and po- file first.
+
+ * gettextize.in:
+ Files installed in top directory of package are now preceded by root-.
+ All other are ignore (esp aclocal.m4).
+
+1995-08-14 23:50 Ulrich Drepper <drepper@myware>
+
+ * Makefile.in (exec_prefix, bindir):
+ Directories needed for installing gettextize.
+ (transform): Standard GNU program name transformation.
+ (INSTALL_PROGRAM): Program to install gettextize as executable.
+ (DISTFILES): Remove makelinks.in. Distribute gettextize.in instead.
+ (install-src): Install gettextize in selected binary directory.
+
+ * gettextize.in: Initial revision
+
+1995-08-10 22:18 Ulrich Drepper <drepper@myware>
+
+ * gettext-sh: Fix typos. Reported by Franc,ois Pinard.
+ (TEXTDOMAIN): Set value from ${PACKAGE-NAME} variable and document it.
+
+1995-08-08 21:45 Ulrich Drepper <drepper@myware>
+
+ * Makefile.in (DISTFILES): Add locale.alias.
+
+1995-08-07 23:48 Ulrich Drepper <drepper@myware>
+
+ * Makefile.in (DISTFILES): gettext.perl moved from intl/.
+ gettext-sh: New file.
+
+ * gettext-sh: Initial revision.
+
+ * elisp-comp:
+ Use `rm -fr $tempdir' instead of `rm -f $tempdir/*; rmdir $tempdir'
+ because some NFS implementation create .nfsxxx files which are
+ not caught be the *. Reported by Paul Nevai.
+
+1995-08-04 22:38 Ulrich Drepper <drepper@myware>
+
+ * Makefile.in (.el.elc):
+ Include Franc,ois' wonderful pun to highlight warning text.
+
+ * Makefile.in (distclean): Remove makelinks.
+
+ * Makefile.in (dist): Remove `copying instead' message.
+
+1995-08-02 19:44 Ulrich Drepper <drepper@myware>
+
+ * Makefile.in (DISTFILES): makelinks.in instead of makelinks-sh.
+
+ * makelinks.in: First try making symbolic links.
+ Rename to makelinks.in because it will be configure by
+ config.status.
+
+1995-08-01 15:54 Ulrich Drepper <drepper@myware>
+
+ * po-mode.el: Fixes to run on DEMACS.
+ Provided by Franc,ois Pinard.
+
+ * Makefile.in (check): Make same as all.
+
+1995-08-01 10:32 Ulrich Drepper <drepper@myware>
+
+ * makelinks-sh: Implement option handling.
+ When intl/ subdir exist give warning and exit unless option -f
+ is given.
+ Use ${echo} in place where translations will be necessary.
+
+1995-07-26 01:24 Ulrich Drepper <drepper@myware>
+
+ * makelinks-sh: Update for correct intl_files list.
+ Handle existing directories.
+ Handle non-existing ln and/or ln -s.
+ Mostly by Franc,ois Pinard.
+
+1995-07-22 01:14 Ulrich Drepper <drepper@myware>
+
+ * Makefile.in (prefix,datadir,lispdir): New definitions.
+ (SITELISPDIR): Remove variable.
+ (all): Now build *.elc files.
+ (install,uninstall): Specify complete path of files to delete.
+
+1995-07-20 00:03 Ulrich Drepper <drepper@myware>
+
+ * Makefile.in (DISTFILES): elisp-comp was missing.
+
+1995-07-18 23:53 Ulrich Drepper <drepper@myware>
+
+ * po-mode.el: Latest version by Franc,ois. This version allows
+ scanning C source code for translatable strings and interactive
+ construction of the .po file. The string matching heuristic is
+ due to Richard Stallman.
+
+1995-07-18 01:32 Ulrich Drepper <drepper@myware>
+
+ * Makefile.in (DISTFILES): Add magic.add. Comes from ../.
+
+ * po-mode.el, makelinks, combine-sh: Moved to here from ../intl/.
+ magic.add: Moved to here from ../.
+
+ * Makefile.in: Initial revision
diff --git a/misc/Makefile.am b/misc/Makefile.am
new file mode 100644
index 0000000..aaf822d
--- /dev/null
+++ b/misc/Makefile.am
@@ -0,0 +1,31 @@
+## Makefile for the misc subdirectory of the GNU NLS Utilities
+## Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+##
+## 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, 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.
+
+## Process this file with automake to produce Makefile.in.
+
+AUTOMAKE_OPTIONS = 1.2 gnits
+
+localedir = $(datadir)/locale
+
+EXTRA_DIST = combine-sh gettext.perl gettext-sh magic.add tcl_gettext.c \
+README-Tcl po-mode.el locale.alias
+DISTCLEANFILES = gettextize
+lisp_LISP = po-mode.el
+
+bin_SCRIPTS = gettextize
+
+locale_DATA = locale.alias
diff --git a/misc/Makefile.in b/misc/Makefile.in
new file mode 100644
index 0000000..a2ec62d
--- /dev/null
+++ b/misc/Makefile.in
@@ -0,0 +1,307 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+ACLOCAL_VERSION = @ACLOCAL_VERSION@
+AS = @AS@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+DATADIRNAME = @DATADIRNAME@
+DLLTOOL = @DLLTOOL@
+EMACS = @EMACS@
+GENCAT = @GENCAT@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GT_NO = @GT_NO@
+GT_YES = @GT_YES@
+INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@
+INSTOBJEXT = @INSTOBJEXT@
+INTLDEPS = @INTLDEPS@
+INTLLIBS = @INTLLIBS@
+INTLOBJS = @INTLOBJS@
+LIBOBJS = @LIBOBJS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+MAKEINFO = @MAKEINFO@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+OBJDUMP = @OBJDUMP@
+PACKAGE = @PACKAGE@
+POFILES = @POFILES@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+YACC = @YACC@
+aclocaldir = @aclocaldir@
+l = @l@
+lispdir = @lispdir@
+
+AUTOMAKE_OPTIONS = 1.2 gnits
+
+localedir = $(datadir)/locale
+
+EXTRA_DIST = combine-sh gettext.perl gettext-sh magic.add tcl_gettext.c README-Tcl po-mode.el locale.alias
+
+DISTCLEANFILES = gettextize
+lisp_LISP = po-mode.el
+
+bin_SCRIPTS = gettextize
+
+locale_DATA = locale.alias
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES = gettextize
+SCRIPTS = $(bin_SCRIPTS)
+
+LISP = $(lisp_LISP)
+
+ELCFILES = po-mode.elc
+DATA = $(locale_DATA)
+
+DIST_COMMON = ChangeLog Makefile.am Makefile.in elisp-comp \
+gettextize.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP_ENV = --best
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .el .elc
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnits misc/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+gettextize: $(top_builddir)/config.status gettextize.in
+ cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+install-binSCRIPTS: $(bin_SCRIPTS)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+ @list='$(bin_SCRIPTS)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " $(INSTALL_SCRIPT) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
+ $(INSTALL_SCRIPT) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+ else if test -f $(srcdir)/$$p; then \
+ echo " $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
+ $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+ else :; fi; fi; \
+ done
+
+uninstall-binSCRIPTS:
+ @$(NORMAL_UNINSTALL)
+ list='$(bin_SCRIPTS)'; for p in $$list; do \
+ rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+ done
+
+install-lispLISP: $(lisp_LISP) $(ELCFILES)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(lispdir)
+ @list='$(lisp_LISP)'; for p in $$list; do \
+ if test -f "$$p"; then d= ; else d="$(srcdir)/"; fi; \
+ echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(lispdir)/$$p"; \
+ $(INSTALL_DATA) $$d$$p $(DESTDIR)$(lispdir)/$$p; \
+ if test -f $${p}c; then \
+ echo " $(INSTALL_DATA) $${p}c $(DESTDIR)$(lispdir)/$${p}c"; \
+ $(INSTALL_DATA) $${p}c $(DESTDIR)$(lispdir)/$${p}c; \
+ else : ; fi; \
+ done
+
+uninstall-lispLISP:
+ @$(NORMAL_UNINSTALL)
+ list='$(lisp_LISP)'; for p in $$list; do \
+ rm -f $(lispdir)/$$p $(DESTDIR)$(lispdir)/$${p}c; \
+ done
+.el.elc:
+ @echo 'WARNING: Warnings can be ignored. :-)'
+ if test $(EMACS) != no; then \
+ EMACS=$(EMACS) $(SHELL) $(srcdir)/elisp-comp $<; \
+ fi
+
+mostlyclean-lisp:
+
+clean-lisp:
+ -test -z "$(ELCFILES)" || rm -f $(ELCFILES)
+
+distclean-lisp:
+
+maintainer-clean-lisp:
+
+install-localeDATA: $(locale_DATA)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(localedir)
+ @list='$(locale_DATA)'; for p in $$list; do \
+ if test -f $(srcdir)/$$p; then \
+ echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(localedir)/$$p"; \
+ $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(localedir)/$$p; \
+ else if test -f $$p; then \
+ echo " $(INSTALL_DATA) $$p $(DESTDIR)$(localedir)/$$p"; \
+ $(INSTALL_DATA) $$p $(DESTDIR)$(localedir)/$$p; \
+ fi; fi; \
+ done
+
+uninstall-localeDATA:
+ @$(NORMAL_UNINSTALL)
+ list='$(locale_DATA)'; for p in $$list; do \
+ rm -f $(DESTDIR)$(localedir)/$$p; \
+ done
+tags: TAGS
+TAGS:
+
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = misc
+
+distdir: $(DISTFILES)
+ here=`cd $(top_builddir) && pwd`; \
+ top_distdir=`cd $(top_distdir) && pwd`; \
+ distdir=`cd $(distdir) && pwd`; \
+ cd $(top_srcdir) \
+ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnits misc/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+ cp -pr $$/$$file $(distdir)/$$file; \
+ else \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am: install-binSCRIPTS
+install-exec: install-exec-am
+
+install-data-am: install-lispLISP install-localeDATA
+install-data: install-data-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-binSCRIPTS uninstall-lispLISP \
+ uninstall-localeDATA
+uninstall: uninstall-am
+all-am: Makefile $(SCRIPTS) $(LISP) $(ELCFILES) $(DATA)
+all-redirect: all-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(lispdir) \
+ $(DESTDIR)$(localedir)
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+mostlyclean-am: mostlyclean-lisp mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am: clean-lisp clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am: distclean-lisp distclean-generic clean-am
+ -rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am: maintainer-clean-lisp maintainer-clean-generic \
+ distclean-am
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: uninstall-binSCRIPTS install-binSCRIPTS uninstall-lispLISP \
+install-lispLISP mostlyclean-lisp distclean-lisp clean-lisp \
+maintainer-clean-lisp uninstall-localeDATA install-localeDATA tags \
+distdir info-am info dvi-am dvi check check-am installcheck-am \
+installcheck install-exec-am install-exec install-data-am install-data \
+install-am install uninstall-am uninstall all-redirect all-am all \
+installdirs mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/misc/README-Tcl b/misc/README-Tcl
new file mode 100644
index 0000000..7b9f6f9
--- /dev/null
+++ b/misc/README-Tcl
@@ -0,0 +1,52 @@
+ Gettext support for Tcl
+ =======================
+
+The file `tcl_gettext.c' contains the first attempt to provide an
+interface for Tcl. I know that TclX already supports `catgets', but
+because GNU uses `gettext' and because I think `gettext' is the better
+concept I wrote this file.
+
+
+Unlike many other interpreter extension I haven't provided a
+`tclAppInit.c' file. I have three reason: it's easy to write (see
+Ousterhout's book), It will probably combined with other extensions
+and so would be more or less useless. But the most important reason
+is that I don't find Tcl useful without the dynamic loading introduced
+in version 7.5.
+
+The way I think you should use this module is to build a dynamic
+object and load it at runtime with the command `load'. The following
+transcript shows the way I work on my Linux/ELF box. Consult other
+Tcl modules or a local wizard to see how it works for your system.
+
+
+1. Compile the file to position independent object code:
+
+ gcc -fPIC -O3 -c tcl_gettext.c
+
+ (The file `tcl.h' from tcl7.5 or up and `libintl.h' as installed
+ from GNU gettext must be found in the path.)
+
+2. Link the file to a shared object:
+
+ gcc -shared -o gettext.so tcl_gettext.o -lintl
+
+ (The system's or GNU gettext libintl.a must be found in the path
+ of the linker.)
+
+3. Now we are ready to run:
+
+bash> tclsh7.5
+% load ./gettext.so Gettext
+% textdomain "xxx"
+% gettext "some string"
+The translated form
+% exit
+bash>
+
+
+If you have some ideas how to improve this or you found a bug, please
+let me know.
+
+Ulrich Drepper <drepper@gnu.ai.mit.edu>, 18. December 1995.
+
diff --git a/misc/combine-sh b/misc/combine-sh
new file mode 100755
index 0000000..b26fb4f
--- /dev/null
+++ b/misc/combine-sh
@@ -0,0 +1,141 @@
+#!/bin/sh
+
+TMPDIR=/tmp
+TMPNAME=/tmp/combine1.$$.sed
+
+trap 'rm -fr $TMPNAME combine; exit 1' 1 2 15
+
+rm -f $TMPNAME
+cat > $TMPNAME <<EOF
+/@@ end of prolog @@/,/@@ begin of epilog @@/!d
+/@@ end of prolog @@/ {
+ =
+ d
+}
+/@@ begin of epilog @@/d
+EOF
+
+
+rm -fr combine
+mkdir combine
+cat > combine/libintl.c <<EOF
+/* Combined sources of GNU gettext library
+ Copyright (C) 1995 Software Foundation, Inc.
+
+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, 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. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define USE_COMBINED_HEADER 1
+#include "libintlP.h"
+
+#if HAVE_CATGETS
+
+#include <stdlib.h>
+
+#ifdef HAVE_LOCALE_H
+# include <locale.h>
+#endif
+
+#ifdef HAVE_NL_TYPES_H
+# include <nl_types.h>
+#endif
+
+EOF
+
+CATCFILES=cat-compat.c
+GETCFILES="bindtextdom.c dcgettext.c dgettext.c finddomain.c gettext.c \
+loadmsgcat.c textdomain.c"
+
+for file in $CATCFILES; do
+ sed -f $TMPNAME < $file \
+ | sed -e '1s/.*/#line & "'$file'"/' >> combine/libintl.c
+done
+cat >> combine/libintl.c <<EOF
+
+#else /* !HAVE_CATGETS */
+
+#include <alloca.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_LOCALE_H
+# include <locale.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_MMAP
+# include <sys/mman.h>
+#endif
+
+EOF
+for file in $GETCFILES; do
+ sed -f $TMPNAME < $file \
+ | sed -e '1s/.*/#line & "'$file'"/' >> combine/libintl.c
+done
+cat >> combine/libintl.c <<EOF
+#endif /* HAVE_CATGETS */
+EOF
+
+cat > combine/libintlP.h <<EOF
+/* Combined header files of GNU gettext library
+ Copyright (C) 1995 Software Foundation, Inc.
+
+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, 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. */
+
+EOF
+
+PUBHEAD=libgettext.h
+PRIVHEAD="gettext.h gettextP.h hash-string.h"
+
+for file in $PUBHEAD; do
+ sed -f $TMPNAME < $file \
+ | sed -e '1s/.*/#line & "'$file'"/' >> combine/libintlP.h
+done
+cat >> combine/libintlP.h <<EOF
+
+#ifdef USE_COMBINED_HEADER
+EOF
+for file in $PRIVHEAD; do
+ sed -f $TMPNAME < $file \
+ | sed -e '1s/.*/#line & "'$file'"/' >> combine/libintlP.h
+done
+cat >> combine/libintlP.h <<EOF
+#endif /* USE_COMBINED_HEADER */
+EOF
+
+
+rm -f $TMPNAME
+exit 0
diff --git a/misc/elisp-comp b/misc/elisp-comp
new file mode 100755
index 0000000..ddd15f6
--- /dev/null
+++ b/misc/elisp-comp
@@ -0,0 +1,42 @@
+#!/bin/sh
+# Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+# François Pinard <pinard@iro.umontreal.ca>, 1995.
+#
+# 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, 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.
+
+# This script byte-compiles all `.el' files which are part of its
+# arguments, using GNU Emacs, and put the resulting `.elc' files into
+# the current directory, so disregarding the original directories used
+# in `.el' arguments.
+#
+# This script manages in such a way that all Emacs LISP files to
+# be compiled are made visible between themselves, in the event
+# they require or load-library one another.
+
+if test $# = 0; then
+ echo 1>&2 "No files given to $0"
+else
+ tempdir=elc.$$
+ mkdir $tempdir
+ cp $* $tempdir
+ cd $tempdir
+
+ echo "(setq load-path (cons nil load-path))" > script
+ ${EMACS-emacs} -batch -l script -f batch-byte-compile *.el
+ mv *.elc ..
+
+ cd ..
+ rm -fr $tempdir
+fi
diff --git a/misc/gettext-sh b/misc/gettext-sh
new file mode 100644
index 0000000..ee15bab
--- /dev/null
+++ b/misc/gettext-sh
@@ -0,0 +1,63 @@
+# Copyright (C) 1995 Free Software Foundation, Inc.
+# Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, August 1995
+#
+# 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, 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.
+#
+# Shell script excerpt to be inserted in shell scripts which are intended
+# to be internationalized using GNU gettext.
+#
+# Precondition:
+# ${PACKAGE-IDENT} is the name of one program of the package which
+# understands the --print-text-domain-dir option
+# ${PACKAGE-NAME} is the name of the message domain the package uses
+# ${PATH} should list all directories which should be searched
+# for either `gettext' or ${PACKAGE-IDENT}.
+#
+# Postcondition:
+# ${echo} command to use like Un*x echo command which translates
+# its arguments when a translation is available.
+#
+save_IFS="${IFS}"
+IFS="${IFS}:"
+gettext_dir=FAILED
+locale_dir=FAILED
+for dir in ${PATH}
+do
+ if test "${gettext_dir}" = "FAILED" && test -x ${dir}/gettext \
+ && (${dir}/gettext --version >/dev/null 2>&1)
+ then
+ set `${dir}/gettext --version 2>&1`
+ if test "$3" = "GNU"
+ then
+ gettext_dir=${dir}
+ fi
+ fi
+ if test "${locale_dir}" = "FAILED" && test -x ${dir}/${PACKAGE-IDENT} \
+ && (${dir}/${PACKAGE-IDENT} --print-text-domain-dir >/dev/null 2>&1)
+ then
+ locale_dir=`${dir}/${PACKAGE-IDENT} --print-text-domain-dir`
+ fi
+done
+IFS="${save_IFS}"
+if test "${locale_dir}" = "FAILED" || test "${gettext_dir}" = "FAILED"
+then
+ echo=echo
+else
+ TEXTDOMAINDIR=${locale_dir}
+ export TEXTDOMAINDIR
+ TEXTDOMAIN=${PACKAGE-NAME}
+ export TEXTDOMAIN
+ echo="${gettext_dir}/gettext -s"
+fi
diff --git a/misc/gettext.perl b/misc/gettext.perl
new file mode 100644
index 0000000..7bd1ee8
--- /dev/null
+++ b/misc/gettext.perl
@@ -0,0 +1,86 @@
+# Toying at an interface between Perl and GNU gettext .mo format.
+# Copyright (C) 1995 Free Software Foundation, Inc.
+# François Pinard <pinard@iro.umontreal.ca>, 1995.
+
+textdomain ("tar");
+print &_("Try \`%s --help\' for more information.\n");
+exit 0;
+
+## --------------------------------------------------------------- ##
+## The `&textdomain (DOMAIN_NAME)' routine reads the given domain ##
+## into an associative array %_, able to later translate strings. ##
+## --------------------------------------------------------------- ##
+
+sub textdomain
+{
+ local ($language, $catalog, $domain, $buffer);
+ local ($reverse);
+ local ($magic, $revision, $nstrings, $orig_tab_offset, $trans_tab_offset);
+ local ($orig_length, $orig_pointer, $trans_length, $trans_pointer);
+
+ %_ = ();
+
+ $language = $ENV{"LANG"};
+ return if ! $language;
+ $domain = $_[0];
+ $catalog = "/usr/local/share/locale/$language/LC_MESSAGES/$domain.mo";
+
+ open (CATALOG, $catalog) || return;
+ sysread (CATALOG, $buffer, (stat CATALOG)[7]);
+ close CATALOG;
+
+ $magic = unpack ("I", $buffer);
+ if (sprintf ("%x", $magic) eq "de120495")
+ {
+ $reverse = 1;
+ }
+ elsif (sprintf ("%x", $magic) ne "950412de")
+ {
+ die "Not a catalog file\n";
+ }
+
+ $revision = &mo_format_value (4);
+ $nstrings = &mo_format_value (8);
+ $orig_tab_offset = &mo_format_value (12);
+ $trans_tab_offset = &mo_format_value (16);
+
+ while ($nstrings-- > 0)
+ {
+ $orig_length = &mo_format_value ($orig_tab_offset);
+ $orig_pointer = &mo_format_value ($orig_tab_offset + 4);
+ $orig_tab_offset += 8;
+
+ $trans_length = &mo_format_value ($trans_tab_offset);
+ $trans_pointer = &mo_format_value ($trans_tab_offset + 4);
+ $trans_tab_offset += 8;
+
+ $_{substr ($buffer, $orig_pointer, $orig_length)}
+ = substr ($buffer, $trans_pointer, $trans_length);
+ }
+}
+
+## ----------------------------------------------------------------- ##
+## The `&mo_format_value (ADDRESS)' routine returns the value at a ##
+## given address in the .mo format catalog, once read into $buffer ##
+## by `&textdomain'. This is a service routine of `&textdomain', ##
+## which uses $buffer and $reverse variables local in that routine. ##
+## ----------------------------------------------------------------- ##
+
+sub mo_format_value
+{
+ unpack ("i",
+ $reverse
+ ? pack ("c4", reverse unpack ("c4", substr ($buffer, $_[0], 4)))
+ : substr ($buffer, $_[0], 4));
+}
+
+## ------------------------------------------------------------ ##
+## The `&_(STRING)' routine translates STRING if there is some ##
+## translation offered for it in the `%_' associative array, or ##
+## return STRING itself, otherwize. ##
+## ------------------------------------------------------------ ##
+
+sub _
+{
+ defined $_{$_[0]} ? $_{$_[0]} : $_[0];
+}
diff --git a/misc/gettextize.in b/misc/gettextize.in
new file mode 100644
index 0000000..75e3c2e
--- /dev/null
+++ b/misc/gettextize.in
@@ -0,0 +1,177 @@
+#! /bin/sh
+#
+# Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+#
+# 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, 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.
+#
+
+# This file is meant for authors or maintainers which want to
+# internationalize their package with the help of GNU gettext. For
+# further information how to use it consult the GNU gettext manual.
+
+echo=echo
+progname=$0
+force=0
+configstatus=0
+origdir=`pwd`
+usage="\
+Usage: gettextize [OPTION]... [package-dir]
+ --help print this help and exit
+ --version print version information and exit
+ -c, --copy copy files instead of making symlinks
+ -f, --force force writing of new files even if old exist
+Report bugs to <bug-gnu-utils@prep.ai.mit.edu>."
+package=@PACKAGE@
+version=@VERSION@
+aclocal_version=@ACLOCAL_VERSION@
+try_ln_s=:
+
+while test $# -gt 0; do
+ case "$1" in
+ -c | --copy | --c* )
+ shift
+ try_ln_s=false ;;
+ -f | --force | --f* )
+ shift
+ force=1 ;;
+ -r | --run | --r* )
+ shift
+ configstatus=1 ;;
+ --help | --h* )
+ $echo "$usage"; exit 0 ;;
+ --version | --v* )
+ echo "$progname (GNU $package) $version"
+ $echo "Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+ $echo "Written by" "Ulrich Drepper"
+ exit 0 ;;
+ -- ) # Stop option prcessing
+ shift; break ;;
+ -* )
+ $echo "gettextize: unknown option $1"
+ $echo "Try \`gettextize --help' for more information."; exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# -gt 1; then
+ $echo "$usage"
+ exit 1
+fi
+
+# Fill in the command line options value.
+if test $# -eq 1; then
+ srcdir=$1
+ if cd $srcdir; then
+ srcdir=`pwd`
+ else
+ $echo "Cannot change directory to \`$srcdir'"
+ exit 1
+ fi
+else
+ srcdir=$origdir
+fi
+
+# Directory where the sources are stored.
+prefix=@prefix@
+gettext_dir=@datadir@/gettext
+
+test -f configure.in || {
+ $echo "Missing configure.in, please cd to your package first."
+ exit 1
+}
+
+if test -d intl && test $force -eq 0; then
+ $echo "\
+intl/ subdirectory exists: use option -f if you really want to delete it."
+ exit 1
+fi
+
+if test -f po/Makefile.in.in && test $force -eq 0; then
+ $echo "\
+po/Makefile.in.in exists: use option -f if you really want to delete it."
+ exit 1
+fi
+
+if test -f NLS && test $force -eq 0; then
+ $echo "NLS exists: use option -f if you really want to delete it."
+ exit 1
+fi
+
+rm -fr intl
+mkdir intl || {
+ $echo "failed to create intl/ subdirectory"
+ exit 1;
+}
+
+test -d po || mkdir po || {
+ $echo "failed to create po/ subdirectory"
+ exit 1
+}
+
+# For simplicity we changed to the gettext source directory.
+cd $gettext_dir
+
+# Now copy all files. Take care for the destination directories.
+for file in *; do
+ case $file in
+ intl | po | demo)
+ ;;
+ *)
+ rm -f $srcdir/$file
+ ($try_ln_s && ln -s $gettext_dir/$file $srcdir/$file) 2>/dev/null ||
+ cp $file $srcdir/$file
+ ;;
+ esac
+done
+
+# Copy files to intl/ subdirectory.
+cd intl
+for file in *; do
+ rm -f $srcdir/intl/$file
+ ($try_ln_s && ln -s $gettext_dir/intl/$file $srcdir/intl/$file) 2>/dev/null ||
+ cp $file $srcdir/intl/$file
+done
+
+# Copy files to po/ subdirectory.
+cd ../po
+for file in *; do
+ rm -f $srcdir/po/$file
+ ($try_ln_s && ln -s $gettext_dir/po/$file $srcdir/po/$file) 2>/dev/null ||
+ cp $file $srcdir/po/$file
+done
+
+
+# Check whether we can run config.status to produce intl/Makefile.in.
+cd $origdir
+if test -f ./config.status; then
+ if test $configstatus -eq 0; then
+ echo "Shall I run config.status? (y/N)"
+ read ans
+ case "$ans" in
+ y* | Y* | 1* )
+ configstatus=1 ;;
+ * )
+ ;;
+ esac
+ fi
+
+ test $configstatus -ne 0 &&
+ (CONFIG_FILES=intl/Makefile CONFIG_HEADERS= ./config.status)
+fi
+
+exit 0
diff --git a/misc/locale.alias b/misc/locale.alias
new file mode 100644
index 0000000..c3666fc
--- /dev/null
+++ b/misc/locale.alias
@@ -0,0 +1,52 @@
+# Locale name alias data base
+# Copyright (C) 1995 Free Software Foundation, Inc.
+#
+# 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, 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.
+
+# The format of this file is the same as for the corresponding file of
+# the X Window System, which normally can be found in
+# /usr/lib/X11/locale/locale.alias
+# A single line contains two fields: an alias and a substitution value.
+# All entries are case independent.
+
+# Note: This file is far from being complete. If you have a value for
+# your own site which you think might be useful for others too, share it
+# with the rest of us. Send it to bug-gnu-utils@prep.ai.mit.edu.
+
+czech cs_CZ.ISO-8859-2
+danish da_DK.ISO-8859-1
+dansk da_DK.ISO-8859-1
+deutsch de_DE.ISO-8859-1
+dutch nl_NL.ISO-8859-1
+finnish fi_FI.ISO-8859-1
+français fr_FR.ISO-8859-1
+french fr_FR.ISO-8859-1
+german de_DE.ISO-8859-1
+greek el_GR.ISO-8859-7
+hebrew iw_IL.ISO-8859-8
+hungarian hu_HU.ISO-8859-2
+icelandic is_IS.ISO-8859-1
+italian it_CH.ISO-8859-1
+japanese ja_JP.EUC
+norwegian no_NO.ISO-8859-1
+polish pl_PL.ISO-8859-2
+portuguese pt_PT.ISO-8859-1
+rumanian ro_RO.ISO-8859-2
+russian ru_SU.ISO-8859-5
+slovak sk_SK.ISO-8859-2
+slovene sl_CS.ISO-8859-2
+spanish es_ES.ISO-8859-1
+swedish sv_SE.ISO-8859-1
+turkish tr_TR.ISO-8859-9
diff --git a/misc/magic.add b/misc/magic.add
new file mode 100644
index 0000000..85af567
--- /dev/null
+++ b/misc/magic.add
@@ -0,0 +1,9 @@
+#
+# GNU nlsutils message catalog file format
+#
+0 string \336\22\4\225 GNU message catalog (little endian),
+>4 lelong x revision %d,
+>8 lelong x %d messages
+0 string \225\4\22\336 GNU message catalog (big endian),
+>4 belong x revision %d,
+>8 belong x %d messages
diff --git a/misc/po-mode.el b/misc/po-mode.el
new file mode 100644
index 0000000..bdab3c0
--- /dev/null
+++ b/misc/po-mode.el
@@ -0,0 +1,2602 @@
+;;; po-mode.el -- for helping GNU gettext lovers to edit PO files.
+;;; Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
+;;; François Pinard <pinard@iro.umontreal.ca>, 1995.
+;;; Helped by Greg McGary <gkm@magilla.cichlid.com>.
+
+;; This file is part of GNU gettext.
+
+;; GNU gettext 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.
+
+;; GNU gettext 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, 59 Temple Place - Suite 330, Boston,
+;; MA 02111-1307, USA.
+
+;;; This package provides the tools meant to help editing PO files,
+;;; as documented in the GNU gettext user's manual. See this manual
+;;; for user documentation, which is not repeated here.
+
+;;; To install, merely put this file somewhere GNU Emacs will find it,
+;;; then add the following lines to your .emacs file:
+;;;
+;;; (autoload 'po-mode "po-mode")
+;;; (setq auto-mode-alist (cons '("\\.po[tx]?\\'\\|\\.po\\." . po-mode)
+;;; auto-mode-alist))
+;;;
+;;; To automatically use proper fonts under Emacs 20, also add:
+;;;
+;;; (autoload 'po-find-file-coding-system "po-mode")
+;;; (modify-coding-system-alist 'file "\\.po[tx]?\\'\\|\\.po\\."
+;;; 'po-find-file-coding-system)
+;;;
+;;; You may also adjust some variables, below, by defining them in your
+;;; `.emacs' file, either directly or through command `M-x customize'.
+
+;;; Emacs portability matters.
+
+;;; Most portability matters are addressed in this page. All other cases
+;;; involve one of `eval-and-compile' or `fboundp', just search for these.
+
+;; Identify which Emacs variety is being used.
+(eval-and-compile
+ (cond ((string-match "Lucid\\|XEmacs" emacs-version)
+ (setq po-EMACS20 nil po-XEMACS t))
+ ((and (string-lessp "19" emacs-version) (featurep 'faces))
+ (setq po-EMACS20 t po-XEMACS nil))
+ (t (setq po-EMACS20 nil po-XEMACS nil))))
+
+;; Experiment with Emacs LISP message internationalisation.
+(eval-and-compile
+ (or (fboundp 'set-translation-domain)
+ (defsubst set-translation-domain (string) nil))
+ (or (fboundp 'translate-string)
+ (defsubst translate-string (string) string)))
+(defsubst _ (string) (translate-string string))
+(defsubst N_ (string) string)
+
+;; Handle missing `customs' package.
+(eval-and-compile
+ (condition-case ()
+ (require 'custom)
+ (error nil))
+ (if (and (featurep 'custom) (fboundp 'custom-declare-variable))
+ nil
+ (defmacro defgroup (&rest args)
+ nil)
+ (defmacro defcustom (var value doc &rest args)
+ (` (defvar (, var) (, value) (, doc))))))
+
+;; Protect string comparisons from text properties.
+(eval-and-compile
+ (fset 'po-buffer-substring
+ (symbol-function (if (fboundp 'buffer-substring-no-properties)
+ 'buffer-substring-no-properties
+ 'buffer-substring))))
+
+;; Handle missing `with-temp-buffer' function.
+(eval-and-compile
+ (if nil ; FIXME: just testing... (fboundp 'with-temp-buffer)
+
+ (fset 'po-with-temp-buffer (symbol-function 'with-temp-buffer))
+
+ (defmacro po-with-temp-buffer (&rest forms)
+ "Create a temporary buffer, and evaluate FORMS there like `progn'."
+ (let ((curr-buffer (make-symbol "curr-buffer"))
+ (temp-buffer (make-symbol "temp-buffer")))
+ `(let ((,curr-buffer (current-buffer))
+ (,temp-buffer (get-buffer-create
+ (generate-new-buffer-name " *po-temp*"))))
+ (unwind-protect
+ (progn
+ (set-buffer ,temp-buffer)
+ ,@forms)
+ (set-buffer ,curr-buffer)
+ (and (buffer-name ,temp-buffer)
+ (kill-buffer ,temp-buffer))))))))
+
+;; Handle missing `kill-new' function.
+(eval-and-compile
+ (if (fboundp 'kill-new)
+
+ (fset 'po-kill-new (symbol-function 'kill-new))
+
+ (defun po-kill-new (string)
+ "Push STRING onto the kill ring, for Emacs 18 where kill-new is missing."
+ (po-with-temp-buffer
+ (insert string)
+ (kill-region (point-min) (point-max))))))
+
+;; Handle missing `read-event' function.
+(eval-and-compile
+ (fset 'po-read-event
+ (cond ((fboundp 'read-event)
+ ;; GNU Emacs.
+ 'read-event)
+ ((fboundp 'next-command-event)
+ ;; XEmacs.
+ 'next-command-event)
+ (t
+ ;; Older Emacses.
+ 'read-char))))
+
+;; Handle missing `force-mode-line-update' function.
+(eval-and-compile
+ (if (fboundp 'force-mode-line-update)
+
+ (fset 'po-force-mode-line-update
+ (symbol-function 'force-mode-line-update))
+
+ (defun po-force-mode-line-update ()
+ "Force the mode-line of the current buffer to be redisplayed."
+ (set-buffer-modified-p (buffer-modified-p)))))
+
+;; Handle portable highlighting. Code has been adapted (OK... stolen! :-)
+;; from `ispell.el'.
+(eval-and-compile
+ (cond
+ (po-EMACS20
+
+ (defun po-create-overlay ()
+ "Create and return a deleted overlay structure.
+The variable `po-highlight-face' selects the face to use for highlighting."
+ (let ((overlay (make-overlay (point) (point))))
+ (overlay-put overlay 'face po-highlight-face)
+ ;; The fun thing is that a deleted overlay retains its face, and is
+ ;; movable.
+ (delete-overlay overlay)
+ overlay))
+
+ (defun po-highlight (overlay start end &optional buffer)
+ "Use OVERLAY to highlight the string from START to END.
+If limits are not relative to the current buffer, use optional BUFFER."
+ (move-overlay overlay start end (or buffer (current-buffer))))
+
+ (defun po-rehighlight (overlay)
+ "Ensure OVERLAY is highlighted."
+ ;; There is nothing to do, as GNU Emacs allows multiple highlights.
+ nil)
+
+ (defun po-dehighlight (overlay)
+ "Display normally the last string which OVERLAY highlighted.
+The current buffer should be in PO mode, when this function is called."
+ (delete-overlay overlay)))
+
+ (po-XEMACS
+
+ (defun po-create-overlay ()
+ "Create and return a deleted overlay structure."
+ (cons (make-marker) (make-marker)))
+
+ (defun po-highlight (overlay start end &optional buffer)
+ "Use OVERLAY to highlight the string from START to END.
+If limits are not relative to the current buffer, use optional BUFFER."
+ (if buffer
+ (save-excursion
+ (set-buffer buffer)
+ (isearch-highlight start end))
+ (isearch-highlight start end))
+ (set-marker (car overlay) start (or buffer (current-buffer)))
+ (set-marker (cdr overlay) end (or buffer (current-buffer))))
+
+ (defun po-rehighlight (overlay)
+ "Ensure OVERLAY is highlighted."
+ (let ((buffer (marker-buffer (car overlay)))
+ (start (marker-position (car overlay)))
+ (end (marker-position (cdr overlay))))
+ (and buffer
+ (name-buffer buffer)
+ (po-highlight overlay start end buffer))))
+
+ (defun po-dehighlight (overlay)
+ "Display normally the last string which OVERLAY highlighted."
+ (isearch-dehighlight t)
+ (setcar overlay (make-marker))
+ (setcdr overlay (make-marker))))
+
+ (t
+
+ (defun po-create-overlay ()
+ "Create and return a deleted overlay structure."
+ (cons (make-marker) (make-marker)))
+
+ (defun po-highlight (overlay start end &optional buffer)
+ "Use OVERLAY to highlight the string from START to END.
+If limits are not relative to the current buffer, use optional BUFFER.
+No doubt that highlighting, when Emacs does not allow it, is a kludge."
+ (save-excursion
+ (and buffer (set-buffer buffer))
+ (let ((modified (buffer-modified-p))
+ (buffer-read-only nil)
+ (inhibit-quit t)
+ (buffer-undo-list t)
+ (text (buffer-substring start end)))
+ (goto-char start)
+ (delete-region start end)
+ (insert-char ? (- end start))
+ (sit-for 0)
+ (setq inverse-video (not inverse-video))
+ (delete-region start end)
+ (insert text)
+ (sit-for 0)
+ (setq inverse-video (not inverse-video))
+ (set-buffer-modified-p modified)))
+ (set-marker (car overlay) start (or buffer (current-buffer)))
+ (set-marker (cdr overlay) end (or buffer (current-buffer))))
+
+ (defun po-rehighlight (overlay)
+ "Ensure OVERLAY is highlighted."
+ (let ((buffer (marker-buffer (car overlay)))
+ (start (marker-position (car overlay)))
+ (end (marker-position (cdr overlay))))
+ (and buffer
+ (name-buffer buffer)
+ (po-highlight overlay start end buffer))))
+
+ (defun po-dehighlight (overlay)
+ "Display normally the last string which OVERLAY highlighted."
+ (let ((buffer (marker-buffer (car overlay)))
+ (start (marker-position (car overlay)))
+ (end (marker-position (cdr overlay))))
+ (if buffer
+ (save-excursion
+ (set-buffer buffer)
+ (let ((modified (buffer-modified-p))
+ (buffer-read-only nil)
+ (inhibit-quit t)
+ (buffer-undo-list t))
+ (let ((text (buffer-substring start end)))
+ (goto-char start)
+ (delete-region start end)
+ (insert-char ? (- end start))
+ (sit-for 0)
+ (delete-region start end)
+ (insert text)
+ (sit-for 0)
+ (set-buffer-modified-p modified)))))
+ (setcar overlay (make-marker))
+ (setcdr overlay (make-marker))))
+
+ )))
+
+;;; Customisation.
+
+(defgroup po nil
+ "Major mode for editing PO files"
+ :group 'i18n)
+
+(defcustom po-auto-edit-with-msgid nil
+ "*Automatically use msgid when editing untranslated entries."
+ :type 'boolean
+ :group 'po)
+
+(defcustom po-auto-fuzzy-on-edit nil
+ "*Automatically mark entries fuzzy when being edited."
+ :type 'boolean
+ :group 'po)
+
+(defcustom po-auto-select-on-unfuzzy nil
+ "*Automatically select some new entry while making an entry not fuzzy."
+ :type 'boolean
+ :group 'po)
+
+(defcustom po-auto-replace-revision-date 'ask
+ "*Automatically revise date in headers. Value is nil, t, or ask."
+ :type '(choice (const nil)
+ (const t)
+ (const ask))
+ :group 'po)
+
+(defcustom po-default-file-header "\
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid \"\"
+msgstr \"\"
+\"Project-Id-Version: PACKAGE VERSION\\n\"
+\"PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\\n\"
+\"Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n\"
+\"Language-Team: LANGUAGE <LL@li.org>\\n\"
+\"MIME-Version: 1.0\\n\"
+\"Content-Type: text/plain; charset=CHARSET\\n\"
+\"Content-Transfer-Encoding: ENCODING\\n\"
+"
+ "*Default PO file header."
+ :type 'string
+ :group 'po)
+
+(defcustom po-highlighting (or po-EMACS20 po-XEMACS)
+ "*Highlight text whenever appropriate, when non-nil. However, on older
+Emacses, a yet unexplained highlighting bug causes files to get mangled."
+ :type 'boolean
+ :group 'po)
+
+(defcustom po-highlight-face 'highlight
+ "*The face used for PO mode highlighting. For Emacses with overlays.
+Possible values are `highlight', `modeline', `secondary-selection',
+`region', and `underline'.
+This variable can be set by the user to whatever face they desire.
+It's most convenient if the cursor color and highlight color are
+slightly different."
+ :type 'face
+ :group 'po)
+
+(defcustom po-gzip-uuencode-command "gzip -9 | uuencode -m"
+ "*The filter to use for preparing a mail invoice of the PO file.
+Normally \"gzip -9 | uuencode -m\", remove the -9 for lesser compression,
+or remove the -m if you are not using the GNU version of `uuencode'."
+ :type 'string
+ :group 'po)
+
+;;; The following block of declarations has the main purpose of avoiding
+;;; byte compiler warnings. It also introduces some documentation for
+;;; each of these variables, all meant to be local to PO mode buffers.
+
+;; Flag telling that MODE-LINE-STRING should be displayed. See `Window'
+;; page below. Exceptionally, this variable is local to *all* buffers.
+
+(defvar po-mode-flag)
+
+;; PO buffers are kept read-only to prevent random modifications. READ-ONLY
+;; holds the value of the read-only flag before PO mode was entered.
+
+(defvar po-read-only)
+
+;; The current entry extends from START-OF-ENTRY to END-OF-ENTRY, it
+;; includes preceding whitespace and excludes following whitespace. The
+;; start of keyword lines are START-OF-MSGID and START-OF-MSGSTR.
+;; ENTRY-TYPE classifies the entry.
+
+(defvar po-start-of-entry)
+(defvar po-start-of-msgid)
+(defvar po-start-of-msgstr)
+(defvar po-end-of-entry)
+(defvar po-entry-type)
+
+;; A few counters are usefully shown in the Emacs mode line.
+
+(defvar po-translated-counter)
+(defvar po-fuzzy-counter)
+(defvar po-untranslated-counter)
+(defvar po-obsolete-counter)
+(defvar po-mode-line-string)
+
+;; PO mode keeps track of fields being edited, for one given field should
+;; have one editing buffer at most, and for exiting a PO buffer properly
+;; should offer to close all pending edits. Variable EDITED-FIELDS holds an
+;; an list of "slots" of the form: (ENTRY-MARKER EDIT-BUFFER OVERLAY-INFO).
+;; To allow simultaneous edition of the comment and the msgstr of an entry,
+;; ENTRY-MARKER points to the msgid line if a comment is being edited, or to
+;; the msgstr line if the msgstr is being edited. EDIT-BUFFER is the
+;; temporary Emacs buffer used to edit the string. OVERLAY-INFO, when not
+;; nil, holds an overlay (or if overlays are not supported, a cons of two
+;; markers) for this msgid string which became highlighted for the edit.
+
+(defvar po-edited-fields)
+
+;; We maintain a set of movable pointers for returning to entries.
+
+(defvar po-marker-stack)
+
+;; SEARCH path contains a list of directories where files may be found,
+;; in a format suitable for read completion. Each directory includes
+;; its trailing slash. PO mode starts with "./" and "../".
+
+(defvar po-search-path)
+
+;; The following variables are meaningful only when REFERENCE-CHECK
+;; is identical to START-OF-ENTRY, else they should be recomputed.
+;; REFERENCE-ALIST contains all known references for the current
+;; entry, each list element is (PROMPT FILE LINE), where PROMPT may
+;; be used for completing read, FILE is a string and LINE is a number.
+;; REFERENCE-CURSOR is a cycling cursor into REFERENCE-ALIST.
+
+(defvar po-reference-alist)
+(defvar po-reference-cursor)
+(defvar po-reference-check)
+
+;; The following variables are for marking translatable strings in program
+;; sources. KEYWORDS is the list of keywords for marking translatable
+;; strings, kept in a format suitable for reading with completion.
+;; NEXT-FILE-LIST is the list of source files to visit, gotten from the tags
+;; table. STRING-START is the position for the beginning of the last found
+;; string, or nil if the string is invalidated. STRING-END is the position
+;; for the end of the string and indicates where the search should be
+;; resumed, or nil for the beginning of the current file. MARKING-OVERLAY,
+;; if not `nil', holds the overlay which highlight the last found string;
+;; for older Emacses, it holds the cons of two markers around the
+;; highlighted region.
+
+(defvar po-keywords)
+(defvar po-next-file-list)
+(defvar po-string-start)
+(defvar po-string-end)
+(defvar po-marking-overlay)
+
+;;; PO mode variables and constants (usually not to customize).
+
+;; The textdomain should really be "gettext", only trying it for now.
+;; All this requires more thinking, we cannot just do this like that.
+(set-translation-domain "po-mode")
+
+(defun po-mode-version ()
+ "Show Emacs PO mode version."
+ (interactive)
+ (message (_"Emacs PO mode, version %s") (substring "$Revision: 1.43 $" 11 -2)))
+
+(defconst po-help-display-string
+ (_"\
+PO Mode Summary Next Previous Miscellaneous
+*: Later, /: Docum n p Any type . Redisplay
+ /t /M-t Translated /v Version info
+Moving around f M-f Fuzzy ?, h This help
+< First if any o M-o Obsolete = Current index
+> Last if any u M-u Untranslated O Other window
+/SPC Auto select V Validate
+ Msgstr Comments M Mail officially
+Modifying entries RET # Call editor U Undo
+TAB Remove fuzzy mark k K Kill to E Edit out full
+/DEL Fuzzy or fade out w W Copy to Q Forceful quit
+LFD Init with msgid y Y Yank from q Confirm and quit
+
+gettext Keyword Marking Position Stack
+, Find next string Compendiums m Mark and push current
+M-, Mark translatable *c To compendium r Pop and return
+M-. Change mark, mark *M-C Select, save x Exchange current/top
+
+Program Sources Auxiliary Files Lexicography
+s Cycle reference a Cycle file *l Lookup translation
+M-s Select reference M-a Select file *M-l Add/edit translation
+S Consider path A Consider PO file *L Consider lexicon
+M-S Ignore path M-A Ignore PO file *M-L Ignore lexicon
+")
+ "Help page for PO mode.")
+
+(defconst po-mode-menu-layout
+ '("PO"
+ ("Moving around"
+ ["Auto select" po-auto-select-entry t]
+ "---"
+ "Forward"
+ ["Any next" po-next-entry t]
+ ["Next translated" po-next-translated-entry t]
+ ["Next fuzzy" po-next-fuzzy-entry t]
+ ["Next obsolete" po-next-obsolete-entry t]
+ ["Next untranslated" po-next-untranslated-entry t]
+ ["Last file entry" po-last-entry t]
+ "---"
+ "Backward"
+ ["Any previous" po-previous-entry t]
+ ["Previous translated" po-previous-translated-entry t]
+ ["Previous fuzzy" po-previous-fuzzy-entry t]
+ ["Previous obsolete" po-previous-obsolete-entry t]
+ ["Previous untranslated" po-previous-untranslated-entry t]
+ ["First file entry" po-first-entry t]
+ "---"
+ "Position stack"
+ ["Mark and push current" po-push-location t]
+ ["Pop and return" po-pop-location t]
+ ["Exchange current/top" po-exchange-location t]
+ "---"
+ ["Redisplay" po-current-entry t]
+ ["Current index" po-statistics t])
+ ("Modifying entries"
+ ["Undo" po-undo t]
+ "---"
+ "Msgstr"
+ ["Edit msgstr" po-edit-msgstr t]
+ ["Kill msgstr" po-kill-msgstr t]
+ ["Save msgstr" po-kill-ring-save-msgstr t]
+ ["Yank msgstr" po-yank-msgstr t]
+ "---"
+ "Comments"
+ ["Edit comment" po-edit-comment t]
+ ["Kill comment" po-kill-comment t]
+ ["Save comment" po-kill-ring-save-comment t]
+ ["Yank comment" po-yank-comment t]
+ "---"
+ ["Remove fuzzy mark" po-unfuzzy t]
+ ["Fuzzy or fade out" po-fade-out-entry t]
+ ["Init with msgid" po-msgid-to-msgstr t])
+ ("Other files"
+ ["Other window" po-other-window t]
+ "---"
+ "Program sources"
+ ["Cycle reference" po-cycle-source-reference t]
+ ["Select reference" po-select-source-reference t]
+ ["Consider path" po-consider-source-path t]
+ ["Ignore path" po-ignore-source-path t]
+ "---"
+ "Compendiums"
+ ["To compendium" po-save-entry nil]
+ ["Select, save" po-select-and-save-entry nil]
+ "---"
+ "Auxiliary files"
+ ["Cycle file" po-cycle-auxiliary t]
+ ["Select file" po-select-auxiliary t]
+ ["Consider file" po-consider-as-auxiliary t]
+ ["Ignore file" po-ignore-as-auxiliary t]
+ "---"
+ "Lexicography"
+ ["Lookup translation" po-lookup-lexicons nil]
+ ["Add/edit translation" po-edit-lexicon-entry nil]
+ ["Consider lexicon" po-consider-lexicon-file nil]
+ ["Ignore lexicon" po-ignore-lexicon-file nil])
+ "---"
+ "Source marking"
+ ["Find first string" (po-tags-search '(nil)) t]
+ ["Prefer keyword" (po-select-mark-and-mark '(nil)) t]
+ ["Find next string" po-tags-search t]
+ ["Mark preferred" po-mark-translatable t]
+ ["Mark with keyword" po-select-mark-and-mark t]
+ "---"
+ ["Version info" po-mode-version t]
+ ["Help page" po-help t]
+ ["Validate" po-validate t]
+ ["Mail officially" po-send-mail t]
+ ["Edit out full" po-edit-out-full t]
+ "---"
+ ["Forceful quit" po-quit t]
+ ["Soft quit" po-confirm-and-quit t])
+ "Menu layout for PO mode.")
+
+;; FIXME: subedit mode should also have its own layout.
+
+(defconst po-subedit-message
+ (_"Type `C-c C-c' once done, or `C-c C-k' to abort edit")
+ "Message to post in the minibuffer when an edit buffer is displayed.")
+
+(defconst po-content-type-charset-alist
+ '((euc . japanese-iso-8bit))
+ "How to convert Content-Type into a Mule coding system.")
+
+(defvar po-auxiliary-list nil
+ "List of auxiliary PO files, in completing read format.")
+
+(defvar po-auxiliary-cursor nil
+ "Cursor into the `po-auxiliary-list'.")
+
+(defvar po-translation-project-address
+ "translation@iro.umontreal.ca"
+ "Electronic mail address of the Translation Project.")
+
+(defvar po-compose-mail-function
+ (let ((functions '(compose-mail-other-window
+ message-mail-other-window
+ compose-mail
+ message-mail))
+ result)
+ (while (and (not result) functions)
+ (if (fboundp (car functions))
+ (setq result (car functions))
+ (setq functions (cdr functions))))
+ (cond (result)
+ ((fboundp 'mail-other-window)
+ (function (lambda (to subject)
+ (mail-other-window nil to subject))))
+ ((fboundp 'mail)
+ (function (lambda (to subject)
+ (mail nil to subject))))
+ (t (function (lambda (to subject)
+ (error (_"I do not know how to mail to `%s'") to))))))
+ "Function to start composing an electronic message.")
+
+(defvar po-any-msgid-regexp
+ "^\\(#~?[ \t]*\\)?msgid.*\n\\(\\(#~?[ \t]*\\)?\".*\n\\)*"
+ "Regexp matching a whole msgid field, whether obsolete or not.")
+
+(defvar po-any-msgstr-regexp
+ "^\\(#~?[ \t]*\\)?msgstr.*\n\\(\\(#~?[ \t]*\\)?\".*\n\\)*"
+ "Regexp matching a whole msgstr field, whether obsolete or not.")
+
+(defvar po-msgfmt-program "msgfmt"
+ "Path to msgfmt program from GNU gettext package.")
+
+;; Font lock based highlighting code.
+(defconst po-font-lock-keywords
+ '(
+ ("^\\(msgid \\|msgstr \\)?\"\\|\"$" . font-lock-keyword-face)
+ ("\\\\.\\|%[-.0-9ul]*[a-zA-Z]" . font-lock-variable-name-face)
+ ("^# .*\\|^#[:,]?" . font-lock-comment-face)
+ ("^#:\\(.*\\)" 1 font-lock-reference-face)
+ ;; The following line does not work, and I wonder why.
+ ;;("^#,\\(.*\\)" 1 font-function-name-reference-face)
+ )
+ "Additional expressions to highlight in PO mode.")
+
+;; Old activator for `font lock'. Is it still useful? I don't think so.
+;;
+;;(if (boundp 'font-lock-keywords)
+;; (put 'po-mode 'font-lock-keywords 'po-font-lock-keywords))
+
+;; `hilit19' based highlighting code has been disabled, as most probably
+;; nobody really needs it (it also generates ugly byte-compiler warnings).
+;;
+;;(if (fboundp 'hilit-set-mode-patterns)
+;; (hilit-set-mode-patterns 'po-mode
+;; '(("^# .*\\|^#$" nil comment)
+;; ("^#[.,:].*" nil include)
+;; ("^\\(msgid\\|msgstr\\) *\"" nil keyword)
+;; ("^\"\\|\"$" nil keyword))))
+
+;;; Mode activation.
+
+(eval-and-compile
+ (if po-EMACS20
+
+ (defun po-find-file-coding-system (arg-list)
+ "Return a Mule (DECODING . ENCODING) pair, according to PO file charset.
+Called through file-coding-system-alist, before the file is visited for real."
+ (and (eq (car arg-list) 'insert-file-contents)
+ (with-temp-buffer
+ (let ((coding-system-for-read 'no-conversion))
+ ;; Is 4096 enough? FIXME: Retry as needed!
+ (insert-file-contents (nth 1 arg-list) nil 0 4096)
+ (if (re-search-forward
+ "^\"Content-Type: text/plain;[ \t]*charset=\\([^\\]+\\)"
+ nil t)
+ (let* ((charset (intern (downcase (buffer-substring
+ (match-beginning 1)
+ (match-end 1)))))
+ (slot (assq charset
+ po-content-type-charset-alist)))
+ (list (cond (slot (cdr slot))
+ ((memq charset (coding-system-list)) charset)
+ (t 'no-conversion))))
+ '(no-conversion))))))
+
+ ))
+
+(defvar po-mode-map nil
+ "Keymap for PO mode.")
+(if po-mode-map
+ ()
+ ;; The following line because (make-sparse-keymap) does not work on Demacs.
+ (setq po-mode-map (make-keymap))
+ (suppress-keymap po-mode-map)
+ (define-key po-mode-map "\C-i" 'po-unfuzzy)
+ (define-key po-mode-map "\C-j" 'po-msgid-to-msgstr)
+ (define-key po-mode-map "\C-m" 'po-edit-msgstr)
+ (define-key po-mode-map " " 'po-auto-select-entry)
+ (define-key po-mode-map "?" 'po-help)
+ (define-key po-mode-map "#" 'po-edit-comment)
+ (define-key po-mode-map "," 'po-tags-search)
+ (define-key po-mode-map "." 'po-current-entry)
+ (define-key po-mode-map "<" 'po-first-entry)
+ (define-key po-mode-map "=" 'po-statistics)
+ (define-key po-mode-map ">" 'po-last-entry)
+ (define-key po-mode-map "a" 'po-cycle-auxiliary)
+;;;; (define-key po-mode-map "c" 'po-save-entry)
+ (define-key po-mode-map "f" 'po-next-fuzzy-entry)
+ (define-key po-mode-map "h" 'po-help)
+ (define-key po-mode-map "k" 'po-kill-msgstr)
+;;;; (define-key po-mode-map "l" 'po-lookup-lexicons)
+ (define-key po-mode-map "m" 'po-push-location)
+ (define-key po-mode-map "n" 'po-next-entry)
+ (define-key po-mode-map "o" 'po-next-obsolete-entry)
+ (define-key po-mode-map "p" 'po-previous-entry)
+ (define-key po-mode-map "q" 'po-confirm-and-quit)
+ (define-key po-mode-map "r" 'po-pop-location)
+ (define-key po-mode-map "s" 'po-cycle-source-reference)
+ (define-key po-mode-map "t" 'po-next-translated-entry)
+ (define-key po-mode-map "u" 'po-next-untranslated-entry)
+ (define-key po-mode-map "v" 'po-mode-version)
+ (define-key po-mode-map "w" 'po-kill-ring-save-msgstr)
+ (define-key po-mode-map "x" 'po-exchange-location)
+ (define-key po-mode-map "y" 'po-yank-msgstr)
+ (define-key po-mode-map "A" 'po-consider-as-auxiliary)
+ (define-key po-mode-map "E" 'po-edit-out-full)
+ (define-key po-mode-map "K" 'po-kill-comment)
+;;;; (define-key po-mode-map "L" 'po-consider-lexicon-file)
+ (define-key po-mode-map "M" 'po-send-mail)
+ (define-key po-mode-map "O" 'po-other-window)
+ (define-key po-mode-map "Q" 'po-quit)
+ (define-key po-mode-map "S" 'po-consider-source-path)
+ (define-key po-mode-map "U" 'po-undo)
+ (define-key po-mode-map "V" 'po-validate)
+ (define-key po-mode-map "W" 'po-kill-ring-save-comment)
+ (define-key po-mode-map "Y" 'po-yank-comment)
+ (define-key po-mode-map "\177" 'po-fade-out-entry)
+ (define-key po-mode-map "\M-," 'po-mark-translatable)
+ (define-key po-mode-map "\M-." 'po-select-mark-and-mark)
+ (define-key po-mode-map "\M-a" 'po-select-auxiliary)
+;;;; (define-key po-mode-map "\M-c" 'po-select-and-save-entry)
+ (define-key po-mode-map "\M-f" 'po-previous-fuzzy-entry)
+;;;; (define-key po-mode-map "\M-l" 'po-edit-lexicon-entry)
+ (define-key po-mode-map "\M-o" 'po-previous-obsolete-entry)
+ (define-key po-mode-map "\M-t" 'po-previous-translated-entry)
+ (define-key po-mode-map "\M-u" 'po-previous-untranslated-entry)
+ (define-key po-mode-map "\M-s" 'po-select-source-reference)
+ (define-key po-mode-map "\M-A" 'po-ignore-as-auxiliary)
+;;;; (define-key po-mode-map "\M-L" 'po-ignore-lexicon-file)
+ (define-key po-mode-map "\M-S" 'po-ignore-source-path)
+ )
+
+(defun po-mode ()
+ "Major mode for translators when they edit PO files.
+Special commands:\\{po-mode-map}
+Turning on PO mode calls the value of the variable `po-mode-hook',
+if that value is non-nil. Behaviour may be adjusted through some variables,
+all reachable through `M-x customize', in group `Emacs.Editing.I18n.Po'."
+
+ (interactive)
+ (kill-all-local-variables)
+ (setq major-mode 'po-mode
+ mode-name "PO")
+ (use-local-map po-mode-map)
+ (if (fboundp 'easy-menu-define)
+ (progn
+ (easy-menu-define po-mode-menu po-mode-map "" po-mode-menu-layout)
+ (and po-XEMACS (easy-menu-add po-mode-menu))))
+ (make-local-variable 'font-lock-defaults)
+ (setq font-lock-defaults '(po-font-lock-keywords t))
+
+ (make-local-variable 'po-read-only)
+ (setq po-read-only buffer-read-only
+ buffer-read-only t)
+
+ (make-local-variable 'po-start-of-entry)
+ (make-local-variable 'po-start-of-msgid)
+ (make-local-variable 'po-start-of-msgstr)
+ (make-local-variable 'po-end-of-entry)
+ (make-local-variable 'po-entry-type)
+
+ (make-local-variable 'po-translated-counter)
+ (make-local-variable 'po-fuzzy-counter)
+ (make-local-variable 'po-untranslated-counter)
+ (make-local-variable 'po-obsolete-counter)
+ (make-local-variable 'po-mode-line-string)
+
+ (setq po-mode-flag t)
+
+ (po-check-file-header)
+ (po-compute-counters nil)
+
+ (make-local-variable 'po-edited-fields)
+ (setq po-edited-fields nil)
+
+ (make-local-variable 'po-marker-stack)
+ (setq po-marker-stack nil)
+
+ (make-local-variable 'po-search-path)
+ (setq po-search-path '(("./") ("../")))
+
+ (make-local-variable 'po-reference-alist)
+ (make-local-variable 'po-reference-cursor)
+ (make-local-variable 'po-reference-check)
+ (setq po-reference-alist nil
+ po-reference-cursor nil
+ po-reference-check 0)
+
+ (make-local-variable 'po-keywords)
+ (make-local-variable 'po-next-file-list)
+ (make-local-variable 'po-string-start)
+ (make-local-variable 'po-string-end)
+ (make-local-variable 'po-marking-overlay)
+ (setq po-keywords '(("gettext") ("gettext_noop") ("_") ("N_"))
+ po-next-file-list nil
+ po-string-start nil
+ po-string-end nil
+ po-marking-overlay (po-create-overlay))
+
+ (message (_"You may type `h' or `?' for a short PO mode reminder."))
+ (run-hooks 'po-mode-hook))
+
+;;; Window management.
+
+(make-variable-buffer-local 'po-mode-flag)
+
+(defvar po-mode-line-entry '(po-mode-flag (" " po-mode-line-string))
+ "Mode line format entry displaying MODE-LINE-STRING.")
+
+;; Insert MODE-LINE-ENTRY in mode line, but on first load only.
+(or (member po-mode-line-entry mode-line-format)
+ (let ((entry (member 'global-mode-string mode-line-format)))
+ (setcdr entry (cons po-mode-line-entry (cdr entry)))))
+
+(defun po-update-mode-line-string ()
+ "Compute a new statistics string to display in mode line."
+ (setq po-mode-line-string
+ (concat (format "%dt" po-translated-counter)
+ (if (> po-fuzzy-counter 0)
+ (format "+%df" po-fuzzy-counter))
+ (if (> po-untranslated-counter 0)
+ (format "+%du" po-untranslated-counter))
+ (if (> po-obsolete-counter 0)
+ (format "+%do" po-obsolete-counter))))
+ (po-force-mode-line-update))
+
+(defun po-type-counter ()
+ "Return the symbol name of the counter appropriate for the current entry."
+ (cond ((eq po-entry-type 'obsolete) 'po-obsolete-counter)
+ ((eq po-entry-type 'fuzzy) 'po-fuzzy-counter)
+ ((eq po-entry-type 'translated) 'po-translated-counter)
+ ((eq po-entry-type 'untranslated) 'po-untranslated-counter)
+ (t (error (_"Unknown entry type")))))
+
+(defun po-decrease-type-counter ()
+ "Decrease the counter corresponding to the nature of the current entry."
+ (let ((counter (po-type-counter)))
+ (set counter (1- (eval counter)))))
+
+(defun po-increase-type-counter ()
+ "Increase the counter corresponding to the nature of the current entry.
+Then, update the mode line counters."
+ (let ((counter (po-type-counter)))
+ (set counter (1+ (eval counter))))
+ (po-update-mode-line-string))
+
+;; Avoid byte compiler warnings.
+(defvar po-fuzzy-regexp)
+(defvar po-untranslated-regexp)
+
+(defun po-compute-counters (flag)
+ "Prepare counters for mode line display. If FLAG, also echo entry position."
+ (and flag (po-find-span-of-entry))
+ (setq po-translated-counter 0
+ po-fuzzy-counter 0
+ po-untranslated-counter 0
+ po-obsolete-counter 0)
+ (let ((position 0) (total 0) here)
+ (save-excursion
+ (goto-char (point-min))
+ (while (re-search-forward po-any-msgstr-regexp nil t)
+ (and (= (% total 20) 0)
+ (if flag
+ (message (_"Position %d/%d") position total)
+ (message (_"Position %d") total)))
+ (setq here (point))
+ (goto-char (match-beginning 0))
+ (setq total (1+ total))
+ (and flag (eq (point) po-start-of-msgstr) (setq position total))
+ (cond ((eq (following-char) ?#)
+ (setq po-obsolete-counter (1+ po-obsolete-counter)))
+ ((looking-at po-untranslated-regexp)
+ (setq po-untranslated-counter (1+ po-untranslated-counter)))
+ (t (setq po-translated-counter (1+ po-translated-counter))))
+ (goto-char here))
+
+ ;; Make another pass just for the fuzzy entries, kind of kludgey.
+ ;; FIXME: Counts will be wrong if untranslated entries are fuzzy, yet
+ ;; this should not normally happen.
+ (goto-char (point-min))
+ (while (re-search-forward po-fuzzy-regexp nil t)
+ (setq po-fuzzy-counter (1+ po-fuzzy-counter)))
+ (setq po-translated-counter (- po-translated-counter po-fuzzy-counter)))
+
+ ;; Push the results out.
+ (if flag
+ (message (_"\
+Position %d/%d; %d translated, %d fuzzy, %d untranslated, %d obsolete")
+ position total po-translated-counter po-fuzzy-counter
+ po-untranslated-counter po-obsolete-counter)
+ (message "")))
+ (po-update-mode-line-string))
+
+(defun po-redisplay ()
+ "Redisplay the current entry."
+ ;; FIXME: Should try to fit the whole entry on the window. If this is not
+ ;; possible, should try to fit the comment and the msgid. Otherwise,
+ ;; should try to fit the msgid. Else, the first line of the msgid should
+ ;; be at the top of the window.
+ (goto-char po-start-of-msgid))
+
+(defun po-other-window ()
+ "Get the cursor into another window, out of PO mode."
+ (interactive)
+ (if (one-window-p t)
+ (progn
+ (split-window)
+ (switch-to-buffer (other-buffer)))
+ (other-window 1)))
+
+;;; Processing the PO file header entry.
+
+(defun po-check-file-header ()
+ "Create a missing PO mode file header, or replace an oldish one."
+ (save-excursion
+ (let ((buffer-read-only po-read-only)
+ insert-flag end-of-header)
+ (goto-char (point-min))
+ (if (re-search-forward po-any-msgstr-regexp nil t)
+ (progn
+
+ ;; There is at least one entry.
+ (goto-char (match-beginning 0))
+ (previous-line 1)
+ (setq end-of-header (match-end 0))
+ (if (looking-at "msgid \"\"\n")
+
+ ;; There is indeed a PO file header.
+ (if (re-search-forward "\n\"PO-Revision-Date: "
+ end-of-header t)
+ nil
+
+ ;; This is an oldish header. Replace it all.
+ (goto-char end-of-header)
+ (while (> (point) (point-min))
+ (previous-line 1)
+ (insert "#~ ")
+ (beginning-of-line))
+ (beginning-of-line)
+ (setq insert-flag t))
+
+ ;; The first entry is not a PO file header, insert one.
+ (setq insert-flag t)))
+
+ ;; Not a single entry found.
+ (setq insert-flag t))
+
+ (goto-char (point-min))
+ (and insert-flag (insert po-default-file-header "\n")))))
+
+(defun po-replace-revision-date ()
+ "Replace the revision date by current time in the PO file header."
+ (if (fboundp 'format-time-string)
+ (if (or (eq po-auto-replace-revision-date t)
+ (and (eq po-auto-replace-revision-date 'ask)
+ (y-or-n-p (_"May I set PO-Revision-Date? "))))
+ (save-excursion
+ (goto-char (point-min))
+ (if (re-search-forward "^\"PO-Revision-Date:.*" nil t)
+ (let* ((buffer-read-only po-read-only)
+ (time (current-time))
+ (seconds (or (car (current-time-zone time)) 0))
+ (minutes (/ (abs seconds) 60))
+ (zone (format "%c%02d:%02d"
+ (if (< seconds 0) ?- ?+)
+ (/ minutes 60)
+ (% minutes 60))))
+ (replace-match
+ (concat "\"PO-Revision-Date: "
+ (format-time-string "%Y-%m-%d %H:%M" time)
+ zone "\\n\"")
+ t t))))
+ (message ""))
+ (message (_"PO-Revision-Date should be adjusted..."))))
+
+;;; Handling span of entry, entry type and entry attributes.
+
+(defun po-find-span-of-entry ()
+ "Find the extent of the PO file entry where the cursor is. Set variables
+PO-START-OF-ENTRY, PO-START-OF-MSGID, PO-START-OF-MSGSTR, PO-END-OF-ENTRY
+and PO-ENTRY-TYPE to meaningful values. Decreasing priority of type
+interpretation is: obsolete, fuzzy, untranslated or translated."
+ (let ((here (point)))
+ (if (re-search-backward po-any-msgstr-regexp nil t)
+ (progn
+
+ ;; After a backward match, (match-end 0) will not extend
+ ;; beyond point, in case point was *inside* the regexp. We
+ ;; need a dependable (match-end 0), so we redo the match in
+ ;; the forward direction.
+ (re-search-forward po-any-msgstr-regexp)
+ (if (<= (match-end 0) here)
+ (progn
+
+ ;; We most probably found the msgstr of the previous
+ ;; entry. The current entry then starts just after
+ ;; its end, save this information just in case.
+ (setq po-start-of-entry (match-end 0))
+
+ ;; However, it is also possible that we are located in
+ ;; the crumb after the last entry in the file. If
+ ;; yes, we know the middle and end of last PO entry.
+ (setq po-start-of-msgstr (match-beginning 0)
+ po-end-of-entry (match-end 0))
+
+ (if (re-search-forward po-any-msgstr-regexp nil t)
+ (progn
+
+ ;; We definitely were not in the crumb.
+ (setq po-start-of-msgstr (match-beginning 0)
+ po-end-of-entry (match-end 0)))
+
+ ;; We were in the crumb. The start of the last PO
+ ;; file entry is the end of the previous msgstr if
+ ;; any, or else, the beginning of the file.
+ (goto-char po-start-of-msgstr)
+ (setq po-start-of-entry
+ (if (re-search-backward po-any-msgstr-regexp nil t)
+ (match-end 0)
+ (point-min)))))
+
+ ;; The cursor was inside msgstr of the current entry.
+ (setq po-start-of-msgstr (match-beginning 0)
+ po-end-of-entry (match-end 0))
+ ;; The start of this entry is the end of the previous
+ ;; msgstr if any, or else, the beginning of the file.
+ (goto-char po-start-of-msgstr)
+ (setq po-start-of-entry
+ (if (re-search-backward po-any-msgstr-regexp nil t)
+ (match-end 0)
+ (point-min)))))
+
+ ;; The cursor was before msgstr in the first entry in the file.
+ (setq po-start-of-entry (point-min))
+ (goto-char po-start-of-entry)
+ ;; There is at least the PO file header, so this should match.
+ (re-search-forward po-any-msgstr-regexp)
+ (setq po-start-of-msgstr (match-beginning 0)
+ po-end-of-entry (match-end 0)))
+
+ ;; Find start of msgid.
+ (goto-char po-start-of-entry)
+ (re-search-forward po-any-msgid-regexp)
+ (setq po-start-of-msgid (match-beginning 0))
+
+ ;; Classify the entry.
+ (setq po-entry-type
+ (if (eq (following-char) ?#)
+ 'obsolete
+ (goto-char po-start-of-entry)
+ (if (re-search-forward po-fuzzy-regexp po-start-of-msgid t)
+ 'fuzzy
+ (goto-char po-start-of-msgstr)
+ (if (looking-at po-untranslated-regexp)
+ 'untranslated
+ 'translated))))
+
+ ;; Put the cursor back where it was.
+ (goto-char here)))
+
+(defun po-add-attribute (name)
+ "Add attribute NAME to the current entry, unless it is already there."
+ (save-excursion
+ (let ((buffer-read-only po-read-only))
+ (goto-char po-start-of-entry)
+ (if (re-search-forward "\n#[,!] .*" po-start-of-msgid t)
+ (save-restriction
+ (narrow-to-region (match-beginning 0) (match-end 0))
+ (goto-char (point-min))
+ (if (re-search-forward (concat "\\b" name "\\b") nil t)
+ nil
+ (goto-char (point-max))
+ (insert ", " name)))
+ (skip-chars-forward "\n")
+ (while (eq (following-char) ?#)
+ (next-line 1))
+ (insert "#, " name "\n")))))
+
+(defun po-delete-attribute (name)
+ "Delete attribute NAME from the current entry, if any."
+ (save-excursion
+ (let ((buffer-read-only po-read-only))
+ (goto-char po-start-of-entry)
+ (if (re-search-forward "\n#[,!] .*" po-start-of-msgid t)
+ (save-restriction
+ (narrow-to-region (match-beginning 0) (match-end 0))
+ (goto-char (point-min))
+ (if (re-search-forward
+ (concat "\\(\n#[,!] " name "$\\|, " name "$\\| " name ",\\)")
+ nil t)
+ (replace-match "" t t)))))))
+
+;;; Entry positionning.
+
+(defun po-say-location-depth ()
+ "Tell how many entries in the entry location stack."
+ (let ((depth (length po-marker-stack)))
+ (cond ((= depth 0) (message (_"Empty location stack")))
+ ((= depth 1) (message (_"One entry in location stack")))
+ (t (message (_"%d entries in location stack") depth)))))
+
+(defun po-push-location ()
+ "Stack the location of the current entry, for later return."
+ (interactive)
+ (po-find-span-of-entry)
+ (save-excursion
+ (goto-char po-start-of-msgid)
+ (setq po-marker-stack (cons (point-marker) po-marker-stack)))
+ (po-say-location-depth))
+
+(defun po-pop-location ()
+ "Unstack a saved location, and return to the corresponding entry."
+ (interactive)
+ (if po-marker-stack
+ (progn
+ (goto-char (car po-marker-stack))
+ (setq po-marker-stack (cdr po-marker-stack))
+ (po-current-entry)
+ (po-say-location-depth))
+ (error (_"The entry location stack is empty"))))
+
+(defun po-exchange-location ()
+ "Exchange the location of the current entry with the top of stack."
+ (interactive)
+ (if po-marker-stack
+ (progn
+ (po-find-span-of-entry)
+ (goto-char po-start-of-msgid)
+ (let ((location (point-marker)))
+ (goto-char (car po-marker-stack))
+ (setq po-marker-stack (cons location (cdr po-marker-stack))))
+ (po-current-entry)
+ (po-say-location-depth))
+ (error (_"The entry location stack is empty"))))
+
+(defun po-current-entry ()
+ "Display the current entry."
+ (interactive)
+ (po-find-span-of-entry)
+ (po-redisplay))
+
+(defun po-first-entry-with-regexp (regexp)
+ "Display the first entry in the file which msgstr matches REGEXP."
+ (let ((here (point)))
+ (goto-char (point-min))
+ (if (re-search-forward regexp nil t)
+ (progn
+ (goto-char (match-beginning 0))
+ (po-current-entry))
+ (goto-char here)
+ (error (_"There is no such entry")))))
+
+(defun po-last-entry-with-regexp (regexp)
+ "Display the last entry in the file which msgstr matches REGEXP."
+ (let ((here (point)))
+ (goto-char (point-max))
+ (if (re-search-backward regexp nil t)
+ (po-current-entry)
+ (goto-char here)
+ (error (_"There is no such entry")))))
+
+(defun po-next-entry-with-regexp (regexp wrap)
+ "Display the entry following the current entry which msgstr matches REGEXP.
+If WRAP is not nil, the search may wrap around the buffer."
+ (po-find-span-of-entry)
+ (let ((here (point)))
+ (goto-char po-end-of-entry)
+ (if (re-search-forward regexp nil t)
+ (progn
+ (goto-char (match-beginning 0))
+ (po-current-entry))
+ (if (and wrap
+ (progn
+ (goto-char (point-min))
+ (re-search-forward regexp po-start-of-entry t)))
+ (progn
+ (goto-char (match-beginning 0))
+ (po-current-entry)
+ (message (_"Wrapping around the buffer")))
+ (goto-char here)
+ (error (_"There is no such entry"))))))
+
+(defun po-previous-entry-with-regexp (regexp wrap)
+ "Redisplay the entry preceding the current entry which msgstr matches REGEXP.
+If WRAP is not nil, the search may wrap around the buffer."
+ (po-find-span-of-entry)
+ (let ((here (point)))
+ (goto-char po-start-of-entry)
+ (if (re-search-backward regexp nil t)
+ (po-current-entry)
+ (if (and wrap
+ (progn
+ (goto-char (point-max))
+ (re-search-backward regexp po-end-of-entry t)))
+ (progn
+ (po-current-entry)
+ (message (_"Wrapping around the buffer")))
+ (goto-char here)
+ (error (_"There is no such entry"))))))
+
+;; Any entries.
+
+(defun po-first-entry ()
+ "Display the first entry."
+ (interactive)
+ (po-first-entry-with-regexp po-any-msgstr-regexp))
+
+(defun po-last-entry ()
+ "Display the last entry."
+ (interactive)
+ (po-last-entry-with-regexp po-any-msgstr-regexp))
+
+(defun po-next-entry ()
+ "Display the entry following the current entry."
+ (interactive)
+ (po-next-entry-with-regexp po-any-msgstr-regexp nil))
+
+(defun po-previous-entry ()
+ "Display the entry preceding the current entry."
+ (interactive)
+ (po-previous-entry-with-regexp po-any-msgstr-regexp nil))
+
+;; Untranslated entries.
+
+(defvar po-after-entry-regexp
+ "\\(\\'\\|\\(#[ \t]*\\)?[^\"]\\)"
+ "Regexp which should be true after a full msgstr string matched.")
+
+(defvar po-untranslated-regexp
+ (concat "^msgstr[ \t]*\"\"\n" po-after-entry-regexp)
+ "Regexp matching a whole msgstr field, but only if active and empty.")
+
+(defun po-next-untranslated-entry ()
+ "Find the next untranslated entry, wrapping around if necessary."
+ (interactive)
+ (po-next-entry-with-regexp po-untranslated-regexp t))
+
+(defun po-previous-untranslated-entry ()
+ "Find the previous untranslated entry, wrapping around if necessary."
+ (interactive)
+ (po-previous-entry-with-regexp po-untranslated-regexp t))
+
+(defun po-msgid-to-msgstr ()
+ "Use another window to edit msgstr reinitialized with msgid."
+ (interactive)
+ (po-find-span-of-entry)
+ (if (or (eq po-entry-type 'untranslated)
+ (eq po-entry-type 'obsolete)
+ (y-or-n-p (_"Really loose previous translation? ")))
+ (po-set-msgstr (po-get-msgid nil)))
+ (message ""))
+
+;; Obsolete entries.
+
+(defvar po-obsolete-msgstr-regexp
+ "^#~?[ \t]*msgstr.*\n\\(#~?[ \t]*\".*\n\\)*"
+ "Regexp matching a whole msgstr field of an obsolete entry.")
+
+(defun po-next-obsolete-entry ()
+ "Find the next obsolete entry, wrapping around if necessary."
+ (interactive)
+ (po-next-entry-with-regexp po-obsolete-msgstr-regexp t))
+
+(defun po-previous-obsolete-entry ()
+ "Find the previous obsolete entry, wrapping around if necessary."
+ (interactive)
+ (po-previous-entry-with-regexp po-obsolete-msgstr-regexp t))
+
+;; Fuzzy entries.
+
+(defvar po-fuzzy-regexp "^#[,!] .*fuzzy"
+ "Regexp matching the string inserted by msgmerge for translations
+which does not match exactly.")
+
+(defun po-next-fuzzy-entry ()
+ "Find the next fuzzy entry, wrapping around if necessary."
+ (interactive)
+ (po-next-entry-with-regexp po-fuzzy-regexp t))
+
+(defun po-previous-fuzzy-entry ()
+ "Find the next fuzzy entry, wrapping around if necessary."
+ (interactive)
+ (po-previous-entry-with-regexp po-fuzzy-regexp t))
+
+(defun po-unfuzzy ()
+ "Remove the fuzzy attribute for the current entry."
+ (interactive)
+ (po-find-span-of-entry)
+ (cond ((eq po-entry-type 'fuzzy)
+ (po-decrease-type-counter)
+ (po-delete-attribute "fuzzy")
+ (po-current-entry)
+ (po-increase-type-counter)))
+ (if po-auto-select-on-unfuzzy
+ (po-auto-select-entry))
+ (po-update-mode-line-string))
+
+;; Translated entries.
+
+(defun po-next-translated-entry ()
+ "Find the next untranslated entry, wrapping around if necessary."
+ (interactive)
+ (if (= po-translated-counter 0)
+ (error (_"There is no such entry"))
+ (po-next-entry-with-regexp po-untranslated-regexp t)
+ (po-find-span-of-entry)
+ (while (not (eq po-entry-type 'translated))
+ (po-next-entry-with-regexp po-any-msgstr-regexp t)
+ (po-find-span-of-entry))))
+
+(defun po-previous-translated-entry ()
+ "Find the previous untranslated entry, wrapping around if necessary."
+ (interactive)
+ (if (= po-translated-counter 0)
+ (error (_"There is no such entry"))
+ (po-previous-entry-with-regexp po-any-msgstr-regexp t)
+ (po-find-span-of-entry)
+ (while (not (eq po-entry-type 'translated))
+ (po-previous-entry-with-regexp po-untranslated-regexp t)
+ (po-find-span-of-entry))))
+
+;; Auto-selection feature.
+
+(defun po-auto-select-entry ()
+ "Select the next entry having the same type as the current one.
+If none, wrap from the beginning of the buffer with another type,
+going from untranslated to fuzzy, and from fuzzy to obsolete.
+Plain translated entries are always disregarded unless there are
+no entries of the other types."
+ (interactive)
+ (po-find-span-of-entry)
+ (goto-char po-end-of-entry)
+ (if (and (= po-untranslated-counter 0)
+ (= po-fuzzy-counter 0)
+ (= po-obsolete-counter 0))
+
+ ;; All entries are plain translated. Next entry will do, or
+ ;; wrap around if there is none.
+ (if (re-search-forward po-any-msgstr-regexp nil t)
+ (goto-char (match-beginning 0))
+ (goto-char (point-min)))
+
+ ;; If over a translated entry, look for an untranslated one first.
+ ;; Else, look for an entry of the same type first.
+ (let ((goal (if (eq po-entry-type 'translated)
+ 'untranslated
+ po-entry-type)))
+ (while goal
+
+ ;; Find an untranslated entry, or wrap up for a fuzzy entry.
+ (if (eq goal 'untranslated)
+ (if (and (> po-untranslated-counter 0)
+ (re-search-forward po-untranslated-regexp nil t))
+ (progn
+ (goto-char (match-beginning 0))
+ (setq goal nil))
+ (goto-char (point-min))
+ (setq goal 'fuzzy)))
+
+ ;; Find a fuzzy entry, or wrap up for an obsolete entry.
+ (if (eq goal 'fuzzy)
+ (if (and (> po-fuzzy-counter 0)
+ (re-search-forward po-fuzzy-regexp nil t))
+ (progn
+ (goto-char (match-beginning 0))
+ (setq goal nil))
+ (goto-char (point-min))
+ (setq goal 'obsolete)))
+
+ ;; Find an obsolete entry, or wrap up for an untranslated entry.
+ (if (eq goal 'obsolete)
+ (if (and (> po-obsolete-counter 0)
+ (re-search-forward po-obsolete-msgstr-regexp nil t))
+ (progn
+ (goto-char (match-beginning 0))
+ (setq goal nil))
+ (goto-char (point-min))
+ (setq goal 'untranslated))))))
+
+ ;; Display this entry nicely.
+ (po-current-entry))
+
+;;; Killing and yanking fields.
+
+(defun po-extract-unquoted (buffer start end)
+ "Extract and return the unquoted string in BUFFER going from START to END.
+Crumb preceding or following the quoted string is ignored."
+ (po-with-temp-buffer
+ (insert-buffer-substring buffer start end)
+ ;; Remove preceding crumb.
+ (goto-char (point-min))
+ (search-forward "\"")
+ (delete-region (point-min) (point))
+ ;; Remove following crumb.
+ (goto-char (point-max))
+ (search-backward "\"")
+ (delete-region (point) (point-max))
+ ;; Glue concatenated strings.
+ (goto-char (point-min))
+ (while (re-search-forward "\"[ \t]*\\\\?\n\\(#~?\\)?[ \t]*\"" nil t)
+ (replace-match "" t t))
+ ;; Remove escaped newlines.
+ (goto-char (point-min))
+ (while (re-search-forward "\\\\[ \t]*\n" nil t)
+ (replace-match "" t t))
+ ;; Unquote individual characters.
+ (goto-char (point-min))
+ (while (re-search-forward "\\\\[\"abfnt\\0-7]" nil t)
+ (cond ((eq (preceding-char) ?\") (replace-match "\"" t t))
+ ((eq (preceding-char) ?a) (replace-match "\a" t t))
+ ((eq (preceding-char) ?b) (replace-match "\b" t t))
+ ((eq (preceding-char) ?f) (replace-match "\f" t t))
+ ((eq (preceding-char) ?n) (replace-match "\n" t t))
+ ((eq (preceding-char) ?t) (replace-match "\t" t t))
+ ((eq (preceding-char) ?\\) (replace-match "\\" t t))
+ (t (let ((value (- (preceding-char) ?0)))
+ (replace-match "" t t)
+ (while (looking-at "[0-7]")
+ (setq value (+ (* 8 value) (- (following-char) ?0)))
+ (replace-match "" t t))
+ (insert value)))))
+ (buffer-string)))
+
+(defun po-eval-requoted (form prefix obsolete)
+ "Eval FORM, which inserts a string, and return the string fully requoted.
+If PREFIX, precede the result with its contents. If OBSOLETE, comment all
+generated lines in the returned string. Evaluating FORM should insert the
+wanted string in the buffer which is current at the time of evaluation.
+If FORM is itself a string, then this string is used for insertion."
+ (po-with-temp-buffer
+ (if (stringp form)
+ (insert form)
+ (push-mark)
+ (eval form))
+ (goto-char (point-min))
+ (let ((multi-line (re-search-forward "[^\n]\n+[^\n]" nil t)))
+ (goto-char (point-min))
+ (while (re-search-forward "[\"\a\b\f\n\t\\]" nil t)
+ (cond ((eq (preceding-char) ?\") (replace-match "\\\"" t t))
+ ((eq (preceding-char) ?\a) (replace-match "\\a" t t))
+ ((eq (preceding-char) ?\b) (replace-match "\\b" t t))
+ ((eq (preceding-char) ?\f) (replace-match "\\f" t t))
+ ((eq (preceding-char) ?\n)
+ (replace-match (if (or (not multi-line) (eobp))
+ "\\n"
+ "\\n\"\n\"")
+ t t))
+ ((eq (preceding-char) ?\t) (replace-match "\\t" t t))
+ ((eq (preceding-char) ?\\) (replace-match "\\\\" t t))))
+ (goto-char (point-min))
+ (if prefix (insert prefix " "))
+ (insert (if multi-line "\"\"\n\"" "\""))
+ (goto-char (point-max))
+ (insert "\"")
+ (if prefix (insert "\n"))
+ (if obsolete
+ (progn
+ (goto-char (point-min))
+ (while (not (eobp))
+ (or (eq (following-char) ?\n) (insert "#~ "))
+ (search-forward "\n"))))
+ (buffer-string))))
+
+(defun po-get-msgid (kill)
+ "Extract and return the unquoted msgid string.
+If KILL, then add the unquoted string to the kill ring."
+ (let ((string (po-extract-unquoted (current-buffer)
+ po-start-of-msgid po-start-of-msgstr)))
+ (if kill (po-kill-new string))
+ string))
+
+(defun po-get-msgstr (kill)
+ "Extract and return the unquoted msgstr string.
+If KILL, then add the unquoted string to the kill ring."
+ (let ((string (po-extract-unquoted (current-buffer)
+ po-start-of-msgstr po-end-of-entry)))
+ (if kill (po-kill-new string))
+ string))
+
+(defun po-set-msgid (form)
+ "Replace the current msgid, using FORM to get a string.
+Evaluating FORM should insert the wanted string in the current buffer. If
+FORM is itself a string, then this string is used for insertion. The string
+is properly requoted before the replacement occurs.
+
+Returns `nil' if the buffer has not been modified, for if the new msgid
+described by FORM is merely identical to the msgid already in place."
+ (let ((string (po-eval-requoted form "msgid" (eq po-entry-type 'obsolete))))
+ (save-excursion
+ (goto-char po-start-of-entry)
+ (re-search-forward po-any-msgid-regexp po-start-of-msgstr)
+ (and (not (string-equal (po-buffer-substring (match-beginning 0)
+ (match-end 0))
+ string))
+ (let ((buffer-read-only po-read-only))
+ (replace-match string t t)
+ (goto-char po-start-of-msgid)
+ (po-find-span-of-entry)
+ t)))))
+
+(defun po-set-msgstr (form)
+ "Replace the current msgstr, using FORM to get a string.
+Evaluating FORM should insert the wanted string in the current buffer. If
+FORM is itself a string, then this string is used for insertion. The string
+is properly requoted before the replacement occurs.
+
+Returns `nil' if the buffer has not been modified, for if the new msgstr
+described by FORM is merely identical to the msgstr already in place."
+ (let ((string (po-eval-requoted form "msgstr" (eq po-entry-type 'obsolete))))
+ (save-excursion
+ (goto-char po-start-of-entry)
+ (re-search-forward po-any-msgstr-regexp po-end-of-entry)
+ (and (not (string-equal (po-buffer-substring (match-beginning 0)
+ (match-end 0))
+ string))
+ (let ((buffer-read-only po-read-only))
+ (po-decrease-type-counter)
+ (replace-match string t t)
+ (goto-char po-start-of-msgid)
+ (po-find-span-of-entry)
+ (po-increase-type-counter)
+ t)))))
+
+(defun po-kill-ring-save-msgstr ()
+ "Push the msgstr string from current entry on the kill ring."
+ (interactive)
+ (po-find-span-of-entry)
+ (po-get-msgstr t))
+
+(defun po-kill-msgstr ()
+ "Empty the msgstr string from current entry, pushing it on the kill ring."
+ (interactive)
+ (po-kill-ring-save-msgstr)
+ (po-set-msgstr ""))
+
+(defun po-yank-msgstr ()
+ "Replace the current msgstr string by the top of the kill ring."
+ (interactive)
+ (po-find-span-of-entry)
+ (po-set-msgstr (if (eq last-command 'yank) '(yank-pop 1) '(yank)))
+ (setq this-command 'yank))
+
+(defun po-fade-out-entry ()
+ "Mark an active entry as fuzzy; obsolete a fuzzy or untranslated entry;
+or completely delete an obsolete entry, saving its msgstr on the kill ring."
+ (interactive)
+ (po-find-span-of-entry)
+
+ (cond ((eq po-entry-type 'translated)
+ (po-decrease-type-counter)
+ (po-add-attribute "fuzzy")
+ (po-current-entry)
+ (po-increase-type-counter))
+
+ ((or (eq po-entry-type 'fuzzy)
+ (eq po-entry-type 'untranslated))
+ (if (yes-or-no-p (_"Should I really obsolete this entry? "))
+ (progn
+ (po-decrease-type-counter)
+ (save-excursion
+ (save-restriction
+ (narrow-to-region po-start-of-entry po-end-of-entry)
+ (let ((buffer-read-only po-read-only))
+ (goto-char (point-min))
+ (skip-chars-forward "\n")
+ (while (not (eobp))
+ (insert "#~ ")
+ (search-forward "\n")))))
+ (po-current-entry)
+ (po-increase-type-counter)))
+ (message ""))
+
+ ((and (eq po-entry-type 'obsolete)
+ (po-check-for-pending-edit po-start-of-msgid)
+ (po-check-for-pending-edit po-start-of-msgstr))
+ (po-decrease-type-counter)
+ (po-update-mode-line-string)
+ (po-get-msgstr t)
+ (let ((buffer-read-only po-read-only))
+ (delete-region po-start-of-entry po-end-of-entry))
+ (goto-char po-start-of-entry)
+ (if (re-search-forward po-any-msgstr-regexp nil t)
+ (goto-char (match-beginning 0))
+ (re-search-backward po-any-msgstr-regexp nil t))
+ (po-current-entry)
+ (message ""))))
+
+;;; Killing and yanking comments.
+
+(defvar po-active-comment-regexp
+ "^\\(#\n\\|# .*\n\\)+"
+ "Regexp matching the whole editable comment part of an active entry.")
+
+(defvar po-obsolete-comment-regexp
+ "^\\(#~? #\n\\|#~? # .*\n\\)+"
+ "Regexp matching the whole editable comment part of an obsolete entry.")
+
+(defun po-get-comment (kill-flag)
+ "Extract and return the editable comment string, uncommented.
+If KILL-FLAG, then add the unquoted comment to the kill ring."
+ (let ((buffer (current-buffer))
+ (obsolete (eq po-entry-type 'obsolete)))
+ (save-excursion
+ (goto-char po-start-of-entry)
+ (if (re-search-forward (if obsolete po-obsolete-comment-regexp
+ po-active-comment-regexp)
+ po-end-of-entry t)
+ (po-with-temp-buffer
+ (insert-buffer-substring buffer (match-beginning 0) (match-end 0))
+ (goto-char (point-min))
+ (while (not (eobp))
+ (if (looking-at (if obsolete "#~? # ?" "#~? ?"))
+ (replace-match "" t t))
+ (forward-line 1))
+ (and kill-flag (copy-region-as-kill (point-min) (point-max)))
+ (buffer-string))
+ ""))))
+
+(defun po-set-comment (form)
+ "Using FORM to get a string, replace the current editable comment.
+Evaluating FORM should insert the wanted string in the current buffer.
+If FORM is itself a string, then this string is used for insertion.
+The string is properly recommented before the replacement occurs."
+ (let ((obsolete (eq po-entry-type 'obsolete))
+ string)
+ (po-with-temp-buffer
+ (if (stringp form)
+ (insert form)
+ (push-mark)
+ (eval form))
+ (if (not (or (bobp) (= (preceding-char) ?\n)))
+ (insert "\n"))
+ (goto-char (point-min))
+ (while (not (eobp))
+ (insert (if (= (following-char) ?\n)
+ (if obsolete "#~ #" "#")
+ (if obsolete "#~ # " "# ")))
+ (search-forward "\n"))
+ (setq string (buffer-string)))
+ (goto-char po-start-of-entry)
+ (if (re-search-forward
+ (if obsolete po-obsolete-comment-regexp po-active-comment-regexp)
+ po-end-of-entry t)
+ (if (not (string-equal (po-buffer-substring (match-beginning 0)
+ (match-end 0))
+ string))
+ (let ((buffer-read-only po-read-only))
+ (replace-match string t t)))
+ (skip-chars-forward " \t\n")
+ (let ((buffer-read-only po-read-only))
+ (insert string))))
+ (po-current-entry))
+
+(defun po-kill-ring-save-comment ()
+ "Push the msgstr string from current entry on the kill ring."
+ (interactive)
+ (po-find-span-of-entry)
+ (po-get-comment t))
+
+(defun po-kill-comment ()
+ "Empty the msgstr string from current entry, pushing it on the kill ring."
+ (interactive)
+ (po-kill-ring-save-comment)
+ (po-set-comment "")
+ (po-redisplay))
+
+(defun po-yank-comment ()
+ "Replace the current comment string by the top of the kill ring."
+ (interactive)
+ (po-find-span-of-entry)
+ (po-set-comment (if (eq last-command 'yank) '(yank-pop 1) '(yank)))
+ (setq this-command 'yank)
+ (po-redisplay))
+
+;;; Editing management and submode.
+
+;; In a string edit buffer, BACK-POINTER points to one of the slots of the
+;; list EDITED-FIELDS kept in the PO buffer. See its description elsewhere.
+;; Reminder: slots have the form (ENTRY-MARKER EDIT-BUFFER OVERLAY-INFO).
+
+(defvar po-subedit-back-pointer)
+
+(defun po-clean-out-killed-edits ()
+ "From EDITED-FIELDS, clean out any edit having a killed edit buffer."
+ (let ((cursor po-edited-fields))
+ (while cursor
+ (let ((slot (car cursor)))
+ (setq cursor (cdr cursor))
+ (if (buffer-name (nth 1 slot))
+ nil
+ (let ((overlay (nth 2 slot)))
+ (and overlay (po-dehighlight overlay)))
+ (setq po-edited-fields (delete slot po-edited-fields)))))))
+
+(defun po-check-all-pending-edits ()
+ "Resume any pending edit. Return nil if some remains."
+ (po-clean-out-killed-edits)
+ (or (null po-edited-fields)
+ (let ((slot (car po-edited-fields)))
+ (goto-char (nth 0 slot))
+ (pop-to-buffer (nth 1 slot))
+ (let ((overlay (nth 2 slot)))
+ (and overlay (po-rehighlight overlay)))
+ (message po-subedit-message)
+ nil)))
+
+(defun po-check-for-pending-edit (position)
+ "Resume any pending edit at POSITION. Return nil if such edit exists."
+ (po-clean-out-killed-edits)
+ (let ((marker (make-marker)))
+ (set-marker marker position)
+ (let ((slot (assoc marker po-edited-fields)))
+ (if slot
+ (progn
+ (goto-char marker)
+ (pop-to-buffer (nth 1 slot))
+ (let ((overlay (nth 2 slot)))
+ (and overlay (po-rehighlight overlay)))
+ (message po-subedit-message)))
+ (not slot))))
+
+(defun po-edit-out-full ()
+ "Get out of PO mode, leaving PO file buffer in fundamental mode."
+ (interactive)
+ (if (and (po-check-all-pending-edits)
+ (yes-or-no-p (_"Should I let you edit the whole PO file? ")))
+ (progn
+ (setq buffer-read-only po-read-only)
+ (fundamental-mode)
+ (message (_"Type `M-x po-mode RET' once done")))))
+
+(defvar po-subedit-mode-map nil
+ "Keymap while editing a PO mode entry (or the full PO file).")
+(if po-subedit-mode-map
+ ()
+ (setq po-subedit-mode-map (make-sparse-keymap))
+ (define-key po-subedit-mode-map "\C-c\C-a" 'po-subedit-cycle-auxiliary)
+ (define-key po-subedit-mode-map "\C-c\C-c" 'po-subedit-exit)
+ (define-key po-subedit-mode-map "\C-c\C-k" 'po-subedit-abort))
+
+(defun po-subedit-abort ()
+ "Exit the subedit buffer, merely discarding its contents."
+ (interactive)
+ (let* ((edit-buffer (current-buffer))
+ (back-pointer po-subedit-back-pointer)
+ (marker (nth 0 back-pointer))
+ (overlay (nth 2 back-pointer))
+ (buffer (marker-buffer marker)))
+ (if (null buffer)
+ (error (_"Corresponding PO buffer does not exist anymore"))
+ (or (one-window-p) (delete-window))
+ (switch-to-buffer buffer)
+ (goto-char marker)
+ (and overlay (po-dehighlight overlay))
+ (kill-buffer edit-buffer)
+ (setq po-edited-fields (delete back-pointer po-edited-fields)))))
+
+(defun po-subedit-exit ()
+ "Exit the subedit buffer, replacing the string in the PO buffer."
+ (interactive)
+ (goto-char (point-max))
+ (skip-chars-backward " \t\n")
+ (if (eq (preceding-char) ?<)
+ (delete-region (1- (point)) (point-max)))
+ (let ((string (buffer-string)))
+ (po-subedit-abort)
+ (po-find-span-of-entry)
+ (cond ((= (point) po-start-of-msgid)
+ (po-set-comment string)
+ (po-redisplay))
+ ((= (point) po-start-of-msgstr)
+ (let ((replaced (po-set-msgstr string)))
+ (if (and replaced
+ po-auto-fuzzy-on-edit
+ (eq po-entry-type 'translated))
+ (progn
+ (po-decrease-type-counter)
+ (po-add-attribute "fuzzy")
+ (po-current-entry)
+ (po-increase-type-counter)))))
+ (t (debug)))))
+
+(defun po-edit-string (string type expand-tabs)
+ "Prepare a pop up buffer for editing STRING, which is of a given TYPE.
+TYPE may be 'comment or 'msgstr. If EXPAND-TABS, expand tabs to spaces.
+Run functions on po-subedit-mode-hook."
+ (let ((marker (make-marker)))
+ (set-marker marker (cond ((eq type 'comment) po-start-of-msgid)
+ ((eq type 'msgstr) po-start-of-msgstr)))
+ (if (po-check-for-pending-edit marker)
+ (let ((edit-buffer (generate-new-buffer
+ (concat "*" (buffer-name) "*")))
+ (buffer (current-buffer))
+ overlay slot)
+ (if (and (eq type 'msgstr) po-highlighting)
+ ;; ;; Try showing all of msgid in the upper window while editing.
+ ;; (goto-char (1- po-start-of-msgstr))
+ ;; (recenter -1)
+ (save-excursion
+ (goto-char po-start-of-entry)
+ (re-search-forward po-any-msgid-regexp nil t)
+ (let ((end (1- (match-end 0))))
+ (goto-char (match-beginning 0))
+ (re-search-forward "msgid +" nil t)
+ (setq overlay (po-create-overlay))
+ (po-highlight overlay (point) end buffer))))
+ (setq slot (list marker edit-buffer overlay)
+ po-edited-fields (cons slot po-edited-fields))
+ (pop-to-buffer edit-buffer)
+ (make-local-variable 'po-subedit-back-pointer)
+ (setq po-subedit-back-pointer slot)
+ (erase-buffer)
+ (insert string "<")
+ (goto-char (point-min))
+ (and expand-tabs (setq indent-tabs-mode nil))
+ (use-local-map po-subedit-mode-map)
+ (run-hooks 'po-subedit-mode-hook)
+ (message po-subedit-message)))))
+
+(defun po-edit-comment ()
+ "Use another window to edit the current translator comment."
+ (interactive)
+ (po-find-span-of-entry)
+ (po-edit-string (po-get-comment nil) 'comment nil))
+
+(defun po-edit-msgstr ()
+ "Use another window to edit the current msgstr."
+ (interactive)
+ (po-find-span-of-entry)
+ (po-edit-string (if (and po-auto-edit-with-msgid
+ (eq po-entry-type 'untranslated))
+ (po-get-msgid nil)
+ (po-get-msgstr nil))
+ 'msgstr
+ t))
+
+;;; String normalization and searching.
+
+(defun po-normalize-old-style (explain)
+ "Normalize old gettext style fields using K&R C multiline string syntax.
+To minibuffer messages sent while normalizing, add the EXPLAIN string."
+ (let ((here (point-marker))
+ (counter 0)
+ (buffer-read-only po-read-only))
+ (goto-char (point-min))
+ (message (_"Normalizing %d, %s") counter explain)
+ (while (re-search-forward
+ "\\(^#?[ \t]*msg\\(id\\|str\\)[ \t]*\"\\|[^\" \t][ \t]*\\)\\\\\n"
+ nil t)
+ (if (= (% counter 10) 0)
+ (message (_"Normalizing %d, %s") counter explain))
+ (replace-match "\\1\"\n\"" t nil)
+ (setq counter (1+ counter)))
+ (goto-char here)
+ (message (_"Normalizing %d...done") counter)))
+
+(defun po-normalize-field (field explain)
+ "Normalize FIELD of all entries. FIELD is either the symbol msgid or msgstr.
+To minibuffer messages sent while normalizing, add the EXPLAIN string."
+ (let ((here (point-marker))
+ (counter 0))
+ (goto-char (point-min))
+ (while (re-search-forward po-any-msgstr-regexp nil t)
+ (if (= (% counter 10) 0)
+ (message (_"Normalizing %d, %s") counter explain))
+ (goto-char (match-beginning 0))
+ (po-find-span-of-entry)
+ (cond ((eq field 'msgid) (po-set-msgid (po-get-msgid nil)))
+ ((eq field 'msgstr) (po-set-msgstr (po-get-msgstr nil))))
+ (goto-char po-end-of-entry)
+ (setq counter (1+ counter)))
+ (goto-char here)
+ (message (_"Normalizing %d...done") counter)))
+
+;; Normalize, but the British way! :-)
+(defsubst po-normalise () (po-normalize))
+
+(defun po-normalize ()
+ "Normalize all entries in the PO file."
+ (interactive)
+ (po-normalize-old-style (_"pass 1/3"))
+ (po-normalize-field t (_"pass 2/3"))
+ (po-normalize-field nil (_"pass 3/3"))
+ ;; The last PO file entry has just been processed.
+ (if (not (= po-end-of-entry (point-max)))
+ (let ((buffer-read-only po-read-only))
+ (kill-region po-end-of-entry (point-max))))
+ ;; A bizarre format might have fooled the counters, so recompute
+ ;; them to make sure their value is dependable.
+ (po-compute-counters nil))
+
+;;; Multiple PO files.
+
+(defun po-show-auxiliary-list ()
+ "Echo the current auxiliary list in the message area."
+ (if po-auxiliary-list
+ (let ((cursor po-auxiliary-cursor)
+ string)
+ (while cursor
+ (setq string (concat string (if string " ") (car (car cursor)))
+ cursor (cdr cursor)))
+ (setq cursor po-auxiliary-list)
+ (while (not (eq cursor po-auxiliary-cursor))
+ (setq string (concat string (if string " ") (car (car cursor)))
+ cursor (cdr cursor)))
+ (message string))
+ (message (_"No auxiliary files."))))
+
+(defun po-consider-as-auxiliary ()
+ "Add the current PO file to the list of auxiliary files."
+ (interactive)
+ (if (member (list buffer-file-name) po-auxiliary-list)
+ nil
+ (setq po-auxiliary-list
+ (nconc po-auxiliary-list (list (list buffer-file-name))))
+ (or po-auxiliary-cursor
+ (setq po-auxiliary-cursor po-auxiliary-list)))
+ (po-show-auxiliary-list))
+
+(defun po-ignore-as-auxiliary ()
+ "Delete the current PO file from the list of auxiliary files."
+ (interactive)
+ (setq po-auxiliary-list (delete (list buffer-file-name) po-auxiliary-list)
+ po-auxiliary-cursor po-auxiliary-list)
+ (po-show-auxiliary-list))
+
+(defun po-seek-equivalent-translation (name string)
+ "Search a PO file NAME for a `msgid' STRING having a non-empty `msgstr'.
+STRING is the full quoted msgid field, including the `msgid' keyword. When
+found, display the file over the current window, with the `msgstr' field
+possibly highlighted, the cursor at start of msgid, then return `t'.
+Otherwise, move nothing, and just return `nil'."
+ (let ((current (current-buffer))
+ (buffer (find-file-noselect name)))
+ (set-buffer buffer)
+ (let ((start (point))
+ found)
+ (goto-char (point-min))
+ (while (and (not found) (search-forward string nil t))
+ ;; Screen out longer `msgid's.
+ (if (looking-at "^msgstr ")
+ (progn
+ (po-find-span-of-entry)
+ ;; Ignore an untranslated entry.
+ (or (string-equal
+ (buffer-substring po-start-of-msgstr po-end-of-entry)
+ "msgstr \"\"\n")
+ (setq found t)))))
+ (if found
+ (progn
+ (switch-to-buffer buffer)
+ (po-find-span-of-entry)
+ (if po-highlighting
+ (progn
+ (goto-char po-start-of-entry)
+ (re-search-forward po-any-msgstr-regexp nil t)
+ (let ((end (1- (match-end 0))))
+ (goto-char (match-beginning 0))
+ (re-search-forward "msgstr +" nil t)
+ ;; FIXME:
+ (po-highlight (po-create-overlay) (point) end))))
+ (goto-char po-start-of-msgid))
+ (goto-char start)
+ (po-find-span-of-entry)
+ (select-buffer current))
+ found)))
+
+(defun po-cycle-auxiliary ()
+ "Select the next auxiliary file having an entry with same `msgid'."
+ (interactive)
+ (po-find-span-of-entry)
+ (if po-auxiliary-list
+ (let ((string (buffer-substring po-start-of-msgid po-start-of-msgstr))
+ (cursor po-auxiliary-cursor)
+ found name)
+ (while (and (not found) cursor)
+ (setq name (car (car cursor)))
+ (if (and (not (string-equal buffer-file-name name))
+ (po-seek-equivalent-translation name string))
+ (setq found t
+ po-auxiliary-cursor cursor))
+ (setq cursor (cdr cursor)))
+ (setq cursor po-auxiliary-list)
+ (while (and (not found) cursor)
+ (setq name (car (car cursor)))
+ (if (and (not (string-equal buffer-file-name name))
+ (po-seek-equivalent-translation name string))
+ (setq found t
+ po-auxiliary-cursor cursor))
+ (setq cursor (cdr cursor)))
+ (or found (message (_"No other translation found")))
+ found)))
+
+(defun po-subedit-cycle-auxiliary ()
+ "Cycle auxiliary file, but from the translation edit buffer."
+ (interactive)
+ (if po-buffer-of-edited-entry
+ (let ((buffer (current-buffer)))
+ (pop-to-buffer po-buffer-of-edited-entry)
+ (po-cycle-auxiliary)
+ (pop-to-buffer buffer))
+ (error (_"Not editing a PO file entry"))))
+
+(defun po-select-auxiliary ()
+ "Select one of the available auxiliary files and locate an equivalent
+entry. If an entry having the same `msgid' cannot be found, merely select
+the file without moving its cursor."
+ (interactive)
+ (po-find-span-of-entry)
+ (if po-auxiliary-list
+ (let ((string (buffer-substring po-start-of-msgid po-start-of-msgstr))
+ (name (car (assoc (completing-read (_"Which auxiliary file? ")
+ po-auxiliary-list nil t)
+ po-auxiliary-list))))
+ (po-consider-as-auxiliary)
+ (or (po-seek-equivalent-translation name string)
+ (find-file name)))))
+
+;;; Original program sources as context.
+
+(defun po-show-source-path ()
+ "Echo the current source search path in the message area."
+ (if po-search-path
+ (let ((cursor po-search-path)
+ string)
+ (while cursor
+ (setq string (concat string (if string " ") (car (car cursor)))
+ cursor (cdr cursor)))
+ (message string))
+ (message (_"Empty source path."))))
+
+(defun po-consider-source-path (directory)
+ "Add a given DIRECTORY, requested interactively, to the source search path."
+ (interactive "DDirectory for search path: ")
+ (setq po-search-path (cons (list (if (string-match "/$" directory)
+ directory
+ (concat directory "/")))
+ po-search-path))
+ (setq po-reference-check 0)
+ (po-show-source-path))
+
+(defun po-ignore-source-path ()
+ "Delete a directory, selected with completion, from the source search path."
+ (interactive)
+ (setq po-search-path
+ (delete (list (completing-read (_"Directory to remove? ")
+ po-search-path nil t))
+ po-search-path))
+ (setq po-reference-check 0)
+ (po-show-source-path))
+
+(defun po-ensure-source-references ()
+ "Extract all references into a list, with paths resolved, if necessary."
+ (po-find-span-of-entry)
+ (if (= po-start-of-entry po-reference-check)
+ ()
+ (setq po-reference-alist nil)
+ (save-excursion
+ (goto-char po-start-of-entry)
+ (if (re-search-forward "^#:" po-start-of-msgid t)
+ (while (looking-at "\\(\n#:\\)? *\\([^: ]+\\):\\([0-9]+\\)")
+ (goto-char (match-end 0))
+ (let* ((name (po-buffer-substring (match-beginning 2)
+ (match-end 2)))
+ (line (po-buffer-substring (match-beginning 3)
+ (match-end 3)))
+ (path po-search-path)
+ file)
+ (while (and (progn (setq file (concat (car (car path)) name))
+ (not (file-exists-p file)))
+ path)
+ (setq path (cdr path)))
+ (if path
+ (setq po-reference-alist
+ (cons (list (concat file ":" line)
+ file
+ (string-to-int line))
+ po-reference-alist)))))))
+ (setq po-reference-alist (nreverse po-reference-alist)
+ po-reference-cursor po-reference-alist
+ po-reference-check po-start-of-entry)))
+
+(defun po-show-source-context (triplet)
+ "Show the source context given a TRIPLET which is (PROMPT FILE LINE)."
+ (find-file-other-window (car (cdr triplet)))
+ (goto-line (car (cdr (cdr triplet))))
+ (other-window 1)
+ (let ((maximum 0)
+ position
+ (cursor po-reference-alist))
+ (while (not (eq triplet (car cursor)))
+ (setq maximum (1+ maximum)
+ cursor (cdr cursor)))
+ (setq position (1+ maximum)
+ po-reference-cursor cursor)
+ (while cursor
+ (setq maximum (1+ maximum)
+ cursor (cdr cursor)))
+ (message (_"Displaying %d/%d: \"%s\"") position maximum (car triplet))))
+
+(defun po-cycle-source-reference ()
+ "Display some source context for the current entry.
+If the command is repeated many times in a row, cycle through contexts."
+ (interactive)
+ (po-ensure-source-references)
+ (if po-reference-cursor
+ (po-show-source-context
+ (car (if (eq last-command 'po-cycle-source-reference)
+ (or (cdr po-reference-cursor) po-reference-alist)
+ po-reference-cursor)))
+ (error (_"No resolved source references"))))
+
+(defun po-select-source-reference ()
+ "Select one of the available source contexts for the current entry."
+ (interactive)
+ (po-ensure-source-references)
+ (if po-reference-alist
+ (po-show-source-context
+ (assoc
+ (completing-read (_"Which source context? ") po-reference-alist nil t)
+ po-reference-alist))
+ (error (_"No resolved source references"))))
+
+;;; Program sources strings though tags table.
+
+;;; C mode.
+
+;;; A few long string cases (submitted by Ben Pfaff).
+
+;; #define string "This is a long string " \
+;; "that is continued across several lines " \
+;; "in a macro in order to test \\ quoting\\" \
+;; "\\ with goofy strings.\\"
+
+;; char *x = "This is just an ordinary string "
+;; "continued across several lines without needing "
+;; "to use \\ characters at end-of-line.";
+
+;; char *y = "Here is a string continued across \
+;; several lines in the manner that was sanctioned \
+;; in K&R C compilers and still works today, \
+;; even though the method used above is more esthetic.";
+
+;;; End of long string cases.
+
+(defun po-find-c-string (keywords)
+ "Find the next C string, excluding those marked by any of KEYWORDS.
+Returns (START . END) for the found string, or (nil . nil) if none found."
+ (let (start end)
+ (while (and (not start)
+ (re-search-forward "\\([\"']\\|/\\*\\|//\\)" nil t))
+ (cond ((= (preceding-char) ?*)
+ ;; Disregard comments.
+ (search-forward "*/"))
+
+ ((= (preceding-char) ?/)
+ ;; Disregard C++ comments.
+ (end-of-line)
+ (forward-char 1))
+
+ ((= (preceding-char) ?\')
+ ;; Disregard character constants.
+ (forward-char (if (= (following-char) ?\\) 3 2)))
+
+ ((save-excursion
+ (beginning-of-line)
+ (looking-at "^# *\\(include\\|line\\)"))
+ ;; Disregard lines being #include or #line directives.
+ (end-of-line))
+
+ ;; Else, find the end of the (possibly concatenated) string.
+ (t (setq start (1- (point))
+ end nil)
+ (while (not end)
+ (cond ((= (following-char) ?\")
+ (if (looking-at "\"[ \t\n\\\\]*\"")
+ (goto-char (match-end 0))
+ (forward-char 1)
+ (setq end (point))))
+ ((= (following-char) ?\\) (forward-char 2))
+ (t (skip-chars-forward "^\"\\\\"))))
+
+ ;; Check before string for keyword and opening parenthesis.
+ (goto-char start)
+ (skip-chars-backward " \n\t")
+ (if (= (preceding-char) ?\()
+ (progn
+ (backward-char 1)
+ (skip-chars-backward " \n\t")
+ (let ((end-keyword (point)))
+ (skip-chars-backward "_A-Za-z0-9")
+ (if (member (list (po-buffer-substring (point)
+ end-keyword))
+ keywords)
+
+ ;; Disregard already marked strings.
+ (progn
+ (goto-char end)
+ (setq start nil
+ end nil)))))))))
+
+ ;; Return the found string, if any.
+ (cons start end)))
+
+(defun po-mark-c-string (start end keyword)
+ "Mark the C string, from START to END, with KEYWORD.
+Return the adjusted value for END."
+ (goto-char end)
+ (insert ")")
+ (goto-char start)
+ (insert keyword)
+ (if (not (string-equal keyword "_"))
+ (progn (insert " ") (setq end (1+ end))))
+ (insert "(")
+ (+ end 2 (length keyword)))
+
+;;; Emacs LISP mode.
+
+(defun po-find-emacs-lisp-string (keywords)
+ "Find the next Emacs LISP string, excluding those marked by any of KEYWORDS.
+Returns (START . END) for the found string, or (nil . nil) if none found."
+ (let (start end)
+ (while (and (not start)
+ (re-search-forward "[;\"?]" nil t))
+
+ (cond ((= (preceding-char) ?\;)
+ ;; Disregard comments.
+ (search-forward "\n"))
+
+ ((= (preceding-char) ?\?)
+ ;; Disregard character constants.
+ (forward-char (if (= (following-char) ?\\) 2 1)))
+
+ ;; Else, find the end of the string.
+ (t (setq start (1- (point)))
+ (while (not (= (following-char) ?\"))
+ (skip-chars-forward "^\"\\\\")
+ (if (= (following-char) ?\\) (forward-char 2)))
+ (forward-char 1)
+ (setq end (point))
+
+ ;; Check before string for keyword and opening parenthesis.
+ (goto-char start)
+ (skip-chars-backward " \n\t")
+ (let ((end-keyword (point)))
+ (skip-chars-backward "-_A-Za-z0-9")
+ (if (and (= (preceding-char) ?\()
+ (member (list (po-buffer-substring (point)
+ end-keyword))
+ keywords))
+
+ ;; Disregard already marked strings.
+ (progn
+ (goto-char end)
+ (setq start nil
+ end nil)))))))
+
+ ;; Return the found string, if any.
+ (cons start end)))
+
+(defun po-mark-emacs-lisp-string (start end keyword)
+ "Mark the Emacs LISP string, from START to END, with KEYWORD.
+Return the adjusted value for END."
+ (goto-char end)
+ (insert ")")
+ (goto-char start)
+ (insert "(" keyword)
+ (if (not (string-equal keyword "_"))
+ (progn (insert " ") (setq end (1+ end))))
+ (+ end 2 (length keyword)))
+
+;;; Processing generic to all programming modes.
+
+(eval-and-compile
+ (autoload 'visit-tags-table-buffer "etags"))
+
+(defun po-tags-search (restart)
+ "Find an unmarked translatable string through all files in tags table.
+Disregard some simple strings which are most probably non-translatable.
+With prefix argument, restart search at first file."
+ (interactive "P")
+
+ ;; Take care of restarting the search if necessary.
+ (if restart (setq po-next-file-list nil))
+
+ ;; Loop doing things until an interesting string is found.
+ (let ((keywords po-keywords)
+ found buffer start
+ (end po-string-end))
+ (while (not found)
+
+ ;; Reinitialize the source file list if necessary.
+ (if (not po-next-file-list)
+ (progn
+ (setq po-next-file-list
+ (save-excursion
+ (visit-tags-table-buffer)
+ (copy-sequence (tags-table-files))))
+ (or po-next-file-list (error (_"No files to process")))
+ (setq end nil)))
+
+ ;; Try finding a string after resuming the search position.
+ (message (_"Scanning %s...") (car po-next-file-list))
+ (save-excursion
+ (setq buffer (find-file-noselect (car po-next-file-list)))
+ (set-buffer buffer)
+ (goto-char (or end (point-min)))
+
+ (cond ((member mode-name '("C" "C++"))
+ (let ((pair (po-find-c-string keywords)))
+ (setq start (car pair)
+ end (cdr pair))))
+ ((string-equal mode-name "Emacs-Lisp")
+ (let ((pair (po-find-emacs-lisp-string keywords)))
+ (setq start (car pair)
+ end (cdr pair))))
+ (t (message (_"Unknown source mode for PO mode, skipping..."))
+ (setq start nil
+ end nil))))
+
+ ;; Advance to next file if no string was found.
+ (if (not start)
+ (progn
+ (setq po-next-file-list (cdr po-next-file-list))
+ (if po-next-file-list
+ (setq end nil)
+ (setq po-string-end nil)
+ (and po-highlighting (po-dehighlight po-marking-overlay))
+ (error (_"All files processed"))))
+
+ ;; Push the string just found string into a work buffer for study.
+ (po-with-temp-buffer
+ (insert (po-extract-unquoted buffer start end))
+ (goto-char (point-min))
+
+ ;; Do not disregard if at least three letters in a row.
+ (if (re-search-forward "[A-Za-z][A-Za-z][A-Za-z]" nil t)
+ (setq found t)
+
+ ;; Disregard if two letters, and more punctuations than letters.
+ (if (re-search-forward "[A-Za-z][A-Za-z]" nil t)
+ (let ((total (buffer-size)))
+ (goto-char (point-min))
+ (while (re-search-forward "[A-Za-z]+" nil t)
+ (replace-match "" t t))
+ (if (< (* 2 (buffer-size)) total)
+ (setq found t))))
+
+ ;; Disregard if single letters or no letters at all.
+ ))))
+
+ ;; Ensure the string is being displayed.
+
+ (if (one-window-p t) (split-window) (other-window 1))
+ (switch-to-buffer buffer)
+ (goto-char start)
+ (or (pos-visible-in-window-p start) (recenter '(nil)))
+ (if (pos-visible-in-window-p end)
+ (goto-char end)
+ (goto-char end)
+ (recenter -1))
+ (other-window 1)
+ (and po-highlighting (po-highlight po-marking-overlay start end buffer))
+
+ ;; Save the string for later commands.
+ (message (_"Scanning %s...done") (car po-next-file-list))
+ (setq po-string-start start
+ po-string-end end)))
+
+(defun po-mark-found-string (keyword)
+ "Mark last found string in program sources as translatable, using KEYWORD."
+ (and po-highlighting (po-dehighlight po-marking-overlay))
+ (let ((buffer (find-file-noselect (car po-next-file-list)))
+ (start po-string-start)
+ (end po-string-end)
+ line string)
+
+ ;; Mark string in program sources.
+ (setq string (po-extract-unquoted buffer start end))
+ (save-excursion
+ (set-buffer buffer)
+ (setq line (count-lines (point-min) start)
+ end (cond ((member mode-name '("C" "C++"))
+ (po-mark-c-string start end keyword))
+ ((string-equal mode-name "Emacs-Lisp")
+ (po-mark-emacs-lisp-string start end keyword))
+ (t (error (_"Cannot mark in unknown source mode"))))))
+ (setq po-string-end end)
+
+ ;; Add PO file entry.
+ (let ((buffer-read-only po-read-only))
+ (goto-char (point-max))
+ (insert "\n" (format "#: %s:%d\n" (car po-next-file-list) line))
+ (save-excursion
+ (insert (po-eval-requoted string "msgid" nil) "msgstr \"\"\n"))
+ (setq po-untranslated-counter (1+ po-untranslated-counter))
+ (po-update-mode-line-string))))
+
+(defun po-mark-translatable ()
+ "Mark last found string in program sources as translatable, using `_'."
+ (interactive)
+ (if (and po-string-start po-string-end)
+ (progn
+ (po-mark-found-string "_")
+ (setq po-string-start nil))
+ (error (_"No such string"))))
+
+(defun po-select-mark-and-mark (arg)
+ "Mark last found string in program sources as translatable, ask for keywoard,
+using completion. With prefix argument, just ask the name of a preferred
+keyword for subsequent commands, also added to possible completions."
+ (interactive "P")
+ (if arg
+ (let ((keyword (list (read-from-minibuffer (_"Keyword: ")))))
+ (setq po-keywords (cons keyword (delete keyword po-keywords))))
+ (if (and po-string-start po-string-end)
+ (let* ((default (car (car po-keywords)))
+ (keyword (completing-read (format (_"Mark with keywoard? [%s] ")
+ default)
+ po-keywords nil t )))
+ (if (string-equal keyword "") (setq keyword default))
+ (po-mark-found-string keyword)
+ (setq po-string-start nil))
+ (error (_"No such string")))))
+
+;;; Miscellaneous features.
+
+(defun po-help ()
+ "Provide an help window for PO mode."
+ (interactive)
+ (po-with-temp-buffer
+ (insert po-help-display-string)
+ (goto-char (point-min))
+ (save-window-excursion
+ (switch-to-buffer (current-buffer))
+ (delete-other-windows)
+ (message (_"Type any character to continue"))
+ (po-read-event))))
+
+(defun po-undo ()
+ "Undo the last change to the PO file."
+ (interactive)
+ (let ((buffer-read-only po-read-only))
+ (undo))
+ (po-compute-counters nil))
+
+(defun po-statistics ()
+ "Say how many entries in each category, and the current position."
+ (interactive)
+ (po-compute-counters t))
+
+(defun po-validate ()
+ "Use `msgfmt' for validating the current PO file contents."
+ (interactive)
+
+ ;; If modifications were done already, change the last revision date.
+ (if (buffer-modified-p)
+ (po-replace-revision-date))
+
+ ;; This `let' is for protecting the previous value of compile-command.
+ (let ((compile-command (concat po-msgfmt-program
+ " --statistics -c -v -o /dev/null "
+ buffer-file-name)))
+ (compile compile-command)))
+
+(defun po-guess-archive-name ()
+ "Return the ideal file name for this PO file in the central archives."
+ (let (start-of-header end-of-header package version team)
+ (save-excursion
+ ;; Find the PO file header entry.
+ (goto-char (point-min))
+ (re-search-forward po-any-msgstr-regexp)
+ (setq start-of-header (match-beginning 0)
+ end-of-header (match-end 0))
+ ;; Get the package and version.
+ (goto-char start-of-header)
+ (if (re-search-forward
+ "\n\"Project-Id-Version:\\( GNU\\)? \\([^\n ]+\\) \\([^\n ]+\\)\\\\n\"$"
+ end-of-header t)
+ (setq package (buffer-substring (match-beginning 2) (match-end 2))
+ version (buffer-substring (match-beginning 3) (match-end 3))))
+ (if (or (not package) (string-equal package "PACKAGE")
+ (not version) (string-equal version "VERSION"))
+ (error (_"Project-Id-Version field does not have a proper value")))
+ ;; Get the team.
+ (goto-char start-of-header)
+ (if (re-search-forward "\n\"Language-Team:.*<\\(.*\\)@li.org>\\\\n\"$"
+ end-of-header t)
+ (setq team (buffer-substring (match-beginning 1) (match-end 1))))
+ (if (or (not team) (string-equal team "LL"))
+ (error (_"Language-Team field does not have a proper value")))
+ ;; Compose the name.
+ (concat package "-" version "." team ".po"))))
+
+(defun po-guess-team-address ()
+ "Return the team address related to this PO file."
+ (let (team)
+ (save-excursion
+ (goto-char (point-min))
+ (re-search-forward po-any-msgstr-regexp)
+ (goto-char (match-beginning 0))
+ (if (re-search-forward
+ "\n\"Language-Team: +\\(.*<\\(.*\\)@li.org>\\)\\\\n\"$"
+ (match-end 0) t)
+ (setq team (buffer-substring (match-beginning 2) (match-end 2))))
+ (if (or (not team) (string-equal team "LL"))
+ (error (_"Language-Team field does not have a proper value")))
+ (buffer-substring (match-beginning 1) (match-end 1)))))
+
+(defun po-send-mail ()
+ "Start composing a letter, possibly including the current PO file."
+ (interactive)
+ (let* ((team-flag (y-or-n-p
+ (_"\
+Write to your team? (`n' means writing to translation project) ")))
+ (address (if team-flag
+ (po-guess-team-address)
+ po-translation-project-address)))
+ (if (not (y-or-n-p (_"Include current PO file? ")))
+ (apply po-compose-mail-function address
+ (read-string (_"Subject? ")) nil)
+ (if (buffer-modified-p)
+ (error (_"The file is not even saved, you did not validate it.")))
+ (if (and (y-or-n-p (_"You validated (`V') this file, didn't you? "))
+ (or (zerop po-untranslated-counter)
+ (y-or-n-p
+ (format (_"%d entries are untranslated, include anyway? ")
+ po-untranslated-counter)))
+ (or (zerop po-fuzzy-counter)
+ (y-or-n-p
+ (format (_"%d entries are still fuzzy, include anyway? ")
+ po-fuzzy-counter)))
+ (or (zerop po-obsolete-counter)
+ (y-or-n-p
+ (format (_"%d entries are obsolete, include anyway? ")
+ po-obsolete-counter))))
+ (let ((buffer (current-buffer))
+ (name (po-guess-archive-name))
+ (transient-mark-mode nil))
+ (apply po-compose-mail-function address
+ (if team-flag
+ (read-string (_"Subject? "))
+ (format "TP-Robot %s" name))
+ nil)
+ (goto-char (point-min))
+ (re-search-forward
+ (concat "^" (regexp-quote mail-header-separator) "\n"))
+ (save-excursion
+ (insert-buffer buffer)
+ (shell-command-on-region
+ (region-beginning) (region-end)
+ (concat po-gzip-uuencode-command " " name ".gz") t))))))
+ (message ""))
+
+(defun po-confirm-and-quit ()
+ "Confirm if quit should be attempted and then, do it.
+This is a failsafe. Confirmation is asked if only the real quit would not."
+ (interactive)
+ (if (po-check-all-pending-edits)
+ (progn
+ (if (or (buffer-modified-p)
+ (> po-untranslated-counter 0)
+ (> po-fuzzy-counter 0)
+ (> po-obsolete-counter 0)
+ (y-or-n-p (_"Really quit editing this PO file? ")))
+ (po-quit))
+ (message ""))))
+
+(defun po-quit ()
+ "Save the PO file and kill buffer. However, offer validation if
+appropriate and ask confirmation if untranslated strings remain."
+ (interactive)
+ (if (po-check-all-pending-edits)
+ (let ((quit t))
+
+ ;; Offer validation of newly modified entries.
+ (if (and (buffer-modified-p)
+ (not (y-or-n-p
+ (_"File was modified; skip validation step? "))))
+ (progn
+ (message "")
+ (po-validate)
+ ;; If we knew that the validation was all successful, we should
+ ;; just quit. But since we do not know yet, as the validation
+ ;; might be asynchronous with PO mode commands, the safest is to
+ ;; stay within PO mode, even if this implies that another
+ ;; `po-quit' command will be later required to exit for true.
+ (setq quit nil)))
+
+ ;; Offer to work on untranslated entries.
+ (if (and quit
+ (or (> po-untranslated-counter 0)
+ (> po-fuzzy-counter 0)
+ (> po-obsolete-counter 0))
+ (not (y-or-n-p
+ (_"Unprocessed entries remain; quit anyway? "))))
+ (progn
+ (setq quit nil)
+ (po-auto-select-entry)))
+
+ ;; Clear message area.
+ (message "")
+
+ ;; Or else, kill buffers and quit for true.
+ (if quit
+ (progn
+ (and (buffer-modified-p) (po-replace-revision-date))
+ (save-buffer)
+ (kill-buffer (current-buffer)))))))
+
+;;; po-mode.el ends here
diff --git a/misc/tcl_gettext.c b/misc/tcl_gettext.c
new file mode 100644
index 0000000..f399ca0
--- /dev/null
+++ b/misc/tcl_gettext.c
@@ -0,0 +1,165 @@
+/* tcl_gettext - Module implementing gettext interface for Tcl.
+ Copyright (C) 1995, 1998 Free Software Foundation, Inc.
+ Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, December 1995.
+
+ 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, 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. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libintl.h>
+#include <locale.h>
+#include <string.h>
+
+/* Data for Tcl interpreter interface. */
+#include "tcl.h"
+
+/* Prototypes for local functions. */
+static int
+tcl_gettext (ClientData client_data, Tcl_Interp *interp, int argc,
+ char *argv[]);
+static int
+tcl_textdomain (ClientData client_data, Tcl_Interp *interp, int argc,
+ char *argv[]);
+static int
+tcl_bindtextdomain (ClientData client_data, Tcl_Interp *interp, int argc,
+ char *argv[]);
+
+
+/* Initialization functions. Called from the tclAppInit.c/tkAppInit.c
+ or while the dynamic loading with Tcl7.x, x>= 5. */
+int
+Gettext_Init (interp)
+ Tcl_Interp *interp;
+{
+ Tcl_CreateCommand (interp, "gettext", tcl_gettext, (ClientData) 0,
+ (Tcl_CmdDeleteProc *) NULL);
+ Tcl_CreateCommand (interp, "textdomain", tcl_textdomain, (ClientData) 0,
+ (Tcl_CmdDeleteProc *) NULL);
+ Tcl_CreateCommand (interp, "bindtextdomain", tcl_bindtextdomain,
+ (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+
+ return TCL_OK;
+}
+
+
+static int
+tcl_gettext (client_data, interp, argc, argv)
+ ClientData client_data;
+ Tcl_Interp *interp;
+ int argc;
+ char *argv[];
+{
+ const char *domainname = NULL;
+ int category = LC_MESSAGES;
+ const char *msgid;
+
+ /* The pointer which is assigned in the following statement might
+ reference an invalid part of the address space. But we don't use
+ this value before we know the pointer is correct. */
+ msgid = argv[1];
+
+ switch (argc)
+ {
+ case 4:
+#ifdef LC_CTYPE
+ if (strcmp (argv[3], "LC_CTYPE") == 0)
+ category = LC_CTYPE;
+ else
+#endif
+#ifdef LC_COLLATE
+ if (strcmp (argv[3], "LC_COLLATE") == 0)
+ category = LC_COLLATE;
+ else
+#endif
+#ifdef LC_MESSAGES
+ if (strcmp (argv[3], "LC_MESSAGES") == 0)
+ category = LC_MESSAGES;
+ else
+#endif
+#ifdef LC_MONETARY
+ if (strcmp (argv[3], "LC_MONETARY") == 0)
+ category = LC_MONETARY;
+ else
+#endif
+#ifdef LC_NUMERIC
+ if (strcmp (argv[3], "LC_NUMERIC") == 0)
+ category = LC_NUMERIC;
+ else
+#endif
+#ifdef LC_TIME
+ if (strcmp (argv[3], "LC_TIME") == 0)
+ category = LC_TIME;
+ else
+#endif
+ {
+ interp->result = gettext ("invalid third argument");
+ return TCL_ERROR;
+ }
+ /* FALLTHROUGH */
+
+ case 3:
+ domainname = argv[1];
+ msgid = argv[2];
+ /* FALLTHROUGH */
+
+ case 2:
+ interp->result = dcgettext (domainname, msgid, category);
+ break;
+
+ default:
+ interp->result = gettext ("wrong number of arguments");
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+}
+
+
+static int
+tcl_textdomain (client_data, interp, argc, argv)
+ ClientData client_data;
+ Tcl_Interp *interp;
+ int argc;
+ char *argv[];
+{
+ if (argc != 2)
+ {
+ interp->result = gettext ("wrong number of arguments");
+ return TCL_ERROR;
+ }
+
+ interp->result = textdomain (argv[1]);
+
+ return TCL_OK;
+}
+
+
+static int
+tcl_bindtextdomain (client_data, interp, argc, argv)
+ ClientData client_data;
+ Tcl_Interp *interp;
+ int argc;
+ char *argv[];
+{
+ if (argc != 3)
+ {
+ interp->result = gettext ("wrong number of arguments");
+ return TCL_ERROR;
+ }
+
+ return bindtextdomain (argv[1], argv[2]) == NULL ? TCL_ERROR : TCL_OK;
+}