home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / epoch / lightbrite-1.1.2 / lightbrite.el next >
Encoding:
Text File  |  1992-09-13  |  63.8 KB  |  1,459 lines

  1. ;;; --------------------------------------------------------------------------
  2. ;;; File: --- lightbrite.el ---
  3. ;;; Author: Marc Andreessen (marca@ncsa.uiuc.edu)
  4. ;;; Copyright (C) National Center for Supercomputing Applications, 1992.
  5. ;;;
  6. ;;; This program is free software; you can redistribute it and/or modify
  7. ;;; it under the terms of the GNU General Public License as published by
  8. ;;; the Free Software Foundation; either version 1, or (at your option)
  9. ;;; any later version.
  10. ;;;
  11. ;;; This program is distributed in the hope that it will be useful,
  12. ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ;;; GNU General Public License for more details.
  15. ;;;
  16. ;;; You should have received a copy of the GNU General Public License
  17. ;;; along with your copy of Epoch or Lucid Emacs; if not, write to the
  18. ;;; Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
  19. ;;; USA.
  20. ;;;
  21. ;;; CONTENTS
  22. ;;;
  23. ;;; Lightbrite: a minor mode for source code highlighting.
  24. ;;; Version 1.1.2.
  25. ;;;
  26. ;;; FEATURES
  27. ;;;
  28. ;;; o Accurate comment highlighting.
  29. ;;; o Regexp touchup highlighting.
  30. ;;; o Easy specification of visual attributes of multiple 
  31. ;;;   highlighting styles.
  32. ;;; o Instant highlighting (as you type) with adjustable 
  33. ;;;   responsiveness.
  34. ;;; o Buffer size thresholds for both comment and touchup 
  35. ;;;   highlighting.
  36. ;;; o Use of minor mode and local keymaps.
  37. ;;; o Re-highlight visible screen, current paragraph, current
  38. ;;;   function, immediate area, or entire buffer.
  39. ;;; o Large assortment of default mode-specific highlighting
  40. ;;;   patterns.
  41. ;;; o Automatic highlight on find-file and/or write-file.
  42. ;;; o Special handling of mail and rmail modes.
  43. ;;; o Works with both Epoch and Lucid Emacs transparently.
  44. ;;; o Automatic bug report generation.
  45. ;;;
  46. ;;; NEW FEATURES in 1.1.1
  47. ;;;
  48. ;;; o brite::mode-hook and brite::mode-exit-hook.
  49. ;;; o Menubar support for Lucid Emacs.
  50. ;;; o Pointer glyph changes to watch when Lightbrite is working
  51. ;;;   in both Epoch and Lucid Emacs.
  52. ;;;
  53. ;;; NEW FEATURES in 1.1.2
  54. ;;;
  55. ;;; o Lightbrite is now friendly to other zones/extents in the
  56. ;;;   buffer: it won't delete them.
  57. ;;;
  58. ;;; BUG REPORTS
  59. ;;;
  60. ;;; Bugs should be reported with brite::submit-bug-report.  Bug
  61. ;;; *fixes* are especially encouraged.
  62. ;;;
  63. ;;; HISTORY
  64. ;;;
  65. ;;; Sun Apr  5 22:09:51 1992 -- Marc Andreessen
  66. ;;;   Made available v1.0 with incomplete docs.
  67. ;;; Sat Sep 12 02:59:44 1992 -- Marc Andreessen
  68. ;;;   v1.1 functional.  Texinfo docs discarded for the time being.
  69. ;;; Sat Sep 12 04:42:23 1992 -- Marc Andreessen
  70. ;;;   Put initial version of 1.1 on ftp server.
  71. ;;; Sat Sep 12 20:37:04 1992 -- Marc Andreessen
  72. ;;;   Added Lucid Emacs menubar code; added brite::mode-hook
  73. ;;;   and brite::mode-exit-hook.
  74. ;;; Sat Sep 12 22:31:04 1992 -- Marc Andreessen
  75. ;;;   Added pointer munging code.
  76. ;;; Sun Sep 13 17:11:33 1992 -- Marc Andreessen
  77. ;;;   Made 1.1.1 available on ftp server.
  78. ;;; Sun Sep 13 17:12:43 1992 -- Marc Andreessen
  79. ;;;   Changed compare of change-counter with change-interval back
  80. ;;;   to >= (in case change-interval is decreased by user).
  81. ;;; Sun Sep 13 18:15:24 1992 -- Marc Andreessen
  82. ;;;   Added brite::submit-bug-report to menu.
  83. ;;; Mon Sep 14 03:28:55 1992 -- Marc Andreessen
  84. ;;;   Make Lightbrite friendly to other extents in buffer.
  85. ;;;   Don't highlight-on-find rmail-mode buffers.
  86. ;;;
  87. ;;; INTRODUCTION TO HIGHLIGHTING
  88. ;;;
  89. ;;; Lightbrite takes advantage of one the major extensions to GNU Emacs in
  90. ;;; both Epoch and Lucid Emacs: the concept of "zones" (or "extents").  A
  91. ;;; zone is an arbitrary region of a buffer that may have properties
  92. ;;; distinct from other regions in the buffer; such properties include
  93. ;;; foreground and background color, underlining, font, and read-only
  94. ;;; status.  Programs written in Emacs Lisp, like Lightbrite, can direct
  95. ;;; Epoch and Lucid Emacs to create any number of zones in a buffer based
  96. ;;; on whatever criteria the program sees fit to use.
  97. ;;; 
  98. ;;; Lightbrite is called a "highlighting" package because it highlights
  99. ;;; regions of buffers based on the buffer's syntactic content.  An
  100. ;;; example of a highlighted buffer would be a buffer of C code in which
  101. ;;; all `switch' statements are displayed in green and all `break'
  102. ;;; statements are displayed in red, while the normal text color is white
  103. ;;; and comments are displayed in blue.  To achieve the highlighted
  104. ;;; effect, a zone is created for each region of text Lightbright wants to
  105. ;;; highlight.
  106. ;;; 
  107. ;;; Zones are specified by their beginning and ending points in the
  108. ;;; buffer.  Editing actions that take place in or near zones will affect
  109. ;;; the zones themselves.  For example, inserting text in the middle of a
  110. ;;; zone expands the size of the zone, by moving the ending point further
  111. ;;; out.  Because of these and other reasons, it is often necessary to
  112. ;;; refresh a buffer's highlighting; this involves erasing existing zones
  113. ;;; and re-highlighting.  Lightbrite provides an easy way to do this; the
  114. ;;; key sequence 'C-z SPC' re-highlights the current screen.
  115. ;;; 
  116. ;;; Lightbrite also supports a preliminary implementation of an "instant
  117. ;;; highlighting" system, wherein your text is highlighted as you type.
  118. ;;; Theoretically, this should lead to completely transparent, always
  119. ;;; up-to-date highlighting; unfortunately, the current implementation is
  120. ;;; not quite that waterproof, but it is functional.
  121. ;;;
  122. ;;; BASIC USAGE
  123. ;;;
  124. ;;; Lightbrite requires either Epoch (4.2 or higher) or Lucid Emacs
  125. ;;; (19.3 or higher).  It will not work with vanilla GNU Emacs 18.x.
  126. ;;;
  127. ;;; To use lightbrite, install it and syntax-decode.el in a directory in
  128. ;;; your Elisp search path and byte-compile both files; then put:
  129. ;;;
  130. ;;; (require 'lightbrite)
  131. ;;;
  132. ;;; in your .emacs file.  Lightbrite automatically adapts itself to
  133. ;;; either Epoch or Lucid Emacs when it is loaded.  (If you plan to
  134. ;;; use the same .elc files with both Epoch and Lucid Emacs, you should
  135. ;;; byte-compile them with Epoch rather than Lucid Emacs.)
  136. ;;;
  137. ;;; Lightbrite assumes a dark (black) background.  If you have a
  138. ;;; light (white) background, you'll probably want to put the following
  139. ;;; lines in your .emacs file prior to (require 'lightbrite):
  140. ;;;
  141. ;;; (defvar brite::comment-styles '(("foreground" . "cadetblue"))
  142. ;;;   "*Style specification list for comment style.")
  143. ;;; (defvar brite::mild-styles '(("foreground" . "grey70"))
  144. ;;;   "*Style specification list for mild style.")
  145. ;;; (defvar brite::striking-styles '(("foreground"  . "royalblue"))
  146. ;;;   "*Style specification list for striking style.")
  147. ;;; (defvar brite::intense-styles '(("foreground" . "purple"))
  148. ;;;   "*Style specification list for intense style.")
  149. ;;; (defvar brite::blazing-styles '(("foreground" . "orangered"))
  150. ;;;   "*Style specification list for blazing style.")
  151. ;;; (defvar brite::hot-styles '(("foreground" . "darkgoldenrod"))
  152. ;;;   "*Style specification list for hot style.")
  153. ;;; (defvar brite::earnest-styles '(("foreground" . "darkorchid"))
  154. ;;;   "*Style specification list for earnest style.")
  155. ;;;
  156. ;;; By default, visiting a file will enable lightbrite-mode in the new
  157. ;;; buffer.  Then, when you have made changes to part of a file, press
  158. ;;; 'C-z SPC' to re-highlight the visible window.
  159. ;;;
  160. ;;; If you're using Lucid Emacs, Lightbrite will also set up a menubar
  161. ;;; entry for itself; from this menu (entitled "Light") you will be
  162. ;;; able to do most interesting Lightbrite-related actions.
  163. ;;;
  164. ;;; ADVANCED USAGE
  165. ;;;
  166. ;;; Lightbrite usually takes a while to highlight a large file.  To
  167. ;;; avoid total catastrophe when loading a huge file, Lightbrite
  168. ;;; allows you to set thresholds on buffer size for the two types of
  169. ;;; highlighting: comment highlighting and touchup (everything but
  170. ;;; comments) highlighting.  See the variables
  171. ;;; 'brite::comment-threshold' and 'brite::touchup-threshold' for more
  172. ;;; information.  By default, the thresholds are given reasonable
  173. ;;; values for a moderately fast RISC workstation; you may want to
  174. ;;; adjust them up or down based on your platform's speed.
  175. ;;;
  176. ;;; If you're typing along and you suddenly exceed one of the two
  177. ;;; thresholds, Lightbrite will stop highlighting in that manner
  178. ;;; (comment or touchup).  If you want to raise the threshold enough
  179. ;;; to continue editing the current file without having highlighting
  180. ;;; disappear, you can press 'C-z T' or 'C-z C' to "balloon" the
  181. ;;; touchup and comment highlighting thresholds respectively; the
  182. ;;; values are raised to the size of the buffer plus an extra 1000
  183. ;;; characters.
  184. ;;;
  185. ;;; Instant highlighting can be enabled on a per-buffer basis by
  186. ;;; pressing 'C-z a'.  When active, instant highlighting causes the
  187. ;;; visible window to be re-highlighted every 'brite::change-interval'
  188. ;;; changes to the buffer's text.  You may notice strange effects when
  189. ;;; using instant highlight.  For example, if the window is
  190. ;;; re-highlighted while you're typing in the middle of a string (with
  191. ;;; no closing quote), the Emacs expression parsing mechanism that
  192. ;;; Lightbrite uses will assume that text after point is in the
  193. ;;; current string when it really isn't, and that text will be
  194. ;;; highlighted (incorrectly) accordingly.
  195. ;;;
  196. ;;; Lightbrite has other, less interesting, features; they can be
  197. ;;; discovered by trolling through the code.
  198. ;;;
  199. ;;; KNOWN PROBLEMS
  200. ;;;
  201. ;;; Jamie Zawinski's mail-abbrevs package doesn't work well with
  202. ;;; Lightbrite at the moment.  A hacked version of mail-abbrevs that
  203. ;;; does work can be found on ftp.ncsa.uiuc.edu in
  204. ;;; /outgoing/marca/epoch.
  205. ;;;
  206. ;;; FUTURE ENHANCEMENTS
  207. ;;;
  208. ;;; Use map-extents and related Epoch primitive (probably won't
  209. ;;; enhance performance much, but still a good idea).
  210. ;;;
  211. ;;; Link in with Lucid Emacs font-lock primitives.
  212. ;;;
  213. ;;; Eventually, Lightbrite will provide extensive customization
  214. ;;; capabilities and additional functionality that I just don't have
  215. ;;; time to implement right now.  Ideas and code are more than
  216. ;;; welcome.
  217. ;;;
  218. ;;; ACKNOWLEDGEMENTS
  219. ;;;
  220. ;;; Code and ideas stolen from Ken Wood, Heinz W. Schmidt, Paul
  221. ;;; Nakada, Dan LaLiberte, Lynn Slater, Barry Warsaw, Michael
  222. ;;; Lamoureux, Simon Marshall, Jerry Graves, and others.
  223. ;;;
  224. ;;; LCD Archive Entry:
  225. ;;; lightbrite|Marc Andreessen|marca@ncsa.uiuc.edu
  226. ;;; |Source highlighting for Epoch and Lucid Emacs
  227. ;;; |13 Sep 1992|1.1.2|
  228.  
  229. ;;; ----------------------------- Start 'er up. ------------------------------
  230.  
  231. (require 'syntax-decode)
  232.  
  233. (defconst brite::version "Version 1.1.2" "Lightbrite version string.")
  234.  
  235. ;; Check for Epoch.
  236. (defvar brite::running-epoch (boundp 'epoch::version)
  237.   "Non-nil if running Epoch.")
  238.  
  239. ;; Check for Lucid Emacs.
  240. (defvar brite::running-lemacs (string-match "Lucid" emacs-version)
  241.   "Non-nil if running Lucid Emacs.")
  242.  
  243. ;;; ------------------- Lightbrite zone/style manipulation -------------------
  244.  
  245. ;; These functions provide zone/style (extent/face) manipulation
  246. ;; functionality for both Epoch and Lucid Emacs.
  247.  
  248. (cond
  249.  ;; LUCID EMACS LAYER
  250.  (brite::running-lemacs
  251.   (defun brite::zone-at (p)
  252.     "Do extent-at."
  253.     (extent-at p))
  254.   (defun brite::add-zone (beginning end sty)
  255.     "Do make-extent and set-extent-face; set extent data to 'lightbrite."
  256.     (let ((extent (make-extent beginning end)))
  257.       (set-extent-face extent sty)
  258.       (set-extent-data extent 'lightbrite)))
  259.   (defun brite::zone-list (&optional buffer)
  260.     "Build a list of extents using next-extent."
  261.     (let ((l nil) ext)
  262.       ;; Grab the first extent in the buffer.
  263.       (if buffer
  264.           (setq ext (next-extent buffer))
  265.         (setq ext (next-extent (current-buffer))))
  266.       ;; Build a list of extents until we run out.
  267.       (while ext
  268.         (setq l (cons ext l))
  269.         (setq ext (next-extent ext)))
  270.       l))
  271.   (defun brite::clear-zones (&optional buffer)
  272.     "Clear extents that we created in BUFFER with delete-extent."
  273.     (let ((l (brite::zone-list buffer)))
  274.       (while (car l)
  275.         ;; Make sure it's ours before we wipe it out.
  276.         (if (eq 'lightbrite (extent-data (car l)))
  277.             (delete-extent (car l)))
  278.         (setq l (cdr l)))))
  279.   (defun brite::epoch-version ()
  280.     "Fake variable epoch::version."
  281.     "Epoch?  We don' need no steenking Epoch!")
  282.   (defun brite::clear-zones-in-region (start end)
  283.     "Prune zones in region from START and END from zones in buffer."
  284.     (let ((foo-list (brite::zone-list)))
  285.       (while foo-list
  286.         (let* ((foo (car foo-list)) (foo-start (extent-start-position foo)))
  287.           ;; We remove zones that start inside this region, if we created them.
  288.           (if (and (eq 'lightbrite (extent-data foo)) 
  289.                    (>= foo-start start) (<= foo-start end))
  290.               (delete-extent foo))
  291.           (setq foo-list (cdr foo-list))))))
  292.   (defvar brite::original-pointer nil "Original screen pointer.")
  293.   (defun brite::set-wait-pointer ()
  294.     "Set pointer to wait state."
  295.     (let ((screen (selected-screen)))
  296.       (setq brite::original-pointer 
  297.             (cdr (assoc 'pointer (screen-parameters screen))))
  298.       (x-set-screen-pointer screen x-gc-pointer-shape)
  299.       (sit-for 0)))
  300.   (defun brite::set-ready-pointer ()
  301.     "Set pointer to ready state."
  302.     (let ((screen (selected-screen)))
  303.       (x-set-screen-pointer screen brite::original-pointer)
  304.       (sit-for 0))))
  305.  
  306.  ;; EPOCH LAYER.
  307.  (brite::running-epoch
  308.   (defun brite::zone-at (p)
  309.     "Do epoch::zone-at."
  310.     (epoch::zone-at p))
  311.   (defun brite::add-zone (beginning end sty)
  312.     "Do epoch::add-zone; set zone data to 'lightbrite."
  313.     (let ((zone (epoch::add-zone beginning end sty)))
  314.       (epoch::set-zone-data zone 'lightbrite)))
  315.   (defun brite::zone-list (&optional buffer)
  316.     "Do epoch::zone-list."
  317.     (epoch::zone-list buffer))
  318.   (defun brite::clear-zones (&optional buffer)
  319.     "Clear extents that we created in BUFFER with epoch::delete-zone."
  320.     (let ((l (brite::zone-list buffer)))
  321.       (while (car l)
  322.         ;; Make sure it's ours before we wipe it out.
  323.         (if (eq 'lightbrite (epoch::zone-data (car l)))
  324.             (epoch::delete-zone (car l)))
  325.         (setq l (cdr l)))))
  326.   (defun brite::epoch-version ()
  327.     "Look at epoch::version"
  328.     epoch::version)
  329.   (defun brite::clear-zones-in-region (start end)
  330.     "Prune zones in region from START and END from zones in buffer."
  331.     (catch 'brite::done-clearing-zones
  332.       (let ((foo-list (brite::zone-list)))
  333.         (while foo-list
  334.           (let* ((foo (car foo-list)) (foo-start (epoch::zone-start foo)))
  335.             ;; We remove zones that start inside this region.
  336.             (if (and (eq 'lightbrite (epoch::zone-data foo))
  337.                      (>= foo-start start) (<= foo-start end))
  338.                 (epoch::delete-zone foo))
  339.             ;; If the zone starts after the end of this region,
  340.             ;; we're done.
  341.             (if (> foo-start end)
  342.                 (throw 'brite::done-clearing-zones t)))
  343.           (setq foo-list (cdr foo-list))))))
  344.   (defvar brite::original-pointer nil "Original screen pointer.")
  345.   (defun brite::set-wait-pointer ()
  346.     "Set pointer to wait state."
  347.     (setq brite::original-pointer (epoch::cursor-glyph))
  348.     (epoch::cursor-glyph 150)
  349.     (sit-for 0))
  350.   (defun brite::set-ready-pointer ()
  351.     "Set pointer to ready state."
  352.     (epoch::cursor-glyph brite::original-pointer)
  353.     (sit-for 0)))
  354.  
  355.  ;; Vanilla Emacs.
  356.  (t
  357.   (error "Lightbrite requires Epoch or Lucid Emacs.")))
  358.  
  359. ;;; --------------------------- brite::make-style ----------------------------
  360.  
  361. (defun brite::make-style (styles name)
  362.   "Make a new style with STYLES with name NAME.
  363. Each component of STYLES looks like (\"style\" . \"value\").
  364.  
  365. For example, to set the foreground color to red and the font to 9x15bold, use
  366.         '((\"foreground\" . \"red\") (\"font\" . \"9x15bold\"))
  367.  
  368. The \"style\" is in fact concatenated onto \"set-style-\" for Epoch or
  369. \"set-face-\" for Lucid Emacs, and this function is called to set the
  370. style value.
  371.  
  372. The different Epoch styles are background, background-stipple,
  373. cursor-background, cursor-foreground, cursor-stipple, font,
  374. foreground, pixmap, stipple and underline.  See the corresponding
  375. set-style-* functions for their effects.
  376.  
  377. The different Lucid Emacs styles are background, background-pixmap,
  378. font, foreground, or underline-p (Lightbrite also understands style).
  379. (Currently Lucid Emacs can only underline in the current foreground
  380. color.)  See the corresponding set-face-* functions for their
  381. effects."
  382.   (let ((new-style 
  383.          (cond
  384.           (brite::running-lemacs
  385.            (make-face name))
  386.           (brite::running-epoch
  387.            (make-style)))))
  388.     (while styles
  389.       (cond
  390.        (brite::running-lemacs
  391.         (funcall (intern
  392.           (concat "set-face-" 
  393.                   (if (string= (car (car styles)) "underline")
  394.                       "underline-p"
  395.                     (car (car styles)))))
  396.          new-style (cdr (car styles))))
  397.        (brite::running-epoch
  398.         (funcall  (intern 
  399.           (concat "set-style-" (car (car styles))))
  400.          new-style (cdr (car styles)))))
  401.       (setq styles (cdr styles)))
  402.     new-style))
  403.  
  404. ;;; --------------------------------------------------------------------------
  405. ;;; ------------------------------- VARIABLES --------------------------------
  406. ;;; --------------------------------------------------------------------------
  407.  
  408. ;;; ------------------------- buffer-local variables -------------------------
  409.  
  410. ;; Users can setq the *-default variables before loading this file
  411. ;; to affect defaults for buffer-local variables.
  412.  
  413. ;; Define the default values.
  414. (defvar brite::comment-highlight-on-default t
  415.   "*Default value for brite::comment-highlight-on.")
  416. (defvar brite::touchup-highlight-on-default t
  417.   "*Default value for brite::touchup-highlight-on.")
  418. (defvar brite::touchup-check-string-default t
  419.   "*Default value for brite::touchup-check-string.")
  420. (defvar brite::touchup-check-zone-default t
  421.   "*Default value for brite::touchup-check-zone.")
  422. (defvar brite::highlight-on-write-default nil
  423.   "*Default value for brite::highlight-on-write.")
  424.  
  425. ;; Define the buffer-local variables.
  426. (defvar brite::comment-highlight-on nil
  427.   "T if comments should be highlighted in this buffer; NIL otherwise.")
  428. (defvar brite::touchup-highlight-on nil
  429.   "T if syntax-directed touchup should be done in this buffer; NIL otherwise.")
  430. (defvar brite::touchup-check-string nil
  431.   "T if in-string checking should be done in this buffer; NIL otherwise.")
  432. (defvar brite::touchup-check-zone nil
  433.   "T if in-zone checking should be done in this buffer; NIL otherwise.")
  434. (defvar brite::highlight-on-write nil
  435.   "T if this buffer should be re-highlighted on write; NIL otherwise.")
  436. (defvar brite::instant-highlight-on nil 
  437.   "Flag for instant highlighting.  Call brite::toggle-instant-highlight-on
  438. to turn instant highlighting on and off.")
  439.  
  440. ;; Make the buffer-local variables buffer-local.
  441. (make-variable-buffer-local 'brite::comment-highlight-on)
  442. (make-variable-buffer-local 'brite::touchup-highlight-on)
  443. (make-variable-buffer-local 'brite::touchup-check-string)
  444. (make-variable-buffer-local 'brite::touchup-zone-string)
  445. (make-variable-buffer-local 'brite::highlight-on-write)
  446. (make-variable-buffer-local 'brite::instant-highlight-on)
  447.  
  448. ;; Set the defaults.
  449. (setq-default brite::comment-highlight-on brite::comment-highlight-on-default)
  450. (setq-default brite::touchup-highlight-on brite::touchup-highlight-on-default)
  451. (setq-default brite::touchup-check-string brite::touchup-check-string-default)
  452. (setq-default brite::touchup-check-zone brite::touchup-check-zone-default)
  453. (setq-default brite::highlight-on-write brite::highlight-on-write-default)
  454. (setq-default brite::instant-highlight-on nil)
  455.  
  456. ;;; --------------------------- control variables ----------------------------
  457.  
  458. ;; Users can setq these before loading this file.
  459.  
  460. (defvar brite::highlight-on-find t
  461.   "*T if we should highlight each new file when it's first loaded.")
  462.  
  463. ;; Lucid Emacs does extents more efficiently than Epoch does zones,
  464. ;; so make thresholds respecitvely higher.
  465. (defvar brite::comment-threshold (if brite::running-lemacs 200000 100000)
  466.   "*Integer for maximum size of file for which comments are highlighted,
  467. or NIL if comments should always be highlighted.")
  468. (defvar brite::touchup-threshold (if brite::running-lemacs 75000 30000)
  469.   "*Integer for maximum size of file for which touchup highlighting is done,
  470. or NIL if touchup highlighting should always be done.")
  471.  
  472. ;; Setting this value small really makes it look good, but gives
  473. ;; quite a performance hit.
  474. (defvar brite::change-interval 16
  475.   "*Number of changes between line highlighting, when after-change-function
  476. is activated.")
  477.  
  478. (defvar brite::area-extent 160
  479.   "*Half of the size of a local area.")
  480.  
  481. ;;; --------------------------------- hooks ----------------------------------
  482.  
  483. (defvar brite::mode-hook nil 
  484.   "*Hooks to run when entering lightbrite-mode.")
  485. (defvar brite::mode-exit-hook nil 
  486.   "*Hooks to run when leaving lightbrite-mode.")
  487.  
  488. ;;; --------------------------- colors and styles ----------------------------
  489.  
  490. ;; Users can set either brite::*-styles to a list of style alists,
  491. ;; or brite*-style directly to a desired style.
  492.  
  493. ;; The following colors were chosen for a black background.  Suggested
  494. ;; foreground colors are wheat, grey80-grey90, #ffa07a, #ffaf7f,
  495. ;; #ff7f24, and #efafff.  An alternate set of colors for a white
  496. ;; background is upstairs in the initial comments.  If you come up
  497. ;; with a nice set of fg/bg/highlight colors, send them to me.
  498.  
  499. (defvar brite::comment-styles '(("foreground" . "#7f9fcf"))
  500.   "*Style specification list for comment style.")
  501. (defvar brite::mild-styles '(("foreground" . "red"))
  502.   "*Style specification list for mild style.")
  503. (defvar brite::striking-styles '(("foreground" . "hot pink"))
  504.   "*Style specification list for striking style.")
  505. (defvar brite::intense-styles '(("foreground" . "yellow"))
  506.   "*Style specification list for intense style.")
  507. (defvar brite::blazing-styles '(("foreground" . "green"))
  508.   "*Style specification list for blazing style.")
  509. (defvar brite::hot-styles '(("foreground" . "magenta"))
  510.   "*Style specification list for hot style.")
  511. (defvar brite::earnest-styles '(("foreground" . "alice blue"))
  512.   "*Style specification list for earnest style.")
  513.  
  514. (defvar brite::comment-style
  515.   (brite::make-style brite::comment-styles 'brite::comment-style)
  516.   "*Style used to highlight comments.")
  517. (defvar brite::mild-style 
  518.   (brite::make-style brite::mild-styles 'brite::mild-style)
  519.   "*Style used to highlight mildly.")
  520. (defvar brite::hot-style 
  521.   (brite::make-style brite::hot-styles 'brite::hot-style)
  522.   "*Style used to highlight hotly.")
  523. (defvar brite::earnest-style 
  524.   (brite::make-style brite::earnest-styles 'brite::earnest-style)
  525.   "*Style used to highlight in earnest.")
  526. (defvar brite::intense-style 
  527.   (brite::make-style brite::intense-styles 'brite::intense-style)
  528.   "*Style used to highlight intensely.")
  529. (defvar brite::blazing-style 
  530.   (brite::make-style brite::blazing-styles 'brite::blazing-style)
  531.   "*Style used to highlight blazingly.")
  532. (defvar brite::striking-style 
  533.   (brite::make-style brite::striking-styles 'brite::striking-style)
  534.   "*Style used to highlight strikingly.")
  535.  
  536. ;;; --------------------------------------------------------------------------
  537. ;;; --------------------------- internal variables ---------------------------
  538. ;;; --------------------------------------------------------------------------
  539.  
  540. ;; You shouldn't tamper with these.  Your firstborn will be sacrificed
  541. ;; to the Great Eternal Lisp Engine if you do.
  542.  
  543. (defvar brite::highlight-done nil "Flag for highlighting done once here.")
  544. (make-variable-buffer-local 'brite::highlight-done)
  545. (setq-default brite::highlight-done nil)
  546.  
  547. (defvar brite::beginning-point 0 "Starting point for regexp searches.")
  548. (defvar brite::ending-point 0 "Ending point for regexp searches.")
  549.  
  550. (defvar brite::change-counter 0 "Internal counter to track number of changes.")
  551.  
  552. (defvar brite::diagnostics-on nil
  553.   "*If T, print diagnostics to minibuffer as appropriate.")
  554.  
  555. ;; When enabled, infinite loop is hit for some patterns.  FIX IT, STUPID.
  556. (defvar brite::clip-surrounding-whitespace nil
  557.   "T if we should never highlight surrounding whitespace; NIL otherwise.
  558. Current, this should not be set to T.")
  559.  
  560. ;;; --------------------------------------------------------------------------
  561. ;;; ------------------------- MISCELLANEOUS ROUTINES -------------------------
  562. ;;; --------------------------------------------------------------------------
  563.  
  564. ;;; ---------------------------- brite::in-zone-p ----------------------------
  565.  
  566. (defun brite::in-zone-p (point)
  567.   "T if POINT is in a zone, NIL otherwise."
  568.   (if (brite::zone-at point) t nil))
  569.  
  570. ;;; ----------------------- brite::in-quoted-string-p ------------------------
  571.  
  572. (defun brite::in-quoted-string-p (point)
  573.   "Check for POINT in quoted string; return T if so, NIL if not."
  574.   (save-excursion
  575.     (beginning-of-defun)
  576.     (if (nth 3 (parse-partial-sexp (point) point)) t nil)))
  577.  
  578. ;;; ------------------------- brite::regexp-touchup --------------------------
  579.  
  580. ;; Ideas for a Mocklisp defun:
  581. ;;   zonify-pattern START END STYLE INTERNAL-REGEXP START-REGEXP END-REGEXP
  582. ;;     Scan current buffer from 'START' to 'END' and locate strings
  583. ;;     that match given REGEXP patterns; when found, add a zone with
  584. ;;     style STYLE.
  585.  
  586. (defun brite::regexp-touchup (regexp sty &optional everytime)
  587.   "Highlight all matches of REGEXP in a given style.  Second arg STY 
  588. is a style.  Optional third arg EVERYTIME indicates that pattern should 
  589. always be highlighted, even when in a zone or string."
  590.   (let (brite::beginning brite::end (case-fold-search nil))
  591.     (save-excursion
  592.       (goto-char brite::beginning-point)
  593.       ;; Loop through all matches in this buffer.
  594.       (while (re-search-forward regexp brite::ending-point t)
  595.         ;; Preserve values of begin/end from search.
  596.         ;; Now we skip whitespace on either side of a match
  597.         ;; as well, by searching forward from start and
  598.         ;; backward from end, if brite::clip-surrounding-whitespace
  599.         ;; is t.
  600.         (cond
  601.          (brite::clip-surrounding-whitespace
  602.           (setq brite::end (match-end 0)
  603.                 brite::beginning (progn
  604.                                    (goto-char (match-beginning 0))
  605.                                    (re-search-forward "[^\t ]")
  606.                                    (match-beginning 0))
  607.                 brite::end (progn
  608.                              (goto-char brite::end)
  609.                              (re-search-backward "[^\t ]")
  610.                              (match-end 0))))
  611.          (t
  612.           (setq brite::beginning (match-beginning 0)
  613.                 brite::end (match-end 0))))
  614.         ;; If everytime flag not set, and brite::touchup-check-zone
  615.         ;; not set, check for in-zone-p.
  616.         (if (or everytime (not brite::touchup-check-zone) 
  617.                 (not (brite::in-zone-p brite::beginning)))
  618.             ;; Either everytime is set, or we're not checking
  619.             ;; strings, or we're not in a string.
  620.             (if (or everytime
  621.                     (not brite::touchup-check-string) 
  622.                     (not (brite::in-quoted-string-p brite::beginning)))
  623.                 (brite::add-zone brite::beginning brite::end sty)))))))
  624.  
  625. ;;; --------------------- convenience touchup functions ----------------------
  626.  
  627. (defun brite::regexp-touchup-mild (regexp)
  628.   "Touchup REGEXP mildly."
  629.   (brite::regexp-touchup regexp brite::mild-style))
  630. (defun brite::regexp-touchup-hot (regexp)
  631.   "Touchup REGEXP hotly."
  632.   (brite::regexp-touchup regexp brite::hot-style))
  633. (defun brite::regexp-touchup-earnest (regexp)
  634.   "Touchup REGEXP in earnest."
  635.   (brite::regexp-touchup regexp brite::earnest-style))
  636. (defun brite::regexp-touchup-intense (regexp)
  637.   "Touchup REGEXP intensely."
  638.   (brite::regexp-touchup regexp brite::intense-style))
  639. (defun brite::regexp-touchup-intense-always (regexp)
  640.   "Touchup REGEXP intensely always."
  641.   (brite::regexp-touchup regexp brite::intense-style t))
  642. (defun brite::regexp-touchup-blazing (regexp)
  643.   "Touchup REGEXP blazingly."
  644.   (brite::regexp-touchup regexp brite::blazing-style nil))
  645. (defun brite::regexp-touchup-striking (regexp)
  646.   "Touchup REGEXP strikingly."
  647.   (brite::regexp-touchup regexp brite::striking-style nil))
  648. (defun brite::regexp-touchup-comment (regexp)
  649.   "Touchup REGEXP as a comment."
  650.   (brite::regexp-touchup regexp brite::comment-style nil))
  651.  
  652. ;;; --------------------------------------------------------------------------
  653. ;;; -------------------------- COMMENT HIGHLIGHTING --------------------------
  654. ;;; --------------------------------------------------------------------------
  655.  
  656. ;;; ----------------------- brite::highlight-comments ------------------------
  657.  
  658. ;; This function is stolen almost verbatim from Ken Wood's package.
  659. (defun brite::highlight-comments ()
  660.   "Highlight all comments in a buffer if the buffer's size does not
  661. exceed brite::comment-threshold."
  662.   ;; Silently do nothing if there are no regexps to search with
  663.   ;; or if the buffer is too large to highlight.
  664.   (if (and syndecode-comment-start-regexp syndecode-comment-end-regexp
  665.            brite::comment-threshold 
  666.            (< (buffer-size) brite::comment-threshold))
  667.       (let ((starting-point brite::beginning-point)
  668.             comment-start-begin comment-start-end comment-end-end)
  669.         (save-excursion
  670.           (goto-char brite::beginning-point)
  671.           ;; Algorithm is: search for start of a comment,
  672.           ;; make sure it really is a comment; then highlight
  673.           ;; from there to the end of the comment.
  674.           ;; First, find a comment-start sequence.
  675.           (while (re-search-forward syndecode-comment-start-regexp
  676.                                     brite::ending-point t)
  677.             (progn
  678.               (setq comment-start-begin (match-beginning 0)
  679.                     comment-start-end (match-end 0))
  680.               ;; Check that the comment start sequence really does
  681.               ;; indicate the start of a comment, and that it's not
  682.               ;; inside a string etc.
  683.               (if (nth 4 (parse-partial-sexp starting-point comment-start-end))
  684.                   ;; Yes, this is really the start of a comment
  685.                   (progn
  686.                     (goto-char comment-start-end)
  687.                     ;; Find the end of the comment by searching
  688.                     ;; for a comment terminating sequence.
  689.                     ;; Second arg was changed to brite::ending-point
  690.                     ;; to keep emacs from complaining during per-line
  691.                     ;; highlighting.
  692.                     (re-search-forward syndecode-comment-end-regexp
  693.                                        brite::ending-point t)
  694.                     (setq comment-end-end (point))
  695.                     ;; Highlight the comment
  696.                     (brite::add-zone comment-start-begin comment-end-end
  697.                                     brite::comment-style)
  698.                     ;; Start the next syntax parse at the end of the
  699.                     ;; comment just processed.
  700.                     (setq starting-point comment-end-end)))))))))
  701.  
  702. ;;; --------------------------------------------------------------------------
  703. ;;; -------------------------- TOUCHUP HIGHLIGHTING --------------------------
  704. ;;; --------------------------------------------------------------------------
  705.  
  706. ;;; ------------------------- brite::true-mode-name --------------------------
  707.  
  708. ;; Author: Lynn Slater (lrs@indetech.com).
  709. (defun brite::true-mode-name ()
  710.   "Returns the name of the mode in such a form that the mode may be
  711. re-established by calling the function named by appending '-name' to
  712. this string.  This differs from the variable called mode-name in that
  713. this is guaranteed to work while the values held by the variable may
  714. have embedded spaces or other junk."
  715.   (let ((major-mode-name (symbol-name major-mode)))
  716.     (substring major-mode-name 0
  717.                (or (string-match "-mode" major-mode-name)
  718.                    (length major-mode-name)))))
  719.  
  720. ;;; ------------------------ brite::do-buffer-touchup ------------------------
  721.  
  722. ;; Datatype must be preceded by whitespace, open paren, or open brace.
  723. (defvar brite::c-datatype-prefix "[ \n\t({]")
  724. ;; Datatype must be followed by whitespace, close paren, or *.
  725. (defvar brite::c-datatype-suffix "[ \n\t)*]")
  726.  
  727. ;; Keyword must be preceded by whitespace or open brace.
  728. (defvar brite::c-keyword-prefix "[ \n\t{]")
  729. ;; Keyword must be followed by whitespace, semicolon, or open paren.
  730. (defvar brite::c-keyword-suffix "[ \n\t;(]")
  731.  
  732. (defvar brite::c-directives
  733.   "\\(#endif\\|#else\\|#ifdef\\|#ifndef\\|#if\\|NULL\\)")
  734. (defvar brite::c-defines
  735.   "\\(#define\\|#include\\|#undef\\)")
  736. (defvar brite::c-dataglobs 
  737.   "\\(typedef\\|enum\\|struct\\|union\\|[ \t]case.*:\\|[ \t]default:\\)")
  738. (defvar brite::c-datatypes
  739.   (concat brite::c-datatype-prefix 
  740.           "\\(int\\|float\\|Float\\|char\\|double\\|short\\|long\\|void\\)" 
  741.           brite::c-datatype-suffix))
  742. (defvar brite::c-data-attributes
  743.   "\\(unsigned\\|extern\\|static\\|public\\|private\\)")
  744. (defvar brite::c-flagged-keywords
  745.   (concat brite::c-keyword-prefix  "\\(return\\|exit\\|assert\\)"
  746.           brite::c-keyword-suffix))
  747.  
  748. ;; Keyword must be preceded by whitespace or open brace.
  749. (defvar brite::perl-keyword-prefix "[ \n\t{]")
  750. ;; Keyword must be followed by whitespace, semicolon, or open paren.
  751. (defvar brite::perl-keyword-suffix "[ \n\t;(]")
  752.  
  753. (defvar brite::perl-directives
  754.   "\\(#endif\\|#else\\|#ifdef\\|#ifndef\\|#if\\|#include\\|#define\\|#undef\\)")
  755. (defvar brite::perl-flow
  756.   (concat brite::perl-keyword-prefix 
  757.           "\\(if\\|until\\|while\\|elsif\\|else\\|unless\\|for\\|foreach\\|continue\\|exit\\|die\\|last\\|goto\\|next\\|redo\\|return\\)" 
  758.           brite::perl-keyword-suffix))
  759.  
  760. ;; In the future this will be in table format and facilities will be
  761. ;; provided for extending both the modes supported and the regexp's
  762. ;; used.
  763. (defun brite::do-buffer-touchup ()
  764.   "Based on current mode, do series of calls to brite::regexp-touchup routines
  765. to highlight certain regex patterns certain colors, if the buffer's size
  766. is less than brite::touchup-threshold."
  767.   ;; Allow touchup-threshold to be nil also.
  768.   (if (or (null brite::touchup-threshold)
  769.           (< (buffer-size) brite::touchup-threshold))
  770.       (cond
  771.        ;;-------------------------------------------------------------------
  772.        ((string-equal (brite::true-mode-name) "text")
  773.         ;; String between sets of three dashes is a section header.
  774.         ;; Three equal-signs marks a subsection.
  775.         ;; '-->' and 'o' are 'item' indicators.
  776.         ;; String 'Justification:' is always red;
  777.         ;; at the moment we flag comments (in shell scripts,
  778.         ;; etc) in red also.
  779.         ;; Also 1> 2> etc are red, as are (1) (2) etc.
  780.         ;; UNRESOLVED/FUTURE/CORRECTION/TODO should be flagged.
  781.         (brite::regexp-touchup-hot "\\( ===\\|=== \\)")
  782.         ;; clip-surrounding-whitespace really does not like ^o[ \n\t]. WHY?
  783.         ;; (brite::regexp-touchup-earnest "\\(-?-->\\|[ \n\t]o[ \t]\\|^o[ \n\t]\\)")
  784.         (brite::regexp-touchup-earnest "\\(-?-->\\|[ \n\t]o[ \t]\\|^@[A-Z]+\\)")
  785.         (brite::regexp-touchup-mild 
  786.          "\\(Justification: \\|^[0-9]+>\\|[ \t]*[0-9]+>\\|^([0-9]+)\\|[ \t]*([0-9]+)\\|-----[-]*\\)")
  787.         (brite::regexp-touchup-comment "#.*")
  788.         (brite::regexp-touchup-intense 
  789.          "\\(UNRESOLVED\\|FUTURE\\|CORRECTION\\|T[Oo][ ]?D[Oo]\\|--- .* ---\\)")
  790.         )
  791.        ;;-------------------------------------------------------------------
  792.        ((string-equal (brite::true-mode-name) "rmail")
  793.         ;; These don't have beginning-of-line rules ("^From" etc.) because
  794.         ;; I like them highlighted in messages included in other messages.
  795.         (brite::regexp-touchup-intense "From:.*")
  796.         (brite::regexp-touchup-hot "Date:.*")
  797.         (brite::regexp-touchup-earnest "Subject:.*"))
  798.        ;;-------------------------------------------------------------------
  799.        ((string-equal (brite::true-mode-name) "rmail-summary")
  800.         ;; If this is a message we've sent, highlight the receiver.
  801.         (brite::regexp-touchup-hot " to: [^ ]*")
  802.         ;; Highlight the date column.
  803.         (brite::regexp-touchup-earnest " [ 0-9][0-9]-[A-Za-z][A-Za-z][A-Za-z] "))
  804.        ;;-------------------------------------------------------------------
  805.        ((string-equal (brite::true-mode-name) "mail")
  806.         (brite::regexp-touchup-mild "--text follows this line--")
  807.         (brite::regexp-touchup-earnest "Subject:.*")
  808.         (brite::regexp-touchup-hot "\\(^To:.*\\|^CC:.*\\)")
  809.         (brite::regexp-touchup-striking "^BCC:.*")
  810.         (brite::regexp-touchup-blazing "^In\-reply\-to:.*"))
  811.        ;;-------------------------------------------------------------------
  812.        ((string-equal (brite::true-mode-name) "texinfo")
  813.         (brite::regexp-touchup-intense 
  814.          "\\(^@node[^,]*\\|^@table\\|@itemize\\|^@end \\(table\\|itemize\\)\\)")
  815.         (brite::regexp-touchup-striking 
  816.          "\\(^@menu\\|^@item\\|^@defun\\|^@defvar\\|^@example\\|^@end \\(menu\\|defun\\|defvar\\|example\\)\\)")
  817.         (brite::regexp-touchup-blazing 
  818.          "\\(^@chapter.*\\|^@section.*\\|^@subs.*\\|^@unnumbered\\|^@appendix\\)")
  819.         ;; Code fragments and keystrokes in earnest.
  820.         (brite::regexp-touchup-earnest 
  821.          "\\(@code{[^}]*}\\|\@kbd{[^}]*}\\|@file{[^}]*}\\)")
  822.         ;; Menu entries and xrefs in magenta.
  823.         (brite::regexp-touchup-hot 
  824.          "\\(\*.*::\\|@xref{[^}]*}\\|@var{[^}]*}\\)")
  825.         ;; (brite::regexp-touchup-intense 
  826.         ;; "\\(^@chapter.*\\|^@section.*\\|^@unnumbered.*\\)")
  827.         (brite::regexp-touchup-mild "\\(@dfn{[^}]*}\\|^@[a-z]index.*\\)")
  828.         )
  829.        ;;-------------------------------------------------------------------
  830.        ((or (string-equal mode-name "AUC-LaTeX") (string-equal mode-name "LaTeX"))
  831.         (brite::regexp-touchup-intense 
  832.          "\\([\\]document.*[}]\\|[\\]input.*[}]\\|[\\]include.*[}]\\|includeonly.*[}]\\)")
  833.         (brite::regexp-touchup-hot "\\([\\]begin.*[}]\\|[\\]end.*[}]\\)")
  834.         ;; String between sets of three dashes is in a comment banner.
  835.         (brite::regexp-touchup-intense-always "--- .* ---")
  836.         ;; For font changes, pick up:
  837.         ;;   o Opening brace, backslash, and keyword.
  838.         ;;   o Any number of characters, except }.
  839.         ;;   o Closing brace.
  840.         ;; How to pick up entire \verb<char><string><char>?
  841.         ;; How to handle multiline footnote?
  842.         (brite::regexp-touchup-mild 
  843.          "\\([\\]item\\|[{][\\]it[^}]*[}]\\|[{][\\]sc[^}]*[}]\\|[{][\\]em[^}]*[}]\\|[\\]verb\\|[\\]footnote\\|[\\]label.*[}]\\|[\\]ref.*[}]\\)")
  844.         ;; Assume citation is one long word; always on one line.
  845.         ;; Also get three dashes in normal text.
  846.         (brite::regexp-touchup-earnest 
  847.          "\\([\\]cite[^}]*[}]\\|[ \n]---[ \n]\\|[\\]chapter\\|[\\]section\\|[\\]subsection\\|[\\]subsubsection\\|[\\]appendix\\|[\\]tableofcontents\\|[\\]newpage\\)"))
  848.        ;;-------------------------------------------------------------------
  849.        ((or (string-equal mode-name "C") (string-equal mode-name "C++"))
  850.         (brite::regexp-touchup-mild brite::c-directives)
  851.         ;; These are removed for performance reasons.
  852.         ;; (brite::regexp-touchup-hot brite::c-datatypes)
  853.         (brite::regexp-touchup-hot "\\([ \t]switch[ (]\\|[ \t]break;\\)")
  854.         (brite::regexp-touchup-earnest brite::c-data-attributes)
  855.         (brite::regexp-touchup-intense brite::c-defines)
  856.         (brite::regexp-touchup-blazing brite::c-dataglobs)
  857.         (brite::regexp-touchup-striking brite::c-flagged-keywords)
  858.         ;; Function declarations: if anyone has a better one than
  859.         ;; this, PLEASE send it to me.
  860.         (brite::regexp-touchup-hot
  861.          "^[_a-zA-Z][^=\n]*(\\([^)]*);\\|[^{;]*\\)") 
  862.         (brite::regexp-touchup-intense-always "--- .* ---"))
  863.        ;;-------------------------------------------------------------------
  864.        ((or (string-equal mode-name "Emacs-Lisp") 
  865.             (string-equal mode-name "Lisp"))
  866.         (brite::regexp-touchup-hot "(interactive[^)\n]*)")
  867.         (brite::regexp-touchup-earnest 
  868.          "\\(setq\\|setf\\|defvar\\|defconst\\|let[ \*]\\|global-set-key\\|define-key\\)")
  869.         (brite::regexp-touchup-mild "\\(nil\\|epoch::[^ \t\n)]*\\)")
  870.         ;; This gets strings, unless they contain quotes, which
  871.         ;; throws it out of whack.
  872.         ;; (brite::regexp-touchup-mild "\"[^\"]*\"")
  873.         (brite::regexp-touchup-intense 
  874.          "\\(return\\|(require[^)]*)\\|(load[^)]*)\\)")
  875.         (brite::regexp-touchup-blazing
  876.          "(provide[^)]*)")
  877.         ;; This relies on whitespace clipping.
  878.         (brite::regexp-touchup-striking "defun [^ ]*")
  879.         ;; This doesn't, but it doesn't look real good.
  880.         ;; (brite::regexp-touchup-blazing "defun [a-zA-Z\-\*:]+")
  881.         (brite::regexp-touchup-intense-always "--- .* ---"))
  882.        ;;-------------------------------------------------------------------
  883.        ((string-equal (brite::true-mode-name) "gnus-Article")
  884.         (brite::regexp-touchup-intense "From:.*")
  885.         (brite::regexp-touchup-hot "Date:.*")
  886.         (brite::regexp-touchup-earnest "Subject:.*"))
  887.        ((string-equal (brite::true-mode-name) "gnus-Subject")
  888.         ;; If this is a message we've sent, highlight the receiver.
  889.         ;; (brite::regexp-touchup-hot " [0-9]+:[ +]")
  890.         (brite::regexp-touchup-earnest "\\[[ 0-9][^\]]*\\]")
  891.         ;; (brite::regexp-touchup-intense "^D")
  892.         ;; (brite::regexp-touchup-mild "Re: ")
  893.         )
  894.        ((string-equal (brite::true-mode-name) "news-reply")
  895.         (brite::regexp-touchup-intense "Newsgroups:.*")
  896.         (brite::regexp-touchup-hot "In-reply-to:.*")
  897.         (brite::regexp-touchup-earnest "Subject:.*")
  898.         (brite::regexp-touchup-mild "--text follows this line--"))
  899.        ((string-equal mode-name "Perl")
  900.         (brite::regexp-touchup-hot "^[ \n\t]*sub.*\\{")
  901.         (brite::regexp-touchup-blazing "[ \n\t{]*eval[ \n\t(;]")
  902.         (brite::regexp-touchup-mild brite::perl-directives)
  903.         (brite::regexp-touchup-earnest brite::perl-flow)
  904.         (brite::regexp-touchup-intense-always "\\(--- .* ---\\|=== .* ===\\)"))
  905.        )))
  906.  
  907. ;;; --------------------------------------------------------------------------
  908. ;;; ---------------------- SEARCH CONSTRAINT FUNCTIONS -----------------------
  909. ;;; --------------------------------------------------------------------------
  910.  
  911. ;;; --------------------- brite::set-search-whole-buffer ---------------------
  912.  
  913. (defun brite::set-search-whole-buffer ()
  914.   "Tell the highlighting code to search the entire buffer."
  915.   (setq brite::beginning-point (point-min)
  916.         brite::ending-point (point-max)))
  917.  
  918. ;;; -------------------- brite::set-search-this-function ---------------------
  919.  
  920. (defun brite::set-search-this-function ()
  921.   "Tell the highlighting code to only search this function."
  922.   (save-excursion
  923.     (beginning-of-defun)
  924.     ;; Catch leading comments too.
  925.     (backward-paragraph)
  926.     (setq brite::beginning-point (point))
  927.     (end-of-defun)
  928.     (setq brite::ending-point (point))))
  929.  
  930. ;;; -------------------- brite::set-search-this-paragraph --------------------
  931.  
  932. (defun brite::set-search-this-paragraph ()
  933.   "Tell the highlighting code to only search this paragraph."
  934.   (save-excursion
  935.     (backward-paragraph)
  936.     (setq brite::beginning-point (point))
  937.     (forward-paragraph)
  938.     (setq brite::ending-point (point))))
  939.  
  940. ;;; ---------------------- brite::set-search-this-line -----------------------
  941.  
  942. (defun brite::set-search-this-line ()
  943.   "Tell the highlighting code to only search this line."
  944.   (save-excursion
  945.     (beginning-of-line)
  946.     (setq brite::beginning-point (point))
  947.     (end-of-line)
  948.     (setq brite::ending-point (point))))
  949.  
  950. ;;; ---------------------- brite::set-search-this-area -----------------------
  951.  
  952. (defun brite::set-search-this-area ()
  953.   "Tell the highlighting code to only search the immediate area."
  954.   ;; We assume the re-search routines will do range-checking
  955.   ;; (definitely checking on bound is done).
  956.   (setq brite::beginning-point (- (point) brite::area-extent)
  957.         brite::ending-point (+ (point) brite::area-extent)))
  958.  
  959. ;;; -------------------- brite::set-search-visible-window --------------------
  960.  
  961. (defun brite::set-search-visible-window ()
  962.   "Tell the highlighting code to only search area visible in window."
  963.   (save-excursion
  964.     (move-to-window-line 0)
  965.     (forward-line -5)
  966.     (setq brite::beginning-point (point))
  967.     (move-to-window-line -1)
  968.     (forward-line 5)
  969.     (setq brite::ending-point (point))))
  970.  
  971. ;;; --------------------------------------------------------------------------
  972. ;;; ---------------------- HIGHLIGHTING ACTION ROUTINES ----------------------
  973. ;;; --------------------------------------------------------------------------
  974.  
  975. ;;; ----------------------- brite::internal-highlight ------------------------
  976.  
  977. (defun brite::internal-highlight (&optional pointer-action)
  978.   "Highlight as appropriate.  Optional arg POINTER-ACTION causes pointer to
  979. not change if equal to 'static-pointer; else cursor changes to watch shape
  980. and back when highlighting."
  981.   (or (eq pointer-action 'static-pointer)
  982.       (brite::set-wait-pointer))
  983.   (unwind-protect
  984.       (progn
  985.         (if brite::comment-highlight-on (brite::highlight-comments))
  986.         (if brite::touchup-highlight-on (brite::do-buffer-touchup)))
  987.     (or (eq pointer-action 'static-pointer)
  988.         (brite::set-ready-pointer))))
  989.  
  990. ;;; ---------------------- brite::do-highlight-on-find -----------------------
  991.  
  992. (defun brite::do-highlight-on-find ()
  993.   "Called by find-file-hooks; goes into lightbrite-mode as appropriate."
  994.   (if (and brite::highlight-on-find 
  995.            ;; Don't highlight TAGS buffer!
  996.            (not (string= (buffer-name) "TAGS"))
  997.            ;; Don't highlight result of rmail-input.
  998.            (not (string= (brite::true-mode-name) "rmail")))
  999.       (progn
  1000.         (condition-case ()
  1001.             (lightbrite-mode 1)
  1002.           (error nil)))))
  1003.  
  1004. ;;; ---------------------- brite::do-highlight-on-mail -----------------------
  1005.  
  1006. (defun brite::do-highlight-on-mail ()
  1007.   "Called by mail-setup-hook; goes into lightbrite-mode."
  1008.   (lightbrite-mode 1))
  1009.  
  1010. ;;; ---------------------- brite::do-highlight-on-write ----------------------
  1011.  
  1012. (defun brite::do-highlight-on-write ()
  1013.   "Called by write-file-hooks; does highlighting as appropriate."
  1014.   ;; Check to see if we highlight this buffer on write.
  1015.   (if brite::highlight-on-write
  1016.       (progn
  1017.         ;; Check to see if there is any highlighting currently in effect.
  1018.         (if brite::highlight-done
  1019.             ;; If so, remove & redo highlighting.
  1020.             (progn
  1021.               (brite::clear-zones)
  1022.               (brite::set-search-whole-buffer)
  1023.               (brite::internal-highlight))
  1024.           ;; Else, do highlighting for the first time.
  1025.           (progn
  1026.             (lightbrite-mode 1)))))
  1027.   ;; Have to return nil or write-file-hooks will get stuffed up.
  1028.   nil)
  1029.  
  1030. ;;; ---------------------- brite::do-highlight-explicit ----------------------
  1031.  
  1032. (defvar brite::num-zones-begin nil "Number of zones before highlighting.")
  1033. (defvar brite::num-zones-end nil "Number of zones after highlighting.")
  1034.  
  1035. (defun brite::num-zones (&optional buffer)
  1036.   "Count the number of zones in the current buffer; optional BUFFER arg for
  1037. alternate buffer."
  1038.   (length (brite::zone-list buffer)))
  1039.  
  1040. (defun brite::do-highlight-explicit (&optional pointer-action)
  1041.   "Called interactively; does highlighting as appropriate.  Optional arg
  1042. POINTER-ACTION, when set to 'static-pointer, prevents pointer munging
  1043. from taking place."
  1044.   (interactive)
  1045.   (if lightbrite-mode
  1046.       (progn
  1047.         (if brite::diagnostics-on
  1048.             (setq brite::num-zones-begin (brite::num-zones)))
  1049.         ;; Check to see if there is any highlighting currently in effect.
  1050.         (if brite::highlight-done
  1051.             ;; If so, remove & redo highlighting.
  1052.             (progn
  1053.               (brite::clear-zones)
  1054.               (brite::set-search-whole-buffer)
  1055.               (brite::internal-highlight pointer-action))
  1056.           ;; Else, do highlighting for the first time.
  1057.           (progn
  1058.             (decode-syntax-table)
  1059.             (brite::set-search-whole-buffer)
  1060.             (brite::internal-highlight pointer-action)
  1061.             (setq brite::highlight-done t)))
  1062.         (if brite::diagnostics-on
  1063.             (setq brite::num-zones-end (brite::num-zones)))
  1064.         (if brite::diagnostics-on
  1065.             (message "Highlighting done; made %d zones." 
  1066.                      (- brite::num-zones-end brite::num-zones-begin))))
  1067.     ;; If we weren't in lightbrite-mode before, go to it now.
  1068.     (lightbrite-mode 1)))
  1069.     
  1070. ;;; ----------------------- brite::rmail-show-message ------------------------
  1071.  
  1072. (defun brite::rmail-show-message ()
  1073.   "Called from rmail-show-message hook, and ensures that rmail buffers
  1074. will always be highlighted."
  1075.   ;; Save current value of touchup max size and temporarily balloon it
  1076.   ;; to nil.  This is safe since RMAIL only sets the buffer extents to
  1077.   ;; that part of the file that holds the current message, so
  1078.   ;; (point-min) is not necessarily 0 and (point-max) is not
  1079.   ;; necessarily (buffer-size); thus, we can highlight the whole
  1080.   ;; buffer for each message without incurring huge performance
  1081.   ;; penalties.
  1082.   (if lightbrite-mode
  1083.       ;; If lightbrite-mode already active, just do this message.
  1084.       (progn
  1085.         (let ((brite::touchup-threshold-temp brite::touchup-threshold))
  1086.           (setq brite::touchup-threshold nil)
  1087.           (brite::do-highlight-explicit 'static-pointer)
  1088.           (setq brite::touchup-threshold brite::touchup-threshold-temp)))
  1089.     ;; Otherwise, do lightbrite-mode and then then this message.
  1090.    (progn
  1091.      (let ((brite::touchup-threshold-temp brite::touchup-threshold))
  1092.        (setq brite::touchup-threshold nil)
  1093.        (lightbrite-mode 1)
  1094.        (setq brite::touchup-threshold brite::touchup-threshold-temp)))))
  1095.     
  1096. ;;; ---------------------- brite::do-highlight-function ----------------------
  1097.  
  1098. (defun brite::do-highlight-function ()
  1099.   "Called interactively; highlights current defun only."
  1100.   (interactive)
  1101.   (message "Highlighting function.")
  1102.   ;; Check to see if there is any highlighting currently in effect.
  1103.   (if brite::highlight-done
  1104.       ;; If so, remove & redo highlighting.
  1105.       (progn
  1106.         ;; We have brite::set-search-this-function to set function
  1107.         ;; extents in globals, then clear that region.
  1108.         (brite::set-search-this-function)
  1109.         (brite::clear-zones-in-region brite::beginning-point 
  1110.                                       brite::ending-point)
  1111.         (brite::internal-highlight 'static-pointer))
  1112.     ;; Else, do highlighting for the first time.
  1113.     (progn
  1114.       (lightbrite-mode 1))))
  1115.  
  1116. ;;; --------------------- brite::do-highlight-paragraph ----------------------
  1117.  
  1118. (defun brite::do-highlight-paragraph ()
  1119.   "Called interactively; highlights current paragraph only."
  1120.   (interactive)
  1121.   (message "Highlighting paragraph.")
  1122.   ;; Check to see if there is any highlighting currently in effect.
  1123.   (if brite::highlight-done
  1124.       ;; If so, remove & redo highlighting.
  1125.       (progn
  1126.         ;; We have brite::set-search-this-paragraph to set paragraph
  1127.         ;; extents in globals, then clear that region.
  1128.         (brite::set-search-this-paragraph)
  1129.         (brite::clear-zones-in-region brite::beginning-point 
  1130.                                       brite::ending-point)
  1131.         (brite::internal-highlight 'static-pointer))
  1132.     ;; Else, do highlighting for the first time.
  1133.     (progn
  1134.       (lightbrite-mode 1))))
  1135.  
  1136. ;;; ------------------- brite::do-highlight-visible-window -------------------
  1137.  
  1138. (defun brite::do-highlight-visible-window ()
  1139.   "Called interactively; highlights visible window only."
  1140.   (interactive)
  1141.   ;; Check to see if there is any highlighting currently in effect.
  1142.   (if brite::highlight-done
  1143.     ;; If so, remove & redo highlighting.
  1144.     (progn
  1145.       ;; We have brite::set-search-visible-window to set window
  1146.       ;; extents in globals, then clear that region.
  1147.       (brite::set-search-visible-window)
  1148.       (brite::clear-zones-in-region brite::beginning-point 
  1149.                                     brite::ending-point)
  1150.       (brite::internal-highlight 'static-pointer))
  1151.     ;; Else, do highlighting for the first time.
  1152.     (progn
  1153.       (lightbrite-mode 1))))
  1154.  
  1155. ;;; ----------------------- brite::highlight-on-change -----------------------
  1156.  
  1157. (defun brite::highlight-on-change (pos inspos dellen)
  1158.   "Highlights current line only.  Accepts arguments as per 
  1159. after-change-function.  Don't do anything if DELLEN nonzero.  Assume
  1160. highlighting has already been done here to speed things up.  Only do
  1161. this every brite::change-interval changes."
  1162.   ;; First make sure this isn't a deletion.
  1163.   (if (= dellen 0)
  1164.       (progn
  1165.         ;; Increment the change counter.
  1166.         (setq brite::change-counter (+ brite::change-counter 1))
  1167.         ;; Do line highlight if this is a good time.
  1168.         (if (>= brite::change-counter brite::change-interval)
  1169.             ;; Protect everything to keep this from messing up replaces.
  1170.             (save-excursion
  1171.               (let ((data (match-data)))
  1172.                 (unwind-protect
  1173.                     (progn
  1174.                       (setq brite::change-counter 0)
  1175.                       ;; To search on the current line, use this:
  1176.                       ;; (brite::set-search-this-line)
  1177.                       ;; To search in the immediate area, do this:
  1178.                       ;; (brite::set-search-this-area)
  1179.                       ;; To search in the whole window, do this:
  1180.                       (brite::set-search-visible-window)
  1181.                       (brite::clear-zones-in-region brite::beginning-point 
  1182.                                                     brite::ending-point)
  1183.                       (brite::internal-highlight 'static-pointer))
  1184.                   (store-match-data data))))))))
  1185.  
  1186. ;;; -------------------------------------------------------------------------- 
  1187. ;;; ------------------- INTERACTIVE STATUS CHANGE ROUTINES -------------------
  1188. ;;; --------------------------------------------------------------------------
  1189.  
  1190. (defun brite::toggle-comment-highlight-on ()
  1191.   "Toggle buffer-local comment highlighting."
  1192.   (interactive)
  1193.   (setq brite::comment-highlight-on (not brite::comment-highlight-on))
  1194.   (message "Setting comment highlighting to %s." brite::comment-highlight-on)
  1195.   (brite::do-highlight-explicit))
  1196.  
  1197. (defun brite::toggle-touchup-highlight-on ()
  1198.   "Toggle buffer-local touchup highlighting."
  1199.   (interactive)
  1200.   (setq brite::touchup-highlight-on (not brite::touchup-highlight-on))
  1201.   (message "Setting touchup highlighting to %s." brite::touchup-highlight-on)
  1202.   (brite::do-highlight-explicit))
  1203.  
  1204. (defun brite::toggle-touchup-check-string ()
  1205.   "Toggle buffer-local in-quoted-string checking."
  1206.   (interactive)
  1207.   (setq brite::touchup-check-string (not brite::touchup-check-string))
  1208.   (message "Setting touchup string-checking to %s."
  1209.            brite::touchup-check-string)
  1210.   (brite::do-highlight-explicit))
  1211.  
  1212. (defun brite::toggle-touchup-check-zone ()
  1213.   "Toggle buffer-local in-zone checking."
  1214.   (interactive)
  1215.   (setq brite::touchup-check-zone (not brite::touchup-check-zone))
  1216.   (message "Setting touchup zone-checking to %s."
  1217.            brite::touchup-check-zone)
  1218.   (brite::do-highlight-explicit))
  1219.  
  1220. (defun brite::toggle-highlight-on-write ()
  1221.   "Toggle buffer-local highlighting on write."
  1222.   (interactive)
  1223.   (setq brite::highlight-on-write (not brite::highlight-on-write))
  1224.   (message "Setting highlight on write to %s." brite::highlight-on-write))
  1225.  
  1226. (defun brite::balloon-comment-threshold ()
  1227.   "Balloon the maximum file size for comment highlighting."
  1228.   (interactive)
  1229.   (setq brite::comment-threshold (+ (buffer-size) 1000))
  1230.   (message "Ballooning comment highlighting max size to %d."
  1231.            brite::comment-threshold)
  1232.   (brite::do-highlight-explicit))
  1233.  
  1234. (defun brite::balloon-touchup-threshold ()
  1235.   "Balloon the maximum file size for touchup highlighting."
  1236.   (interactive)
  1237.   (setq brite::touchup-threshold (+ (buffer-size) 1000))
  1238.   (message "Ballooning touchup highlighting max size to %d."
  1239.            brite::touchup-threshold)
  1240.   (brite::do-highlight-explicit)
  1241.   (if brite::diagnostics-on
  1242.       (message "%d zones in buffer." (length (brite::zone-list)))))
  1243.  
  1244. (defun brite::toggle-instant-highlight-on ()
  1245.   "Toggle value of brite::instant-highlight-on."
  1246.   (interactive)
  1247.   (if (boundp 'after-change-function)
  1248.       (progn
  1249.         (setq brite::instant-highlight-on (not brite::instant-highlight-on))
  1250.         (if brite::instant-highlight-on
  1251.             (progn
  1252.               (make-variable-buffer-local 'after-change-function)
  1253.               (setq after-change-function 'brite::highlight-on-change)
  1254.               (message "Instant highlighting is active."))
  1255.           (progn
  1256.             (setq after-change-function nil)
  1257.             (message "Instant highlighting in inactive."))))))
  1258.  
  1259. ;;; --------------------------------------------------------------------------
  1260. ;;; ---------------------- brite::postpend-unique-hook -----------------------
  1261. ;;; --------------------------------------------------------------------------
  1262.  
  1263. ;; Author: Daniel LaLiberte (liberte@cs.uiuc.edu).
  1264.  
  1265. (defun brite::postpend-unique-hook (hook-var hook-function)
  1266.   "Postpend HOOK-VAR with HOOK-FUNCTION, if it is not already an element.
  1267. hook-var's value may be a single function or a list of functions."
  1268.   (if (boundp hook-var)
  1269.       (let ((value (symbol-value hook-var)))
  1270.         (if (and (listp value) (not (eq (car value) 'lambda)))
  1271.             (and (not (memq hook-function value))
  1272.                  (set hook-var (append value (list hook-function))))
  1273.           (and (not (eq hook-function value))
  1274.                (set hook-var (append value (list hook-function))))))
  1275.     (set hook-var (list hook-function))))
  1276.  
  1277. ;;; --------------------------------------------------------------------------
  1278. ;;; ------------------------------ BUG REPORTS -------------------------------
  1279. ;;; --------------------------------------------------------------------------
  1280.  
  1281. ;; This section is inspired by c++-mode (Barry Warsaw).
  1282.  
  1283. (defvar brite::mailer 'mail
  1284.   "*Mail package to use to generate bug report mail buffer.")
  1285. (defconst brite::help-address "lightbrite-bugs@wintermute.ncsa.uiuc.edu"
  1286.   "Address accepting submission of bug reports.")
  1287.  
  1288. (defun brite::dump-state ()
  1289.   (let ((buffer (current-buffer)))
  1290.     (set-buffer buffer)
  1291.     (insert (brite::epoch-version) "\n")
  1292.     (insert (emacs-version) "\n")
  1293.     (insert "Lightbrite " brite::version "\n")))
  1294.  
  1295. (defun brite::submit-bug-report ()
  1296.   "Submit via mail a bug report using the mailer in brite::mailer."
  1297.   (interactive)
  1298.   (funcall brite::mailer)
  1299.   (insert brite::help-address)
  1300.   (if (re-search-forward "^subject:[ \t]+" (point-max) 'move)
  1301.       (insert "Bug in Lightbrite " brite::version))
  1302.   (if (not (re-search-forward mail-header-separator (point-max) 'move))
  1303.       (progn (goto-char (point-max))
  1304.              (insert "\n" mail-header-separator "\n")
  1305.              (goto-char (point-max)))
  1306.     (forward-line 1))
  1307.   (set-mark (point))
  1308.   (insert "\n\n")
  1309.   (brite::dump-state)
  1310.   (exchange-point-and-mark))
  1311.  
  1312. ;;; --------------------------------------------------------------------------
  1313. ;;; --------------------------- LIGHTBRITE KEYMAP ----------------------------
  1314. ;;; --------------------------------------------------------------------------
  1315.  
  1316. (defun brite::setup-keys ()
  1317.   "Set up Lightbrite's local keymap."
  1318.  
  1319.   ;; C-z C-SPC does buffer highlight.
  1320.   ;; C-z SPC does window highlighting.
  1321.   (local-set-key "\C-z\C-@" 'brite::do-highlight-explicit)
  1322.   (local-set-key "\C-z " 'brite::do-highlight-visible-window)
  1323.   
  1324.   ;; C-z c and C-z t toggle comment/touchup highlighting
  1325.   ;; for this buffer.
  1326.   (local-set-key "\C-zc" 'brite::toggle-comment-highlight-on)
  1327.   (local-set-key "\C-zt" 'brite::toggle-touchup-highlight-on)
  1328.   
  1329.   ;; C-z C and C-z T balloon the comment/touchup threshold for
  1330.   ;; all buffers.
  1331.   (local-set-key "\C-zC" 'brite::balloon-comment-threshold)
  1332.   (local-set-key "\C-zT" 'brite::balloon-touchup-threshold)
  1333.   
  1334.   ;; C-z q/z/w toggle misc parameters.
  1335.   (local-set-key "\C-zq" 'brite::toggle-touchup-check-string)
  1336.   (local-set-key "\C-zz" 'brite::toggle-touchup-check-zone)
  1337.   (local-set-key "\C-zw" 'brite::toggle-highlight-on-write)
  1338.   
  1339.   ;; C-z a toggles instant highlighting.
  1340.   (if (boundp 'after-change-function)
  1341.       (local-set-key "\C-za" 'brite::toggle-instant-highlight-on)))
  1342.  
  1343. ;; Variable to track state of local keymap.
  1344. (defvar brite::old-local-keymap nil "Storage for old local keymap.")
  1345. (make-variable-buffer-local 'brite::old-local-keymap)
  1346. (setq-default brite::old-local-keymap nil)
  1347.  
  1348. (defun brite::turn-on-keymap ()
  1349.   "Active local Lightbrite keymap."
  1350.   (setq brite::old-local-keymap (current-local-map))
  1351.   (if (null brite::old-local-keymap)
  1352.       (setq brite::old-local-keymap (make-keymap)))
  1353.   (use-local-map (copy-keymap brite::old-local-keymap))
  1354.   (brite::setup-keys))
  1355.  
  1356. (defun brite::turn-off-keymap ()
  1357.   "Deactivate local Lightbrite keymap."
  1358.   (use-local-map brite::old-local-keymap)
  1359.   (setq brite::old-local-keymap nil))
  1360.  
  1361. ;;; --------------------------------------------------------------------------
  1362. ;;; ---------------------------- LIGHTBRITE-MODE -----------------------------
  1363. ;;; --------------------------------------------------------------------------
  1364.  
  1365. ;; Variable to track state of lightbrite-mode in each buffer.
  1366. (defvar lightbrite-mode nil "Flag for activation of lightbrite-mode.")
  1367. (make-variable-buffer-local 'lightbrite-mode)
  1368. (setq-default lightbrite-mode nil)
  1369.  
  1370. (defun lightbrite-mode (&optional arg)
  1371.   "Lightbrite is a minor mode for syntax-directed highlighting of
  1372. source code under Epoch 4.2 (or later) or Lucid Emacs 19.3 (or later).
  1373. Optional ARG turns lightbrite-mode on if and only if value is greater
  1374. than 0, else off."
  1375.   (interactive)
  1376.   (setq lightbrite-mode
  1377.         (if (null arg) (not lightbrite-mode)
  1378.           (> (prefix-numeric-value arg) 0)))
  1379.   (cond
  1380.    (lightbrite-mode
  1381.     ;; Avoid turning on keymap twice.
  1382.     (if (null brite::old-local-keymap)
  1383.         (brite::turn-on-keymap))
  1384.     ;; Do initial highlighting.
  1385.     (brite::do-highlight-explicit)
  1386.     ;; Run startup hooks.
  1387.     (run-hooks 'brite::mode-hook))
  1388.    (t ;; not lightbrite-mode
  1389.     (brite::turn-off-keymap)
  1390.     (brite::clear-zones)
  1391.     (run-hooks 'brite::mode-exit-hook))))
  1392.  
  1393. ;;; --------------------------------------------------------------------------
  1394. ;;; ------------------------- RUNTIME INITIALIZATION -------------------------
  1395. ;;; --------------------------------------------------------------------------
  1396.  
  1397. ;; Register lightbrite-mode as a minor mode.
  1398. (or (assq 'lightbrite-mode minor-mode-alist)
  1399.     (setq minor-mode-alist
  1400.           (cons '(lightbrite-mode " Light") minor-mode-alist)))
  1401.  
  1402. ;; Do the hooks.
  1403. (brite::postpend-unique-hook 'find-file-hooks 'brite::do-highlight-on-find)
  1404. (brite::postpend-unique-hook 'write-file-hooks 'brite::do-highlight-on-write)
  1405. (brite::postpend-unique-hook 'rmail-show-message-hook 
  1406.                              'brite::rmail-show-message)
  1407. (brite::postpend-unique-hook 'mail-setup-hook 'brite::do-highlight-on-mail)
  1408.  
  1409. ;; The following hooks are not installed by default, but could be.
  1410. ;; (brite::postpend-unique-hook 'gnus-Article-prepare-hook 
  1411. ;;                              'brite::do-highlight-explicit)
  1412. ;; (brite::postpend-unique-hook 'gnus-Subject-prepare-hook 
  1413. ;;                              'brite::do-highlight-explicit)
  1414.  
  1415. ;;; -------------------------------- Menubar ---------------------------------
  1416.  
  1417. (if brite::running-lemacs
  1418.     (progn
  1419.       (defvar brite::menu
  1420.         '("Lightbrite Commands"
  1421.           ["Highlight Window"          brite::do-highlight-visible-window t]
  1422.           ["Highlight Function"        brite::do-highlight-function       t]
  1423.           ["Highlight Paragraph"       brite::do-highlight-paragraph      t]
  1424.           ["Highlight Buffer"          brite::do-highlight-explicit       t]
  1425.           "----"
  1426.           ["Balloon Touchup Threshold" brite::balloon-touchup-threshold   t]
  1427.           ["Balloon Comment Threshold" brite::balloon-comment-threshold   t]
  1428.           "----"
  1429.           ["Toggle String-Checking"    brite::toggle-touchup-check-string t]
  1430.           ["Toggle Extent-Checking"    brite::toggle-touchup-check-zone   t]
  1431.           ["Toggle Highlight-On-Write" brite::toggle-highlight-on-write   t]
  1432.           "----"
  1433.           ["Toggle Touchup Highlights" brite::toggle-touchup-highlight-on t]
  1434.           ["Toggle Comment Highlights" brite::toggle-comment-highlight-on t]
  1435.           ["Toggle Instant Highlights" brite::toggle-instant-highlight-on t]
  1436.           "----"
  1437.           ["Submit Bug Report"         brite::submit-bug-report           t]
  1438.           ))
  1439.  
  1440.       (defun brite::install-menubar ()
  1441.         (if current-menubar
  1442.             (progn
  1443.               (set-buffer-menubar (copy-sequence current-menubar))
  1444.               (add-menu nil "Light" (cdr brite::menu)))))
  1445.  
  1446.       (defun brite::remove-menubar ()
  1447.         (if current-menubar
  1448.             (delete-menu-item '("Light"))))
  1449.                         
  1450.       (brite::postpend-unique-hook 'brite::mode-hook 'brite::install-menubar)
  1451.       (brite::postpend-unique-hook 'brite::mode-exit-hook
  1452.                                    'brite::remove-menubar)))
  1453.  
  1454. ;;; -------------------------- provide the package ---------------------------
  1455.  
  1456. (provide 'lightbrite)
  1457.  
  1458. ;;; ------------------------------ END OF CODE -------------------------------
  1459.