* mixi.el (mixi-make-release): New function.
[elisp/mixi.git] / ptexinfmt.el
1 ;;; ptexinfmt.el -- portable Texinfo formatter.
2
3 ;; Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993,
4 ;;               1994, 1995, 1996, 1997 Free Software Foundation, Inc.
5 ;; Copyright (C) 1999 Yoshiki Hayashi <yoshiki@xemacs.org>
6 ;; Copyright (C) 2000, 2001, 2002 TAKAHASHI Kaoru <kaoru@kaisei.org>
7
8 ;; Author: TAKAHASHI Kaoru <kaoru@kaisei.org>
9 ;;      Yoshiki Hayashi <yoshiki@xemacs.org>
10 ;;      Katsumi Yamaoka <yamaoka@jpl.org>
11 ;; Maintainer: TAKAHASHI Kaoru <kaoru@kaisei.org>
12 ;; Created: 7 Jul 2000
13 ;; Keywords: maint, tex, docs, emulation, compatibility
14
15 ;; This program is free software; you can redistribute it and/or
16 ;; modify it under the terms of the GNU General Public License as
17 ;; published by the Free Software Foundation; either version 2, or (at
18 ;; your option) any later version.
19
20 ;; This program is distributed in the hope that it will be useful, but
21 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
22 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23 ;; General Public License for more details.
24
25 ;; You should have received a copy of the GNU General Public License
26 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
27 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
28 ;; Boston, MA 02110-1301, USA.
29
30 ;;; Commentary:
31
32 ;; Original code: Yoshiki Hayashi <yoshiki@xemacs.org>
33 ;;      makeinfo.el (gnujdoc project)
34
35 ;; Support texinfmt.el 2.32 or later.
36
37 ;; Modified by Yamaoka not to use APEL functions.
38
39 ;; Unimplemented command:
40 ;;  @abbr
41 ;;  @float, @caption, @shortcaption, @listoffloats
42 ;;  @deftypecv[x]
43 ;;  @headitem
44 ;;  @comma{}
45 ;;  @quotation (optional arguments)
46 ;;  @acronym (optional argument)
47 ;;  @dofirstparagraphindent
48 ;;  @indent
49 ;;  @verbatiminclude
50 ;;  @\
51 ;;  @definfoenclose
52 ;;  @deftypeivar
53 ;;  @deftypeop
54 ;;  @allowcodebreaks
55
56 ;;; Code:
57
58 (require 'texinfmt)
59
60 ;;; Broken
61 (defvar ptexinfmt-disable-broken-notice-flag t
62   "If non-nil disable notice, when call `ptexinfmt-broken-facility'.
63 This is last argument in `ptexinfmt-broken-facility'.")
64
65 (put 'ptexinfmt-broken-facility 'lisp-indent-function 'defun)
66 (defmacro ptexinfmt-broken-facility (facility docstring assertion
67                                               &optional dummy)
68   "Declare a symbol FACILITY is broken if ASSERTION is nil.
69 DOCSTRING will be printed if ASSERTION is nil and
70 `ptexinfmt-disable-broken-notice-flag' is nil."
71   `(let ((facility ',facility)
72          (docstring ,docstring)
73          (assertion (eval ',assertion)))
74      (put facility 'broken (not assertion))
75      (if assertion
76          nil
77        (put facility 'broken-docstring docstring)
78        (if ptexinfmt-disable-broken-notice-flag
79            nil
80          (message "BROKEN FACILITY DETECTED: %s" docstring)))))
81
82 (put 'ptexinfmt-defun-if-broken 'lisp-indent-function 'defun)
83 (defmacro ptexinfmt-defun-if-broken (&rest args)
84   "Redefine a function just like `defun' if it is considered broken."
85   (let ((name (list 'quote (car args))))
86     (setq args (cdr args))
87     `(prog1
88          ,name
89        (if (get ,name 'broken)
90            (defalias ,name
91              (function (lambda ,@args)))))))
92
93 (put 'ptexinfmt-defun-if-void 'lisp-indent-function 'defun)
94 (defmacro ptexinfmt-defun-if-void (&rest args)
95   "Define a function just like `defun' unless it is already defined."
96   (let ((name (list 'quote (car args))))
97     (setq args (cdr args))
98     `(prog1
99          ,name
100        (if (fboundp ,name)
101            nil
102          (defalias ,name
103            (function (lambda ,@args)))))))
104
105 (put 'ptexinfmt-defvar-if-void 'lisp-indent-function 'defun)
106 (defmacro ptexinfmt-defvar-if-void (&rest args)
107   "Define a variable just like `defvar' unless it is already defined."
108   (let ((name (car args)))
109     (setq args (cdr args))
110     `(prog1
111          (defvar ,name)
112        (if (boundp ',name)
113            nil
114          (defvar ,name ,@args)))))
115
116 ;; sort -fd
117 (ptexinfmt-broken-facility texinfo-format-printindex
118   "Can't sort on Mule for Windows."
119   (if (and (memq system-type '(windows-nt ms-dos))
120 ;;; I don't know version threshold.
121 ;;;        (string< texinfmt-version "2.37 of 24 May 1997")
122            (boundp 'MULE) (not (featurep 'meadow))) ; Mule for Windows
123       nil
124     t))
125
126 ;; @var
127 (ptexinfmt-broken-facility texinfo-format-var
128   "Don't perse @var argument."
129   (condition-case nil
130       (with-temp-buffer
131         (let (texinfo-enclosure-list texinfo-alias-list)
132           (texinfo-mode)
133           (insert "@var{@asis{foo}}\n")
134           (texinfo-format-expand-region (point-min) (point-max))
135           t))
136     (error nil)))
137
138 ;; @xref
139 (ptexinfmt-broken-facility texinfo-format-xref
140   "Can't format @xref, 1st argument is empty."
141   (condition-case nil
142       (with-temp-buffer
143         (let (texinfo-enclosure-list texinfo-alias-list)
144           (texinfo-mode)
145           (insert "@xref{, xref, , file}\n")
146           (texinfo-format-expand-region (point-min) (point-max))
147           t))
148     (error nil)))
149
150 ;; @uref
151 (ptexinfmt-broken-facility texinfo-format-uref
152   "Parse twice @uref argument."
153   (condition-case nil
154       (with-temp-buffer
155         (let (texinfo-enclosure-list texinfo-alias-list)
156           (texinfo-mode)
157           (insert "@uref{mailto:foo@@noncommand.example.com}\n")
158           (texinfo-format-expand-region (point-min) (point-max))
159           t))
160     (error nil)))
161
162 ;; @multitable
163 (ptexinfmt-broken-facility texinfo-multitable-widths
164   "`texinfo-multitable-widths' unsupport wide-char."
165   (if (fboundp 'texinfo-multitable-widths)
166       (with-temp-buffer
167         (let ((str "\e$BI}9-J8;z\e(B"))
168           (texinfo-mode)
169           (insert (format " {%s}\n" str))
170           (goto-char (point-min))
171           (if (= (car (texinfo-multitable-widths)) (length str))
172               t
173             nil)))
174     ;; function definition is void
175     nil))
176
177 (ptexinfmt-broken-facility texinfo-multitable-item
178   "`texinfo-multitable-item' unsupport wide-char."
179   (not (get 'texinfo-multitable-widths 'broken)))
180
181
182 ;;; Hardcopy and HTML (discard)
183 ;; html
184 (put 'documentlanguage 'texinfo-format 'texinfo-discard-line-with-args)
185 (put 'documentencoding 'texinfo-format 'texinfo-discard-line-with-args)
186 (put 'documentdescription 'texinfo-format 'texinfo-discard-line-with-args)
187
188 ;; size
189 (put 'smallbook 'texinfo-format 'texinfo-discard-line)
190 (put 'letterpaper 'texinfo-format 'texinfo-discard-line)
191 (put 'afourpaper 'texinfo-format 'texinfo-discard-line)
192 (put 'afourlatex 'texinfo-format 'texinfo-discard-line)
193 (put 'afourwide 'texinfo-format 'texinfo-discard-line)
194 (put 'afivepaper 'texinfo-format 'texinfo-discard-line)
195 (put 'pagesizes 'texinfo-format 'texinfo-discard-line-with-args)
196
197 ;; style
198 (put 'setchapternewpage 'texinfo-format 'texinfo-discard-line-with-args)
199 (put 'kbdinputstyle 'texinfo-format 'texinfo-discard-line-with-args)
200
201 ;; flags
202 (put 'setcontentsaftertitlepage 'texinfo-format 'texinfo-discard-line)
203 (put 'setshortcontentsaftertitlepage 'texinfo-format 'texinfo-discard-line)
204 (put 'novalidate 'texinfo-format 'texinfo-discard-line-with-args)
205 (put 'frenchspacing 'texinfo-format 'texinfo-discard-line-with-args)
206
207 ;; head & foot
208 (put 'headings 'texinfo-format 'texinfo-discard-line-with-args)
209 (put 'evenfooting 'texinfo-format 'texinfo-discard-line-with-args)
210 (put 'evenheading 'texinfo-format 'texinfo-discard-line-with-args)
211 (put 'oddfooting 'texinfo-format 'texinfo-discard-line-with-args)
212 (put 'oddheading 'texinfo-format 'texinfo-discard-line-with-args)
213 (put 'everyfooting 'texinfo-format 'texinfo-discard-line-with-args)
214 (put 'everyheading 'texinfo-format 'texinfo-discard-line-with-args)
215
216 ;; misc
217 (put 'page 'texinfo-format 'texinfo-discard-line)
218 (put 'hyphenation 'texinfo-format 'texinfo-discard-command-and-arg)
219
220 ;; @slanted{} (makeinfo 4.8 or later)
221 (put 'slanted 'texinfo-format 'texinfo-format-noop)
222
223 ;; @sansserif{} (makeinfo 4.8 or later)
224 (put 'sansserif 'texinfo-format 'texinfo-format-noop)
225
226 ;; @tie{} (makeinfo 4.3 or later)
227 (put 'tie 'texinfo-format 'texinfo-format-tie)
228 (ptexinfmt-defun-if-void texinfo-format-tie ()
229   (texinfo-parse-arg-discard)
230   (insert " "))
231
232 \f
233 ;;; Directory File
234 ;; @direcategory
235 (put 'dircategory 'texinfo-format 'texinfo-format-dircategory)
236 (ptexinfmt-defun-if-void texinfo-format-dircategory ()
237   (let ((str (texinfo-parse-arg-discard)))
238     (delete-region (point)
239                    (progn
240                      (skip-chars-forward " ")
241                      (point)))
242     (insert "INFO-DIR-SECTION " str "\n")))
243
244 ;; @direntry
245 (put 'direntry 'texinfo-format 'texinfo-format-direntry)
246 (ptexinfmt-defun-if-void texinfo-format-direntry ()
247   (texinfo-push-stack 'direntry nil)
248   (texinfo-discard-line)
249   (insert "START-INFO-DIR-ENTRY\n"))
250
251 (put 'direntry 'texinfo-end 'texinfo-end-direntry)
252 (ptexinfmt-defun-if-void texinfo-end-direntry ()
253   (texinfo-discard-command)
254   (insert "END-INFO-DIR-ENTRY\n\n")
255   (texinfo-pop-stack 'direntry))
256
257
258 ;;; Block Enclosing
259 ;; @detailmenu ... @end detailmenu
260 (put 'detailmenu 'texinfo-format 'texinfo-discard-line)
261 (put 'detailmenu 'texinfo-end 'texinfo-discard-command)
262
263 ;; @smalldisplay ... @end smalldisplay
264 (put 'smalldisplay 'texinfo-format 'texinfo-format-example)
265 (put 'smalldisplay 'texinfo-end 'texinfo-end-example)
266
267 ;; @smallformat ... @end smallformat
268 (put 'smallformat 'texinfo-format 'texinfo-format-flushleft)
269 (put 'smallformat 'texinfo-end 'texinfo-end-flushleft)
270
271 ;; @cartouche  ... @end cartouche
272 (put 'cartouche 'texinfo-format 'texinfo-discard-line)
273 (put 'cartouche 'texinfo-end 'texinfo-discard-command)
274
275
276 ;;; Conditional
277 ;; @ifnottex ... @end ifnottex (makeinfo 3.11 or later)
278 (put 'ifnottex 'texinfo-format 'texinfo-discard-line)
279 (put 'ifnottex 'texinfo-end 'texinfo-discard-command)
280
281 ;; @ifnothtml ... @end ifnothtml (makeinfo 3.11 or later)
282 (put 'ifnothtml 'texinfo-format 'texinfo-discard-line)
283 (put 'ifnothtml 'texinfo-end 'texinfo-discard-command)
284
285 ;; @ifnotplaintext ... @end ifnotplaintext (makeinfo 4.2 or later)
286 (put 'ifnotplaintext 'texinfo-format 'texinfo-discard-line)
287 (put 'ifnotplaintext 'texinfo-end 'texinfo-discard-command)
288
289 ;; @ifnotdocbook ... @end ifnotdocbook (makeinfo 4.7 or later)
290 (put 'ifnotdocbook 'texinfo-format 'texinfo-discard-line)
291 (put 'ifnotdocbook 'texinfo-end 'texinfo-discard-command)
292
293 ;; @ifnotinfo ... @end ifnotinfo (makeinfo 3.11 or later)
294 (put 'ifnotinfo 'texinfo-format 'texinfo-format-ifnotinfo)
295 (ptexinfmt-defun-if-void texinfo-format-ifnotinfo ()
296   (delete-region texinfo-command-start
297                  (progn (re-search-forward "@end ifnotinfo[ \t]*\n")
298                         (point))))
299
300 ;; @html ... @end html (makeinfo 3.11 or later)
301 (put 'html 'texinfo-format 'texinfo-format-html)
302 (ptexinfmt-defun-if-void texinfo-format-html ()
303   (delete-region texinfo-command-start
304                  (progn (re-search-forward "@end html[ \t]*\n")
305                         (point))))
306
307 ;; @docbook ... @end docbook (makeinfo 4.7 or later)
308 (put 'docbook 'texinfo-format 'texinfo-format-docbook)
309 (ptexinfmt-defun-if-void texinfo-format-docbook ()
310   (delete-region texinfo-command-start
311                  (progn (re-search-forward "@end docbook[ \t]*\n")
312                         (point))))
313
314 ;; @ifhtml ... @end ifhtml (makeinfo 3.8 or later)
315 (put 'ifhtml 'texinfo-format 'texinfo-format-ifhtml)
316 (defun texinfo-format-ifhtml ()
317   (delete-region texinfo-command-start
318                  (progn (re-search-forward "@end ifhtml[ \t]*\n")
319                         (point))))
320
321 ;; @ifplaintext ... @end ifplaintext (makeinfo 4.2 or later)
322 (put 'ifplaintext 'texinfo-format 'texinfo-format-ifplaintext)
323 (ptexinfmt-defun-if-void texinfo-format-ifplaintext ()
324   (delete-region texinfo-command-start
325                  (progn (re-search-forward "@end ifplaintext[ \t]*\n")
326                         (point))))
327
328 ;; @ifdocbook ... @end ifdocbook (makeinfo 4.7 or later)
329 (put 'ifdocbook 'texinfo-format 'texinfo-format-ifdocbook)
330 (ptexinfmt-defun-if-void texinfo-format-ifdocbook ()
331   (delete-region texinfo-command-start
332                  (progn (re-search-forward "@end ifdocbook[ \t]*\n")
333                         (point))))
334
335 \f
336 ;;; Marking
337 ;; @indicateurl, @url, @env, @command, 
338 (put 'env 'texinfo-format 'texinfo-format-code)
339 (put 'command 'texinfo-format 'texinfo-format-code)
340
341 (put 'indicateurl 'texinfo-format 'texinfo-format-code)
342 (put 'url 'texinfo-format 'texinfo-format-uref) ; Texinfo 4.7
343
344 ;; @acronym
345 (put 'acronym 'texinfo-format 'texinfo-format-var)
346
347 (ptexinfmt-defun-if-broken texinfo-format-var ()
348   (let ((arg (texinfo-parse-expanded-arg)))
349     (texinfo-discard-command)
350     (insert (upcase arg))))
351
352 ;; @key
353 (put 'key 'texinfo-format 'texinfo-format-key)
354 (ptexinfmt-defun-if-void texinfo-format-key ()
355   (insert (texinfo-parse-arg-discard))
356   (goto-char texinfo-command-start))
357
358 ;; @email{EMAIL-ADDRESS[, DISPLAYED-TEXT]}
359 (put 'email 'texinfo-format 'texinfo-format-email)
360 (ptexinfmt-defun-if-void texinfo-format-email ()
361   "Format EMAIL-ADDRESS and optional DISPLAYED-TXT.
362 Insert < ... > around EMAIL-ADDRESS."
363   (let ((args (texinfo-format-parse-args)))
364   (texinfo-discard-command)
365     ;; if displayed-text
366     (if (nth 1 args)
367         (insert (nth 1 args) " <" (nth 0 args) ">")
368       (insert "<" (nth 0 args) ">"))))
369
370 ;; @option
371 (put 'option 'texinfo-format 'texinfo-format-option)
372 (ptexinfmt-defun-if-void texinfo-format-option ()
373   "Insert ` ... ' around arg unless inside a table; in that case, no quotes."
374   ;; `looking-at-backward' not available in v. 18.57, 20.2
375   ;; searched-for character is a control-H
376   (if (not (search-backward "\010"
377                             (save-excursion (beginning-of-line) (point))
378                             t))
379       (insert "`" (texinfo-parse-arg-discard) "'")
380     (insert (texinfo-parse-arg-discard)))
381   (goto-char texinfo-command-start))
382
383 ;; @verb{<char>TEXT<char>}  (makeinfo 4.1 or later)
384 (put 'verb 'texinfo-format 'texinfo-format-verb)
385 (ptexinfmt-defun-if-void texinfo-format-verb ()
386   "Format text between non-quoted unique delimiter characters verbatim.
387 Enclose the verbatim text, including the delimiters, in braces.  Print
388 text exactly as written (but not the delimiters) in a fixed-width.
389
390 For example, @verb\{|@|\} results in @ and
391 @verb\{+@'e?`!`+} results in @'e?`!`."
392
393   (let ((delimiter (buffer-substring-no-properties
394                     (1+ texinfo-command-end) (+ 2 texinfo-command-end))))
395     (unless (looking-at "{")
396       (error "Not found: @verb start brace"))
397     (delete-region texinfo-command-start (+ 2 texinfo-command-end))
398     (search-forward  delimiter))
399   (delete-backward-char 1)
400   (unless (looking-at "}")
401     (error "Not found: @verb end brace"))
402   (delete-char 1))
403
404 \f
405 ;;; @LaTeX, @registeredsymbol{}
406 (put 'LaTeX 'texinfo-format 'texinfo-format-LaTeX)
407 (ptexinfmt-defun-if-void texinfo-format-LaTeX ()
408   (texinfo-parse-arg-discard)
409   (insert "LaTeX"))
410
411 (put 'registeredsymbol 'texinfo-format 'texinfo-format-registeredsymbol)
412 (ptexinfmt-defun-if-void texinfo-format-registeredsymbol ()
413   (texinfo-parse-arg-discard)
414   (insert "(R)"))
415
416 ;;; Accents and Special characters
417 ;; @euro{}      ==>     Euro
418 (put 'euro 'texinfo-format 'texinfo-format-euro)
419 (ptexinfmt-defun-if-void texinfo-format-euro ()
420   (texinfo-parse-arg-discard)
421   (insert "Euro "))
422
423 ;; @pounds{}    ==>     #       Pounds Sterling
424 (put 'pounds 'texinfo-format 'texinfo-format-pounds)
425 (ptexinfmt-defun-if-void texinfo-format-pounds ()
426   (texinfo-parse-arg-discard)
427   (insert "#"))
428
429 ;; @ordf{}      ==>     a       Spanish feminine
430 (put 'ordf 'texinfo-format 'texinfo-format-ordf)
431 (ptexinfmt-defun-if-void texinfo-format-ordf ()
432   (texinfo-parse-arg-discard)
433   (insert "a"))
434
435 ;; @ordm{}      ==>     o       Spanish masculine
436 (put 'ordm 'texinfo-format 'texinfo-format-ordm)
437 (ptexinfmt-defun-if-void texinfo-format-ordm ()
438   (texinfo-parse-arg-discard)
439   (insert "o"))
440
441 ;; @OE{}        ==>     OE      French-OE-ligature
442 (put 'OE 'texinfo-format 'texinfo-format-French-OE-ligature)
443 (ptexinfmt-defun-if-void texinfo-format-French-OE-ligature ()
444   (insert "OE" (texinfo-parse-arg-discard))
445   (goto-char texinfo-command-start))
446
447 ;; @oe{}        ==>     oe
448 (put 'oe 'texinfo-format 'texinfo-format-French-oe-ligature)
449 (ptexinfmt-defun-if-void texinfo-format-French-oe-ligature () ; lower case
450   (insert "oe" (texinfo-parse-arg-discard))
451   (goto-char texinfo-command-start))
452
453 ;; @AA{}        ==>     AA      Scandinavian-A-with-circle
454 (put 'AA 'texinfo-format 'texinfo-format-Scandinavian-A-with-circle)
455 (ptexinfmt-defun-if-void texinfo-format-Scandinavian-A-with-circle ()
456   (insert "AA" (texinfo-parse-arg-discard))
457   (goto-char texinfo-command-start))
458
459 ;; @aa{}        ==>     aa
460 (put 'aa 'texinfo-format 'texinfo-format-Scandinavian-a-with-circle)
461 (ptexinfmt-defun-if-void texinfo-format-Scandinavian-a-with-circle () ; lower case
462   (insert "aa" (texinfo-parse-arg-discard))
463   (goto-char texinfo-command-start))
464
465 ;; @AE{}        ==>     AE      Latin-Scandinavian-AE
466 (put 'AE 'texinfo-format 'texinfo-format-Latin-Scandinavian-AE)
467 (ptexinfmt-defun-if-void texinfo-format-Latin-Scandinavian-AE ()
468   (insert "AE" (texinfo-parse-arg-discard))
469   (goto-char texinfo-command-start))
470
471 ;; @ae{}        ==>     ae
472 (put 'ae 'texinfo-format 'texinfo-format-Latin-Scandinavian-ae)
473 (ptexinfmt-defun-if-void texinfo-format-Latin-Scandinavian-ae () ; lower case
474   (insert "ae" (texinfo-parse-arg-discard))
475   (goto-char texinfo-command-start))
476
477 ;; @ss{}        ==>     ss      German-sharp-S
478 (put 'ss 'texinfo-format 'texinfo-format-German-sharp-S)
479 (ptexinfmt-defun-if-void texinfo-format-German-sharp-S ()
480   (insert "ss" (texinfo-parse-arg-discard))
481   (goto-char texinfo-command-start))
482
483 ;; @questiondown{}      ==>     ?       upside-down-question-mark
484 (put 'questiondown 'texinfo-format 'texinfo-format-upside-down-question-mark)
485 (ptexinfmt-defun-if-void texinfo-format-upside-down-question-mark ()
486   (insert "?" (texinfo-parse-arg-discard))
487   (goto-char texinfo-command-start))
488
489 ;; @exclamdown{}        ==>     !       upside-down-exclamation-mark
490 (put 'exclamdown 'texinfo-format 'texinfo-format-upside-down-exclamation-mark)
491 (ptexinfmt-defun-if-void texinfo-format-upside-down-exclamation-mark ()
492   (insert "!" (texinfo-parse-arg-discard))
493   (goto-char texinfo-command-start))
494
495 ;; @L{}         ==>     L/      Polish suppressed-L (Lslash)
496 (put 'L 'texinfo-format 'texinfo-format-Polish-suppressed-L)
497 (ptexinfmt-defun-if-void texinfo-format-Polish-suppressed-L ()
498   (insert (texinfo-parse-arg-discard) "/L")
499   (goto-char texinfo-command-start))
500
501 ;; @l{}         ==>     l/      Polish suppressed-L (Lslash) (lower case)
502 (put 'l 'texinfo-format 'texinfo-format-Polish-suppressed-l-lower-case)
503 (ptexinfmt-defun-if-void texinfo-format-Polish-suppressed-l-lower-case ()
504   (insert (texinfo-parse-arg-discard) "/l")
505   (goto-char texinfo-command-start))
506
507 ;; @O{}         ==>     O/      Scandinavian O-with-slash
508 (put 'O 'texinfo-format 'texinfo-format-Scandinavian-O-with-slash)
509 (ptexinfmt-defun-if-void texinfo-format-Scandinavian-O-with-slash ()
510   (insert (texinfo-parse-arg-discard) "O/")
511   (goto-char texinfo-command-start))
512
513 ;; @o{}         ==>     o/      Scandinavian O-with-slash (lower case)
514 (put 'o 'texinfo-format 'texinfo-format-Scandinavian-o-with-slash-lower-case)
515 (ptexinfmt-defun-if-void texinfo-format-Scandinavian-o-with-slash-lower-case ()
516   (insert (texinfo-parse-arg-discard) "o/")
517   (goto-char texinfo-command-start))
518
519 ;; @,{c}        ==>     c,      cedilla accent
520 (put '\, 'texinfo-format 'texinfo-format-cedilla-accent)
521 (ptexinfmt-defun-if-void texinfo-format-cedilla-accent ()
522   (insert (texinfo-parse-arg-discard) ",")
523   (goto-char texinfo-command-start))
524
525
526 ;; @dotaccent{o}        ==>     .o      overdot-accent
527 (put 'dotaccent 'texinfo-format 'texinfo-format-overdot-accent)
528 (ptexinfmt-defun-if-void texinfo-format-overdot-accent ()
529   (insert "." (texinfo-parse-arg-discard))
530   (goto-char texinfo-command-start))
531
532 ;; @ubaraccent{o}       ==>     _o      underbar-accent
533 (put 'ubaraccent 'texinfo-format 'texinfo-format-underbar-accent)
534 (ptexinfmt-defun-if-void texinfo-format-underbar-accent ()
535   (insert "_" (texinfo-parse-arg-discard))
536   (goto-char texinfo-command-start))
537
538 ;; @udotaccent{o}       ==>     o-.     underdot-accent
539 (put 'udotaccent 'texinfo-format 'texinfo-format-underdot-accent)
540 (ptexinfmt-defun-if-void texinfo-format-underdot-accent ()
541   (insert (texinfo-parse-arg-discard) "-.")
542   (goto-char texinfo-command-start))
543
544 ;; @H{o}        ==>     ""o     long Hungarian umlaut
545 (put 'H 'texinfo-format 'texinfo-format-long-Hungarian-umlaut)
546 (ptexinfmt-defun-if-void texinfo-format-long-Hungarian-umlaut ()
547   (insert "\"\"" (texinfo-parse-arg-discard))
548   (goto-char texinfo-command-start))
549
550 ;; @ringaccent{o}       ==>     *o      ring accent
551 (put 'ringaccent 'texinfo-format 'texinfo-format-ring-accent)
552 (ptexinfmt-defun-if-void texinfo-format-ring-accent ()
553   (insert "*" (texinfo-parse-arg-discard))
554   (goto-char texinfo-command-start))
555
556 ;; @tieaccent{oo}       ==>     [oo     tie after accent
557 (put 'tieaccent 'texinfo-format 'texinfo-format-tie-after-accent)
558 (ptexinfmt-defun-if-void texinfo-format-tie-after-accent ()
559   (insert "[" (texinfo-parse-arg-discard))
560   (goto-char texinfo-command-start))
561
562 ;; @u{o}        ==>     (o      breve accent
563 (put 'u 'texinfo-format 'texinfo-format-breve-accent)
564 (ptexinfmt-defun-if-void texinfo-format-breve-accent ()
565   (insert "(" (texinfo-parse-arg-discard))
566   (goto-char texinfo-command-start))
567
568 ;; @v{o}        ==>     <o      hacek accent
569 (put 'v 'texinfo-format 'texinfo-format-hacek-accent)
570 (ptexinfmt-defun-if-void texinfo-format-hacek-accent ()
571   (insert "<" (texinfo-parse-arg-discard))
572   (goto-char texinfo-command-start))
573
574 ;; @dotless{i}  ==>     i       dotless i and dotless j
575 (put 'dotless 'texinfo-format 'texinfo-format-dotless)
576 (ptexinfmt-defun-if-void texinfo-format-dotless ()
577   (insert (texinfo-parse-arg-discard))
578   (goto-char texinfo-command-start))
579
580 ;; @.
581 (put '\. 'texinfo-format 'texinfo-format-\.)
582 (ptexinfmt-defun-if-void texinfo-format-\. ()
583   (texinfo-discard-command)
584   (insert "."))
585
586 ;; @:
587 (put '\: 'texinfo-format 'texinfo-format-\:)
588 (ptexinfmt-defun-if-void texinfo-format-\: ()
589   (texinfo-discard-command))
590
591 ;; @-
592 (put '\- 'texinfo-format 'texinfo-format-soft-hyphen)
593 (ptexinfmt-defun-if-void texinfo-format-soft-hyphen ()
594   (texinfo-discard-command))
595
596 ;; @/
597 (put '\/ 'texinfo-format 'texinfo-format-\/)
598 (ptexinfmt-defun-if-void texinfo-format-\/ ()
599   (texinfo-discard-command))
600
601 \f
602 ;;; Cross References
603 ;; @ref, @xref
604 (put 'ref 'texinfo-format 'texinfo-format-xref)
605
606 (ptexinfmt-defun-if-broken texinfo-format-xref ()
607   (let ((args (texinfo-format-parse-args)))
608     (texinfo-discard-command)
609     (insert "*Note ")
610     (let ((fname (or (nth 1 args) (nth 2 args))))
611       (if (null (or fname (nth 3 args)))
612           (insert (nth 0 args) "::")
613         (insert (or fname (nth 0 args)) ": ")
614         (if (nth 3 args)
615             (insert "(" (nth 3 args) ")"))
616         (unless (null (nth 0 args))
617           (insert (nth 0 args)))))))
618
619 ;; @uref{URL [,TEXT] [,REPLACEMENT]}
620 (put 'uref 'texinfo-format 'texinfo-format-uref)
621 (ptexinfmt-defun-if-broken texinfo-format-uref ()
622   "Format URL and optional URL-TITLE.
623 Insert ` ... ' around URL if no URL-TITLE argument;
624 otherwise, insert URL-TITLE followed by URL in parentheses."
625   (let ((args (texinfo-format-parse-args)))
626     (texinfo-discard-command)
627     ;; if url-title
628     (if (nth 1 args)
629         (insert  (nth 1 args) " (" (nth 0 args) ")")
630       (insert "`" (nth 0 args) "'"))))
631
632 ;; @inforef
633 (put 'inforef 'texinfo-format 'texinfo-format-inforef)
634 (ptexinfmt-defun-if-void texinfo-format-inforef ()
635   (let ((args (texinfo-format-parse-args)))
636     (texinfo-discard-command)
637     (if (nth 1 args)
638         (insert "*Note " (nth 1 args) ": (" (nth 2 args) ")" (car args))
639       (insert "*Note " "(" (nth 2 args) ")" (car args) "::"))))
640
641
642 ;; @anchor
643 ;; don't emulation
644 ;; If support @anchor for Mule 2.3, We must fix informat.el and info.el:
645 ;;  - Info-tagify suport @anthor-*-refill.
646 ;;  - info.el support Ref in Tag table.
647 (unless (get 'anchor 'texinfo-format)
648   (put 'anchor 'texinfo-format 'texinfo-discard-command-and-arg))
649
650
651 \f
652 ;;; New command definition
653 ;; @alias NEW=EXISTING
654 (put 'alias 'texinfo-format 'texinfo-alias)
655 (ptexinfmt-defun-if-void texinfo-alias ()
656   (let ((start (1- (point)))
657         args)
658     (skip-chars-forward " ")
659     (save-excursion (end-of-line) (setq texinfo-command-end (point)))
660     (if (not (looking-at "\\([^=]+\\)=\\(.*\\)"))
661         (error "Invalid alias command")
662       (setq texinfo-alias-list
663             (cons
664              (cons
665               (buffer-substring (match-beginning 1) (match-end 1))
666               (buffer-substring (match-beginning 2) (match-end 2)))
667              texinfo-alias-list))
668       (texinfo-discard-command))))
669
670 \f
671 ;;; Indent
672 ;; @exampleindent INDENT  (makeinfo 4.0 or later)
673
674 ;; @paragraphindent INDENT  (makeinfo 4.0 or later)
675 ;; INDENT: asis, 0, n
676
677 ;; @firstparagraphindent WORD   (makeinfo 4.6 or later)
678 ;; WORD: none, insert
679
680
681 \f
682 ;;; Special
683 ;; @image{FILENAME [, WIDTH] [, HEIGHT]}
684 (put 'image 'texinfo-format 'texinfo-format-image)
685 (ptexinfmt-defun-if-void texinfo-format-image ()
686   ;; I don't know makeinfo parse FILENAME.
687   (let ((args (texinfo-format-parse-args))
688         filename)
689     (when (null (nth 0 args))
690       (error "Invalid image command"))
691     (texinfo-discard-command)
692     ;; makeinfo uses FILENAME.txt
693     (setq filename (format "%s.txt" (nth 0 args)))
694     (message "Reading included file: %s" filename)
695     ;; verbatim for Info output
696     (goto-char (+ (point) (cadr (insert-file-contents filename))))
697     (message "Reading included file: %s...done" filename)))
698
699 ;; @hyphenation command discards an argument within braces
700 (put 'hyphenation 'texinfo-format 'texinfo-discard-command-and-arg)
701 (ptexinfmt-defun-if-void texinfo-discard-command-and-arg ()
702   "Discard both @-command and its argument in braces."
703   (goto-char texinfo-command-end)
704   (forward-list 1)
705   (setq texinfo-command-end (point))
706   (delete-region texinfo-command-start texinfo-command-end))
707
708 \f
709 ;;; @multitable ... @end multitable
710 (ptexinfmt-defvar-if-void texinfo-extra-inter-column-width 0
711   "*Number of extra spaces between entries (columns) in @multitable.")
712
713 (ptexinfmt-defvar-if-void texinfo-multitable-buffer-name
714   "*multitable-temporary-buffer*")
715 (ptexinfmt-defvar-if-void texinfo-multitable-rectangle-name
716   "texinfo-multitable-temp-")
717
718 ;; These commands are defined in texinfo.tex for printed output.
719 (put 'multitableparskip 'texinfo-format 'texinfo-discard-line-with-args)
720 (put 'multitableparindent 'texinfo-format 'texinfo-discard-line-with-args)
721 (put 'multitablecolmargin 'texinfo-format 'texinfo-discard-line-with-args)
722 (put 'multitablelinespace 'texinfo-format 'texinfo-discard-line-with-args)
723
724 (put 'multitable 'texinfo-format 'texinfo-multitable)
725
726 (ptexinfmt-defun-if-void texinfo-multitable ()
727   "Produce multi-column tables."
728
729 ;; This function pushes information onto the `texinfo-stack'.
730 ;; A stack element consists of:
731 ;;   - type-of-command, i.e., multitable
732 ;;   - the information about column widths, and
733 ;;   - the position of texinfo-command-start.
734 ;; e.g., ('multitable (1 2 3 4) 123)
735 ;; The command line is then deleted.
736   (texinfo-push-stack
737    'multitable
738    ;; push width information on stack
739    (texinfo-multitable-widths))
740   (texinfo-discard-line-with-args))
741
742 (put 'multitable 'texinfo-end 'texinfo-end-multitable)
743 (ptexinfmt-defun-if-void texinfo-end-multitable ()
744   "Discard the @end multitable line and pop the stack of multitable."
745   (texinfo-discard-command)
746   (texinfo-pop-stack 'multitable))
747
748 (ptexinfmt-defun-if-broken texinfo-multitable-widths ()
749   "Return list of widths of each column in a multi-column table."
750   (let (texinfo-multitable-width-list)
751     ;; Fractions format:
752     ;;  @multitable @columnfractions .25 .3 .45
753     ;;
754     ;; Template format:
755     ;;  @multitable {Column 1 template} {Column 2} {Column 3 example}
756     ;; Place point before first argument
757     (skip-chars-forward " \t")
758     (cond
759      ;; Check for common misspelling
760      ((looking-at "@columnfraction ")
761       (error "In @multitable, @columnfractions misspelled"))
762      ;; Case 1: @columnfractions .25 .3 .45
763      ((looking-at "@columnfractions")
764       (forward-word 1)
765       (while (not (eolp))
766         (setq texinfo-multitable-width-list
767               (cons
768                (truncate
769                 (1-
770                  (* fill-column (read (get-buffer (current-buffer))))))
771                texinfo-multitable-width-list))))
772      ;;
773      ;; Case 2: {Column 1 template} {Column 2} {Column 3 example}
774      ((looking-at "{")
775       (let ((start-of-templates (point)))
776         (while (not (eolp))
777           (skip-chars-forward " \t")
778           (let* ((start-of-template (1+ (point)))
779                  (end-of-template
780                   ;; forward-sexp works with braces in Texinfo mode
781                   (progn (forward-sexp 1) (1- (point)))))
782             (setq texinfo-multitable-width-list
783                   (cons (- (progn
784                              (goto-char end-of-template)
785                              (current-column))
786                            (progn
787                              (goto-char start-of-template)
788                              (current-column)))
789                         texinfo-multitable-width-list))
790             ;; Remove carriage return from within a template, if any.
791             ;; This helps those those who want to use more than
792             ;; one line's worth of words in @multitable line.
793             (narrow-to-region start-of-template end-of-template)
794             (goto-char (point-min))
795             (while (search-forward "\n" nil t)
796               (delete-char -1))
797             (goto-char (point-max))
798             (widen)
799             (forward-char 1)))))
800      ;;
801      ;; Case 3: Trouble
802      (t
803       (error "\
804 You probably need to specify column widths for @multitable correctly")))
805     ;; Check whether columns fit on page.
806     (let ((desired-columns
807            (+
808             ;; between column spaces
809             (length texinfo-multitable-width-list)
810             ;; additional between column spaces, if any
811             texinfo-extra-inter-column-width
812             ;; sum of spaces for each entry
813             (apply '+ texinfo-multitable-width-list))))
814       (if (> desired-columns fill-column)
815           (error (format "\
816 Multi-column table width, %d chars, is greater than page width, %d chars."
817                          desired-columns fill-column))))
818     texinfo-multitable-width-list))
819
820 ;; @item  A1  @tab  A2  @tab  A3
821 (ptexinfmt-defun-if-void texinfo-multitable-extract-row ()
822   "Return multitable row, as a string.
823 End of row is beginning of next @item or beginning of @end.
824 Cells within rows are separated by @tab."
825   (skip-chars-forward " \t")
826   (let* ((start (point))
827          (end (progn
828                 (re-search-forward "@item\\|@end")
829                 (match-beginning 0)))
830          (row (progn (goto-char end)
831                      (skip-chars-backward " ")
832                      ;; remove whitespace at end of argument
833                      (delete-region (point) end)
834                      (buffer-substring start (point)))))
835     (delete-region texinfo-command-start end)
836     row))
837
838 (put 'multitable 'texinfo-item 'texinfo-multitable-item)
839 (ptexinfmt-defun-if-void texinfo-multitable-item ()
840   "Format a row within a multicolumn table.
841 Cells in row are separated by @tab.
842 Widths of cells are specified by the arguments in the @multitable line.
843 All cells are made to be the same height.
844 This command is executed when texinfmt sees @item inside @multitable."
845   (let ((original-buffer (current-buffer))
846         (table-widths (reverse (car (cdr (car texinfo-stack)))))
847         (existing-fill-column fill-column)
848         start
849         end
850         (table-column       0)
851         (table-entry-height 0)
852         ;; unformatted row looks like:  A1  @tab  A2  @tab  A3
853         ;; extract-row command deletes the source line in the table.
854         (unformated-row (texinfo-multitable-extract-row)))
855     ;; Use a temporary buffer
856     (set-buffer (get-buffer-create texinfo-multitable-buffer-name))
857     (delete-region (point-min) (point-max))
858     (insert unformated-row)
859     (goto-char (point-min))
860 ;; 1. Check for correct number of @tab in line.
861     (let ((tab-number 1)) ;; one @tab between two columns
862       (while (search-forward "@tab" nil t)
863         (setq tab-number (1+ tab-number)))
864       (if (/= tab-number (length table-widths))
865           (error "Wrong number of @tab's in a @multitable row")))
866     (goto-char (point-min))
867 ;; 2. Format each cell, and copy to a rectangle
868     ;; buffer looks like this:    A1  @tab  A2  @tab  A3
869     ;; Cell #1: format up to @tab
870     ;; Cell #2: format up to @tab
871     ;; Cell #3: format up to eob
872     (while (not (eobp))
873       (setq start (point))
874       (setq end (save-excursion
875                   (if (search-forward "@tab" nil 'move)
876                       ;; Delete the @tab command, including the @-sign
877                       (delete-region
878                        (point)
879                        (progn (forward-word -1) (1- (point)))))
880                   (point)))
881       ;; Set fill-column *wider* than needed to produce inter-column space
882       (setq fill-column (+ 1
883                            texinfo-extra-inter-column-width
884                            (nth table-column table-widths)))
885       (narrow-to-region start end)
886       ;; Remove whitespace before and after entry.
887       (skip-chars-forward " ")
888       (delete-region (point) (save-excursion (beginning-of-line) (point)))
889       (goto-char (point-max))
890       (skip-chars-backward " ")
891       (delete-region (point) (save-excursion (end-of-line) (point)))
892       ;; Temorarily set texinfo-stack to nil so texinfo-format-scan
893       ;; does not see an unterminated @multitable.
894       (let (texinfo-stack) ;; nil
895         (texinfo-format-scan))
896       (let (fill-prefix) ;; no fill prefix
897         (fill-region (point-min) (point-max)))
898       (setq table-entry-height
899             (max table-entry-height (count-lines (point-min) (point-max))))
900 ;; 3. Move point to end of bottom line, and pad that line to fill column.
901       (goto-char (point-min))
902       (forward-line (1- table-entry-height))
903       (let* ((beg (point)) ;; beginning of line
904              ;; add one more space for inter-column spacing
905              (needed-whitespace
906               (1+
907                (- fill-column
908                   (progn
909                     (end-of-line)
910                     (current-column)))))) ;; end of existing line
911         (insert (make-string
912                  (if (> needed-whitespace 0) needed-whitespace 1)
913                  ? )))
914       ;; now, put formatted cell into a rectangle
915       (set (intern (concat texinfo-multitable-rectangle-name
916                            (int-to-string table-column)))
917            (extract-rectangle (point-min) (point)))
918       (delete-region (point-min) (point))
919       (goto-char (point-max))
920       (setq table-column (1+ table-column))
921       (widen))
922 ;; 4. Add extra lines to rectangles so all are of same height
923     (let ((total-number-of-columns table-column)
924           (column-number 0)
925           here)
926       (while (> table-column 0)
927         (let ((this-rectangle (int-to-string table-column)))
928           (while (< (length this-rectangle) table-entry-height)
929             (setq this-rectangle (append this-rectangle '("")))))
930         (setq table-column (1- table-column)))
931 ;; 5. Insert formatted rectangles in original buffer
932       (switch-to-buffer original-buffer)
933       (open-line table-entry-height)
934       (while (< column-number total-number-of-columns)
935         (setq here (point))
936         (insert-rectangle
937          (eval (intern
938                 (concat texinfo-multitable-rectangle-name
939                         (int-to-string column-number)))))
940         (goto-char here)
941         (end-of-line)
942         (setq column-number (1+ column-number))))
943     (kill-buffer texinfo-multitable-buffer-name)
944     (setq fill-column existing-fill-column)))
945
946 \f
947 (ptexinfmt-defun-if-broken texinfo-format-printindex ()
948   (let ((indexelts (symbol-value
949                     (cdr (assoc (texinfo-parse-arg-discard)
950                                 texinfo-indexvar-alist))))
951         opoint)
952     (insert "\n* Menu:\n\n")
953     (setq opoint (point))
954     (texinfo-print-index nil indexelts)
955
956     (if (memq system-type '(vax-vms windows-nt ms-dos))
957         (texinfo-sort-region opoint (point))
958       (shell-command-on-region opoint (point) "sort -fd" 1))))
959
960 (ptexinfmt-broken-facility texinfo-format-end-node ()
961   (with-temp-buffer
962     (insert (prin1-to-string (symbol-function 'texinfo-format-end-node)))
963     (goto-char (point-min))
964     (not (search-forward "fill-paragraph" nil t nil))))
965
966 (ptexinfmt-defun-if-broken texinfo-format-end-node ()
967   (let (start
968         (arg (texinfo-parse-line-arg)))
969     (texinfo-discard-command) ; remove or insert whitespace, as needed
970     (delete-region (save-excursion (skip-chars-backward " \t\n") (point))
971                    (point))
972     (insert (format " (%d) " texinfo-footnote-number))
973     ;;(fill-paragraph nil)
974     (save-excursion
975       (if (search-forward "\n--------- Footnotes ---------\n" nil t)
976           (progn ; already have footnote, put new one before end of node
977             (if (re-search-forward "^@node" nil 'move)
978                 (forward-line -1))
979             (setq start (point))
980             (insert (format "\n(%d)  %s\n" texinfo-footnote-number arg))
981             (fill-region start (point)))
982         ;; else no prior footnote
983         (if (re-search-forward "^@node" nil 'move)
984             (forward-line -1))
985         (insert "\n--------- Footnotes ---------\n")
986         (setq start (point))
987         (insert (format "\n(%d)  %s\n" texinfo-footnote-number arg))))))
988
989 \f
990 ;; @copying ... @end copying
991 ;; that Emacs 21.4 and lesser and XEmacs don't support.
992 (if (fboundp 'texinfo-copying)
993     nil
994   (defvar texinfo-copying-text ""
995     "Text of the copyright notice and copying permissions.")
996
997   (defun texinfo-copying ()
998     "Copy the copyright notice and copying permissions from the Texinfo file,
999 as indicated by the @copying ... @end copying command;
1000 insert the text with the @insertcopying command."
1001     (let ((beg (progn (beginning-of-line) (point)))
1002           (end  (progn (re-search-forward "^@end copying[ \t]*\n") (point))))
1003       (setq texinfo-copying-text
1004             (buffer-substring-no-properties
1005              (save-excursion (goto-char beg) (forward-line 1) (point))
1006              (save-excursion (goto-char end) (forward-line -1) (point))))
1007       (delete-region beg end)))
1008
1009   (defun texinfo-insertcopying ()
1010     "Insert the copyright notice and copying permissions from the Texinfo file,
1011 which are indicated by the @copying ... @end copying command."
1012     (insert (concat "\n" texinfo-copying-text)))
1013
1014   (defadvice texinfo-format-scan (before expand-@copying-section activate)
1015     "Extract @copying and replace @insertcopying with it."
1016     (goto-char (point-min))
1017     (when (search-forward "@copying" nil t)
1018       (texinfo-copying))
1019     (while (search-forward "@insertcopying" nil t)
1020       (delete-region (match-beginning 0) (match-end 0))
1021       (texinfo-insertcopying))))
1022
1023 (provide 'ptexinfmt)
1024
1025 ;;; ptexinfmt.el ends here