Commits

Anonymous committed e1cc51d

New version from package maintainer.

See <m27lfw1s72.fsf@zion.ne.mediaone.net> with
subject "Improved Patch to mic-paren.el".

Comments (0)

Files changed (1)

 ;;; mic-paren.el --- highlight matching parenthesises.
-;;; Version 1.3.1 - 97-02-27
+;;; Version 2.3 - 2000-02-20
 ;;; Copyright (C) 1997 Mikael Sjödin (mic@docs.uu.se)
 ;;;
-;;; Author: Mikael Sjödin  --  mic@docs.uu.se
+;;; Maintenance and further development: Klaus Berndl -- berndl@sdm.de
+;;; Original author: Mikael Sjödin  --  mic@docs.uu.se
 ;;; Additional code by: Vinicius Jose Latorre <vinicius@cpqd.br>
 ;;;                     Steven L Baur <steve@xemacs.org>
+;;;                     Klaus Berndl  <berndl@sdm.de>
 ;;;                      
 ;;; Keywords: languages, faces
 ;;;
 ;;; This file is NOT part of GNU Emacs.
-;;; You may however redistribute it and/or modify it under the terms of the GNU
-;;; General Public License as published by the Free Software Foundation; either
-;;; version 2, or (at your option) any later version.
+;;; You may however redistribute it and/or modify it under the terms of the
+;;; GNU General Public License as published by the Free Software
+;;; Foundation; either version 2, or (at your option) any later version.
 ;;;
-;;; mic-paren is distributed in the hope that it will be useful,
-;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;;; GNU General Public License for more details.
+;;; mic-paren is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;;; General Public License for more details.
 
 ;;; ----------------------------------------------------------------------
 ;;; Short Description:
 ;;;
 ;;; Load this file and Emacs will display highlighting on whatever
