comparison lisp/woman.el @ 29074:3b4c3f9b9c66

(From Francis J. Wright <F.J.Wright@Maths.QMW.ac.uk) (woman-mapcan, woman-parse-man.conf) (woman-toggle-use-extended-font, woman-toggle-use-symbol-font) (woman-reset-emulation): New functions. (woman-parse-colon-path): Call woman-mapcan. Recognize Cygwin path syntax better. (woman-man.conf-path, woman-use-own-frame): New defcustoms. (woman-manpath): Call woman-parse-man.conf. (woman-emulation): New defcustom, defaults to nroff. (woman-font-support): New defconst. (woman-select-symbol-fonts): New function. (woman-use-symbol-font): New defcustom. (woman-menu): Add new menu items: "Colored/BW", "Advanced", "Emulation". Many functions: Doc fix.
author Eli Zaretskii <eliz@gnu.org>
date Mon, 22 May 2000 06:58:47 +0000
parents eb06b6bb8aa8
children eea914233f47
comparison
equal deleted inserted replaced
29073:b46c4dc8c51a 29074:3b4c3f9b9c66
5 ;; Author: Francis J. Wright <F.J.Wright@Maths.QMW.ac.uk> 5 ;; Author: Francis J. Wright <F.J.Wright@Maths.QMW.ac.uk>
6 ;; Maintainer: Francis J. Wright <F.J.Wright@Maths.QMW.ac.uk> 6 ;; Maintainer: Francis J. Wright <F.J.Wright@Maths.QMW.ac.uk>
7 ;; Keywords: help, man, UN*X, manual 7 ;; Keywords: help, man, UN*X, manual
8 ;; Adapted-By: Eli Zaretskii <eliz@is.elta.co.il> 8 ;; Adapted-By: Eli Zaretskii <eliz@is.elta.co.il>
9 ;; Version: see `woman-version' 9 ;; Version: see `woman-version'
10 ;; URL: http://centaur.maths.qmw.ac.uk/Emacs/
10 11
11 ;; This file is part of GNU Emacs. 12 ;; This file is part of GNU Emacs.
12 13
13 ;; GNU Emacs is free software; you can redistribute it and/or modify 14 ;; GNU Emacs is free software; you can redistribute it and/or modify
14 ;; it under the terms of the GNU General Public License as published by 15 ;; it under the terms of the GNU General Public License as published by
64 ;; Help' when WoMan is running. 65 ;; Help' when WoMan is running.
65 66
66 ;; WoMan is still under development! Please let me know what doesn't 67 ;; WoMan is still under development! Please let me know what doesn't
67 ;; work -- I am adding and improving functionality as testing shows 68 ;; work -- I am adding and improving functionality as testing shows
68 ;; that it is necessary. See below for guidance on reporting bugs. 69 ;; that it is necessary. See below for guidance on reporting bugs.
69
70 ;; The latest versions of this (and related) files are available from
71 ;; the URL
72
73 ;; http://centaur.maths.qmw.ac.uk/Emacs/
74 70
75 ;; Recommended use 71 ;; Recommended use
76 ;; =============== 72 ;; ===============
77 73
78 ;; Put this in your .emacs: 74 ;; Put this in your .emacs:
98 94
99 ;; Or (3): Put the next two sexpr's in your .emacs: 95 ;; Or (3): Put the next two sexpr's in your .emacs:
100 ;; (autoload 'woman-dired-find-file "woman" 96 ;; (autoload 'woman-dired-find-file "woman"
101 ;; "In dired, run the WoMan man-page browser on this file." t) 97 ;; "In dired, run the WoMan man-page browser on this file." t)
102 ;; (add-hook 'dired-mode-hook 98 ;; (add-hook 'dired-mode-hook
103 ;; #'(lambda () 99 ;; (lambda ()
104 ;; (define-key dired-mode-map "W" 'woman-dired-find-file))) 100 ;; (define-key dired-mode-map "W" 'woman-dired-find-file)))
105 ;; and open the directory containing the man page file using dired, 101 ;; and open the directory containing the man page file using dired,
106 ;; put the cursor on the file, and press `W'. 102 ;; put the cursor on the file, and press `W'.
107 103
108 ;; In each case, the result should (!) be a buffer in Man mode showing 104 ;; In each case, the result should (!) be a buffer in Man mode showing
109 ;; a formatted manual entry. When called from WoMan, Man mode should 105 ;; a formatted manual entry. When called from WoMan, Man mode should
156 152
157 ;; The variable `woman-topic-at-point' can be rebound locally, which 153 ;; The variable `woman-topic-at-point' can be rebound locally, which
158 ;; may be useful to provide special private key bindings, e.g. 154 ;; may be useful to provide special private key bindings, e.g.
159 155
160 ;; (global-set-key "\C-cw" 156 ;; (global-set-key "\C-cw"
161 ;; #'(lambda () 157 ;; (lambda ()
162 ;; (interactive) 158 ;; (interactive)
163 ;; (let ((woman-topic-at-point t)) 159 ;; (let ((woman-topic-at-point t))
164 ;; (woman))))) 160 ;; (woman)))))
165 161
166 162
272 268
273 ;; (setq format-alist 269 ;; (setq format-alist
274 ;; (cons 270 ;; (cons
275 ;; '(man "UN*X man-page source format" "\\.\\(TH\\|ig\\) " 271 ;; '(man "UN*X man-page source format" "\\.\\(TH\\|ig\\) "
276 ;; woman-decode-region nil nil 272 ;; woman-decode-region nil nil
277 ;; #'(lambda (arg) 273 ;; (lambda (arg)
278 ;; (set-visited-file-name 274 ;; set-visited-file-name
279 ;; (file-name-sans-extension buffer-file-name))))) 275 ;; (file-name-sans-extension buffer-file-name)))))
280 ;; format-alist)) 276 ;; format-alist))
281 277
282 278
283 ;; Reporting Bugs 279 ;; Reporting Bugs
284 ;; ============== 280 ;; ==============
334 330
335 331
336 ;; TO DO 332 ;; TO DO
337 ;; ===== 333 ;; =====
338 334
335 ;; Reconsider case sensitivity of file names.
339 ;; MUST PROCESS .if, .nr IN ORDER ENCOUNTERED IN FILE! (rcsfile, mf). 336 ;; MUST PROCESS .if, .nr IN ORDER ENCOUNTERED IN FILE! (rcsfile, mf).
340 ;; Allow general delimiter in `\v', cf. `\h'. 337 ;; Allow general delimiter in `\v', cf. `\h'.
341 ;; Improve major-mode documentation. 338 ;; Improve major-mode documentation.
342 ;; Pre-process conditionals in macro bodies if possible for speed? 339 ;; Pre-process conditionals in macro bodies if possible for speed?
343 ;; Emulate some preprocessor support for tbl (.TS/.TE) and eqn (.EQ/.EN) 340 ;; Emulate some preprocessor support for tbl (.TS/.TE) and eqn (.EQ/.EN)
354 ;; Add apropos facility by searching NAME (?) entry in man files? 351 ;; Add apropos facility by searching NAME (?) entry in man files?
355 ;; Documentation -- optional auto-display of formatted WoMan man page? 352 ;; Documentation -- optional auto-display of formatted WoMan man page?
356 ;; Implement a bug reporter? 353 ;; Implement a bug reporter?
357 ;; Support diversion and traps (to some extent) - for Tcl/tk pages? 354 ;; Support diversion and traps (to some extent) - for Tcl/tk pages?
358 ;; Add a menu of WoMan buffers? 355 ;; Add a menu of WoMan buffers?
356 ;; Fix .fc properly?
359 357
360 358
361 ;; Implementation strategy [this description is now well out of date!] 359 ;; Implementation strategy [this description is now well out of date!]
362 ;; -- three main passes, each to process respectively: 360 ;; -- three main passes, each to process respectively:
363 361
368 ;; For each pass, a control function finds and pre-processes the 366 ;; For each pass, a control function finds and pre-processes the
369 ;; escape or request and then calls the appropriate function to 367 ;; escape or request and then calls the appropriate function to
370 ;; perform the required formatting. Based originally on enriched.el 368 ;; perform the required formatting. Based originally on enriched.el
371 ;; and format.el. 369 ;; and format.el.
372 370
373 ;; See also /usr/local/share/groff/tmac/tmac.an 371 ;; The background information that made this project possible is
372 ;; freely available courtesy of Bell Labs from
373 ;; http://cm.bell-labs.com/7thEdMan/
374 374
375 375
376 ;; Acknowledgements 376 ;; Acknowledgements
377 ;; ================ 377 ;; ================
378 378
413 ;; Wei-Xue Shi <wxshi@ma.neweb.ne.jp> 413 ;; Wei-Xue Shi <wxshi@ma.neweb.ne.jp>
414 ;; Fabio Somenzi <fabio@joplin.colorado.edu> 414 ;; Fabio Somenzi <fabio@joplin.colorado.edu>
415 ;; Karel Sprenger <ks@ic.uva.nl> 415 ;; Karel Sprenger <ks@ic.uva.nl>
416 ;; Chris Szurgot <szurgot@itribe.net> 416 ;; Chris Szurgot <szurgot@itribe.net>
417 ;; Paul A. Thompson <pat@po.cwru.edu> 417 ;; Paul A. Thompson <pat@po.cwru.edu>
418 ;; Arrigo Triulzi <arrigo@maths.qmw.ac.uk>
418 ;; Geoff Voelker <voelker@cs.washington.edu> 419 ;; Geoff Voelker <voelker@cs.washington.edu>
419 420
420 (defconst woman-version "0.52 (beta), Time-stamp: <09 January 2000>" 421 (defvar woman-version "0.54 (beta)" "WoMan version information.")
421 "WoMan version information.") 422
422 423 ;;; History:
423 ;; $Id: woman.el,v 1.26 2000-01-09 09:44:25+00 fjw Rel $ 424 ;; For recent change log see end of file.
424
425 ;; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
426 ;; Changes in version 0.52 ([*] => user interface change)
427 ;; Speeded up handling of underlined faces (mainly for "italics").
428 ;; [*] WoMan formatting time display and log added. Emacs `man'
429 ;; formatting time display advice added. (This suggests that
430 ;; WoMan formatting is faster than Emacs `man' *formatting*,
431 ;; i.e. when man is not using `catman' caching. E.g. `woman
432 ;; bash' takes 27s whereas `man bash' takes 35s and for smaller
433 ;; files `woman' can be relatively much faster than `man'.)
434 ;; [*] Experimental support for non-ASCII characters from the
435 ;; default and symbol fonts added, initially only for MS-Windows.
436 ;; NOTE: It is off by default, mainly because it may increase the
437 ;; line spacing; customize `woman-use-symbols' to `on' to use it.
438 ;; Pad character handling for .fc fixed.
439 ;; Tested: see `woman.status'.
440
441 ;; Changes in version 0.51 ([*] => user interface change)
442 ;; [*] Improved handling of underlined faces (mainly for "italics").
443 ;; [*] Allow environment variables in directory path elements.
444 ;; Display of pre-formatted files improved.
445 ;; [*] Unintentional interaction with standard Man mode reduced.
446 ;; [*] bzip2 decompression support added. All decompression now
447 ;; works by turning on `auto-compression-mode' to decompress the
448 ;; file if necessary, rather than decompressing explicitly.
449 ;; Filename and compression regexps are now customizable user
450 ;; options.
451
452 ;; Changes in version 0.50 ([*] => user interface change)
453 ;; [*] Requires GNU Emacs 20.3+.
454 ;; [*] `defface' used to define faces.
455 ;; [*] Follow `see also' references with mouse-2 click.
456 ;; Number register increment support added (woman-registers).
457 ;; .j must be a NUMBER acceptable by .ad request.
458 ;; Very crude field support added.
459 ;; Vertical unit specifier `v' added to register handling.
460 ;; Improvement to local horizontal motion processing.
461 ;; Minor fix to handle negative numeric arguments.
462 ;; Handle horizontal motion escapes `\h' better.
463 ;; Allow arbitrary delimiters in `.if', inc. special character escapes.
464 ;; Allow `\n' within `.if' string comparisons.
465 ;; Allow arbitrary delimiters in `\w', inc. special character escapes.
466 ;; Processing of `\h' moved much later -- after indenting etc!
467 ;; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
468 425
469 426
470 ;;; Code: 427 ;;; Code:
471 428
472 (require 'man) 429 (require 'man)
473 (eval-when-compile ; to avoid compiler warnings 430 (eval-when-compile ; to avoid compiler warnings
474 (require 'dired) 431 (require 'dired)
475 (require 'apropos)) 432 (require 'apropos))
476 433
434 (defun woman-mapcan (fn x)
435 "Return concatenated list of FN applied to successive CAR elements of X.
436 FN must return a list, cons or nil. Useful for splicing into a list."
437 ;; Based on the Standard Lisp function MAPCAN but with args swapped!
438 (and x (nconc (funcall fn (car x)) (woman-mapcan fn (cdr x)))))
439
477 (defun woman-parse-colon-path (cd-path) 440 (defun woman-parse-colon-path (cd-path)
478 "Explode a search path CD-PATH into a list of directory names. 441 "Explode a search path CD-PATH into a list of directory names.
479 If the platform is MS-DOS/MS-Windows and any path begins with `//', 442 If the platform is Microsoft Windows and no path contains `\\' then
480 assume a Cygwin-style colon-separated search path and convert any 443 assume a Cygwin-style colon-separated search path and convert any
481 leading drive specifier `//X/' to `X:', otherwise assume paths 444 leading drive specifier `//X/' to `X:', otherwise assume paths
482 separated by `path-separator'." 445 separated by `path-separator'."
483 ;; Based on a suggestion by Jari Aalto. 446 ;; Based on a suggestion by Jari Aalto.
484 (if (and (memq system-type '(ms-dos windows-nt)) 447 (woman-mapcan ; splice into list...
485 (or (string-match "://" cd-path) 448 (lambda (path)
486 (and (not (string-match ":" cd-path)) 449 ;; parse-colon-path returns nil for a null path component and
487 (string-match "\\`//" cd-path)))) 450 ;; an empty substring of MANPATH denotes the default list...
488 (let ((path-separator ":")) 451 (if path (cons path nil) (woman-parse-man.conf)))
489 (mapcar 452 (if (and (memq system-type '(windows-nt ms-dos))
490 (function 453 (not (or (string-match ";" cd-path)
454 (string-match "\\\\" cd-path))))
455 (let ((path-separator ":"))
456 (mapcar
491 (lambda (path) ; //a/b -> a:/b 457 (lambda (path) ; //a/b -> a:/b
492 (cond ((string-match "\\`//" path) 458 (cond ((and path (string-match "\\`//./" path))
493 (setq path (substring path 1)) ; //a/b -> /a/b 459 (setq path (substring path 1)) ; //a/b -> /a/b
494 (aset path 0 (aref path 1)) ; /a/b -> aa/b 460 (aset path 0 (aref path 1)) ; /a/b -> aa/b
495 (aset path 1 ?:) ; aa/b -> a:/b 461 (aset path 1 ?:) ; aa/b -> a:/b
496 )) 462 ))
497 path)) 463 path)
498 (parse-colon-path cd-path))) 464 (parse-colon-path cd-path)))
499 (parse-colon-path cd-path))) 465 (parse-colon-path cd-path))))
500 466
501 467
502 ;;; User options: 468 ;;; User options:
503 469
504 ;; NB: Group identifiers must be lowercase! 470 ;; NB: Group identifiers must be lowercase!
532 (defgroup woman-interface nil 498 (defgroup woman-interface nil
533 "Interface options for browsing UNIX manual pages `wo (without) man'." 499 "Interface options for browsing UNIX manual pages `wo (without) man'."
534 :tag "WoMan Interface" 500 :tag "WoMan Interface"
535 :group 'woman) 501 :group 'woman)
536 502
503 (defcustom woman-man.conf-path
504 '("/etc" "/usr/local/lib")
505 "*List of dirs to search and/or files to try for man config file.
506 Default is '(\"/etc\" \"/usr/local/lib\") [for GNU/Linux, Cygwin resp.]
507 A trailing separator (`/' for UNIX etc.) on directories is optional
508 and the filename matched if a directory is specified is the first to
509 contain the string \"man.conf\".
510 If MANPATH is not set but a config file is found then it is parsed
511 instead to provide a default value for `woman-manpath'."
512 :type '(repeat string)
513 :group 'woman-interface)
514
515 (defun woman-parse-man.conf ()
516 "Parse man config file if found. (Used only if MANPATH is not set.)
517 Look in `woman-man.conf-path' and return a value for `woman-manpath'.
518 Concatenate data from all lines in the config file of the form
519 MANPATH /usr/man"
520 ;; Functionality suggested by Charles Curley.
521 (let ((path woman-man.conf-path)
522 file manpath)
523 (while (and
524 path
525 (not (and
526 (file-readable-p (setq file (car path)))
527 ;; If not a file then find the file:
528 (or (not (file-directory-p file))
529 (and
530 (setq file
531 (directory-files file t "man\\.conf" t))
532 (file-readable-p (setq file (car file)))))
533 ;; Parse the file -- if no MANPATH data ignore it:
534 (with-temp-buffer
535 (insert-file-contents file)
536 (while (re-search-forward
537 "^[ \t]*MANPATH[ \t]+\\(\\S-+\\)" nil t)
538 (setq manpath (cons (match-string 1) manpath)))
539 manpath))
540 ))
541 (setq path (cdr path)))
542 (nreverse manpath)))
543
537 (defcustom woman-manpath 544 (defcustom woman-manpath
538 (let ((manpath (getenv "MANPATH"))) 545 (let ((manpath (getenv "MANPATH")))
539 (if manpath 546 (or
540 (woman-parse-colon-path manpath) 547 (and manpath (woman-parse-colon-path manpath))
541 ;; NB: `parse-colon-path' creates null elements for redundant 548 (woman-parse-man.conf)
542 ;; (semi-)colons and trailing `/'s! 549 '("/usr/man" "/usr/local/man")
543 '("/usr/man" "/usr/local/man") 550 ))
544 ))
545 "*List of DIRECTORY TREES to search for UN*X manual files. 551 "*List of DIRECTORY TREES to search for UN*X manual files.
546 Each element should be the name of a directory that contains 552 Each element should be the name of a directory that contains
547 subdirectories of the form `man?', or more precisely subdirectories 553 subdirectories of the form `man?', or more precisely subdirectories
548 selected by the value of `woman-manpath-man-regexp'. Non-directory 554 selected by the value of `woman-manpath-man-regexp'. Non-directory
549 and unreadable files are ignored. The default value of this variable 555 and unreadable files are ignored.
550 is based on the UN*X MANPATH environment variable if set, otherwise 556
557 If not set then the environment variable MANPATH is used. If no such
558 environment variable is found, the default list is determined by
559 consulting the man configuration file if found. By default this is
560 either `/etc/man.config' or `/usr/local/lib/man.conf', which is
561 determined by the user option `woman-man.conf-path'. An empty
562 substring of MANPATH denotes the default list. Otherwise, the default
563 value of this variable is
551 564
552 (\"/usr/man\" \"/usr/local/man\"). 565 (\"/usr/man\" \"/usr/local/man\").
553 566
554 Any environment variables (which must have the UN*X-style form $NAME, 567 Any environment variables (names must have the UN*X-style form $NAME,
555 e.g. $HOME, $EMACSDATA, $EMACS_DIR) are evaluated first but each 568 e.g. $HOME, $EMACSDATA, $EMACS_DIR) are evaluated first but each
556 element must evaluate to a SINGLE directory name. Trailing `/'s are 569 element must evaluate to a SINGLE directory name. Trailing `/'s are
557 ignored. (Specific directories in `woman-path' are also searched.) 570 ignored. (Specific directories in `woman-path' are also searched.)
558 571
559 Microsoft platforms: 572 Microsoft platforms:
652 see the documentation for `imenu-generic-expression'." 665 see the documentation for `imenu-generic-expression'."
653 :type 'sexp 666 :type 'sexp
654 :group 'woman-interface) 667 :group 'woman-interface)
655 668
656 (defcustom woman-imenu nil 669 (defcustom woman-imenu nil
657 "*If non-nil, WoMan adds a Contents menu to the menubar. 670 "*If non-nil then WoMan adds a Contents menu to the menubar.
658 WoMan adds the Contents menu by calling `imenu-add-to-menubar'. 671 It does this by calling `imenu-add-to-menubar'. Default is nil."
659 Default is nil."
660 :type 'boolean 672 :type 'boolean
661 :group 'woman-interface) 673 :group 'woman-interface)
662 674
663 (defcustom woman-imenu-title "CONTENTS" 675 (defcustom woman-imenu-title "CONTENTS"
664 "*The title to use if WoMan adds a Contents menu to the menubar. 676 "*The title to use if WoMan adds a Contents menu to the menubar.
697 (defvar woman-uncompressed-file-regexp) ; for the compiler 709 (defvar woman-uncompressed-file-regexp) ; for the compiler
698 (defvar woman-file-compression-regexp) ; for the compiler 710 (defvar woman-file-compression-regexp) ; for the compiler
699 711
700 (defun set-woman-file-regexp (symbol value) 712 (defun set-woman-file-regexp (symbol value)
701 "Bind SYMBOL to VALUE and set `woman-file-regexp' as per user customizations. 713 "Bind SYMBOL to VALUE and set `woman-file-regexp' as per user customizations.
702 Used as :set cookie by Customize when user customized the user options 714 Used as :set cookie by Customize when customizing the user options
703 `woman-uncompressed-file-regexp' and `woman-file-compression-regexp'." 715 `woman-uncompressed-file-regexp' and `woman-file-compression-regexp'."
704 (set-default symbol value) 716 (set-default symbol value)
705 (and (boundp 'woman-uncompressed-file-regexp) 717 (and (boundp 'woman-uncompressed-file-regexp)
706 (boundp 'woman-file-compression-regexp) 718 (boundp 'woman-file-compression-regexp)
707 (setq woman-file-regexp 719 (setq woman-file-regexp
727 739
728 (defcustom woman-file-compression-regexp 740 (defcustom woman-file-compression-regexp
729 "\\.\\(g?z\\|bz2\\)\\'" 741 "\\.\\(g?z\\|bz2\\)\\'"
730 "*Do not change this unless you are sure you know what you are doing! 742 "*Do not change this unless you are sure you know what you are doing!
731 Regexp used to match compressed man file extensions for which 743 Regexp used to match compressed man file extensions for which
732 decompressors are available and handled by function `auto-compression-mode', 744 decompressors are available and handled by auto-compression mode,
733 e.g. \"\\\\.\\\\(g?z\\\\|bz2\\\\)\\\\'\" for `gzip' or `bzip2'. 745 e.g. \"\\\\.\\\\(g?z\\\\|bz2\\\\)\\\\'\" for `gzip' or `bzip2'.
734 Should begin with \\. and end with \\' and MUST NOT be optional." 746 Should begin with \\. and end with \\' and MUST NOT be optional."
747 ;; Should be compatible with car of
748 ;; `jka-compr-file-name-handler-entry', but that is unduly
749 ;; complicated, includes an inappropriate extension (.tgz) and is
750 ;; not loaded by default!
735 :type 'regexp 751 :type 'regexp
736 :set 'set-woman-file-regexp 752 :set 'set-woman-file-regexp
753 :group 'woman-interface)
754
755 (defcustom woman-use-own-frame
756 (or (and (fboundp 'display-graphic-p) (display-graphic-p))
757 (memq window-system '(x w32)))
758 "*If non-nil then use a dedicated frame for displaying WoMan windows.
759 Only useful when run on a graphic display such as X or MS-Windows."
760 :type 'boolean
737 :group 'woman-interface) 761 :group 'woman-interface)
738 762
739 763
740 ;; Formatting options 764 ;; Formatting options
741 765
766 Heading emboldening is NOT standard `man' behaviour." 790 Heading emboldening is NOT standard `man' behaviour."
767 :type 'boolean 791 :type 'boolean
768 :group 'woman-formatting) 792 :group 'woman-formatting)
769 793
770 (defcustom woman-ignore t 794 (defcustom woman-ignore t
771 "*If non-nil then unrecognised requests are ignored. Default is t. 795 "*If non-nil then unrecognised requests etc. are ignored. Default is t.
772 This gives the standard ?roff behaviour. If nil then they are left in 796 This gives the standard ?roff behaviour. If nil then they are left in
773 the buffer, which may aid debugging." 797 the buffer, which may aid debugging."
774 :type 'boolean 798 :type 'boolean
775 :group 'woman-formatting) 799 :group 'woman-formatting)
776 800
777 (defcustom woman-preserve-ascii nil 801 (defcustom woman-preserve-ascii nil
778 "*If non-nil then preserve ASCII characters in the WoMan buffer. 802 "*If non-nil then preserve ASCII characters in the WoMan buffer.
779 Otherwise, non-ASCII characters (that display as ASCII) may remain. 803 Otherwise, non-ASCII characters (that display as ASCII) may remain.
780 This is irrelevant unless the buffer is to be saved to a file." 804 This is irrelevant unless the buffer is to be saved to a file."
781 :type 'boolean 805 :type 'boolean
806 :group 'woman-formatting)
807
808 (defcustom woman-emulation 'nroff
809 "*WoMan emulation, currently either nroff or troff. Default is nroff.
810 Troff emulation is experimental and largely untested.
811 \(Add groff later?)"
812 :type '(choice (const nroff) (const troff))
782 :group 'woman-formatting) 813 :group 'woman-formatting)
783 814
784 815
785 ;; Faces: 816 ;; Faces:
786 817
841 (interactive) 872 (interactive)
842 (set-face-foreground 'woman-italic-face "Black") 873 (set-face-foreground 'woman-italic-face "Black")
843 (set-face-foreground 'woman-bold-face "Black")) 874 (set-face-foreground 'woman-bold-face "Black"))
844 875
845 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 876 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
846 ;; Experimental symbol font support, initially only for MS-Windows. 877 ;; Experimental font support, initially only for MS-Windows.
847 (eval-when-compile 878 (defconst woman-font-support
848 (defvar woman-symbol-font) 879 (eq window-system 'w32) ; Support X later!
849 (defvar woman-use-symbols)) 880 "If non-nil then non-ASCII characters and symbol font supported.")
850 881
851 (when (and window-system (eq system-type 'windows-nt)) 882 (defun woman-select-symbol-fonts (fonts)
883 "Select symbol fonts from a list FONTS of font name strings."
884 (let (symbol-fonts)
885 ;; With NTEmacs 20.5, the PATTERN option to `x-list-fonts' does
886 ;; not seem to work and fonts may be repeated, so ...
887 (while fonts
888 (and (string-match "-Symbol-" (car fonts))
889 (not (member (car fonts) symbol-fonts))
890 (setq symbol-fonts (cons (car fonts) symbol-fonts)))
891 (setq fonts (cdr fonts)))
892 symbol-fonts))
893
894 (when woman-font-support
852 (make-face 'woman-symbol-face) 895 (make-face 'woman-symbol-face)
853 896
854 ;; Set up the symbol font only if `woman-use-symbols' is true, to 897 ;; Set the symbol font only if `woman-use-symbol-font' is true, to
855 ;; avoid unnecessarily upsetting the line spacing in NTEmacs 20.5! 898 ;; avoid unnecessarily upsetting the line spacing in NTEmacs 20.5!
856 899
857 (defcustom woman-use-symbols nil 900 (defcustom woman-use-extended-font t
858 "*If non-nil then may use symbol font and non-ASCII characters 901 "*If non-nil then may use non-ASCII characters from the default font."
859 from the default font for special characters. It is off by default,
860 mainly because it may increase the line spacing in NTEmacs 20.5."
861 :type 'boolean 902 :type 'boolean
862 :set #'(lambda (symbol value)
863 (set-default symbol value)
864 (if (and (boundp 'woman-symbol-font)
865 (stringp woman-symbol-font))
866 (set-face-font 'woman-symbol-face woman-symbol-font)))
867 :group 'woman-faces) 903 :group 'woman-faces)
868 904
905 (defcustom woman-use-symbol-font nil
906 "*If non-nil then may use the symbol font. It is off by default,
907 mainly because it may change the line spacing (in NTEmacs 20.5)."
908 :type 'boolean
909 :group 'woman-faces)
910
869 (defconst woman-symbol-font-list 911 (defconst woman-symbol-font-list
870 (let ((fonts (x-list-fonts "*" 'default)) 912 (or (woman-select-symbol-fonts (x-list-fonts "*" 'default))
871 symbol-fonts) 913 (woman-select-symbol-fonts (x-list-fonts "*")))
872 ;; With NTEmacs 20.5, the PATTERN option to `x-list-fonts' does 914 "Symbol font(s), preferably same size as default when WoMan was loaded.")
873 ;; not seem to work and fonts may be repeated, so ...
874 (while fonts
875 (and (string-match "-Symbol-" (car fonts))
876 (not (member (car fonts) symbol-fonts))
877 (setq symbol-fonts (cons (car fonts) symbol-fonts)))
878 (setq fonts (cdr fonts)))
879 symbol-fonts)
880 "Symbol fonts in the same size as the default font when WoMan was loaded.")
881 915
882 (defcustom woman-symbol-font (car woman-symbol-font-list) 916 (defcustom woman-symbol-font (car woman-symbol-font-list)
883 "*A string describing the symbol font to use for special characters. 917 "*A string describing the symbol font to use for special characters.
884 It should be compatible with, and the same size as, the default text font. 918 It should be compatible with, and the same size as, the default text font.
885 Under MS-Windows, the default is 919 Under MS-Windows, the default is
886 \"-*-Symbol-normal-r-*-*-*-*-96-96-p-*-ms-symbol\"." 920 \"-*-Symbol-normal-r-*-*-*-*-96-96-p-*-ms-symbol\"."
887 :type `(choice 921 :type `(choice
888 ,@(mapcar #'(lambda (x) (list 'const x)) 922 ,@(mapcar (lambda (x) (list 'const x))
889 woman-symbol-font-list) 923 woman-symbol-font-list)
890 string) 924 string)
891 :set #'(lambda (symbol value)
892 (set-default symbol value)
893 (if woman-use-symbols
894 (set-face-font 'woman-symbol-face value)))
895 :group 'woman-faces) 925 :group 'woman-faces)
896 926
897 ) 927 )
898 928
899 (defvar woman-use-symbols nil) ; for non windows-nt 929 ;; For non windows-nt ...
930 (defvar woman-use-extended-font nil)
931 (defvar woman-use-symbol-font nil)
932 (defvar woman-symbol-font nil)
900 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 933 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
901 934
902 935
903 ;;; Internal variables: 936 ;;; Internal variables:
904 937
944 (defvar woman-nospace nil 977 (defvar woman-nospace nil
945 "Current no-space mode: nil for normal spacing. 978 "Current no-space mode: nil for normal spacing.
946 Set by `.ns' request; reset by any output or `.rs' request") 979 Set by `.ns' request; reset by any output or `.rs' request")
947 980
948 (defsubst woman-reset-nospace () 981 (defsubst woman-reset-nospace ()
949 "Make woman-nospace be nil." 982 "Set `woman-nospace' to nil."
950 (setq woman-nospace nil)) 983 (setq woman-nospace nil))
951 984
952 (defconst woman-mode-line-format 985 (defconst woman-mode-line-format
953 ;; This is essentially the Man-mode format with page numbers removed 986 ;; This is essentially the Man-mode format with page numbers removed
954 ;; and line numbers added. (Online documents do not have pages, but 987 ;; and line numbers added. (Online documents do not have pages, but
968 ;; suppress breaks! 1001 ;; suppress breaks!
969 ;; Could end with "\\( +\\|$\\)" instead of " *" 1002 ;; Could end with "\\( +\\|$\\)" instead of " *"
970 "Regexp to match a ?roff request plus trailing white space.") 1003 "Regexp to match a ?roff request plus trailing white space.")
971 1004
972 (defvar woman-imenu-done nil 1005 (defvar woman-imenu-done nil
973 "Buffer-local: set to true if `woman-imenu' has been called.") 1006 "Buffer-local: set to true if function `woman-imenu' has been called.")
974 (make-variable-buffer-local 'woman-imenu-done) 1007 (make-variable-buffer-local 'woman-imenu-done)
975 1008
976 ;; From imenu.el -- needed when reformatting a file in its old buffer. 1009 ;; From imenu.el -- needed when reformatting a file in its old buffer.
977 ;; The latest buffer index used to update the menu bar menu. 1010 ;; The latest buffer index used to update the menu bar menu.
978 (eval-when-compile 1011 (eval-when-compile
979 (require 'imenu)) 1012 (require 'imenu))
980 (make-variable-buffer-local 'imenu--last-menubar-index-alist) 1013 (make-variable-buffer-local 'imenu--last-menubar-index-alist)
981 1014
982 (defvar woman-buffer-alist nil 1015 (defvar woman-buffer-alist nil
983 "An alist of WoMan buffers that are already decoded. 1016 "An alist representing WoMan buffers that are already decoded.
984 Each element is of the form (FILE-NAME BUFFER-NAME).") 1017 Each element is of the form (FILE-NAME . BUFFER-NAME).")
985 1018
986 (defvar woman-buffer-number 0 1019 (defvar woman-buffer-number 0
987 "Ordinal number of current buffer entry in `woman-buffer-alist'. 1020 "Ordinal number of current buffer entry in `woman-buffer-alist'.
988 The ordinal numbers start from 0.") 1021 The ordinal numbers start from 0.")
989 1022
1023 (defvar woman-if-conditions-true '(?n ?e ?o)
1024 "List of one-character built-in condition names that are true.
1025 Should include ?e, ?o (page even/odd) and either ?n (nroff) or ?t (troff).
1026 Default is '(?n ?e ?o). Set via `woman-emulation'.")
1027
990 1028
991 ;;; Specialized utility functions: 1029 ;;; Specialized utility functions:
992 1030
993 ;;; Fast deletion without saving on the kill ring (cf. simple.el): 1031 ;;; Fast deletion without saving on the kill ring (cf. simple.el):
994 1032
995 (defun woman-delete-line (&optional arg) 1033 (defun woman-delete-line (&optional arg)
996 "Delete the rest of the current line; if all-blank line, delete thru newline. 1034 "Delete rest of current line; if all blank then delete thru newline.
997 With a numeric argument ARG, delete that many lines from point. 1035 With a numeric argument ARG, delete that many lines from point.
998 Negative arguments delete lines backward." 1036 Negative arguments delete lines backward."
999 ;; This is a non-interactive version of kill-line in simple.el that 1037 ;; This is a non-interactive version of kill-line in simple.el that
1000 ;; deletes instead of killing and assumes kill-whole-line is nil, 1038 ;; deletes instead of killing and assumes kill-whole-line is nil,
1001 ;; which is essential! 1039 ;; which is essential!
1038 (defvar woman-topic-all-completions nil 1076 (defvar woman-topic-all-completions nil
1039 "Expanded topic alist cache. Resetting to nil forces update.") 1077 "Expanded topic alist cache. Resetting to nil forces update.")
1040 1078
1041 ;;;###autoload 1079 ;;;###autoload
1042 (defun woman (&optional topic re-cache) 1080 (defun woman (&optional topic re-cache)
1043 "Browse a UN*X man page for TOPIC WithOut using a `man' program. 1081 "Browse UN*X man page for TOPIC (Without using external Man program).
1044 The major browsing mode used is essentially the standard Man mode. 1082 The major browsing mode used is essentially the standard Man mode.
1045 Choose the filename for the man page using completion, based on the 1083 Choose the filename for the man page using completion, based on the
1046 topic selected from the directories specified in `woman-manpath' and 1084 topic selected from the directories specified in `woman-manpath' and
1047 `woman-path'. The directory expansions and topics are cached for 1085 `woman-path'. The directory expansions and topics are cached for
1048 speed, but a non-nil interactive argument forces the caches to be 1086 speed, but a non-nil interactive argument forces the caches to be
1049 updated (e.g. to re-interpret the current directory). 1087 updated (e.g. to re-interpret the current directory).
1050 1088
1051 Used non-interactively, arguments are optional: if they are given then 1089 Used non-interactively, arguments are optional: if given then TOPIC
1052 the argument TOPIC should be a topic string and the RE-CACHE may be 1090 should be a topic string and non-nil RE-CACHE forces re-caching."
1053 non-nil to force re-caching."
1054 (interactive (list nil current-prefix-arg)) 1091 (interactive (list nil current-prefix-arg))
1055 ;; The following test is for non-interactive calls via gnudoit etc. 1092 ;; The following test is for non-interactive calls via gnudoit etc.
1056 (if (or (interactive-p) (not (stringp topic)) (string-match "\\S " topic)) 1093 (if (or (interactive-p) (not (stringp topic)) (string-match "\\S " topic))
1057 (let ((file-name (woman-file-name topic re-cache))) 1094 (let ((file-name (woman-file-name topic re-cache)))
1058 (if file-name 1095 (if file-name
1063 ) 1100 )
1064 (message "WoMan Error: No topic specified in non-interactive call") 1101 (message "WoMan Error: No topic specified in non-interactive call")
1065 (ding)) 1102 (ding))
1066 ) 1103 )
1067 1104
1068 ;; The following allows to call WoMan via the standard Help menu 1105 ;; Allow WoMan to be called via the standard Help menu:
1069 ;; without the need to call it first via the keyboard:
1070
1071 ;; Repeated calls of `define-key-after' do not seem to matter!
1072 (define-key-after menu-bar-manuals-menu [woman] 1106 (define-key-after menu-bar-manuals-menu [woman]
1073 '(menu-item "Read Man Page (WoMan)..." woman 1107 '(menu-item "Read Man Page (WoMan)..." woman
1074 :help "Man-page documentation Without Man") t) 1108 :help "Man-page documentation Without Man") t)
1075 1109
1076 (defvar woman-cached-data nil 1110 (defvar woman-cached-data nil
1085 (mapcar 'substitute-in-file-name woman-manpath) 1119 (mapcar 'substitute-in-file-name woman-manpath)
1086 (mapcar 'substitute-in-file-name woman-path))) 1120 (mapcar 'substitute-in-file-name woman-path)))
1087 1121
1088 (defun woman-read-directory-cache () 1122 (defun woman-read-directory-cache ()
1089 "Load the directory and topic cache. 1123 "Load the directory and topic cache.
1090 The cache is loaded from the file named precisely as specified by the 1124 It is loaded from the file named by the variable `woman-cache-filename'.
1091 variable `woman-cache-filename'. 1125 Return t if the file exists, nil otherwise."
1092 Value is t if the file exists, nil otherwise."
1093 (and 1126 (and
1094 woman-cache-filename 1127 woman-cache-filename
1095 (load woman-cache-filename t nil t) ; file exists 1128 (load woman-cache-filename t nil t) ; file exists
1096 (equal woman-cached-data (woman-cached-data)))) ; cache valid 1129 (equal woman-cached-data (woman-cached-data)))) ; cache valid
1097 1130
1098 (defun woman-write-directory-cache () 1131 (defun woman-write-directory-cache ()
1099 "Save the directory and topic cache. 1132 "Save the directory and topic cache.
1100 The directory and topic cache is written to the file named precisely as 1133 It is saved to the file named by the variable `woman-cache-filename'."
1101 specified by the variable `woman-cache-filename'."
1102 (if woman-cache-filename 1134 (if woman-cache-filename
1103 (save-excursion ; to restore current buffer 1135 (save-excursion ; to restore current buffer
1104 ;; Make a temporary buffer; name starting with space "hides" it. 1136 ;; Make a temporary buffer; name starting with space "hides" it.
1105 (let ((standard-output 1137 (let ((standard-output
1106 (set-buffer (generate-new-buffer "WoMan tmp buffer"))) 1138 (set-buffer (generate-new-buffer "WoMan tmp buffer")))
1125 (defvar woman-topic-history nil "Topic read history.") 1157 (defvar woman-topic-history nil "Topic read history.")
1126 (defvar woman-file-history nil "File-name read history.") 1158 (defvar woman-file-history nil "File-name read history.")
1127 1159
1128 (defun woman-file-name (topic &optional re-cache) 1160 (defun woman-file-name (topic &optional re-cache)
1129 "Get the name of the UN*X man-page file describing a chosen TOPIC. 1161 "Get the name of the UN*X man-page file describing a chosen TOPIC.
1130 When called interactively, the word at point may be used as the topic 1162 When `woman' is called interactively, the word at point may be used as
1131 or initial topic suggestion, subject to the value of the user option 1163 the topic or initial topic suggestion, subject to the value of the
1132 `woman-topic-at-point'. 1164 user option `woman-topic-at-point'. Return nil if no file can be found.
1133 Optional argument RE-CACHE, if non-nil, forces the cache to be re-read. 1165 Optional argument RE-CACHE, if non-nil, forces the cache to be re-read."
1134 Value is nil if no file can be found."
1135 ;; Handle the caching of the directory and topic lists: 1166 ;; Handle the caching of the directory and topic lists:
1136 (if (and (not re-cache) 1167 (if (and (not re-cache)
1137 (or 1168 (or
1138 (and woman-expanded-directory-path woman-topic-all-completions) 1169 (and woman-expanded-directory-path woman-topic-all-completions)
1139 (woman-read-directory-cache))) 1170 (woman-read-directory-cache)))
1216 "Return t if DIR is readable, otherwise log a warning." 1247 "Return t if DIR is readable, otherwise log a warning."
1217 (or (file-readable-p dir) 1248 (or (file-readable-p dir)
1218 (WoMan-warn "Ignoring unreadable `manpath' directory tree `%s'!" dir))) 1249 (WoMan-warn "Ignoring unreadable `manpath' directory tree `%s'!" dir)))
1219 1250
1220 (defun woman-directory-files (head dir) 1251 (defun woman-directory-files (head dir)
1221 "Return a sorted list of files in directory HEAD matching the regexp in DIR. 1252 "Return a sorted list of files in directory HEAD matching regexp in DIR.
1222 Value is a sorted list of the absolute pathnames of all the files in 1253 Value is a sorted list of the absolute pathnames of all the files in
1223 directory HEAD, or the current directory if HEAD is nil, that match the 1254 directory HEAD, or the current directory if HEAD is nil, that match the
1224 regexp that is the final component of DIR. Log a warning if list is empty." 1255 regexp that is the final component of DIR. Log a warning if list is empty."
1225 (or (directory-files 1256 (or (directory-files
1226 (or head (directory-file-name default-directory)) ; was "." 1257 (or head (directory-file-name default-directory)) ; was "."
1232 "Return t if DIR is accessible, otherwise log a warning." 1263 "Return t if DIR is accessible, otherwise log a warning."
1233 (or (file-accessible-directory-p dir) 1264 (or (file-accessible-directory-p dir)
1234 (WoMan-warn "Ignoring inaccessible `man-page' directory `%s'!" dir))) 1265 (WoMan-warn "Ignoring inaccessible `man-page' directory `%s'!" dir)))
1235 1266
1236 (defun woman-expand-directory-path (woman-manpath woman-path) 1267 (defun woman-expand-directory-path (woman-manpath woman-path)
1237 "Expand manual directories in WOMAN-MANPATH and WOMAN-PATH. 1268 "Expand the manual directories in WOMAN-MANPATH and WOMAN-PATH.
1238 WOMAN-MANPATH should be the list of the general manual directories, while 1269 WOMAN-MANPATH should be a list of general manual directories, while
1239 WOMAN-PATH should be the list of specific manual directory regexps. 1270 WOMAN-PATH should be a list of specific manual directory regexps.
1240 Ignore any paths that are unreadable or not directories." 1271 Ignore any paths that are unreadable or not directories."
1241 ;; Allow each path to be a single string or a list of strings: 1272 ;; Allow each path to be a single string or a list of strings:
1242 (if (not (listp woman-manpath)) (setq woman-manpath (list woman-manpath))) 1273 (if (not (listp woman-manpath)) (setq woman-manpath (list woman-manpath)))
1243 (if (not (listp woman-path)) (setq woman-path (list woman-path))) 1274 (if (not (listp woman-path)) (setq woman-path (list woman-path)))
1244 (let (dir head dirs) 1275 (let (dir head dirs)
1267 ;; was "." -- at head of list for later filtering 1298 ;; was "." -- at head of list for later filtering
1268 ))) 1299 )))
1269 (woman-select 'woman-file-accessible-directory-p dirs))) 1300 (woman-select 'woman-file-accessible-directory-p dirs)))
1270 1301
1271 (defun woman-canonicalize-dir (dir) 1302 (defun woman-canonicalize-dir (dir)
1272 "Canonicalize a directory name DIR. 1303 "Canonicalize the directory name DIR.
1273 Any UN*X-style environment variables are evaluated first." 1304 Any UN*X-style environment variables are evaluated first."
1274 (setq dir (expand-file-name (substitute-in-file-name dir))) 1305 (setq dir (expand-file-name (substitute-in-file-name dir)))
1275 ;; A path that ends with / matches all directories in it, 1306 ;; A path that ends with / matches all directories in it,
1276 ;; including `.' and `..', so remove any trailing / !!! 1307 ;; including `.' and `..', so remove any trailing / !!!
1277 (if (string= (substring dir -1) "/") 1308 (if (string= (substring dir -1) "/")
1278 (setq dir (substring dir 0 -1))) 1309 (setq dir (substring dir 0 -1)))
1279 (if (memq system-type '(windows-nt ms-dos)) ; what else? 1310 (if (memq system-type '(windows-nt ms-dos)) ; what else?
1280 ;; Match capitalization used by `file-name-directory': 1311 ;; Match capitalization used by `file-name-directory':
1281 (setq dir (concat (file-name-directory dir) 1312 (setq dir (concat (file-name-directory dir)
1282 (file-name-nondirectory dir)))) 1313 (file-name-nondirectory dir))))
1283 dir) 1314 dir)
1284 1315
1285 (defsubst woman-not-member (dir path) 1316 (defsubst woman-not-member (dir path)
1286 "Return true if DIR is not a member of the list PATH. 1317 "Return t if DIR is not a member of the list PATH, nil otherwise.
1287 If DIR is `.' it is first replaced by the current directory." 1318 If DIR is `.' it is first replaced by the current directory."
1288 (not (member dir path))) 1319 (not (member dir path)))
1289 1320
1290 (defun woman-topic-all-completions (path) 1321 (defun woman-topic-all-completions (path)
1291 "Return an alist of the man files in all man directories in the list PATH. 1322 "Return an alist of the man files in all man directories in the list PATH.
1313 (setcdr (nthcdr (1- n) args) nil)) 1344 (setcdr (nthcdr (1- n) args) nil))
1314 args) 1345 args)
1315 1346
1316 (defun woman-topic-all-completions-1 (dir path-index) 1347 (defun woman-topic-all-completions-1 (dir path-index)
1317 "Return an alist of the man files in directory DIR with index PATH-INDEX. 1348 "Return an alist of the man files in directory DIR with index PATH-INDEX.
1318 The cdr of each alist element is the path-index / filename." 1349 The `cdr' of each alist element is the path-index / filename."
1350 ;; *** NEED case-fold-search t HERE ???
1319 (let ((old (directory-files dir nil woman-file-regexp)) 1351 (let ((old (directory-files dir nil woman-file-regexp))
1320 new file) 1352 new file)
1321 ;; Convert list to alist of non-directory files: 1353 ;; Convert list to alist of non-directory files:
1322 (while old 1354 (while old
1323 (setq file (car old) 1355 (setq file (car old)
1336 new)))) 1368 new))))
1337 new)) 1369 new))
1338 1370
1339 (defun woman-topic-all-completions-merge (alist) 1371 (defun woman-topic-all-completions-merge (alist)
1340 "Merge the alist ALIST so that the keys are unique. 1372 "Merge the alist ALIST so that the keys are unique.
1341 Also, make each path-info component into a list. 1373 Also make each path-info component into a list.
1342 \(Note that this function changes the value of ALIST.)" 1374 \(Note that this function changes the value of ALIST.)"
1343 ;; Intended to be fast by avoiding recursion and list copying. 1375 ;; Intended to be fast by avoiding recursion and list copying.
1344 (if (> woman-cache-level 1) 1376 (if (> woman-cache-level 1)
1345 (let ((newalist alist)) 1377 (let ((newalist alist))
1346 (while newalist 1378 (while newalist
1485 ;;;###autoload 1517 ;;;###autoload
1486 (defun woman-find-file (file-name &optional reformat) 1518 (defun woman-find-file (file-name &optional reformat)
1487 "Find, decode and browse a specific UN*X man-page source file FILE-NAME. 1519 "Find, decode and browse a specific UN*X man-page source file FILE-NAME.
1488 Use existing buffer if possible; reformat only if prefix arg given. 1520 Use existing buffer if possible; reformat only if prefix arg given.
1489 When called interactively, optional argument REFORMAT forces reformatting 1521 When called interactively, optional argument REFORMAT forces reformatting
1490 of existing WoMan buffers formatted earlier. 1522 of an existing WoMan buffer formatted earlier.
1491 No external programs are used, except that `gunzip' will be used to 1523 No external programs are used, except that `gunzip' will be used to
1492 decompress the file if appropriate. See the documentation for the 1524 decompress the file if appropriate. See the documentation for the
1493 `woman' command for further details." 1525 `woman' command for further details."
1494 (interactive "fBrowse UN*X manual file: \nP") 1526 (interactive "fBrowse UN*X manual file: \nP")
1495 (setq woman-last-file-name 1527 (setq woman-last-file-name
1529 (substring bufname (1+ dot)) " " 1561 (substring bufname (1+ dot)) " "
1530 (substring bufname 0 dot)))) 1562 (substring bufname 0 dot))))
1531 (generate-new-buffer-name ; ensure uniqueness 1563 (generate-new-buffer-name ; ensure uniqueness
1532 (concat "*WoMan " bufname "*")))) 1564 (concat "*WoMan " bufname "*"))))
1533 1565
1566 (defvar woman-frame nil
1567 "Dedicated frame used for displaying WoMan windows.")
1568
1534 (defun woman-really-find-file (filename compressed bufname) 1569 (defun woman-really-find-file (filename compressed bufname)
1535 "Find, decompress, and decode a UN*X man page FILENAME. 1570 "Find, decompress, and decode a UN*X man page FILENAME.
1536 If COMPRESSED is non-nil, turn on `auto-compression-mode' to 1571 If COMPRESSED is non-nil, turn on auto-compression mode to decompress
1537 decompress the file if necessary. Set buffer name and major mode. 1572 the file if necessary. Set buffer name BUFNAME and major mode.
1538 Do not call directly!" 1573 Do not call directly!"
1539 (let ((WoMan-current-file filename)) ; used for message logging 1574 (let ((WoMan-current-file filename)) ; used for message logging
1575 (if woman-use-own-frame
1576 (select-frame
1577 (or (and (frame-live-p woman-frame) woman-frame)
1578 (setq woman-frame (make-frame)))))
1540 (switch-to-buffer (get-buffer-create bufname)) 1579 (switch-to-buffer (get-buffer-create bufname))
1541 (buffer-disable-undo) 1580 (buffer-disable-undo)
1542 (setq buffer-read-only nil) 1581 (setq buffer-read-only nil)
1543 (erase-buffer) ; NEEDED for reformat 1582 (erase-buffer) ; NEEDED for reformat
1544 (woman-insert-file-contents filename compressed) 1583 (woman-insert-file-contents filename compressed)
1613 ) 1652 )
1614 1653
1615 (defun woman-insert-file-contents (filename compressed) 1654 (defun woman-insert-file-contents (filename compressed)
1616 "Insert file FILENAME into the current buffer. 1655 "Insert file FILENAME into the current buffer.
1617 If COMPRESSED is t, or is non-nil and the filename implies compression, 1656 If COMPRESSED is t, or is non-nil and the filename implies compression,
1618 turn on `auto-compression-mode' to decompress the file. 1657 then turn on auto-compression mode to decompress the file.
1619 Leave point at end of new text. Return length of inserted text." 1658 Leave point at end of new text. Return length of inserted text."
1620 ;; Leaves point at end of inserted text in GNU Emacs 20.3, but at 1659 ;; Leaves point at end of inserted text in GNU Emacs 20.3, but at
1621 ;; start in 19.34! 1660 ;; start in 19.34!
1622 (save-excursion 1661 (save-excursion
1623 (let ((case-fold-search t)) 1662 (let ((case-fold-search t))
1689 ["Kill WoMan Buffer" Man-kill t] 1728 ["Kill WoMan Buffer" Man-kill t]
1690 "--" 1729 "--"
1691 ;; ["Toggle Fill Frame Width" woman-toggle-fill-frame t] 1730 ;; ["Toggle Fill Frame Width" woman-toggle-fill-frame t]
1692 ["Use Full Frame Width" woman-toggle-fill-frame 1731 ["Use Full Frame Width" woman-toggle-fill-frame
1693 :active t :style toggle :selected woman-fill-frame] 1732 :active t :style toggle :selected woman-fill-frame]
1694 ["Reformat Last File" woman-reformat-last-file t] 1733 ["Reformat Last Man Page" woman-reformat-last-file t]
1695 ["Use Coloured Main Faces" woman-colour-faces t] 1734 ["Use Coloured Main Faces" woman-colour-faces t]
1696 ["Use Black Main Faces" woman-black-faces t] 1735 ["Use Black Main Faces" woman-black-faces t]
1697 ["Make Contents Menu" (woman-imenu t) (not woman-imenu-done)] 1736 ["Make Contents Menu" (woman-imenu t) (not woman-imenu-done)]
1698 "--" 1737 "--"
1699 ["Describe (Wo)Man Mode" describe-mode t] 1738 ["Describe (Wo)Man Mode" describe-mode t]
1700 ["Mini Help" woman-mini-help t] 1739 ["Mini Help" woman-mini-help t]
1701 ,@(if (fboundp 'customize-group) 1740 ,@(if (fboundp 'customize-group)
1702 '(["Customize..." (customize-group 'woman) t])) 1741 '(["Customize..." (customize-group 'woman) t]))
1703 ["Show Version" (message "WoMan %s" woman-version) t] 1742 ["Show Version" (message "WoMan %s" woman-version) t]
1743 "--"
1744 ("Advanced"
1745 ["View Source" (view-file woman-last-file-name) woman-last-file-name]
1746 ["Show Log" (switch-to-buffer-other-window "*WoMan-Log*" t) t]
1747 ["Extended Font" woman-toggle-use-extended-font
1748 :included woman-font-support
1749 :active t :style toggle :selected woman-use-extended-font]
1750 ["Symbol Font" woman-toggle-use-symbol-font
1751 :included woman-font-support
1752 :active t :style toggle :selected woman-use-symbol-font]
1753 ["Font Map" woman-display-extended-fonts
1754 :included woman-font-support
1755 :active woman-use-symbol-font]
1756 "--"
1757 "Emulation"
1758 ["nroff" (woman-reset-emulation 'nroff)
1759 :active t :style radio :selected (eq woman-emulation 'nroff)]
1760 ["troff" (woman-reset-emulation 'troff)
1761 :active t :style radio :selected (eq woman-emulation 'troff)]
1762 )
1704 )) 1763 ))
1764
1765 (defun woman-toggle-use-extended-font ()
1766 "Toggle `woman-use-extended-font' and reformat, for menu use."
1767 (interactive)
1768 (setq woman-use-extended-font (not woman-use-extended-font))
1769 (woman-reformat-last-file))
1770
1771 (defun woman-toggle-use-symbol-font ()
1772 "Toggle `woman-use-symbol-font' and reformat, for menu use."
1773 (interactive)
1774 (setq woman-use-symbol-font (not woman-use-symbol-font))
1775 (woman-reformat-last-file))
1776
1777 (defun woman-reset-emulation (value)
1778 "Reset `woman-emulation' to VALUE and reformat, for menu use."
1779 (interactive)
1780 (setq woman-emulation value)
1781 (woman-reformat-last-file))
1705 1782
1706 (defun woman-mode () 1783 (defun woman-mode ()
1707 "Turn on (most of) Man mode to browse a buffer formatted by WoMan. 1784 "Turn on (most of) Man mode to browse a buffer formatted by WoMan.
1708 WoMan is an ELisp emulation of much of the functionality of the Emacs 1785 WoMan is an ELisp emulation of much of the functionality of the Emacs
1709 `man' command running the standard UN*X man and ?roff programs. 1786 `man' command running the standard UN*X man and ?roff programs.
1778 (let ((message 1855 (let ((message
1779 (let ((standard-output (get-buffer-create "*Apropos*"))) 1856 (let ((standard-output (get-buffer-create "*Apropos*")))
1780 (print-help-return-message 'identity)))) 1857 (print-help-return-message 'identity))))
1781 (setq apropos-accumulator 1858 (setq apropos-accumulator
1782 (apropos-internal "woman" 1859 (apropos-internal "woman"
1783 #'(lambda (symbol) 1860 (lambda (symbol)
1784 (or (commandp symbol) 1861 (or (commandp symbol)
1785 (user-variable-p symbol))))) 1862 (user-variable-p symbol)))))
1786 ;; Filter out any inhibited symbols: 1863 ;; Filter out any inhibited symbols:
1787 (let ((tem apropos-accumulator)) 1864 (let ((tem apropos-accumulator))
1788 (while tem 1865 (while tem
1789 (if (get (car tem) 'apropos-inhibit) 1866 (if (get (car tem) 'apropos-inhibit)
1790 (setq apropos-accumulator (delq (car tem) apropos-accumulator))) 1867 (setq apropos-accumulator (delq (car tem) apropos-accumulator)))
1889 () 1966 ()
1890 (WoMan-next-manpage))) 1967 (WoMan-next-manpage)))
1891 1968
1892 (defun WoMan-find-buffer () 1969 (defun WoMan-find-buffer ()
1893 "Switch to buffer corresponding to `woman-buffer-number' and return it. 1970 "Switch to buffer corresponding to `woman-buffer-number' and return it.
1894 If such a buffer doesn't exist, remove its association from the alist in 1971 If such a buffer does not exist then remove its association from the
1895 `woman-buffer-alist' and return nil." 1972 alist in `woman-buffer-alist' and return nil."
1896 (if (zerop woman-buffer-number) 1973 (if (zerop woman-buffer-number)
1897 (let ((buffer (get-buffer (cdr (car woman-buffer-alist))))) 1974 (let ((buffer (get-buffer (cdr (car woman-buffer-alist)))))
1898 (if buffer 1975 (if buffer
1899 (switch-to-buffer buffer) 1976 (switch-to-buffer buffer)
1900 ;; Delete alist element: 1977 ;; Delete alist element:
2059 woman-RS-prevailing-indent nil 2136 woman-RS-prevailing-indent nil
2060 woman-adjust woman-adjust-both 2137 woman-adjust woman-adjust-both
2061 woman-justify (nth woman-adjust woman-justify-list) 2138 woman-justify (nth woman-adjust woman-justify-list)
2062 woman-nofill nil) 2139 woman-nofill nil)
2063 2140
2141 (setq woman-if-conditions-true
2142 (cons (string-to-char (symbol-name woman-emulation)) '(?e ?o)))
2143
2064 ;; Prepare non-underlined versions of underlined faces: 2144 ;; Prepare non-underlined versions of underlined faces:
2065 (woman-non-underline-faces) 2145 (woman-non-underline-faces)
2146 ;; Set font of `woman-symbol-face' to `woman-symbol-font' if
2147 ;; `woman-symbol-font' is well defined.
2148 (and woman-use-symbol-font
2149 (stringp woman-symbol-font)
2150 (set-face-font 'woman-symbol-face woman-symbol-font
2151 (and (frame-live-p woman-frame) woman-frame)))
2066 2152
2067 ;; Set syntax and display tables: 2153 ;; Set syntax and display tables:
2068 (set-syntax-table woman-syntax-table) 2154 (set-syntax-table woman-syntax-table)
2069 (woman-set-buffer-display-table) 2155 (woman-set-buffer-display-table)
2070 2156
2215 2301
2216 ;; Must return the new end of file if used in format-alist. 2302 ;; Must return the new end of file if used in format-alist.
2217 (point-max))) 2303 (point-max)))
2218 2304
2219 (defun woman-horizontal-escapes (to) 2305 (defun woman-horizontal-escapes (to)
2220 "\\h'+/-N' local horizontal motion, preserving `point'. 2306 "Process \\h'+/-N' local horizontal motion escapes upto TO.
2221 Argument TO is the target of the motion. 2307 Implements arbitrary forward and non-overlapping backward motion.
2222 Implement arbitrary forward and non-overlapping backward motion." 2308 Preserves location of `point'."
2223 ;; Moved from `woman-decode-region' for version 0.50. 2309 ;; Moved from `woman-decode-region' for version 0.50.
2224 ;; N may include width escape \w'...' (but may already be processed! 2310 ;; N may include width escape \w'...' (but may already be processed!
2225 (let ((from (point))) 2311 (let ((from (point)))
2226 (while (re-search-forward 2312 (while (re-search-forward
2227 ;; Delimiter can be a special char escape sequence \(.. or 2313 ;; Delimiter can be a special char escape sequence \(.. or
2263 )) 2349 ))
2264 (goto-char from))) 2350 (goto-char from)))
2265 2351
2266 2352
2267 2353
2268 ;;; Process ignore requests (.ig), conditionals (.if etc.), 2354 ;; Process ignore requests (.ig), conditionals (.if etc.),
2269 ;;; source-switch (.so), macro definitions (.de etc.) and macro 2355 ;; source-switch (.so), macro definitions (.de etc.) and macro
2270 ;;; expansions. 2356 ;; expansions.
2271 2357
2272 (defvar woman0-if-to) ; marker bound in woman0-roff-buffer 2358 (defvar woman0-if-to) ; marker bound in woman0-roff-buffer
2273 (defvar woman0-macro-alist) ; bound in woman0-roff-buffer 2359 (defvar woman0-macro-alist) ; bound in woman0-roff-buffer
2274 (defvar woman0-search-regex) ; bound in woman0-roff-buffer 2360 (defvar woman0-search-regex) ; bound in woman0-roff-buffer
2275 (defvar woman0-search-regex-start ; bound in woman0-roff-buffer 2361 (defvar woman0-search-regex-start ; bound in woman0-roff-buffer
2279 ;; Alternatively, force maximal match (Posix?) 2365 ;; Alternatively, force maximal match (Posix?)
2280 2366
2281 (defvar woman0-rename-alist) ; bound in woman0-roff-buffer 2367 (defvar woman0-rename-alist) ; bound in woman0-roff-buffer
2282 2368
2283 (defun woman0-roff-buffer (from) 2369 (defun woman0-roff-buffer (from)
2284 "Process conditional-type requests and user-defined macros, starting at FROM. 2370 "Process conditional-type requests and user-defined macros.
2285 Re-scan new text as appropriate." 2371 Start at FROM and re-scan new text as appropriate."
2286 (goto-char from) 2372 (goto-char from)
2287 (let ((woman0-if-to (make-marker)) 2373 (let ((woman0-if-to (make-marker))
2288 request woman0-macro-alist 2374 request woman0-macro-alist
2289 (woman0-search-regex-start woman0-search-regex-start) 2375 (woman0-search-regex-start woman0-search-regex-start)
2290 (woman0-search-regex 2376 (woman0-search-regex
2347 (set-marker woman0-if-to 2433 (set-marker woman0-if-to
2348 (save-excursion (skip-syntax-forward "^ ") (point))) 2434 (save-excursion (skip-syntax-forward "^ ") (point)))
2349 ;; Process condition: 2435 ;; Process condition:
2350 (if (setq negated (= (following-char) ?!)) (delete-char 1)) 2436 (if (setq negated (= (following-char) ?!)) (delete-char 1))
2351 (cond 2437 (cond
2352 ((looking-at "[no]") (setq c t)) ; accept n(roff) and o(dd page) 2438 ;; ((looking-at "[no]") (setq c t)) ; accept n(roff) and o(dd page)
2353 ((looking-at "[te]") (setq c nil)) ; reject t(roff) and e(ven page) 2439 ;; ((looking-at "[te]") (setq c nil)) ; reject t(roff) and e(ven page)
2440 ((looking-at "[ntoe]")
2441 (setq c (memq (following-char) woman-if-conditions-true)))
2354 ;; Unrecognised letter so reject: 2442 ;; Unrecognised letter so reject:
2355 ((looking-at "[A-Za-z]") (setq c nil) 2443 ((looking-at "[A-Za-z]") (setq c nil)
2356 (WoMan-warn "%s %s -- unrecognised condition name rejected!" 2444 (WoMan-warn "%s %s -- unrecognised condition name rejected!"
2357 request (match-string 0))) 2445 request (match-string 0)))
2358 ;; Accept strings if identical: 2446 ;; Accept strings if identical:
2382 (woman-if-ignore woman0-if-to request) ; ERROR! 2470 (woman-if-ignore woman0-if-to request) ; ERROR!
2383 (woman-if-body request woman0-if-to (eq c negated))) 2471 (woman-if-body request woman0-if-to (eq c negated)))
2384 )) 2472 ))
2385 2473
2386 (defun woman-if-body (request to delete) ; should be reversed as `accept'? 2474 (defun woman-if-body (request to delete) ; should be reversed as `accept'?
2387 "Process if-body, including \\{ ... \\}, deleting it if TO is non-nil. 2475 "Process if-body, including \\{ ... \\}.
2388 REQUEST is the invoking directive. 2476 REQUEST is the invoking directive without the leading dot.
2389 If DELETE is non-nil, delete from point." 2477 If TO is non-nil then delete the if-body.
2478 If DELETE is non-nil then delete from point."
2390 ;; Assume concealed newlines already processed. 2479 ;; Assume concealed newlines already processed.
2391 (let ((from (point))) 2480 (let ((from (point)))
2392 (if to (delete-region (point) to)) 2481 (if to (delete-region (point) to))
2393 (delete-horizontal-space) 2482 (delete-horizontal-space)
2394 (cond (;;(looking-at "[^{\n]*\\\\{\\s *") ; multi-line 2483 (cond (;;(looking-at "[^{\n]*\\\\{\\s *") ; multi-line
2440 (skip-chars-forward "^ \t") 2529 (skip-chars-forward "^ \t")
2441 (if (looking-at "[ \t]*\\{") (search-forward "\\}")) 2530 (if (looking-at "[ \t]*\\{") (search-forward "\\}"))
2442 (forward-line 1)))) 2531 (forward-line 1))))
2443 2532
2444 (defun woman-if-ignore (to request) 2533 (defun woman-if-ignore (to request)
2445 "Ignore an if request REQUEST at TO and warn about that." 2534 "Ignore but warn about an if request ending at TO, named REQUEST."
2446 (WoMan-warn-ignored request "ignored -- condition not handled!") 2535 (WoMan-warn-ignored request "ignored -- condition not handled!")
2447 (if woman-ignore 2536 (if woman-ignore
2448 (woman-if-body request to t) 2537 (woman-if-body request to t)
2449 ;; Ignore -- leave in buffer 2538 ;; Ignore -- leave in buffer
2450 ;; This does not work too well, but it's only for debugging! 2539 ;; This does not work too well, but it's only for debugging!
2523 (defconst woman-unescape-regex 2612 (defconst woman-unescape-regex
2524 (concat woman-escaped-escape-string 2613 (concat woman-escaped-escape-string
2525 "\\(" woman-escaped-escape-string "\\)?")) 2614 "\\(" woman-escaped-escape-string "\\)?"))
2526 2615
2527 (defsubst woman-unescape (macro) 2616 (defsubst woman-unescape (macro)
2528 "Replace escaped sequences in body of MACRO. 2617 "Replace escape sequences in the body of MACRO.
2529 Replaces || by |, but | by \, where | denotes the internal escape." 2618 Replaces || by |, but | by \, where | denotes the internal escape."
2530 (let (start) 2619 (let (start)
2531 (while (setq start (string-match woman-unescape-regex macro start)) 2620 (while (setq start (string-match woman-unescape-regex macro start))
2532 (setq macro 2621 (setq macro
2533 (if (match-string 1 macro) 2622 (if (match-string 1 macro)
2577 )) 2666 ))
2578 (beginning-of-line) ; delete .de/am line 2667 (beginning-of-line) ; delete .de/am line
2579 (woman-delete-line 1)) 2668 (woman-delete-line 1))
2580 2669
2581 (defun woman0-macro (request) 2670 (defun woman0-macro (request)
2582 "Process macro call like the named REQUEST." 2671 "Process the macro call named REQUEST."
2583 ;; Leaves point at start of new text. 2672 ;; Leaves point at start of new text.
2584 (let ((macro (assoc request woman0-macro-alist))) 2673 (let ((macro (assoc request woman0-macro-alist)))
2585 (if macro 2674 (if macro
2586 (woman-interpolate-macro (cdr macro)) 2675 (woman-interpolate-macro (cdr macro))
2587 ;; SHOULD DELETE THE UNINTERPRETED REQUEST!!!!! 2676 ;; SHOULD DELETE THE UNINTERPRETED REQUEST!!!!!
2588 ;; Output this message once only per call (cf. strings)? 2677 ;; Output this message once only per call (cf. strings)?
2589 (WoMan-warn "Undefined macro %s not interpolated!" request)))) 2678 (WoMan-warn "Undefined macro %s not interpolated!" request))))
2590 2679
2591 (defun woman-interpolate-macro (macro) 2680 (defun woman-interpolate-macro (macro)
2592 "Interpolate (.de) or append (.am) a expansion of MACRO into the buffer." 2681 "Interpolate (.de) or append (.am) expansion of MACRO into the buffer."
2593 ;; Could make this more efficient by checking which arguments are 2682 ;; Could make this more efficient by checking which arguments are
2594 ;; actually used in the expansion! 2683 ;; actually used in the expansion!
2595 (skip-chars-forward " \t") 2684 (skip-chars-forward " \t")
2596 ;; Process arguments: 2685 ;; Process arguments:
2597 (let ((argno 0) (append (car macro)) 2686 (let ((argno 0) (append (car macro))
2631 2720
2632 2721
2633 ;;; Process strings: 2722 ;;; Process strings:
2634 2723
2635 (defun woman-strings (&optional to) 2724 (defun woman-strings (&optional to)
2636 "Process ?roff strings: defined/updated by `.ds xx string' requests. 2725 "Process ?roff string requests and escape sequences up to buffer position TO.
2637 Interpolate by `\*x' and `\*(xx' escapes. 2726 Strings are defined/updated by `.ds xx string' requests and
2638 Optional argument TO specifies where in the buffer does the request end." 2727 interpolated by `\*x' and `\*(xx' escapes."
2639 ;; Add support for .as and .rm? 2728 ;; Add support for .as and .rm?
2640 (while 2729 (while
2641 ;; Find .ds requests and \* escapes: 2730 ;; Find .ds requests and \* escapes:
2642 (re-search-forward "\\(^[.'][ \t]*ds\\)\\|\\\\\\*" to t) 2731 (re-search-forward "\\(^[.'][ \t]*ds\\)\\|\\\\\\*" to t)
2643 (cond ((match-string 1) ; .ds 2732 (cond ((match-string 1) ; .ds
2737 i.e. omitted, to indicate use of the default font. 2826 i.e. omitted, to indicate use of the default font.
2738 Any element may be nil. Avoid control character codes (0 to \\37, \\180 2827 Any element may be nil. Avoid control character codes (0 to \\37, \\180
2739 to \\237) in `extended-font-string' for now, since they can be 2828 to \\237) in `extended-font-string' for now, since they can be
2740 displayed only with a modified display table. 2829 displayed only with a modified display table.
2741 2830
2742 Use the Emacs command `woman-display-extended-fonts' or a character 2831 Use the WoMan command `woman-display-extended-fonts' or a character
2743 map accessory to help construct this alist.") 2832 map accessory to help construct this alist.")
2744 2833
2834 (defsubst woman-replace-match (newtext &optional face)
2835 "Replace text matched by last search with NEWTEXT and return t.
2836 Set NEWTEXT in face FACE if specified."
2837 (woman-delete-match 0)
2838 (insert-before-markers newtext)
2839 (if face (put-text-property (1- (point)) (point)
2840 'face 'woman-symbol-face))
2841 t)
2842
2745 (defun woman-special-characters (to) 2843 (defun woman-special-characters (to)
2746 "Process special character escapes \(xx up to buffer position TO." 2844 "Process special character escapes \(xx up to buffer position TO.
2747 ;; Must be done AFTER translation, which may use special chars. 2845 \(This must be done AFTER translation, which may use special characters.)"
2748 (while (re-search-forward "\\\\(\\(..\\)" to t) 2846 (while (re-search-forward "\\\\(\\(..\\)" to t)
2749 (let ((replacement 2847 (let ((replacement
2750 (assoc (match-string-no-properties 1) woman-special-characters))) 2848 (assoc (match-string-no-properties 1) woman-special-characters)))
2751 (if (and 2849 (if (and
2752 replacement 2850 replacement
2753 (cond ((and woman-use-symbols (cddr replacement)) 2851 (cond ((and (cddr replacement)
2754 ; use extended font 2852 (if (nthcdr 3 replacement)
2755 (woman-delete-match 0) 2853 ;; Need symbol font:
2756 (insert-before-markers (nth 2 replacement)) 2854 (if woman-use-symbol-font
2757 (if (nthcdr 3 replacement) ; use woman-symbol-face 2855 (woman-replace-match (nth 2 replacement)
2758 (put-text-property (1- (point)) (point) 2856 'woman-symbol-face))
2759 'face 'woman-symbol-face)) 2857 ;; Need extended font:
2760 t) 2858 (if woman-use-extended-font
2859 (woman-replace-match (nth 2 replacement))))))
2761 ((cadr replacement) ; Use ASCII simulation 2860 ((cadr replacement) ; Use ASCII simulation
2762 (woman-delete-match 0) 2861 (woman-replace-match (cadr replacement)))))
2763 (insert-before-markers (cadr replacement))
2764 t)))
2765 () 2862 ()
2766 (WoMan-warn "Special character \\(%s not interpolated!" 2863 (WoMan-warn "Special character \\(%s not interpolated!"
2767 (match-string-no-properties 1)) 2864 (match-string-no-properties 1))
2768 (if woman-ignore (woman-delete-match 0)))) 2865 (if woman-ignore (woman-delete-match 0))))
2769 )) 2866 ))
2770 2867
2771 (defun woman-display-extended-fonts () 2868 (defun woman-display-extended-fonts ()
2772 "Display glyphs of graphic charactes and their octal codes. 2869 "Display table of glyphs of graphic characters and their octal codes.
2773 All the characters in the ranges [32..127] and [160..255] are displayed 2870 All the octal codes in the ranges [32..127] and [160..255] are displayed
2774 together with the corresponding glyphs from the default and symbol fonts. 2871 together with the corresponding glyphs from the default and symbol fonts.
2775 Useful for constructing the `woman-special-characters' alist." 2872 Useful for constructing the alist variable `woman-special-characters'."
2776 (interactive) 2873 (interactive)
2777 (with-output-to-temp-buffer "*WoMan Extended Font Map*" 2874 (with-output-to-temp-buffer "*WoMan Extended Font Map*"
2778 (save-excursion 2875 (save-excursion
2779 (set-buffer standard-output) 2876 (set-buffer standard-output)
2780 (let ((i 32)) 2877 (let ((i 32))
2857 ".I -- Set words of current line in italic font." 2954 ".I -- Set words of current line in italic font."
2858 (woman1-B-or-I ".ft I\n")) 2955 (woman1-B-or-I ".ft I\n"))
2859 2956
2860 (defun woman1-B-or-I (B-or-I) 2957 (defun woman1-B-or-I (B-or-I)
2861 ".B/I -- Set words of current line in bold/italic font. 2958 ".B/I -- Set words of current line in bold/italic font.
2862 B-OR-I is the invoking directive." 2959 B-OR-I is the appropriate complete control line."
2863 ;; Should NOT concatenate the arguments! 2960 ;; Should NOT concatenate the arguments!
2864 (insert B-or-I) ; because it might be a control line 2961 (insert B-or-I) ; because it might be a control line
2865 ;; Return to bol to process .SM/.B, .B/.if etc. 2962 ;; Return to bol to process .SM/.B, .B/.if etc.
2866 ;; or start of first arg to hide leading control char. 2963 ;; or start of first arg to hide leading control char.
2867 (save-excursion 2964 (save-excursion
2876 ".SM -- Set the current line in small font, i.e. IGNORE!" 2973 ".SM -- Set the current line in small font, i.e. IGNORE!"
2877 nil) 2974 nil)
2878 2975
2879 (defalias 'woman1-SB 'woman1-B) 2976 (defalias 'woman1-SB 'woman1-B)
2880 ;; .SB -- Set the current line in small bold font, i.e. just embolden! 2977 ;; .SB -- Set the current line in small bold font, i.e. just embolden!
2881 ;; (This is what c:/usr/local/share/groff/tmac/tmac.an does. The 2978 ;; (This is what /usr/local/share/groff/tmac/tmac.an does. The
2882 ;; Linux man.7 is wrong about this!) 2979 ;; Linux man.7 is wrong about this!)
2883 2980
2884 (defun woman1-BI () 2981 (defun woman1-BI ()
2885 ".BI -- Join words of current line alternating bold and italic fonts." 2982 ".BI -- Join words of current line alternating bold and italic fonts."
2886 (woman1-alt-fonts (list "\\fB" "\\fI"))) 2983 (woman1-alt-fonts (list "\\fB" "\\fI")))
2919 (woman-forward-arg unquote 'concat)) ; unquote is bound above 3016 (woman-forward-arg unquote 'concat)) ; unquote is bound above
2920 (insert "\\fR") 3017 (insert "\\fR")
2921 )) 3018 ))
2922 3019
2923 (defun woman-forward-arg (&optional unquote concat) 3020 (defun woman-forward-arg (&optional unquote concat)
2924 "Move forward over one ?roff argument, optionally deleting quotes. 3021 "Move forward over one ?roff argument, optionally unquoting and/or joining.
2925 If optional arg UNQUOTE is non-nil, delete any argument quotes. 3022 If optional arg UNQUOTE is non-nil then delete any argument quotes.
2926 If optional arg CONCAT is non-nil, join arguments." 3023 If optional arg CONCAT is non-nil then join arguments."
2927 (if (eq (following-char) ?\") 3024 (if (eq (following-char) ?\")
2928 (progn 3025 (progn
2929 (if unquote (delete-char 1) (forward-char)) 3026 (if unquote (delete-char 1) (forward-char))
2930 (re-search-forward "\"\\|$") 3027 (re-search-forward "\"\\|$")
2931 ;; Repeated double-quote represents single double-quote 3028 ;; Repeated double-quote represents single double-quote
2942 ((eq concat 'noskip)) ; do not skip following whitespace 3039 ((eq concat 'noskip)) ; do not skip following whitespace
2943 (t (woman-delete-following-space))) 3040 (t (woman-delete-following-space)))
2944 ) 3041 )
2945 3042
2946 3043
2947 ;;; The following requests are not explicit font-change requests and 3044 ;; The following requests are not explicit font-change requests and
2948 ;;; so are flagged `notfont' to turn off automatic request deletion 3045 ;; so are flagged `notfont' to turn off automatic request deletion
2949 ;;; and further processing. 3046 ;; and further processing.
2950 3047
2951 (put 'woman1-TP 'notfont t) 3048 (put 'woman1-TP 'notfont t)
2952 (defun woman1-TP () 3049 (defun woman1-TP ()
2953 ".TP -- After tag line, reset font to Roman for paragraph body." 3050 ".TP -- After tag line, reset font to Roman for paragraph body."
2954 ;; Same for .IP, but forward only 1 line? 3051 ;; Same for .IP, but forward only 1 line?
2967 (insert ".ft I\n") 3064 (insert ".ft I\n")
2968 (forward-line N) 3065 (forward-line N)
2969 (insert ".ft R\n") 3066 (insert ".ft R\n")
2970 )) 3067 ))
2971 3068
2972 ;; Other non-breaking requests: 3069 ;;; Other non-breaking requests:
2973 3070
2974 ;; Hyphenation 3071 ;; Hyphenation
2975 ;; Warnings commented out. 3072 ;; Warnings commented out.
2976 3073
2977 (put 'woman1-nh 'notfont t) 3074 (put 'woman1-nh 'notfont t)
3005 (defun woman1-hw () 3102 (defun woman1-hw ()
3006 ".hw words -- Set hyphenation exception words, i.e. IGNORE!" 3103 ".hw words -- Set hyphenation exception words, i.e. IGNORE!"
3007 ;; (WoMan-log-1 ".hw request ignored -- hyphenation not supported!") 3104 ;; (WoMan-log-1 ".hw request ignored -- hyphenation not supported!")
3008 (woman-delete-whole-line)) 3105 (woman-delete-whole-line))
3009 3106
3010 ;; Other non-breaking requests correctly ignored by nroff: 3107 ;;; Other non-breaking requests correctly ignored by nroff:
3011 3108
3012 (put 'woman1-ps 'notfont t) 3109 (put 'woman1-ps 'notfont t)
3013 (defalias 'woman1-ps 'woman-delete-whole-line) 3110 (defalias 'woman1-ps 'woman-delete-whole-line)
3014 ;; .ps -- Point size -- IGNORE! 3111 ;; .ps -- Point size -- IGNORE!
3015 3112
3031 3128
3032 (put 'woman1-bd 'notfont t) 3129 (put 'woman1-bd 'notfont t)
3033 (defalias 'woman1-bd 'woman-delete-whole-line) 3130 (defalias 'woman1-bd 'woman-delete-whole-line)
3034 ;; .bd -- Embolden font -- IGNORE! 3131 ;; .bd -- Embolden font -- IGNORE!
3035 3132
3036 ;; Non-breaking SunOS-specific macros: 3133 ;;; Non-breaking SunOS-specific macros:
3037 3134
3038 (defun woman1-TX () 3135 (defun woman1-TX ()
3039 ".TX t p -- Resolve SunOS abbrev t and join to p (usually punctuation)." 3136 ".TX t p -- Resolve SunOS abbrev t and join to p (usually punctuation)."
3040 (insert "SunOS ") 3137 (insert "SunOS ")
3041 (woman-forward-arg 'unquote 'concat)) 3138 (woman-forward-arg 'unquote 'concat))
3165 (prog1 (char-to-string (following-char)) 3262 (prog1 (char-to-string (following-char))
3166 (delete-char 1)))) 3263 (delete-char 1))))
3167 3264
3168 (defun woman2-tr (to) 3265 (defun woman2-tr (to)
3169 ".tr abcde -- Translate a -> b, c -> d, ..., e -> space. 3266 ".tr abcde -- Translate a -> b, c -> d, ..., e -> space.
3170 TO is the buffer position where the directive ends. 3267 Format paragraphs upto TO. Supports special chars.
3171 \(Breaks, but should not.) Supports special chars." 3268 \(Breaks, but should not.)"
3172 ;; This should be an update, but consing onto the front of the alist 3269 ;; This should be an update, but consing onto the front of the alist
3173 ;; has the same effect and match duplicates should not matter. 3270 ;; has the same effect and match duplicates should not matter.
3174 ;; Initialize translation data structures: 3271 ;; Initialize translation data structures:
3175 (let ((matches (car translations)) 3272 (let ((matches (car translations))
3176 (alist (cdr translations)) 3273 (alist (cdr translations))
3250 (woman2-process-escapes 3347 (woman2-process-escapes
3251 (save-excursion (end-of-line) (point-marker)) 3348 (save-excursion (end-of-line) (point-marker))
3252 numeric)) 3349 numeric))
3253 3350
3254 (defun woman2-nr (to) 3351 (defun woman2-nr (to)
3255 ".nr R +/-N M -- Assign +/-N to register R wrt to previous value, if any. 3352 ".nr R +/-N M -- Assign +/-N (wrt to previous value, if any) to register R.
3256 The increment for auto-incrementing is set to M. 3353 The increment for auto-incrementing is set to M.
3257 TO is where the directive ends. 3354 Format paragraphs upto TO. (Breaks, but should not!)"
3258 \[Breaks, but should not!]"
3259 (let* ((name (buffer-substring 3355 (let* ((name (buffer-substring
3260 (point) 3356 (point)
3261 (progn (skip-syntax-forward "^ ") (point)))) 3357 (progn (skip-syntax-forward "^ ") (point))))
3262 (pm (progn ; increment 3358 (pm (progn ; increment
3263 (skip-chars-forward " \t") 3359 (skip-chars-forward " \t")
3293 3389
3294 3390
3295 ;;; Numeric (and "non-text") request arguments: 3391 ;;; Numeric (and "non-text") request arguments:
3296 3392
3297 (defsubst woman-get-numeric-arg () 3393 (defsubst woman-get-numeric-arg ()
3298 "Get the value of a numeric argument at or after point, don't move point. 3394 "Get the value of a numeric argument at or after point.
3299 The argument can include the width function and scale indicators. 3395 The argument can include the width function and scale indicators.
3300 Assumes 10 characters per inch." 3396 Assumes 10 characters per inch. Does not move point."
3301 (woman2-process-escapes-to-eol 'numeric) 3397 (woman2-process-escapes-to-eol 'numeric)
3302 (save-excursion (woman-parse-numeric-arg))) 3398 (save-excursion (woman-parse-numeric-arg)))
3303 3399
3304 (defun woman-parse-numeric-arg () 3400 (defun woman-parse-numeric-arg ()
3305 "Get the value of a numeric expression at or after point. 3401 "Get the value of a numeric expression at or after point.
3348 value 3444 value
3349 )) 3445 ))
3350 3446
3351 (defun woman-parse-numeric-value () 3447 (defun woman-parse-numeric-value ()
3352 "Get a single numeric value at or after point. 3448 "Get a single numeric value at or after point.
3353 Leaving point after the value. It can be a number register or width 3449 The value can be a number register or width function (which assumes 10
3354 function (which assumes 10 characters per inch) and can include scale 3450 characters per inch) and can include scale indicators. It may be an
3355 indicators. The value may be an expression in parentheses." 3451 expression in parentheses. Leaves point after the value."
3356 ;; Must replace every \' by some different single character first 3452 ;; Must replace every \' by some different single character first
3357 ;; before calling this function by calling 3453 ;; before calling this function by calling
3358 ;; (woman2-process-escapes-to-eol 'numeric) 3454 ;; (woman2-process-escapes-to-eol 'numeric)
3359 (if (eq (following-char) ?\() 3455 (if (eq (following-char) ?\()
3360 ;; Treat parenthesized expression as a single value. 3456 ;; Treat parenthesized expression as a single value.
3432 ))) 3528 )))
3433 3529
3434 3530
3435 ;;; VERTICAL FORMATTING -- Formatting macros that cause a break: 3531 ;;; VERTICAL FORMATTING -- Formatting macros that cause a break:
3436 3532
3437 ; Vertical spacing philosophy: 3533 ;; Vertical spacing philosophy:
3438 ; Delete all vertical space as it is encountered. Then insert 3534 ;; Delete all vertical space as it is encountered. Then insert
3439 ; vertical space only before text, as required. 3535 ;; vertical space only before text, as required.
3440 3536
3441 (defun woman2-roff-buffer () 3537 (defun woman2-roff-buffer ()
3442 "Process breaks. Format paragraphs and headings." 3538 "Process breaks. Format paragraphs and headings."
3443 (let ((case-fold-search t) 3539 (let ((case-fold-search t)
3444 (to (make-marker)) 3540 (to (make-marker))
3518 (woman-delete-line 2))) 3614 (woman-delete-line 2)))
3519 (if to (1- to) (point-max)))) 3615 (if to (1- to) (point-max))))
3520 3616
3521 (defun woman2-PD (to) 3617 (defun woman2-PD (to)
3522 ".PD d -- Set the interparagraph distance to d. 3618 ".PD d -- Set the interparagraph distance to d.
3523 Round to whole lines, default 1 line. (Breaks, but should not.) 3619 Round to whole lines, default 1 line. Format paragraphs upto TO.
3524 TO is the buffer position where the directive ends." 3620 (Breaks, but should not.)"
3525 ;; .ie \\n[.$] .nr PD (v;\\$1) 3621 ;; .ie \\n[.$] .nr PD (v;\\$1)
3526 ;; .el .nr PD .4v>?\n[.V] 3622 ;; .el .nr PD .4v>?\n[.V]
3527 (woman-set-interparagraph-distance) 3623 (woman-set-interparagraph-distance)
3528 (woman2-format-paragraphs to)) 3624 (woman2-format-paragraphs to))
3529 3625
3530 (defun woman-set-interparagraph-distance () 3626 (defun woman-set-interparagraph-distance ()
3531 "Set interparagraph distance from .PD directive at point." 3627 "Set the interparagraph distance from a .PD request at point."
3532 (setq woman-interparagraph-distance 3628 (setq woman-interparagraph-distance
3533 (if (eolp) 1 (woman-get-numeric-arg))) 3629 (if (eolp) 1 (woman-get-numeric-arg)))
3534 ;; Should allow .PD 0 to set zero line spacing 3630 ;; Should allow .PD 0 to set zero line spacing
3535 (woman-delete-line 1)) ; ignore remaining args 3631 (woman-delete-line 1)) ; ignore remaining args
3536 3632
3537 (defsubst woman-interparagraph-space () 3633 (defsubst woman-interparagraph-space ()
3538 "Set `woman-leave-blank-lines' from `woman-interparagraph-distance'." 3634 "Set variable `woman-leave-blank-lines' from `woman-interparagraph-distance'."
3539 ; (if (> woman-interparagraph-distance 0) 3635 ; (if (> woman-interparagraph-distance 0)
3540 ; (forward-line 1) ; leave 1 blank line 3636 ; (forward-line 1) ; leave 1 blank line
3541 ; (woman-delete-line 1)) ; do not leave blank line 3637 ; (woman-delete-line 1)) ; do not leave blank line
3542 (setq woman-leave-blank-lines woman-interparagraph-distance) 3638 (setq woman-leave-blank-lines woman-interparagraph-distance)
3543 ) 3639 )
3544 3640
3545 (defun woman2-TH (to) 3641 (defun woman2-TH (to)
3546 ".TH n c x v m -- Begin a page as per directive ending at TO. 3642 ".TH n c x v m -- Begin a man page. Format paragraphs upto TO.
3547 n is the name of the chapter c; x is extra commentary; v alters page 3643 n is the name of the page in chapter c\; x is extra commentary\;
3548 foot left; m alters page head center. 3644 v alters page foot left; m alters page head center.
3549 \(Should set prevailing indent (and tabs) to 5.)" 3645 \(Should set prevailing indent and tabs to 5.)"
3550 (woman-forward-arg 'unquote 'concat) 3646 (woman-forward-arg 'unquote 'concat)
3551 (insert ?\() 3647 (insert ?\()
3552 (woman-forward-arg 'unquote 'concat) 3648 (woman-forward-arg 'unquote 'concat)
3553 (insert ?\)) 3649 (insert ?\))
3554 (let ((start (point)) here) 3650 (let ((start (point)) here)
3574 (setq woman-left-margin woman-default-indent) 3670 (setq woman-left-margin woman-default-indent)
3575 (setq woman-prevailing-indent woman-default-indent) 3671 (setq woman-prevailing-indent woman-default-indent)
3576 (woman2-format-paragraphs to woman-left-margin)) 3672 (woman2-format-paragraphs to woman-left-margin))
3577 3673
3578 (defun woman2-SH (to) 3674 (defun woman2-SH (to)
3579 ".SH -- Sub-head. Leave blank line and subhead at TO. 3675 ".SH -- Sub-head. Leave blank line and subhead.
3580 Format following paragraph. Set prevailing indent to 5." 3676 Format paragraphs upto TO. Set prevailing indent to 5."
3581 (if (eolp) ; If no args then 3677 (if (eolp) ; If no args then
3582 (delete-char 1) ; apply to next line 3678 (delete-char 1) ; apply to next line
3583 (woman-unquote-args) ; else unquote to end of heading 3679 (woman-unquote-args) ; else unquote to end of heading
3584 (beginning-of-line)) 3680 (beginning-of-line))
3585 (woman2-process-escapes-to-eol) 3681 (woman2-process-escapes-to-eol)
3594 woman-nofill nil) ; fill output lines 3690 woman-nofill nil) ; fill output lines
3595 (setq woman-prevailing-indent woman-default-indent) 3691 (setq woman-prevailing-indent woman-default-indent)
3596 (woman2-format-paragraphs to woman-left-margin)) 3692 (woman2-format-paragraphs to woman-left-margin))
3597 3693
3598 (defun woman2-SS (to) 3694 (defun woman2-SS (to)
3599 ".SS -- Sub-sub-head at TO. Like .SH but indent heading 3 spaces." 3695 ".SS -- Sub-sub-head. Like .SH but indent heading 3 spaces.
3696 Format paragraphs upto TO."
3600 (if (eolp) ; If no args then 3697 (if (eolp) ; If no args then
3601 (delete-char 1)) ; apply to next line. 3698 (delete-char 1)) ; apply to next line.
3602 (insert " ") 3699 (insert " ")
3603 (beginning-of-line) 3700 (beginning-of-line)
3604 (woman2-SH to)) 3701 (woman2-SH to))
3605 3702
3606 (defun woman2-LP (to) 3703 (defun woman2-LP (to)
3607 ".LP,.PP -- Begin paragraph at TO. Set prevailing indent to 5. 3704 ".LP,.PP -- Begin paragraph. Set prevailing indent to 5.
3608 Leave 1 blank line and format following paragraph." 3705 Leave 1 blank line. Format paragraphs upto TO."
3609 (woman-delete-line 1) ; ignore any arguments 3706 (woman-delete-line 1) ; ignore any arguments
3610 (woman-interparagraph-space) 3707 (woman-interparagraph-space)
3611 (setq woman-prevailing-indent woman-default-indent) 3708 (setq woman-prevailing-indent woman-default-indent)
3612 (woman2-format-paragraphs to woman-left-margin)) 3709 (woman2-format-paragraphs to woman-left-margin))
3613 3710
3614 (defalias 'woman2-PP 'woman2-LP) 3711 (defalias 'woman2-PP 'woman2-LP)
3615 (defalias 'woman2-P 'woman2-LP) 3712 (defalias 'woman2-P 'woman2-LP)
3616 3713
3617 (defun woman2-ns (to) 3714 (defun woman2-ns (to)
3618 ".ns -- Turn on no-space mode at TO and format following paragraph." 3715 ".ns -- Turn on no-space mode. Format paragraphs upto TO."
3619 ;; Should not cause a break! 3716 ;; Should not cause a break!
3620 (woman-delete-line 1) ; ignore argument(s) 3717 (woman-delete-line 1) ; ignore argument(s)
3621 (setq woman-nospace t) 3718 (setq woman-nospace t)
3622 (woman2-format-paragraphs to)) 3719 (woman2-format-paragraphs to))
3623 3720
3624 (defun woman2-rs (to) 3721 (defun woman2-rs (to)
3625 ".rs -- Turn off no-space mode at TO and format following paragraph." 3722 ".rs -- Turn off no-space mode. Format paragraphs upto TO."
3626 ;; Should not cause a break! 3723 ;; Should not cause a break!
3627 (woman-delete-line 1) ; ignore argument(s) 3724 (woman-delete-line 1) ; ignore argument(s)
3628 (setq woman-nospace nil) 3725 (setq woman-nospace nil)
3629 (woman2-format-paragraphs to)) 3726 (woman2-format-paragraphs to))
3630 3727
3631 (defun woman2-sp (to) 3728 (defun woman2-sp (to)
3632 ".sp N -- If N > 0, leave 1 blank line at TO and format following paragraph." 3729 ".sp N -- If N > 0 then leave 1 blank line. Format paragraphs upto TO."
3633 (let ((N (if (eolp) 1 (woman-get-numeric-arg)))) 3730 (let ((N (if (eolp) 1 (woman-get-numeric-arg))))
3634 (if (>= N 0) 3731 (if (>= N 0)
3635 (woman-delete-line 1) ; ignore argument(s) 3732 (woman-delete-line 1) ; ignore argument(s)
3636 (setq woman-negative-vertical-space t) 3733 (setq woman-negative-vertical-space t)
3637 (insert ".sp ") 3734 (insert ".sp ")
3784 )) 3881 ))
3785 3882
3786 ;;; 4. Text Filling, Adjusting, and Centering 3883 ;;; 4. Text Filling, Adjusting, and Centering
3787 3884
3788 (defun woman2-br (to) 3885 (defun woman2-br (to)
3789 ".br -- Break. Leave no blank line at TO and format following paragraph." 3886 ".br -- Break. Leave no blank line. Format paragraphs upto TO."
3790 (woman-delete-line 1) ; ignore any arguments 3887 (woman-delete-line 1) ; ignore any arguments
3791 (woman2-format-paragraphs to)) 3888 (woman2-format-paragraphs to))
3792 3889
3793 (defun woman2-fi (to) 3890 (defun woman2-fi (to)
3794 ".fi -- Fill subsequent output lines at TO. 3891 ".fi -- Fill subsequent output lines. Leave no blank line.
3795 Leave no blank line and format following paragraph" 3892 Format paragraphs upto TO."
3796 (setq woman-nofill nil) 3893 (setq woman-nofill nil)
3797 (woman-delete-line 1) ; ignore any arguments 3894 (woman-delete-line 1) ; ignore any arguments
3798 ;; Preserve any final blank line in the nofill region: 3895 ;; Preserve any final blank line in the nofill region:
3799 (save-excursion 3896 (save-excursion
3800 (forward-line -1) 3897 (forward-line -1)
3801 (if (looking-at "[ \t]*$") (setq woman-leave-blank-lines 1))) 3898 (if (looking-at "[ \t]*$") (setq woman-leave-blank-lines 1)))
3802 (woman2-format-paragraphs to)) 3899 (woman2-format-paragraphs to))
3803 3900
3804 (defun woman2-nf (to) 3901 (defun woman2-nf (to)
3805 ".nf -- Nofill at TO. Subsequent lines are neither filled nor adjusted. 3902 ".nf -- Nofill. Subsequent lines are neither filled nor adjusted.
3806 Input text lines are copied directly to output lines without regard for 3903 Input text lines are copied directly to output lines without regard
3807 the current line length." 3904 for the current line length. Format paragraphs upto TO."
3808 (setq woman-nofill t) 3905 (setq woman-nofill t)
3809 (woman-delete-line 1) ; ignore any arguments 3906 (woman-delete-line 1) ; ignore any arguments
3810 (woman2-format-paragraphs to)) 3907 (woman2-format-paragraphs to))
3811 3908
3812 (defun woman2-ad (to) 3909 (defun woman2-ad (to)
3813 ".ad c -- Line adjustment is begun at TO (once fill mode is on). 3910 ".ad c -- Line adjustment is begun (once fill mode is on).
3814 Set justification mode to c if specified. (Breaks, but should not.)" 3911 Set justification mode to c if specified.
3912 Format paragraphs upto TO. (Breaks, but should not.)"
3815 ;; c = l -- left, r -- right, c -- center, b or n -- both, 3913 ;; c = l -- left, r -- right, c -- center, b or n -- both,
3816 ;; absent -- unchanged. Initial mode adj,both. 3914 ;; absent -- unchanged. Initial mode adj,both.
3817 (setq woman-adjust 3915 (setq woman-adjust
3818 (cond ((eolp) woman-adjust-previous) 3916 (cond ((eolp) woman-adjust-previous)
3819 ((eq (following-char) ?l) woman-adjust-left) 3917 ((eq (following-char) ?l) woman-adjust-left)
3825 woman-justify (nth woman-adjust woman-justify-list)) 3923 woman-justify (nth woman-adjust woman-justify-list))
3826 (woman-delete-line 1) ; ignore any remaining arguments 3924 (woman-delete-line 1) ; ignore any remaining arguments
3827 (woman2-format-paragraphs to)) 3925 (woman2-format-paragraphs to))
3828 3926
3829 (defun woman2-na (to) 3927 (defun woman2-na (to)
3830 ".na -- No adjusting at TO. 3928 ".na -- No adjusting. Format paragraphs upto TO.
3831 (Breaks, but should not.)" 3929 (Breaks, but should not.)"
3832 (setq woman-adjust-previous woman-adjust 3930 (setq woman-adjust-previous woman-adjust
3833 woman-justify-previous woman-justify 3931 woman-justify-previous woman-justify
3834 woman-adjust woman-adjust-left ; fill but do not adjust 3932 woman-adjust woman-adjust-left ; fill but do not adjust
3835 woman-justify (nth woman-adjust woman-justify-list)) 3933 woman-justify (nth woman-adjust woman-justify-list))
3838 3936
3839 ;;; The main formatting functions: 3937 ;;; The main formatting functions:
3840 3938
3841 (defun woman-leave-blank-lines (&optional leave) 3939 (defun woman-leave-blank-lines (&optional leave)
3842 "Delete all blank lines around point. 3940 "Delete all blank lines around point.
3843 Leave one blank line if optional argument LEAVE is non-nil and non-zero, 3941 Leave one blank line if optional argument LEAVE is non-nil and
3844 or if LEAVE is nil and `woman-leave-blank-lines' is non-nil and non-zero." 3942 non-zero, or if LEAVE is nil and variable `woman-leave-blank-lines' is
3943 non-nil and non-zero."
3845 ;; ***** It may suffice to delete only lines ABOVE point! ***** 3944 ;; ***** It may suffice to delete only lines ABOVE point! *****
3846 ;; NOTE: Function arguments are evaluated left to right 3945 ;; NOTE: Function arguments are evaluated left to right
3847 ;; (*note (elisp)Function Forms::.). 3946 ;; (*note (elisp)Function Forms::.).
3848 (delete-region 3947 (delete-region
3849 (save-excursion 3948 (save-excursion
3867 ;; text filling function, so that is what I use here. 3966 ;; text filling function, so that is what I use here.
3868 3967
3869 (defvar woman-temp-indent nil) 3968 (defvar woman-temp-indent nil)
3870 3969
3871 (defun woman2-format-paragraphs (to &optional new-left) 3970 (defun woman2-format-paragraphs (to &optional new-left)
3872 "Indent paragraphs at TO to current left margin. 3971 "Indent, fill and adjust paragraphs upto TO to current left margin.
3873 Optional argument NEW-LEFT, if non-nil, means set current left margin. 3972 If optional arg NEW-LEFT is non-nil then reset current left margin.
3874 If `woman-nofill' is nil, also fill and adjust." 3973 If `woman-nofill' is non-nil then indent without filling or adjusting."
3875 ;; Blank space should only ever be output before text. 3974 ;; Blank space should only ever be output before text.
3876 (if new-left (setq left-margin new-left)) 3975 (if new-left (setq left-margin new-left))
3877 (if (looking-at "^\\s *$") 3976 (if (looking-at "^\\s *$")
3878 ;; A blank line should leave a space like .sp 1 (p. 14). 3977 ;; A blank line should leave a space like .sp 1 (p. 14).
3879 (setq woman-leave-blank-lines 1)) 3978 (setq woman-leave-blank-lines 1))
3958 4057
3959 4058
3960 ;;; Tagged, indented and hanging paragraphs: 4059 ;;; Tagged, indented and hanging paragraphs:
3961 4060
3962 (defun woman2-TP (to) 4061 (defun woman2-TP (to)
3963 ".TP i -- Set prevailing indent to i at TO. 4062 ".TP i -- Set prevailing indent to i. Format paragraphs upto TO.
3964 Begin indented paragraph with hanging tag given by next text line. 4063 Begin indented paragraph with hanging tag given by next text line.
3965 If tag doesn't fit, place it on a separate line." 4064 If tag doesn't fit, place it on a separate line."
3966 (let ((i (woman2-get-prevailing-indent))) 4065 (let ((i (woman2-get-prevailing-indent)))
3967 (woman-leave-blank-lines woman-interparagraph-distance) 4066 (woman-leave-blank-lines woman-interparagraph-distance)
3968 (woman2-tagged-paragraph to i))) 4067 (woman2-tagged-paragraph to i)))
3969 4068
3970 (defun woman2-IP (to) 4069 (defun woman2-IP (to)
3971 ".IP x i -- Same as .TP with tag x. TO is where the directive ends." 4070 ".IP x i -- Same as .TP with tag x. Format paragraphs upto TO."
3972 (woman-interparagraph-space) 4071 (woman-interparagraph-space)
3973 (if (eolp) ; no args 4072 (if (eolp) ; no args
3974 ;; Like LP without resetting prevailing indent 4073 ;; Like LP without resetting prevailing indent
3975 (woman2-format-paragraphs to (+ woman-left-margin 4074 (woman2-format-paragraphs to (+ woman-left-margin
3976 woman-prevailing-indent)) 4075 woman-prevailing-indent))
3985 (if (looking-at "^[.']") 4084 (if (looking-at "^[.']")
3986 (point) 4085 (point)
3987 (woman-find-next-control-line))) 4086 (woman-find-next-control-line)))
3988 4087
3989 (defun woman2-tagged-paragraph (to i) 4088 (defun woman2-tagged-paragraph (to i)
3990 "Set prevailing indent at TO to I. 4089 "Begin indented paragraph with hanging tag given by current text line.
3991 Begin indented paragraph with hanging tag given by current text line. 4090 If tag doesn't fit, leave it on separate line.
3992 If tag doesn't fit, leave it on separate line." 4091 Format paragraphs upto TO. Set prevailing indent to I."
3993 (if (not (looking-at "\\s *$")) ; non-empty tag 4092 (if (not (looking-at "\\s *$")) ; non-empty tag
3994 (setq woman-leave-blank-lines nil)) 4093 (setq woman-leave-blank-lines nil))
3995 4094
3996 ;; Temporary hack for bash.1 and groff_mmse.7 until code is revised 4095 ;; Temporary hack for bash.1 and groff_mmse.7 until code is revised
3997 ;; to process all requests uniformly: 4096 ;; to process all requests uniformly:
4040 (goto-char to) ; necessary ??? 4139 (goto-char to) ; necessary ???
4041 )) 4140 ))
4042 )) 4141 ))
4043 4142
4044 (defun woman2-HP (to) 4143 (defun woman2-HP (to)
4045 ".HP i -- Set prevailing indent at TO to i. 4144 ".HP i -- Set prevailing indent to i. Format paragraphs upto TO.
4046 Begin paragraph with hanging indent." 4145 Begin paragraph with hanging indent."
4047 (let ((i (woman2-get-prevailing-indent))) 4146 (let ((i (woman2-get-prevailing-indent)))
4048 (woman-interparagraph-space) 4147 (woman-interparagraph-space)
4049 (setq woman-temp-indent woman-left-margin) 4148 (setq woman-temp-indent woman-left-margin)
4050 (woman2-format-paragraphs to (+ woman-left-margin i)) 4149 (woman2-format-paragraphs to (+ woman-left-margin i))
4051 )) 4150 ))
4052 4151
4053 (defun woman2-get-prevailing-indent (&optional leave-eol) 4152 (defun woman2-get-prevailing-indent (&optional leave-eol)
4054 "Set the prevailing indent to an integer argument at point, and return it. 4153 "Set prevailing indent to integer argument at point, and return it.
4055 If no argument at point, return prevailing indent. 4154 If no argument then return the existing prevailing indent.
4056 Delete line from point and eol unless LEAVE-EOL is non-nil." 4155 Delete line from point and eol unless LEAVE-EOL is non-nil."
4057 (if (eolp) 4156 (if (eolp)
4058 (or leave-eol (delete-char 1)) 4157 (or leave-eol (delete-char 1))
4059 (let ((i (woman-get-numeric-arg))) 4158 (let ((i (woman-get-numeric-arg)))
4060 (woman-delete-line) (or leave-eol (delete-char 1)) 4159 (woman-delete-line) (or leave-eol (delete-char 1))
4065 (defmacro woman-push (value stack) 4164 (defmacro woman-push (value stack)
4066 "Push VALUE onto STACK." 4165 "Push VALUE onto STACK."
4067 `(setq ,stack (cons ,value ,stack))) 4166 `(setq ,stack (cons ,value ,stack)))
4068 4167
4069 (defmacro woman-pop (variable stack) 4168 (defmacro woman-pop (variable stack)
4070 "Pop the value at the top of STACK into VARIABLE. 4169 "Pop into VARIABLE the value at the top of STACK.
4071 Allow for mismatched requests!" 4170 Allow for mismatched requests!"
4072 `(if ,stack 4171 `(if ,stack
4073 (setq ,variable (car ,stack) 4172 (setq ,variable (car ,stack)
4074 ,stack (cdr ,stack)))) 4173 ,stack (cdr ,stack))))
4075 4174
4076 (defun woman2-RS (to) 4175 (defun woman2-RS (to)
4077 ".RS i -- Start relative indent at TO, move left margin in distance i. 4176 ".RS i -- Start relative indent, move left margin in distance i.
4078 Set prevailing indent to 5 for nested indents." 4177 Set prevailing indent to 5 for nested indents. Format paragraphs upto TO."
4079 (woman-push woman-left-margin woman-RS-left-margin) 4178 (woman-push woman-left-margin woman-RS-left-margin)
4080 (woman-push woman-prevailing-indent woman-RS-prevailing-indent) 4179 (woman-push woman-prevailing-indent woman-RS-prevailing-indent)
4081 (setq woman-left-margin (+ woman-left-margin 4180 (setq woman-left-margin (+ woman-left-margin
4082 (woman2-get-prevailing-indent)) 4181 (woman2-get-prevailing-indent))
4083 woman-prevailing-indent woman-default-indent) 4182 woman-prevailing-indent woman-default-indent)
4084 (woman2-format-paragraphs to woman-left-margin)) 4183 (woman2-format-paragraphs to woman-left-margin))
4085 4184
4086 (defun woman2-RE (to) 4185 (defun woman2-RE (to)
4087 ".RE -- End of relative indent at TO. 4186 ".RE -- End of relative indent. Format paragraphs upto TO.
4088 Set prevailing indent to amount of starting .RS." 4187 Set prevailing indent to amount of starting .RS."
4089 (woman-pop woman-left-margin woman-RS-left-margin) 4188 (woman-pop woman-left-margin woman-RS-left-margin)
4090 (woman-pop woman-prevailing-indent woman-RS-prevailing-indent) 4189 (woman-pop woman-prevailing-indent woman-RS-prevailing-indent)
4091 (woman-delete-line 1) ; ignore any arguments 4190 (woman-delete-line 1) ; ignore any arguments
4092 (woman2-format-paragraphs to woman-left-margin)) 4191 (woman2-format-paragraphs to woman-left-margin))
4093 4192
4094 4193
4095 ;;; Line Length and Indenting: 4194 ;;; Line Length and Indenting:
4096 4195
4097 (defun woman-set-arg (arg &optional previous) 4196 (defun woman-set-arg (arg &optional previous)
4098 "Reset, increment or decrement ARG, delete the whole remaining control line. 4197 "Reset, increment or decrement argument ARG, which must be quoted.
4099 Argument must be quoted. 4198 If no argument then use value of optional arg PREVIOUS if non-nil,
4100 Optional argument PREVIOUS, if non-nil, is evaluated to set ARG at eol." 4199 otherwise set PREVIOUS. Delete the whole remaining control line."
4101 (if (eolp) ; space already skipped 4200 (if (eolp) ; space already skipped
4102 (set arg (if previous (eval previous) 0)) 4201 (set arg (if previous (eval previous) 0))
4103 (if previous (set previous (eval arg))) 4202 (if previous (set previous (eval arg)))
4104 (woman2-process-escapes-to-eol 'numeric) 4203 (woman2-process-escapes-to-eol 'numeric)
4105 (let ((pm (if (looking-at "[+-]") 4204 (let ((pm (if (looking-at "[+-]")
4116 ;; NEED TO RATIONALIZE NAMES FOR PREVIOUS VALUES! 4215 ;; NEED TO RATIONALIZE NAMES FOR PREVIOUS VALUES!
4117 (defvar woman-ll-fill-column woman-fill-column) 4216 (defvar woman-ll-fill-column woman-fill-column)
4118 (defvar woman-in-left-margin woman-left-margin) 4217 (defvar woman-in-left-margin woman-left-margin)
4119 4218
4120 (defun woman2-ll (to) 4219 (defun woman2-ll (to)
4121 ".ll +/-N -- Set, increment or decrement line length at TO. 4220 ".ll +/-N -- Set, increment or decrement line length.
4122 \(Breaks, but should not.)" 4221 Format paragraphs upto TO. (Breaks, but should not.)"
4123 (woman-set-arg 'fill-column 'woman-ll-fill-column) 4222 (woman-set-arg 'fill-column 'woman-ll-fill-column)
4124 (woman2-format-paragraphs to)) 4223 (woman2-format-paragraphs to))
4125 4224
4126 (defun woman2-in (to) 4225 (defun woman2-in (to)
4127 ".in +/-N -- Set, increment or decrement the indent at TO." 4226 ".in +/-N -- Set, increment or decrement the indent.
4227 Format paragraphs upto TO."
4128 (woman-set-arg 'left-margin 'woman-in-left-margin) 4228 (woman-set-arg 'left-margin 'woman-in-left-margin)
4129 (woman2-format-paragraphs to)) 4229 (woman2-format-paragraphs to))
4130 4230
4131 (defun woman2-ti (to) 4231 (defun woman2-ti (to)
4132 ".ti +/-N -- Temporary indent at TO." 4232 ".ti +/-N -- Temporary indent. Format paragraphs upto TO."
4133 ;; Ignore if no argument. 4233 ;; Ignore if no argument.
4134 ;; Indent next output line only wrt current indent. 4234 ;; Indent next output line only wrt current indent.
4135 ;; Current indent is not changed. 4235 ;; Current indent is not changed.
4136 (setq woman-temp-indent left-margin) 4236 (setq woman-temp-indent left-margin)
4137 (woman-set-arg 'woman-temp-indent) 4237 (woman-set-arg 'woman-temp-indent)
4139 4239
4140 4240
4141 ;;; Tabs, Leaders, and Fields: 4241 ;;; Tabs, Leaders, and Fields:
4142 4242
4143 (defun woman2-ta (to) 4243 (defun woman2-ta (to)
4144 ".ta Nt ... -- Set tabs at TO, left type, unless t=R(right), C(centered). 4244 ".ta Nt ... -- Set tabs, left type, unless t=R(right), C(centered).
4145 \(Breaks, but should not.) The tab stops are separated by spaces; 4245 \(Breaks, but should not.) The tab stops are separated by spaces\;
4146 a value preceded by + represents an increment to the previous stop value." 4246 a value preceded by + represents an increment to the previous stop value.
4247 Format paragraphs upto TO."
4147 (setq tab-stop-list nil) 4248 (setq tab-stop-list nil)
4148 (woman2-process-escapes-to-eol 'numeric) 4249 (woman2-process-escapes-to-eol 'numeric)
4149 (save-excursion 4250 (save-excursion
4150 (let ((tab-stop 0)) 4251 (let ((tab-stop 0))
4151 (while (not (eolp)) 4252 (while (not (eolp))
4166 "If TAB-STOP-LIST is a cons, return its car, else return TAB-STOP-LIST." 4267 "If TAB-STOP-LIST is a cons, return its car, else return TAB-STOP-LIST."
4167 (if (consp tab-stop-list) (car tab-stop-list) tab-stop-list)) 4268 (if (consp tab-stop-list) (car tab-stop-list) tab-stop-list))
4168 4269
4169 (defun woman-tab-to-tab-stop () 4270 (defun woman-tab-to-tab-stop ()
4170 "Insert spaces to next defined tab-stop column. 4271 "Insert spaces to next defined tab-stop column.
4171 The variable `tab-stop-list' is a list of columns where there are tab stops: 4272 The variable `tab-stop-list' is a list whose elements are either left
4172 pairs (COLUMN . TYPE) where type is either R or C." 4273 tab stop columns or pairs (COLUMN . TYPE) where TYPE is R or C."
4173 ;; Based on tab-to-tab-stop in indent.el. 4274 ;; Based on tab-to-tab-stop in indent.el.
4174 ;; R & C tabs probably not quite right! 4275 ;; R & C tabs probably not quite right!
4175 (delete-backward-char 1) 4276 (delete-backward-char 1)
4176 (let ((tabs tab-stop-list)) 4277 (let ((tabs tab-stop-list))
4177 (while (and tabs (>= (current-column) 4278 (while (and tabs (>= (current-column)
4193 (insert ?\ ) 4294 (insert ?\ )
4194 (setq n (1- n)))) 4295 (setq n (1- n))))
4195 (insert ?\ )))) 4296 (insert ?\ ))))
4196 4297
4197 (defun woman2-DT (to) 4298 (defun woman2-DT (to)
4198 ".DT -- Restore default tabs at TO. 4299 ".DT -- Restore default tabs. Format paragraphs upto TO.
4199 (Breaks, but should not.)" 4300 \(Breaks, but should not.)"
4200 ;; Currently just terminates special tab processing. 4301 ;; Currently just terminates special tab processing.
4201 (setq tab-stop-list nil) 4302 (setq tab-stop-list nil)
4202 (woman-delete-line 1) ; ignore any arguments 4303 (woman-delete-line 1) ; ignore any arguments
4203 (woman2-format-paragraphs to)) 4304 (woman2-format-paragraphs to))
4204 4305
4205 (defun woman2-fc (to) 4306 (defun woman2-fc (to)
4206 ".fc a b -- Set field delimiter a and pad character b at TO. 4307 ".fc a b -- Set field delimiter a and pad character b.
4308 Format paragraphs upto TO.
4207 A VERY FIRST ATTEMPT to make fields at least readable! 4309 A VERY FIRST ATTEMPT to make fields at least readable!
4208 Needs doing properly!" 4310 Needs doing properly!"
4209 (if (eolp) 4311 (if (eolp)
4210 (woman-delete-whole-line) ; ignore! 4312 (woman-delete-whole-line) ; ignore!
4211 (let ((delim (following-char)) 4313 (let ((delim (following-char))
4237 (woman2-format-paragraphs to)) 4339 (woman2-format-paragraphs to))
4238 4340
4239 4341
4240 ;;; WoMan message logging: 4342 ;;; WoMan message logging:
4241 4343
4242 ;;; The basis for this logging code was shamelessly pirated from bytecomp.el 4344 ;; The basis for this logging code was shamelessly pirated from bytecomp.el
4243 ;;; by Jamie Zawinski <jwz@lucid.com> & Hallvard Furuseth <hbf@ulrik.uio.no> 4345 ;; by Jamie Zawinski <jwz@lucid.com> & Hallvard Furuseth <hbf@ulrik.uio.no>
4244 4346
4245 (defvar WoMan-current-file nil) ; bound in woman-really-find-file 4347 (defvar WoMan-current-file nil) ; bound in woman-really-find-file
4246 (defvar WoMan-Log-header-point-max nil) 4348 (defvar WoMan-Log-header-point-max nil)
4247 4349
4248 (defun WoMan-log-begin () 4350 (defun WoMan-log-begin ()
4288 with the message." 4390 with the message."
4289 (WoMan-log-1 (format "Formatting time %d seconds." time) 'end)) 4391 (WoMan-log-1 (format "Formatting time %d seconds." time) 'end))
4290 4392
4291 (defun WoMan-log-1 (string &optional end) 4393 (defun WoMan-log-1 (string &optional end)
4292 "Log a message STRING in *WoMan-Log*. 4394 "Log a message STRING in *WoMan-Log*.
4293 Optional argument END, if non-nil, means make buffer read-only after logging 4395 If optional argument END is non-nil then make buffer read-only after
4294 the message." 4396 logging the message."
4295 (save-excursion 4397 (save-excursion
4296 (set-buffer (get-buffer-create "*WoMan-Log*")) 4398 (set-buffer (get-buffer-create "*WoMan-Log*"))
4297 (goto-char (point-max)) 4399 (goto-char (point-max))
4298 (or end (insert " ")) (insert string "\n") 4400 (or end (insert " ")) (insert string "\n")
4299 (if end 4401 (if end
4309 ))))) 4411 )))))
4310 nil) ; for woman-file-readable-p etc. 4412 nil) ; for woman-file-readable-p etc.
4311 4413
4312 (provide 'woman) 4414 (provide 'woman)
4313 4415
4416 ;; RECENT CHANGE LOG
4417 ;; =================
4418
4419 ;; Changes in version 0.50 ([*] => user interface change)
4420 ;; [*] Requires GNU Emacs 20.3+.
4421 ;; [*] `defface' used to define faces.
4422 ;; [*] Follow `see also' references with mouse-2 click.
4423 ;; Number register increment support added (woman-registers).
4424 ;; .j must be a NUMBER acceptable by .ad request.
4425 ;; Very crude field support added.
4426 ;; Vertical unit specifier `v' added to register handling.
4427 ;; Improvement to local horizontal motion processing.
4428 ;; Minor fix to handle negative numeric arguments.
4429 ;; Handle horizontal motion escapes `\h' better.
4430 ;; Allow arbitrary delimiters in `.if', inc. special character escapes.
4431 ;; Allow `\n' within `.if' string comparisons.
4432 ;; Allow arbitrary delimiters in `\w', inc. special character escapes.
4433 ;; Processing of `\h' moved much later -- after indenting etc!
4434
4435 ;; Changes in version 0.51 ([*] => user interface change)
4436 ;; [*] Improved handling of underlined faces (mainly for "italics").
4437 ;; [*] Allow environment variables in directory path elements.
4438 ;; Display of pre-formatted files improved.
4439 ;; [*] Unintentional interaction with standard Man mode reduced.
4440 ;; [*] bzip2 decompression support added. All decompression now
4441 ;; works by turning on `auto-compression-mode' to decompress the
4442 ;; file if necessary, rather than decompressing explicitly.
4443 ;; Filename and compression regexps are now customizable user
4444 ;; options.
4445
4446 ;; Changes in version 0.52 ([*] => user interface change)
4447 ;; Speeded up handling of underlined faces (mainly for "italics").
4448 ;; [*] WoMan formatting time display and log added. Emacs `man'
4449 ;; formatting time display advice added. (This suggests that
4450 ;; WoMan formatting is faster than Emacs `man' *formatting*,
4451 ;; i.e. when man is not using `catman' caching. E.g. `woman
4452 ;; bash' takes 27s whereas `man bash' takes 35s and for smaller
4453 ;; files `woman' can be relatively much faster than `man'.)
4454 ;; [*] Experimental support for non-ASCII characters from the
4455 ;; default and symbol fonts added, initially only for MS-Windows.
4456 ;; NOTE: It is off by default, mainly because it may increase the
4457 ;; line spacing; customize `woman-use-symbols' to `on' to use it.
4458 ;; Pad character handling for .fc fixed.
4459 ;; Tested: see `woman.status'.
4460
4461 ;; Changes in version 0.53 ([*] => user interface change)
4462 ;; [*] Customization option to use a separate frame for WoMan windows.
4463 ;; [*] Experimental option to emulate nroff (default) or troff (not tested).
4464 ;; [*] Separation of extended and symbol font options.
4465 ;; Only symbol font size 16 seems to work, and only with Win 95, not NT!
4466 ;; [*] `Advanced' sub-menu containing:
4467 ;; `View Source' option;
4468 ;; `Show Log' option;
4469 ;; `Extended Font' toggle and reformat;
4470 ;; `Symbol Font' toggle and reformat;
4471 ;; `Font Map' option;
4472 ;; `Emulation' radio buttons.
4473 ;; [*] Support for man config file added for default manpath.
4474
4475 ;; Changes in version 0.54
4476 ;; Revised for distribution with Emacs 21.
4477 ;; Comment order and doc strings changed substantially.
4478 ;; MS-DOS support added (by Eli Zaretskii).
4479 ;; checkdoc run: no real errors.
4480
4314 ;;; woman.el ends here 4481 ;;; woman.el ends here