Trailing whitepace deleted.
[bpt/emacs.git] / lisp / progmodes / pascal.el
index bdc2cb6..debe52e 100644 (file)
@@ -1,66 +1,68 @@
-;;; pascal.el  -  Major mode for editing pascal source in emacs.
+;;; pascal.el --- major mode for editing pascal source in Emacs
 
-;;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 94, 95, 96, 97, 98, 1999, 2000 Free Software Foundation, Inc.
 
-;;; Author: Espen Skoglund (espensk@stud.cs.uit.no)
-;;; Keywords: languages
+;; Author: Espen Skoglund <esk@gnu.org>
+;; Keywords: languages
 
-;;; This file is part of GNU Emacs.
+;; This file is part of GNU Emacs.
 
-;;; This program is free software; you can 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 of the License, or
-;;; (at your option) any later version.
+;; GNU Emacs is free software; you can 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.
 
-;;; This program 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.
+;; GNU Emacs 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.
 
-;;; You should have received a copy of the GNU General Public License
-;;; along with this program; if not, write to the Free Software
-;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
 
 ;;; Commentary:
 
-;;; USAGE
-;;; =====
-
-;;; Emacs should enter Pascal mode when you find a Pascal source file.
-;;; When you have entered Pascal mode, you may get more info by pressing
-;;; C-h m. You may also get online help describing various functions by:
-;;; C-h f <Name of function you want described>
-
-;;; If you want to customize Pascal mode to fit you better, you may add
-;;; these lines (the values of the variables presented here are the defaults):
-;;;
-;;; ;; User customization for Pascal mode
-;;; (setq pascal-indent-level       3
-;;;       pascal-case-indent        2
-;;;       pascal-auto-newline       nil
-;;;       pascal-tab-always-indent  t
-;;;       pascal-auto-endcomments   t
-;;;       pascal-auto-lineup        '(all)
-;;;       pascal-toggle-completions nil
-;;;       pascal-type-keywords      '("array" "file" "packed" "char" 
-;;;                                  "integer" "real" "string" "record")
-;;;       pascal-start-keywords     '("begin" "end" "function" "procedure"
-;;;                                  "repeat" "until" "while" "read" "readln"
-;;;                                  "reset" "rewrite" "write" "writeln")
-;;;       pascal-separator-keywords '("downto" "else" "mod" "div" "then"))
-
-;;; KNOWN BUGS / BUGREPORTS
-;;; =======================
-;;; As far as I know, there are no bugs in the current version of this
-;;; package.  This may not be true however, since I never use this mode
-;;; myself and therefore would never notice them anyway.   If you do
-;;; find any bugs, you may submit them to: espensk@stud.cs.uit.no
-;;; as well as to bug-gnu-emacs@prep.ai.mit.edu.
+;; USAGE
+;; =====
+
+;; Emacs should enter Pascal mode when you find a Pascal source file.
+;; When you have entered Pascal mode, you may get more info by pressing
+;; C-h m. You may also get online help describing various functions by:
+;; C-h f <Name of function you want described>
+
+;; If you want to customize Pascal mode to fit you better, you may add
+;; these lines (the values of the variables presented here are the defaults):
+;;
+;; ;; User customization for Pascal mode
+;; (setq pascal-indent-level       3
+;;       pascal-case-indent        2
+;;       pascal-auto-newline       nil
+;;       pascal-tab-always-indent  t
+;;       pascal-auto-endcomments   t
+;;       pascal-auto-lineup        '(all)
+;;       pascal-toggle-completions nil
+;;       pascal-type-keywords      '("array" "file" "packed" "char"
+;;                                  "integer" "real" "string" "record")
+;;       pascal-start-keywords     '("begin" "end" "function" "procedure"
+;;                                  "repeat" "until" "while" "read" "readln"
+;;                                  "reset" "rewrite" "write" "writeln")
+;;       pascal-separator-keywords '("downto" "else" "mod" "div" "then"))
+
+;; KNOWN BUGS / BUGREPORTS
+;; =======================
+;; As far as I know, there are no bugs in the current version of this
+;; package.  This may not be true however, since I never use this mode
+;; myself and therefore would never notice them anyway.   If you do
+;; find any bugs, you may submit them to: esk@gnu.org as well as to
+;; bug-gnu-emacs@gnu.org.
 \f
 ;;; Code:
 