-;;; parenthesis matches the one before or after point.  This is an extension to
-;;; the paren.el file distributed with Emacs.  The default behaviour is similar
-;;; to paren.el but try the authors favourite options:
+;;; parenthesis (and paired delimiter if you like this) matches the one
+;;; before or after point.  This is an extension to the paren.el file
+;;; distributed with Emacs.  The default behaviour is similar to paren.el
+;;; but try the favourite options of the original author:
 ;;;   (setq paren-face 'bold)
 ;;;   (setq paren-sexp-mode t)
+;;;
+;;; Or - if you are a LaTeX writer like the current maintainer - try the
+;;; following setup in your .emacs:
+;;; 
+;;; ;; per default we want no matching of quoted parens and paired delimiter
+;;; (mic-paren-toggle-matching-quoted-paren -1)
+;;; (mic-paren-toggle-matching-paired-delimiter -1)
+;;; ;; But in LaTeX-mode we want this
+;;; (add-hook 'LaTeX-mode-hook
+;;;           (function (lambda ()
+;;;                       (mic-paren-toggle-matching-quoted-paren 1)
+;;;                       (mic-paren-toggle-matching-paired-delimiter 1))))
 
 ;;; ----------------------------------------------------------------------
 ;;; Installation:
 ;;;
 ;;; o Place this file in a directory in your 'load-path.
 ;;; o Put the following in your .emacs file:
-;;;     (if window-system
-;;;         (require 'mic-paren))
+;;;   (GNU Emacs supports mic-paren only within a window-system but XEmacs
+;;;   supports mic-paren also without X)
+;;;   (when (or (string-match "XEmacs\\|Lucid" emacs-version) window-system)
+;;;      (require 'mic-paren)
+;;;      ;;; set here any of the customizable variables of mic-paren, e.g.:
+;;;      ;;; (setq paren-face 'bold)
+;;;      ;;; (setq paren-sexp-mode t)
+;;;   )
 ;;; o Restart your Emacs. mic-paren is now installed and activated!
 ;;; o To list the possible customisation enter `C-h f paren-activate'
 ;;;
 ;;; ----------------------------------------------------------------------
 ;;; Long Description:
 ;;;
-;;; mic-paren.el is an extension to the packages paren.el and stig-paren.el for
-;;; Emacs.  When mic-paren is active (it is activated when loaded) Emacs normal
-;;; parenthesis matching is deactivated.  Instead parenthesis matching will be
-;;; performed as soon as the cursor is positioned at a parenthesis.  The
-;;; matching parenthesis (or the entire expression between the parenthesises)
-;;; is highlighted until the cursor is moved away from the parenthesis.
-;;; Features include:
+;;; mic-paren.el is an extension to the packages paren.el and stig-paren.el
+;;; for Emacs.  When mic-paren is active (it is activated when loaded)
+;;; Emacs normal parenthesis matching is deactivated.  Instead parenthesis
+;;; matching will be performed as soon as the cursor is positioned at a
+;;; parenthesis.  The matching parenthesis (or the entire expression
+;;; between the parenthesises) is highlighted until the cursor is moved
+;;; away from the parenthesis.  Features include:
 ;;; o Both forward and backward parenthesis matching (simultaneously if
 ;;;   cursor is between two expressions).
 ;;; o Indication of mismatched parenthesises.
-;;; o Recognition of "escaped" parenthesises.
+;;; o Recognition of "escaped" (also often called "quoted") parenthesises.
+;;; o Option to match "escaped" parens too, especially in (La)TeX-mode
+;;;   (e.g. matches expressions like "\(foo bar\)" properly).
+;;; o Offers two functions as replacement for forward-sexp and
+;;;   backward-sexp which handle properly quoted parens (s.a.).
+;;; o Option to activate matching of paired delimiter (i.e. characters with
+;;;   syntax '$'). This is useful for writing in LaTeX-mode for example.
 ;;; o Option to select if only the matching parenthesis or the entire
 ;;;   expression should be highlighted.
 ;;; o Message describing the match when the matching parenthesis is
-;;;   off-screen. 
+;;;   off-screen. Option to select in which cases this message should be
+;;;   displayed.
 ;;; o Optional delayed highlighting (useful on slow systems), 
 ;;; o Functions to activate/deactivate mic-paren.el is provided.
 ;;; o Numerous options to control the behaviour and appearance of
 ;;;   mic-paren.el. 
 ;;;
-;;; mic-paren.el is developed and tested under Emacs 19.28 - 19.34.  It should
+;;; mic-paren.el is developed and tested under Emacs 19.28 - 20.5.  It should
 ;;; work on earlier and forthcoming Emacs versions.  XEmacs compatibility has
 ;;; been provided by Steven L Baur <steve@xemacs.org>.  Jan Dubois
 ;;; (jaduboi@ibm.net) provided help to get mic-paren to work in OS/2.
 ;;; ----------------------------------------------------------------------
 ;;; Versions:
 ;;;
+;;; v2.3    No additional feature but replacing 'char-bytes and
+;;;         'char-before with 'mic-char-bytes and 'mic-char-before to
+;;;         prevent the global-namespace.
+;;;
+;;; v2.2    Adding the new feature for matching paired delimiter. Not
+;;;         tested with XEmacs. Implemented by Klaus Berndl <berndl@sdm.de>
+;;;
+;;; v2.1    Adding the new feature for matching escaped parens too. Not
+;;;         tested with XEmacs. Implemented by Klaus Berndl <berndl@sdm.de>
+;;;
+;;; v2.0    Support for MULE and Emacs 20 multibyte characters added.  Inspired
+;;;         by the suggestion and code of Saito Takaaki
+;;;         <takaaki@is.s.u-tokyo.ac.jp>
+;;;
+;;; v1.9    Avoids multiple messages/dings when point has not moved.  Thus,
+;;;	    mic-paren no longer overwrites messages in minibuffer.  Inspired by
+;;;	    the suggestion and code of Barzilay Eliyahu <eli@cs.bgu.ac.il>.
+;;;
 ;;; v1.3.1  Some spelling corrected (from Vinicius Jose Latorre
 ;;;	    <vinicius@cpqd.br> and Steven L Baur <steve@xemacs.org>)
 ;;;
 ;;; v1.3    Added code from Vinicius Jose Latorre <vinicius@cpqd.br> to
-;;;	    highlight unmathced parenthesises (useful in minibuffer)
+;;;	    highlight unmatched parenthesises (useful in minibuffer)
 ;;;
 ;;; v1.2.1  Fixed stuff to work with OS/2 emx-emacs
-;;;           - checks if x-display-color-p is bound before calling it
-;;;           - changed how X/Lucid Emacs is deteced
+;;;           - checks if x-display-colour-p is bound before calling it
+;;;           - changed how X/Lucid Emacs is detected
 ;;;         Added automatic load of the timer-feature (+ variable to disable
 ;;;         the loading) 
 
 ;;; ------------------------------
 
 (defvar paren-highlight-offscreen nil
-  "*If non-nil stig-paren will highlight text which is not visible in the
+  "*If non-nil mic-paren will highlight text which is not visible in the
 current buffer.  
 
 This is useful if you regularly display the current buffer in multiple windows
 
 ;;; ------------------------------
 
-(defvar paren-message-offscreen t
-  "*Display message if matching parenthesis is off-screen.")
+(defvar paren-display-message 'only
+  "*Display message if matching parenthesis is off-screen.
+Possible settings are:
+- 'always: message is always displayed regardless if offscreen or not
+- 'only:   message is only displayed when matching is offscreen
+- nil:     never a message is displayed.")
 
 ;;; ------------------------------
 
 
 ;;; ------------------------------
 
-(defvar paren-dont-activate-on-load t
- "*If non-nil mic-paren will not activate itself when loaded.")
+(defvar paren-dont-activate-on-load nil
+  "*If non-nil mic-paren will not activate itself when loaded.")
 
 ;;; ------------------------------
 
 (defvar paren-dont-load-timer (not (string-match "XEmacs\\|Lucid"
-						 emacs-version))
+                                                 emacs-version))
   "*If non-nil mic-paren will not try to load the timer-feature when loaded.
 
 (I have no idea why Emacs user ever want to set this to non-nil but I hate
 
 ;;; ------------------------------
 
-(defgroup mic-paren nil
-  "Highlighting of (non)matching parentheses and expressions."
-  :group 'matching)
+(defvar paren-match-quoted-paren nil
+  "* Non-nil causes to match properly quoted \(or escaped\) parens \(e.g. in
+TeX-files, e.g. \"\\\(x-3y + z = 7\\\)\"\). FSF-Emacs can not match quoted
+parens, so we must temporally deactivate the quoting until emacs has done
+its sexp-parsing. Therefore emacs itself does not \(can not!\) take into
+consideration if either both matched parens are quoted or none. But
+nevertheless we do this! Only symmetric balanced parens are matched: means
+either both matching parens must we quoted or none, otherwise they we will
+be highlighted as mismatched.
+This package offers also two slightly modified versions of forward-sexp
+\(resp. backward-sexp\):
+`mic-paren-forward-sexp'\(`mic-paren-backward-sexp'\). This versions can also
+jump to escaped/quoted parens.
+If this variable is not nil and `paren-bind-modified-sexp-functions' is set
+to non nil then `mic-paren-toggle-matching-quoted-paren' will also toggle
+the orginal binding of `forward-sexp' \(resp. backward-sexp\) between the
+orginal functions and the modified equivalents.
+This behaviour can only be guaranted if you do NOT set this variable
+directly but use `mic-paren-toggle-matching-quoted-paren' to
+activate/deactivate/toggle this feature!. The best method is to do this in
+a mode hook, e.g.:
+\(add-hook \'LaTeX-mode-hook
+          \(function \(lambda \(\)
+                      \(mic-paren-toggle-matching-quoted-paren 1\)\)\)\)")
+(make-variable-buffer-local 'paren-match-quoted-paren)
 
-(defface paren-face '((((class color)
-			(background light))
-		       (:background "lightgoldenrod"))
-		      (((class color)
-			(background dark))
-		       (:background "darkolivegreen"))
-		      (t
-		       (:underline t)))
-  "*Face to use for showing the matching parenthesis."
-  :group 'mic-paren)
+(defvar paren-match-paired-delimiter nil
+"* If not nil then characters with syntax '$' \(means paired delimiter\)
+will be matched if possible (e.g. in LaTeX \"$...$\" is equal with
+\"\\(...\\)\"\) . Unlike to parens quoted/escaped paired delimiter will
+never match.
+Do NOT set this variable directly but use
+`mic-paren-toggle-matching-paired-delimiter' to activate/deactivate/toggle
+this feature!. The best method is to do this in a mode hook, e.g.:
+\(add-hook \'LaTeX-mode-hook
+          \(function \(lambda \(\)
+                      \(mic-paren-toggle-matching-paired-delimiter 1\)\)\)\)")
+(make-variable-buffer-local 'paren-match-paired-delimiter)
 
-(defvar paren-face 'paren-face
-  "Don't even think of using this.
-The variable is obsolete, use the `paren-face' face instead.")
 
-(defface paren-mismatch-face '((((class color)
-				 (background light))
-				(:background "DeepPink"))
-			       (((class color)
-				 (background dark))
-				(:background "DeepPink3"))
-			       (t
-				(:inverse-video t)))
-  "*Face to use when highlighting a mismatched parenthesis."
-  :group 'mic-paren)
+(defvar paren-bind-modified-sexp-functions t
+"* If non nil mic-paren checks at load-time the keybindings for the functions
+`forward-sexp' and `backward-sexp' and binds the modified sexp-functions
+`mic-paren-forward-sexp' and `mic-paren-backward-sexp' to exactly these
+bindings if and only if matching quoted/escaped parens is turned on by
+`mic-paren-toggle-matching-quoted-paren'. These new binding is done only
+for the buffer local-key-map, therefore if you activate the quoted matching
+only in some modes from within a hook only in these buffers the new binding
+is active and 'in all other not.
+If you deactivate the quoted matching feature by
+`mic-paren-toggle-matching-quoted-paren' then `forward-sexp' and
+`backward-sexp' will be bound again to their original key-bindings!")
 
-(defvar paren-mismatch-face 'paren-mismatch-face
-  "Don't even think of using this.
-The variable is obsolete, use the `paren-mismatch-face' face instead.")
 
-(defface paren-no-match-face '((((class color)
-				 (background light))
-				(:background "yellow"))
-			       (((class color)
-				 (background dark))
-				(:background "yellow4"))
-			       (t nil))
-  "*Face to use when highlighting an unmatched parenthesis."
-  :group 'mic-paren)
+(defconst mic-paren-orginal-keybinding-of-sexp-functions
+  (list (car (where-is-internal 'forward-sexp))
+        (car (where-is-internal 'backward-sexp))))
 
-(defvar paren-no-match-face 'paren-no-match-face
-  "Don't even think of using this.
-The variable is obsolete, use the `paren-no-match-face' face instead.")
+;;; ------------------------------
+
+(defvar paren-face (if (and (fboundp 'x-display-color-p)
+                            (x-display-color-p)) 
+                       'highlight 'underline)
+  "*Face to use for showing the matching parenthesis.")
+
+;;; ------------------------------
+
+(defvar paren-mismatch-face (if (and (fboundp 'x-display-color-p)
+                                     (x-display-color-p))
+                                (let ((fn 'paren-mismatch-face))
+                                  (copy-face 'default fn)
+                                  (set-face-background fn "DeepPink")
+                                  fn)
+                              'modeline)
+  "*Face to use when highlighting a mismatched parenthesis.")
+
+;;; ------------------------------
+
+(defvar paren-no-match-face (if (x-display-color-p)
+                                (let ((fn 'paren-no-match-face))
+                                  (copy-face 'default fn)
+                                  (set-face-background fn "yellow")
+                                  fn)
+                              'default)
+  "*Face to use when highlighting an unmatched parenthesis.")
 
 ;;; ======================================================================
-;;; User Functions:
+;;; Compatibility.
+;;; Try to make mic-paren work in different Emacs flavours.
 
 ;; XEmacs compatibility (mainly by Steven L Baur <steve@xemacs.org>)
 (eval-and-compile
   (if (string-match "\\(Lucid\\|XEmacs\\)" emacs-version)
       (progn
-	(fset 'mic-make-overlay 'make-extent)
-	(fset 'mic-delete-overlay 'delete-extent)
-	(fset 'mic-overlay-put 'set-extent-property)
-	(defun mic-cancel-timer (timer) (delete-itimer timer))
-	(fset 'mic-run-with-idle-timer 'start-itimer)
-	)
+        (fset 'mic-make-overlay 'make-extent)
+        (fset 'mic-delete-overlay 'delete-extent)
+        (fset 'mic-overlay-put 'set-extent-property)
+        (defun mic-cancel-timer (timer) (delete-itimer timer))
+        (fset 'mic-run-with-idle-timer 'start-itimer)
+        )
     (fset 'mic-make-overlay 'make-overlay)
     (fset 'mic-delete-overlay 'delete-overlay)
     (fset 'mic-overlay-put 'overlay-put)
     ))
 
 
+;; MULE and Emacs 20 multibyte char compatibility.
+;; Implemented by defining dummys for functions which do not exist in vanilla
+;; Emacs.
+
+(if (fboundp 'char-bytes)
+    (fset 'mic-char-bytes 'char-bytes)
+  (defun mic-char-bytes (ch)
+      "Returns 1 for all input CH.
+Function defined by mic-paren to be compatible with multibyte Emacses."
+      1))
+
+(if (fboundp 'char-before)
+    (fset 'mic-char-before 'char-before)
+  (defun mic-char-before (pos)
+      "Return character in current buffer preceding position POS.
+       POS is an integer or a buffer pointer.
+       If POS is out of range, the value is nil.
+Function defined by mic-paren to be compatible with multibyte Emacses."
+      (char-after (1- pos))))
+
+;;; ======================================================================
+;;; User Functions:
+
 (defun paren-activate ()
   "Activates mic-paren parenthesis highlighting.
 paren-activate deactivates the paren.el and stig-paren.el packages if they are
   paren-sexp-mode
   paren-highlight-at-point
   paren-highlight-offscreen
-  paren-message-offscreen
+  paren-display-message
+  paren-match-quoted-parens
+  paren-match-paired-delimiter
   paren-message-no-match
   paren-ding-unmatched
   paren-delay
       (setq blink-matching-paren nil))
 
   (cond(
-	;; If timers are available use them
-	;; (Emacs 19.31 and above)
-	(featurep 'timer)
-	(if (numberp paren-delay)
-	    (setq mic-paren-idle-timer 
-		  (mic-run-with-idle-timer paren-delay t
-					   'mic-paren-command-idle-hook))
-	  (add-hook 'post-command-hook 'mic-paren-command-hook)))
+        ;; If timers are available use them
+        ;; (Emacs 19.31 and above)
+        (featurep 'timer)
+        (if (numberp paren-delay)
+            (setq mic-paren-idle-timer 
+                  (mic-run-with-idle-timer paren-delay t
+                                           'mic-paren-command-idle-hook))
+          (add-hook 'post-command-hook 'mic-paren-command-hook)))
        ;; If the idle hook exists assume it is functioning and use it 
        ;; (Emacs 19.30)
        ((and (boundp 'post-command-idle-hook) 
-	     (boundp 'post-command-idle-delay))
-	(if paren-delay
-	    (add-hook 'post-command-idle-hook 'mic-paren-command-idle-hook)
-	  (add-hook 'post-command-hook 'mic-paren-command-hook)))
-       ;; Check if we (at least) have a post-command-hook, and use it
+             (boundp 'post-command-idle-delay))
+        (if paren-delay
+            (add-hook 'post-command-idle-hook 'mic-paren-command-idle-hook)
+          (add-hook 'post-command-hook 'mic-paren-command-hook)))
+       ;; Check if we (at least) have a post-comand-hook, and use it
        ;; (Emacs 19.29 and below)
        ((boundp 'post-command-hook) 
-	(add-hook 'post-command-hook 'mic-paren-command-hook))
+        (add-hook 'post-command-hook 'mic-paren-command-hook))
        ;; Not possible to install mic-paren hooks
        (t (error "Cannot activate mic-paren in this Emacs version"))))
 
       (setq blink-matching-paren t))
   )
 
+(defun mic-paren-toggle-matching-paired-delimiter (arg)
+"Toggle matching paired delimiter, force off with negative arg. Use this
+in mode-hooks to activate or deactivate paired delimiter matching."
+  (interactive "P")
+  (setq paren-match-paired-delimiter (if (numberp arg)
+                                         (> arg 0)
+                                       (not paren-match-paired-delimiter)))
+  (message "Matching paired delimiter is %s"
+           (if paren-match-paired-delimiter
+               "ON, you should be in (La)TeX-mode!"
+             "OFF")))
+
+
+(defun mic-paren-toggle-matching-quoted-paren (arg)
+  "Toggle matching quoted parens, force off with negative arg. Use this in
+mode-hooks to activate or deactivate quoted paren matching."
+  (interactive "P")
+  (setq paren-match-quoted-paren (if (numberp arg)
+                                         (> arg 0)
+                                       (not paren-match-quoted-paren)))
+  ;; if matching quoted parens is active now bind the original binding of
+  ;; forward-sexp and backward-sexp to the modified
+  ;; versions mic-paren-forward-sexp (resp. mic-paren-backward-sexp)
+  ;; if not bind it back to the original forward-sexp (resp. backward-sexp).
+  (let ((key-forward-sexp (car
+                           mic-paren-orginal-keybinding-of-sexp-functions))
+        (key-backward-sexp (car
+                            (cdr 
+                             mic-paren-orginal-keybinding-of-sexp-functions))))        
+    (if (and paren-bind-modified-sexp-functions
+             key-backward-sexp
+             key-forward-sexp)
+        (if paren-match-quoted-paren
+            (progn
+              (local-set-key key-forward-sexp
+                             (quote mic-paren-forward-sexp))
+              (local-set-key key-backward-sexp
+                             (quote mic-paren-backward-sexp)))
+          (global-set-key key-forward-sexp (quote forward-sexp))
+          (global-set-key key-backward-sexp (quote backward-sexp)))))
+  (message "Matching quoted parens is %s"
+           (if paren-match-quoted-paren
+               "ON, you should be in (La)TeX-mode!"
+             "OFF")))
+
+(defun mic-paren-forward-sexp (&optional arg)
+  "Acts like forward-sexp but can also matching quoted parens. Look at
+`paren-match-quoted-paren' for a detailed comment"
+  (interactive "p")
+  (or arg (setq arg 1))
+  (let* ((uncharquote-diff (if (< arg 0) 2 1))
+         (match-check-diff (if (< arg 0) 1 2))
+         (charquote (mic-paren-uncharquote (- (point) uncharquote-diff)))
+         match-pos mismatch)
+    ;; we must encapsulate this in condition-case so we regain control
+    ;; after error and we can undo our unquoting if any done before!
+    (condition-case ()
+        (setq match-pos (scan-sexps (point) arg))
+      (error nil))
+    (mic-paren-recharquote charquote)
+    (if (not match-pos)
+        (buffer-end arg)
+      (setq mismatch (if charquote
+                         (not (mic-paren-is-following-char-quoted
+                               (- match-pos match-check-diff)))
+                       (mic-paren-is-following-char-quoted
+                        (- match-pos match-check-diff))))
+      (if (not mismatch)
+          (goto-char match-pos)
+        (forward-sexp arg)
+        ))))
+
+(defun mic-paren-backward-sexp (&optional arg)
+  "Acts like backward-sexp but can also matching quoted parens. Look at
+`paren-match-quoted-paren' for a detailed comment"
+  (interactive "p")
+  (or arg (setq arg 1))
+  (mic-paren-forward-sexp (- arg)))
+
 ;;; ======================================================================
 ;;; Internal variables:
 
 (defvar mic-paren-idle-timer nil
   "Idle-timer.  Used only in Emacs 19.31 and above (and if paren-delay is nil)")
 
-
-
+(defvar mic-paren-previous-location [nil nil nil]
+  "Records where point was the last time mic-paren performed some action.
+Format is [POINT BUFFER WINDOW]")
 
 ;;; ======================================================================
 ;;; Internal function:
 
 (defun mic-paren-command-hook ()
   (or executing-kbd-macro
-      (input-pending-p)			;[This might cause trouble since the
+      (input-pending-p)                 ;[This might cause trouble since the
                                         ; function is unreliable]
       (condition-case paren-error
-	  (mic-paren-highlight)
-	(error 
-	 (if (not (window-minibuffer-p (selected-window)))
-	     (message "mic-paren caught an error (please report): %s"
-		      paren-error))))))
+          (mic-paren-highlight)
+        (error 
+         (if (not (window-minibuffer-p (selected-window)))
+             (message "mic-paren catched error (please report): %s"
+                      paren-error))))))
 
 (defun mic-paren-command-idle-hook ()
   (condition-case paren-error
       (mic-paren-highlight)
     (error 
      (if (not (window-minibuffer-p (selected-window)))
-	 (message "mic-paren caught an error (please report): %s" 
-		  paren-error)))))
-
+         (message "mic-paren catched error (please report): %s" 
+                  paren-error)))))
 
 (defun mic-paren-highlight ()
   "The main-function of mic-paren. Does all highlighting, dinging, messages,
   (mic-delete-overlay mic-paren-point-overlay)
   (mic-delete-overlay mic-paren-backw-overlay)
 
-  ;; Handle backward highlighting (when after a close-paren):
-  ;; If positioned after a close-paren, and
+  ;; Handle backward highlighting (when after a close-paren or a paired
+  ;; delimiter):
+  ;; If (positioned after a close-paren, and
   ;;    not before an open-paren when priority=open, and
-  ;;    the close-paren is not escaped then
+  ;;    (paren-match-quoted-paren is t or the close-paren is not escaped))
+  ;;    or
+  ;;    (positioned after a paired delimiter, and
+  ;;    not before a paired-delimiter when priority=open, and
+  ;;    the paired-delimiter is not escaped))
+  ;; then
   ;;      perform highlighting
-  ;; else
-  ;;      remove any old backward highlights
-  (if (and (eq (char-syntax (preceding-char)) ?\))
-	   (not (and (eq (char-syntax (following-char)) ?\()
-		     (eq paren-priority 'open)))
-	   (paren-evenp (paren-backslashes-before-char (1- (point)))))
-       (let (open)
-	 ;; Find the position for the open-paren
-	 (save-excursion
-	   (save-restriction
-	     (if blink-matching-paren-distance
-		 (narrow-to-region 
-		  (max (point-min)
-		       (- (point) blink-matching-paren-distance))
-		  (point-max)))
-	     (condition-case ()
-		 (setq open (scan-sexps (point) -1))
-	       (error nil))))
+  (if (or (and (eq (char-syntax (preceding-char)) ?\))
+               (not (and (eq (char-syntax (following-char)) ?\()
+                         (eq paren-priority 'open)))
+               (or paren-match-quoted-paren
+                   (not (mic-paren-is-following-char-quoted (- (point)
+                                                               2)))))
+          (and paren-match-paired-delimiter
+               (eq (char-syntax (preceding-char)) ?\$)
+               (not (and (eq (char-syntax (following-char)) ?\$)
+                         (eq paren-priority 'open)))
+               (not (mic-paren-is-following-char-quoted (- (point) 2)))))
+      (let (open matched-paren charquote)
+        ;; if we want to match quoted parens we must change the syntax of
+        ;; the escape or quote-char temporaly. This will be undone later.
+        (setq charquote (mic-paren-uncharquote (- (point) 2)))
+        ;; Find the position for the open-paren
+        (save-excursion
+          (save-restriction
+            (if blink-matching-paren-distance
+                (narrow-to-region
+                 (max (point-min)
+                      (- (point) blink-matching-paren-distance))
+                 (point-max)))
+            (condition-case ()
+                (setq open (scan-sexps (point) -1))
+              (error nil))))
 
-	 ;; If match found
-	 ;;    highlight expression and/or print messages
-	 ;; else
-	 ;;    highlight unmatched paren
-	 ;;    print no-match message
-	 (if open
-	     (let ((mismatch (not (eq (matching-paren (preceding-char)) 
-				      (char-after open))))
-		   (visible (pos-visible-in-window-p open)))
-	       ;; If highlight is appropriate
-	       ;;    highlight
-	       ;; else
-	       ;;    remove any old highlight
-	       (if (or visible paren-highlight-offscreen paren-sexp-mode)
-		   ;; If sexp-mode
-		   ;;    highlight sexp
-		   ;; else
-		   ;;    highlight the two parens
-		   (if paren-sexp-mode
-		       (progn
-			 (setq mic-paren-backw-overlay
-			       (mic-make-overlay open (point)))
-			 (if mismatch
-			     (mic-overlay-put mic-paren-backw-overlay 
-					      'face paren-mismatch-face)
-			   (mic-overlay-put mic-paren-backw-overlay 
-					    'face paren-face)))
-		     (setq mic-paren-backw-overlay
-			   (mic-make-overlay open (1+ open)))
-		     (and paren-highlight-at-point
-			  (setq mic-paren-point-overlay
-				(mic-make-overlay (1- (point)) (point))))
-		     (if mismatch
-			 (progn
-			   (mic-overlay-put mic-paren-backw-overlay 
-					    'face paren-mismatch-face)
-			   (and paren-highlight-at-point
-				(mic-overlay-put mic-paren-point-overlay 
-						 'face paren-mismatch-face)))
-		       (mic-overlay-put mic-paren-backw-overlay 
-					'face paren-face)
-		       (and paren-highlight-at-point 
-			    (mic-overlay-put mic-paren-point-overlay 
-					     'face paren-face)))))
-	       ;; Print messages if match is offscreen
-	       (and paren-message-offscreen
-		    (not visible)
-		    (not (window-minibuffer-p (selected-window)))
-		    (message "%s %s" 
-			     (if mismatch "MISMATCH:" "Matches")
-			     (mic-paren-get-matching-open-text open)))
-	       ;; Ding if mismatch
-	       (and mismatch
-		    paren-ding-unmatched
-		    (ding)))
-	   (setq mic-paren-backw-overlay
-		 (mic-make-overlay (1- (point)) (point)))
-	   (mic-overlay-put mic-paren-backw-overlay
-			    'face paren-no-match-face)
-	   (and paren-message-no-match
-		(not (window-minibuffer-p (selected-window)))
-		(message "No opening parenthesis found"))
-	   (and paren-message-no-match
-		paren-ding-unmatched
-		(ding)))))
+        ;; we must call matching-paren because scan-sexps don´t care about
+        ;; the kind of paren (e.g. matches '( and '}). matching-paren only
+        ;; returns the character displaying the matching paren in buffer´s
+        ;; syntax-table (regardless of the buffer´s current contents!).
+        ;; Below we compare the results of scan-sexps and matching-paren
+        ;; and if different we display a mismatch.
+        (setq matched-paren (matching-paren (preceding-char)))
+        ;; matching-paren can only handle characters with syntax ) or (
+        (if (eq (char-syntax (preceding-char)) ?\$)
+            (setq matched-paren (preceding-char)))
+        
+        ;; if we have changed the syntax of the escape or quote-char we
+        ;; must undo this and we can do this first now.
+        (mic-paren-recharquote charquote)
+        
+        ;; If match found
+        ;;    highlight expression and/or print messages
+        ;; else
+        ;;    highlight unmatched paren
+        ;;    print no-match message
+        (if open
+            (let ((mismatch (or (not matched-paren)
+                                (/= matched-paren (char-after open))
+                                (if charquote
+                                    (not (mic-paren-is-following-char-quoted
+                                          (1- open)))
+                                  (mic-paren-is-following-char-quoted
+                                   (1- open)))))
+                  (visible (pos-visible-in-window-p open)))
+              ;; If highlight is appropriate
+              ;;    highlight
+              ;; else
+              ;;    remove any old highlight
+              (if (or visible paren-highlight-offscreen paren-sexp-mode)
+                  ;; If sexp-mode
+                  ;;    highlight sexp
+                  ;; else
+                  ;;    highlight the two parens
+                  (if paren-sexp-mode
+                      (progn
+                        (setq mic-paren-backw-overlay
+                              (mic-make-overlay open (point)))
+                        (if mismatch
+                            (mic-overlay-put mic-paren-backw-overlay 
+                                             'face paren-mismatch-face)
+                          (mic-overlay-put mic-paren-backw-overlay 
+                                           'face paren-face)))
+                    (setq mic-paren-backw-overlay
+                          (mic-make-overlay 
+                           open
+                           (+ open
+                              (mic-char-bytes (char-after open)))))
+                    (and paren-highlight-at-point
+                         (setq mic-paren-point-overlay
+                               (mic-make-overlay 
+                                (- (point)
+                                   (mic-char-bytes (preceding-char)))
+                                (point))))
+                    (if mismatch
+                        (progn
+                          (mic-overlay-put mic-paren-backw-overlay 
+                                           'face paren-mismatch-face)
+                          (and paren-highlight-at-point
+                               (mic-overlay-put mic-paren-point-overlay 
+                                                'face paren-mismatch-face)))
+                      (mic-overlay-put mic-paren-backw-overlay 
+                                       'face paren-face)
+                      (and paren-highlight-at-point 
+                           (mic-overlay-put mic-paren-point-overlay 
+                                            'face paren-face)))))
+              ;; Print messages if match is offscreen
+              (and paren-display-message
+                   (or (not visible) (eq paren-display-message 'always))
+                   (not (window-minibuffer-p (selected-window)))
+                   (mic-paren-is-new-location)
+                   (message "%s %s" 
+                            (if mismatch "MISMATCH:" "Matches")
+                            (mic-paren-get-matching-open-text open)))
+              ;; Ding if mismatch
+              (and mismatch
+                   paren-ding-unmatched
+                   (mic-paren-is-new-location)
+                   (ding)))
+          (setq mic-paren-backw-overlay
+                (mic-make-overlay (point)
+                                  (- (point)
+                                     (mic-char-bytes (preceding-char)))))
+          (mic-overlay-put mic-paren-backw-overlay
+                           'face paren-no-match-face)
+          (and paren-message-no-match
+               (not (window-minibuffer-p (selected-window)))
+               (mic-paren-is-new-location)
+               (message "No opening parenthesis found"))
+          (and paren-message-no-match
+               paren-ding-unmatched
+               (mic-paren-is-new-location)
+               (ding)))))
+  
+  ;; Handle forward highlighting (when before an open-paren or a paired
+  ;; delimiter):
+  ;; If (positioned before an open-paren, and
+  ;;    not after a close-paren when priority=close, and
+  ;;    (paren-match-quoted-paren is t or the open-paren is not escaped))
+  ;;    or
+  ;;    (positioned before a paired delimiter, and
+  ;;    not after a paired-delimiter when priority=close, and
+  ;;    the paired-delimiter is not escaped))
+  ;; then
+  ;;      perform highlighting
+  (if (or (and (eq (char-syntax (following-char)) ?\()
+               (not (and (eq (char-syntax (preceding-char)) ?\))
+                         (eq paren-priority 'close)))
+               (or paren-match-quoted-paren
+                   (not (mic-paren-is-following-char-quoted (1-
+                                                             (point))))))
+          (and paren-match-paired-delimiter
+               (eq (char-syntax (following-char)) ?\$)
+               (not (and (eq (char-syntax (preceding-char)) ?\$)
+                         (eq paren-priority 'close)))
+               (not (mic-paren-is-following-char-quoted (1- (point))))))
+      (let (close matched-paren charquote)
+        ;; if we want to match quoted parens we must change the syntax of
+        ;; the escape or quote-char temporaly. This will be undo later.
+        (setq charquote (mic-paren-uncharquote (1- (point))))
+        ;; Find the position for the close-paren
+        (save-excursion
+          (save-restriction
+            (if blink-matching-paren-distance
+                (narrow-to-region 
+                 (point-min)
+                 (min (point-max)
+                      (+ (point) blink-matching-paren-distance))))
+            (condition-case ()
+                (setq close (scan-sexps (point) 1))
+              (error nil))))
 
-  ;; Handle forward highlighting (when before an open-paren):
-  ;; If positioned before an open-paren, and
-  ;;    not after a close-paren when priority=close, and
-  ;;    the open-paren is not escaped then
-  ;;      perform highlighting
-  ;; else
-  ;;      remove any old forward highlights
-  (if (and (eq (char-syntax (following-char)) ?\()
-	   (not (and (eq (char-syntax (preceding-char)) ?\))
-		     (eq paren-priority 'close)))
-	   (paren-evenp (paren-backslashes-before-char (point))))
-       (let (close)
-	 ;; Find the position for the close-paren
-	 (save-excursion
-	   (save-restriction
-	     (if blink-matching-paren-distance
-		 (narrow-to-region 
-		  (point-min)
-		  (min (point-max)
-		       (+ (point) blink-matching-paren-distance))))
-      	     (condition-case ()
-		 (setq close (scan-sexps (point) 1))
-	       (error nil))))
-	 ;; If match found
-	 ;;    highlight expression and/or print messages
-	 ;; else
-	 ;;    highlight unmatched paren
-	 ;;    print no-match message
-	 (if close
-	     (let ((mismatch (not (eq (matching-paren (following-char))
-				      (char-after (1- close)))))
-		   (visible (pos-visible-in-window-p close)))
-	       ;; If highlight is appropriate
-	       ;;    highlight
-	       ;; else
-	       ;;    remove any old highlight
-	       (if (or visible paren-highlight-offscreen paren-sexp-mode)
-		   ;; If sexp-mode
-		   ;;    highlight sexp
-		   ;; else
-		   ;;    highlight the two parens
-		   (if paren-sexp-mode
-		       (progn
-			 (setq mic-paren-forw-overlay
-			       (mic-make-overlay (point) close))
-			 (if mismatch
-			     (mic-overlay-put mic-paren-forw-overlay 
-					      'face paren-mismatch-face)
-			   (mic-overlay-put mic-paren-forw-overlay 
-					    'face paren-face)))
-		     (setq mic-paren-forw-overlay
-			   (mic-make-overlay (1- close) close))
-		     (if mismatch
-			 (mic-overlay-put mic-paren-forw-overlay 
-					  'face paren-mismatch-face)
-		       (mic-overlay-put mic-paren-forw-overlay 
-					'face paren-face))))
+        ;; for an explanation look above.
+        (setq matched-paren (matching-paren (following-char)))
+        (if (eq (char-syntax (following-char)) ?\$)
+            (setq matched-paren (following-char)))
+        
+        ;; if we have changed the syntax of the escape or quote-char we
+        ;; must undo this and we can do this first now.
+        (mic-paren-recharquote charquote)
+        
+        ;; If match found
+        ;;    highlight expression and/or print messages
+        ;; else
+        ;;    highlight unmatched paren
+        ;;    print no-match message
+        (if close
+            (let ((mismatch (or (not matched-paren)
+                                (/= matched-paren (mic-char-before close))
+                                (if charquote
+                                    (not (mic-paren-is-following-char-quoted
+                                          (- close 2)))
+                                  (mic-paren-is-following-char-quoted
+                                   (- close 2)))))
+                  (visible (pos-visible-in-window-p close)))
+              ;; If highlight is appropriate
+              ;;    highlight
+              ;; else
+              ;;    remove any old highlight
+              (if (or visible paren-highlight-offscreen paren-sexp-mode)
+                  ;; If sexp-mode
+                  ;;    highlight sexp
+                  ;; else
+                  ;;    highlight the two parens
+                  (if paren-sexp-mode
+                      (progn
+                        (setq mic-paren-forw-overlay
+                              (mic-make-overlay (point) close))
+                        (if mismatch
+                            (mic-overlay-put mic-paren-forw-overlay 
+                                             'face paren-mismatch-face)
+                          (mic-overlay-put mic-paren-forw-overlay 
+                                           'face paren-face)))
+                    (setq mic-paren-forw-overlay
+                          (mic-make-overlay
+                           (- close
+                              (mic-char-bytes (mic-char-before close)))
+                           close))
+                    (if mismatch
+                        (mic-overlay-put mic-paren-forw-overlay 
+                                         'face paren-mismatch-face)
+                      (mic-overlay-put mic-paren-forw-overlay 
+                                       'face paren-face))))
 
-	       ;; Print messages if match is offscreen
-	       (and paren-message-offscreen
-		    (not visible)
-		    (not (window-minibuffer-p (selected-window)))
-		    (message "%s %s" 
-			     (if mismatch "MISMATCH:" "Matches")
-			     (mic-paren-get-matching-close-text close)))
-	       ;; Ding if mismatch
-	       (and mismatch
-		    paren-ding-unmatched
-		    (ding)))
-	   (setq mic-paren-forw-overlay
-		 (mic-make-overlay (point) (1+ (point))))
-	   (mic-overlay-put mic-paren-forw-overlay
-			    'face paren-no-match-face)
-	   (and paren-message-no-match
-		(not (window-minibuffer-p (selected-window)))
-		(message "No closing parenthesis found"))
-	   (and paren-message-no-match
-		paren-ding-unmatched
-		(ding))))))
+              ;; Print messages if match is offscreen
+              (and paren-display-message
+                   (or (not visible) (eq paren-display-message 'always))
+                   (not (window-minibuffer-p (selected-window)))
+                   (mic-paren-is-new-location)
+                   (message "%s %s" 
+                            (if mismatch "MISMATCH:" "Matches")
+                            (mic-paren-get-matching-close-text close)))
+              ;; Ding if mismatch
+              (and mismatch
+                   (mic-paren-is-new-location)
+                   paren-ding-unmatched
+                   (ding)))
+          (setq mic-paren-forw-overlay
+                (mic-make-overlay (point)
+                                  (+ (point)
+                                     (mic-char-bytes (following-char)))))
+          (mic-overlay-put mic-paren-forw-overlay
+                           'face paren-no-match-face)
+          (and paren-message-no-match
+               (not (window-minibuffer-p (selected-window)))
+               (mic-paren-is-new-location)
+               (message "No closing parenthesis found"))
+          (and paren-message-no-match
+               paren-ding-unmatched
+               (mic-paren-is-new-location)
+               (ding)))))
+
+  ;; Store the points position in mic-paren-previous-location
+  ;; Later used by mic-paren-is-new-location
+  (or (window-minibuffer-p (selected-window))
+      (progn
+        (aset mic-paren-previous-location 0 (point))
+        (aset mic-paren-previous-location 1 (current-buffer))
+        (aset mic-paren-previous-location 2 (selected-window))))
+  )
 
 ;;; --------------------------------------------------
 
   (save-excursion
     (goto-char open)
     (if (save-excursion
-	  (skip-chars-backward " \t")
-	  (not (bolp)))
-	(progn
-	  (beginning-of-line)
-	  (concat (buffer-substring (point) (1+ open)) "..."))
-      (forward-char 1)			;From the beginning-of-line
+          (skip-chars-backward " \t")
+          (not (bolp)))
+        (progn
+          (beginning-of-line)
+          (concat (buffer-substring (point) (1+ open)) "..."))
+      (forward-char 1)                  ;From the beginning-of-line
       (skip-chars-forward "\n \t")
       (end-of-line)
       (buffer-substring open (point)))))
      (progn 
        (goto-char close)
        (if (looking-at "[ \t]*$")
-	   ""
-	 "...")))))
+           ""
+         "...")))))
   
 
-(defun paren-evenp (number)
-  "Returns t if NUMBER is an even number, nil otherwise"
-  (eq 0 (% number 2)))
+(defun mic-paren-is-new-location ()
+  "Returns t if the points location is not the same as stored in
+`mic-paren-previous-location', nil otherwise.
 
-(defun paren-backslashes-before-char (pnt)
-  (setq pnt (1- pnt))
+The variable `mic-paren-previous-location' is set by
+`mic-paren-highlight'."
+  (not (and (eq (point) (aref mic-paren-previous-location 0))
+            (eq (current-buffer) (aref mic-paren-previous-location 1))
+            (eq (selected-window) (aref mic-paren-previous-location 2)))))
+
+
+(defun mic-paren-is-following-char-quoted (pnt)
+  "returns true if character at point PNT escapes or quotes the following
+char."
   (let ((n 0))
     (while (and (>= pnt (point-min))
-		(eq (char-syntax (char-after pnt)) ?\\))
+                (or (eq (char-syntax (char-after pnt)) ?\\)
+                    (eq (char-syntax (char-after pnt)) ?/)))
       (setq n (1+ n))
       (setq pnt (1- pnt)))
-    n))
+    (if (eq 0 (% n 2)) nil t)))
 
+(defun mic-paren-uncharquote (pnt)
+  "if the syntax of character <c> at point PNT is escape or quote and if the
+character is not escaped or quoted itself then its syntax will be modified
+to punctuation and multiple values (<c> \"<syntax-of-c>\") will be returned;
+otherwise nil."
+  (let (c cs)
+    (if (< pnt (point-min))
+        nil
+      (setq c (char-after pnt))
+      (setq cs (char-syntax c))
+      (if (not (and paren-match-quoted-paren
+                    (mic-paren-is-following-char-quoted pnt)))
+          nil
+        (modify-syntax-entry c ".")
+        (list c (char-to-string cs))))))
+
+(defun mic-paren-recharquote (charquote)
+  "CHARQUOTE is a 2-element-list: car is a character <c> and its cadr
+is a syntaxstring <s>. The syntax of character <c> will be set to syntax
+<s>. If CHARQUOTE is nil nothing will be done."
+  (if charquote
+      (modify-syntax-entry (car charquote) (car (cdr charquote)))))
     
 
 ;;; ======================================================================
 (or paren-dont-load-timer
     (featurep 'timer)
     (condition-case ()
-	(require 'timer)
+        (require 'timer)
       (error nil)))
 
 
 
 ;;; This is in case mic-paren.el is preloaded. [Does this work? /Mic]
 (add-hook 'window-setup-hook
-	  (function (lambda ()
-		      (and window-system
-			   (not paren-dont-activate-on-load)
-			   (paren-activate)))))
+          (function (lambda ()
+                      (and window-system
+                           (not paren-dont-activate-on-load)
+                           (paren-activate)))))
 
 (provide 'mic-paren)
 (provide 'paren)