aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorKaroly Lorentey2004-10-07 16:52:19 +0000
committerKaroly Lorentey2004-10-07 16:52:19 +0000
commitc5f80d9d13d6033e5ee75d65bb5383d4d75dc427 (patch)
tree1aa58eeabb309b4460144425f6e5a2ca0ad81eaf /lisp
parent04ccca970d4a21222cd1f58c7c41983461f009fc (diff)
parenteb6a2b61401ca737487aa7770389c01c0e962cb0 (diff)
downloademacs-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/ChangeLog75
-rw-r--r--lisp/calendar/cal-iso.el53
-rw-r--r--lisp/calendar/cal-menu.el5
-rw-r--r--lisp/calendar/calendar.el5
-rw-r--r--lisp/calendar/icalendar.el1299
-rw-r--r--lisp/gnus/ChangeLog18
-rw-r--r--lisp/gnus/gnus-group.el3
-rw-r--r--lisp/gnus/gnus-msg.el3
-rw-r--r--lisp/gnus/gnus-sum.el21
-rw-r--r--lisp/gnus/message.el4
-rw-r--r--lisp/info.el29
-rw-r--r--lisp/isearch.el21
-rw-r--r--lisp/newcomment.el4
-rw-r--r--lisp/progmodes/gdb-ui.el1
-rw-r--r--lisp/textmodes/enriched.el4
-rw-r--r--lisp/textmodes/tex-mode.el74
-rw-r--r--lisp/url/ChangeLog5
-rw-r--r--lisp/url/url-handlers.el2
-rw-r--r--lisp/xml.el24
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 @@
12004-10-06 Nick Roberts <nickrob@snap.net.nz>
2
3 * progmodes/gdb-ui.el (gdb-ann3): (Re-)initialise gdb-input-queue.
4
52004-10-06 John Paul Wallington <jpw@gnu.org>
6
7 * xml.el (xml-parse-dtd): Fix `error' call.
8
92004-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
142004-10-05 Ulf Jasper <ulf.jasper@web.de>
15
16 * calendar/icalendar.el: New file.
17
182004-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
282004-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
342004-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
422004-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
482004-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
622004-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
12004-10-02 Dan Nicolaescu <dann@ics.uci.edu> 672004-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
122004-10-01 Luc Teirlinck <teirllm@auburn.edu> 772004-10-01 Luc Teirlinck <teirllm@auburn.edu>
13 78
@@ -33,8 +98,8 @@
33 98
342004-09-29 Luc Teirlinck <teirllm@auburn.edu> 992004-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 131Interactively, 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.
107This string defines how iCalendar events are inserted into diary
108file. 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.
119This applies only if the subject is not empty! `%s' is replaced
120by 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.
127This applies only if the description is not empty! `%s' is
128replaced 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.
135This applies only if the location is not empty! `%s' is replaced
136by 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.
143This applies only if the organizer is not empty! `%s' is
144replaced by the organizer."
145 :type 'string
146 :group 'icalendar)
147
148(defcustom icalendar-duration-correction
149 t
150 "Workaround for all-day events.
151If non-nil the length=duration of iCalendar appointments that
152have a length of exactly n days is decreased by one day. This
153fixes problems with all-day events, which appear to be one day
154longer 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.
187Currently 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.
204Folding is the iCalendar way of wrapping long lines. In the
205created buffer all occurrences of CR LF BLANK are replaced by the
206empty string. Argument FOLDED-ICAL-BUFFER is the unfolded input
207buffer."
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.
230INVALUE gives the current iCalendar element we are reading.
231INPARAMS gives the current parameters.....
232This function calls itself recursively for each nested calendar element
233it 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.
314For instance the VCALENDAR node can have VEVENT children as well as VTODO
315children."
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'.
362Converts from ISO-8601 to Emacs representation. If ISODATETIMESTRING
363specifies UTC time (trailing letter Z) the decoded time is given in
364the local time zone! FIXME: TZID-attributes are ignored....! FIXME:
365multiple 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'.
400Converts from ISO-8601 to Emacs representation. If ISODURATIONSTRING
401specifies UTC time (trailing letter Z) the decoded time is given in
402the local time zone! FIXME: TZID-attributes are ignored....! FIXME:
403multiple 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.
458Both times must be given in decoded form. One of these times must be
459valid (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.
475Non-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.
485European format: (day month year).
486FIXME"
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.
496Note 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.
516If 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
518takes 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.
581In this example the TIMESTRING would be \"9:30\" and the AMPMSTRING
582would 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!!!.
610Argument DIARY-FILENAME is the input `diary-file'.
611Argument ICAL-FILENAME is the output iCalendar file.
612If DO-NOT-CLEAR-DIARY-FILE is not nil the target iCalendar file
613is not erased."
614 (interactive "FExport diary data from file:
615Finto 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!
974Argument ICAL-FILENAME output iCalendar file.
975Argument DIARY-FILENAME input `diary-file'.
976Optional argument NON-MARKING determines whether events are created as
977non-marking or not.
978If DO-NOT-CLEAR-DIARY-FILE is not nil the target diary file is
979not erased."
980 (interactive "fImport iCalendar data from file:
981Finto diary file (will be erased!):
982p")
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
999This function searches the current buffer for the first iCalendar
1000object, reads it and adds all VEVENT elements to the diary
1001DIARY-FILE.
1002
1003It will ask for each appointment whether to add it to the diary
1004when DO-NOT-ASK is non-nil. When called interactively,
1005DO-NOT-ASK is set to t, so that you are asked fore each event.
1006
1007NON-MARKING determines whether diary events are created as
1008non-marking.
1009
1010This function attempts to notify about problems that occur when
1011reading, 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.
1081Import VEVENTS from the iCalendar object ICAL-LIST and saves them to a
1082DIARY-FILE. If DO-NOT-ASK is nil the user is asked for each event
1083whether to actually import it. NON-MARKING determines whether diary
1084events are created as non-marking.
1085This function attempts to return t if something goes wrong. In this
1086case an error string which describes all the errors and problems is
1087written 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.
1273STRING must be a properly formatted valid diary entry. NON-MARKING
1274determines whether diary events are created as non-marking. If
1275SUBJECT is not nil it must be a string that gives the subject of the
1276entry. In this case the user will be asked whether he wants to insert
1277the 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 @@
12004-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
112004-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
12004-10-01 Katsumi Yamaoka <yamaoka@jpl.org> 192004-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.
1750Table of contents is created from the tree structure of menus." 1750Table 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.
425Returns nil if not inside a comment, else moves point and returns 425Returns nil if not inside a comment, else moves point and returns
426the same as `comment-search-forward'." 426the 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.
201If it is a string, that specifies the command directly. 205If it is a string, that specifies the command directly.
202If this string contains an asterisk (`*'), that is replaced by the file name; 206If 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.
1225Every element of the list has the form (NAME . SKEL-ELEM) where NAME is 1237Every element of the list has the form (NAME . SKEL-ELEM) where NAME is
1226the name of the environment and SKEL-ELEM is an element to use in 1238the 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.
1235Every element of the list has the form (NAME . SKEL-ELEM) where NAME is 1250Every element of the list has the form (NAME . SKEL-ELEM) where NAME is
1236the name of the environment and SKEL-ELEM is an element to use in 1251the 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 @@
12004-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
12004-09-20 Stefan Monnier <monnier@iro.umontreal.ca> 62004-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.