diff options
| author | Karoly Lorentey | 2004-10-07 16:52:19 +0000 |
|---|---|---|
| committer | Karoly Lorentey | 2004-10-07 16:52:19 +0000 |
| commit | c5f80d9d13d6033e5ee75d65bb5383d4d75dc427 (patch) | |
| tree | 1aa58eeabb309b4460144425f6e5a2ca0ad81eaf /lisp | |
| parent | 04ccca970d4a21222cd1f58c7c41983461f009fc (diff) | |
| parent | eb6a2b61401ca737487aa7770389c01c0e962cb0 (diff) | |
| download | emacs-c5f80d9d13d6033e5ee75d65bb5383d4d75dc427.tar.gz emacs-c5f80d9d13d6033e5ee75d65bb5383d4d75dc427.zip | |
Merged in changes from CVS trunk.
Patches applied:
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-593
Update from CVS
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-594
Update from CVS
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-595
Update from CVS
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-596
Update from CVS
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-597
Update from CVS
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-598
Update from CVS
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-599
Merge from gnus--rel--5.10
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-600
Update from CVS
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-601
Update from CVS
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-602
Update from CVS
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-603
Merge from gnus--rel--5.10
* miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-42
Update from CVS
* miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-43
Merge from emacs--cvs-trunk--0
* miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-44
Update from CVS
git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-253
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/ChangeLog | 75 | ||||
| -rw-r--r-- | lisp/calendar/cal-iso.el | 53 | ||||
| -rw-r--r-- | lisp/calendar/cal-menu.el | 5 | ||||
| -rw-r--r-- | lisp/calendar/calendar.el | 5 | ||||
| -rw-r--r-- | lisp/calendar/icalendar.el | 1299 | ||||
| -rw-r--r-- | lisp/gnus/ChangeLog | 18 | ||||
| -rw-r--r-- | lisp/gnus/gnus-group.el | 3 | ||||
| -rw-r--r-- | lisp/gnus/gnus-msg.el | 3 | ||||
| -rw-r--r-- | lisp/gnus/gnus-sum.el | 21 | ||||
| -rw-r--r-- | lisp/gnus/message.el | 4 | ||||
| -rw-r--r-- | lisp/info.el | 29 | ||||
| -rw-r--r-- | lisp/isearch.el | 21 | ||||
| -rw-r--r-- | lisp/newcomment.el | 4 | ||||
| -rw-r--r-- | lisp/progmodes/gdb-ui.el | 1 | ||||
| -rw-r--r-- | lisp/textmodes/enriched.el | 4 | ||||
| -rw-r--r-- | lisp/textmodes/tex-mode.el | 74 | ||||
| -rw-r--r-- | lisp/url/ChangeLog | 5 | ||||
| -rw-r--r-- | lisp/url/url-handlers.el | 2 | ||||
| -rw-r--r-- | lisp/xml.el | 24 |
19 files changed, 1555 insertions, 95 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index dd26fb647bc..ceb72e1eebb 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,69 @@ | |||
| 1 | 2004-10-06 Nick Roberts <nickrob@snap.net.nz> | ||
| 2 | |||
| 3 | * progmodes/gdb-ui.el (gdb-ann3): (Re-)initialise gdb-input-queue. | ||
| 4 | |||
| 5 | 2004-10-06 John Paul Wallington <jpw@gnu.org> | ||
| 6 | |||
| 7 | * xml.el (xml-parse-dtd): Fix `error' call. | ||
| 8 | |||
| 9 | 2004-10-05 Mark A. Hershberger <mah@everybody.org> | ||
| 10 | |||
| 11 | * xml.el (xml-substitute-special): Return a single string instead | ||
| 12 | of a list of strings if an entity substitution is made. | ||
| 13 | |||
| 14 | 2004-10-05 Ulf Jasper <ulf.jasper@web.de> | ||
| 15 | |||
| 16 | * calendar/icalendar.el: New file. | ||
| 17 | |||
| 18 | 2004-10-05 Juri Linkov <juri@jurta.org> | ||
| 19 | |||
| 20 | * isearch.el (isearch-done): Set mark after running hook. | ||
| 21 | Suggested by Drew Adams <drew.adams@oracle.com>. | ||
| 22 | |||
| 23 | * info.el (Info-history, Info-toc): Fix Info headers. | ||
| 24 | (Info-toc): Narrow buffer before Info-fontify-node. | ||
| 25 | (Info-build-toc): Don't check for special Info file names. | ||
| 26 | Set main-file to nil if Info-find-file returns a symbol. | ||
| 27 | |||
| 28 | 2004-10-05 Emilio C. Lopes <eclig@gmx.net>: | ||
| 29 | |||
| 30 | * calendar/calendar.el (calendar-goto-iso-week): Add autoload. | ||
| 31 | (calendar-mode-map): Add binding for `calendar-goto-iso-week'. | ||
| 32 | * calendar/cal-menu.el (calendar-mode-map): Ditto. | ||
| 33 | |||
| 34 | 2004-10-05 Glenn Morris <gmorris@ast.cam.ac.uk> | ||
| 35 | |||
| 36 | * calendar/cal-iso.el (calendar-iso-read-args): New function, | ||
| 37 | for old interactive spec from calendar-goto-iso-date. | ||
| 38 | (calendar-goto-iso-date): Use it. | ||
| 39 | (calendar-goto-iso-week): New function. Suggested by Emilio | ||
| 40 | C. Lopes <eclig@gmx.net>. | ||
| 41 | |||
| 42 | 2004-10-04 Luc Teirlinck <teirllm@auburn.edu> | ||
| 43 | |||
| 44 | * textmodes/enriched.el (enriched-mode-map): Give | ||
| 45 | `set-left-margin' and `set-right-margin' bindings that follow the | ||
| 46 | minor mode conventions. | ||
| 47 | |||
| 48 | 2004-10-03 Stefan <monnier@iro.umontreal.ca> | ||
| 49 | |||
| 50 | * textmodes/tex-mode.el (tex-dvi-view-command): Use `yap' on w32. | ||
| 51 | (tex-font-lock-keywords-1): Add url and nolinkurl for args with `_'. | ||
| 52 | (latex-block-args-alist): Add minipage and picture. | ||
| 53 | (latex-block-body-alist): Use reftex-label if enabled. | ||
| 54 | (latex-insert-block): Don't insert a \n if not necessary. | ||
| 55 | (tex-compile-commands): Make sure dvips doesn't send to printer. | ||
| 56 | (tex-compile-default): Handle the case where no executable is found. | ||
| 57 | (latex-noindent-environments): New var. | ||
| 58 | (latex-find-indent): Use it. Take an empty line as an arg-breaker. | ||
| 59 | If tex-indent-allhanging is non-nil, make sure we only align for macros | ||
| 60 | at beginning of line. | ||
| 61 | |||
| 62 | 2004-10-03 Daniel Pfeiffer <occitan@esperanto.org> | ||
| 63 | |||
| 64 | * newcomment.el (comment-beginning): Doc fix and don't choke on | ||
| 65 | unset `comment-end-skip' when at beginning of comment. | ||
| 66 | |||
| 1 | 2004-10-02 Dan Nicolaescu <dann@ics.uci.edu> | 67 | 2004-10-02 Dan Nicolaescu <dann@ics.uci.edu> |
| 2 | 68 | ||
| 3 | * term.el (term-adjust-current-row-cache): Don't allow the current | 69 | * term.el (term-adjust-current-row-cache): Don't allow the current |
| @@ -5,9 +71,8 @@ | |||
| 5 | (term-emulate-terminal): Fix insert mode. Handle tab insertion at | 71 | (term-emulate-terminal): Fix insert mode. Handle tab insertion at |
| 6 | the end of the line. Fix scroll down. Add comments. | 72 | the end of the line. Fix scroll down. Add comments. |
| 7 | (term-handle-ansi-escape): Don't exceed terminal width when moving | 73 | (term-handle-ansi-escape): Don't exceed terminal width when moving |
| 8 | right. | 74 | right. |
| 9 | (term-scroll-region): Move the cursor after setting the scroll | 75 | (term-scroll-region): Move the cursor after setting the scroll region. |
| 10 | region. | ||
| 11 | 76 | ||
| 12 | 2004-10-01 Luc Teirlinck <teirllm@auburn.edu> | 77 | 2004-10-01 Luc Teirlinck <teirllm@auburn.edu> |
| 13 | 78 | ||
| @@ -33,8 +98,8 @@ | |||
| 33 | 98 | ||
| 34 | 2004-09-29 Luc Teirlinck <teirllm@auburn.edu> | 99 | 2004-09-29 Luc Teirlinck <teirllm@auburn.edu> |
| 35 | 100 | ||
| 36 | * textmodes/paragraphs.el (forward-paragraph): Avoid | 101 | * textmodes/paragraphs.el (forward-paragraph): |
| 37 | args-out-of-range error when point winds up at the beginning of | 102 | Avoid args-out-of-range error when point winds up at the beginning of |
| 38 | the buffer and hard newlines are enabled. | 103 | the buffer and hard newlines are enabled. |
| 39 | 104 | ||
| 40 | * newcomment.el (comment-multi-line): Doc fix. | 105 | * newcomment.el (comment-multi-line): Doc fix. |
diff --git a/lisp/calendar/cal-iso.el b/lisp/calendar/cal-iso.el index 0d9ad45c7d6..058bdf071d7 100644 --- a/lisp/calendar/cal-iso.el +++ b/lisp/calendar/cal-iso.el | |||
| @@ -1,8 +1,9 @@ | |||
| 1 | ;;; cal-iso.el --- calendar functions for the ISO calendar | 1 | ;;; cal-iso.el --- calendar functions for the ISO calendar |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 1995, 1997 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 1995, 1997, 2004 Free Software Foundation, Inc. |
| 4 | 4 | ||
| 5 | ;; Author: Edward M. Reingold <reingold@cs.uiuc.edu> | 5 | ;; Author: Edward M. Reingold <reingold@cs.uiuc.edu> |
| 6 | ;; Maintainer: Glenn Morris <gmorris@ast.cam.ac.uk> | ||
| 6 | ;; Keywords: calendar | 7 | ;; Keywords: calendar |
| 7 | ;; Human-Keywords: ISO calendar, calendar, diary | 8 | ;; Human-Keywords: ISO calendar, calendar, diary |
| 8 | 9 | ||
| @@ -96,27 +97,39 @@ Defaults to today's date if DATE is not given." | |||
| 96 | (message "ISO date: %s" | 97 | (message "ISO date: %s" |
| 97 | (calendar-iso-date-string (calendar-cursor-to-date t)))) | 98 | (calendar-iso-date-string (calendar-cursor-to-date t)))) |
| 98 | 99 | ||
| 100 | (defun calendar-iso-read-args (&optional dayflag) | ||
| 101 | "Interactively read the arguments for an iso date command." | ||
| 102 | (let* ((today (calendar-current-date)) | ||
| 103 | (year (calendar-read | ||
| 104 | "ISO calendar year (>0): " | ||
| 105 | '(lambda (x) (> x 0)) | ||
| 106 | (int-to-string (extract-calendar-year today)))) | ||
| 107 | (no-weeks (extract-calendar-month | ||
| 108 | (calendar-iso-from-absolute | ||
| 109 | (1- | ||
| 110 | (calendar-dayname-on-or-before | ||
| 111 | 1 (calendar-absolute-from-gregorian | ||
| 112 | (list 1 4 (1+ year)))))))) | ||
| 113 | (week (calendar-read | ||
| 114 | (format "ISO calendar week (1-%d): " no-weeks) | ||
| 115 | '(lambda (x) (and (> x 0) (<= x no-weeks))))) | ||
| 116 | (day (if dayflag (calendar-read | ||
| 117 | "ISO day (1-7): " | ||
| 118 | '(lambda (x) (and (<= 1 x) (<= x 7)))) | ||
| 119 | 1))) | ||
| 120 | (list (list week day year)))) | ||
| 121 | |||
| 99 | (defun calendar-goto-iso-date (date &optional noecho) | 122 | (defun calendar-goto-iso-date (date &optional noecho) |
| 100 | "Move cursor to ISO DATE; echo ISO date unless NOECHO is t." | 123 | "Move cursor to ISO DATE; echo ISO date unless NOECHO is t." |
| 101 | (interactive | 124 | (interactive (calendar-iso-read-args t)) |
| 102 | (let* ((today (calendar-current-date)) | 125 | (calendar-goto-date (calendar-gregorian-from-absolute |
| 103 | (year (calendar-read | 126 | (calendar-absolute-from-iso date))) |
| 104 | "ISO calendar year (>0): " | 127 | (or noecho (calendar-print-iso-date))) |
| 105 | '(lambda (x) (> x 0)) | 128 | |
| 106 | (int-to-string (extract-calendar-year today)))) | 129 | (defun calendar-goto-iso-week (date &optional noecho) |
| 107 | (no-weeks (extract-calendar-month | 130 | "Move cursor to ISO DATE; echo ISO date unless NOECHO is t. |
| 108 | (calendar-iso-from-absolute | 131 | Interactively, goes to the first day of the specified week." |
| 109 | (1- | 132 | (interactive (calendar-iso-read-args)) |
| 110 | (calendar-dayname-on-or-before | ||
| 111 | 1 (calendar-absolute-from-gregorian | ||
| 112 | (list 1 4 (1+ year)))))))) | ||
| 113 | (week (calendar-read | ||
| 114 | (format "ISO calendar week (1-%d): " no-weeks) | ||
| 115 | '(lambda (x) (and (> x 0) (<= x no-weeks))))) | ||
| 116 | (day (calendar-read | ||
| 117 | "ISO day (1-7): " | ||
| 118 | '(lambda (x) (and (<= 1 x) (<= x 7)))))) | ||
| 119 | (list (list week day year)))) | ||
| 120 | (calendar-goto-date (calendar-gregorian-from-absolute | 133 | (calendar-goto-date (calendar-gregorian-from-absolute |
| 121 | (calendar-absolute-from-iso date))) | 134 | (calendar-absolute-from-iso date))) |
| 122 | (or noecho (calendar-print-iso-date))) | 135 | (or noecho (calendar-print-iso-date))) |
diff --git a/lisp/calendar/cal-menu.el b/lisp/calendar/cal-menu.el index a652e7ca768..ceb4c56f7fd 100644 --- a/lisp/calendar/cal-menu.el +++ b/lisp/calendar/cal-menu.el | |||
| @@ -1,9 +1,10 @@ | |||
| 1 | ;;; cal-menu.el --- calendar functions for menu bar and popup menu support | 1 | ;;; cal-menu.el --- calendar functions for menu bar and popup menu support |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 1994, 1995, 2001, 2003 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 1994, 1995, 2001, 2003, 2004 Free Software Foundation, Inc. |
| 4 | 4 | ||
| 5 | ;; Author: Edward M. Reingold <reingold@cs.uiuc.edu> | 5 | ;; Author: Edward M. Reingold <reingold@cs.uiuc.edu> |
| 6 | ;; Lara Rios <lrios@coewl.cen.uiuc.edu> | 6 | ;; Lara Rios <lrios@coewl.cen.uiuc.edu> |
| 7 | ;; Maintainer: Glenn Morris <gmorris@ast.cam.ac.uk> | ||
| 7 | ;; Keywords: calendar | 8 | ;; Keywords: calendar |
| 8 | ;; Human-Keywords: calendar, popup menus, menu bar | 9 | ;; Human-Keywords: calendar, popup menus, menu bar |
| 9 | 10 | ||
| @@ -121,6 +122,8 @@ | |||
| 121 | '("Astronomical Date" . calendar-goto-astro-day-number)) | 122 | '("Astronomical Date" . calendar-goto-astro-day-number)) |
| 122 | (define-key calendar-mode-map [menu-bar goto iso] | 123 | (define-key calendar-mode-map [menu-bar goto iso] |
| 123 | '("ISO Date" . calendar-goto-iso-date)) | 124 | '("ISO Date" . calendar-goto-iso-date)) |
| 125 | (define-key calendar-mode-map [menu-bar goto iso-week] | ||
| 126 | '("ISO Week" . calendar-goto-iso-week)) | ||
| 124 | (define-key calendar-mode-map [menu-bar goto day-of-year] | 127 | (define-key calendar-mode-map [menu-bar goto day-of-year] |
| 125 | '("Day of Year" . calendar-goto-day-of-year)) | 128 | '("Day of Year" . calendar-goto-day-of-year)) |
| 126 | (define-key calendar-mode-map [menu-bar goto gregorian] | 129 | (define-key calendar-mode-map [menu-bar goto gregorian] |
diff --git a/lisp/calendar/calendar.el b/lisp/calendar/calendar.el index 9d38cde21ce..aa0b3005fad 100644 --- a/lisp/calendar/calendar.el +++ b/lisp/calendar/calendar.el | |||
| @@ -1769,6 +1769,10 @@ Driven by the variable `calendar-date-display-form'.") | |||
| 1769 | "Move cursor to ISO date." | 1769 | "Move cursor to ISO date." |
| 1770 | t) | 1770 | t) |
| 1771 | 1771 | ||
| 1772 | (autoload 'calendar-goto-iso-week "cal-iso" | ||
| 1773 | "Move cursor to start of ISO week." | ||
| 1774 | t) | ||
| 1775 | |||
| 1772 | (autoload 'calendar-print-iso-date "cal-iso" | 1776 | (autoload 'calendar-print-iso-date "cal-iso" |
| 1773 | "Show the ISO date equivalents of date." | 1777 | "Show the ISO date equivalents of date." |
| 1774 | t) | 1778 | t) |
| @@ -2204,6 +2208,7 @@ the inserted text. Value is always t." | |||
| 2204 | (define-key calendar-mode-map "ge" 'calendar-goto-ethiopic-date) | 2208 | (define-key calendar-mode-map "ge" 'calendar-goto-ethiopic-date) |
| 2205 | (define-key calendar-mode-map "gp" 'calendar-goto-persian-date) | 2209 | (define-key calendar-mode-map "gp" 'calendar-goto-persian-date) |
| 2206 | (define-key calendar-mode-map "gc" 'calendar-goto-iso-date) | 2210 | (define-key calendar-mode-map "gc" 'calendar-goto-iso-date) |
| 2211 | (define-key calendar-mode-map "gw" 'calendar-goto-iso-week) | ||
| 2207 | (define-key calendar-mode-map "gf" 'calendar-goto-french-date) | 2212 | (define-key calendar-mode-map "gf" 'calendar-goto-french-date) |
| 2208 | (define-key calendar-mode-map "gml" 'calendar-goto-mayan-long-count-date) | 2213 | (define-key calendar-mode-map "gml" 'calendar-goto-mayan-long-count-date) |
| 2209 | (define-key calendar-mode-map "gmpc" 'calendar-previous-calendar-round-date) | 2214 | (define-key calendar-mode-map "gmpc" 'calendar-previous-calendar-round-date) |
diff --git a/lisp/calendar/icalendar.el b/lisp/calendar/icalendar.el new file mode 100644 index 00000000000..e83e8e980b6 --- /dev/null +++ b/lisp/calendar/icalendar.el | |||
| @@ -0,0 +1,1299 @@ | |||
| 1 | ;;; icalendar.el --- iCalendar implementation | ||
| 2 | |||
| 3 | ;; Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: Ulf Jasper <ulf.jasper@web.de> | ||
| 6 | ;; Created: August 2002 | ||
| 7 | ;; Keywords: calendar | ||
| 8 | ;; Human-Keywords: calendar, diary, iCalendar, vCalendar | ||
| 9 | |||
| 10 | ;; This file is part of GNU Emacs. | ||
| 11 | |||
| 12 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 13 | ;; it under the terms of the GNU General Public License as published by | ||
| 14 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 15 | ;; any later version. | ||
| 16 | |||
| 17 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 18 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 19 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 20 | ;; GNU General Public License for more details. | ||
| 21 | |||
| 22 | ;; You should have received a copy of the GNU General Public License | ||
| 23 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 24 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 25 | ;; Boston, MA 02111-1307, USA. | ||
| 26 | |||
| 27 | ;;; Commentary: | ||
| 28 | |||
| 29 | ;; This package is documented in the Emacs Manual. | ||
| 30 | |||
| 31 | |||
| 32 | ;;; History: | ||
| 33 | |||
| 34 | ;; 0.06 Bugfixes regarding icalendar-import-format-*. | ||
| 35 | ;; Fix in icalendar-convert-diary-to-ical -- thanks to Philipp Grau. | ||
| 36 | |||
| 37 | ;; 0.05: New import format scheme: Replaced icalendar-import-prefix-*, | ||
| 38 | ;; icalendar-import-ignored-properties, and | ||
| 39 | ;; icalendar-import-separator with icalendar-import-format(-*). | ||
| 40 | ;; icalendar-import-file and icalendar-convert-diary-to-ical | ||
| 41 | ;; have an extra parameter which should prevent them from | ||
| 42 | ;; erasing their target files (untested!). | ||
| 43 | ;; Tested with Emacs 21.3.2 | ||
| 44 | |||
| 45 | ;; 0.04: Bugfix: import: double quoted param values did not work | ||
| 46 | ;; Read DURATION property when importing. | ||
| 47 | ;; Added parameter icalendar-duration-correction. | ||
| 48 | |||
| 49 | ;; 0.03: Export takes care of european-calendar-style. | ||
| 50 | ;; Tested with Emacs 21.3.2 and XEmacs 21.4.12 | ||
| 51 | |||
| 52 | ;; 0.02: Should work in XEmacs now. Thanks to Len Trigg for the | ||
| 53 | ;; XEmacs patches! | ||
| 54 | ;; Added exporting from Emacs diary to ical. | ||
| 55 | ;; Some bugfixes, after testing with calendars from | ||
| 56 | ;; http://icalshare.com. | ||
| 57 | ;; Tested with Emacs 21.3.2 and XEmacs 21.4.12 | ||
| 58 | |||
| 59 | ;; 0.01: First published version. Trial version. Alpha version. | ||
| 60 | |||
| 61 | ;; ====================================================================== | ||
| 62 | ;; To Do: | ||
| 63 | |||
| 64 | ;; * Import from ical: | ||
| 65 | ;; + Need more properties for icalendar-import-format | ||
| 66 | ;; + check vcalendar version | ||
| 67 | ;; + check (unknown) elements | ||
| 68 | ;; + recurring events! | ||
| 69 | ;; + works for european style calendars only! Does it? | ||
| 70 | ;; + alarm | ||
| 71 | ;; + exceptions in recurring events | ||
| 72 | ;; + the parser is too soft | ||
| 73 | ;; + error log is incomplete | ||
| 74 | ;; + nice to have: #include "webcal://foo.com/some-calendar.ics" | ||
| 75 | |||
| 76 | ;; * Export into ical | ||
| 77 | ;; + diary-date, diary-float, and self-made sexp entries are not | ||
| 78 | ;; understood | ||
| 79 | ;; + timezones, currently all times are local! | ||
| 80 | |||
| 81 | ;; * Other things | ||
| 82 | ;; + defcustom icalendar-import-ignored-properties does not work with | ||
| 83 | ;; XEmacs. | ||
| 84 | ;; + clean up all those date/time parsing functions | ||
| 85 | ;; + Handle todo items? | ||
| 86 | ;; + Check iso 8601 for datetime and period | ||
| 87 | ;; + Which chars to (un)escape? | ||
| 88 | ;; + Time to find out how the profiler works? | ||
| 89 | |||
| 90 | |||
| 91 | ;;; Code: | ||
| 92 | |||
| 93 | (defconst icalendar-version 0.06 | ||
| 94 | "Version number of icalendar.el.") | ||
| 95 | |||
| 96 | ;; ====================================================================== | ||
| 97 | ;; Customizables | ||
| 98 | ;; ====================================================================== | ||
| 99 | (defgroup icalendar nil | ||
| 100 | "Icalendar support." | ||
| 101 | :prefix "icalendar-" | ||
| 102 | :group 'calendar) | ||
| 103 | |||
| 104 | (defcustom icalendar-import-format | ||
| 105 | "%s%d%l%o" | ||
| 106 | "Format string for importing events from iCalendar into Emacs diary. | ||
| 107 | This string defines how iCalendar events are inserted into diary | ||
| 108 | file. Meaning of the specifiers: | ||
| 109 | %d Description, see `icalendar-import-format-description' | ||
| 110 | %l Location, see `icalendar-import-format-location' | ||
| 111 | %o Organizer, see `icalendar-import-format-organizer' | ||
| 112 | %s Subject, see `icalendar-import-format-subject'" | ||
| 113 | :type 'string | ||
| 114 | :group 'icalendar) | ||
| 115 | |||
| 116 | (defcustom icalendar-import-format-subject | ||
| 117 | "%s" | ||
| 118 | "Format string defining how the subject element is formatted. | ||
| 119 | This applies only if the subject is not empty! `%s' is replaced | ||
| 120 | by the subject." | ||
| 121 | :type 'string | ||
| 122 | :group 'icalendar) | ||
| 123 | |||
| 124 | (defcustom icalendar-import-format-description | ||
| 125 | "\n Desc: %s" | ||
| 126 | "Format string defining how the description element is formatted. | ||
| 127 | This applies only if the description is not empty! `%s' is | ||
| 128 | replaced by the description." | ||
| 129 | :type 'string | ||
| 130 | :group 'icalendar) | ||
| 131 | |||
| 132 | (defcustom icalendar-import-format-location | ||
| 133 | "\n Location: %s" | ||
| 134 | "Format string defining how the location element is formatted. | ||
| 135 | This applies only if the location is not empty! `%s' is replaced | ||
| 136 | by the location." | ||
| 137 | :type 'string | ||
| 138 | :group 'icalendar) | ||
| 139 | |||
| 140 | (defcustom icalendar-import-format-organizer | ||
| 141 | "\n Organizer: %s" | ||
| 142 | "Format string defining how the organizer element is formatted. | ||
| 143 | This applies only if the organizer is not empty! `%s' is | ||
| 144 | replaced by the organizer." | ||
| 145 | :type 'string | ||
| 146 | :group 'icalendar) | ||
| 147 | |||
| 148 | (defcustom icalendar-duration-correction | ||
| 149 | t | ||
| 150 | "Workaround for all-day events. | ||
| 151 | If non-nil the length=duration of iCalendar appointments that | ||
| 152 | have a length of exactly n days is decreased by one day. This | ||
| 153 | fixes problems with all-day events, which appear to be one day | ||
| 154 | longer than they are." | ||
| 155 | :type 'boolean | ||
| 156 | :group 'icalendar) | ||
| 157 | |||
| 158 | |||
| 159 | ;; ====================================================================== | ||
| 160 | ;; NO USER SERVICABLE PARTS BELOW THIS LINE | ||
| 161 | ;; ====================================================================== | ||
| 162 | |||
| 163 | (defconst icalendar-weekdayabbrev-table | ||
| 164 | '(("mon\\(day\\)?" . "MO") | ||
| 165 | ("tue\\(sday\\)?" . "TU") | ||
| 166 | ("wed\\(nesday\\)?" . "WE") | ||
| 167 | ("thu\\(rsday\\)?" . "TH") | ||
| 168 | ("fri\\(day\\)?" . "FR") | ||
| 169 | ("sat\\(urday\\)?" . "SA") | ||
| 170 | ("sun\\(day\\)?" . "SU")) | ||
| 171 | "Translation table for weekdays.") | ||
| 172 | |||
| 173 | (defconst icalendar-monthnumber-table | ||
| 174 | '(("^jan\\(uar\\)?y?$" . 1) | ||
| 175 | ("^feb\\(ruar\\)?y?$" . 2) | ||
| 176 | ("^mar\\(ch\\)?\\|märz?$" . 3) | ||
| 177 | ("^apr\\(il\\)?$" . 4) | ||
| 178 | ("^ma[iy]$" . 5) | ||
| 179 | ("^jun[ie]?$" . 6) | ||
| 180 | ("^jul[iy]?$" . 7) | ||
| 181 | ("^aug\\(ust\\)?$" . 8) | ||
| 182 | ("^sep\\(tember\\)?$" . 9) | ||
| 183 | ("^o[ck]t\\(ober\\)?$" . 10) | ||
| 184 | ("^nov\\(ember\\)?$" . 11) | ||
| 185 | ("^de[cz]\\(ember\\)?$" . 12)) | ||
| 186 | "Regular expressions for month names. | ||
| 187 | Currently this matches only German and English.") | ||
| 188 | |||
| 189 | (defvar icalendar-debug nil ".") | ||
| 190 | |||
| 191 | ;; ====================================================================== | ||
| 192 | ;; all the other libs we need | ||
| 193 | ;; ====================================================================== | ||
| 194 | (require 'calendar) | ||
| 195 | (require 'appt) | ||
| 196 | |||
| 197 | ;; ====================================================================== | ||
| 198 | ;; Core functionality | ||
| 199 | ;; Functions for parsing icalendars, importing and so on | ||
| 200 | ;; ====================================================================== | ||
| 201 | |||
| 202 | (defun icalendar-get-unfolded-buffer (folded-ical-buffer) | ||
| 203 | "Return a new buffer containing the unfolded contents of a buffer. | ||
| 204 | Folding is the iCalendar way of wrapping long lines. In the | ||
| 205 | created buffer all occurrences of CR LF BLANK are replaced by the | ||
| 206 | empty string. Argument FOLDED-ICAL-BUFFER is the unfolded input | ||
| 207 | buffer." | ||
| 208 | (let ((unfolded-buffer (get-buffer-create " *icalendar-work*"))) | ||
| 209 | (save-current-buffer | ||
| 210 | (set-buffer unfolded-buffer) | ||
| 211 | (erase-buffer) | ||
| 212 | (insert-buffer folded-ical-buffer) | ||
| 213 | (while (re-search-forward "\r?\n[ \t]" nil t) | ||
| 214 | (replace-match "" nil nil)) | ||
| 215 | ) | ||
| 216 | unfolded-buffer)) | ||
| 217 | |||
| 218 | ;; Replace regexp RE with RP in string ST and return the new string. | ||
| 219 | ;; This is here for compatibility with XEmacs. | ||
| 220 | (defsubst icalendar-rris (re rp st) | ||
| 221 | ;; XEmacs: | ||
| 222 | (if (fboundp 'replace-in-string) | ||
| 223 | (save-match-data ;; apparently XEmacs needs save-match-data | ||
| 224 | (replace-in-string st re rp)) | ||
| 225 | ;; Emacs: | ||
| 226 | (replace-regexp-in-string re rp st))) | ||
| 227 | |||
| 228 | (defun icalendar-read-element (invalue inparams) | ||
| 229 | "Recursively read the next iCalendar element in the current buffer. | ||
| 230 | INVALUE gives the current iCalendar element we are reading. | ||
| 231 | INPARAMS gives the current parameters..... | ||
| 232 | This function calls itself recursively for each nested calendar element | ||
| 233 | it finds" | ||
| 234 | (let (element children line name params param param-name param-value | ||
| 235 | value | ||
| 236 | (continue t)) | ||
| 237 | (setq children '()) | ||
| 238 | (while (and continue | ||
| 239 | (re-search-forward "^\\([A-Za-z0-9-]+\\)[;:]" nil t)) | ||
| 240 | (setq name (intern (match-string 1))) | ||
| 241 | (backward-char 1) | ||
| 242 | (setq params '()) | ||
| 243 | (setq line '()) | ||
| 244 | (while (looking-at ";") | ||
| 245 | (re-search-forward ";\\([A-Za-z0-9-]+\\)=" nil nil) | ||
| 246 | (setq param-name (intern (match-string 1))) | ||
| 247 | (re-search-forward "\\(\\([^;,:\"]+\\)\\|\"\\([^\"]+\\)\"\\)[;:]" | ||
| 248 | nil t) | ||
| 249 | (backward-char 1) | ||
| 250 | (setq param-value (or (match-string 2) (match-string 3))) | ||
| 251 | (setq param (list param-name param-value)) | ||
| 252 | (while (looking-at ",") | ||
| 253 | (re-search-forward "\\(\\([^;,:]+\\)\\|\"\\([^\"]+\\)\"\\)" | ||
| 254 | nil t) | ||
| 255 | (if (match-string 2) | ||
| 256 | (setq param-value (match-string 2)) | ||
| 257 | (setq param-value (match-string 3))) | ||
| 258 | (setq param (append param param-value))) | ||
| 259 | (setq params (append params param))) | ||
| 260 | (unless (looking-at ":") | ||
| 261 | (error "Oops")) | ||
| 262 | (forward-char 1) | ||
| 263 | (re-search-forward "\\(.*\\)\\(\r?\n[ \t].*\\)*" nil t) | ||
| 264 | (setq value (icalendar-rris "\r?\n[ \t]" "" (match-string 0))) | ||
| 265 | (setq line (list name params value)) | ||
| 266 | (cond ((eq name 'BEGIN) | ||
| 267 | (setq children | ||
| 268 | (append children | ||
| 269 | (list (icalendar-read-element (intern value) | ||
| 270 | params))))) | ||
| 271 | ((eq name 'END) | ||
| 272 | (setq continue nil)) | ||
| 273 | (t | ||
| 274 | (setq element (append element (list line)))))) | ||
| 275 | (if invalue | ||
| 276 | (list invalue inparams element children) | ||
| 277 | children))) | ||
| 278 | |||
| 279 | ;; ====================================================================== | ||
| 280 | ;; helper functions for examining events | ||
| 281 | ;; ====================================================================== | ||
| 282 | |||
| 283 | (defsubst icalendar-get-all-event-properties (event) | ||
| 284 | "Return the list of properties in this EVENT." | ||
| 285 | (car (cddr event))) | ||
| 286 | |||
| 287 | (defun icalendar-get-event-property (event prop) | ||
| 288 | "For the given EVENT return the value of the property PROP." | ||
| 289 | (catch 'found | ||
| 290 | (let ((props (car (cddr event))) pp) | ||
| 291 | (while props | ||
| 292 | (setq pp (car props)) | ||
| 293 | (if (eq (car pp) prop) | ||
| 294 | (throw 'found (car (cddr pp)))) | ||
| 295 | (setq props (cdr props)))) | ||
| 296 | nil)) | ||
| 297 | |||
| 298 | (defun icalendar-set-event-property (event prop new-value) | ||
| 299 | "For the given EVENT set the property PROP to the value NEW-VALUE." | ||
| 300 | (catch 'found | ||
| 301 | (let ((props (car (cddr event))) pp) | ||
| 302 | (while props | ||
| 303 | (setq pp (car props)) | ||
| 304 | (when (eq (car pp) prop) | ||
| 305 | (setcdr (cdr pp) new-value) | ||
| 306 | (throw 'found (car (cddr pp)))) | ||
| 307 | (setq props (cdr props))) | ||
| 308 | (setq props (car (cddr event))) | ||
| 309 | (setcar (cddr event) | ||
| 310 | (append props (list (list prop nil new-value))))))) | ||
| 311 | |||
| 312 | (defun icalendar-get-children (node name) | ||
| 313 | "Return all children of the given NODE which have a name NAME. | ||
| 314 | For instance the VCALENDAR node can have VEVENT children as well as VTODO | ||
| 315 | children." | ||
| 316 | (let ((result nil) | ||
| 317 | (children (cadr (cddr node)))) | ||
| 318 | (when (eq (car node) name) | ||
| 319 | (setq result node)) | ||
| 320 | ;;(message "%s" node) | ||
| 321 | (when children | ||
| 322 | (let ((subresult | ||
| 323 | (delq nil | ||
| 324 | (mapcar (lambda (n) | ||
| 325 | (icalendar-get-children n name)) | ||
| 326 | children)))) | ||
| 327 | (if subresult | ||
| 328 | (if result | ||
| 329 | (setq result (append result subresult)) | ||
| 330 | (setq result subresult))))) | ||
| 331 | result)) | ||
| 332 | |||
| 333 | ; private | ||
| 334 | (defun icalendar-all-events (icalendar) | ||
| 335 | "Return the list of all existing events in the given ICALENDAR." | ||
| 336 | (interactive "") | ||
| 337 | (icalendar-get-children (car icalendar) 'VEVENT)) | ||
| 338 | |||
| 339 | (defun icalendar-split-value (value-string) | ||
| 340 | "Splits VALUE-STRING at ';='." | ||
| 341 | (let ((result '()) | ||
| 342 | param-name param-value) | ||
| 343 | (when value-string | ||
| 344 | (save-current-buffer | ||
| 345 | (set-buffer (get-buffer-create " *ical-temp*")) | ||
| 346 | (set-buffer-modified-p nil) | ||
| 347 | (erase-buffer) | ||
| 348 | (insert value-string) | ||
| 349 | (goto-char (point-min)) | ||
| 350 | (while | ||
| 351 | (re-search-forward | ||
| 352 | "\\([A-Za-z0-9-]+\\)=\\(\\([^;,:]+\\)\\|\"\\([^\"]+\\)\"\\);?" | ||
| 353 | nil t) | ||
| 354 | (setq param-name (intern (match-string 1))) | ||
| 355 | (setq param-value (match-string 2)) | ||
| 356 | (setq result | ||
| 357 | (append result (list (list param-name param-value))))))) | ||
| 358 | result)) | ||
| 359 | |||
| 360 | (defun icalendar-decode-isodatetime (isodatetimestring) | ||
| 361 | "Return ISODATETIMESTRING in format like `decode-time'. | ||
| 362 | Converts from ISO-8601 to Emacs representation. If ISODATETIMESTRING | ||
| 363 | specifies UTC time (trailing letter Z) the decoded time is given in | ||
| 364 | the local time zone! FIXME: TZID-attributes are ignored....! FIXME: | ||
| 365 | multiple comma-separated values should be allowed!" | ||
| 366 | (icalendar-dmsg isodatetimestring) | ||
| 367 | (if isodatetimestring | ||
| 368 | ;; day/month/year must be present | ||
| 369 | (let ((year (read (substring isodatetimestring 0 4))) | ||
| 370 | (month (read (substring isodatetimestring 4 6))) | ||
| 371 | (day (read (substring isodatetimestring 6 8))) | ||
| 372 | (hour 0) | ||
| 373 | (minute 0) | ||
| 374 | (second 0)) | ||
| 375 | (when (> (length isodatetimestring) 12) | ||
| 376 | ;; hour/minute present | ||
| 377 | (setq hour (read (substring isodatetimestring 9 11))) | ||
| 378 | (setq minute (read (substring isodatetimestring 11 13)))) | ||
| 379 | (when (> (length isodatetimestring) 14) | ||
| 380 | ;; seconds present | ||
| 381 | (setq second (read (substring isodatetimestring 13 15)))) | ||
| 382 | (when (and (> (length isodatetimestring) 15) | ||
| 383 | ;; UTC specifier present | ||
| 384 | (char-equal ?Z (aref isodatetimestring 15))) | ||
| 385 | ;; if not UTC add current-time-zone offset | ||
| 386 | (setq second (+ (car (current-time-zone)) second))) | ||
| 387 | ;; create the decoded date-time | ||
| 388 | ;; FIXME!?! | ||
| 389 | (condition-case nil | ||
| 390 | (decode-time (encode-time second minute hour day month year)) | ||
| 391 | (error | ||
| 392 | (message "Cannot decode \"%s\"" isodatetimestring) | ||
| 393 | ;; hope for the best... | ||
| 394 | (list second minute hour day month year 0 nil 0)))) | ||
| 395 | ;; isodatetimestring == nil | ||
| 396 | nil)) | ||
| 397 | |||
| 398 | (defun icalendar-decode-isoduration (isodurationstring) | ||
| 399 | "Return ISODURATIONSTRING in format like `decode-time'. | ||
| 400 | Converts from ISO-8601 to Emacs representation. If ISODURATIONSTRING | ||
| 401 | specifies UTC time (trailing letter Z) the decoded time is given in | ||
| 402 | the local time zone! FIXME: TZID-attributes are ignored....! FIXME: | ||
| 403 | multiple comma-separated values should be allowed!" | ||
| 404 | (if isodurationstring | ||
| 405 | (save-match-data | ||
| 406 | (string-match | ||
| 407 | (concat | ||
| 408 | "^P[+-]?\\(" | ||
| 409 | "\\(\\([0-9]+\\)D\\)" ; days only | ||
| 410 | "\\|" | ||
| 411 | "\\(\\(\\([0-9]+\\)D\\)?T\\(\\([0-9]+\\)H\\)?" ; opt days | ||
| 412 | "\\(\\([0-9]+\\)M\\)?\\(\\([0-9]+\\)S\\)?\\)" ; mand. time | ||
| 413 | "\\|" | ||
| 414 | "\\(\\([0-9]+\\)W\\)" ; weeks only | ||
| 415 | "\\)$") isodurationstring) | ||
| 416 | (let ((seconds 0) | ||
| 417 | (minutes 0) | ||
| 418 | (hours 0) | ||
| 419 | (days 0) | ||
| 420 | (months 0) | ||
| 421 | (years 0)) | ||
| 422 | (cond | ||
| 423 | ((match-beginning 2) ;days only | ||
| 424 | (setq days (read (substring isodurationstring | ||
| 425 | (match-beginning 3) | ||
| 426 | (match-end 3)))) | ||
| 427 | (when icalendar-duration-correction | ||
| 428 | (setq days (1- days)))) | ||
| 429 | ((match-beginning 4) ;days and time | ||
| 430 | (if (match-beginning 5) | ||
| 431 | (setq days (* 7 (read (substring isodurationstring | ||
| 432 | (match-beginning 6) | ||
| 433 | (match-end 6)))))) | ||
| 434 | (if (match-beginning 7) | ||
| 435 | (setq hours (read (substring isodurationstring | ||
| 436 | (match-beginning 8) | ||
| 437 | (match-end 8))))) | ||
| 438 | (if (match-beginning 9) | ||
| 439 | (setq minutes (read (substring isodurationstring | ||
| 440 | (match-beginning 10) | ||
| 441 | (match-end 10))))) | ||
| 442 | (if (match-beginning 11) | ||
| 443 | (setq seconds (read (substring isodurationstring | ||
| 444 | (match-beginning 12) | ||
| 445 | (match-end 12))))) | ||
| 446 | ) | ||
| 447 | ((match-beginning 13) ;weeks only | ||
| 448 | (setq days (* 7 (read (substring isodurationstring | ||
| 449 | (match-beginning 14) | ||
| 450 | (match-end 14)))))) | ||
| 451 | ) | ||
| 452 | (list seconds minutes hours days months years))) | ||
| 453 | ;; isodatetimestring == nil | ||
| 454 | nil)) | ||
| 455 | |||
| 456 | (defun icalendar-add-decoded-times (time1 time2) | ||
| 457 | "Add TIME1 to TIME2. | ||
| 458 | Both times must be given in decoded form. One of these times must be | ||
| 459 | valid (year > 1900 or something)." | ||
| 460 | ;; FIXME: does this function exist already? | ||
| 461 | (decode-time (encode-time | ||
| 462 | (+ (nth 0 time1) (nth 0 time2)) | ||
| 463 | (+ (nth 1 time1) (nth 1 time2)) | ||
| 464 | (+ (nth 2 time1) (nth 2 time2)) | ||
| 465 | (+ (nth 3 time1) (nth 3 time2)) | ||
| 466 | (+ (nth 4 time1) (nth 4 time2)) | ||
| 467 | (+ (nth 5 time1) (nth 5 time2)) | ||
| 468 | nil | ||
| 469 | nil | ||
| 470 | ;;(or (nth 6 time1) (nth 6 time2)) ;; FIXME? | ||
| 471 | ))) | ||
| 472 | |||
| 473 | (defun icalendar-datetime-to-noneuropean-date (datetime) | ||
| 474 | "Convert the decoded DATETIME to non-european-style format. | ||
| 475 | Non-European format: (month day year)." | ||
| 476 | (if datetime | ||
| 477 | (list (nth 4 datetime) ;month | ||
| 478 | (nth 3 datetime) ;day | ||
| 479 | (nth 5 datetime));year | ||
| 480 | ;; datetime == nil | ||
| 481 | nil)) | ||
| 482 | |||
| 483 | (defun icalendar-datetime-to-european-date (datetime) | ||
| 484 | "Convert the decoded DATETIME to European format. | ||
| 485 | European format: (day month year). | ||
| 486 | FIXME" | ||
| 487 | (if datetime | ||
| 488 | (format "%d %d %d" (nth 3 datetime); day | ||
| 489 | (nth 4 datetime) ;month | ||
| 490 | (nth 5 datetime));year | ||
| 491 | ;; datetime == nil | ||
| 492 | nil)) | ||
| 493 | |||
| 494 | (defun icalendar-datetime-to-colontime (datetime) | ||
| 495 | "Extract the time part of a decoded DATETIME into 24-hour format. | ||
| 496 | Note that this silently ignores seconds." | ||
| 497 | (format "%02d:%02d" (nth 2 datetime) (nth 1 datetime))) | ||
| 498 | |||
| 499 | (defun icalendar-get-month-number (monthname) | ||
| 500 | "Return the month number for the given MONTHNAME." | ||
| 501 | (save-match-data | ||
| 502 | (let ((case-fold-search t)) | ||
| 503 | (assoc-default monthname icalendar-monthnumber-table | ||
| 504 | 'string-match)))) | ||
| 505 | |||
| 506 | (defun icalendar-get-weekday-abbrev (weekday) | ||
| 507 | "Return the abbreviated WEEKDAY." | ||
| 508 | ;;FIXME: ISO-like(?). | ||
| 509 | (save-match-data | ||
| 510 | (let ((case-fold-search t)) | ||
| 511 | (assoc-default weekday icalendar-weekdayabbrev-table | ||
| 512 | 'string-match)))) | ||
| 513 | |||
| 514 | (defun icalendar-datestring-to-isodate (datestring &optional day-shift) | ||
| 515 | "Convert diary-style DATESTRING to iso-style date. | ||
| 516 | If DAY-SHIFT is non-nil, the result is shifted by DAY-SHIFT days | ||
| 517 | -- DAY-SHIFT must be either nil or an integer. This function | ||
| 518 | takes care of european-style." | ||
| 519 | (let ((day -1) month year) | ||
| 520 | (save-match-data | ||
| 521 | (cond (;; numeric date | ||
| 522 | (string-match (concat "\\s-*" | ||
| 523 | "0?\\([1-9][0-9]?\\)[ \t/]\\s-*" | ||
| 524 | "0?\\([1-9][0-9]?\\),?[ \t/]\\s-*" | ||
| 525 | "\\([0-9]\\{4\\}\\)") | ||
| 526 | datestring) | ||
| 527 | (setq day (read (substring datestring (match-beginning 1) | ||
| 528 | (match-end 1)))) | ||
| 529 | (setq month (read (substring datestring (match-beginning 2) | ||
| 530 | (match-end 2)))) | ||
| 531 | (setq year (read (substring datestring (match-beginning 3) | ||
| 532 | (match-end 3)))) | ||
| 533 | (unless european-calendar-style | ||
| 534 | (let ((x month)) | ||
| 535 | (setq month day) | ||
| 536 | (setq day x)))) | ||
| 537 | (;; date contains month names -- european-style | ||
| 538 | (and european-calendar-style | ||
| 539 | (string-match (concat "\\s-*" | ||
| 540 | "0?\\([123]?[0-9]\\)[ \t/]\\s-*" | ||
| 541 | "\\([A-Za-z][^ ]+\\)[ \t/]\\s-*" | ||
| 542 | "\\([0-9]\\{4\\}\\)") | ||
| 543 | datestring)) | ||
| 544 | (setq day (read (substring datestring (match-beginning 1) | ||
| 545 | (match-end 1)))) | ||
| 546 | (setq month (icalendar-get-month-number | ||
| 547 | (substring datestring (match-beginning 2) | ||
| 548 | (match-end 2)))) | ||
| 549 | (setq year (read (substring datestring (match-beginning 3) | ||
| 550 | (match-end 3))))) | ||
| 551 | (;; date contains month names -- non-european-style | ||
| 552 | (and (not european-calendar-style) | ||
| 553 | (string-match (concat "\\s-*" | ||
| 554 | "\\([A-Za-z][^ ]+\\)[ \t/]\\s-*" | ||
| 555 | "0?\\([123]?[0-9]\\),?[ \t/]\\s-*" | ||
| 556 | "\\([0-9]\\{4\\}\\)") | ||
| 557 | datestring)) | ||
| 558 | (setq day (read (substring datestring (match-beginning 2) | ||
| 559 | (match-end 2)))) | ||
| 560 | (setq month (icalendar-get-month-number | ||
| 561 | (substring datestring (match-beginning 1) | ||
| 562 | (match-end 1)))) | ||
| 563 | (setq year (read (substring datestring (match-beginning 3) | ||
| 564 | (match-end 3))))) | ||
| 565 | (t | ||
| 566 | nil))) | ||
| 567 | (if (> day 0) | ||
| 568 | (let ((mdy (calendar-gregorian-from-absolute | ||
| 569 | (+ (calendar-absolute-from-gregorian (list month day year)) | ||
| 570 | (or day-shift 0))))) | ||
| 571 | (format "%04d%02d%02d" (nth 2 mdy) (nth 0 mdy) (nth 1 mdy))) | ||
| 572 | nil))) | ||
| 573 | |||
| 574 | (defun icalendar-dmsg (&rest args) | ||
| 575 | "Print message ARGS if `icalendar-debug' is non-nil." | ||
| 576 | (if icalendar-debug | ||
| 577 | (apply 'message args))) | ||
| 578 | |||
| 579 | (defun icalendar-diarytime-to-isotime (timestring ampmstring) | ||
| 580 | "Convert a a time like 9:30pm to an iso-conform string like T213000. | ||
| 581 | In this example the TIMESTRING would be \"9:30\" and the AMPMSTRING | ||
| 582 | would be \"pm\"." | ||
| 583 | (if timestring | ||
| 584 | (let ((starttimenum (read (icalendar-rris ":" "" timestring)))) | ||
| 585 | ;; take care of am/pm style | ||
| 586 | (if (and ampmstring (string= "pm" ampmstring)) | ||
| 587 | (setq starttimenum (+ starttimenum 1200))) | ||
| 588 | (format "T%04d00" starttimenum)) | ||
| 589 | nil)) | ||
| 590 | |||
| 591 | (defun icalendar-convert-string-for-export (s) | ||
| 592 | "Escape comma and other critical characters in string S." | ||
| 593 | (icalendar-rris "," "\\\\," s)) | ||
| 594 | |||
| 595 | (defun icalendar-convert-for-import (string) | ||
| 596 | "Remove escape chars for comma, semicolon etc. from STRING." | ||
| 597 | (icalendar-rris | ||
| 598 | "\\\\n" "\n " (icalendar-rris | ||
| 599 | "\\\\\"" "\"" (icalendar-rris | ||
| 600 | "\\\\;" ";" (icalendar-rris | ||
| 601 | "\\\\," "," string))))) | ||
| 602 | |||
| 603 | ;; ====================================================================== | ||
| 604 | ;; export -- convert emacs-diary to icalendar | ||
| 605 | ;; ====================================================================== | ||
| 606 | |||
| 607 | (defun icalendar-convert-diary-to-ical (diary-filename ical-filename | ||
| 608 | &optional do-not-clear-diary-file) | ||
| 609 | "Export diary file to iCalendar format -- erases ical-filename!!!. | ||
| 610 | Argument DIARY-FILENAME is the input `diary-file'. | ||
| 611 | Argument ICAL-FILENAME is the output iCalendar file. | ||
| 612 | If DO-NOT-CLEAR-DIARY-FILE is not nil the target iCalendar file | ||
| 613 | is not erased." | ||
| 614 | (interactive "FExport diary data from file: | ||
| 615 | Finto iCalendar file: ") | ||
| 616 | (let ((result "") | ||
| 617 | (start 0) | ||
| 618 | (entry-main "") | ||
| 619 | (entry-rest "") | ||
| 620 | (header "") | ||
| 621 | (contents) | ||
| 622 | (oops nil) | ||
| 623 | (nonmarker (concat "^" (regexp-quote diary-nonmarking-symbol) | ||
| 624 | "?"))) | ||
| 625 | (save-current-buffer | ||
| 626 | (set-buffer (find-file diary-filename)) | ||
| 627 | (goto-char (point-min)) | ||
| 628 | (while (re-search-forward | ||
| 629 | "^\\([^ \t\n].*\\)\\(\n[ \t].*\\)*" nil t) | ||
| 630 | (setq entry-main (match-string 1)) | ||
| 631 | (if (match-beginning 2) | ||
| 632 | (setq entry-rest (match-string 2)) | ||
| 633 | (setq entry-rest "")) | ||
| 634 | (setq header (format "\nBEGIN:VEVENT\nUID:emacs%d%d%d" | ||
| 635 | (car (current-time)) | ||
| 636 | (cadr (current-time)) | ||
| 637 | (car (cddr (current-time))))) | ||
| 638 | (setq oops nil) | ||
| 639 | (cond | ||
| 640 | ;; anniversaries | ||
| 641 | ((string-match | ||
| 642 | (concat nonmarker | ||
| 643 | "%%(diary-anniversary \\([^)]+\\))\\s-*\\(.*\\)") | ||
| 644 | entry-main) | ||
| 645 | (icalendar-dmsg "diary-anniversary %s" entry-main) | ||
| 646 | (let* ((datetime (substring entry-main (match-beginning 1) | ||
| 647 | (match-end 1))) | ||
| 648 | (summary (icalendar-convert-string-for-export | ||
| 649 | (substring entry-main (match-beginning 2) | ||
| 650 | (match-end 2)))) | ||
| 651 | (startisostring (icalendar-datestring-to-isodate | ||
| 652 | datetime)) | ||
| 653 | (endisostring (icalendar-datestring-to-isodate | ||
| 654 | datetime 1))) | ||
| 655 | (setq contents | ||
| 656 | (concat "\nDTSTART;VALUE=DATE:" startisostring | ||
| 657 | "\nDTEND;VALUE=DATE:" endisostring | ||
| 658 | "\nSUMMARY:" summary | ||
| 659 | "\nRRULE:FREQ=YEARLY;INTERVAL=1" | ||
| 660 | ;; the following is redundant, | ||
| 661 | ;; but korganizer seems to expect this... ;( | ||
| 662 | ;; and evolution doesn't understand it... :( | ||
| 663 | ;; so... who is wrong?! | ||
| 664 | ";BYMONTH=" (substring startisostring 4 6) | ||
| 665 | ";BYMONTHDAY=" (substring startisostring 6 8) | ||
| 666 | ))) | ||
| 667 | (unless (string= entry-rest "") | ||
| 668 | (setq contents (concat contents "\nDESCRIPTION:" | ||
| 669 | (icalendar-convert-string-for-export | ||
| 670 | entry-rest))))) | ||
| 671 | ;; cyclic events | ||
| 672 | ;; %%(diary-cyclic ) | ||
| 673 | ((string-match | ||
| 674 | (concat nonmarker | ||
| 675 | "%%(diary-cyclic \\([^ ]+\\) +" | ||
| 676 | "\\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\))\\s-*\\(.*\\)") | ||
| 677 | entry-main) | ||
| 678 | (icalendar-dmsg "diary-cyclic %s" entry-main) | ||
| 679 | (let* ((frequency (substring entry-main (match-beginning 1) | ||
| 680 | (match-end 1))) | ||
| 681 | (datetime (substring entry-main (match-beginning 2) | ||
| 682 | (match-end 2))) | ||
| 683 | (summary (icalendar-convert-string-for-export | ||
| 684 | (substring entry-main (match-beginning 3) | ||
| 685 | (match-end 3)))) | ||
| 686 | (startisostring (icalendar-datestring-to-isodate | ||
| 687 | datetime)) | ||
| 688 | (endisostring (icalendar-datestring-to-isodate | ||
| 689 | datetime 1))) | ||
| 690 | (setq contents | ||
| 691 | (concat "\nDTSTART;VALUE=DATE:" startisostring | ||
| 692 | "\nDTEND;VALUE=DATE:" endisostring | ||
| 693 | "\nSUMMARY:" summary | ||
| 694 | "\nRRULE:FREQ=DAILY;INTERVAL=" frequency | ||
| 695 | ;; strange: korganizer does not expect | ||
| 696 | ;; BYSOMETHING here... | ||
| 697 | ))) | ||
| 698 | (unless (string= entry-rest "") | ||
| 699 | (setq contents (concat contents "\nDESCRIPTION:" | ||
| 700 | (icalendar-convert-string-for-export | ||
| 701 | entry-rest))))) | ||
| 702 | ;; diary-date -- FIXME | ||
| 703 | ((string-match | ||
| 704 | (concat nonmarker | ||
| 705 | "%%(diary-date \\([^)]+\\))\\s-*\\(.*\\)") | ||
| 706 | entry-main) | ||
| 707 | (icalendar-dmsg "diary-date %s" entry-main) | ||
| 708 | (setq oops t)) | ||
| 709 | ;; float events -- FIXME | ||
| 710 | ((string-match | ||
| 711 | (concat nonmarker | ||
| 712 | "%%(diary-float \\([^)]+\\))\\s-*\\(.*\\)") | ||
| 713 | entry-main) | ||
| 714 | (icalendar-dmsg "diary-float %s" entry-main) | ||
| 715 | (setq oops t)) | ||
| 716 | ;; block events | ||
| 717 | ((string-match | ||
| 718 | (concat nonmarker | ||
| 719 | "%%(diary-block \\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\) +" | ||
| 720 | "\\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\))\\s-*\\(.*\\)") | ||
| 721 | entry-main) | ||
| 722 | (icalendar-dmsg "diary-block %s" entry-main) | ||
| 723 | (let* ((startstring (substring entry-main (match-beginning 1) | ||
| 724 | (match-end 1))) | ||
| 725 | (endstring (substring entry-main (match-beginning 2) | ||
| 726 | (match-end 2))) | ||
| 727 | (summary (icalendar-convert-string-for-export | ||
| 728 | (substring entry-main (match-beginning 3) | ||
| 729 | (match-end 3)))) | ||
| 730 | (startisostring (icalendar-datestring-to-isodate | ||
| 731 | startstring)) | ||
| 732 | (endisostring (icalendar-datestring-to-isodate | ||
| 733 | endstring 1))) | ||
| 734 | (setq contents | ||
| 735 | (concat "\nDTSTART;VALUE=DATE:" startisostring | ||
| 736 | "\nDTEND;VALUE=DATE:" endisostring | ||
| 737 | "\nSUMMARY:" summary | ||
| 738 | )) | ||
| 739 | (unless (string= entry-rest "") | ||
| 740 | (setq contents (concat contents "\nDESCRIPTION:" | ||
| 741 | (icalendar-convert-string-for-export | ||
| 742 | entry-rest)))))) | ||
| 743 | ;; other sexp diary entries -- FIXME | ||
| 744 | ((string-match | ||
| 745 | (concat nonmarker | ||
| 746 | "%%(\\([^)]+\\))\\s-*\\(.*\\)") | ||
| 747 | entry-main) | ||
| 748 | (icalendar-dmsg "diary-sexp %s" entry-main) | ||
| 749 | (setq oops t)) | ||
| 750 | ;; weekly by day | ||
| 751 | ;; Monday 8:30 Team meeting | ||
| 752 | ((and (string-match | ||
| 753 | (concat nonmarker | ||
| 754 | "\\([a-z]+\\)\\s-+" | ||
| 755 | "\\(0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?" | ||
| 756 | "\\(-0?" | ||
| 757 | "\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?" | ||
| 758 | "\\)?" | ||
| 759 | "\\s-*\\(.*\\)$") | ||
| 760 | entry-main) | ||
| 761 | (icalendar-get-weekday-abbrev | ||
| 762 | (substring entry-main (match-beginning 1) (match-end 1)))) | ||
| 763 | (icalendar-dmsg "weekly %s" entry-main) | ||
| 764 | (let* ((day (icalendar-get-weekday-abbrev | ||
| 765 | (substring entry-main (match-beginning 1) | ||
| 766 | (match-end 1)))) | ||
| 767 | (starttimestring (icalendar-diarytime-to-isotime | ||
| 768 | (if (match-beginning 3) | ||
| 769 | (substring entry-main | ||
| 770 | (match-beginning 3) | ||
| 771 | (match-end 3)) | ||
| 772 | nil) | ||
| 773 | (if (match-beginning 4) | ||
| 774 | (substring entry-main | ||
| 775 | (match-beginning 4) | ||
| 776 | (match-end 4)) | ||
| 777 | nil))) | ||
| 778 | (endtimestring (icalendar-diarytime-to-isotime | ||
| 779 | (if (match-beginning 6) | ||
| 780 | (substring entry-main | ||
| 781 | (match-beginning 6) | ||
| 782 | (match-end 6)) | ||
| 783 | nil) | ||
| 784 | (if (match-beginning 7) | ||
| 785 | (substring entry-main | ||
| 786 | (match-beginning 7) | ||
| 787 | (match-end 7)) | ||
| 788 | nil))) | ||
| 789 | (summary (icalendar-convert-string-for-export | ||
| 790 | (substring entry-main (match-beginning 8) | ||
| 791 | (match-end 8))))) | ||
| 792 | (when starttimestring | ||
| 793 | (unless endtimestring | ||
| 794 | (let ((time (read (icalendar-rris "^T0?" "" | ||
| 795 | starttimestring)))) | ||
| 796 | (setq endtimestring (format "T%06d" (+ 10000 time)))))) | ||
| 797 | (setq contents | ||
| 798 | (concat "\nDTSTART" | ||
| 799 | (if starttimestring "" ";VALUE=DATE") | ||
| 800 | ":19000101" ;; FIXME? Probability that this | ||
| 801 | ;; is the right day is 1/7 | ||
| 802 | (or starttimestring "") | ||
| 803 | "\nDTEND" | ||
| 804 | (if endtimestring "" ";VALUE=DATE") | ||
| 805 | ":19000101" ;; FIXME? | ||
| 806 | (or endtimestring "") | ||
| 807 | "\nSUMMARY:" summary | ||
| 808 | "\nRRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=" day | ||
| 809 | ))) | ||
| 810 | (unless (string= entry-rest "") | ||
| 811 | (setq contents (concat contents "\nDESCRIPTION:" | ||
| 812 | (icalendar-convert-string-for-export | ||
| 813 | entry-rest))))) | ||
| 814 | ;; yearly by day | ||
| 815 | ;; 1 May Tag der Arbeit | ||
| 816 | ((string-match | ||
| 817 | (concat nonmarker | ||
| 818 | (if european-calendar-style | ||
| 819 | "0?\\([1-9]+[0-9]?\\)\\s-+\\([a-z]+\\)\\s-+" | ||
| 820 | "\\([a-z]+\\)\\s-+0?\\([1-9]+[0-9]?\\)\\s-+") | ||
| 821 | "\\*?\\s-*" | ||
| 822 | "\\(0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?" | ||
| 823 | "\\(" | ||
| 824 | "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?" | ||
| 825 | "\\)?" | ||
| 826 | "\\s-*\\([^0-9]+.*\\)$"; must not match years | ||
| 827 | ) | ||
| 828 | entry-main) | ||
| 829 | (icalendar-dmsg "yearly %s" entry-main) | ||
| 830 | (let* ((daypos (if european-calendar-style 1 2)) | ||
| 831 | (monpos (if european-calendar-style 2 1)) | ||
| 832 | (day (read (substring entry-main (match-beginning daypos) | ||
| 833 | (match-end daypos)))) | ||
| 834 | (month (icalendar-get-month-number | ||
| 835 | (substring entry-main (match-beginning monpos) | ||
| 836 | (match-end monpos)))) | ||
| 837 | (starttimestring (icalendar-diarytime-to-isotime | ||
| 838 | (if (match-beginning 4) | ||
| 839 | (substring entry-main | ||
| 840 | (match-beginning 4) | ||
| 841 | (match-end 4)) | ||
| 842 | nil) | ||
| 843 | (if (match-beginning 5) | ||
| 844 | (substring entry-main | ||
| 845 | (match-beginning 5) | ||
| 846 | (match-end 5)) | ||
| 847 | nil))) | ||
| 848 | (endtimestring (icalendar-diarytime-to-isotime | ||
| 849 | (if (match-beginning 7) | ||
| 850 | (substring entry-main | ||
| 851 | (match-beginning 7) | ||
| 852 | (match-end 7)) | ||
| 853 | nil) | ||
| 854 | (if (match-beginning 8) | ||
| 855 | (substring entry-main | ||
| 856 | (match-beginning 8) | ||
| 857 | (match-end 8)) | ||
| 858 | nil))) | ||
| 859 | (summary (icalendar-convert-string-for-export | ||
| 860 | (substring entry-main (match-beginning 9) | ||
| 861 | (match-end 9))))) | ||
| 862 | (when starttimestring | ||
| 863 | (unless endtimestring | ||
| 864 | (let ((time (read (icalendar-rris "^T0?" "" | ||
| 865 | starttimestring)))) | ||
| 866 | (setq endtimestring (format "T%06d" (+ 10000 time)))))) | ||
| 867 | (setq contents | ||
| 868 | (concat "\nDTSTART" | ||
| 869 | (if starttimestring "" ";VALUE=DATE") | ||
| 870 | (format ":1900%02d%02d" month day) | ||
| 871 | (or starttimestring "") | ||
| 872 | "\nDTEND" | ||
| 873 | (if endtimestring "" ";VALUE=DATE") | ||
| 874 | (format ":1900%02d%02d" month day) | ||
| 875 | (or endtimestring "") | ||
| 876 | "\nSUMMARY:" summary | ||
| 877 | "\nRRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=" | ||
| 878 | (format "%2d" month) | ||
| 879 | ";BYMONTHDAY=" | ||
| 880 | (format "%2d" day) | ||
| 881 | ))) | ||
| 882 | (unless (string= entry-rest "") | ||
| 883 | (setq contents (concat contents "\nDESCRIPTION:" | ||
| 884 | (icalendar-convert-string-for-export | ||
| 885 | entry-rest))))) | ||
| 886 | ;; "ordinary" events, start and end time given | ||
| 887 | ;; 1 Feb 2003 Hs Hochzeitsfeier, Dreieich | ||
| 888 | ((string-match | ||
| 889 | (concat nonmarker | ||
| 890 | "\\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\)\\s-+" | ||
| 891 | "\\(0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?" | ||
| 892 | "\\(" | ||
| 893 | "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?" | ||
| 894 | "\\)?" | ||
| 895 | "\\s-*\\(.*\\)") | ||
| 896 | entry-main) | ||
| 897 | (icalendar-dmsg "ordinary %s" entry-main) | ||
| 898 | (let* ((datestring (icalendar-datestring-to-isodate | ||
| 899 | (substring entry-main (match-beginning 1) | ||
| 900 | (match-end 1)))) | ||
| 901 | (starttimestring (icalendar-diarytime-to-isotime | ||
| 902 | (if (match-beginning 3) | ||
| 903 | (substring entry-main | ||
| 904 | (match-beginning 3) | ||
| 905 | (match-end 3)) | ||
| 906 | nil) | ||
| 907 | (if (match-beginning 4) | ||
| 908 | (substring entry-main | ||
| 909 | (match-beginning 4) | ||
| 910 | (match-end 4)) | ||
| 911 | nil))) | ||
| 912 | (endtimestring (icalendar-diarytime-to-isotime | ||
| 913 | (if (match-beginning 6) | ||
| 914 | (substring entry-main | ||
| 915 | (match-beginning 6) | ||
| 916 | (match-end 6)) | ||
| 917 | nil) | ||
| 918 | (if (match-beginning 7) | ||
| 919 | (substring entry-main | ||
| 920 | (match-beginning 7) | ||
| 921 | (match-end 7)) | ||
| 922 | nil))) | ||
| 923 | (summary (icalendar-convert-string-for-export | ||
| 924 | (substring entry-main (match-beginning 8) | ||
| 925 | (match-end 8))))) | ||
| 926 | (when starttimestring | ||
| 927 | (unless endtimestring | ||
| 928 | (let ((time (read (icalendar-rris "^T0?" "" | ||
| 929 | starttimestring)))) | ||
| 930 | (setq endtimestring (format "T%06d" (+ 10000 time)))))) | ||
| 931 | (setq contents (format | ||
| 932 | "\nDTSTART%s:%s%s\nDTEND%s:%s%s\nSUMMARY:%s" | ||
| 933 | (if starttimestring "" ";VALUE=DATE") | ||
| 934 | datestring | ||
| 935 | (or starttimestring "") | ||
| 936 | (if endtimestring "" | ||
| 937 | ";VALUE=DATE") | ||
| 938 | datestring | ||
| 939 | (or endtimestring "") | ||
| 940 | summary)) | ||
| 941 | (unless (string= entry-rest "") | ||
| 942 | (setq contents (concat contents "\nDESCRIPTION:" | ||
| 943 | (icalendar-convert-string-for-export | ||
| 944 | entry-rest)))))) | ||
| 945 | ;; everything else | ||
| 946 | (t | ||
| 947 | ;; Oops! what's that? | ||
| 948 | (setq oops t))) | ||
| 949 | (if oops | ||
| 950 | (message "Cannot export entry on line %d" | ||
| 951 | (count-lines (point-min) (point))) | ||
| 952 | (setq result (concat result header contents "\nEND:VEVENT")))) | ||
| 953 | ;; we're done, insert everything into the file | ||
| 954 | (let ((coding-system-for-write 'utf8)) | ||
| 955 | (set-buffer (find-file ical-filename)) | ||
| 956 | (unless do-not-clear-diary-file | ||
| 957 | (erase-buffer)) | ||
| 958 | (insert | ||
| 959 | "BEGIN:VCALENDAR\nPRODID:-//Emacs//NONSGML icalendar.el//EN") | ||
| 960 | (insert "\nVERSION:2.0") | ||
| 961 | (insert result) | ||
| 962 | (insert "\nEND:VCALENDAR\n"))))) | ||
| 963 | |||
| 964 | |||
| 965 | ;; ====================================================================== | ||
| 966 | ;; import -- convert icalendar to emacs-diary | ||
| 967 | ;; ====================================================================== | ||
| 968 | |||
| 969 | ;; user function | ||
| 970 | (defun icalendar-import-file (ical-filename diary-filename | ||
| 971 | &optional non-marking | ||
| 972 | do-not-clear-diary-file) | ||
| 973 | "Import a iCalendar file and save to a diary file -- erases diary-file! | ||
| 974 | Argument ICAL-FILENAME output iCalendar file. | ||
| 975 | Argument DIARY-FILENAME input `diary-file'. | ||
| 976 | Optional argument NON-MARKING determines whether events are created as | ||
| 977 | non-marking or not. | ||
| 978 | If DO-NOT-CLEAR-DIARY-FILE is not nil the target diary file is | ||
| 979 | not erased." | ||
| 980 | (interactive "fImport iCalendar data from file: | ||
| 981 | Finto diary file (will be erased!): | ||
| 982 | p") | ||
| 983 | ;; clean up the diary file | ||
| 984 | (save-current-buffer | ||
| 985 | (unless do-not-clear-diary-file | ||
| 986 | ;; clear the target diary file | ||
| 987 | (set-buffer (find-file diary-filename)) | ||
| 988 | (erase-buffer)) | ||
| 989 | ;; now load and convert from the ical file | ||
| 990 | (set-buffer (find-file ical-filename)) | ||
| 991 | (icalendar-extract-ical-from-buffer diary-filename t non-marking))) | ||
| 992 | |||
| 993 | ; user function | ||
| 994 | (defun icalendar-extract-ical-from-buffer (&optional | ||
| 995 | diary-file do-not-ask | ||
| 996 | non-marking) | ||
| 997 | "Extract iCalendar events from current buffer. | ||
| 998 | |||
| 999 | This function searches the current buffer for the first iCalendar | ||
| 1000 | object, reads it and adds all VEVENT elements to the diary | ||
| 1001 | DIARY-FILE. | ||
| 1002 | |||
| 1003 | It will ask for each appointment whether to add it to the diary | ||
| 1004 | when DO-NOT-ASK is non-nil. When called interactively, | ||
| 1005 | DO-NOT-ASK is set to t, so that you are asked fore each event. | ||
| 1006 | |||
| 1007 | NON-MARKING determines whether diary events are created as | ||
| 1008 | non-marking. | ||
| 1009 | |||
| 1010 | This function attempts to notify about problems that occur when | ||
| 1011 | reading, parsing, or converting iCalendar data!" | ||
| 1012 | (interactive) | ||
| 1013 | (save-current-buffer | ||
| 1014 | ;; prepare ical | ||
| 1015 | (message "Preparing icalendar...") | ||
| 1016 | (set-buffer (icalendar-get-unfolded-buffer (current-buffer))) | ||
| 1017 | (goto-char (point-min)) | ||
| 1018 | (message "Preparing icalendar...done") | ||
| 1019 | (if (re-search-forward "^BEGIN:VCALENDAR\\s-*$" nil t) | ||
| 1020 | (let (ical-contents ical-errors) | ||
| 1021 | ;; read ical | ||
| 1022 | (message "Reading icalendar...") | ||
| 1023 | (beginning-of-line) | ||
| 1024 | (setq ical-contents (icalendar-read-element nil nil)) | ||
| 1025 | (message "Reading icalendar...done") | ||
| 1026 | ;; convert ical | ||
| 1027 | (message "Converting icalendar...") | ||
| 1028 | (setq ical-errors (icalendar-convert-ical-to-diary | ||
| 1029 | ical-contents | ||
| 1030 | diary-file do-not-ask non-marking)) | ||
| 1031 | (when diary-file | ||
| 1032 | ;; save the diary file | ||
| 1033 | (save-current-buffer | ||
| 1034 | (set-buffer (find-buffer-visiting diary-file)) | ||
| 1035 | (save-buffer))) | ||
| 1036 | (message "Converting icalendar...done") | ||
| 1037 | (if (and ical-errors (y-or-n-p | ||
| 1038 | (concat "Something went wrong -- " | ||
| 1039 | "do you want to see the " | ||
| 1040 | "error log? "))) | ||
| 1041 | (switch-to-buffer " *icalendar-errors*"))) | ||
| 1042 | (message | ||
| 1043 | "Current buffer does not contain icalendar contents!")))) | ||
| 1044 | |||
| 1045 | ;; ---------------------------------------------------------------------- | ||
| 1046 | ;; private area | ||
| 1047 | ;; ---------------------------------------------------------------------- | ||
| 1048 | (defun icalendar-format-ical-event (event) | ||
| 1049 | "Create a string representation of an iCalendar EVENT." | ||
| 1050 | (let ((string icalendar-import-format) | ||
| 1051 | (conversion-list | ||
| 1052 | '(("%d" DESCRIPTION icalendar-import-format-description) | ||
| 1053 | ("%s" SUMMARY icalendar-import-format-subject) | ||
| 1054 | ("%l" LOCATION icalendar-import-format-location) | ||
| 1055 | ("%o" ORGANIZER icalendar-import-format-organizer)))) | ||
| 1056 | ;; convert the specifiers in the format string | ||
| 1057 | (mapcar (lambda (i) | ||
| 1058 | (let* ((spec (car i)) | ||
| 1059 | (prop (cadr i)) | ||
| 1060 | (format (car (cddr i))) | ||
| 1061 | (contents (icalendar-get-event-property event prop)) | ||
| 1062 | (formatted-contents "")) | ||
| 1063 | ;;(message "%s" event) | ||
| 1064 | ;;(message "contents%s = %s" prop contents) | ||
| 1065 | (when (and contents (> (length contents) 0)) | ||
| 1066 | (setq formatted-contents | ||
| 1067 | (icalendar-rris "%s" | ||
| 1068 | (icalendar-convert-for-import | ||
| 1069 | contents) | ||
| 1070 | (symbol-value format)))) | ||
| 1071 | (setq string (icalendar-rris spec | ||
| 1072 | formatted-contents | ||
| 1073 | string)))) | ||
| 1074 | conversion-list) | ||
| 1075 | string)) | ||
| 1076 | |||
| 1077 | (defun icalendar-convert-ical-to-diary (ical-list diary-file | ||
| 1078 | &optional do-not-ask | ||
| 1079 | non-marking) | ||
| 1080 | "Convert an iCalendar file to an Emacs diary file. | ||
| 1081 | Import VEVENTS from the iCalendar object ICAL-LIST and saves them to a | ||
| 1082 | DIARY-FILE. If DO-NOT-ASK is nil the user is asked for each event | ||
| 1083 | whether to actually import it. NON-MARKING determines whether diary | ||
| 1084 | events are created as non-marking. | ||
| 1085 | This function attempts to return t if something goes wrong. In this | ||
| 1086 | case an error string which describes all the errors and problems is | ||
| 1087 | written into the buffer ` *icalendar-errors*'." | ||
| 1088 | (let* ((ev (icalendar-all-events ical-list)) | ||
| 1089 | (error-string "") | ||
| 1090 | (event-ok t) | ||
| 1091 | (found-error nil) | ||
| 1092 | e diary-string) | ||
| 1093 | ;; step through all events/appointments | ||
| 1094 | (while ev | ||
| 1095 | (setq e (car ev)) | ||
| 1096 | (setq ev (cdr ev)) | ||
| 1097 | (setq event-ok nil) | ||
| 1098 | (condition-case error-val | ||
| 1099 | (let* ((dtstart (icalendar-decode-isodatetime | ||
| 1100 | (icalendar-get-event-property e 'DTSTART))) | ||
| 1101 | (start-d (calendar-date-string | ||
| 1102 | (icalendar-datetime-to-noneuropean-date | ||
| 1103 | dtstart) | ||
| 1104 | t t)) | ||
| 1105 | (start-t (icalendar-datetime-to-colontime dtstart)) | ||
| 1106 | (dtend (icalendar-decode-isodatetime | ||
| 1107 | (icalendar-get-event-property e 'DTEND))) | ||
| 1108 | end-d | ||
| 1109 | end-t | ||
| 1110 | (subject (icalendar-convert-for-import | ||
| 1111 | (or (icalendar-get-event-property e 'SUMMARY) | ||
| 1112 | "No Subject"))) | ||
| 1113 | (rrule (icalendar-get-event-property e 'RRULE)) | ||
| 1114 | (rdate (icalendar-get-event-property e 'RDATE)) | ||
| 1115 | (duration (icalendar-get-event-property e 'DURATION))) | ||
| 1116 | (icalendar-dmsg "%s: %s" start-d subject) | ||
| 1117 | (when duration | ||
| 1118 | (let ((dtend2 (icalendar-add-decoded-times | ||
| 1119 | dtstart | ||
| 1120 | (icalendar-decode-isoduration duration)))) | ||
| 1121 | (if (and dtend (not (eq dtend dtend2))) | ||
| 1122 | (message "Inconsistent endtime and duration for %s" | ||
| 1123 | subject)) | ||
| 1124 | (setq dtend dtend2))) | ||
| 1125 | (setq end-d (if dtend | ||
| 1126 | (calendar-date-string | ||
| 1127 | (icalendar-datetime-to-noneuropean-date | ||
| 1128 | dtend) | ||
| 1129 | t t) | ||
| 1130 | start-d)) | ||
| 1131 | (setq end-t (if dtend | ||
| 1132 | (icalendar-datetime-to-colontime dtend) | ||
| 1133 | start-t)) | ||
| 1134 | (icalendar-dmsg "start-d: %s, end-d: %s" start-d end-d) | ||
| 1135 | (cond | ||
| 1136 | ;; recurring event | ||
| 1137 | (rrule | ||
| 1138 | (icalendar-dmsg "recurring event") | ||
| 1139 | (let* ((rrule-props (icalendar-split-value rrule)) | ||
| 1140 | (frequency (car (cdr (assoc 'FREQ rrule-props)))) | ||
| 1141 | (until (car (cdr (assoc 'UNTIL rrule-props)))) | ||
| 1142 | (interval (read (car (cdr (assoc 'INTERVAL | ||
| 1143 | rrule-props)))))) | ||
| 1144 | (cond ((string-equal frequency "WEEKLY") | ||
| 1145 | (if (not start-t) | ||
| 1146 | (progn | ||
| 1147 | ;; weekly and all-day | ||
| 1148 | (icalendar-dmsg "weekly all-day") | ||
| 1149 | (setq diary-string | ||
| 1150 | (format | ||
| 1151 | "%%%%(diary-cyclic %d %s)" | ||
| 1152 | (* interval 7) | ||
| 1153 | (icalendar-datetime-to-european-date | ||
| 1154 | dtstart)))) | ||
| 1155 | ;; weekly and not all-day | ||
| 1156 | (let* ((byday (cadr (assoc 'BYDAY rrule-props))) | ||
| 1157 | (weekday | ||
| 1158 | (cdr (rassoc | ||
| 1159 | byday | ||
| 1160 | icalendar-weekdayabbrev-table)))) | ||
| 1161 | (icalendar-dmsg "weekly not-all-day") | ||
| 1162 | (if weekday | ||
| 1163 | (setq diary-string | ||
| 1164 | (format "%s %s%s%s" weekday | ||
| 1165 | start-t (if end-t "-" "") | ||
| 1166 | (or end-t ""))) | ||
| 1167 | ;; FIXME!!!! | ||
| 1168 | ;; DTSTART;VALUE=DATE-TIME:20030919T090000 | ||
| 1169 | ;; DTEND;VALUE=DATE-TIME:20030919T113000 | ||
| 1170 | (setq diary-string | ||
| 1171 | (format | ||
| 1172 | "%%%%(diary-cyclic %s %s) %s%s%s" | ||
| 1173 | (* interval 7) | ||
| 1174 | (icalendar-datetime-to-european-date | ||
| 1175 | dtstart) | ||
| 1176 | start-t (if end-t "-" "") (or end-t "")))) | ||
| 1177 | (setq event-ok t)))) | ||
| 1178 | ;; yearly | ||
| 1179 | ((string-equal frequency "YEARLY") | ||
| 1180 | (icalendar-dmsg "yearly") | ||
| 1181 | (setq diary-string | ||
| 1182 | (format | ||
| 1183 | "%%%%(diary-anniversary %s)" | ||
| 1184 | (icalendar-datetime-to-european-date dtstart))) | ||
| 1185 | (setq event-ok t)) | ||
| 1186 | ;; FIXME: war auskommentiert: | ||
| 1187 | ((and (string-equal frequency "DAILY") | ||
| 1188 | ;;(not (string= start-d end-d)) | ||
| 1189 | ;;(not start-t) | ||
| 1190 | ;;(not end-t) | ||
| 1191 | ) | ||
| 1192 | (let ((ds (icalendar-datetime-to-noneuropean-date | ||
| 1193 | (icalendar-decode-isodatetime | ||
| 1194 | (icalendar-get-event-property e | ||
| 1195 | 'DTSTART)))) | ||
| 1196 | (de (icalendar-datetime-to-noneuropean-date | ||
| 1197 | (icalendar-decode-isodatetime | ||
| 1198 | until)))) | ||
| 1199 | (setq diary-string | ||
| 1200 | (format | ||
| 1201 | "%%%%(diary-block %d %d %d %d %d %d)" | ||
| 1202 | (nth 1 ds) (nth 0 ds) (nth 2 ds) | ||
| 1203 | (nth 1 de) (nth 0 de) (nth 2 de)))) | ||
| 1204 | (setq event-ok t))) | ||
| 1205 | )) | ||
| 1206 | (rdate | ||
| 1207 | (icalendar-dmsg "rdate event") | ||
| 1208 | (setq diary-string "") | ||
| 1209 | (mapcar (lambda (datestring) | ||
| 1210 | (setq diary-string | ||
| 1211 | (concat diary-string | ||
| 1212 | (format "......")))) | ||
| 1213 | (icalendar-split-value rdate))) | ||
| 1214 | ;; non-recurring event | ||
| 1215 | ;; long event | ||
| 1216 | ((not (string= start-d end-d)) | ||
| 1217 | (icalendar-dmsg "non-recurring event") | ||
| 1218 | (let ((ds (icalendar-datetime-to-noneuropean-date dtstart)) | ||
| 1219 | (de (icalendar-datetime-to-noneuropean-date dtend))) | ||
| 1220 | (setq diary-string | ||
| 1221 | (format "%%%%(diary-block %d %d %d %d %d %d)" | ||
| 1222 | (nth 1 ds) (nth 0 ds) (nth 2 ds) | ||
| 1223 | (nth 1 de) (nth 0 de) (nth 2 de)))) | ||
| 1224 | (setq event-ok t)) | ||
| 1225 | ;; not all-day | ||
| 1226 | ((and start-t (or (not end-t) | ||
| 1227 | (not (string= start-t end-t)))) | ||
| 1228 | (icalendar-dmsg "not all day event") | ||
| 1229 | (cond (end-t | ||
| 1230 | (setq diary-string (format "%s %s-%s" start-d | ||
| 1231 | start-t end-t))) | ||
| 1232 | (t | ||
| 1233 | (setq diary-string (format "%s %s" start-d | ||
| 1234 | start-t)))) | ||
| 1235 | (setq event-ok t)) | ||
| 1236 | ;; all-day event | ||
| 1237 | (t | ||
| 1238 | (icalendar-dmsg "all day event") | ||
| 1239 | (setq diary-string start-d) | ||
| 1240 | (setq event-ok t))) | ||
| 1241 | ;; add all other elements unless the user doesn't want to have | ||
| 1242 | ;; them | ||
| 1243 | (if event-ok | ||
| 1244 | (progn | ||
| 1245 | (setq diary-string | ||
| 1246 | (concat diary-string " " | ||
| 1247 | (icalendar-format-ical-event e))) | ||
| 1248 | (if do-not-ask (setq subject nil)) | ||
| 1249 | (icalendar-add-diary-entry diary-string diary-file | ||
| 1250 | non-marking subject)) | ||
| 1251 | ;; event was not ok | ||
| 1252 | (setq found-error t) | ||
| 1253 | (setq error-string | ||
| 1254 | (format "%s\nCannot handle this event:%s" | ||
| 1255 | error-string e)))) | ||
| 1256 | ;; handle errors | ||
| 1257 | (error | ||
| 1258 | (message "Ignoring event \"%s\"" e) | ||
| 1259 | (setq found-error t) | ||
| 1260 | (setq error-string (format "%s\nCannot handle this event: %s" | ||
| 1261 | error-string e))))) | ||
| 1262 | (if found-error | ||
| 1263 | (save-current-buffer | ||
| 1264 | (set-buffer (get-buffer-create " *icalendar-errors*")) | ||
| 1265 | (erase-buffer) | ||
| 1266 | (insert error-string))) | ||
| 1267 | (message "Converting icalendar...done") | ||
| 1268 | found-error)) | ||
| 1269 | |||
| 1270 | (defun icalendar-add-diary-entry (string diary-file non-marking | ||
| 1271 | &optional subject) | ||
| 1272 | "Add STRING to the diary file DIARY-FILE. | ||
| 1273 | STRING must be a properly formatted valid diary entry. NON-MARKING | ||
| 1274 | determines whether diary events are created as non-marking. If | ||
| 1275 | SUBJECT is not nil it must be a string that gives the subject of the | ||
| 1276 | entry. In this case the user will be asked whether he wants to insert | ||
| 1277 | the entry." | ||
| 1278 | (when (or (not subject) ; | ||
| 1279 | (y-or-n-p (format "Add appointment for `%s' to diary? " | ||
| 1280 | subject))) | ||
| 1281 | (when subject | ||
| 1282 | (setq non-marking | ||
| 1283 | (y-or-n-p (format "Make appointment non-marking? ")))) | ||
| 1284 | (save-window-excursion | ||
| 1285 | (unless diary-file | ||
| 1286 | (setq diary-file | ||
| 1287 | (read-file-name "Add appointment to this diary file: "))) | ||
| 1288 | (make-diary-entry string non-marking diary-file)))) | ||
| 1289 | |||
| 1290 | ;; ====================================================================== | ||
| 1291 | ;; (add-hook 'list-diary-entries-hook 'include-icalendar-files) | ||
| 1292 | ;; ====================================================================== | ||
| 1293 | (defun include-icalendar-files () | ||
| 1294 | "Not yet implemented.") | ||
| 1295 | |||
| 1296 | (provide 'icalendar) | ||
| 1297 | |||
| 1298 | ;; arch-tag: 74fdbe8e-0451-4e38-bb61-4416e822f4fc | ||
| 1299 | ;;; icalendar.el ends here | ||
diff --git a/lisp/gnus/ChangeLog b/lisp/gnus/ChangeLog index 907ad5f3411..f4b77297867 100644 --- a/lisp/gnus/ChangeLog +++ b/lisp/gnus/ChangeLog | |||
| @@ -1,3 +1,21 @@ | |||
| 1 | 2004-10-06 Katsumi Yamaoka <yamaoka@jpl.org> | ||
| 2 | |||
| 3 | * gnus-group.el (gnus-update-group-mark-positions): | ||
| 4 | * gnus-sum.el (gnus-update-summary-mark-positions): | ||
| 5 | * message.el (message-check-news-body-syntax): | ||
| 6 | * gnus-msg.el (gnus-debug): Use mm-string-as-multibyte instead | ||
| 7 | of string-as-multibyte. | ||
| 8 | |||
| 9 | * gnus-sum.el (gnus-summary-insert-subject): Remove redundant setq. | ||
| 10 | |||
| 11 | 2004-10-05 Juri Linkov <juri@jurta.org> | ||
| 12 | |||
| 13 | * gnus-group.el (gnus-update-group-mark-positions): | ||
| 14 | * gnus-sum.el (gnus-update-summary-mark-positions): | ||
| 15 | * message.el (message-check-news-body-syntax): | ||
| 16 | * gnus-msg.el (gnus-debug): Use `string-as-multibyte' to convert | ||
| 17 | 8-bit unibyte values to a multibyte string for search functions. | ||
| 18 | |||
| 1 | 2004-10-01 Katsumi Yamaoka <yamaoka@jpl.org> | 19 | 2004-10-01 Katsumi Yamaoka <yamaoka@jpl.org> |
| 2 | 20 | ||
| 3 | * gnus-sum.el (gnus-summary-toggle-header): Make it work even if | 21 | * gnus-sum.el (gnus-summary-toggle-header): Make it work even if |
diff --git a/lisp/gnus/gnus-group.el b/lisp/gnus/gnus-group.el index 9f7b259e066..435acb1d6c2 100644 --- a/lisp/gnus/gnus-group.el +++ b/lisp/gnus/gnus-group.el | |||
| @@ -1046,7 +1046,8 @@ The following commands are available: | |||
| 1046 | (gnus-group-insert-group-line "dummy.group" 0 nil 0 nil) | 1046 | (gnus-group-insert-group-line "dummy.group" 0 nil 0 nil) |
| 1047 | (goto-char (point-min)) | 1047 | (goto-char (point-min)) |
| 1048 | (setq gnus-group-mark-positions | 1048 | (setq gnus-group-mark-positions |
| 1049 | (list (cons 'process (and (search-forward "\200" nil t) | 1049 | (list (cons 'process (and (search-forward |
| 1050 | (mm-string-as-multibyte "\200") nil t) | ||
| 1050 | (- (point) 2)))))))) | 1051 | (- (point) 2)))))))) |
| 1051 | 1052 | ||
| 1052 | (defun gnus-mouse-pick-group (e) | 1053 | (defun gnus-mouse-pick-group (e) |
diff --git a/lisp/gnus/gnus-msg.el b/lisp/gnus/gnus-msg.el index 33531e7f8a4..7dcef4b813b 100644 --- a/lisp/gnus/gnus-msg.el +++ b/lisp/gnus/gnus-msg.el | |||
| @@ -1534,7 +1534,8 @@ The source file has to be in the Emacs load path." | |||
| 1534 | ;; Remove any control chars - they seem to cause trouble for some | 1534 | ;; Remove any control chars - they seem to cause trouble for some |
| 1535 | ;; mailers. (Byte-compiled output from the stuff above.) | 1535 | ;; mailers. (Byte-compiled output from the stuff above.) |
| 1536 | (goto-char point) | 1536 | (goto-char point) |
| 1537 | (while (re-search-forward "[\000-\010\013-\037\200-\237]" nil t) | 1537 | (while (re-search-forward (mm-string-as-multibyte |
| 1538 | "[\000-\010\013-\037\200-\237]") nil t) | ||
| 1538 | (replace-match (format "\\%03o" (string-to-char (match-string 0))) | 1539 | (replace-match (format "\\%03o" (string-to-char (match-string 0))) |
| 1539 | t t)))) | 1540 | t t)))) |
| 1540 | 1541 | ||
diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el index 92ba2346949..84de9c4e1ab 100644 --- a/lisp/gnus/gnus-sum.el +++ b/lisp/gnus/gnus-sum.el | |||
| @@ -3231,20 +3231,24 @@ buffer that was in action when the last article was fetched." | |||
| 3231 | [0 "" "" "05 Apr 2001 23:33:09 +0400" "" "" 0 0 "" nil] | 3231 | [0 "" "" "05 Apr 2001 23:33:09 +0400" "" "" 0 0 "" nil] |
| 3232 | 0 nil t 128 t nil "" nil 1) | 3232 | 0 nil t 128 t nil "" nil 1) |
| 3233 | (goto-char (point-min)) | 3233 | (goto-char (point-min)) |
| 3234 | (setq pos (list (cons 'unread (and (search-forward "\200" nil t) | 3234 | (setq pos (list (cons 'unread |
| 3235 | (- (point) (point-min) 1))))) | 3235 | (and (search-forward |
| 3236 | (mm-string-as-multibyte "\200") nil t) | ||
| 3237 | (- (point) (point-min) 1))))) | ||
| 3236 | (goto-char (point-min)) | 3238 | (goto-char (point-min)) |
| 3237 | (push (cons 'replied (and (search-forward "\201" nil t) | 3239 | (push (cons 'replied (and (search-forward |
| 3240 | (mm-string-as-multibyte "\201") nil t) | ||
| 3238 | (- (point) (point-min) 1))) | 3241 | (- (point) (point-min) 1))) |
| 3239 | pos) | 3242 | pos) |
| 3240 | (goto-char (point-min)) | 3243 | (goto-char (point-min)) |
| 3241 | (push (cons 'score (and (search-forward "\202" nil t) | 3244 | (push (cons 'score (and (search-forward |
| 3245 | (mm-string-as-multibyte "\202") nil t) | ||
| 3242 | (- (point) (point-min) 1))) | 3246 | (- (point) (point-min) 1))) |
| 3243 | pos) | 3247 | pos) |
| 3244 | (goto-char (point-min)) | 3248 | (goto-char (point-min)) |
| 3245 | (push (cons 'download | 3249 | (push (cons 'download (and (search-forward |
| 3246 | (and (search-forward "\203" nil t) | 3250 | (mm-string-as-multibyte "\203") nil t) |
| 3247 | (- (point) (point-min) 1))) | 3251 | (- (point) (point-min) 1))) |
| 3248 | pos))) | 3252 | pos))) |
| 3249 | (setq gnus-summary-mark-positions pos)))) | 3253 | (setq gnus-summary-mark-positions pos)))) |
| 3250 | 3254 | ||
| @@ -6009,8 +6013,7 @@ the subject line on." | |||
| 6009 | ;; Remove list identifiers from subject. | 6013 | ;; Remove list identifiers from subject. |
| 6010 | (when gnus-list-identifiers | 6014 | (when gnus-list-identifiers |
| 6011 | (let ((gnus-newsgroup-headers (list header))) | 6015 | (let ((gnus-newsgroup-headers (list header))) |
| 6012 | (gnus-summary-remove-list-identifiers) | 6016 | (gnus-summary-remove-list-identifiers))) |
| 6013 | (setq header (car gnus-newsgroup-headers)))) | ||
| 6014 | (when old-header | 6017 | (when old-header |
| 6015 | (mail-header-set-number header (mail-header-number old-header))) | 6018 | (mail-header-set-number header (mail-header-number old-header))) |
| 6016 | (setq gnus-newsgroup-sparse | 6019 | (setq gnus-newsgroup-sparse |
diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el index 8e5edbc048a..bfaf1675703 100644 --- a/lisp/gnus/message.el +++ b/lisp/gnus/message.el | |||
| @@ -4399,7 +4399,9 @@ Otherwise, generate and save a value for `canlock-password' first." | |||
| 4399 | nil)))) | 4399 | nil)))) |
| 4400 | ;; Check for control characters. | 4400 | ;; Check for control characters. |
| 4401 | (message-check 'control-chars | 4401 | (message-check 'control-chars |
| 4402 | (if (re-search-forward "[\000-\007\013\015-\032\034-\037\200-\237]" nil t) | 4402 | (if (re-search-forward |
| 4403 | (mm-string-as-multibyte "[\000-\007\013\015-\032\034-\037\200-\237]") | ||
| 4404 | nil t) | ||
| 4403 | (y-or-n-p | 4405 | (y-or-n-p |
| 4404 | "The article contains control characters. Really post? ") | 4406 | "The article contains control characters. Really post? ") |
| 4405 | t)) | 4407 | t)) |
diff --git a/lisp/info.el b/lisp/info.el index b779bb41ca6..2a20fc4898c 100644 --- a/lisp/info.el +++ b/lisp/info.el | |||
| @@ -1729,7 +1729,7 @@ If SAME-FILE is non-nil, do not move to a different Info file." | |||
| 1729 | (let ((inhibit-read-only t)) | 1729 | (let ((inhibit-read-only t)) |
| 1730 | (erase-buffer) | 1730 | (erase-buffer) |
| 1731 | (goto-char (point-min)) | 1731 | (goto-char (point-min)) |
| 1732 | (insert "\n\^_\nFile: history Node: Top, Up: (dir)\n\n") | 1732 | (insert "\n\^_\nFile: history, Node: Top, Up: (dir)\n\n") |
| 1733 | (insert "Recently Visited Nodes\n**********************\n\n") | 1733 | (insert "Recently Visited Nodes\n**********************\n\n") |
| 1734 | (insert "* Menu:\n\n") | 1734 | (insert "* Menu:\n\n") |
| 1735 | (let ((hl (delete '("history" "Top") Info-history-list))) | 1735 | (let ((hl (delete '("history" "Top") Info-history-list))) |
| @@ -1749,26 +1749,31 @@ If SAME-FILE is non-nil, do not move to a different Info file." | |||
| 1749 | "Go to a node with table of contents of the current Info file. | 1749 | "Go to a node with table of contents of the current Info file. |
| 1750 | Table of contents is created from the tree structure of menus." | 1750 | Table of contents is created from the tree structure of menus." |
| 1751 | (interactive) | 1751 | (interactive) |
| 1752 | (let ((curr-file Info-current-file) | 1752 | (let ((curr-file (substring-no-properties Info-current-file)) |
| 1753 | (curr-node Info-current-node) | 1753 | (curr-node (substring-no-properties Info-current-node)) |
| 1754 | p) | 1754 | p) |
| 1755 | (with-current-buffer (get-buffer-create " *info-toc*") | 1755 | (with-current-buffer (get-buffer-create " *info-toc*") |
| 1756 | (let ((inhibit-read-only t) | 1756 | (let ((inhibit-read-only t) |
| 1757 | (node-list (Info-build-toc curr-file))) | 1757 | (node-list (Info-build-toc curr-file))) |
| 1758 | (erase-buffer) | 1758 | (erase-buffer) |
| 1759 | (goto-char (point-min)) | 1759 | (goto-char (point-min)) |
| 1760 | (insert "\n\^_\nFile: toc Node: Top, Up: (dir)\n\n") | 1760 | (insert "\n\^_\nFile: toc, Node: Top, Up: (dir)\n\n") |
| 1761 | (insert "Table of Contents\n*****************\n\n") | 1761 | (insert "Table of Contents\n*****************\n\n") |
| 1762 | (insert "*Note Top::\n") | 1762 | (insert "*Note Top: (" curr-file ")Top.\n") |
| 1763 | (Info-insert-toc | 1763 | (Info-insert-toc |
| 1764 | (nth 2 (assoc "Top" node-list)) ; get Top nodes | 1764 | (nth 2 (assoc "Top" node-list)) ; get Top nodes |
| 1765 | node-list 0 (substring-no-properties curr-file))) | 1765 | node-list 0 curr-file)) |
| 1766 | (if (not (bobp)) | 1766 | (if (not (bobp)) |
| 1767 | (let ((Info-hide-note-references 'hide) | 1767 | (let ((Info-hide-note-references 'hide) |
| 1768 | (Info-fontify-visited-nodes nil)) | 1768 | (Info-fontify-visited-nodes nil)) |
| 1769 | (Info-mode) | 1769 | (Info-mode) |
| 1770 | (setq Info-current-file "toc" Info-current-node "Top") | 1770 | (setq Info-current-file "toc" Info-current-node "Top") |
| 1771 | (Info-fontify-node))) | 1771 | (goto-char (point-min)) |
| 1772 | (narrow-to-region (or (re-search-forward "\n[\^_\f]\n" nil t) | ||
| 1773 | (point-min)) | ||
| 1774 | (point-max)) | ||
| 1775 | (Info-fontify-node) | ||
| 1776 | (widen))) | ||
| 1772 | (goto-char (point-min)) | 1777 | (goto-char (point-min)) |
| 1773 | (if (setq p (search-forward (concat "*Note " curr-node ":") nil t)) | 1778 | (if (setq p (search-forward (concat "*Note " curr-node ":") nil t)) |
| 1774 | (setq p (- p (length curr-node) 2)))) | 1779 | (setq p (- p (length curr-node) 2)))) |
| @@ -1789,14 +1794,12 @@ Table of contents is created from the tree structure of menus." | |||
| 1789 | 1794 | ||
| 1790 | (defun Info-build-toc (file) | 1795 | (defun Info-build-toc (file) |
| 1791 | "Build table of contents from menus of Info FILE and its subfiles." | 1796 | "Build table of contents from menus of Info FILE and its subfiles." |
| 1792 | (if (equal file "dir") | ||
| 1793 | (error "Table of contents for Info directory is not supported yet")) | ||
| 1794 | (with-temp-buffer | 1797 | (with-temp-buffer |
| 1795 | (let* ((default-directory (or (and (stringp file) | 1798 | (let* ((file (and (stringp file) (Info-find-file file))) |
| 1796 | (file-name-directory | 1799 | (default-directory (or (and (stringp file) |
| 1797 | (setq file (Info-find-file file)))) | 1800 | (file-name-directory file)) |
| 1798 | default-directory)) | 1801 | default-directory)) |
| 1799 | (main-file file) | 1802 | (main-file (and (stringp file) file)) |
| 1800 | (sections '(("Top" "Top"))) | 1803 | (sections '(("Top" "Top"))) |
| 1801 | nodes subfiles) | 1804 | nodes subfiles) |
| 1802 | (while (or main-file subfiles) | 1805 | (while (or main-file subfiles) |
diff --git a/lisp/isearch.el b/lisp/isearch.el index 117d1bfdc13..96a3e0e0ac2 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el | |||
| @@ -680,16 +680,7 @@ is treated as a regexp. See \\[isearch-forward] for more info." | |||
| 680 | (if isearch-small-window | 680 | (if isearch-small-window |
| 681 | (goto-char found-point) | 681 | (goto-char found-point) |
| 682 | ;; Exiting the save-window-excursion clobbers window-start; restore it. | 682 | ;; Exiting the save-window-excursion clobbers window-start; restore it. |
| 683 | (set-window-start (selected-window) found-start t)) | 683 | (set-window-start (selected-window) found-start t))) |
| 684 | |||
| 685 | ;; If there was movement, mark the starting position. | ||
| 686 | ;; Maybe should test difference between and set mark iff > threshold. | ||
| 687 | (if (/= (point) isearch-opoint) | ||
| 688 | (or (and transient-mark-mode mark-active) | ||
| 689 | (progn | ||
| 690 | (push-mark isearch-opoint t) | ||
| 691 | (or executing-kbd-macro (> (minibuffer-depth) 0) | ||
| 692 | (message "Mark saved where search started")))))) | ||
| 693 | 684 | ||
| 694 | (setq isearch-mode nil) | 685 | (setq isearch-mode nil) |
| 695 | (if isearch-input-method-local-p | 686 | (if isearch-input-method-local-p |
| @@ -714,6 +705,16 @@ is treated as a regexp. See \\[isearch-forward] for more info." | |||
| 714 | (isearch-update-ring isearch-string isearch-regexp)) | 705 | (isearch-update-ring isearch-string isearch-regexp)) |
| 715 | 706 | ||
| 716 | (run-hooks 'isearch-mode-end-hook) | 707 | (run-hooks 'isearch-mode-end-hook) |
| 708 | |||
| 709 | ;; If there was movement, mark the starting position. | ||
| 710 | ;; Maybe should test difference between and set mark iff > threshold. | ||
| 711 | (if (/= (point) isearch-opoint) | ||
| 712 | (or (and transient-mark-mode mark-active) | ||
| 713 | (progn | ||
| 714 | (push-mark isearch-opoint t) | ||
| 715 | (or executing-kbd-macro (> (minibuffer-depth) 0) | ||
| 716 | (message "Mark saved where search started"))))) | ||
| 717 | |||
| 717 | (and (not edit) isearch-recursive-edit (exit-recursive-edit))) | 718 | (and (not edit) isearch-recursive-edit (exit-recursive-edit))) |
| 718 | 719 | ||
| 719 | (defun isearch-update-ring (string &optional regexp) | 720 | (defun isearch-update-ring (string &optional regexp) |
diff --git a/lisp/newcomment.el b/lisp/newcomment.el index 120777ab704..5711e7903ad 100644 --- a/lisp/newcomment.el +++ b/lisp/newcomment.el | |||
| @@ -423,7 +423,7 @@ and raises an error or returns nil if NOERROR is non-nil." | |||
| 423 | (defun comment-beginning () | 423 | (defun comment-beginning () |
| 424 | "Find the beginning of the enclosing comment. | 424 | "Find the beginning of the enclosing comment. |
| 425 | Returns nil if not inside a comment, else moves point and returns | 425 | Returns nil if not inside a comment, else moves point and returns |
| 426 | the same as `comment-search-forward'." | 426 | the same as `comment-search-backward'." |
| 427 | ;; HACK ATTACK! | 427 | ;; HACK ATTACK! |
| 428 | ;; We should really test `in-string-p' but that can be expensive. | 428 | ;; We should really test `in-string-p' but that can be expensive. |
| 429 | (unless (eq (get-text-property (point) 'face) 'font-lock-string-face) | 429 | (unless (eq (get-text-property (point) 'face) 'font-lock-string-face) |
| @@ -435,7 +435,7 @@ the same as `comment-search-forward'." | |||
| 435 | (and | 435 | (and |
| 436 | ;; For modes where comment-start and comment-end are the same, | 436 | ;; For modes where comment-start and comment-end are the same, |
| 437 | ;; the search above may have found a `ce' rather than a `cs'. | 437 | ;; the search above may have found a `ce' rather than a `cs'. |
| 438 | (or (not (looking-at comment-end-skip)) | 438 | (or (if comment-end-skip (not (looking-at comment-end-skip))) |
| 439 | ;; Maybe font-lock knows that it's a `cs'? | 439 | ;; Maybe font-lock knows that it's a `cs'? |
| 440 | (eq (get-text-property (match-end 0) 'face) | 440 | (eq (get-text-property (match-end 0) 'face) |
| 441 | 'font-lock-comment-face) | 441 | 'font-lock-comment-face) |
diff --git a/lisp/progmodes/gdb-ui.el b/lisp/progmodes/gdb-ui.el index 612a2034e00..d8f2cf34867 100644 --- a/lisp/progmodes/gdb-ui.el +++ b/lisp/progmodes/gdb-ui.el | |||
| @@ -188,6 +188,7 @@ detailed description of this mode. | |||
| 188 | (setq gdb-var-changed nil) | 188 | (setq gdb-var-changed nil) |
| 189 | (setq gdb-first-prompt nil) | 189 | (setq gdb-first-prompt nil) |
| 190 | (setq gdb-prompting nil) | 190 | (setq gdb-prompting nil) |
| 191 | (setq gdb-input-queue nil) | ||
| 191 | (setq gdb-current-item nil) | 192 | (setq gdb-current-item nil) |
| 192 | (setq gdb-pending-triggers nil) | 193 | (setq gdb-pending-triggers nil) |
| 193 | (setq gdb-output-sink 'user) | 194 | (setq gdb-output-sink 'user) |
diff --git a/lisp/textmodes/enriched.el b/lisp/textmodes/enriched.el index c2ed47cb48d..71bb6cf137d 100644 --- a/lisp/textmodes/enriched.el +++ b/lisp/textmodes/enriched.el | |||
| @@ -258,8 +258,8 @@ Commands: | |||
| 258 | (define-key enriched-mode-map "\M-j" 'facemenu-justification-menu) | 258 | (define-key enriched-mode-map "\M-j" 'facemenu-justification-menu) |
| 259 | (define-key enriched-mode-map "\M-S" 'set-justification-center) | 259 | (define-key enriched-mode-map "\M-S" 'set-justification-center) |
| 260 | (define-key enriched-mode-map "\C-x\t" 'increase-left-margin) | 260 | (define-key enriched-mode-map "\C-x\t" 'increase-left-margin) |
| 261 | (define-key enriched-mode-map "\C-c\C-l" 'set-left-margin) | 261 | (define-key enriched-mode-map "\C-c[" 'set-left-margin) |
| 262 | (define-key enriched-mode-map "\C-c\C-r" 'set-right-margin) | 262 | (define-key enriched-mode-map "\C-c]" 'set-right-margin) |
| 263 | 263 | ||
| 264 | ;;; | 264 | ;;; |
| 265 | ;;; Some functions dealing with text-properties, especially indentation | 265 | ;;; Some functions dealing with text-properties, especially indentation |
diff --git a/lisp/textmodes/tex-mode.el b/lisp/textmodes/tex-mode.el index 1c4b89f0a62..2a9059e2f56 100644 --- a/lisp/textmodes/tex-mode.el +++ b/lisp/textmodes/tex-mode.el | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | ;;; tex-mode.el --- TeX, LaTeX, and SliTeX mode commands -*- coding: utf-8 -*- | 1 | ;;; tex-mode.el --- TeX, LaTeX, and SliTeX mode commands -*- coding: utf-8 -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 1985,86,89,92,94,95,96,97,98,1999,2002,03,2004 | 3 | ;; Copyright (C) 1985, 1986, 1989, 1992, 1994, 1995, 1996, 1997, 1998, 1999, |
| 4 | ;; Free Software Foundation, Inc. | 4 | ;; 2002, 2003, 2004 Free Software Foundation, Inc. |
| 5 | 5 | ||
| 6 | ;; Maintainer: FSF | 6 | ;; Maintainer: FSF |
| 7 | ;; Keywords: tex | 7 | ;; Keywords: tex |
| @@ -196,7 +196,11 @@ use." | |||
| 196 | :group 'tex-view) | 196 | :group 'tex-view) |
| 197 | 197 | ||
| 198 | ;;;###autoload | 198 | ;;;###autoload |
| 199 | (defcustom tex-dvi-view-command '(if (eq window-system 'x) "xdvi" "dvi2tty * | cat -s") | 199 | (defcustom tex-dvi-view-command |
| 200 | '(cond | ||
| 201 | ((eq window-system 'x) "xdvi") | ||
| 202 | ((eq window-system 'w32) "yap") | ||
| 203 | (t "dvi2tty * | cat -s")) | ||
| 200 | "*Command used by \\[tex-view] to display a `.dvi' file. | 204 | "*Command used by \\[tex-view] to display a `.dvi' file. |
| 201 | If it is a string, that specifies the command directly. | 205 | If it is a string, that specifies the command directly. |
| 202 | If this string contains an asterisk (`*'), that is replaced by the file name; | 206 | If this string contains an asterisk (`*'), that is replaced by the file name; |
| @@ -453,7 +457,8 @@ An alternative value is \" . \", if you use a font with a narrow period." | |||
| 453 | '("input" "include" "includeonly" "bibliography" | 457 | '("input" "include" "includeonly" "bibliography" |
| 454 | "epsfig" "psfig" "epsf" "nofiles" "usepackage" | 458 | "epsfig" "psfig" "epsf" "nofiles" "usepackage" |
| 455 | "documentstyle" "documentclass" "verbatiminput" | 459 | "documentstyle" "documentclass" "verbatiminput" |
| 456 | "includegraphics" "includegraphics*") | 460 | "includegraphics" "includegraphics*" |
| 461 | "url" "nolinkurl") | ||
| 457 | t)) | 462 | t)) |
| 458 | ;; Miscellany. | 463 | ;; Miscellany. |
| 459 | (slash "\\\\") | 464 | (slash "\\\\") |
| @@ -771,8 +776,10 @@ Inherits `shell-mode-map' with a few additions.") | |||
| 771 | "part" "chapter" "newcommand" | 776 | "part" "chapter" "newcommand" |
| 772 | "renewcommand") 'words) | 777 | "renewcommand") 'words) |
| 773 | "\\|NeedsTeXFormat{LaTeX"))) | 778 | "\\|NeedsTeXFormat{LaTeX"))) |
| 774 | (if (looking-at | 779 | (if (and (looking-at |
| 775 | "document\\(style\\|class\\)\\(\\[.*\\]\\)?{slides}") | 780 | "document\\(style\\|class\\)\\(\\[.*\\]\\)?{slides}") |
| 781 | ;; SliTeX is almost never used any more nowadays. | ||
| 782 | (tex-executable-exists-p slitex-run-command)) | ||
| 776 | 'slitex-mode | 783 | 'slitex-mode |
| 777 | 'latex-mode) | 784 | 'latex-mode) |
| 778 | 'plain-tex-mode)))) | 785 | 'plain-tex-mode)))) |
| @@ -1219,8 +1226,13 @@ A prefix arg inhibits the checking." | |||
| 1219 | (defvar latex-block-default "enumerate") | 1226 | (defvar latex-block-default "enumerate") |
| 1220 | 1227 | ||
| 1221 | (defvar latex-block-args-alist | 1228 | (defvar latex-block-args-alist |
| 1222 | '(("array" nil ?\{ (skeleton-read "[options]: ") ?\}) | 1229 | '(("array" nil ?\{ (skeleton-read "Format: ") ?\}) |
| 1223 | ("tabular" nil ?\{ (skeleton-read "[options]: ") ?\})) | 1230 | ("tabular" nil ?\{ (skeleton-read "Format: ") ?\}) |
| 1231 | ("minipage" nil ?\{ (skeleton-read "Size: ") ?\}) | ||
| 1232 | ("picture" nil ?\( (skeleton-read "SizeX,SizeY: ") ?\)) | ||
| 1233 | ;; FIXME: This is right for Prosper, but not for seminar. | ||
| 1234 | ;; ("slide" nil ?\{ (skeleton-read "Title: ") ?\}) | ||
| 1235 | ) | ||
| 1224 | "Skeleton element to use for arguments to particular environments. | 1236 | "Skeleton element to use for arguments to particular environments. |
| 1225 | Every element of the list has the form (NAME . SKEL-ELEM) where NAME is | 1237 | Every element of the list has the form (NAME . SKEL-ELEM) where NAME is |
| 1226 | the name of the environment and SKEL-ELEM is an element to use in | 1238 | the name of the environment and SKEL-ELEM is an element to use in |
| @@ -1229,8 +1241,11 @@ a skeleton (see `skeleton-insert').") | |||
| 1229 | (defvar latex-block-body-alist | 1241 | (defvar latex-block-body-alist |
| 1230 | '(("enumerate" nil '(latex-insert-item) > _) | 1242 | '(("enumerate" nil '(latex-insert-item) > _) |
| 1231 | ("itemize" nil '(latex-insert-item) > _) | 1243 | ("itemize" nil '(latex-insert-item) > _) |
| 1232 | ("table" nil "\\caption{" > - "}" > \n _) | 1244 | ("table" nil "\\caption{" > (skeleton-read "Caption: ") "}" > \n |
| 1233 | ("figure" nil > _ \n "\\caption{" > _ "}" >)) | 1245 | '(if (and (boundp 'reftex-mode) reftex-mode) (reftex-label "table")) |
| 1246 | \n _) | ||
| 1247 | ("figure" nil > _ \n "\\caption{" > (skeleton-read "Caption: ") "}" > \n | ||
| 1248 | '(if (and (boundp 'reftex-mode) reftex-mode) (reftex-label "table")))) | ||
| 1234 | "Skeleton element to use for the body of particular environments. | 1249 | "Skeleton element to use for the body of particular environments. |
| 1235 | Every element of the list has the form (NAME . SKEL-ELEM) where NAME is | 1250 | Every element of the list has the form (NAME . SKEL-ELEM) where NAME is |
| 1236 | the name of the environment and SKEL-ELEM is an element to use in | 1251 | the name of the environment and SKEL-ELEM is an element to use in |
| @@ -1254,7 +1269,8 @@ Puts point on a blank line between them." | |||
| 1254 | choice) | 1269 | choice) |
| 1255 | \n "\\begin{" str "}" | 1270 | \n "\\begin{" str "}" |
| 1256 | (cdr (assoc str latex-block-args-alist)) | 1271 | (cdr (assoc str latex-block-args-alist)) |
| 1257 | > \n (or (cdr (assoc str latex-block-body-alist)) '(nil > _)) \n | 1272 | > \n (or (cdr (assoc str latex-block-body-alist)) '(nil > _)) |
| 1273 | (unless (bolp) '\n) | ||
| 1258 | "\\end{" str "}" > \n) | 1274 | "\\end{" str "}" > \n) |
| 1259 | 1275 | ||
| 1260 | (define-skeleton latex-insert-item | 1276 | (define-skeleton latex-insert-item |
| @@ -1598,7 +1614,7 @@ If NOT-ALL is non-nil, save the `.dvi' file." | |||
| 1598 | ("texindex %r.??") | 1614 | ("texindex %r.??") |
| 1599 | ("dvipdfm %r" "%r.dvi" "%r.pdf") | 1615 | ("dvipdfm %r" "%r.dvi" "%r.pdf") |
| 1600 | ("dvipdf %r" "%r.dvi" "%r.pdf") | 1616 | ("dvipdf %r" "%r.dvi" "%r.pdf") |
| 1601 | ("dvips %r" "%r.dvi" "%r.ps") | 1617 | ("dvips -o %r.ps %r" "%r.dvi" "%r.ps") |
| 1602 | ("ps2pdf %r.ps" "%r.ps" "%r.pdf") | 1618 | ("ps2pdf %r.ps" "%r.ps" "%r.pdf") |
| 1603 | ("gv %r.ps &" "%r.ps") | 1619 | ("gv %r.ps &" "%r.ps") |
| 1604 | ("gv %r.pdf &" "%r.pdf") | 1620 | ("gv %r.pdf &" "%r.pdf") |
| @@ -1767,7 +1783,7 @@ FILE is typically the output DVI or PDF file." | |||
| 1767 | (not (tex-uptodate-p (format-spec out fspec))))))) | 1783 | (not (tex-uptodate-p (format-spec out fspec))))))) |
| 1768 | 1784 | ||
| 1769 | (defun tex-compile-default (fspec) | 1785 | (defun tex-compile-default (fspec) |
| 1770 | "Guess a default command given the format-spec FSPEC." | 1786 | "Guess a default command given the `format-spec' FSPEC." |
| 1771 | ;; TODO: Learn to do latex+dvips! | 1787 | ;; TODO: Learn to do latex+dvips! |
| 1772 | (let ((cmds nil) | 1788 | (let ((cmds nil) |
| 1773 | (unchanged-in nil)) | 1789 | (unchanged-in nil)) |
| @@ -1777,6 +1793,9 @@ FILE is typically the output DVI or PDF file." | |||
| 1777 | (if (tex-command-active-p cmd fspec) | 1793 | (if (tex-command-active-p cmd fspec) |
| 1778 | (push cmd cmds) | 1794 | (push cmd cmds) |
| 1779 | (push (nth 1 cmd) unchanged-in)))) | 1795 | (push (nth 1 cmd) unchanged-in)))) |
| 1796 | ;; If no command seems to be applicable, arbitrarily pick the first one. | ||
| 1797 | (unless cmds | ||
| 1798 | (setq cmds (list (car tex-compile-commands)))) | ||
| 1780 | ;; Remove those commands whose input was considered stable for | 1799 | ;; Remove those commands whose input was considered stable for |
| 1781 | ;; some other command (typically if (t . "%.pdf") is inactive | 1800 | ;; some other command (typically if (t . "%.pdf") is inactive |
| 1782 | ;; then we're using pdflatex and the fact that the dvi file | 1801 | ;; then we're using pdflatex and the fact that the dvi file |
| @@ -2261,6 +2280,7 @@ Runs the shell command defined by `tex-show-queue-command'." | |||
| 2261 | (defvar tex-indent-basic 2) | 2280 | (defvar tex-indent-basic 2) |
| 2262 | (defvar tex-indent-item tex-indent-basic) | 2281 | (defvar tex-indent-item tex-indent-basic) |
| 2263 | (defvar tex-indent-item-re "\\\\\\(bib\\)?item\\>") | 2282 | (defvar tex-indent-item-re "\\\\\\(bib\\)?item\\>") |
| 2283 | (defvar latex-noindent-environments '("document")) | ||
| 2264 | 2284 | ||
| 2265 | (defvar tex-latex-indent-syntax-table | 2285 | (defvar tex-latex-indent-syntax-table |
| 2266 | (let ((st (make-syntax-table tex-mode-syntax-table))) | 2286 | (let ((st (make-syntax-table tex-mode-syntax-table))) |
| @@ -2311,7 +2331,6 @@ There might be text before point." | |||
| 2311 | (latex-find-indent 'virtual)))) | 2331 | (latex-find-indent 'virtual)))) |
| 2312 | ;; Default (maybe an argument) | 2332 | ;; Default (maybe an argument) |
| 2313 | (let ((pos (point)) | 2333 | (let ((pos (point)) |
| 2314 | (char (char-after)) | ||
| 2315 | ;; Outdent \item if necessary. | 2334 | ;; Outdent \item if necessary. |
| 2316 | (indent (if (looking-at tex-indent-item-re) (- tex-indent-item) 0)) | 2335 | (indent (if (looking-at tex-indent-item-re) (- tex-indent-item) 0)) |
| 2317 | up-list-pos) | 2336 | up-list-pos) |
| @@ -2329,6 +2348,17 @@ There might be text before point." | |||
| 2329 | ;; Have to indent relative to the open-paren. | 2348 | ;; Have to indent relative to the open-paren. |
| 2330 | (goto-char up-list-pos) | 2349 | (goto-char up-list-pos) |
| 2331 | (if (and (not tex-indent-allhanging) | 2350 | (if (and (not tex-indent-allhanging) |
| 2351 | (save-excursion | ||
| 2352 | ;; Make sure we're an argument to a macro and | ||
| 2353 | ;; that the macro is at the beginning of a line. | ||
| 2354 | (condition-case nil | ||
| 2355 | (progn | ||
| 2356 | (while (eq (char-syntax (char-after)) ?\() | ||
| 2357 | (forward-sexp -1)) | ||
| 2358 | (and (eq (char-syntax (char-after)) ?/) | ||
| 2359 | (progn (skip-chars-backward " \t&") | ||
| 2360 | (bolp)))) | ||
| 2361 | (scan-error nil))) | ||
| 2332 | (> pos (progn (latex-down-list) | 2362 | (> pos (progn (latex-down-list) |
| 2333 | (forward-comment (point-max)) | 2363 | (forward-comment (point-max)) |
| 2334 | (point)))) | 2364 | (point)))) |
| @@ -2336,18 +2366,24 @@ There might be text before point." | |||
| 2336 | (current-column) | 2366 | (current-column) |
| 2337 | ;; We're the first element after a hanging brace. | 2367 | ;; We're the first element after a hanging brace. |
| 2338 | (goto-char up-list-pos) | 2368 | (goto-char up-list-pos) |
| 2339 | (+ indent tex-indent-basic (latex-find-indent 'virtual)))) | 2369 | (+ (if (and (looking-at "\\\\begin *{\\([^\n}]+\\)") |
| 2370 | (member (match-string 1) | ||
| 2371 | latex-noindent-environments)) | ||
| 2372 | 0 tex-indent-basic) | ||
| 2373 | indent (latex-find-indent 'virtual)))) | ||
| 2340 | ;; We're now at the "beginning" of a line. | 2374 | ;; We're now at the "beginning" of a line. |
| 2341 | ((not (and (not virtual) (eq (char-after) ?\\))) | 2375 | ((not (and (not virtual) (eq (char-after) ?\\))) |
| 2342 | ;; Nothing particular here: just keep the same indentation. | 2376 | ;; Nothing particular here: just keep the same indentation. |
| 2343 | (+ indent (current-column))) | 2377 | (+ indent (current-column))) |
| 2344 | ;; We're now looking at a macro call. | 2378 | ;; We're now looking at a macro call. |
| 2345 | ((looking-at tex-indent-item-re) | 2379 | ((looking-at tex-indent-item-re) |
| 2346 | ;; Indenting relative to an item, have to re-add the outdenting. | 2380 | ;; Indenting relative to an item, have to re-add the outdenting. |
| 2347 | (+ indent (current-column) tex-indent-item)) | 2381 | (+ indent (current-column) tex-indent-item)) |
| 2348 | (t | 2382 | (t |
| 2349 | (let ((col (current-column))) | 2383 | (let ((col (current-column))) |
| 2350 | (if (or (null char) (not (eq (char-syntax char) ?\())) | 2384 | (if (or (not (eq (char-syntax (or (char-after pos) ?\ )) ?\()) |
| 2385 | ;; Can't be an arg if there's an empty line inbetween. | ||
| 2386 | (save-excursion (re-search-forward "^[ \t]*$" pos t))) | ||
| 2351 | ;; If the first char was not an open-paren, there's | 2387 | ;; If the first char was not an open-paren, there's |
| 2352 | ;; a risk that this is really not an argument to the | 2388 | ;; a risk that this is really not an argument to the |
| 2353 | ;; macro at all. | 2389 | ;; macro at all. |
| @@ -2422,5 +2458,5 @@ There might be text before point." | |||
| 2422 | 2458 | ||
| 2423 | (provide 'tex-mode) | 2459 | (provide 'tex-mode) |
| 2424 | 2460 | ||
| 2425 | ;;; arch-tag: c0a680b1-63aa-4547-84b9-4193c29c0080 | 2461 | ;; arch-tag: c0a680b1-63aa-4547-84b9-4193c29c0080 |
| 2426 | ;;; tex-mode.el ends here | 2462 | ;;; tex-mode.el ends here |
diff --git a/lisp/url/ChangeLog b/lisp/url/ChangeLog index 69851ac5046..0da4297bb86 100644 --- a/lisp/url/ChangeLog +++ b/lisp/url/ChangeLog | |||
| @@ -1,3 +1,8 @@ | |||
| 1 | 2004-10-06 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * url-handlers.el (url-insert-file-contents): Use the URL to decide the | ||
| 4 | encoding, not the buffer-file-name (which might not even exist). | ||
| 5 | |||
| 1 | 2004-09-20 Stefan Monnier <monnier@iro.umontreal.ca> | 6 | 2004-09-20 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 7 | ||
| 3 | * url-handlers.el (url-insert-file-contents): Decode contents. | 8 | * url-handlers.el (url-insert-file-contents): Decode contents. |
diff --git a/lisp/url/url-handlers.el b/lisp/url/url-handlers.el index 56497b00119..18a2e273637 100644 --- a/lisp/url/url-handlers.el +++ b/lisp/url/url-handlers.el | |||
| @@ -208,7 +208,7 @@ accessible." | |||
| 208 | ;; annotation which we could use as a hint of the locale in use | 208 | ;; annotation which we could use as a hint of the locale in use |
| 209 | ;; at the remote site. Not sure how/if that should be done. --Stef | 209 | ;; at the remote site. Not sure how/if that should be done. --Stef |
| 210 | (decode-coding-inserted-region | 210 | (decode-coding-inserted-region |
| 211 | start (point) buffer-file-name visit beg end replace))) | 211 | start (point) url visit beg end replace))) |
| 212 | (list url (length data)))) | 212 | (list url (length data)))) |
| 213 | 213 | ||
| 214 | (defun url-file-name-completion (url directory) | 214 | (defun url-file-name-completion (url directory) |
diff --git a/lisp/xml.el b/lisp/xml.el index 993ef59b276..f1d8cbb1f00 100644 --- a/lisp/xml.el +++ b/lisp/xml.el | |||
| @@ -598,8 +598,8 @@ This follows the rule [28] in the XML specifications." | |||
| 598 | nil) | 598 | nil) |
| 599 | (t | 599 | (t |
| 600 | (if xml-validating-parser | 600 | (if xml-validating-parser |
| 601 | error "XML: (Validity) Invalid element type in the DTD"))) | 601 | (error "XML: (Validity) Invalid element type in the DTD")))) |
| 602 | 602 | ||
| 603 | ;; rule [45]: the element declaration must be unique | 603 | ;; rule [45]: the element declaration must be unique |
| 604 | (if (and (assoc element dtd) | 604 | (if (and (assoc element dtd) |
| 605 | xml-validating-parser) | 605 | xml-validating-parser) |
| @@ -727,13 +727,13 @@ This follows the rule [28] in the XML specifications." | |||
| 727 | (match-string 1 this-part))))))) | 727 | (match-string 1 this-part))))))) |
| 728 | 728 | ||
| 729 | (cond ((null children) | 729 | (cond ((null children) |
| 730 | (if (stringp expansion) | 730 | (if (and (eq (length expansion) 1) |
| 731 | (stringp (cadr expansion))) | ||
| 731 | (setq children (concat prev-part expansion)) | 732 | (setq children (concat prev-part expansion)) |
| 732 | (if (stringp (car (last expansion))) | 733 | (if (stringp (car expansion)) |
| 733 | (progn | 734 | (setq children |
| 734 | (setq children | 735 | (list (concat prev-part (car expansion)) |
| 735 | (list (concat prev-part (car expansion)) | 736 | (append (cdr expansion)))) |
| 736 | (cdr expansion)))) | ||
| 737 | (setq children (append expansion prev-part))))) | 737 | (setq children (append expansion prev-part))))) |
| 738 | ((stringp children) | 738 | ((stringp children) |
| 739 | (if (stringp expansion) | 739 | (if (stringp expansion) |
| @@ -756,11 +756,15 @@ This follows the rule [28] in the XML specifications." | |||
| 756 | (cond ((stringp children) | 756 | (cond ((stringp children) |
| 757 | (concat children (substring string point))) | 757 | (concat children (substring string point))) |
| 758 | ((stringp (car (last children))) | 758 | ((stringp (car (last children))) |
| 759 | (concat (car children) (substring string point))) | 759 | (concat (car (last children)) (substring string point))) |
| 760 | ((null children) | 760 | ((null children) |
| 761 | string) | 761 | string) |
| 762 | (t | 762 | (t |
| 763 | (nreverse children))))) | 763 | (concat (mapconcat 'identity |
| 764 | (nreverse children) | ||
| 765 | "") | ||
| 766 | (substring string point)))))) | ||
| 767 | |||
| 764 | ;;******************************************************************* | 768 | ;;******************************************************************* |
| 765 | ;;** | 769 | ;;** |
| 766 | ;;** Printing a tree. | 770 | ;;** Printing a tree. |