-(defconst pascal-mode-version "2.3"
-  "Version of `pascal.el'.")
+(defgroup pascal nil
+  "Major mode for editing Pascal source in Emacs"
+  :group 'languages)
 
 (defvar pascal-mode-abbrev-table nil
   "Abbrev table in use in Pascal-mode buffers.")
   (define-key pascal-mode-map "."        'electric-pascal-semi-or-dot)
   (define-key pascal-mode-map ":"        'electric-pascal-colon)
   (define-key pascal-mode-map "="        'electric-pascal-equal)
+  (define-key pascal-mode-map "#"        'electric-pascal-hash)
   (define-key pascal-mode-map "\r"       'electric-pascal-terminate-line)
   (define-key pascal-mode-map "\t"       'electric-pascal-tab)
-  (define-key pascal-mode-map "\e\t"     'pascal-complete-word)
-  (define-key pascal-mode-map "\e?"      'pascal-show-completions)
+  (define-key pascal-mode-map "\M-\t"    'pascal-complete-word)
+  (define-key pascal-mode-map "\M-?"     'pascal-show-completions)
   (define-key pascal-mode-map "\177"     'backward-delete-char-untabify)
-  (define-key pascal-mode-map "\e\C-h"   'pascal-mark-defun)
-  (define-key pascal-mode-map "\C-cb"    'pascal-insert-block)
+  (define-key pascal-mode-map "\M-\C-h"  'pascal-mark-defun)
+  (define-key pascal-mode-map "\C-c\C-b" 'pascal-insert-block)
   (define-key pascal-mode-map "\M-*"     'pascal-star-comment)
   (define-key pascal-mode-map "\C-c\C-c" 'pascal-comment-area)
   (define-key pascal-mode-map "\C-c\C-u" 'pascal-uncomment-area)
-  (define-key pascal-mode-map "\e\C-a"   'pascal-beg-of-defun)
-  (define-key pascal-mode-map "\e\C-e"   'pascal-end-of-defun)
-  (define-key pascal-mode-map "\C-cg"    'pascal-goto-defun)
-  (define-key pascal-mode-map "\C-c\C-o"  'pascal-outline)
+  (define-key pascal-mode-map "\M-\C-a"  'pascal-beg-of-defun)
+  (define-key pascal-mode-map "\M-\C-e"  'pascal-end-of-defun)
+  (define-key pascal-mode-map "\C-c\C-d" 'pascal-goto-defun)
+  (define-key pascal-mode-map "\C-c\C-o" 'pascal-outline)
 ;;; A command to change the whole buffer won't be used terribly
 ;;; often, so no need for a key binding.
 ;  (define-key pascal-mode-map "\C-cd"    'pascal-downcase-keywords)
 ;  (define-key pascal-mode-map "\C-cu"    'pascal-upcase-keywords)
 ;  (define-key pascal-mode-map "\C-cc"    'pascal-capitalize-keywords)
   )
-  
+
+(defvar pascal-imenu-generic-expression
+  '((nil "^[ \t]*\\(function\\|procedure\\)[ \t\n]+\\([a-zA-Z0-9_.:]+\\)" 2))
+  "Imenu expression for Pascal-mode.  See `imenu-generic-expression'.")
+
 (defvar pascal-keywords
-  '("and" "array" "begin" "case" "const" "div" "do" "downto" "else" "end" 
-    "file" "for" "function" "goto" "if" "in" "label" "mod" "nil" "not" "of" 
-    "or" "packed" "procedure" "program" "record" "repeat" "set" "then" "to" 
+  '("and" "array" "begin" "case" "const" "div" "do" "downto" "else" "end"
+    "file" "for" "function" "goto" "if" "in" "label" "mod" "nil" "not" "of"
+    "or" "packed" "procedure" "program" "record" "repeat" "set" "then" "to"
     "type" "until" "var" "while" "with"
     ;; The following are not standard in pascal, but widely used.
     "get" "put" "input" "output" "read" "readln" "reset" "rewrite" "write"
 (defconst pascal-beg-block-re   "\\<\\(begin\\|case\\|record\\|repeat\\)\\>")
 (defconst pascal-end-block-re   "\\<\\(end\\|until\\)\\>")
 (defconst pascal-declaration-re "\\<\\(const\\|label\\|type\\|var\\)\\>")
+(defconst pascal-progbeg-re     "\\<\\program\\>")
 (defconst pascal-defun-re       "\\<\\(function\\|procedure\\|program\\)\\>")
 (defconst pascal-sub-block-re   "\\<\\(if\\|else\\|for\\|while\\|with\\)\\>")
 (defconst pascal-noindent-re    "\\<\\(begin\\|end\\|until\\|else\\)\\>")
 (if pascal-mode-syntax-table
     ()
   (setq pascal-mode-syntax-table (make-syntax-table))
-  (modify-syntax-entry ?\\ "\\"  pascal-mode-syntax-table)
-  (modify-syntax-entry ?( "()1"  pascal-mode-syntax-table)  
+  (modify-syntax-entry ?\\ "."   pascal-mode-syntax-table)
+  (modify-syntax-entry ?( "()1"  pascal-mode-syntax-table)
   (modify-syntax-entry ?) ")(4"  pascal-mode-syntax-table)
-  (modify-syntax-entry ?* ". 23" pascal-mode-syntax-table)
+  (modify-syntax-entry ?* ". 23b" pascal-mode-syntax-table)
   (modify-syntax-entry ?{ "<"    pascal-mode-syntax-table)
   (modify-syntax-entry ?} ">"    pascal-mode-syntax-table)
   (modify-syntax-entry ?+ "."    pascal-mode-syntax-table)
   (modify-syntax-entry ?> "."    pascal-mode-syntax-table)
   (modify-syntax-entry ?& "."    pascal-mode-syntax-table)
   (modify-syntax-entry ?| "."    pascal-mode-syntax-table)
-  (modify-syntax-entry ?_ "w"    pascal-mode-syntax-table)
+  (modify-syntax-entry ?_ "_"    pascal-mode-syntax-table)
   (modify-syntax-entry ?\' "\""  pascal-mode-syntax-table))
 
-(defvar pascal-indent-level 3
-  "*Indentation of Pascal statements with respect to containing block.")
-
-(defvar pascal-case-indent 2
-  "*Indentation for case statements.")
-
-(defvar pascal-auto-newline nil
-  "*Non-nil means automatically newline after simcolons and the punctation mark
-after an end.")
-
-(defvar pascal-tab-always-indent t
-  "*Non-nil means TAB in Pascal mode should always reindent the current line,
-regardless of where in the line point is when the TAB command is used.")
-
-(defvar pascal-auto-endcomments t
-  "*Non-nil means a comment { ... } is set after the ends which ends cases and
-functions. The name of the function or case will be set between the braces.")
-
-(defvar pascal-auto-lineup '(all)
+(defconst pascal-font-lock-keywords (purecopy
+  (list
+   '("^[ \t]*\\(function\\|pro\\(cedure\\|gram\\)\\)\\>[ \t]*\\([a-z]\\)"
+     1 font-lock-keyword-face)
+   '("^[ \t]*\\(function\\|pro\\(cedure\\|gram\\)\\)\\>[ \t]*\\([a-z][a-z0-9_]*\\)"
+     3 font-lock-function-name-face t)
+;   ("type" "const" "real" "integer" "char" "boolean" "var"
+;    "record" "array" "file")
+   (cons (concat "\\<\\(array\\|boolean\\|c\\(har\\|onst\\)\\|file\\|"
+                "integer\\|re\\(al\\|cord\\)\\|type\\|var\\)\\>")
+        'font-lock-type-face)
+   '("\\<\\(label\\|external\\|forward\\)\\>" . font-lock-constant-face)
+   '("\\<\\([0-9]+\\)[ \t]*:" 1 font-lock-function-name-face)
+;   ("of" "to" "for" "if" "then" "else" "case" "while"
+;    "do" "until" "and" "or" "not" "in" "with" "repeat" "begin" "end")
+   (concat "\\<\\("
+          "and\\|begin\\|case\\|do\\|e\\(lse\\|nd\\)\\|for\\|i[fn]\\|"
+          "not\\|o[fr]\\|repeat\\|t\\(hen\\|o\\)\\|until\\|w\\(hile\\|ith\\)"
+          "\\)\\>")
+   '("\\<\\(goto\\)\\>[ \t]*\\([0-9]+\\)?"
+     1 font-lock-keyword-face)
+   '("\\<\\(goto\\)\\>[ \t]*\\([0-9]+\\)?"
+     2 font-lock-keyword-face t)))
+  "Additional expressions to highlight in Pascal mode.")
+(put 'pascal-mode 'font-lock-defaults '(pascal-font-lock-keywords nil t))
+
+(defcustom pascal-indent-level 3
+  "*Indentation of Pascal statements with respect to containing block."
+  :type 'integer
+  :group 'pascal)
+
+(defcustom pascal-case-indent 2
+  "*Indentation for case statements."
+  :type 'integer
+  :group 'pascal)
+
+(defcustom pascal-auto-newline nil
+  "*Non-nil means automatically insert newlines in certain cases.
+These include after semicolons and after the punctuation mark after an `end'."
+  :type 'boolean
+  :group 'pascal)
+
+(defcustom pascal-indent-nested-functions t
+  "*Non-nil means nested functions are indented."
+  :type 'boolean
+  :group 'pascal)
+
+(defcustom pascal-tab-always-indent t
+  "*Non-nil means TAB in Pascal mode should always reindent the current line.
+If this is nil, TAB inserts a tab if it is at the end of the line
+and follows non-whitespace text."
+  :type 'boolean
+  :group 'pascal)
+
+(defcustom pascal-auto-endcomments t
+  "*Non-nil means automatically insert comments after certain `end's.
+Specifically, this is done after the ends of cases statements and functions.
+The name of the function or case is included between the braces."
+  :type 'boolean
+  :group 'pascal)
+
+(defcustom pascal-auto-lineup '(all)
   "*List of contexts where auto lineup of :'s or ='s should be done.
 Elements can be of type: 'paramlist', 'declaration' or 'case', which will
 do auto lineup in parameterlist, declarations or case-statements
 respectively. The word 'all' will do all lineups. '(case paramlist) for
 instance will do lineup in case-statements and parameterlist, while '(all)
-will do all lineups.")
-
-(defvar pascal-toggle-completions nil
-  "*Non-nil means that \\<pascal-mode-map>\\[pascal-complete-label] should \
-not display a completion buffer when
-the label couldn't be completed, but instead toggle the possible completions
-with repeated \\[pascal-complete-label]'s.")
-
-(defvar pascal-type-keywords
+will do all lineups."
+  :type '(set :extra-offset 8
+             (const :tag "Everything" all)
+             (const :tag "Parameter lists" paramlist)
+             (const :tag "Decalrations" declaration)
+             (const :tag "Case statements" case))
+  :group 'pascal)
+
+(defcustom pascal-toggle-completions nil
+  "*Non-nil means \\<pascal-mode-map>\\[pascal-complete-word] should try all possible completions one by one.
+Repeated use of \\[pascal-complete-word] will show you all of them.
+Normally, when there is more than one possible completion,
+it displays a list of all possible completions."
+  :type 'boolean
+  :group 'pascal)
+
+(defcustom pascal-type-keywords
   '("array" "file" "packed" "char" "integer" "real" "string" "record")
   "*Keywords for types used when completing a word in a declaration or parmlist.
-\(eg. integer, real, char.)  The types defined within the Pascal program
-will be completed runtime, and should not be added to this list.")
+These include integer, real, char, etc.
+The types defined within the Pascal program
+are handled in another way, and should not be added to this list."
+  :type '(repeat (string :tag "Keyword"))
+  :group 'pascal)
 
-(defvar pascal-start-keywords
+(defcustom pascal-start-keywords
   '("begin" "end" "function" "procedure" "repeat" "until" "while"
     "read" "readln" "reset" "rewrite" "write" "writeln")
   "*Keywords to complete when standing at the first word of a statement.
-\(eg. begin, repeat, until, readln.)
+These are keywords such as begin, repeat, until, readln.
 The procedures and variables defined within the Pascal program
-will be completed runtime and should not be added to this list.")
+are handled in another way, and should not be added to this list."
+  :type '(repeat (string :tag "Keyword"))
+  :group 'pascal)
 
-(defvar pascal-separator-keywords
+(defcustom pascal-separator-keywords
   '("downto" "else" "mod" "div" "then")
   "*Keywords to complete when NOT standing at the first word of a statement.
-\(eg. downto, else, mod, then.) 
-Variables and function names defined within the
-Pascal program are completed runtime and should not be added to this list.")
+These are keywords such as downto, else, mod, then.
+Variables and function names defined within the Pascal program
+are handled in another way, and should not be added to this list."
+  :type '(repeat (string :tag "Keyword"))
+  :group 'pascal)
+
 
 ;;;
 ;;;  Macros
@@ -216,11 +283,12 @@ Pascal program are completed runtime and should not be added to this list.")
 (defun pascal-declaration-end ()
   (let ((nest 1))
     (while (and (> nest 0)
-               (re-search-forward 
-                "[:=]\\|\\(\\<record\\>\\)\\|\\(\\<end\\>\\)" 
+               (re-search-forward
+                "[:=]\\|\\(\\<record\\>\\)\\|\\(\\<end\\>\\)"
                 (save-excursion (end-of-line 2) (point)) t))
       (cond ((match-beginning 1) (setq nest (1+ nest)))
-           ((match-beginning 2) (setq nest (1- nest)))))))
+           ((match-beginning 2) (setq nest (1- nest)))
+           ((looking-at "[^(\n]+)") (setq nest 0))))))
 
 
 (defun pascal-declaration-beg ()
@@ -232,7 +300,7 @@ Pascal program are completed runtime and should not be added to this list.")
            ((match-beginning 3) (setq nest (1+ nest)))))
     (= nest 0)))
 
-  
+
 (defsubst pascal-within-string ()
   (save-excursion
     (nth 3 (parse-partial-sexp (pascal-get-beg-of-line) (point)))))
@@ -262,21 +330,23 @@ Other useful functions are:
 
 Variables controlling indentation/edit style:
 
- pascal-indent-level      (default 3)
+ pascal-indent-level (default 3)
     Indentation of Pascal statements with respect to containing block.
- pascal-case-indent       (default 2)
+ pascal-case-indent (default 2)
     Indentation for case statements.
- pascal-auto-newline      (default nil)
-    Non-nil means automatically newline after simcolons and the punctation mark
-    after an end.
+ pascal-auto-newline (default nil)
+    Non-nil means automatically newline after semicolons and the punctuation
+    mark after an end.
+ pascal-indent-nested-functions (default t)
+    Non-nil means nested functions are indented.
  pascal-tab-always-indent (default t)
     Non-nil means TAB in Pascal mode should always reindent the current line,
     regardless of where in the line point is when the TAB command is used.
- pascal-auto-endcomments  (default t)
+ pascal-auto-endcomments (default t)
     Non-nil means a comment { ... } is set after the ends which ends cases and
     functions. The name of the function or case will be set between the braces.
- pascal-auto-lineup       (default t)
-    List of contexts where auto lineup of :'s or ='s hould be done.
+ pascal-auto-lineup (default t)
+    List of contexts where auto lineup of :'s or ='s should be done.
 
 See also the user variables pascal-type-keywords, pascal-start-keywords and
 pascal-separator-keywords.
@@ -292,11 +362,27 @@ no args, if that value is non-nil."
   (set-syntax-table pascal-mode-syntax-table)
   (make-local-variable 'indent-line-function)
   (setq indent-line-function 'pascal-indent-line)
+  (make-local-variable 'comment-indent-function)
   (setq comment-indent-function 'pascal-indent-comment)
   (make-local-variable 'parse-sexp-ignore-comments)
-  (setq parse-sexp-ignore-comments t)
+  (setq parse-sexp-ignore-comments nil)
+  (make-local-variable 'blink-matching-paren-dont-ignore-comments)
+  (setq blink-matching-paren-dont-ignore-comments t)
   (make-local-variable 'case-fold-search)
   (setq case-fold-search t)
+  (make-local-variable 'comment-start)
+  (setq comment-start "{")
+  (make-local-variable 'comment-start-skip)
+  (setq comment-start-skip "(\\*+ *\\|{ *")
+  (make-local-variable 'comment-end)
+  (setq comment-end "}")
+  ;; Font lock support
+  (make-local-variable 'font-lock-defaults)
+  (setq font-lock-defaults '(pascal-font-lock-keywords nil t))
+  ;; Imenu support
+  (make-local-variable 'imenu-generic-expression)
+  (setq imenu-generic-expression pascal-imenu-generic-expression)
+  (setq imenu-case-fold-search t)
   (run-hooks 'pascal-mode-hook))
 
 \f
@@ -334,7 +420,7 @@ no args, if that value is non-nil."
                         (search-forward "*)" (pascal-get-end-of-line) t))))
             (setq setstar t))))
     ;; If last line was a star comment line then this one shall be too.
-    (if (null setstar) 
+    (if (null setstar)
        (pascal-indent-line)
       (insert "*  "))))
 
@@ -370,18 +456,32 @@ no args, if that value is non-nil."
       (let ((pascal-tab-always-indent nil))
        (pascal-indent-command))))
 
+(defun electric-pascal-hash ()
+  "Insert `#', and indent to column 0 if this is a CPP directive."
+  (interactive)
+  (insert last-command-char)
+  (if (save-excursion (beginning-of-line) (looking-at "^[ \t]*#"))
+      (save-excursion (beginning-of-line)
+                     (delete-horizontal-space))))
+
 (defun electric-pascal-tab ()
   "Function called when TAB is pressed in Pascal mode."
   (interactive)
-  ;; Do nothing if within a string.
-  (if (pascal-within-string)
+  ;; Do nothing if within a string or in a CPP directive.
+  (if (or (pascal-within-string)
+         (and (not (bolp))
+              (save-excursion (beginning-of-line) (eq (following-char) ?#))))
       (insert "\t")
     ;; If pascal-tab-always-indent, indent the beginning of the line.
     (if pascal-tab-always-indent
        (save-excursion
          (beginning-of-line)
          (pascal-indent-line))
-      (insert "\t"))
+      (if (save-excursion
+           (skip-chars-backward " \t")
+           (bolp))
+         (pascal-indent-line)
+       (insert "\t")))
     (pascal-indent-command)))
 
 \f
@@ -392,11 +492,10 @@ no args, if that value is non-nil."
 (defun pascal-insert-block ()
   "Insert Pascal begin ... end; block in the code with right indentation."
   (interactive)
-  (pascal-indent-line)
   (insert "begin")
   (electric-pascal-terminate-line)
   (save-excursion
-    (electric-pascal-terminate-line)
+    (newline)
     (insert "end;")
     (beginning-of-line)
     (pascal-indent-line)))
@@ -503,7 +602,7 @@ area.  See also `pascal-comment-area'."
     (if (not (looking-at (concat "\\s \\|\\s)\\|" pascal-defun-re)))
        (forward-sexp 1))
     (let ((nest 0) (max -1) (func 0)
-         (reg (concat pascal-beg-block-re "\\|" 
+         (reg (concat pascal-beg-block-re "\\|"
                       pascal-end-block-re "\\|"
                       pascal-defun-re)))
       (while (re-search-backward reg nil 'move)
@@ -535,7 +634,7 @@ area.  See also `pascal-comment-area'."
       (pascal-beg-of-defun))
   (forward-char 1)
   (let ((nest 0) (func 1)
-       (reg (concat pascal-beg-block-re "\\|" 
+       (reg (concat pascal-beg-block-re "\\|"
                     pascal-end-block-re "\\|"
                     pascal-defun-re)))
     (while (and (/= func 0)
@@ -561,7 +660,8 @@ area.  See also `pascal-comment-area'."
 (defun pascal-end-of-statement ()
   "Move forward to end of current statement."
   (interactive)
-  (let ((nest 0) pos
+  (let ((parse-sexp-ignore-comments t)
+       (nest 0) pos
        (regexp (concat "\\(" pascal-beg-block-re "\\)\\|\\("
                        pascal-end-block-re "\\)")))
     (if (not (looking-at "[ \t\n]")) (forward-sexp -1))
@@ -586,7 +686,7 @@ area.  See also `pascal-comment-area'."
        (catch 'found
          (while t
            (re-search-forward regexp nil 'move)
-           (setq nest (if (match-end 1) 
+           (setq nest (if (match-end 1)
                           (1+ nest)
                         (1- nest)))
            (cond ((eobp)
@@ -681,11 +781,12 @@ on the line which ends a function or procedure named NAME."
 (defconst pascal-indent-alist
   '((block . (+ ind pascal-indent-level))
     (case . (+ ind pascal-case-indent))
+    (caseblock . ind) (cpp . 0)
     (declaration . (+ ind pascal-indent-level))
     (paramlist . (pascal-indent-paramlist t))
-    (comment . (pascal-indent-comment t))
+    (comment . (pascal-indent-comment))
     (defun . ind) (contexp . ind)
-    (unknown . 0) (string . 0)))
+    (unknown . ind) (string . 0) (progbeg . 0)))
 
 (defun pascal-indent-command ()
   "Indent for special part of code."
@@ -713,39 +814,71 @@ on the line which ends a function or procedure named NAME."
   (let* ((indent-str (pascal-calculate-indent))
         (type (car indent-str))
         (ind (car (cdr indent-str))))
-    (if (looking-at "^[0-9a-zA-Z]+[ \t]*:[^=]")
+    ;; Labels should not be indented.
+    (if (and (looking-at "^[0-9a-zA-Z]+[ \t]*:[^=]")
+            (not (eq type 'declaration)))
        (search-forward ":" nil t))
     (delete-horizontal-space)
-    ;; Some thing should not be indented
-    (if (or (and (eq type 'declaration) (looking-at pascal-declaration-re))
-           (looking-at pascal-defun-re))
-       ()
-      ;; Other things should have no extra indent
-      (if (looking-at pascal-noindent-re)
-         (indent-to ind)
-       ;; But most lines are treated this way:
-       (indent-to (eval (cdr (assoc type pascal-indent-alist))))
-       ))))
+    (cond (; Some things should not be indented
+          (or (and (eq type 'declaration) (looking-at pascal-declaration-re))
+              (eq type 'cpp))
+          ())
+         (; Other things should have no extra indent
+          (looking-at pascal-noindent-re)
+          (indent-to ind))
+         (; Nested functions should be indented
+          (looking-at pascal-defun-re)
+          (if (and pascal-indent-nested-functions
+                   (eq type 'defun))
+              (indent-to (+ ind pascal-indent-level))
+            (indent-to ind)))
+         (; But most lines are treated this way
+          (indent-to (eval (cdr (assoc type pascal-indent-alist))))
+          ))))
 
 (defun pascal-calculate-indent ()
   "Calculate the indent of the current Pascal line.
 Return a list of two elements: (INDENT-TYPE INDENT-LEVEL)."
   (save-excursion
-    (let* ((oldpos (point))
+    (let* ((parse-sexp-ignore-comments t)
+          (oldpos (point))
           (state (save-excursion (parse-partial-sexp (point-min) (point))))
-          (nest 0) (par 0) (complete nil)
-          (elsed (looking-at "[ \t]*else\\>"))
+          (nest 0) (par 0) (complete (looking-at "[ \t]*end\\>"))
+          (elsed (looking-at "[ \t]*else\\>")) (funccnt 0)
+          (did-func (looking-at "[ \t]*\\(procedure\\|function\\)\\>"))
           (type (catch 'nesting
                   ;; Check if inside a string, comment or parenthesis
                   (cond ((nth 3 state) (throw 'nesting 'string))
                         ((nth 4 state) (throw 'nesting 'comment))
                         ((> (car state) 0)
                          (goto-char (scan-lists (point) -1 (car state)))
-                         (setq par (1+ (current-column)))))
+                         (setq par (1+ (current-column))))
+                        ((save-excursion (beginning-of-line)
+                                         (eq (following-char) ?#))
+                         (throw 'nesting 'cpp)))
                   ;; Loop until correct indent is found
                   (while t
                     (backward-sexp 1)
-                    (cond (;--Nest block outwards
+                    (cond (;--Escape from case statements
+                           (and (looking-at "[A-Za-z0-9]+[ \t]*:[^=]")
+                                (not complete)
+                                (save-excursion (skip-chars-backward " \t")
+                                                (bolp))
+                                (= (save-excursion
+                                     (end-of-line) (backward-sexp) (point))
+                                   (point))
+                                (> (save-excursion (goto-char oldpos)
+                                                   (beginning-of-line)
+                                                   (point))
+                                   (point)))
+                           (throw 'nesting 'caseblock))
+                          (;--Beginning of program
+                           (looking-at pascal-progbeg-re)
+                           (throw 'nesting 'progbeg))
+                          (;--No known statements
+                           (bobp)
+                           (throw 'nesting 'progbeg))
+                          (;--Nest block outwards
                            (looking-at pascal-beg-block-re)
                            (if (= nest 0)
                                (cond ((looking-at "case\\>")
@@ -753,16 +886,26 @@ Return a list of two elements: (INDENT-TYPE INDENT-LEVEL)."
                                      ((looking-at "record\\>")
                                       (throw 'nesting 'declaration))
                                      (t (throw 'nesting 'block)))
+                             (if (and (looking-at "record\\>") (= nest 1))
+                                 (setq funccnt (1- funccnt)))
                              (setq nest (1- nest))))
                           (;--Nest block inwards
                            (looking-at pascal-end-block-re)
                            (if (and (looking-at "end\\s ")
                                     elsed (not complete))
                                (throw 'nesting 'block))
+                           (if (= nest 0)
+                               (setq funccnt (1+ funccnt)))
                            (setq complete t
                                  nest (1+ nest)))
                           (;--Defun (or parameter list)
-                           (looking-at pascal-defun-re)
+                           (and (looking-at pascal-defun-re)
+                                (progn (setq funccnt (1- funccnt)
+                                             did-func t)
+                                       (or (bolp) (< funccnt 0))))
+                           ;; Prevent searching whole buffer
+                           (if (and (bolp) (>= funccnt 0))
+                               (throw 'nesting 'progbeg))
                            (if (= 0 par)
                                (throw 'nesting 'defun)
                              (setq par 0)
@@ -776,7 +919,9 @@ Return a list of two elements: (INDENT-TYPE INDENT-LEVEL)."
                                    (throw 'nesting 'declaration)
                                  (throw 'nesting 'paramlist)))))
                           (;--Declaration part
-                           (looking-at pascal-declaration-re)
+                           (and (looking-at pascal-declaration-re)
+                                (not did-func)
+                                (= funccnt 0))
                            (if (save-excursion
                                  (goto-char oldpos)
                                  (forward-line -1)
@@ -791,12 +936,10 @@ Return a list of two elements: (INDENT-TYPE INDENT-LEVEL)."
                            (save-excursion (forward-sexp 1)
                                            (= (following-char) ?\;))
                            (setq complete t))
-                          (;--No known statements
-                           (bobp)
-                           (throw 'nesting 'unknown))
                           )))))
+
       ;; Return type of block and indent level.
-      (if (> par 0)                               ; Unclosed Parenthesis 
+      (if (> par 0)                               ; Unclosed Parenthesis
          (list 'contexp par)
        (list type (pascal-indent-level))))))
 
@@ -812,42 +955,41 @@ Do not count labels, case-statements or records."
     (skip-chars-forward " \t")
     (current-column)))
 
-(defun pascal-indent-comment (&optional arg)
-  "Indent current line as comment.
-If optional arg is non-nil, just return the
-column number the line should be indented to."
-    (let* ((stcol (save-excursion
-                   (re-search-backward "(\\*\\|{" nil t)
-                   (1+ (current-column)))))
-      (if arg stcol
-       (delete-horizontal-space)
-       (indent-to stcol))))
+(defun pascal-indent-comment ()
+  "Return indent for current comment."
+  (save-excursion
+    (re-search-backward "\\((\\*\\)\\|{" nil t)
+    (if (match-beginning 1)
+       (1+ (current-column))
+      (current-column))))
 
 (defun pascal-indent-case ()
   "Indent within case statements."
-  (skip-chars-forward ": \t")
-  (let ((end (prog2
+  (let ((savepos (point-marker))
+       (end (prog2
                 (end-of-line)
                 (point-marker)
               (re-search-backward "\\<case\\>" nil t)))
        (beg (point)) oldpos
        (ind 0))
     ;; Get right indent
-    (while (< (point) (marker-position end))
-      (if (re-search-forward 
+    (while (< (point) end)
+      (if (re-search-forward
           "^[ \t]*[^ \t,:]+[ \t]*\\(,[ \t]*[^ \t,:]+[ \t]*\\)*:"
           (marker-position end) 'move)
          (forward-char -1))
-      (delete-horizontal-space)
-      (if (> (current-column) ind)
-         (setq ind (current-column)))
-      (pascal-end-of-statement))
+      (if (< (point) end)
+         (progn
+           (delete-horizontal-space)
+           (if (> (current-column) ind)
+               (setq ind (current-column)))
+           (pascal-end-of-statement))))
     (goto-char beg)
     (setq oldpos (marker-position end))
     ;; Indent all case statements
-    (while (< (point) (marker-position end))
+    (while (< (point) end)
       (if (re-search-forward
-          "^[ \t]*[^ \t,:]+[ \t]*\\(,[ \t]*[^ \t,:]+[ \t]*\\)*:"
+          "^[ \t]*[^][ \t,\\.:]+[ \t]*\\(,[ \t]*[^ \t,:]+[ \t]*\\)*:"
           (marker-position end) 'move)
          (forward-char -1))
       (indent-to (1+ ind))
@@ -858,7 +1000,7 @@ column number the line should be indented to."
        (insert " "))
       (setq oldpos (point))
       (pascal-end-of-statement))
-    (goto-char oldpos)))
+    (goto-char savepos)))
 
 (defun pascal-indent-paramlist (&optional arg)
   "Indent current line in parameterlist.
@@ -868,7 +1010,7 @@ indent of the current line in parameterlist."
     (let* ((oldpos (point))
           (stpos (progn (goto-char (scan-lists (point) -1 1)) (point)))
           (stcol (1+ (current-column)))
-          (edpos (progn (pascal-declaration-end) 
+          (edpos (progn (pascal-declaration-end)
                         (search-backward ")" (pascal-get-beg-of-line) t)
                         (point)))
           (usevar (re-search-backward "\\<var\\>" stpos t)))
@@ -890,7 +1032,7 @@ indent of the current line in parameterlist."
   (let ((pos (point-marker)))
     (if (and (not (or arg start)) (not (pascal-declaration-beg)))
        ()
-      (let ((lineup (if (or (looking-at "\\<var\\>\\|\\<record\\>") arg start) 
+      (let ((lineup (if (or (looking-at "\\<var\\>\\|\\<record\\>") arg start)
                        ":" "="))
            (stpos (if start start
                       (forward-word 2) (backward-word 1) (point)))
@@ -904,7 +1046,7 @@ indent of the current line in parameterlist."
        (goto-char stpos)
        ;; Indent lines in record block
        (if arg
-           (while (<= (point) (marker-position edpos))
+           (while (<= (point) edpos)
              (beginning-of-line)
              (delete-horizontal-space)
              (if (looking-at "end\\>")
@@ -915,7 +1057,7 @@ indent of the current line in parameterlist."
        ;; Do lineup
        (setq ind (pascal-get-lineup-indent stpos edpos lineup))
        (goto-char stpos)
-       (while (<= (point) (marker-position edpos))
+       (while (and (<= (point) edpos) (not (eobp)))
          (if (search-forward lineup (pascal-get-end-of-line) 'move)
              (forward-char -1))
          (delete-horizontal-space)
@@ -932,30 +1074,32 @@ indent of the current line in parameterlist."
 
     ;; If arg - move point
     (if arg (forward-line -1)
-      (goto-char (marker-position pos)))))
+      (goto-char pos))))
 
 ;  "Return the indent level that will line up several lines within the region
 ;from b to e nicely. The lineup string is str."
 (defun pascal-get-lineup-indent (b e str)
   (save-excursion
     (let ((ind 0)
-         (reg (concat str "\\|\\(\\<record\\>\\)"))
-         nest)
+         (reg (concat str "\\|\\(\\<record\\>\\)\\|" pascal-defun-re)))
       (goto-char b)
       ;; Get rightmost position
       (while (< (point) e)
-       (setq nest 1)
-       (if (re-search-forward reg (min e (pascal-get-end-of-line 2)) 'move)
-           (progn
-             ;; Skip record blocks
-             (if (match-beginning 1)
-                 (pascal-declaration-end)
-               (progn
-                 (goto-char (match-beginning 0))
-                 (skip-chars-backward " \t")
-                 (if (> (current-column) ind)
-                     (setq ind (current-column)))
-                 (goto-char (match-end 0)))))))
+       (and (re-search-forward reg (min e (pascal-get-end-of-line 2)) 'move)
+            (cond ((match-beginning 1)
+                   ;; Skip record blocks
+                   (pascal-declaration-end))
+                  ((match-beginning 2)
+                   ;; We have entered a new procedure.  Exit.
+                   (goto-char e))
+                  (t
+                   (goto-char (match-beginning 0))
+                   (skip-chars-backward " \t")
+                   (if (> (current-column) ind)
+                       (setq ind (current-column)))
+                   (goto-char (match-end 0))
+                   (end-of-line)
+                   ))))
       ;; In case no lineup was found
       (if (> ind 0)
          (1+ ind)
@@ -964,12 +1108,18 @@ indent of the current line in parameterlist."
        (end-of-line)
        (skip-chars-backward " \t")
        (1+ (current-column))))))
-    
+
 \f
 
 ;;;
 ;;; Completion
 ;;;
+(defvar pascal-str nil)
+(defvar pascal-all nil)
+(defvar pascal-pred nil)
+(defvar pascal-buffer-to-use nil)
+(defvar pascal-flag nil)
+
 (defun pascal-string-diff (str1 str2)
   "Return index of first letter where STR1 and STR2 differs."
   (catch 'done
@@ -988,31 +1138,32 @@ indent of the current line in parameterlist."
 
 (defun pascal-func-completion (type)
   ;; Build regular expression for function/procedure names
-  (if (string= str "")
-      (setq str "[a-zA-Z_]"))
-  (let ((str (concat (cond ((eq type 'procedure) "\\<\\(procedure\\)\\s +")
-                          ((eq type 'function) "\\<\\(function\\)\\s +")
-                          (t "\\<\\(function\\|procedure\\)\\s +"))
-                    "\\<\\(" str "[a-zA-Z0-9_.]*\\)\\>"))
+  (if (string= pascal-str "")
+      (setq pascal-str "[a-zA-Z_]"))
+  (let ((pascal-str (concat (cond
+                            ((eq type 'procedure) "\\<\\(procedure\\)\\s +")
+                            ((eq type 'function) "\\<\\(function\\)\\s +")
+                            (t "\\<\\(function\\|procedure\\)\\s +"))
+                           "\\<\\(" pascal-str "[a-zA-Z0-9_.]*\\)\\>"))
        match)
-  
+
     (if (not (looking-at "\\<\\(function\\|procedure\\)\\>"))
        (re-search-backward "\\<\\(function\\|procedure\\)\\>" nil t))
     (forward-char 1)
 
     ;; Search through all reachable functions
     (while (pascal-beg-of-defun)
-      (if (re-search-forward str (pascal-get-end-of-line) t)
+      (if (re-search-forward pascal-str (pascal-get-end-of-line) t)
          (progn (setq match (buffer-substring (match-beginning 2)
                                               (match-end 2)))
-                (if (or (null predicate)
-                        (funcall prdicate match))
-                    (setq all (cons match all)))))
+                (if (or (null pascal-pred)
+                        (funcall pascal-pred match))
+                    (setq pascal-all (cons match pascal-all)))))
       (goto-char (match-beginning 0)))))
 
 (defun pascal-get-completion-decl ()
   ;; Macro for searching through current declaration (var, type or const)
-  ;; for matches of `str' and adding the occurence tp `all'
+  ;; for matches of `str' and adding the occurrence to `all'
   (let ((end (save-excursion (pascal-declaration-end)
                             (point)))
        match)
@@ -1020,16 +1171,16 @@ indent of the current line in parameterlist."
     (while (< (point) end)
       (if (re-search-forward "[:=]" (pascal-get-end-of-line) t)
          ;; Traverse current line
-         (while (and (re-search-backward 
-                      (concat "\\((\\|\\<\\(var\\|type\\|const\\)\\>\\)\\|" 
+         (while (and (re-search-backward
+                      (concat "\\((\\|\\<\\(var\\|type\\|const\\)\\>\\)\\|"
                               pascal-symbol-re)
                       (pascal-get-beg-of-line) t)
                      (not (match-end 1)))
            (setq match (buffer-substring (match-beginning 0) (match-end 0)))
-           (if (string-match (concat "\\<" str) match)
-               (if (or (null predicate)
-                       (funcall predicate match))
-                   (setq all (cons match all))))))
+           (if (string-match (concat "\\<" pascal-str) match)
+               (if (or (null pascal-pred)
+                       (funcall pascal-pred match))
+                   (setq pascal-all (cons match pascal-all))))))
       (if (re-search-forward "\\<record\\>" (pascal-get-end-of-line) t)
          (pascal-declaration-end)
        (forward-line 1)))))
@@ -1062,7 +1213,7 @@ indent of the current line in parameterlist."
       (save-excursion
        (if (> start (prog1 (save-excursion (pascal-end-of-defun)
                                            (point))))
-           () ; Declarations not reacable
+           () ; Declarations not reachable
          (if (search-forward "(" (pascal-get-end-of-line) t)
              ;; Check parameterlist
                (pascal-get-completion-decl))
@@ -1081,11 +1232,11 @@ indent of the current line in parameterlist."
 
 (defun pascal-keyword-completion (keyword-list)
   "Give list of all possible completions of keywords in KEYWORD-LIST."
-  (mapcar '(lambda (s) 
-            (if (string-match (concat "\\<" str) s)
-                (if (or (null predicate)
-                        (funcall predicate s))
-                    (setq all (cons s all)))))
+  (mapcar '(lambda (s)
+            (if (string-match (concat "\\<" pascal-str) s)
+                (if (or (null pascal-pred)
+                        (funcall pascal-pred s))
+                    (setq pascal-all (cons s pascal-all)))))
          keyword-list))
 
 ;; Function passed to completing-read, try-completion or
@@ -1097,12 +1248,12 @@ indent of the current line in parameterlist."
 ;; is 'lambda, the function returns t if STR is an exact match, nil
 ;; otherwise.
 
-(defun pascal-completion (str predicate flag)
+(defun pascal-completion (pascal-str pascal-pred pascal-flag)
   (save-excursion
-    (let ((all nil))
+    (let ((pascal-all nil))
       ;; Set buffer to use for searching labels. This should be set
-      ;; within functins which use pascal-completions
-      (set-buffer buffer-to-use)
+      ;; within functions which use pascal-completions
+      (set-buffer pascal-buffer-to-use)
 
       ;; Determine what should be completed
       (let ((state (car (pascal-calculate-indent))))
@@ -1132,22 +1283,22 @@ indent of the current line in parameterlist."
               (save-excursion (pascal-var-completion))
               (pascal-func-completion 'function)
               (pascal-keyword-completion pascal-separator-keywords))))
-      
+
       ;; Now we have built a list of all matches. Give response to caller
       (pascal-completion-response))))
 
 (defun pascal-completion-response ()
-  (cond ((or (equal flag 'lambda) (null flag))
+  (cond ((or (equal pascal-flag 'lambda) (null pascal-flag))
         ;; This was not called by all-completions
-        (if (null all)
+        (if (null pascal-all)
             ;; Return nil if there was no matching label
             nil
           ;; Get longest string common in the labels
-          (let* ((elm (cdr all))
-                 (match (car all))
+          (let* ((elm (cdr pascal-all))
+                 (match (car pascal-all))
                  (min (length match))
-                 exact tmp)
-            (if (string= match str)
+                 tmp)
+            (if (string= match pascal-str)
                 ;; Return t if first match was an exact match
                 (setq match t)
               (while (not (null elm))
@@ -1157,19 +1308,19 @@ indent of the current line in parameterlist."
                       (setq min tmp)
                       (setq match (substring match 0 min))))
                 ;; Terminate with match=t if this is an exact match
-                (if (string= (car elm) str)
+                (if (string= (car elm) pascal-str)
                     (progn
                       (setq match t)
                       (setq elm nil))
                   (setq elm (cdr elm)))))
             ;; If this is a test just for exact match, return nil ot t
-            (if (and (equal flag 'lambda) (not (equal match 't)))
+            (if (and (equal pascal-flag 'lambda) (not (equal match 't)))
                 nil
               match))))
        ;; If flag is t, this was called by all-completions. Return
        ;; list of all possible completions
-       (flag
-        all)))
+       (pascal-flag
+        pascal-all)))
 
 (defvar pascal-last-word-numb 0)
 (defvar pascal-last-word-shown nil)
@@ -1182,16 +1333,17 @@ indent of the current line in parameterlist."
   (interactive)
   (let* ((b (save-excursion (skip-chars-backward "a-zA-Z0-9_") (point)))
         (e (save-excursion (skip-chars-forward "a-zA-Z0-9_") (point)))
-        (str (buffer-substring b e))
+        (pascal-str (buffer-substring b e))
         ;; The following variable is used in pascal-completion
-        (buffer-to-use (current-buffer))
+        (pascal-buffer-to-use (current-buffer))
         (allcomp (if (and pascal-toggle-completions
-                          (string= pascal-last-word-shown str))
+                          (string= pascal-last-word-shown pascal-str))
                      pascal-last-completions
-                   (all-completions str 'pascal-completion)))
+                   (all-completions pascal-str 'pascal-completion)))
         (match (if pascal-toggle-completions
                    "" (try-completion
-                       str (mapcar '(lambda (elm) (cons elm 0)) allcomp)))))
+                       pascal-str (mapcar '(lambda (elm)
+                                             (cons elm 0)) allcomp)))))
     ;; Delete old string
     (delete-region b e)
 
@@ -1200,7 +1352,7 @@ indent of the current line in parameterlist."
        (progn
          ;; Update entry number in list
          (setq pascal-last-completions allcomp
-               pascal-last-word-numb 
+               pascal-last-word-numb
                (if (>= pascal-last-word-numb (1- (length allcomp)))
                    0
                  (1+ pascal-last-word-numb)))
@@ -1208,13 +1360,13 @@ indent of the current line in parameterlist."
          ;; Display next match or same string if no match was found
          (if (not (null allcomp))
              (insert "" pascal-last-word-shown)
-           (insert "" str)
+           (insert "" pascal-str)
            (message "(No match)")))
-      ;; The other form of completion does not necessarly do that.
+      ;; The other form of completion does not necessarily do that.
 
       ;; Insert match if found, or the original string if no match
       (if (or (null match) (equal match 't))
-         (progn (insert "" str)
+         (progn (insert "" pascal-str)
                 (message "(No match)"))
        (insert "" match))
       ;; Give message about current status of completion
@@ -1222,9 +1374,10 @@ indent of the current line in parameterlist."
             (if (not (null (cdr allcomp)))
                 (message "(Complete but not unique)")
               (message "(Sole completion)")))
-           ;; Display buffer if the current completion didn't help 
+           ;; Display buffer if the current completion didn't help
            ;; on completing the label.
-           ((and (not (null (cdr allcomp))) (= (length str) (length match)))
+           ((and (not (null (cdr allcomp))) (= (length pascal-str)
+                                               (length match)))
             (with-output-to-temp-buffer "*Completions*"
               (display-completion-list allcomp))
             ;; Wait for a keypress. Then delete *Completion*  window
@@ -1237,13 +1390,13 @@ indent of the current line in parameterlist."
   (interactive)
   (let* ((b (save-excursion (skip-chars-backward "a-zA-Z0-9_") (point)))
         (e (save-excursion (skip-chars-forward "a-zA-Z0-9_") (point)))
-        (str (buffer-substring b e))
+        (pascal-str (buffer-substring b e))
         ;; The following variable is used in pascal-completion
-        (buffer-to-use (current-buffer))
+        (pascal-buffer-to-use (current-buffer))
         (allcomp (if (and pascal-toggle-completions
-                          (string= pascal-last-word-shown str))
+                          (string= pascal-last-word-shown pascal-str))
                      pascal-last-completions
-                   (all-completions str 'pascal-completion))))
+                   (all-completions pascal-str 'pascal-completion))))
     ;; Show possible completions in a temporary buffer.
     (with-output-to-temp-buffer "*Completions*"
       (display-completion-list allcomp))
@@ -1279,28 +1432,28 @@ With optional second arg non-nil, STR is the complete name of the instruction."
 ;; is an exact match. If flag is 'lambda, the function returns t if
 ;; STR is an exact match, nil otherwise.
 
-(defun pascal-comp-defun (str predicate flag)
+(defun pascal-comp-defun (pascal-str pascal-pred pascal-flag)
   (save-excursion
-    (let ((all nil)
+    (let ((pascal-all nil)
          match)
 
       ;; Set buffer to use for searching labels. This should be set
-      ;; within functins which use pascal-completions
-      (set-buffer buffer-to-use)
+      ;; within functions which use pascal-completions
+      (set-buffer pascal-buffer-to-use)
 
-      (let ((str str))
+      (let ((pascal-str pascal-str))
        ;; Build regular expression for functions
-       (if (string= str "")
-           (setq str (pascal-build-defun-re "[a-zA-Z_]"))
-         (setq str (pascal-build-defun-re str)))
+       (if (string= pascal-str "")
+           (setq pascal-str (pascal-build-defun-re "[a-zA-Z_]"))
+         (setq pascal-str (pascal-build-defun-re pascal-str)))
        (goto-char (point-min))
-      
+
        ;; Build a list of all possible completions
-       (while (re-search-forward str nil t)
+       (while (re-search-forward pascal-str nil t)
          (setq match (buffer-substring (match-beginning 2) (match-end 2)))
-         (if (or (null predicate)
-                 (funcall predicate match))
-             (setq all (cons match all)))))
+         (if (or (null pascal-pred)
+                 (funcall pascal-pred match))
+             (setq pascal-all (cons match pascal-all)))))
 
       ;; Now we have built a list of all matches. Give response to caller
       (pascal-completion-response))))
@@ -1311,7 +1464,7 @@ The default is a name found in the buffer around point."
   (interactive)
   (let* ((default (pascal-get-default-symbol))
         ;; The following variable is used in pascal-comp-function
-        (buffer-to-use (current-buffer))
+        (pascal-buffer-to-use (current-buffer))
         (default (if (pascal-comp-defun default nil 'lambda)
                      default ""))
         (label (if (not (string= default ""))
@@ -1346,8 +1499,8 @@ The default is a name found in the buffer around point."
       (setq pascal-outline-map (copy-keymap pascal-mode-map))
     (setq pascal-outline-map (make-sparse-keymap))
     (set-keymap-parent pascal-outline-map pascal-mode-map))
-  (define-key pascal-outline-map "\e\C-a"   'pascal-outline-prev-defun)
-  (define-key pascal-outline-map "\e\C-e"   'pascal-outline-next-defun)
+  (define-key pascal-outline-map "\M-\C-a"  'pascal-outline-prev-defun)
+  (define-key pascal-outline-map "\M-\C-e"  'pascal-outline-next-defun)
   (define-key pascal-outline-map "\C-c\C-d" 'pascal-outline-goto-defun)
   (define-key pascal-outline-map "\C-c\C-s" 'pascal-show-all)
   (define-key pascal-outline-map "\C-c\C-h" 'pascal-hide-other-defuns))
@@ -1391,10 +1544,11 @@ Pascal Outline mode provides some additional commands.
       (pascal-show-all)
       (use-local-map pascal-mode-map))))
 
-(defun pascal-outline-change (b e flag)
+(defun pascal-outline-change (b e pascal-flag)
   (let ((modp (buffer-modified-p)))
     (unwind-protect
-       (subst-char-in-region b e (if (= flag ?\n) ?\^M ?\n) flag)
+       (subst-char-in-region b e (if (= pascal-flag ?\n)
+                                     ?\^M ?\n) pascal-flag)
       (set-buffer-modified-p modp))))
 
 (defun pascal-show-all ()
@@ -1471,4 +1625,6 @@ Pascal Outline mode provides some additional commands.
   (pascal-goto-defun)
   (pascal-hide-other-defuns))
 
+(provide 'pascal)
+
 ;;; pascal.el ends here