changeset 25903:812005e9c20e

(ada-get-indent-*, ada-indent-current, ada-goto-*, ada-indent-newline-indent): Rewritten to support the new indentation scheme (ada-case-read-exceptions, ada-create-case-exceptions): New functions (ada-fill-comment-paragraph): Add support for the justification parameter (ada-make-body, ada-gen-treat-proc, ada-make-subprogram-body): Rewritten to benefit from the gnatstub external program
author Gerd Moellmann <gerd@gnu.org>
date Thu, 07 Oct 1999 14:33:10 +0000
parents 92828b88cfcc
children 5a88e84b63a4
files lisp/progmodes/ada-mode.el
diffstat 1 files changed, 2706 insertions(+), 2373 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/progmodes/ada-mode.el	Thu Oct 07 14:32:32 1999 +0000
+++ b/lisp/progmodes/ada-mode.el	Thu Oct 07 14:33:10 1999 +0000
@@ -1,46 +1,61 @@
-;;; ada-mode.el --- An Emacs major-mode for editing Ada source.
-
-;; Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc.
-
-;; Authors: Rolf Ebert      <re@waporo.muc.de>
-;;          Markus Heritsch <Markus.Heritsch@studbox.uni-stuttgart.de>
-;; Maintainer: Emmanual Briot <briot@gnat.com>
-;; Keywords: languages oop ada
-;; Rolf Ebert's version: 2.27
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; @(#) ada-mode.el --- major-mode for editing Ada source.
+
+;; Copyright (C) 1994-1999 Free Software Foundation, Inc.
+
+;; Author: Rolf Ebert      <ebert@inf.enst.fr>
+;;      Markus Heritsch <Markus.Heritsch@studbox.uni-stuttgart.de>
+;;      Emmanuel Briot  <briot@gnat.com>
+;; Maintainer: Emmanuel Briot <briot@gnat.com>
+;; Ada Core Technologies's version:   $Revision: 1.70 $
+;; Keywords: languages ada
+
+;; This file is not 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, or (at your option)
 ;; any later version.
 
-;; GNU Emacs is distributed in the hope that it will be useful,
+;; 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.
 
 ;; 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.
-
-;;; This mode is a complete rewrite of a major mode for editing Ada 83
-;;; and Ada 95 source code under Emacs-19.  It contains completely new
-;;; indenting code and support for code browsing (see ada-xref).
-
-
-;;; USAGE
-;;; =====
-;;; Emacs should enter Ada mode when you load an Ada source (*.ad[abs]).
+;; along with GNU Emacs; see the file COPYING.  If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+;;; Commentary:
+;;; This mode is a major mode for editing Ada83 and Ada95 source code.
+;;; This is a major rewrite of the file packaged with Emacs-20.  The
+;;; ada-mode is composed of four lisp file, ada-mode.el, ada-xref.el,
+;;; ada-prj.el and ada-stmt.el. Only this file (ada-mode.el) is
+;;; completly independant from the GNU Ada compiler Gnat, distributed
+;;; by Ada Core Technologies. All the other files rely heavily on
+;;; features provides only by Gnat.
 ;;;
-;;; When you have entered ada-mode, you may get more info by pressing
-;;; C-h m. You may also get online help describing various functions by:
-;;; C-h d <Name of function you want described>
-
-
-;;; HISTORY
-;;; =======
+;;; Note: this mode will not work with Emacs 19. If you are on a VMS
+;;; system, where the latest version of Emacs is 19.28, you will need
+;;; another file, called ada-vms.el, that provides some required
+;;; functions.
+
+;;; Usage:
+;;; Emacs should enter Ada mode automatically when you load an Ada file.
+;;; By default, the valid extensions for Ada files are .ads, .adb or .ada
+;;; If the ada-mode does not start automatically, then simply type the
+;;; following command :
+;;;     M-x ada-mode
+;;;
+;;; By default, ada-mode is configured to take full advantage of the GNAT
+;;; compiler (the menus will include the cross-referencing features,...).
+;;; If you are using another compiler, you might want to set the following
+;;; variable in your .emacs (Note: do not set this in the ada-mode-hook, it
+;;; won't work) :
+;;;    (setq ada-which-compiler 'generic)
+;;;
+;;; This mode requires find-file.el to be present on your system.
+
+;;; History:
 ;;; The first Ada mode for GNU Emacs was written by V. Broman in
 ;;; 1985. He based his work on the already existing Modula-2 mode.
 ;;; This was distributed as ada.el in versions of Emacs prior to 19.29.
@@ -55,287 +70,283 @@
 ;;; Gosling Emacs. L. Slater based his development on ada.el and
 ;;; electric-ada.el.
 ;;;
-;;; The current Ada mode is a complete rewrite by M. Heritsch and
-;;; R. Ebert.  Some ideas from the Ada mode mailing list have been
+;;; A complete rewrite by M. Heritsch and R. Ebert has been done.
+;;; Some ideas from the Ada mode mailing list have been
 ;;; added.  Some of the functionality of L. Slater's mode has not
 ;;; (yet) been recoded in this new mode.  Perhaps you prefer sticking
 ;;; to his version.
-
-
-;;; KNOWN BUGS
-;;; ==========
 ;;;
-;;; In the presence of comments and/or incorrect syntax
-;;; ada-format-paramlist produces weird results.
-;;; -------------------
-;;; Character constants with otherwise syntactic relevant characters
-;;; like `(' or `"' throw indentation off the track.  Fontification
-;;; should work now in Emacs-19.35
-;;; C : constant Character := Character'('"');
-;;; -------------------
-
-
-;;; TODO
-;;; ====
-;;;
-;;; o bodify-single-subprogram
-;;; o make a function "separate" and put it in the corresponding file.
-
-
-
-;;; CREDITS
-;;; =======
-;;;
-;;; Many thanks to
-;;;    Philippe Waroquiers (PW) <philippe@cfmu.eurocontrol.be> in particular,
-;;;    woodruff@stc.llnl.gov (John Woodruff)
-;;;    jj@ddci.dk (Jesper Joergensen)
-;;;    gse@ocsystems.com (Scott Evans)
-;;;    comar@LANG8.CS.NYU.EDU (Cyrille Comar)
+;;; A complete rewrite for Emacs-20 / Gnat-3.11 has been done by Ada Core
+;;; Technologies. Please send bugs to  briot@gnat.com
+
+;;; Credits:
+;;;   Many thanks to John McCabe <john@assen.demon.co.uk> for sending so
+;;;     many patches included in this package.
+;;;   Christian Egli <Christian.Egli@hcsd.hac.com>:
+;;;     ada-imenu-generic-expression
+;;;   Many thanks also to the following persons that have contributed one day
+;;;   to the ada-mode
+;;;     Philippe Waroquiers (PW) <philippe@cfmu.eurocontrol.be> in particular,
+;;;     woodruff@stc.llnl.gov (John Woodruff)
+;;;     jj@ddci.dk (Jesper Joergensen)
+;;;     gse@ocsystems.com (Scott Evans)
+;;;     comar@gnat.com (Cyrille Comar)
+;;;     stephen.leake@gsfc.nasa.gov (Stephen Leake)
 ;;;    and others for their valuable hints.
-
-;;;--------------------
-;;;    USER OPTIONS
-;;;--------------------
-
-
-;; ---- customize support
+
+;;; Code:
+;;; Note: Every function is this package is compiler-independent.
+;;; The names start with  ada-
+;;; The variables that the user can edit can all be modified throught
+;;;   the customize mode. They are sorted in alphabetical order in this
+;;;   file.
+
+
+;; this function is needed at compile time
+(eval-and-compile
+  (defun ada-check-emacs-version (major minor &optional is_xemacs)
+    "Returns t if Emacs's version is greater or equal to major.minor.
+if IS_XEMACS is non-nil, check for XEmacs instead of Emacs"
+    (let ((xemacs_running (or (string-match "Lucid"  emacs-version)
+			      (string-match "XEmacs" emacs-version))))
+      (and (or (and is_xemacs xemacs_running)
+	     (not (or is_xemacs xemacs_running)))
+	   (or (> emacs-major-version major)
+	       (and (= emacs-major-version major)
+		    (>= emacs-minor-version minor)))))))
+  
+
+;;  We create a constant for that, for efficiency only
+;;  This should not be evaluated at compile time, only a runtime
+(defconst ada-xemacs (boundp 'running-xemacs)
+  "Return t if we are using XEmacs")
+
+(unless ada-xemacs
+  (require 'outline))
+
+(eval-and-compile
+  (condition-case nil (require 'find-file) (error nil)))
+
+;;  This call should not be made in the release that is done for the
+;;  official FSF Emacs, since it does nothing useful for the latest version
+(require 'ada-support)
+
+(defvar ada-mode-hook nil
+  "*List of functions to call when Ada mode is invoked.
+This hook is automatically executed after the ada-mode is
+fully loaded.
+This is a good place to add Ada environment specific bindings.")
 
 (defgroup ada nil
   "Major mode for editing Ada source in Emacs"
   :group 'languages)
 
-;; ---- configure indentation
-
-(defcustom ada-indent 3
-  "*Defines the size of Ada indentation."
-  :type 'integer
-  :group 'ada)
+(defcustom ada-auto-case t
+  "*Non-nil means automatically change case of preceding word while typing.
+Casing is done according to `ada-case-keyword', `ada-case-identifier'
+and `ada-case-attribute'."
+  :type 'boolean :group 'ada)
+
+(defcustom ada-broken-decl-indent 0
+  "*Number of columns to indent a broken declaration.
+
+An example is :
+  declare
+     A,
+     >>>>>B : Integer;  --  from ada-broken-decl-indent"
+  :type 'integer :group 'ada)
 
 (defcustom ada-broken-indent 2
-  "*# of columns to indent the continuation of a broken line."
-  :type 'integer
-  :group 'ada)
-
-(defcustom ada-label-indent -4
-  "*# of columns to indent a label."
-  :type 'integer
-  :group 'ada)
-
-(defcustom ada-stmt-end-indent 0
-  "*# of columns to indent a statement end keyword in a separate line.
-Examples are 'is', 'loop', 'record', ..."
-  :type 'integer
-  :group 'ada)
-
-(defcustom ada-when-indent 3
-  "*Defines the indentation for 'when' relative to 'exception' or 'case'."
-  :type 'integer
-  :group 'ada)
-
-(defcustom ada-indent-record-rel-type 3
-  "*Defines the indentation for 'record' relative to 'type' or 'use'."
-  :type 'integer
-  :group 'ada)
-
-(defcustom ada-indent-comment-as-code t
-  "*If non-nil, comment-lines get indented as Ada code."
-  :type 'boolean
-  :group 'ada)
-
-(defcustom ada-indent-is-separate t
-  "*If non-nil, 'is separate' or 'is abstract' on a single line are indented."
-  :type 'boolean
-  :group 'ada)
-
-(defcustom ada-indent-to-open-paren t
-  "*If non-nil, indent according to the innermost open parenthesis."
-  :type 'boolean
-  :group 'ada)
-
-(defcustom ada-search-paren-char-count-limit 3000
-  "*Search that many characters for an open parenthesis."
-  :type 'integer
+  "*Number of columns to indent the continuation of a broken line.
+
+An example is :
+   My_Var : My_Type := (Field1 =>
+                        >>>>>>>>>Value);  -- from ada-broken-indent"
+  :type 'integer :group 'ada)
+
+(defcustom ada-case-attribute 'ada-capitalize-word
+  "*Function to call to adjust the case of Ada attributes.
+It may be `downcase-word', `upcase-word', `ada-loose-case-word' or
+`ada-capitalize-word'."
+  :type '(choice (const downcase-word)
+                 (const upcase-word)
+                 (const ada-capitalize-word)
+                 (const ada-loose-case-word))
   :group 'ada)
 
-
-;; ---- other user options
-
-(defcustom ada-tab-policy 'indent-auto
-  "*Control behaviour of the TAB key.
-Must be one of `indent-rigidly', `indent-auto', `gei', `indent-af'
-or `always-tab'.
-
-`indent-rigidly' : always adds ada-indent blanks at the beginning of the line.
-`indent-auto'    : use indentation functions in this file.
-`gei'            : use David Kågedal's Generic Indentation Engine.
-`indent-af'      : use Gary E. Barnes' ada-format.el
-`always-tab'     : do indent-relative."
-  :type '(choice (const indent-auto)
-                 (const indent-rigidly)
-                 (const gei)
-                 (const indent-af)
-                 (const always-tab))
-  :group 'ada)
-
-(defcustom ada-move-to-declaration nil
-  "*If non-nil, `ada-move-to-start' moves point to the subprog declaration,
-not to 'begin'."
-  :type 'boolean
-  :group 'ada)
-
-(defcustom ada-spec-suffix ".ads"
-  "*Suffix of Ada specification files."
-  :type 'string
-  :group 'ada)
-
-(defcustom ada-body-suffix ".adb"
-  "*Suffix of Ada body files."
-  :type 'string
-  :group 'ada)
-
-(defcustom ada-spec-suffix-as-regexp "\\.ads$"
-  "*Regexp to find Ada specification files."
-  :type 'string
-  :group 'ada)
-
-(defcustom ada-body-suffix-as-regexp "\\.adb$"
-  "*Regexp to find Ada body files."
-  :type 'string
-  :group 'ada)
-
-(defvar ada-other-file-alist
-  (list
-   (list ada-spec-suffix-as-regexp (list ada-body-suffix))
-   (list ada-body-suffix-as-regexp (list ada-spec-suffix))
-   )
-  "*Alist of extensions to find given the current file's extension.
-
-This list should contain the most used extensions before the others,
-since the search algorithm searches sequentially through each directory
-specified in `ada-search-directories'.  If a file is not found, a new one
-is created with the first matching extension (`.adb' yields `.ads').")
-
-(defcustom ada-search-directories
-  '("." "/usr/adainclude" "/usr/local/adainclude" "/opt/gnu/adainclude")
-  "*List of directories to search for Ada files.
-See the description for the `ff-search-directories' variable."
-  :type '(repeat (choice :tag "Directory"
-                         (const :tag "default" nil)
-                         (directory :format "%v")))
-  :group 'ada)
-
-(defcustom ada-language-version 'ada95
-  "*Do we program in `ada83' or `ada95'?"
-  :type '(choice (const ada83)
-                 (const ada95))
-  :group 'ada)
+(defcustom ada-case-exception-file "~/.emacs_case_exceptions"
+  "*Name of the file that contains the list of special casing
+exceptions for identifiers.
+This file should contain one word per line, that gives the casing
+to be used for that words in Ada files"
+  :type 'file :group 'ada)
 
 (defcustom ada-case-keyword 'downcase-word
   "*Function to call to adjust the case of Ada keywords.
-It may be `downcase-word', `upcase-word', `ada-loose-case-word' or 
-`capitalize-word'."
+It may be `downcase-word', `upcase-word', `ada-loose-case-word' or
+`ada-capitalize-word'."
   :type '(choice (const downcase-word)
                  (const upcase-word)
-                 (const capitalize-word)
+                 (const ada-capitalize-word)
                  (const ada-loose-case-word))
   :group 'ada)
 
 (defcustom ada-case-identifier 'ada-loose-case-word
   "*Function to call to adjust the case of an Ada identifier.
-It may be `downcase-word', `upcase-word', `ada-loose-case-word' or 
-`capitalize-word'."
+It may be `downcase-word', `upcase-word', `ada-loose-case-word' or
+`ada-capitalize-word'."
   :type '(choice (const downcase-word)
                  (const upcase-word)
-                 (const capitalize-word)
+                 (const ada-capitalize-word)
                  (const ada-loose-case-word))
   :group 'ada)
 
-(defcustom ada-case-attribute 'capitalize-word
-  "*Function to call to adjust the case of Ada attributes.
-It may be `downcase-word', `upcase-word', `ada-loose-case-word' or 
-`capitalize-word'."
-  :type '(choice (const downcase-word)
-                 (const upcase-word)
-                 (const capitalize-word)
-                 (const ada-loose-case-word))
-  :group 'ada)
-
-(defcustom ada-auto-case t
-  "*Non-nil automatically changes case of preceding word while typing.
-Casing is done according to `ada-case-keyword', `ada-case-identifier'
-and `ada-case-attribute'."
-  :type 'boolean
-  :group 'ada)
-
 (defcustom ada-clean-buffer-before-saving t
-  "*If non-nil, `remove-trailing-spaces' and `untabify' buffer before saving."
-  :type 'boolean
-  :group 'ada)
-
-(defvar ada-mode-hook nil
-  "*List of functions to call when Ada mode is invoked.
-This is a good place to add Ada environment specific bindings.")
-
-(defcustom ada-external-pretty-print-program "aimap"
-  "*External pretty printer to call from within Ada mode."
-  :type 'string
-  :group 'ada)
-
-(defcustom ada-tmp-directory temporary-file-directory
-  "*Directory to store the temporary file for the Ada pretty printer."
-  :type 'string
-  :group 'ada)
-
-(defcustom ada-compile-options "-c"
-  "*Buffer local options passed to the Ada compiler.
-These options are used when the compiler is invoked on the current buffer."
-  :type 'string
-  :group 'ada)
-(make-variable-buffer-local 'ada-compile-options)
-
-(defcustom ada-make-options "-c"
-  "*Buffer local options passed to `ada-compiler-make' (usually `gnatmake').
-These options are used when `gnatmake' is invoked on the current buffer."
-  :type 'string
-  :group 'ada)
-(make-variable-buffer-local 'ada-make-options)
-
-(defcustom ada-compiler-syntax-check "gcc -c -gnats"
-  "*Compiler command with options for syntax checking."
-  :type 'string
-  :group 'ada)
-
-(defcustom ada-compiler-make "gnatmake"
-  "*The `make' command for the given compiler."
-  :type 'string
-  :group 'ada)
+  "*Non-nil means `remove-trailing-spaces' and `untabify' buffer before saving."
+  :type 'boolean :group 'ada)
+
+(defcustom ada-indent 3
+  "*Size of Ada indentation.
+
+An example is :
+procedure Foo is
+begin
+>>>>>>>>>>null;  --  from ada-indent"
+  :type 'integer  :group 'ada)
+
+(defcustom ada-indent-after-return t
+  "*Non-nil means automatically indent after RET or LFD."
+  :type 'boolean :group 'ada)
+
+(defcustom ada-indent-comment-as-code t
+  "*Non-nil means indent comment lines as code"
+  :type 'boolean :group 'ada)
+
+(defcustom ada-indent-is-separate t
+  "*Non-nil means indent 'is separate' or 'is abstract' if on a single line."
+  :type 'boolean :group 'ada)
+
+(defcustom ada-indent-record-rel-type 3
+  "*Indentation for 'record' relative to 'type' or 'use'.
+
+An example is:
+   type A is
+   >>>>>>>>>>>record    --  from ada-indent-record-rel-type"
+  :type 'integer :group 'ada)
+
+(defcustom ada-indent-return 0
+  "*Indentation for 'return' relative to the matching 'function' statement.
+If ada-indent-return is null or negative, the indentation is done relative to
+the open parenthesis (if there is no parenthesis, ada-broken-indent is used)
+
+An example is:
+   function A (B : Integer)
+   >>>>>return C;       --  from ada-indent-return"
+  :type 'integer :group 'ada)
+
+(defcustom ada-indent-to-open-paren t
+  "*Non-nil means indent according to the innermost open parenthesis."
+  :type 'boolean :group 'ada)
 
 (defcustom ada-fill-comment-prefix "-- "
-  "*This is inserted in the first columns when filling a comment paragraph."
-  :type 'string
-  :group 'ada)
+  "*Text inserted in the first columns when filling a comment paragraph.
+Note: if you modify this variable, you will have to restart the ada-mode to
+reread this variable."
+  :type 'string :group 'ada)
 
 (defcustom ada-fill-comment-postfix " --"
-  "*This is inserted at the end of each line when filling a comment paragraph.
+  "*Text inserted at the end of each line when filling a comment paragraph.
 with `ada-fill-comment-paragraph-postfix'."
-  :type 'string
+  :type 'string :group 'ada)
+
+(defcustom ada-label-indent -4
+  "*Number of columns to indent a label.
+
+An example is:
+procedure Foo is
+begin
+>>>>>>>>>>>>Label:  --  from ada-label-indent"
+  :type 'integer :group 'ada)
+
+(defcustom ada-language-version 'ada95
+  "*Do we program in `ada83' or `ada95'?"
+  :type '(choice (const ada83) (const ada95)) :group 'ada)
+
+(defcustom ada-move-to-declaration nil
+  "*Non-nil means `ada-move-to-start' moves point to the subprog declaration,
+not to 'begin'."
+  :type 'boolean :group 'ada)
+
+(defcustom ada-popup-key '[down-mouse-3]
+  "*Key used for binding the contextual menu.
+if nil, no contextual menu is available")
+
+(defcustom ada-search-directories
+  '("." "$ADA_INCLUDE_PATH" "/usr/adainclude" "/usr/local/adainclude"
+    "/opt/gnu/adainclude")
+  "*List of directories to search for Ada files.  See the description
+for the `ff-search-directories' variable.
+Emacs will automatically add the paths defined in your project file."
+  :type '(repeat (choice :tag "Directory"
+                         (const :tag "default" nil)
+                         (directory :format "%v")))
   :group 'ada)
 
-(defcustom ada-krunch-args "0"
-  "*Argument of gnatkr, a string containing the max number of characters.
-Set to 0, if you don't use crunched filenames."
-  :type 'string
+(defcustom ada-stmt-end-indent 0
+  "*Number of columns to indent a statement end keyword on a separate line.
+
+An example is:
+   if A = B
+   >>>>>>>>>>>then   --  from ada-stmt-end-indent"
+  :type 'integer :group 'ada)
+
+(defcustom ada-tab-policy 'indent-auto
+  "*Control the behaviour of the TAB key.
+This is used only in the ada-tab and ada-untab functions.
+Must be one of :
+`indent-rigidly' : always adds ada-indent blanks at the beginning of the line.
+`indent-auto'    : use indentation functions in this file.
+`always-tab'     : do indent-relative."
+  :type '(choice (const indent-auto)
+                 (const indent-rigidly)
+                 (const always-tab))
   :group 'ada)
 
+(defcustom ada-when-indent 3
+  "*Indentation for 'when' relative to 'exception' or 'case'.
+
+An example is:
+   case A is
+   >>>>>>>>when B =>     --  from ada-when-indentx"
+  :type 'integer :group 'ada)
+
+(defcustom ada-which-compiler 'gnat
+  "*Name of the compiler we use. This will determine what features are
+made available through the ada-mode. The possible choices are :
+
+`gnat': Use Ada Core Technologies' Gnat compiler. Add some cross-referencing
+    features
+`generic': Use a generic compiler"
+  :type '(choice (const gnat)
+                 (const generic))
+  :group 'ada)
+
+
 ;;; ---- end of user configurable variables
 
 
-(defvar ada-mode-abbrev-table nil
-  "Abbrev table used in Ada mode.")
-(define-abbrev-table 'ada-mode-abbrev-table ())
-
-(defvar ada-mode-map ()
+(defvar ada-body-suffixes '(".adb")
+  "List of possible suffixes for Ada body files. The extensions should
+include a `.' if needed")
+
+(defvar ada-spec-suffixes '(".ads")
+  "List of possible suffixes for Ada spec files. The extensions should
+include a `.' if needed")
+
+(defvar ada-mode-menu (make-sparse-keymap)
+  "Menu for ada-mode")
+
+(defvar ada-mode-map (make-sparse-keymap)
   "Local keymap used for Ada mode.")
 
 (defvar ada-mode-syntax-table nil
@@ -344,56 +355,60 @@
 (defvar ada-mode-symbol-syntax-table nil
   "Syntax table for Ada, where `_' is a word constituent.")
 
+(eval-when-compile
+  (defconst ada-83-string-keywords
+    '("abort" "abs" "accept" "access" "all" "and" "array" "at" "begin"
+      "body" "case" "constant" "declare" "delay" "delta" "digits" "do"
+      "else" "elsif" "end" "entry" "exception" "exit" "for" "function"
+      "generic" "goto" "if" "in" "is" "limited" "loop" "mod" "new"
+      "not" "null" "of" "or" "others" "out" "package" "pragma" "private"
+      "procedure" "raise" "range" "record" "rem" "renames" "return"
+      "reverse" "select" "separate" "subtype" "task" "terminate" "then"
+      "type" "use" "when" "while" "with" "xor")
+    "List of ada keywords  -- This variable is not used instead to define
+ada-83-keywords and ada-95-keywords"))
+
+(defvar ada-ret-binding nil
+  "Variable to save key binding of RET when casing is activated.")
+
+(defvar ada-case-exception '()
+  "Alist of words (entities) that have special casing, and should not
+be reindented according to the function `ada-case-identifier'.
+Its value is read from the file `ada-case-exception-file'")
+
+(defvar ada-lfd-binding nil
+  "Variable to save key binding of LFD when casing is activated.")
+
+(defvar ada-other-file-alist nil
+  "Variable used by find-file to find the name of the other package.
+See `ff-other-file-alist'"
+  )
+
+;;; ---- Below are the regexp used in this package for parsing
+
 (defconst ada-83-keywords
-  "\\<\\(abort\\|abs\\|accept\\|access\\|all\\|and\\|array\\|\
-at\\|begin\\|body\\|case\\|constant\\|declare\\|delay\\|delta\\|\
-digits\\|do\\|else\\|elsif\\|end\\|entry\\|exception\\|exit\\|for\\|\
-function\\|generic\\|goto\\|if\\|in\\|is\\|limited\\|loop\\|mod\\|\
-new\\|not\\|null\\|of\\|or\\|others\\|out\\|package\\|pragma\\|\
-private\\|procedure\\|raise\\|range\\|record\\|rem\\|renames\\|\
-return\\|reverse\\|select\\|separate\\|subtype\\|task\\|terminate\\|\
-then\\|type\\|use\\|when\\|while\\|with\\|xor\\)\\>"
-;  "\\<\\(a\\(b\\(ort\\|s\\)\\|cce\\(pt\\|ss\\)\\|ll\\|nd\\|rray\\|t\\)\\|\
-;b\\(egin\\|ody\\)\\|c\\(ase\\|onstant\\)\\|\
-;d\\(e\\(clare\\|l\\(ay\\|ta\\)\\)\\|igits\\|o\\)\\|\
-;e\\(ls\\(e\\|if\\)\\|n\\(d\\|try\\)\\|x\\(ception\\|it\\)\\)\\|\
-;f\\(or\\|unction\\)\\|g\\(eneric\\|oto\\)\\|i[fns]\\|l\\(imited\\|oop\\)\\|\
-;mod\\|n\\(ew\\|ot\\|ull\\)\\|o\\([fr]\\|thers\\|ut\\)\\|\
-;p\\(ackage\\|r\\(agma\\|ivate\\|ocedure\\)\\)\\|\
-;r\\(a\\(ise\\|nge\\)\\|e\\(cord\\|m\\|names\\|turn\\|verse\\)\\)\\|\
-;s\\(e\\(lect\\|parate\\)\\|ubtype\\)\\|use\\|
-;t\\(ask\\|erminate\\|hen\\|ype\\)\\|w\\(h\\(en\\|ile\\)\\|ith\\)\\|xor\\)\\>"
+  (eval-when-compile
+    (concat "\\<" (regexp-opt ada-83-string-keywords t) "\\>"))
   "Regular expression for looking at Ada83 keywords.")
 
 (defconst ada-95-keywords
-  "\\<\\(abort\\|abs\\|abstract\\|accept\\|access\\|aliased\\|\
-all\\|and\\|array\\|at\\|begin\\|body\\|case\\|constant\\|declare\\|\
-delay\\|delta\\|digits\\|do\\|else\\|elsif\\|end\\|entry\\|\
-exception\\|exit\\|for\\|function\\|generic\\|goto\\|if\\|in\\|\
-is\\|limited\\|loop\\|mod\\|new\\|not\\|null\\|of\\|or\\|others\\|\
-out\\|package\\|pragma\\|private\\|procedure\\|protected\\|raise\\|\
-range\\|record\\|rem\\|renames\\|requeue\\|return\\|reverse\\|\
-select\\|separate\\|subtype\\|tagged\\|task\\|terminate\\|then\\|\
-type\\|until\\|use\\|when\\|while\\|with\\|xor\\)\\>"
+  (eval-when-compile
+    (concat "\\<" (regexp-opt
+                   (append
+                    '("abstract" "aliased" "protected" "requeue"
+                      "tagged" "until")
+                    ada-83-string-keywords) t) "\\>"))
   "Regular expression for looking at Ada95 keywords.")
 
 (defvar ada-keywords ada-95-keywords
   "Regular expression for looking at Ada keywords.")
 
-(defvar ada-ret-binding nil
-  "Variable to save key binding of RET when casing is activated.")
-
-(defvar ada-lfd-binding nil
-  "Variable to save key binding of LFD when casing is activated.")
-
-;;; ---- Regexps to find procedures/functions/packages
-
-(defconst ada-ident-re 
-  "[a-zA-Z0-9_\\.]+"
+(defconst ada-ident-re
+  "\\(\\sw\\|[_.]\\)+"
   "Regexp matching Ada (qualified) identifiers.")
 
 (defvar ada-procedure-start-regexp
-  "^[ \t]*\\(procedure\\|function\\|task\\)[ \t\n]+\\([a-zA-Z0-9_\\.]+\\)"
+  "^[ \t]*\\(procedure\\|function\\|task\\)[ \t\n]+\\(\\(\\sw\\|[_.]\\)+\\)"
   "Regexp used to find Ada procedures/functions.")
 
 (defvar ada-package-start-regexp
@@ -404,57 +419,145 @@
 ;;; ---- regexps for indentation functions
 
 (defvar ada-block-start-re
-  "\\<\\(begin\\|select\\|declare\\|private\\|or\\|generic\\|\
-exception\\|loop\\|else\\|\
-\\(\\(limited\\|abstract\\|tagged\\)[ \t]+\\)*record\\)\\>"
+  (eval-when-compile
+    (concat "\\<\\(" (regexp-opt '("begin" "declare" "else"
+                                   "exception" "generic" "loop" "or"
+                                   "private" "select" ))
+            "\\|\\(\\(limited\\|abstract\\|tagged\\)[ \t\n]+\\)*record\\)\\>"))
   "Regexp for keywords starting Ada blocks.")
 
 (defvar ada-end-stmt-re
-  "\\(;\\|=>\\|^[ \t]*separate[ \t]+([a-zA-Z0-9_\\.]+)\\|\
-\\<\\(begin\\|else\\|record\\|loop\\|select\\|do\\|then\\|\
-declare\\|generic\\|private\\)\\>\\|\
-^[ \t]*\\(package\\|procedure\\|function\\)\\>[ \ta-zA-Z0-9_\\.]+\\<is\\>\\|\
-^[ \t]*exception\\>\\)"
+  (eval-when-compile
+    (concat "\\("
+            ";"                                        "\\|"
+            "=>[ \t]*$"                                "\\|"
+            "^[ \t]*separate[ \t]*(\\(\\sw\\|[_.]\\)+)"  "\\|"
+            "\\<" (regexp-opt '("begin" "declare" "is" "do" "else" "generic" "loop"
+                                "private" "record" "select" "then") t) "\\>"  "\\|"
+            "^[ \t]*" (regexp-opt '("function" "package" "procedure")
+                                  t) "\\>\\(\\sw\\|[ \t_.]\\)+\\<is\\>"        "\\|"
+            "^[ \t]*exception\\>"
+            "\\)")                      )
   "Regexp of possible ends for a non-broken statement.
 A new statement starts after these.")
 
+(defvar ada-matching-start-re
+  (eval-when-compile
+    (concat "\\<"
+            (regexp-opt
+             '("end" "loop" "select" "begin" "case" "do"
+               "if" "task" "package" "record" "protected") t)
+            "\\>"))
+  "Regexp used in ada-goto-matching-start")
+
+(defvar ada-matching-decl-start-re
+  (eval-when-compile
+    (concat "\\<"
+            (regexp-opt
+             '("is" "separate" "end" "declare" "if" "new" "begin" "generic") t)
+            "\\>"))
+  "Regexp used in ada-goto-matching-decl-start")
+
+
 (defvar ada-loop-start-re
   "\\<\\(for\\|while\\|loop\\)\\>"
   "Regexp for the start of a loop.")
 
 (defvar ada-subprog-start-re
-  "\\<\\(procedure\\|protected\\|package\\|function\\|\
-task\\|accept\\|entry\\)\\>"
+  (eval-when-compile
+    (concat "\\<" (regexp-opt '("accept" "entry" "function" "package" "procedure"
+                                "protected" "task") t) "\\>"))
   "Regexp for the start of a subprogram.")
 
 (defvar ada-named-block-re
-  "[ \t]*[a-zA-Z_0-9]+ *:[^=]"
+  "[ \t]*\\(\\sw\\|_\\)+[ \t]*:[^=]"
   "Regexp of the name of a block or loop.")
 
+
+
+;;------------------------------------------------------------------
+;; Support for imenu  (see imenu.el)
+;;------------------------------------------------------------------
+
+(defvar ada-imenu-generic-expression
+  (list
+   '(nil "^[ \t]*\\(procedure\\|function\\)[ \t\n]+\\(\\(\\sw\\|_\\)+\\)[ \t\n]*\\([ \t\n]\\|([^)]+)\\)[ \t\n]*\\(return[ \t\n]+\\(\\sw\\|[_.]\\)+[ \t\n]*\\)?is[ \t\n]" 2)
+   (list "*Specs*"
+         (concat
+          "^[ \t]*\\(procedure\\|function\\)[ \t\n]+\\(\\(\\sw\\|_\\)+\\)"
+          "\\("
+          "\\([ \t\n]+\\|[ \t\n]*([^)]+)\\)";; parameter list or simple space
+          "\\([ \t\n]*return[ \t\n]+\\(\\sw\\|[_.]\\)+[ \t\n]*\\)?"
+          "\\)?;") 2)
+   '("*Tasks*" "^[ \t]*task[ \t]+\\(\\(body\\|type\\)[ \t]+\\)?\\(\\(\\sw\\|_\\)+\\)" 3)
+   '("*Type Defs*" "^[ \t]*\\(sub\\)?type[ \t]+\\(\\(\\sw\\|_\\)+\\)" 2)
+   '("*Packages*" "^[ \t]*package[ \t]+\\(\\(body[ \t]+\\)?\\(\\sw\\|[_.]\\)+\\)" 1))
+  "Imenu generic expression for Ada mode.  See `imenu-generic-expression'.
+This variable will create two submenus, one for type and subtype definitions,
+the other for subprograms declarations. The main menu will reference the bodies
+of the subprograms.")
+
 
-;; Written by Christian Egli <Christian.Egli@hcsd.hac.com>
-;;
-(defvar ada-imenu-generic-expression
-      '((nil "^\\s-*\\(procedure\\|function\\)\\s-+\\([A-Za-z0-9_]+\\)" 2)
-	("Type Defs" "^\\s-*\\(sub\\)?type\\s-+\\([A-Za-z0-9_]+\\)" 2))
-
-  "Imenu generic expression for Ada mode.  See `imenu-generic-expression'.")
-
+
+;;------------------------------------------------------------
+;;  Supporte for compile.el
+;;------------------------------------------------------------
+
+(defun ada-compile-mouse-goto-error ()
+  "mouse interface for ada-compile-goto-error"
+  (interactive)
+  (mouse-set-point last-input-event)
+  (ada-compile-goto-error (point))
+  )
+
+(defun ada-compile-goto-error (pos)
+  "replaces compile-goto-error from compile.el: if point is on an file and line
+location, go to this position. It adds to compile.el the capacity to go to a
+reference in an error message.
+For instance, on this line:
+  foo.adb:61:11: missing argument for parameter set in call to size declared at foo.ads:11
+both file locations can be clicked on and jumped to"
+  (interactive "d")
+  (goto-char pos)
+
+  (skip-chars-backward "-a-zA-Z0-9_:./\\")
+  (cond
+   ;;  special case: looking at a filename:line not at the beginning of a line
+   ((and (not (bolp))
+	 (looking-at
+	  "\\(\\(\\sw\\|[_-.]\\)+\\):\\([0-9]+\\)\\(:\\([0-9]+\\)\\)?"))
+    (let ((line (match-string 3))
+          (error-pos (point-marker))
+          source)
+      (save-excursion
+        (save-restriction
+          (widen)
+          (set-buffer (compilation-find-file (point-marker) (match-string 1)
+                                             "./"))
+          (if (stringp line)
+              (goto-line (string-to-number line)))
+          (set 'source (point-marker))))
+      (compilation-goto-locus (cons source error-pos))
+      ))
+
+   ;; otherwise, default behavior
+   (t
+    (compile-goto-error))
+   )
+  (recenter))
+
 ;;;-------------
 ;;;  functions
 ;;;-------------
 
-(defun ada-xemacs ()
-  (or (string-match "Lucid"  emacs-version)
-      (string-match "XEmacs" emacs-version)))
-
 (defun ada-create-syntax-table ()
   "Create the syntax table for Ada mode."
   ;; There are two different syntax-tables.  The standard one declares
-  ;; `_' as a symbol constituent, in the second one, it is a word
-  ;; constituent.  For some search and replacing routines we
+  ;; `_' as a symbol constituant, in the second one, it is a word
+  ;; constituant.  For some search and replacing routines we
   ;; temporarily switch between the two.
-  (setq ada-mode-syntax-table (make-syntax-table))
+  (interactive)
+  (set 'ada-mode-syntax-table (make-syntax-table))
   (set-syntax-table  ada-mode-syntax-table)
 
   ;; define string brackets (`%' is alternative string bracket, but
@@ -463,8 +566,6 @@
   (modify-syntax-entry ?%  "$" ada-mode-syntax-table)
   (modify-syntax-entry ?\" "\"" ada-mode-syntax-table)
 
-  (modify-syntax-entry ?\#  "$" ada-mode-syntax-table)
-
   (modify-syntax-entry ?:  "." ada-mode-syntax-table)
   (modify-syntax-entry ?\; "." ada-mode-syntax-table)
   (modify-syntax-entry ?&  "." ada-mode-syntax-table)
@@ -487,6 +588,17 @@
   ;; a single hyphen is punctuation, but a double hyphen starts a comment
   (modify-syntax-entry ?-  ". 12" ada-mode-syntax-table)
 
+  ;; # is set to be a matched-pair, since it is used for based numbers,
+  ;; as in 16#3f#. The syntax class will be modifed later when it
+  ;; appears at the beginning of a line for gnatprep statements.
+  ;; For Emacs, the modification is done in font-lock-syntactic-keywords
+  ;; or ada-after-change-function.
+  ;; For XEmacs, this is not done correctly for now, based numbers won't
+  ;; be handled correctly.
+  (if ada-xemacs
+      (modify-syntax-entry ?#  "<" ada-mode-syntax-table)
+    (modify-syntax-entry ?#  "$" ada-mode-syntax-table))
+
   ;; and \f and \n end a comment
   (modify-syntax-entry ?\f  ">   " ada-mode-syntax-table)
   (modify-syntax-entry ?\n  ">   " ada-mode-syntax-table)
@@ -498,10 +610,200 @@
   (modify-syntax-entry ?\( "()" ada-mode-syntax-table)
   (modify-syntax-entry ?\) ")(" ada-mode-syntax-table)
 
-  (setq ada-mode-symbol-syntax-table (copy-syntax-table ada-mode-syntax-table))
+  (set 'ada-mode-symbol-syntax-table (copy-syntax-table ada-mode-syntax-table))
   (modify-syntax-entry ?_ "w" ada-mode-symbol-syntax-table)
   )
 
+;;
+;;  This is to support XEmacs, which does not have the syntax-table attribute
+;;  as used in ada-after-change-function
+;;  When executing parse-partial-sexp, we simply modify the strings before and
+;;  after, so that the special constants '"', '(' and ')' do not interact
+;;  with parse-partial-sexp.
+
+(if ada-xemacs
+    (defadvice parse-partial-sexp (around parse-partial-sexp-protect-constants)
+      (let (change)
+        (if (< to from)
+            (let ((tmp from))
+              (setq from to  to tmp)))
+        (save-excursion
+          (goto-char from)
+          (while (re-search-forward "'\\([(\")#]\\)'" to t)
+            (set 'change (cons (list (match-beginning 1)
+                                     1
+                                     (match-string 1))
+                               change))
+            (replace-match "'A'"))
+          (goto-char from)
+          (while (re-search-forward "\\(#[0-9a-fA-F]*#\\)" to t)
+            (set 'change (cons (list (match-beginning 1)
+                                     (length (match-string 1))
+                                     (match-string 1))
+                               change))
+	    (replace-match (make-string (length (match-string 1)) ?@))))
+        ad-do-it
+        (save-excursion
+          (while change
+            (goto-char (caar change))
+            (delete-char (cadar change))
+            (insert (caddar change))
+            (set 'change (cdr change)))))))
+
+;;
+;;  The following three functions handle the text properties in the buffer:
+;;  the problem in Ada is that ' can be both a constant character delimiter
+;;  and an attribute delimiter. To handle this easily (and allowing us to
+;;  use the standard Emacs functions for sexp... as in ada-in-string-p), we
+;;  change locally the syntax table every time we see a character constant.
+;;  The three characters are then said to be part of a string.
+;;  This handles nicely the '"' case (" is simply ignored in that case)
+;;
+;;  The idea for this code was borrowed from font-lock.el, which actually
+;;  does the same job thanks to ada-font-lock-syntactic-keywords. No need
+;;  to duplicate the work if we already use font-lock
+;;
+;;  This code is not executed for XEmacs, since the syntax-table attribute is
+;;  not known
+
+(defun ada-deactivate-properties ()
+  "Deactivate ada-mode's properties handling, since this would be
+a duplicate of font-lock"
+  (remove-hook 'after-change-functions 'ada-after-change-function t))
+
+(defun ada-initialize-properties ()
+  "Initialize some special text properties in the whole buffer.
+In particular, character constants that contain string delimiters are said
+to be strings.
+We also treat  #..# as numbers, instead of gnatprep comments
+"
+  (save-excursion
+    (save-restriction
+      (widen)
+      (goto-char (point-min))
+      (while (re-search-forward "'.'" nil t)
+        (add-text-properties (match-beginning 0) (match-end 0)
+                             '(syntax-table ("'" . ?\"))))
+      (goto-char (point-min))
+      (while (re-search-forward "^[ \t]*#" nil t)
+        (add-text-properties (match-beginning 0) (match-end 0)
+                             '(syntax-table (11 . 10))))
+      (set-buffer-modified-p nil)
+
+      ;;  Setting this only if font-lock is not set won't work
+      ;;  if the user activates or deactivates font-lock-mode,
+      ;;  but will make things faster most of the time
+      (make-local-hook 'after-change-functions)
+      (add-hook 'after-change-functions 'ada-after-change-function nil t)
+      )))
+
+(defun ada-after-change-function (beg end old-len)
+  "Called every time a character is changed in the buffer"
+  ;; borrowed from font-lock.el
+  (let ((inhibit-point-motion-hooks t)
+        (eol (point)))
+    (save-excursion
+      (save-match-data
+        (beginning-of-line)
+        (remove-text-properties (point) eol '(syntax-table nil))
+        (while (re-search-forward "'.'" eol t)
+          (add-text-properties (match-beginning 0) (match-end 0)
+                               '(syntax-table ("'" . ?\"))))
+        (beginning-of-line)
+        (if (looking-at "^[ \t]*#")
+            (add-text-properties (match-beginning 0) (match-end 0)
+                                 '(syntax-table (11 . 10))))
+        ))))
+
+
+(defvar ada-contextual-menu-on-identifier nil)
+
+(defvar ada-contextual-menu
+  (if ada-xemacs
+      '("Ada"
+	["Goto Declaration/Body" ada-goto-declaration
+	 :included ada-contextual-menu-on-identifier]
+	["Goto Previous Reference" ada-xref-goto-previous-reference]
+	["List References" ada-find-references
+	 :included ada-contextual-menu-on-identifier]
+	["-" nil nil]
+	["Other File" ff-find-other-file]
+	["Goto Parent Unit" ada-goto-parent]
+	)
+    
+    (let ((map (make-sparse-keymap "Ada")))
+      ;; The identifier part
+      (if (equal ada-which-compiler 'gnat)
+	  (progn
+	    (define-key-after map [Ref]
+	      '(menu-item "Goto Declaration/Body"
+			  ada-point-and-xref
+			  :visible ada-contextual-menu-on-identifier
+			  ) t)
+	    (define-key-after map [Prev]
+	      '("Goto Previous Reference" .ada-xref-goto-previous-reference) t)
+	    (define-key-after map [List]
+	      '(menu-item "List References"
+			  ada-find-references
+			  :visible ada-contextual-menu-on-identifier) t)
+	    (define-key-after map [-] '("-" nil) t)
+	    ))
+      (define-key-after map [Other] '("Other file" . ff-find-other-file) t)
+      (define-key-after map [Parent] '("Goto Parent Unit" . ada-goto-parent)t)
+      map)))
+
+(defun ada-popup-menu (position)
+  "Pops up a contextual menu, depending on where the user clicked"
+  (interactive "e")
+  (mouse-set-point last-input-event)
+
+  (setq ada-contextual-menu-on-identifier
+	(and (or (= (char-syntax (char-after)) ?w)
+		 (= (char-after) ?_))
+	     (not (ada-in-string-or-comment-p))
+	     (save-excursion (skip-syntax-forward "w")
+			      (not (ada-after-keyword-p)))
+	     ))
+  (let (choice)
+    (if ada-xemacs
+	(set 'choice (popup-menu ada-contextual-menu))
+      (set 'choice (x-popup-menu position ada-contextual-menu)))
+    (if choice
+	(funcall (lookup-key ada-contextual-menu (vector (car choice)))))))
+
+;;;###autoload
+(defun ada-add-extensions (spec body)
+  "Add a new set of extensions to the ones recognized by ada-mode.
+The addition is done so that `goto-other-file' works as expected"
+  
+  (let* ((reg (concat (regexp-quote body) "$"))
+	 (tmp (assoc reg ada-other-file-alist)))
+    (if tmp
+	(setcdr tmp (list (cons spec (cadr tmp))))
+      (add-to-list 'ada-other-file-alist (list reg (list spec)))))
+  
+  (let* ((reg (concat (regexp-quote spec) "$"))
+	 (tmp (assoc reg ada-other-file-alist)))
+    (if tmp
+	(setcdr tmp (list (cons body (cadr tmp))))
+      (add-to-list 'ada-other-file-alist (list reg (list body)))))
+
+  (add-to-list 'auto-mode-alist (cons spec 'ada-mode))
+  (add-to-list 'auto-mode-alist (cons body 'ada-mode))
+
+  (add-to-list 'ada-spec-suffixes spec)
+  (add-to-list 'ada-body-suffixes body)
+
+  ;; Support for speedbar (Specifies that we want to see these files in
+  ;; speedbar)
+  (condition-case nil
+      (progn
+        (require 'speedbar)
+        (speedbar-add-supported-extension spec)
+        (speedbar-add-supported-extension body)))
+  )
+
+
 
 ;;;###autoload
 (defun ada-mode ()
@@ -514,16 +816,11 @@
 
  Re-format the parameter-list point is in             '\\[ada-format-paramlist]'
  Indent all lines in region                           '\\[ada-indent-region]'
- Call external pretty printer program                 '\\[ada-call-pretty-printer]'
 
  Adjust case of identifiers and keywords in region    '\\[ada-adjust-case-region]'
  Adjust case of identifiers and keywords in buffer    '\\[ada-adjust-case-buffer]'
 
- Call EXTERNAL pretty printer (if you have one)       '\\[ada-call-pretty-printer]'
-
- Fill comment paragraph                               '\\[ada-fill-comment-paragraph]'
- Fill comment paragraph and justify each line         '\\[ada-fill-comment-paragraph-justify]'
- Fill comment paragraph, justify and append postfix   '\\[ada-fill-comment-paragraph-postfix]'
+ Fill comment paragraph, justify and append postfix   '\\[fill-paragraph]'
 
  Next func/proc/task '\\[ada-next-procedure]'  Previous func/proc/task '\\[ada-previous-procedure]'
  Next package        '\\[ada-next-package]'  Previous package        '\\[ada-previous-package]'
@@ -545,430 +842,374 @@
                                                    or '\\[ff-mouse-find-other-file]
  Switch to other file in other window                 '\\[ada-ff-other-window]'
                                                    or '\\[ff-mouse-find-other-file-other-window]
- If you use this function in a spec and no body is available, it gets created
- with body stubs.
+ If you use this function in a spec and no body is available, it gets created with body stubs.
 
 If you use ada-xref.el:
  Goto declaration:          '\\[ada-point-and-xref]' on the identifier
                          or '\\[ada-goto-declaration]' with point on the identifier
- Complete identifier:       '\\[ada-complete-identifier]'
- Execute Gnatf:             '\\[ada-gnatf-current]'"
+ Complete identifier:       '\\[ada-complete-identifier]'"
 
   (interactive)
   (kill-all-local-variables)
 
-  (make-local-variable 'require-final-newline)
-  (setq require-final-newline t)
+  (set (make-local-variable 'require-final-newline) t)
 
   (make-local-variable 'comment-start)
-  (setq comment-start "-- ")
+  (if ada-fill-comment-prefix
+      (set 'comment-start ada-fill-comment-prefix)
+    (set 'comment-start "-- "))
+
+  ;;  Set the paragraph delimiters so that one can select a whole block
+  ;;  simply with M-h
+  (set (make-local-variable 'paragraph-start) "[ \t\n\f]*$")
+  (set (make-local-variable 'paragraph-separate) "[ \t\n\f]*$")
 
   ;; comment end must be set because it may hold a wrong value if
   ;; this buffer had been in another mode before. RE
-  (make-local-variable 'comment-end)
-  (setq comment-end "")
-
-  (make-local-variable 'comment-start-skip) ;; used by autofill
-  (setq comment-start-skip "--+[ \t]*")
-
-  (make-local-variable 'indent-line-function)
-  (setq indent-line-function 'ada-indent-current-function)
-
-  (make-local-variable 'fill-column)
-  (setq fill-column 75)
-
-  (make-local-variable 'comment-column)
-  (setq comment-column 40)
-
-  (make-local-variable 'parse-sexp-ignore-comments)
-  (setq parse-sexp-ignore-comments t)
-
-  (make-local-variable 'case-fold-search)
-  (setq case-fold-search t)
-
-  (make-local-variable 'outline-regexp)
-  (setq outline-regexp "[^\n\^M]")
-  (make-local-variable 'outline-level)
-  (setq outline-level 'ada-outline-level)
-
-  (make-local-variable 'fill-paragraph-function)
-  (setq fill-paragraph-function 'ada-fill-comment-paragraph)
-  ;;(make-local-variable 'adaptive-fill-regexp)
-
-  (make-local-variable 'imenu-generic-expression)
-  (setq imenu-generic-expression ada-imenu-generic-expression)
-  (setq imenu-case-fold-search t)
-
-  (if (ada-xemacs) nil ; XEmacs uses properties 
-    (make-local-variable 'font-lock-defaults)
-    (setq font-lock-defaults
-          '((ada-font-lock-keywords
-             ada-font-lock-keywords-1 ada-font-lock-keywords-2)
-            nil t
-            ((?\_ . "w")(?\. . "w"))
-            beginning-of-line
-            (font-lock-syntactic-keywords . ada-font-lock-syntactic-keywords)))
-
-    ;; Set up support for find-file.el.
-    (make-variable-buffer-local 'ff-other-file-alist)
-    (make-variable-buffer-local 'ff-search-directories)
-    (setq ff-other-file-alist   'ada-other-file-alist
-          ff-search-directories 'ada-search-directories
-          ff-pre-load-hooks     'ff-which-function-are-we-in
-          ff-post-load-hooks    'ff-set-point-accordingly
-          ff-file-created-hooks 'ada-make-body))
-
-  (setq major-mode 'ada-mode)
-  (setq mode-name "Ada")
+  (set (make-local-variable 'comment-end) "")
+
+  ;; used by autofill and indent-new-comment-line
+  (set (make-local-variable 'comment-start-skip) "---*[ \t]*")
+
+  ;; used by autofill to break a comment line and continue it on another line.
+  ;; The reason we need this one is that the default behavior does not work
+  ;; correctly with the definition of paragraph-start above when the comment
+  ;; is right after a multiline subprogram declaration (the comments are
+  ;; aligned under the latest parameter, not under the declaration start).
+  (set (make-local-variable 'comment-line-break-function)
+       (lambda (&optional soft) (let ((fill-prefix nil))
+  				  (indent-new-comment-line soft))))
+  
+  (set (make-local-variable 'indent-line-function)
+       'ada-indent-current-function)
+
+  (set (make-local-variable 'comment-column) 40)
+
+  ;;  Emacs 20.3 defines a comment-padding to insert spaces between
+  ;;  the comment and the text. We do not want any, this is already
+  ;;  included in comment-start
+  (unless ada-xemacs
+    (progn
+      (if (ada-check-emacs-version 20 3)
+          (progn
+            (set (make-local-variable 'parse-sexp-ignore-comments) t)
+            (set (make-local-variable 'comment-padding) 0)))
+      (set (make-local-variable 'parse-sexp-lookup-properties) t)
+      ))
+
+  (set 'case-fold-search t)
+  (if (boundp 'imenu-case-fold-search)
+      (set 'imenu-case-fold-search t))
+
+  (set (make-local-variable 'fill-paragraph-function)
+       'ada-fill-comment-paragraph)
+
+  (set (make-local-variable 'imenu-generic-expression)
+       ada-imenu-generic-expression)
+
+  ;;  Support for compile.el
+  ;;  We just substitute our own functions to go to the error.
+  (add-hook 'compilation-mode-hook
+            '(lambda()
+	       (set 'compile-auto-highlight 40)
+               (define-key compilation-minor-mode-map [mouse-2]
+                 'ada-compile-mouse-goto-error)
+               (define-key compilation-minor-mode-map "\C-c\C-c"
+                 'ada-compile-goto-error)
+               (define-key compilation-minor-mode-map "\C-m"
+                 'ada-compile-goto-error)
+               ))
+
+  ;;  font-lock support :
+  ;;  We need to set some properties for Xemacs, and define some variables
+  ;;  for Emacs
+
+  (if ada-xemacs
+      ;;  XEmacs
+      (put 'ada-mode 'font-lock-defaults
+           '(ada-font-lock-keywords
+             nil t ((?\_ . "w") (?# . ".")) beginning-of-line))
+    ;;  Emacs
+    (set (make-local-variable 'font-lock-defaults)
+         '(ada-font-lock-keywords
+           nil t
+           ((?\_ . "w") (?# . "."))
+           beginning-of-line
+           (font-lock-syntactic-keywords . ada-font-lock-syntactic-keywords)))
+    )
+  
+  ;; Set up support for find-file.el.
+  (set (make-variable-buffer-local 'ff-other-file-alist)
+       'ada-other-file-alist)
+  (set (make-variable-buffer-local 'ff-search-directories)
+       'ada-search-directories)
+  (setq ff-post-load-hooks    'ada-set-point-accordingly
+	ff-file-created-hooks 'ada-make-body)
+  (add-hook 'ff-pre-load-hooks 'ada-which-function-are-we-in)
+  
+  ;; Some special constructs for find-file.el
+  ;; We do not need to add the construction for 'with', which is in the
+  ;; standard find-file.el
+  ;; Go to the parent package :
+  (make-local-variable 'ff-special-constructs)
+  (add-to-list 'ff-special-constructs
+	       (cons (eval-when-compile
+		       (concat "^\\(private[ \t]\\)?[ \t]*package[ \t]+"
+			       "\\(body[ \t]+\\)?"
+			       "\\(\\(\\sw\\|[_.]\\)+\\)\\.\\(\\sw\\|_\\)+[ \t\n]+is"))
+		     '(lambda ()
+			(set 'fname (ff-get-file
+				     ff-search-directories
+				     (ada-make-filename-from-adaname
+				      (match-string 3))
+				     ada-spec-suffixes)))))
+  ;; Another special construct for find-file.el : when in a separate clause,
+  ;; go to the correct package.
+  (add-to-list 'ff-special-constructs
+	       (cons "^separate[ \t\n]*(\\(\\(\\sw\\|[_.]\\)+\\))"
+		     '(lambda ()
+			(set 'fname (ff-get-file
+				     ff-search-directories
+				     (ada-make-filename-from-adaname
+				      (match-string 1))
+				     ada-spec-suffixes)))))
+  ;; Another special construct, that redefines the one in find-file.el. The
+  ;; old one can handle only one possible type of extension for Ada files
+  (add-to-list 'ff-special-constructs
+	       (cons "^with[ \t]+\\([a-zA-Z0-9_\\.]+\\)" 
+		     '(lambda ()
+			(set 'fname (ff-get-file
+				     ff-search-directories
+				     (ada-make-filename-from-adaname
+				      (match-string 1))
+				     ada-spec-suffixes)))))
+  
+  ;;  Support for outline-minor-mode
+  (set (make-local-variable 'outline-regexp)
+       "\\([ \t]*\\(procedure\\|function\\|package\\|with\\|use\\)\\|--\\|end\\)")
+  (set (make-local-variable 'outline-level) 'ada-outline-level)
+
+  ;;  Support for imenu : We want a sorted index
+  (set 'imenu-sort-function 'imenu--sort-by-name)
+
+  ;;  Set up the contextual menu
+  (if ada-popup-key
+      (define-key ada-mode-map ada-popup-key 'ada-popup-menu))
+
+  ;;  Support for indent-new-comment-line (Especially for XEmacs)
+  (set 'comment-multi-line nil)
+  (defconst comment-indent-function (lambda () comment-column))
+
+  (set 'major-mode 'ada-mode)
+  (set 'mode-name "Ada")
 
   (use-local-map ada-mode-map)
 
-  (if ada-mode-syntax-table
-      (set-syntax-table ada-mode-syntax-table)
-    (ada-create-syntax-table))
+  (if ada-xemacs
+      (easy-menu-add ada-mode-menu ada-mode-map))
+  
+  (set-syntax-table ada-mode-syntax-table)
 
   (if ada-clean-buffer-before-saving
       (progn
-	;; remove all spaces at the end of lines in the whole buffer.
-	(add-hook 'local-write-file-hooks 'ada-remove-trailing-spaces)
-	;; convert all tabs to the correct number of spaces.
-	(add-hook 'local-write-file-hooks 'ada-untabify-buffer)))
-
-
-  ;; add menu 'Ada' to the menu bar
-  (ada-add-ada-menu)
+        ;; remove all spaces at the end of lines in the whole buffer.
+        (add-hook 'local-write-file-hooks 'ada-remove-trailing-spaces)
+        ;; convert all tabs to the correct number of spaces.
+        (add-hook 'local-write-file-hooks
+                  '(lambda () (untabify (point-min) (point-max))))))
 
   (run-hooks 'ada-mode-hook)
 
+  ;;  Run this after the hook to give the users a chance to activate
+  ;;  font-lock-mode
+
+  (unless ada-xemacs
+    (progn
+      (ada-initialize-properties)
+      (make-local-hook 'font-lock-mode-hook)
+      (add-hook 'font-lock-mode-hook 'ada-deactivate-properties nil t)))
+
   ;; the following has to be done after running the ada-mode-hook
   ;; because users might want to set the values of these variable
   ;; inside the hook (MH)
+  ;; Note that we add the new elements at the end of ada-other-file-alist
+  ;; since some user might want to give priority to some other extensions
+  ;; first (for instance, a .adb file could be associated with a .ads
+  ;; or a .ads.gp (gnatprep)).
+  ;; This is why we can't use add-to-list here.
 
   (cond ((eq ada-language-version 'ada83)
-         (setq ada-keywords ada-83-keywords))
+         (set 'ada-keywords ada-83-keywords))
         ((eq ada-language-version 'ada95)
-         (setq ada-keywords ada-95-keywords)))
+         (set 'ada-keywords ada-95-keywords)))
 
   (if ada-auto-case
       (ada-activate-keys-for-case)))
 
 
-;;;--------------------------
-;;;  Compile support
-;;;--------------------------
-
-(defun ada-check-syntax ()
-  "Check syntax of the current buffer. 
-Uses the function `compile' to execute `ada-compiler-syntax-check'."
-  (interactive)
-  (let ((old-compile-command compile-command))
-    (setq compile-command (concat ada-compiler-syntax-check
-                                  (if (eq ada-language-version 'ada83)
-                                      "-gnat83 ")
-                                  " " ada-compile-options " "
-                                  (buffer-name)))
-    (setq compile-command (read-from-minibuffer
-                           "enter command for syntax check: "
-                           compile-command))
-    (compile compile-command)
-    ;; restore old compile-command
-    (setq compile-command old-compile-command)))
-
-(defun ada-make-local ()
-  "Bring current Ada unit up-to-date. 
-Uses the function `compile' to execute `ada-compile-make'."
-  (interactive)
-  (let ((old-compile-command compile-command))
-    (setq compile-command (concat ada-compiler-make
-                                  " " ada-make-options " "
-                                  (buffer-name)))
-    (setq compile-command (read-from-minibuffer
-                           "enter command for local make: "
-                           compile-command))
-    (compile compile-command)
-    ;; restore old compile-command
-    (setq compile-command old-compile-command)))
-
-
-
-
-;;;--------------------------
-;;;  Fill Comment Paragraph
-;;;--------------------------
-
-(defun ada-fill-comment-paragraph-justify ()
-  "Fills current comment paragraph and justifies each line as well."
-  (interactive)
-  (ada-fill-comment-paragraph t))
-
-
-(defun ada-fill-comment-paragraph-postfix ()
-  "Fills current comment paragraph and justifies each line as well.
-Prompts for a postfix to be appended to each line."
+
+;;;--------------------------------------------------------
+;;;                      auto-casing
+;;;--------------------------------------------------------
+
+
+(defun ada-create-case-exception (&optional word)
+  "Defines WORD as an exception for the casing system. If WORD
+is not given, then the current word in the buffer is used instead.
+Every time the ada-mode will see the same word, the same casing will
+be used.
+The new words is added to the file `ada-case-exception-file'"
   (interactive)
-  (ada-fill-comment-paragraph t t))
-
-
-(defun ada-fill-comment-paragraph (&optional justify postfix)
-  "Fills the current comment paragraph.
-If JUSTIFY is non-nil, each line is justified as well.
-If POSTFIX and JUSTIFY are  non-nil, `ada-fill-comment-postfix' is appended
-to each filled and justified line.
-If `ada-indent-comment-as-code' is non-nil, the paragraph is idented."
-  (interactive "P")
-  (let ((opos (point-marker))
-        (begin nil)
-        (end nil)
-        (end-2 nil)
-        (indent nil)
-        (ada-fill-comment-old-postfix "")
-        (fill-prefix nil))
-
-    ;; check if inside comment
-    (if (not (ada-in-comment-p))
-        (error "not inside comment"))
-
-    ;; prompt for postfix if wanted
-    (if (and justify
-             postfix)
-        (setq ada-fill-comment-postfix
-              (read-from-minibuffer "enter new postfix string: "
-                                    ada-fill-comment-postfix)))
-
-    ;; prompt for old postfix to remove if necessary
-    (if (and justify
-             postfix)
-        (setq ada-fill-comment-old-postfix
-              (read-from-minibuffer "enter already existing postfix string: "
-                                    ada-fill-comment-postfix)))
-
-    ;;
-    ;; find limits of paragraph
-    ;;
-    (message "filling comment paragraph ...")
-    (save-excursion
-      (back-to-indentation)
-      ;; find end of paragraph
-      (while (and (looking-at "--.*$")
-                  (not (looking-at "--[ \t]*$")))
-        (forward-line 1)
-        (back-to-indentation))
-      (beginning-of-line)
-      (setq end (point-marker))
-      (goto-char opos)
-      ;; find begin of paragraph
-      (back-to-indentation)
-      (while (and (looking-at "--.*$")
-                  (not (looking-at "--[ \t]*$")))
-        (forward-line -1)
-        (back-to-indentation))
-      (forward-line 1)
-      ;; get indentation to calculate width for filling
-      (ada-indent-current)
-      (back-to-indentation)
-      (setq indent (current-column))
-      (setq begin (point-marker)))
-
-    ;; delete old postfix if necessary
-    (if (and justify
-             postfix)
-        (save-excursion
-          (goto-char begin)
-          (while (re-search-forward (concat ada-fill-comment-old-postfix
-                                            "\n")
-                                    end t)
-            (replace-match "\n"))))
-
-    ;; delete leading whitespace and uncomment
-    (save-excursion
-      (goto-char begin)
-      (beginning-of-line)
-      (while (re-search-forward "^[ \t]*--[ \t]*" end t)
-        (replace-match "")))
-
-    ;; calculate fill width
-    (setq fill-column (- fill-column indent
-                         (length ada-fill-comment-prefix)
-                         (if postfix
-                             (length ada-fill-comment-postfix)
-                           0)))
-    ;; fill paragraph
-    (fill-region begin (1- end) justify)
-    (setq fill-column (+ fill-column indent
-                         (length ada-fill-comment-prefix)
-                         (if postfix
-                             (length ada-fill-comment-postfix)
-                           0)))
-   ;; find end of second last line
-    (save-excursion
-      (goto-char end)
-      (forward-line -2)
-      (end-of-line)
-      (setq end-2 (point-marker)))
-
-    ;; re-comment and re-indent region
-    (save-excursion
-      (goto-char begin)
-      (indent-to indent)
-      (insert ada-fill-comment-prefix)
-      (while (re-search-forward "\n" (1- end-2) t)
-        (replace-match (concat "\n" ada-fill-comment-prefix))
-        (beginning-of-line)
-        (indent-to indent)))
-
-    ;; append postfix if wanted
-    (if (and justify
-             postfix
-             ada-fill-comment-postfix)
-        (progn
-          ;; append postfix up to there
-          (save-excursion
-            (goto-char begin)
-            (while (re-search-forward "\n" (1- end-2) t)
-              (replace-match (concat ada-fill-comment-postfix "\n")))
-
-            ;; fill last line and append postfix
-            (end-of-line)
-            (insert-char ?
-                         (- fill-column
-                            (current-column)
-                            (length ada-fill-comment-postfix)))
-            (insert ada-fill-comment-postfix))))
-
-    ;; delete the extra line that gets inserted somehow(??)
-    (save-excursion
-      (goto-char (1- end))
-      (end-of-line)
-      (delete-char 1))
-
-     (message "filling comment paragraph ... done")
-    (goto-char opos))
-  t)
-
-
-;;;--------------------------------;;;
-;;;  Call External Pretty Printer  ;;;
-;;;--------------------------------;;;
-
-(defun ada-call-pretty-printer ()
-  "Calls the external Pretty Printer.
-The name is specified in `ada-external-pretty-print-program'.  Saves the
-current buffer in a directory specified by `ada-tmp-directory',
-starts the pretty printer as external process on that file and then
-reloads the beautified program in the buffer and cleans up
-`ada-tmp-directory'."
+  (let ((previous-syntax-table (syntax-table))
+	(exception-list '()))
+    (set-syntax-table ada-mode-symbol-syntax-table)
+    (unless word
+      (save-excursion
+	(skip-syntax-backward "w")
+	(set 'word (buffer-substring-no-properties
+                  (point) (save-excursion (forward-word 1) (point))))))
+
+    ;;  Reread the exceptions file, in case it was modified by some other,
+    ;;  and to keep the end-of-line comments that may exist in it.
+    (if (file-readable-p (expand-file-name ada-case-exception-file))
+	(let ((buffer (current-buffer)))
+	  (find-file (expand-file-name ada-case-exception-file))
+	  (set-syntax-table ada-mode-symbol-syntax-table)
+	  (widen)
+	  (goto-char (point-min))
+	  (while (not (eobp))
+	    (add-to-list 'exception-list
+			 (list
+			  (buffer-substring-no-properties
+			   (point) (save-excursion (forward-word 1) (point)))
+			  (buffer-substring-no-properties
+			   (save-excursion (forward-word 1) (point))
+			   (save-excursion (end-of-line) (point)))
+			  t))
+	    (forward-line 1))
+	  (kill-buffer nil)
+	  (set-buffer buffer)))
+    
+    ;;  If the word is already in the list, even with a different casing
+    ;;  we simply want to replace it.
+    (if (and (not (equal exception-list '()))
+	     (assoc-ignore-case word exception-list))
+	(setcar (assoc-ignore-case word exception-list)
+		word)
+      (add-to-list 'exception-list (list word "" t))
+      )
+
+    (if (and (not (equal ada-case-exception '()))
+	     (assoc-ignore-case word ada-case-exception))
+	(setcar (assoc-ignore-case word ada-case-exception)
+		word)
+      (add-to-list 'ada-case-exception (cons word t))
+      )
+
+    ;;  Save the list in the file
+    (find-file (expand-file-name ada-case-exception-file))
+    (erase-buffer)
+    (mapcar '(lambda (x) (insert (car x) (nth 1 x) "\n"))
+	    (sort exception-list
+		  (lambda(a b) (string< (car a) (car b)))))
+    (save-buffer)
+    (kill-buffer nil)
+    (set-syntax-table previous-syntax-table)
+    ))
+  
+(defun ada-case-read-exceptions ()
+  "Read the file `ada-case-exception-file' for the list of identifiers that
+have special casing"
   (interactive)
-  (let ((filename-with-path buffer-file-name)
-        (curbuf (current-buffer))
-        (orgpos (point))
-        (mesgbuf nil) ;; for byte-compiling
-        (file-path (file-name-directory buffer-file-name))
-        (filename-without-path (file-name-nondirectory buffer-file-name))
-        (tmp-file-with-directory
-         (concat ada-tmp-directory
-                 (file-name-nondirectory buffer-file-name))))
-    ;;
-    ;; save buffer in temporary file
-    ;;
-    (message "saving current buffer to temporary file ...")
-    (write-file tmp-file-with-directory)
-    (auto-save-mode nil)
-    (message "saving current buffer to temporary file ... done")
-    ;;
-    ;; call external pretty printer program
-    ;;
-
-    (message "running external pretty printer ...")
-    ;; create a temporary buffer for messages of pretty printer
-    (setq mesgbuf (get-buffer-create "Pretty Printer Messages"))
-    ;; execute pretty printer on temporary file
-    (call-process ada-external-pretty-print-program
-                  nil mesgbuf t
-                  tmp-file-with-directory)
-    ;; display messages if there are some
-    (if (buffer-modified-p mesgbuf)
-        ;; show the message buffer
-        (display-buffer mesgbuf t)
-      ;; kill the message buffer
-      (kill-buffer mesgbuf))
-    (message "running external pretty printer ... done")
-    ;;
-    ;; kill current buffer and load pretty printer output
-    ;; or restore old buffer
-    ;;
-    (if (y-or-n-p
-         "Really replace current buffer with pretty printer output ? ")
-        (progn
-          (set-buffer-modified-p nil)
-          (kill-buffer curbuf)
-          (find-file tmp-file-with-directory))
-      (message "old buffer contents restored"))
-    ;;
-    ;; delete temporary file and restore information of current buffer
-    ;;
-    (delete-file tmp-file-with-directory)
-    (set-visited-file-name filename-with-path)
-    (auto-save-mode t)
-    (goto-char orgpos)))
-
-
-;;;---------------
-;;;  auto-casing
-;;;---------------
-
-;; from Philippe Waroquiers <philippe@cfmu.eurocontrol.be>
-;; modified by RE and MH
+  (set 'ada-case-exception '())
+  (if (file-readable-p (expand-file-name ada-case-exception-file))
+      (let ((buffer (current-buffer)))
+	(find-file (expand-file-name ada-case-exception-file))
+	(set-syntax-table ada-mode-symbol-syntax-table)
+        (widen)
+        (goto-char (point-min))
+        (while (not (eobp))
+          (add-to-list 'ada-case-exception
+                       (cons
+                        (buffer-substring-no-properties
+                         (point) (save-excursion (forward-word 1) (point)))
+                        t))
+          (forward-line 1))
+        (kill-buffer nil)
+        (set-buffer buffer)
+	)))
+
+(defun ada-adjust-case-identifier ()
+  "Adjust case of the previous identifier. The auto-casing is
+done according to the value of `ada-case-identifier' and the
+exceptions defined in `ada-case-exception'"
+
+  (if (or (equal ada-case-exception '())
+          (equal (char-after) ?_))
+      (funcall ada-case-identifier -1)
+
+    (progn
+      (let ((end   (point))
+            (start (save-excursion (skip-syntax-backward "w")
+				   (point)))
+            match)
+        ;;  If we have an exception, replace the word by the correct casing
+        (if (set 'match (assoc-ignore-case (buffer-substring start end)
+                                           ada-case-exception))
+
+            (progn
+              (delete-region start end)
+              (insert (car match)))
+
+          ;;  Else simply recase the word
+          (funcall ada-case-identifier -1))))))
 
 (defun ada-after-keyword-p ()
   ;; returns t if cursor is after a keyword.
   (save-excursion
     (forward-word -1)
-    (and (save-excursion
-           (or
-            (= (point) (point-min))
-            (backward-char 1))
-           (not (looking-at "_")))     ; (MH)
+    (and (not (and (char-before) (= (char-before) ?_)));; unless we have a _
          (looking-at (concat ada-keywords "[^_]")))))
 
-(defun ada-in-char-const-p ()
-  ;; Returns t if point is inside a character constant.
-  ;; We assume to be in a constant if the previous and the next character
-  ;; are "'". 
-  (save-excursion
-    (if (> (point) 1)
-        (and
-         (progn
-           (forward-char 1)
-           (looking-at "'"))
-         (progn
-           (forward-char -2)
-           (looking-at "'")))
-      nil)))
-
-
 (defun ada-adjust-case (&optional force-identifier)
   "Adjust the case of the word before the just typed character.
-Respect options `ada-case-keyword', `ada-case-identifier', and 
+Respect options `ada-case-keyword', `ada-case-identifier', and
 `ada-case-attribute'.
 If FORCE-IDENTIFIER is non-nil then also adjust keyword as identifier." ; (MH)
-  (forward-char -1)
-  (if (and (> (point) 1) (not (or (ada-in-string-p)
-                                  (ada-in-comment-p)
-                                  (ada-in-char-const-p))))
-      (if (eq (char-syntax (char-after (1- (point)))) ?w)
-	  (if (save-excursion
-		(forward-word -1)
-		(or (= (point) (point-min))
-		    (backward-char 1))
-		(looking-at "'"))
-	      (funcall ada-case-attribute -1)
-	    (if (and
-		 (not force-identifier) ; (MH)
-		 (ada-after-keyword-p))
-		(funcall ada-case-keyword -1)
-	      (funcall ada-case-identifier -1)))))
-  (forward-char 1))
-
+  (let ((previous-syntax-table (syntax-table)))
+    (set-syntax-table ada-mode-symbol-syntax-table)
+
+    (forward-char -1)
+
+    ;;  Do nothing in some cases
+    (if (and (> (point) 1)
+
+	     ;;  or if at the end of a character constant
+	     (not (and (eq (char-after) ?')
+		       (eq (char-before (1- (point))) ?')))
+
+	     ;;  or if the previous character was not part of a word
+	     (eq (char-syntax (char-before)) ?w)
+
+	     ;;  if in a string or a comment
+	     (not (ada-in-string-or-comment-p))
+	     )
+	
+	(if (save-excursion
+	      (forward-word -1)
+	      (or (= (point) (point-min))
+		  (backward-char 1))
+	      (= (char-after) ?'))
+	    (funcall ada-case-attribute -1)
+	  (if (and
+	       (not force-identifier) ; (MH)
+	       (ada-after-keyword-p))
+	      (funcall ada-case-keyword -1)
+	    (ada-adjust-case-identifier))))
+    (forward-char 1)
+    (set-syntax-table previous-syntax-table)
+    )
+  )
 
 (defun ada-adjust-case-interactive (arg)
   (interactive "P")
@@ -996,40 +1237,52 @@
 
 
 (defun ada-activate-keys-for-case ()
+  (interactive)
   ;; save original keybindings to allow swapping ret/lfd
   ;; when casing is activated
   ;; the 'or ...' is there to be sure that the value will not
   ;; be changed again when Ada mode is called more than once (MH)
   (or ada-ret-binding
-      (setq ada-ret-binding (key-binding "\C-M")))
+      (set 'ada-ret-binding (key-binding "\C-M")))
   (or ada-lfd-binding
-      (setq ada-lfd-binding (key-binding "\C-j")))
+      (set 'ada-lfd-binding (key-binding "\C-j")))
   ;; call case modifying function after certain keys.
   (mapcar (function (lambda(key) (define-key
                                    ada-mode-map
                                    (char-to-string key)
                                    'ada-adjust-case-interactive)))
           '( ?` ?~ ?! ?@ ?# ?$ ?% ?^ ?& ?* ?( ?)  ?- ?= ?+ ?[ ?{ ?] ?}
-                ?_ ?\\ ?| ?\; ?: ?' ?\" ?< ?, ?. ?> ?? ?/ ?\n 32 ?\r )))
-;; deleted ?\t from above list
+		?\\ ?| ?\; ?: ?' ?\" ?< ?, ?. ?> ?? ?/ ?\n 32 ?\r )))
 
 ;;
 ;; added by MH
 ;;
 (defun ada-loose-case-word (&optional arg)
-  "Capitalizes the first letter and the letters following `_'.
-ARG is ignored, it's there to fit the standard casing functions' style."
+  "Capitalizes the first letter and the letters following `_' for the following
+word. Ignores Arg (its there to conform to capitalize-word parameters)
+Does not change other letters"
+  (interactive)
   (let ((pos (point))
         (first t))
-    (skip-chars-backward "a-zA-Z0-9_")
+    (skip-syntax-backward "w")
     (while (or first
                (search-forward "_" pos t))
       (and first
-           (setq first nil))
+           (set 'first nil))
       (insert-char (upcase (following-char)) 1)
       (delete-char 1))
     (goto-char pos)))
 
+(defun ada-capitalize-word (&optional arg)
+  "Capitalizes the first letter and the letters following '_', and
+lower case other letters"
+  (interactive)
+  (let ((pos (point)))
+    (skip-syntax-backward "w")
+    (modify-syntax-entry ?_ "_")
+    (capitalize-region (point) pos)
+    (goto-char pos)
+    (modify-syntax-entry ?_ "w")))
 
 ;;
 ;; added by MH
@@ -1042,45 +1295,44 @@
   (let ((begin nil)
         (end nil)
         (keywordp nil)
-        (attribp nil))
+        (attribp nil)
+        (previous-syntax-table (syntax-table)))
+    (message "Adjusting case ...")
     (unwind-protect
-	(save-excursion
-	  (set-syntax-table ada-mode-symbol-syntax-table)
-	  (goto-char to)
-	  ;;
-	  ;; loop: look for all identifiers, keywords, and attributes
-	  ;;
-	  (while (re-search-backward
-		  "[^a-zA-Z0-9_]\\([a-zA-Z0-9_]+\\)[^a-zA-Z0-9_]"
-		  from
-		  t)
-	    ;;
-	    ;; print status message
-	    ;;
-	    (message "adjusting case ... %5d characters left" (- (point) from))
-	    (setq attribp (looking-at "'[a-zA-Z0-9_]+[^']"))
-	    (forward-char 1)
-	    (or
-	     ;; do nothing if it is a string or comment
-	     (ada-in-string-or-comment-p)
-	     (progn
-	       ;;
-	       ;; get the identifier or keyword or attribute
-	       ;;
-	       (setq begin (point))
-	       (setq keywordp (looking-at (concat ada-keywords "[^_]")))
-	       (skip-chars-forward "a-zA-Z0-9_")
-	       ;;
-	       ;; casing according to user-option
-	       ;;
-	       (if keywordp
-		   (funcall ada-case-keyword -1)
-		 (if attribp
-		     (funcall ada-case-attribute -1)
-		   (funcall ada-case-identifier -1)))
-	       (goto-char begin))))
-	  (message "adjusting case ... done"))
-      (set-syntax-table ada-mode-syntax-table))))
+        (save-excursion
+          (set-syntax-table ada-mode-symbol-syntax-table)
+          (goto-char to)
+          ;;
+          ;; loop: look for all identifiers, keywords, and attributes
+          ;;
+          (while (re-search-backward "\\<\\(\\sw+\\)\\>" from t)
+            (set 'end (match-end 1))
+            (set 'attribp
+                 (and (> (point) from)
+                      (save-excursion
+                        (forward-char -1)
+                        (set 'attribp (looking-at "'.[^']")))))
+            (or
+             ;; do nothing if it is a string or comment
+             (ada-in-string-or-comment-p)
+             (progn
+               ;;
+               ;; get the identifier or keyword or attribute
+               ;;
+               (set 'begin (point))
+               (set 'keywordp (looking-at ada-keywords))
+               (goto-char end)
+               ;;
+               ;; casing according to user-option
+               ;;
+               (if attribp
+                   (funcall ada-case-attribute -1)
+                 (if keywordp
+                     (funcall ada-case-keyword -1)
+                   (ada-adjust-case-identifier)))
+               (goto-char begin))))
+          (message "Adjusting case ... Done"))
+      (set-syntax-table previous-syntax-table))))
 
 
 ;;
@@ -1096,7 +1348,6 @@
 ;;;------------------------;;;
 ;;; Format Parameter Lists ;;;
 ;;;------------------------;;;
-
 (defun ada-format-paramlist ()
   "Reformats a parameter list.
 ATTENTION:  1) Comments inside the list are killed !
@@ -1108,57 +1359,57 @@
   (let ((begin nil)
         (end nil)
         (delend nil)
-        (paramlist nil))
+        (paramlist nil)
+        (previous-syntax-table (syntax-table)))
     (unwind-protect
-	(progn 
-	  (set-syntax-table ada-mode-symbol-syntax-table)
-
-	  ;; check if really inside parameter list
-	  (or (ada-in-paramlist-p)
-	      (error "not in parameter list"))
-	  ;;
-	  ;; find start of current parameter-list
-	  ;;
-	  (ada-search-ignore-string-comment
+        (progn
+          (set-syntax-table ada-mode-symbol-syntax-table)
+
+          ;; check if really inside parameter list
+          (or (ada-in-paramlist-p)
+              (error "not in parameter list"))
+          ;;
+          ;; find start of current parameter-list
+          ;;
+          (ada-search-ignore-string-comment
            (concat ada-subprog-start-re "\\|\\<body\\>" ) t nil)
-	  (ada-search-ignore-string-comment "(" nil nil t)
-	  (backward-char 1)
-	  (setq begin (point))
-
-	  ;;
-	  ;; find end of parameter-list
-	  ;;
-	  (forward-sexp 1)
-	  (setq delend (point))
-	  (delete-char -1)
-
-	  ;;
-	  ;; find end of last parameter-declaration
-	  ;;
-	  (ada-search-ignore-string-comment "[^ \t\n]" t nil t)
-	  (forward-char 1)
-	  (setq end (point))
-
-	  ;;
-	  ;; build a list of all elements of the parameter-list
-	  ;;
-	  (setq paramlist (ada-scan-paramlist (1+ begin) end))
-
-	  ;;
-	  ;; delete the original parameter-list
-	  ;;
-	  (delete-region begin (1- delend))
-
-	  ;;
-	  ;; insert the new parameter-list
-	  ;;
-	  (goto-char begin)
-	  (ada-insert-paramlist paramlist))
+          (down-list 1)
+          (backward-char 1)
+          (set 'begin (point))
+
+          ;;
+          ;; find end of parameter-list
+          ;;
+          (forward-sexp 1)
+          (set 'delend (point))
+          (delete-char -1)
+
+          ;;
+          ;; find end of last parameter-declaration
+          ;;
+          (forward-comment -1000)
+          (set 'end (point))
+
+          ;;
+          ;; build a list of all elements of the parameter-list
+          ;;
+          (set 'paramlist (ada-scan-paramlist (1+ begin) end))
+
+          ;;
+          ;; delete the original parameter-list
+          ;;
+          (delete-region begin (1- delend))
+
+          ;;
+          ;; insert the new parameter-list
+          ;;
+          (goto-char begin)
+          (ada-insert-paramlist paramlist))
 
       ;;
       ;; restore syntax-table
       ;;
-      (set-syntax-table ada-mode-syntax-table)
+      (set-syntax-table previous-syntax-table)
       )))
 
 
@@ -1190,66 +1441,59 @@
       ;; find first character of parameter-declaration
       ;;
       (ada-goto-next-non-ws)
-      (setq apos (point))
+      (set 'apos (point))
 
       ;;
       ;; find last character of parameter-declaration
       ;;
-      (if (setq match-cons
-                (ada-search-ignore-string-comment "[ \t\n]*;" nil end t))
+      (if (set 'match-cons
+               (ada-search-ignore-string-comment "[ \t\n]*;" nil end t))
           (progn
-            (setq epos (car match-cons))
-            (setq semipos (cdr match-cons)))
-        (setq epos end))
+            (set 'epos (car match-cons))
+            (set 'semipos (cdr match-cons)))
+        (set 'epos end))
 
       ;;
       ;; read name(s) of parameter(s)
       ;;
       (goto-char apos)
-      (looking-at "\\([a-zA-Z0-9_, \t\n]*[a-zA-Z0-9_]\\)[ \t\n]*:[^=]")
-
-      (setq param (list (buffer-substring (match-beginning 1)
-                                          (match-end 1))))
-      (ada-search-ignore-string-comment ":" nil epos t)
+      (looking-at "\\(\\(\\sw\\|[_, \t\n]\\)*\\(\\sw\\|_\\)\\)[ \t\n]*:[^=]")
+
+      (set 'param (list (match-string 1)))
+      (ada-search-ignore-string-comment ":" nil epos t 'search-forward)
 
       ;;
       ;; look for 'in'
       ;;
-      (setq apos (point))
-      (setq param
-            (append param
-                    (list
-                     (consp
-                      (ada-search-ignore-string-comment "\\<in\\>"
-                                                        nil
-                                                        epos
-                                                        t)))))
+      (set 'apos (point))
+      (set 'param
+           (append param
+                   (list
+                    (consp
+                     (ada-search-ignore-string-comment
+                      "in" nil epos t 'word-search-forward)))))
 
       ;;
       ;; look for 'out'
       ;;
       (goto-char apos)
-      (setq param
-            (append param
-                    (list
-                     (consp
-                      (ada-search-ignore-string-comment "\\<out\\>"
-                                                        nil
-                                                        epos
-                                                        t)))))
+      (set 'param
+           (append param
+                   (list
+                    (consp
+                     (ada-search-ignore-string-comment
+                      "out" nil epos t 'word-search-forward)))))
 
       ;;
       ;; look for 'access'
       ;;
       (goto-char apos)
-      (setq param
-            (append param
-                    (list
-                     (consp
-                      (ada-search-ignore-string-comment "\\<access\\>"
-                                                        nil
-                                                        epos
-                                                        t)))))
+      (set 'param
+           (append param
+                   (list
+                    (consp
+                     (ada-search-ignore-string-comment
+                      "access" nil epos t 'word-search-forward)))))
 
       ;;
       ;; skip 'in'/'out'/'access'
@@ -1261,43 +1505,38 @@
         (ada-goto-next-non-ws))
 
       ;;
-      ;; read type of parameter 
+      ;; read type of parameter
       ;;
-      (looking-at "\\<[a-zA-Z0-9_\\.\\']+\\>")
-      (setq param
-            (append param
-                    (list
-                     (buffer-substring (match-beginning 0)
-                                       (match-end 0)))))
+      (looking-at "\\<\\(\\sw\\|[_.']\\)+\\>")
+      (set 'param
+           (append param
+                   (list (match-string 0))))
 
       ;;
       ;; read default-expression, if there is one
       ;;
-      (goto-char (setq apos (match-end 0)))
-      (setq param
-            (append param
-                    (list
-                     (if (setq match-cons
-                               (ada-search-ignore-string-comment ":="
-                                                                 nil
-                                                                 epos
-                                                                 t))
-                         (buffer-substring (car match-cons)
-                                           epos)
-                       nil))))
+      (goto-char (set 'apos (match-end 0)))
+      (set 'param
+           (append param
+                   (list
+                    (if (set 'match-cons
+                             (ada-search-ignore-string-comment
+                              ":=" nil epos t 'search-forward))
+                        (buffer-substring (car match-cons) epos)
+                      nil))))
       ;;
       ;; add this parameter-declaration to the list
       ;;
-      (setq paramlist (append paramlist (list param)))
+      (set 'paramlist (append paramlist (list param)))
 
       ;;
       ;; check if it was the last parameter
       ;;
       (if (eq epos end)
-          (setq notend nil)
+          (set 'notend nil)
         (goto-char semipos))
 
-      ) ; end of loop
+      )                                 ; end of loop
 
     (reverse paramlist)))
 
@@ -1313,53 +1552,52 @@
         (outp nil)
         (accessp nil)
         (column nil)
-        (orgpoint 0)
         (firstcol nil))
 
     ;;
     ;; loop until last parameter
     ;;
     (while (not (zerop i))
-      (setq i (1- i))
+      (set 'i (1- i))
 
       ;;
       ;; get max length of parameter-name
       ;;
-      (setq parlen
-            (if (<= parlen (setq temp
-                              (length (nth 0 (nth i paramlist)))))
-                temp
-              parlen))
+      (set 'parlen
+           (if (<= parlen (set 'temp
+                               (length (nth 0 (nth i paramlist)))))
+               temp
+             parlen))
 
       ;;
       ;; get max length of type-name
       ;;
-      (setq typlen
-            (if (<= typlen (setq temp
-                              (length (nth 4 (nth i paramlist)))))
-                temp
-              typlen))
+      (set 'typlen
+           (if (<= typlen (set 'temp
+                               (length (nth 4 (nth i paramlist)))))
+               temp
+             typlen))
 
       ;;
       ;; is there any 'in' ?
       ;;
-      (setq inp
-            (or inp
-                (nth 1 (nth i paramlist))))
+      (set 'inp
+           (or inp
+               (nth 1 (nth i paramlist))))
 
       ;;
       ;; is there any 'out' ?
       ;;
-      (setq outp
-            (or outp
-                (nth 2 (nth i paramlist))))
+      (set 'outp
+           (or outp
+               (nth 2 (nth i paramlist))))
 
       ;;
       ;; is there any 'access' ?
       ;;
-      (setq accessp
-            (or accessp
-                (nth 3 (nth i paramlist))))) ; end of loop
+      (set 'accessp
+           (or accessp
+               (nth 3 (nth i paramlist))))) ; end of loop
 
     ;;
     ;; does paramlist already start on a separate line ?
@@ -1368,31 +1606,35 @@
           (re-search-backward "^.\\|[^ \t]" nil t)
           (looking-at "^."))
         ;; yes => re-indent it
-        (ada-indent-current)
+        (progn
+          (ada-indent-current)
+          (save-excursion
+            (if (looking-at "\\(is\\|return\\)")
+                (replace-match " \\1"))))
       ;;
-      ;; no => insert newline and indent it
+      ;; no => insert it where we are after removing any whitespace
       ;;
-      (progn
-        (ada-indent-current)
-        (newline)
-        (delete-horizontal-space)
-        (setq orgpoint (point))
-        (setq column (save-excursion
-                       (funcall (ada-indent-function) orgpoint)))
-        (indent-to column)
-        ))
+      (fixup-whitespace)
+      (save-excursion
+        (cond
+         ((looking-at "[ \t]*\\(\n\\|;\\)")
+          (replace-match "\\1"))
+         ((looking-at "[ \t]*\\(is\\|return\\)")
+          (replace-match " \\1"))))
+      (insert " "))
 
     (insert "(")
-
-    (setq firstcol (current-column))
-    (setq i (length paramlist))
+    (ada-indent-current)
+
+    (set 'firstcol (current-column))
+    (set 'i (length paramlist))
 
     ;;
     ;; loop until last parameter
     ;;
     (while (not (zerop i))
-      (setq i (1- i))
-      (setq column firstcol)
+      (set 'i (1- i))
+      (set 'column firstcol)
 
       ;;
       ;; insert parameter-name, space and colon
@@ -1400,7 +1642,7 @@
       (insert (nth 0 (nth i paramlist)))
       (indent-to (+ column parlen 1))
       (insert ": ")
-      (setq column (current-column))
+      (set 'column (current-column))
 
       ;;
       ;; insert 'in' or space
@@ -1430,7 +1672,7 @@
       (if (nth 3 (nth i paramlist))
           (insert "access "))
 
-      (setq column (current-column))
+      (set 'column (current-column))
 
       ;;
       ;; insert type-name and, if necessary, space and default-expression
@@ -1444,23 +1686,20 @@
       ;;
       ;; check if it was the last parameter
       ;;
-      (if (not (zerop i))
-          ;; no => insert ';' and newline and indent
-          (progn
-            (insert ";")
-            (newline)
-            (indent-to firstcol))
-        ;; yes
-        (insert ")"))
-
-      ) ; end of loop
+      (if (zerop i)
+          (insert ")")
+        ;; no => insert ';' and newline and indent
+        (insert ";")
+        (newline)
+        (indent-to firstcol))
+      )                                 ; end of loop
 
     ;;
-    ;; if anything follows, except semicolon:
+    ;; if anything follows, except semicolon, newline, is or return
     ;; put it in a new line and indent it
     ;;
-    (if (not (looking-at "[ \t]*[;\n]"))
-        (ada-indent-newline-indent))
+    (unless (looking-at "[ \t]*\\(;\\|\n\\|is\\|return\\)")
+      (ada-indent-newline-indent))
 
     ))
 
@@ -1468,117 +1707,114 @@
 ;;;----------------------------;;;
 ;;; Move To Matching Start/End ;;;
 ;;;----------------------------;;;
-
 (defun ada-move-to-start ()
   "Moves point to the matching start of the current Ada structure."
   (interactive)
-  (let ((pos (point)))
+  (let ((pos (point))
+        (previous-syntax-table (syntax-table)))
     (unwind-protect
-	(progn
-	  (set-syntax-table ada-mode-symbol-syntax-table)
-
-	  (message "searching for block start ...")
-	  (save-excursion
-	    ;;
-	    ;; do nothing if in string or comment or not on 'end ...;'
-	    ;;            or if an error occurs during processing
-	    ;;
-	    (or
-	     (ada-in-string-or-comment-p)
-	     (and (progn
-		    (or (looking-at "[ \t]*\\<end\\>")
-			(backward-word 1))
-		    (or (looking-at "[ \t]*\\<end\\>")
-			(backward-word 1))
-		    (or (looking-at "[ \t]*\\<end\\>")
-			(error "not on end ...;")))
-		  (ada-goto-matching-start 1)
-		  (setq pos (point))
-
-		  ;;
-		  ;; on 'begin' => go on, according to user option
-		  ;;
-		  ada-move-to-declaration
-		  (looking-at "\\<begin\\>")
-		  (ada-goto-matching-decl-start)
-		  (setq pos (point))))
-
-	    ) ; end of save-excursion
-
-	  ;; now really move to the found position
-	  (goto-char pos)
-	  (message "searching for block start ... done"))
+        (progn
+          (set-syntax-table ada-mode-symbol-syntax-table)
+
+          (message "searching for block start ...")
+          (save-excursion
+            ;;
+            ;; do nothing if in string or comment or not on 'end ...;'
+            ;;            or if an error occurs during processing
+            ;;
+            (or
+             (ada-in-string-or-comment-p)
+             (and (progn
+                    (or (looking-at "[ \t]*\\<end\\>")
+                        (backward-word 1))
+                    (or (looking-at "[ \t]*\\<end\\>")
+                        (backward-word 1))
+                    (or (looking-at "[ \t]*\\<end\\>")
+                        (error "not on end ...;")))
+                  (ada-goto-matching-start 1)
+                  (set 'pos (point))
+
+                  ;;
+                  ;; on 'begin' => go on, according to user option
+                  ;;
+                  ada-move-to-declaration
+                  (looking-at "\\<begin\\>")
+                  (ada-goto-matching-decl-start)
+                  (set 'pos (point))))
+
+            )                           ; end of save-excursion
+
+          ;; now really move to the found position
+          (goto-char pos)
+          (message "searching for block start ... done"))
 
       ;;
       ;; restore syntax-table
       ;;
-      (set-syntax-table ada-mode-syntax-table))))
-
+      (set-syntax-table previous-syntax-table))))
 
 (defun ada-move-to-end ()
   "Moves point to the matching end of the current block around point.
 Moves to 'begin' if in a declarative part."
   (interactive)
   (let ((pos (point))
-        (decstart nil)
-        (packdecl nil))
+        (previous-syntax-table (syntax-table)))
     (unwind-protect
-	(progn
-	  (set-syntax-table ada-mode-symbol-syntax-table)
-
-	  (message "searching for block end ...")
-	  (save-excursion
-
-	    (forward-char 1)
-	    (cond
-	     ;; directly on 'begin'
-	     ((save-excursion
-		(ada-goto-previous-word)
-		(looking-at "\\<begin\\>"))
-	      (ada-goto-matching-end 1))
-	     ;; on first line of defun declaration
-	     ((save-excursion
-		(and (ada-goto-stmt-start)
-		     (looking-at "\\<function\\>\\|\\<procedure\\>" )))
-	      (ada-search-ignore-string-comment "\\<begin\\>"))
-	     ;; on first line of task declaration
-	     ((save-excursion
-		(and (ada-goto-stmt-start)
-		     (looking-at "\\<task\\>" )
-		     (forward-word 1)
-		     (ada-search-ignore-string-comment "[^ \n\t]")
-		     (not (backward-char 1))
-		     (looking-at "\\<body\\>")))
-	      (ada-search-ignore-string-comment "\\<begin\\>"))
-	     ;; accept block start
-	     ((save-excursion
-		(and (ada-goto-stmt-start)
-		     (looking-at "\\<accept\\>" )))
-	      (ada-goto-matching-end 0))
-	     ;; package start
-	     ((save-excursion
-		(and (ada-goto-matching-decl-start t)
-		     (looking-at "\\<package\\>")))
-	      (ada-goto-matching-end 1))
-	     ;; inside a 'begin' ... 'end' block
-	     ((save-excursion
-		(ada-goto-matching-decl-start t))
-	      (ada-search-ignore-string-comment "\\<begin\\>"))
-	     ;; (hopefully ;-) everything else
-	     (t
-	      (ada-goto-matching-end 1)))
-	    (setq pos (point))
-
-	    ) ; end of save-excursion
-
-	  ;; now really move to the found position
-	  (goto-char pos)
-	  (message "searching for block end ... done"))
-      
+        (progn
+          (set-syntax-table ada-mode-symbol-syntax-table)
+
+          (message "searching for block end ...")
+          (save-excursion
+
+            (forward-char 1)
+            (cond
+             ;; directly on 'begin'
+             ((save-excursion
+                (ada-goto-previous-word)
+                (looking-at "\\<begin\\>"))
+              (ada-goto-matching-end 1))
+             ;; on first line of defun declaration
+             ((save-excursion
+                (and (ada-goto-stmt-start)
+                     (looking-at "\\<function\\>\\|\\<procedure\\>" )))
+              (ada-search-ignore-string-comment "begin" nil nil nil 'word-search-forward))
+             ;; on first line of task declaration
+             ((save-excursion
+                (and (ada-goto-stmt-start)
+                     (looking-at "\\<task\\>" )
+                     (forward-word 1)
+                     (ada-goto-next-non-ws)
+                     (looking-at "\\<body\\>")))
+              (ada-search-ignore-string-comment "begin" nil nil nil 'word-search-forward))
+             ;; accept block start
+             ((save-excursion
+                (and (ada-goto-stmt-start)
+                     (looking-at "\\<accept\\>" )))
+              (ada-goto-matching-end 0))
+             ;; package start
+             ((save-excursion
+                (and (ada-goto-matching-decl-start t)
+                     (looking-at "\\<package\\>")))
+              (ada-goto-matching-end 1))
+             ;; inside a 'begin' ... 'end' block
+             ((save-excursion
+                (ada-goto-matching-decl-start t))
+              (ada-search-ignore-string-comment "begin" nil nil nil 'word-search-forward))
+             ;; (hopefully ;-) everything else
+             (t
+              (ada-goto-matching-end 1)))
+            (set 'pos (point))
+
+            )                           ; end of save-excursion
+
+          ;; now really move to the found position
+          (goto-char pos)
+          (message "searching for block end ... done"))
+
       ;;
       ;; restore syntax-table
       ;;
-      (set-syntax-table ada-mode-syntax-table))))
+      (set-syntax-table previous-syntax-table))))
 
 
 ;;;-----------------------------;;;
@@ -1586,33 +1822,27 @@
 ;;;-----------------------------;;;
 
 ;; ---- main functions for indentation
-
 (defun ada-indent-region (beg end)
   "Indents the region using `ada-indent-current' on each line."
   (interactive "*r")
   (goto-char beg)
   (let ((block-done 0)
-	(lines-remaining (count-lines beg end))
-	(msg (format "indenting %4d lines %%4d lines remaining ..."
-		     (count-lines beg end)))
+        (lines-remaining (count-lines beg end))
+        (msg (format "indenting %4d lines %%4d lines remaining ..."
+                     (count-lines beg end)))
         (endmark (copy-marker end)))
     ;; catch errors while indenting
-    (condition-case err
-        (while (< (point) endmark)
-          (if (> block-done 9)
-              (progn (message msg lines-remaining)
-                     (setq block-done 0)))
-	  (if (looking-at "^$") nil
-	    (ada-indent-current))
-          (forward-line 1)
-	  (setq block-done (1+ block-done))
-	  (setq lines-remaining (1- lines-remaining)))
-      ;; show line number where the error occurred
-      (error
-       (error "line %d: %s" (1+ (count-lines (point-min) (point))) err) nil))
+    (while (< (point) endmark)
+      (if (> block-done 39)
+          (progn (message msg lines-remaining)
+                 (set 'block-done 0)))
+      (if (looking-at "^$") nil
+        (ada-indent-current))
+      (forward-line 1)
+      (set 'block-done (1+ block-done))
+      (set 'lines-remaining (1- lines-remaining)))
     (message "indenting ... done")))
 
-
 (defun ada-indent-newline-indent ()
   "Indents the current line, inserts a newline and then indents the new line."
   (interactive "*")
@@ -1620,104 +1850,151 @@
   (newline)
   (ada-indent-current))
 
+(defun ada-indent-newline-indent-conditional ()
+  "If `ada-indent-after-return' is non-nil, then indents the current line,
+insert a newline and indents the newline.
+If `ada-indent-after-return' is nil then inserts a newline and indents the
+newline.
+This function is intended to be bound to the \C-m and \C-j keys"
+  (interactive "*")
+  (if ada-indent-after-return (ada-indent-current))
+  (newline)
+  (ada-indent-current))
+
+(defun ada-justified-indent-current ()
+  "Indent the current line and explains how it was chosen"
+  (interactive)
+
+  (let ((cur-indent (ada-indent-current)))
+
+    (message nil)
+    (if (equal (cdr cur-indent) '(0))
+	(message "same indentation")
+      (message (mapconcat (lambda(x)
+			    (cond
+			     ((symbolp x)
+			      (symbol-name x))
+			     ((numberp x)
+			      (number-to-string x))
+			     ((listp x)
+			      (concat "- " (symbol-name (cadr x))))
+			     ))
+			  (cdr cur-indent)
+			  " + ")))
+    (save-excursion
+      (goto-char (car cur-indent))
+      (sit-for 1))))
 
 (defun ada-indent-current ()
   "Indents current line as Ada code.
-This works by two steps:
- 1) It moves point to the end of the previous code line.
-    Then it calls the function to calculate the indentation for the
-    following line as if a newline would be inserted there.
-    The calculated column # is saved and the old position of point
-    is restored.
- 2) Then another function is called to calculate the indentation for
-    the current line, based on the previously calculated column #."
+Each of these steps returns a two element list:
+  - position of reference in the buffer
+  - offset to indent from this position (can also be a symbol or a list
+    that are evaluated"
 
   (interactive)
-
-  (unwind-protect
-      (progn
-	(set-syntax-table ada-mode-symbol-syntax-table)
-
-	(let ((line-end)
-	      (orgpoint (point-marker))
-	      (cur-indent)
-	      (prev-indent)
-	      (prevline t))
-
-	  ;;
-	  ;; first step
-	  ;;
+  (let ((previous-syntax-table (syntax-table))
+	(orgpoint (point-marker))
+	cur-indent tmp-indent
+	prev-indent)
+    
+    (set-syntax-table ada-mode-symbol-syntax-table)
+    
+    ;;  This need to be done here so that the advice is not always activated
+    ;;  (this might interact badly with other modes)
+    (if ada-xemacs
+        (ad-activate 'parse-partial-sexp t))
+
+    (unwind-protect
+        (progn
+
 	  (save-excursion
-	    (if (ada-goto-prev-nonblank-line t)
-		;;
-		;; we are not in the first accessible line in the buffer
-		;;
-		(progn
-		  ;;(end-of-line)
-		  ;;(forward-char 1)
-		  ;; we are already at the BOL
-		  (forward-line 1)
-		  (setq line-end (point))
-		  (setq prev-indent
-			(save-excursion
-			  (funcall (ada-indent-function) line-end))))
-              (progn                    ; first line of buffer -> set indent
-                (beginning-of-line)     ; to 0
-                (delete-horizontal-space)
-                (setq prevline nil))))
-
-	  (if prevline
-	      ;;
-	      ;; we are not in the first accessible line in the buffer
-	      ;;
-	      (progn
-		;;
-		;; second step
-		;;
-		(back-to-indentation)
-		(setq cur-indent (ada-get-current-indent prev-indent))
-                ;; only reindent if indentation is different then the current
-                (if (= (current-column) cur-indent)
-                    nil
-		  (delete-horizontal-space)
-                  (indent-to cur-indent))
-		;;
-		;; restore position of point
-		;;
-		(goto-char orgpoint)
-		(if (< (current-column) (current-indentation))
-		    (back-to-indentation))))))
-
+	    (set 'cur-indent
+		 ;; Not First line in the buffer ?
+		 
+		 (if (save-excursion (zerop (forward-line -1)))
+		     (progn
+		       (back-to-indentation)
+		       (ada-get-current-indent))
+		   
+		   ;; first line in the buffer
+		   (list (point-min) 0))))
+	    
+	  ;; Evaluate the list to get the column to indent to
+	  ;; prev-indent contains the column to indent to
+	  (set 'prev-indent (save-excursion (goto-char (car cur-indent)) (current-column)))
+	  (set 'tmp-indent (cdr cur-indent))
+	  (while (not (null tmp-indent))
+	    (cond
+	     ((numberp (car tmp-indent))
+	      (set 'prev-indent (+ prev-indent (car tmp-indent))))
+	     (t
+	      (set 'prev-indent (+ prev-indent (eval (car tmp-indent)))))
+	     )
+	    (set 'tmp-indent (cdr tmp-indent)))
+	  
+	  ;; only reindent if indentation is different then the current
+	  (if (= (save-excursion (back-to-indentation) (current-column)) prev-indent)
+	      nil
+	    (beginning-of-line)
+	    (delete-horizontal-space)
+	    (indent-to prev-indent))
+	  ;;
+	  ;; restore position of point
+	  ;;
+	  (goto-char orgpoint)
+	  (if (< (current-column) (current-indentation))
+	      (back-to-indentation))))
     ;;
     ;; restore syntax-table
     ;;
-    (set-syntax-table ada-mode-syntax-table)))
-
-
-(defun ada-get-current-indent (prev-indent)
-  ;; Returns the column # to indent the current line to.
-  ;; PREV-INDENT is the indentation resulting from the previous lines.
-  (let ((column nil)
-        (pos nil)
-        (match-cons nil))
-
+    (if ada-xemacs
+	(ad-deactivate 'parse-partial-sexp))
+    (set-syntax-table previous-syntax-table)
+    cur-indent
+    ))
+
+
+(defun ada-get-current-indent ()
+  "Returns the column number to indent the current line to.
+
+Returns a list of two elements (same as prev-indent):
+  - Position in the cursor that is used as a reference (its columns
+    is used)
+  - variable used to calculate the indentation from position"
+
+  (let (column
+	pos
+	match-cons
+	(orgpoint (save-excursion
+		    (beginning-of-line)
+		    (forward-comment -10000)
+		    (forward-line 1)
+		    (point))))
     (cond
      ;;
+     ;; preprocessor line (gnatprep)
+     ;;
+     ((and (equal ada-which-compiler 'gnat)
+           (looking-at "#[ \t]*\\(if\\|else\\|elsif\\|end[ \t]*if\\)"))
+      (list (save-excursion (beginning-of-line) (point)) 0))
+
+     ;;
      ;; in open parenthesis, but not in parameter-list
      ;;
      ((and
        ada-indent-to-open-paren
        (not (ada-in-paramlist-p))
-       (setq column (ada-in-open-paren-p)))
+       (set 'column (ada-in-open-paren-p)))
       ;; check if we have something like this  (Table_Component_Type =>
-      ;;                                          Source_File_Record,)
+      ;;                                          Source_File_Record)
       (save-excursion
-        (if (and (ada-search-ignore-string-comment "[^ \t]" t nil)
-                 (looking-at "\n")
-                 (ada-search-ignore-string-comment "[^ \t\n]" t nil)
-                 (looking-at ">"))
-            (setq column (+ ada-broken-indent column))))
-      column)
+        (if (and (skip-chars-backward " \t")
+                 (= (char-before) ?\n)
+                 (not (forward-comment -10000))
+                 (= (char-before) ?>))
+	    (list column 'ada-broken-indent);; ??? Could use a different variable
+	  (list column 0))))
 
      ;;
      ;; end
@@ -1731,111 +2008,104 @@
           ;; found 'loop' => skip back to 'while' or 'for'
           ;;                 if 'loop' is not on a separate line
           ;;
-          (if (and
-               (looking-at "\\<loop\\>")
-               (save-excursion
-                 (back-to-indentation)
-                 (not (looking-at "\\<loop\\>"))))
+          (if (save-excursion
+                (beginning-of-line)
+                (looking-at ".+\\<loop\\>"))
               (if (save-excursion
                     (and
-                     (setq match-cons
-                           (ada-search-ignore-string-comment
-                            ada-loop-start-re t nil))
+                     (set 'match-cons
+                          (ada-search-ignore-string-comment ada-loop-start-re t))
                      (not (looking-at "\\<loop\\>"))))
                   (progn
                     (goto-char (car match-cons))
                     (save-excursion
                       (beginning-of-line)
                       (if (looking-at ada-named-block-re)
-                          (setq label (- ada-label-indent)))))))
-
-          (+ (current-indentation) label))))
+                          (set 'label (- ada-label-indent)))))))
+
+	  (list (+ (save-excursion (back-to-indentation) (point)) label) 0))))
      ;;
      ;; exception
      ;;
      ((looking-at "\\<exception\\>")
       (save-excursion
         (ada-goto-matching-start 1)
-        (current-indentation)))
+	(list (save-excursion (back-to-indentation) (point)) 0)))
      ;;
      ;; when
      ;;
      ((looking-at "\\<when\\>")
       (save-excursion
         (ada-goto-matching-start 1)
-        (+ (current-indentation) ada-when-indent)))
+	(list (save-excursion (back-to-indentation) (point)) 'ada-when-indent)))
      ;;
      ;; else
      ;;
      ((looking-at "\\<else\\>")
-      (if (save-excursion
-            (ada-goto-previous-word)
-            (looking-at "\\<or\\>"))
-          prev-indent
+      (if (save-excursion  (ada-goto-previous-word)
+			   (looking-at "\\<or\\>"))
+	  (ada-indent-on-previous-lines nil orgpoint orgpoint)
         (save-excursion
           (ada-goto-matching-start 1 nil t)
-          (current-indentation))))
+	  (list (progn (back-to-indentation) (point)) 0))))
      ;;
      ;; elsif
      ;;
      ((looking-at "\\<elsif\\>")
       (save-excursion
         (ada-goto-matching-start 1 nil t)
-        (current-indentation)))
+	(list (progn (back-to-indentation) (point)) 0)))
      ;;
      ;; then
      ;;
      ((looking-at "\\<then\\>")
-      (if (save-excursion
-            (ada-goto-previous-word)
-            (looking-at "\\<and\\>"))
-          prev-indent
+      (if (save-excursion (ada-goto-previous-word)
+			  (looking-at "\\<and\\>"))
+	  (ada-indent-on-previous-lines nil orgpoint orgpoint)
         (save-excursion
-          (ada-search-ignore-string-comment "\\<elsif\\>\\|\\<if\\>" t nil)
-          (+ (current-indentation) ada-stmt-end-indent))))
+          ;;  Select has been added for the statement:  "select ... then abort"
+          (ada-search-ignore-string-comment "\\<\\(elsif\\|if\\|select\\)\\>" t nil)
+	  (list (progn (back-to-indentation) (point)) 'ada-stmt-end-indent))))
      ;;
      ;; loop
      ;;
      ((looking-at "\\<loop\\>")
-      (setq pos (point))
+      (set 'pos (point))
       (save-excursion
         (goto-char (match-end 0))
         (ada-goto-stmt-start)
-        (if (looking-at "\\<loop\\>\\|\\<if\\>")
-            prev-indent
-          (progn
-            (if (not (looking-at ada-loop-start-re))
-                (ada-search-ignore-string-comment ada-loop-start-re
-                                                  nil pos))
-            (if (looking-at "\\<loop\\>")
-                prev-indent
-              (+ (current-indentation) ada-stmt-end-indent))))))
+        (if (looking-at "\\<\\(loop\\|if\\)\\>")
+	    (ada-indent-on-previous-lines nil orgpoint orgpoint)
+	  (unless (looking-at ada-loop-start-re)
+	    (ada-search-ignore-string-comment ada-loop-start-re
+					      nil pos))
+	  (if (looking-at "\\<loop\\>")
+	      (ada-indent-on-previous-lines nil orgpoint orgpoint)
+	    (list (progn (back-to-indentation) (point)) 'ada-stmt-end-indent)))))
      ;;
      ;; begin
      ;;
      ((looking-at "\\<begin\\>")
       (save-excursion
         (if (ada-goto-matching-decl-start t)
-            (current-indentation)
-          prev-indent)))
+	    (list (progn (back-to-indentation) (point)) 0)
+	  (ada-indent-on-previous-lines nil orgpoint orgpoint))))
      ;;
      ;; is
      ;;
      ((looking-at "\\<is\\>")
-      (if (and
-           ada-indent-is-separate
-           (save-excursion
-             (goto-char (match-end 0))
-             (ada-goto-next-non-ws (save-excursion
-                                     (end-of-line)
-                                     (point)))
-             (looking-at "\\<abstract\\>\\|\\<separate\\>")))
+      (if (and ada-indent-is-separate
+	       (save-excursion
+		 (goto-char (match-end 0))
+		 (ada-goto-next-non-ws (save-excursion (end-of-line)
+						       (point)))
+		 (looking-at "\\<abstract\\>\\|\\<separate\\>")))
           (save-excursion
             (ada-goto-stmt-start)
-            (+ (current-indentation) ada-indent))
+	    (list (progn (back-to-indentation) (point)) 'ada-indent))
         (save-excursion
           (ada-goto-stmt-start)
-          (+ (current-indentation) ada-stmt-end-indent))))
+	  (list (progn (back-to-indentation) (point)) 'ada-stmt-end-indent))))
      ;;
      ;; record
      ;;
@@ -1844,46 +2114,60 @@
         (ada-search-ignore-string-comment
          "\\<\\(type\\|use\\)\\>" t nil)
         (if (looking-at "\\<use\\>")
-            (ada-search-ignore-string-comment "\\<for\\>" t nil))
-        (+ (current-indentation) ada-indent-record-rel-type)))
+            (ada-search-ignore-string-comment "for" t nil nil 'word-search-backward))
+	(list (progn (back-to-indentation) (point)) 'ada-indent-record-rel-type)))
      ;;
-     ;; or as statement-start
+     ;; 'or'      as statement-start
+     ;; 'private' as statement-start
      ;;
-     ((ada-looking-at-semi-or)
+     ((or (ada-looking-at-semi-or)
+	  (ada-looking-at-semi-private))
       (save-excursion
         (ada-goto-matching-start 1)
-        (current-indentation)))
-     ;;
-     ;; private as statement-start
-     ;;
-     ((ada-looking-at-semi-private)
-      (save-excursion
-        (ada-goto-matching-decl-start)
-        (current-indentation)))
+	(list (progn (back-to-indentation) (point)) 0)))
      ;;
      ;; new/abstract/separate
      ;;
      ((looking-at "\\<\\(new\\|abstract\\|separate\\)\\>")
-      (- prev-indent ada-indent (- ada-broken-indent)))
+      (ada-indent-on-previous-lines nil orgpoint orgpoint))
      ;;
      ;; return
      ;;
      ((looking-at "\\<return\\>")
       (save-excursion
-        (forward-sexp -1)
-        (if (and (looking-at "(")
+	(forward-comment -1000)
+	(if (= (char-before) ?\))
+	    (forward-sexp -1)
+	  (forward-word -1))
+
+	;; If there is a parameter list, and we have a function declaration
+        (if (and (= (char-after) ?\()
                  (save-excursion
                    (backward-sexp 2)
                    (looking-at "\\<function\\>")))
-            (1+ (current-column))
-          prev-indent)))
+
+	    ;; The indentation depends of the value of ada-indent-return
+	    (if (<= ada-indent-return 0)
+		(list (point) (- ada-indent-return))
+	      (list (progn (backward-sexp 2) (point)) ada-indent-return))
+
+	  ;; Else there is no parameter list, but we have a function
+	  ;; Only do something special if the user want to indent relative
+	  ;; to the "function" keyword
+	  (if (and (> ada-indent-return 0)
+		   (save-excursion (forward-word -1)
+				   (looking-at "\\<function\\>")))
+	      (list (progn (forward-word -1) (point)) ada-indent-return)
+
+	    ;; Else...
+	    (ada-indent-on-previous-lines nil orgpoint orgpoint)))))
      ;;
      ;; do
      ;;
      ((looking-at "\\<do\\>")
       (save-excursion
         (ada-goto-stmt-start)
-        (+ (current-indentation) ada-stmt-end-indent)))
+	(list (progn (back-to-indentation) (point)) 'ada-stmt-end-indent)))
      ;;
      ;; package/function/procedure
      ;;
@@ -1896,163 +2180,178 @@
         ;; look for 'generic'
         (if (and (ada-goto-matching-decl-start t)
                  (looking-at "generic"))
-            (current-column)
-          prev-indent)))
+	    (list (progn (back-to-indentation) (point)) 0)
+	  (ada-indent-on-previous-lines nil orgpoint orgpoint))))
      ;;
      ;; label
      ;;
-     ((looking-at "\\<[a-zA-Z0-9_]+[ \t\n]*:[^=]")
+     ((looking-at "\\<\\(\\sw\\|_\\)+[ \t\n]*:[^=]")
       (if (ada-in-decl-p)
-          prev-indent
-        (+ prev-indent ada-label-indent)))
+	  (ada-indent-on-previous-lines nil orgpoint orgpoint)
+	(set 'pos (ada-indent-on-previous-lines nil orgpoint orgpoint))
+	(list (car pos)
+	      (cadr pos)
+	      'ada-label-indent)))
      ;;
      ;; identifier and other noindent-statements
      ;;
-     ((looking-at "\\<[a-zA-Z0-9_]+[ \t\n]*")
-      prev-indent)
+     ((looking-at "\\<\\(\\sw\\|_\\)+[ \t\n]*")
+      (ada-indent-on-previous-lines nil orgpoint orgpoint))
      ;;
      ;; beginning of a parameter list
      ;;
-     ((looking-at "(")
-      prev-indent)
+     ((and (not (eobp)) (= (char-after) ?\())
+      (ada-indent-on-previous-lines nil orgpoint orgpoint))
      ;;
      ;; end of a parameter list
      ;;
-     ((looking-at ")")
+     ((and (not (eobp)) (= (char-after) ?\)))
       (save-excursion
         (forward-char 1)
         (backward-sexp 1)
-        (current-column)))
+	(list (point) 0)))
      ;;
      ;; comment
      ;;
      ((looking-at "--")
       (if ada-indent-comment-as-code
-          prev-indent
-        (current-indentation)))
+	  ;; If previous line is a comment, indent likewise
+	  (save-excursion
+	    (forward-line -1)
+	    (beginning-of-line)
+	    (if (looking-at "[ \t]*--")
+		(list (progn (back-to-indentation) (point)) 0)
+	      (ada-indent-on-previous-lines nil orgpoint orgpoint)))
+	(list (save-excursion (back-to-indentation) (point)) 0)))
      ;;
      ;; unknown syntax - maybe this should signal an error ?
      ;;
      (t
-      prev-indent))))
-
-
-(defun ada-indent-function (&optional nomove)
-  ;; Returns the function to calculate the indentation for the current
-  ;; line according to the previous statement, ignoring the contents
-  ;; of the current line after point.  Moves point to the beginning of
-  ;; the current statement, if NOMOVE is nil.
-
-  (let ((orgpoint (point))
-        (func nil))
+      (ada-indent-on-previous-lines nil orgpoint orgpoint)))))
+
+(defun ada-indent-on-previous-lines (&optional nomove orgpoint initial-pos)
+  "Calculate the indentation of the current line, based on the previous lines
+in the buffer. This function does not pay any attention to the current line,
+since this is the role of the second step in the indentation
+ (see ada-get-current-indent).
+
+Returns a two element list:
+    - position of reference in the buffer
+    - offset to indent from this position (can also be a symbol or a list
+      that are evaluated)
+Moves point to the beginning of the current statement, if NOMOVE is nil."
+  (if initial-pos
+      (goto-char initial-pos))
+  (let ((oldpoint (point))
+        result)
     ;;
-    ;; inside a parameter-list
+    ;; Is inside a parameter-list ?
     ;;
     (if (ada-in-paramlist-p)
-        (setq func 'ada-get-indent-paramlist)
-      (progn
-        ;;
-        ;; move to beginning of current statement
-        ;;
-        (if (not nomove)
-            (ada-goto-stmt-start))
-        ;;
-        ;; no beginning found => don't change indentation
-        ;;
-        (if (and
-             (eq orgpoint (point))
-             (not nomove))
-            (setq func 'ada-get-indent-nochange)
-
-          (cond
-           ;;
-           ((and
-             ada-indent-to-open-paren
-             (ada-in-open-paren-p))
-            (setq func 'ada-get-indent-open-paren))
-           ;;
-           ((looking-at "\\<end\\>")
-            (setq func 'ada-get-indent-end))
-           ;;
-           ((looking-at ada-loop-start-re)
-            (setq func 'ada-get-indent-loop))
-           ;;
-           ((looking-at ada-subprog-start-re)
-            (setq func 'ada-get-indent-subprog))
-           ;;
-           ((looking-at ada-block-start-re)
-            (setq func 'ada-get-indent-block-start))
-           ;;
-           ((looking-at "\\<type\\>")
-            (setq func 'ada-get-indent-type))
-           ;;
-           ((looking-at "\\<\\(els\\)?if\\>")
-            (setq func 'ada-get-indent-if))
-           ;;
-           ((looking-at "\\<case\\>")
-            (setq func 'ada-get-indent-case))
-           ;;
-           ((looking-at "\\<when\\>")
-            (setq func 'ada-get-indent-when))
-           ;;
-           ((looking-at "--")
-            (setq func 'ada-get-indent-comment))
-           ;;
-           ((looking-at "[a-zA-Z0-9_]+[ \t\n]*:[^=]")
-            (setq func 'ada-get-indent-label))
-           ;;
-	   ((looking-at "\\<separate\\>")
-	    (setq func 'ada-get-indent-nochange))
-           (t
-            (setq func 'ada-get-indent-noindent))))))
-
-    func))
+        (set 'result (ada-get-indent-paramlist orgpoint))
+
+      ;;
+      ;; move to beginning of current statement
+      ;;
+      (unless nomove
+        (ada-goto-stmt-start))
+
+      (unless result
+        (progn
+          ;;
+          ;; no beginning found => don't change indentation
+          ;;
+          (if (and (eq oldpoint (point))
+                   (not nomove))
+              (set 'result (ada-get-indent-nochange orgpoint))
+
+            (cond
+             ;;
+             ((and
+               ada-indent-to-open-paren
+               (ada-in-open-paren-p))
+              (set 'result (ada-get-indent-open-paren orgpoint)))
+             ;;
+             ((looking-at "end\\>")
+              (set 'result (ada-get-indent-end orgpoint)))
+             ;;
+             ((looking-at ada-loop-start-re)
+              (set 'result (ada-get-indent-loop orgpoint)))
+             ;;
+             ((looking-at ada-subprog-start-re)
+              (set 'result (ada-get-indent-subprog orgpoint)))
+             ;;
+             ((looking-at ada-block-start-re)
+              (set 'result (ada-get-indent-block-start orgpoint)))
+             ;;
+             ((looking-at "\\(sub\\)?type\\>")
+              (set 'result (ada-get-indent-type orgpoint)))
+	     ;;
+             ((looking-at "\\(els\\)?if\\>")
+              (set 'result (ada-get-indent-if orgpoint)))
+             ;;
+             ((looking-at "case\\>")
+              (set 'result (ada-get-indent-case orgpoint)))
+             ;;
+             ((looking-at "when\\>")
+              (set 'result (ada-get-indent-when orgpoint)))
+             ;;
+             ((looking-at "\\(\\sw\\|_\\)+[ \t\n]*:[^=]")
+              (set 'result (ada-get-indent-label orgpoint)))
+             ;;
+             ((looking-at "separate\\>")
+              (set 'result (ada-get-indent-nochange orgpoint)))
+             (t
+              (set 'result (ada-get-indent-noindent orgpoint))))))))
+
+    result))
 
 
 ;; ---- functions to return indentation for special cases
 
 (defun ada-get-indent-open-paren (orgpoint)
-  ;; Returns the indentation (column #) for the new line after ORGPOINT.
-  ;; Assumes point to be behind an open parenthesis not yet closed.
-  (ada-in-open-paren-p))
+  "Returns the two element list for the indentation, when point is
+behind an open parenthesis not yet closed"
+  (list (ada-in-open-paren-p) 0))
 
 
 (defun ada-get-indent-nochange (orgpoint)
-  ;; Returns the indentation (column #) of the current line.
+  "Returns the two element list for the indentation of the current line"
   (save-excursion
     (forward-line -1)
-    (current-indentation)))
+    (list (progn (back-to-indentation) (point)) 0)))
 
 
 (defun ada-get-indent-paramlist (orgpoint)
-  ;; Returns the indentation (column #) for the new line after ORGPOINT.
-  ;; Assumes point to be inside a parameter-list.
+  "Returns the classical two position list for indentation for the new line
+after ORGPOINT.
+Assumes point to be inside a parameter list"
   (save-excursion
     (ada-search-ignore-string-comment "[^ \t\n]" t nil t)
     (cond
      ;;
      ;; in front of the first parameter
      ;;
-     ((looking-at "(")
+     ((= (char-after) ?\()
       (goto-char (match-end 0))
-      (current-column))
+      (list (point) 0))
      ;;
      ;; in front of another parameter
      ;;
-     ((looking-at ";")
+     ((= (char-after) ?\;)
       (goto-char (cdr (ada-search-ignore-string-comment "(\\|;" t nil t)))
       (ada-goto-next-non-ws)
-      (current-column))
+      (list (point) 0))
      ;;
      ;; inside a parameter declaration
      ;;
      (t
       (goto-char (cdr (ada-search-ignore-string-comment "(\\|;" t nil t)))
       (ada-goto-next-non-ws)
-      (+ (current-column) ada-broken-indent)))))
-
-
-(defun ada-get-indent-end (orgpoint)
+      (list (point) 'ada-broken-indent)))))
+
+
+(defun ada-get-indent-end (orgpoint &optional do-not-check-start)
   ;; Returns the indentation (column #) for the new line after ORGPOINT.
   ;; Assumes point to be at the beginning of an end-statement.
   ;; Therefore it has to find the corresponding start. This can be a little
@@ -2065,7 +2364,7 @@
     ;; is the line already terminated by ';' ?
     ;;
     (if (save-excursion
-          (ada-search-ignore-string-comment ";" nil orgpoint))
+          (ada-search-ignore-string-comment ";" nil orgpoint nil 'search-forward))
         ;;
         ;; yes, look what's following 'end'
         ;;
@@ -2073,206 +2372,185 @@
           (forward-word 1)
           (ada-goto-next-non-ws)
           (cond
+	   ((looking-at "\\<\\(loop\\|select\\|if\\|case\\)\\>")
+	    (unless do-not-check-start
+	      (save-excursion (ada-check-matching-start (match-string 0))))
+	    (list (save-excursion (back-to-indentation) (point)) 0))
+	    
            ;;
            ;; loop/select/if/case/record/select
            ;;
-           ((looking-at "\\<\\(loop\\|select\\|if\\|case\\|record\\)\\>")
+           ((looking-at "\\<record\\>")
             (save-excursion
-              (ada-check-matching-start
-               (buffer-substring (match-beginning 0)
-                                 (match-end 0)))
-              (if (looking-at "\\<\\(loop\\|record\\)\\>")
-                  (progn
-                    (forward-word 1)
-                    (ada-goto-stmt-start)))
-              ;; a label ? => skip it
-              (if (looking-at ada-named-block-re)
-                  (progn
-                    (setq label (- ada-label-indent))
-                    (goto-char (match-end 0))
-                    (ada-goto-next-non-ws)))
-              ;; really looking-at the right thing ?
-              (or (looking-at (concat "\\<\\("
-                                      "loop\\|select\\|if\\|case\\|"
-                                      "record\\|while\\|type\\)\\>"))
-                  (progn
-                    (ada-search-ignore-string-comment
-                     (concat "\\<\\("
-                             "loop\\|select\\|if\\|case\\|"
-                             "record\\|while\\|type\\)\\>")))
-                  (backward-word 1))
-              (+ (current-indentation) label)))
+              (ada-check-matching-start (match-string 0))
+	      ;;  we are now looking at the matching "record" statement
+	      (forward-word 1)
+	      (ada-goto-stmt-start)
+	      ;;  now on the matching type declaration, or use clause
+	      (unless (looking-at "\\(for\\|type\\)\\>")
+		(ada-search-ignore-string-comment "\\<type\\>" t))
+	      (list (progn (back-to-indentation) (point)) 0)))
            ;;
            ;; a named block end
            ;;
            ((looking-at ada-ident-re)
-            (setq defun-name (buffer-substring (match-beginning 0)
-                                               (match-end 0)))
-            (save-excursion
-              (ada-goto-matching-start 0)
-              (ada-check-defun-name defun-name)
-              (current-indentation)))
+	    (unless do-not-check-start
+	      (progn
+		(set 'defun-name (match-string 0))
+		(save-excursion
+		  (ada-goto-matching-start 0)
+		  (ada-check-defun-name defun-name))))
+	    (list (progn (back-to-indentation) (point)) 0))
            ;;
            ;; a block-end without name
            ;;
-           ((looking-at ";")
-            (save-excursion
-              (ada-goto-matching-start 0)
-              (if (looking-at "\\<begin\\>")
-                  (progn
-                    (setq indent (current-column))
-                    (if (ada-goto-matching-decl-start t)
-                        (current-indentation)
-                      indent)))))
+           ((= (char-after) ?\;)
+	    (unless do-not-check-start
+	      (save-excursion
+		(ada-goto-matching-start 0)
+		(if (looking-at "\\<begin\\>")
+		    (progn
+		      (set 'indent (list (point) 0))
+		      (if (ada-goto-matching-decl-start t)
+			  (list (progn (back-to-indentation) (point)) 0)
+			indent))))
+	      (list (progn (back-to-indentation) (point)) 0)))
            ;;
            ;; anything else - should maybe signal an error ?
            ;;
            (t
-            (+ (current-indentation) ada-broken-indent))))
-
-      (+ (current-indentation) ada-broken-indent))))
+	    (list (save-excursion (back-to-indentation) (point)) 'ada-broken-indent))))
+
+      (list (save-excursion (back-to-indentation) (point)) 'ada-broken-indent))))
 
 
 (defun ada-get-indent-case (orgpoint)
   ;; Returns the indentation (column #) for the new line after ORGPOINT.
   ;; Assumes point to be at the beginning of a case-statement.
-  (let ((cur-indent (current-indentation))
-        (match-cons nil)
+  (let ((match-cons nil)
         (opos (point)))
     (cond
      ;;
      ;; case..is..when..=>
      ;;
      ((save-excursion
-        (setq match-cons (and
+        (set 'match-cons (and
                           ;; the `=>' must be after the keyword `is'.
                           (ada-search-ignore-string-comment
-                           "\\<is\\>" nil orgpoint)
+                           "is" nil orgpoint nil 'word-search-forward)
                           (ada-search-ignore-string-comment
                            "[ \t\n]+=>" nil orgpoint))))
       (save-excursion
         (goto-char (car match-cons))
-        (if (not (ada-search-ignore-string-comment "\\<when\\>" t opos))
-            (error "missing 'when' between 'case' and '=>'"))
-        (+ (current-indentation) ada-indent)))
+        (unless (ada-search-ignore-string-comment "when" t opos)
+          (error "missing 'when' between 'case' and '=>'"))
+	(list (save-excursion (back-to-indentation) (point)) 'ada-indent)))
      ;;
      ;; case..is..when
      ;;
      ((save-excursion
-       (setq match-cons (ada-search-ignore-string-comment
-                         "\\<when\\>" nil orgpoint)))
+        (set 'match-cons (ada-search-ignore-string-comment
+                          "when" nil orgpoint nil 'word-search-forward)))
       (goto-char (cdr match-cons))
-      (+ (current-indentation) ada-broken-indent))
+      (list (save-excursion (back-to-indentation) (point)) 'ada-broken-indent))
      ;;
      ;; case..is
      ;;
      ((save-excursion
-       (setq match-cons (ada-search-ignore-string-comment
-                         "\\<is\\>" nil orgpoint)))
-      (+ (current-indentation) ada-when-indent))
+        (set 'match-cons (ada-search-ignore-string-comment
+                          "is" nil orgpoint nil 'word-search-forward)))
+      (list (save-excursion (back-to-indentation) (point)) 'ada-when-indent))
      ;;
      ;; incomplete case
      ;;
      (t
-      (+ (current-indentation) ada-broken-indent)))))
+      (list (save-excursion (back-to-indentation) (point)) 'ada-broken-indent)))))
 
 
 (defun ada-get-indent-when (orgpoint)
   ;; Returns the indentation (column #) for the new line after ORGPOINT.
   ;; Assumes point to be at the beginning of an when-statement.
-  (let ((cur-indent (current-indentation)))
+  (let ((cur-indent (save-excursion (back-to-indentation) (point))))
     (if (ada-search-ignore-string-comment
-         "[ \t\n]+=>" nil orgpoint)
-        (+ cur-indent  ada-indent)
-      (+ cur-indent ada-broken-indent))))
+         "[ \t\n]*=>" nil orgpoint)
+	(list cur-indent 'ada-indent)
+      (list cur-indent 'ada-broken-indent))))
 
 
 (defun ada-get-indent-if (orgpoint)
   ;; Returns the indentation (column #) for the new line after ORGPOINT.
   ;; Assumes point to be at the beginning of an if-statement.
-  (let ((cur-indent (current-indentation))
+  (let ((cur-indent (save-excursion (back-to-indentation) (point)))
         (match-cons nil))
     ;;
-    ;; if..then ?
+    ;; Move to the correct then (ignore all "and then")
     ;;
-    (if (ada-search-but-not
-         "\\<then\\>" "\\<and\\>[ \t\n]+\\<then\\>" nil orgpoint)
-
+    (while (and (set 'match-cons (ada-search-ignore-string-comment
+                                  "\\<\\(then\\|and[ \t]*then\\)\\>"
+                                  nil orgpoint))
+                (= (char-after (car match-cons)) ?a)))
+    ;; If "then" was found (we are looking at it)
+    (if match-cons
         (progn
           ;;
           ;; 'then' first in separate line ?
-          ;; => indent according to 'then'
+          ;; => indent according to 'then',
+	  ;; => else indent according to 'if'
           ;;
           (if (save-excursion
                 (back-to-indentation)
                 (looking-at "\\<then\\>"))
-              (setq cur-indent (current-indentation)))
+              (set 'cur-indent (save-excursion (back-to-indentation) (point))))
+	  ;; skip 'then'
           (forward-word 1)
-          ;;
-          ;; something follows 'then' ?
-          ;;
-          (if (setq match-cons
-                    (ada-search-ignore-string-comment
-                     "[^ \t\n]" nil orgpoint))
-              (progn
-                (goto-char (car match-cons))
-                (+ ada-indent
-                   (- cur-indent (current-indentation))
-                   (funcall (ada-indent-function t) orgpoint)))
-
-            (+ cur-indent ada-indent)))
-
-      (+ cur-indent ada-broken-indent))))
+	  (list cur-indent 'ada-indent))
+
+      (list cur-indent 'ada-broken-indent))))
 
 
 (defun ada-get-indent-block-start (orgpoint)
   ;; Returns the indentation (column #) for the new line after
   ;; ORGPOINT.  Assumes point to be at the beginning of a block start
   ;; keyword.
-  (let ((cur-indent (current-indentation))
-        (pos nil))
+  (let ((pos nil))
     (cond
      ((save-excursion
         (forward-word 1)
-        (setq pos (car (ada-search-ignore-string-comment
-                        "[^ \t\n]" nil orgpoint))))
+        (set 'pos (ada-goto-next-non-ws orgpoint)))
       (goto-char pos)
       (save-excursion
-        (funcall (ada-indent-function t) orgpoint)))
+        (ada-indent-on-previous-lines t orgpoint)))
      ;;
      ;; nothing follows the block-start
      ;;
      (t
-      (+ (current-indentation) ada-indent)))))
+      (list (save-excursion (back-to-indentation) (point)) 'ada-indent)))))
 
 
 (defun ada-get-indent-subprog (orgpoint)
   ;; Returns the indentation (column #) for the new line after ORGPOINT.
   ;; Assumes point to be at the beginning of a subprog-/package-declaration.
   (let ((match-cons nil)
-        (cur-indent (current-indentation))
-        (foundis nil)
-        (addind 0)
-        (fstart (point)))
+        (cur-indent (save-excursion (back-to-indentation) (point)))
+        (foundis nil))
     ;;
     ;; is there an 'is' in front of point ?
     ;;
     (if (save-excursion
-          (setq match-cons
-                (ada-search-ignore-string-comment
-                 "\\<\\(is\\|do\\)\\>" nil orgpoint)))
+          (set 'match-cons
+               (ada-search-ignore-string-comment
+                "\\<\\(is\\|do\\)\\>" nil orgpoint)))
         ;;
         ;; yes, then skip to its end
         ;;
         (progn
-          (setq foundis t)
+          (set 'foundis t)
           (goto-char (cdr match-cons)))
       ;;
       ;; no, then goto next non-ws, if there is one in front of point
       ;;
       (progn
-        (if (ada-search-ignore-string-comment "[^ \t\n]" nil orgpoint)
-            (ada-goto-next-non-ws)
+        (unless (ada-goto-next-non-ws orgpoint)
           (goto-char orgpoint))))
 
     (cond
@@ -2284,17 +2562,17 @@
        (save-excursion
          (not (ada-search-ignore-string-comment
                "[^ \t\n]" nil orgpoint t))))
-      (+ cur-indent ada-indent))
+      (list cur-indent 'ada-indent))
      ;;
      ;; is abstract/separate/new ...
      ;;
      ((and
        foundis
        (save-excursion
-         (setq match-cons
-               (ada-search-ignore-string-comment
-                "\\<\\(separate\\|new\\|abstract\\)\\>"
-                nil orgpoint))))
+         (set 'match-cons
+              (ada-search-ignore-string-comment
+               "\\<\\(separate\\|new\\|abstract\\)\\>"
+               nil orgpoint))))
       (goto-char (car match-cons))
       (ada-search-ignore-string-comment ada-subprog-start-re t)
       (ada-get-indent-noindent orgpoint))
@@ -2303,21 +2581,20 @@
      ;;
      ((and
        foundis
-       (save-excursion
-         (ada-search-ignore-string-comment "[^ \t\n]" nil orgpoint))
-       (ada-goto-next-non-ws)
-      (funcall (ada-indent-function t) orgpoint)))
+       (save-excursion (set 'match-cons (ada-goto-next-non-ws orgpoint)))
+       (goto-char match-cons)
+       (ada-indent-on-previous-lines t orgpoint)))
      ;;
      ;; no 'is' but ';'
      ;;
      ((save-excursion
-        (ada-search-ignore-string-comment ";" nil orgpoint))
-      cur-indent)
+        (ada-search-ignore-string-comment ";" nil orgpoint nil 'search-forward))
+      (list cur-indent 0))
      ;;
      ;; no 'is' or ';'
      ;;
      (t
-      (+ cur-indent ada-broken-indent)))))
+      (list cur-indent 'ada-broken-indent)))))
 
 
 (defun ada-get-indent-noindent (orgpoint)
@@ -2326,13 +2603,45 @@
   (let ((label 0))
     (save-excursion
       (beginning-of-line)
-      (if (looking-at ada-named-block-re)
-          (setq label (- ada-label-indent))))
-    (if (save-excursion
-          (ada-search-ignore-string-comment ";" nil orgpoint))
-        (+ (current-indentation) label)
-      (+ (current-indentation) ada-broken-indent label))))
-
+
+      (cond
+
+       ;;  This one is called when indenting a line preceded by a multiline
+       ;;  subprogram declaration (in that case, we are at this point inside
+       ;;  the parameter declaration list)
+       ((ada-in-paramlist-p)
+        (ada-previous-procedure)
+	(list (save-excursion (back-to-indentation) (point)) 0))
+
+       ;;  This one is called when indenting the second line of a multiline
+       ;;  declaration section, in a declare block or a record declaration
+       ((looking-at "[ \t]*\\(\\sw\\|_\\)*[ \t]*,[ \t]*$")
+	(list (save-excursion (back-to-indentation) (point))
+	      'ada-broken-decl-indent))
+
+       ;;  This one is called in every over case when indenting a line at the
+       ;;  top level
+       (t
+        (if (looking-at ada-named-block-re)
+            (set 'label (- ada-label-indent))
+
+          ;;  "with private" or "null record" cases
+          (if (or (and (re-search-forward "\\<private\\>" orgpoint t)
+                       (save-excursion (forward-char -7);; skip back "private"
+                                       (ada-goto-previous-word)
+                                       (looking-at "with")))
+		  (and (re-search-forward "\\<record\\>" orgpoint t)
+		       (save-excursion (forward-char -6);; skip back "record"
+				       (ada-goto-previous-word)
+				       (looking-at "null"))))
+              (progn
+                (re-search-backward "\\<\\(type\\|subtype\\)\\>" nil t)
+		(list (save-excursion (back-to-indentation) (point)) 0))))
+        (if (save-excursion
+              (ada-search-ignore-string-comment ";" nil orgpoint nil 'search-forward))
+	    (list (+ (save-excursion (back-to-indentation) (point)) label) 0)
+	  (list (+ (save-excursion (back-to-indentation) (point)) label)
+		'ada-broken-indent)))))))
 
 (defun ada-get-indent-label (orgpoint)
   ;; Returns the indentation (column #) for the new line after ORGPOINT.
@@ -2340,76 +2649,62 @@
   ;; Checks the context to decide if it's a label or a variable declaration.
   ;; This check might be a bit slow.
   (let ((match-cons nil)
-        (cur-indent (current-indentation)))
-    (goto-char (cdr (ada-search-ignore-string-comment ":")))
+        (cur-indent (save-excursion (back-to-indentation) (point))))
+    (ada-search-ignore-string-comment ":" nil)
     (cond
-     ;;
      ;; loop label
-     ;;
      ((save-excursion
-        (setq match-cons (ada-search-ignore-string-comment
-                          ada-loop-start-re nil orgpoint)))
+        (set 'match-cons (ada-search-ignore-string-comment ada-loop-start-re nil orgpoint)))
       (goto-char (car match-cons))
       (ada-get-indent-loop orgpoint))
-     ;;
+
      ;; declare label
-     ;;
-     ((save-excursion
-        (setq match-cons (ada-search-ignore-string-comment
-                          "\\<declare\\|begin\\>" nil orgpoint)))
-      (save-excursion
-        (goto-char (car match-cons))
-        (+ (current-indentation) ada-indent)))
-     ;;
-     ;; complete statement following colon
-     ;;
      ((save-excursion
-        (ada-search-ignore-string-comment ";" nil orgpoint))
-      (if (ada-in-decl-p)
-          cur-indent                      ; variable-declaration
-        (- cur-indent ada-label-indent))) ; label
-     ;;
-     ;; broken statement
-     ;;
-     ((save-excursion
-        (ada-search-ignore-string-comment "[^ \t\n]" nil orgpoint))
-      (if (ada-in-decl-p)
-          (+ cur-indent ada-broken-indent)
-        (+ cur-indent ada-broken-indent (- ada-label-indent))))
-     ;;
+        (set 'match-cons (ada-search-ignore-string-comment "\\<declare\\|begin\\>" nil orgpoint)))
+      (goto-char (car match-cons))
+      (list (save-excursion (back-to-indentation) (point)) 'ada-indent))
+
+     ;; variable declaration
+     ((ada-in-decl-p)
+      (if (save-excursion
+            (ada-search-ignore-string-comment ";" nil orgpoint))
+          (list cur-indent 0)
+	(list cur-indent 'ada-broken-indent)))
+
      ;; nothing follows colon
-     ;;
      (t
-      (if (ada-in-decl-p)
-          (+ cur-indent ada-broken-indent)   ; variable-declaration
-        (- cur-indent ada-label-indent)))))) ; label
-
+      (list cur-indent '(- ada-label-indent))))))
 
 (defun ada-get-indent-loop (orgpoint)
-  ;; Returns the indentation (column #) for the new line after ORGPOINT.
-  ;; Assumes point to be at the beginning of a loop statement
-  ;; or (unfortunately) also a for ... use statement.
+  "Returns the two-element list for indentation.
+Assumes point to be at the beginning of a loop statement
+or a for ... use statement."
   (let ((match-cons nil)
         (pos (point))
+
+	;; If looking at a named block, skip the label
         (label (save-excursion
                  (beginning-of-line)
                  (if (looking-at ada-named-block-re)
                      (- ada-label-indent)
                    0))))
-          
+
     (cond
 
      ;;
      ;; statement complete
      ;;
      ((save-excursion
-        (ada-search-ignore-string-comment ";" nil orgpoint))
-      (+ (current-indentation) label))
+        (ada-search-ignore-string-comment ";" nil orgpoint nil 'search-forward))
+      (list (+ (save-excursion (back-to-indentation) (point)) label) 0))
      ;;
      ;; simple loop
      ;;
      ((looking-at "loop\\>")
-      (+ (ada-get-indent-block-start orgpoint) label))
+      (set 'pos (ada-get-indent-block-start orgpoint))
+      (if (equal label 0)
+	  pos
+	(list (+ (car pos) label) (cdr pos))))
 
      ;;
      ;; 'for'- loop (or also a for ... use statement)
@@ -2422,43 +2717,42 @@
        ((save-excursion
           (and
            (goto-char (match-end 0))
-           (ada-search-ignore-string-comment "[^ /n/t]" nil orgpoint)
-           (not (backward-char 1))
-           (not (zerop (skip-chars-forward "_a-zA-Z0-9'")))
-           (ada-search-ignore-string-comment "[^ /n/t]" nil orgpoint)
-           (not (backward-char 1))
+           (ada-goto-next-non-ws orgpoint)
+           (forward-word 1)
+           (if (= (char-after) ?') (forward-word 1) t)
+           (ada-goto-next-non-ws orgpoint)
            (looking-at "\\<use\\>")
            ;;
            ;; check if there is a 'record' before point
            ;;
            (progn
-             (setq match-cons (ada-search-ignore-string-comment
-                               "\\<record\\>" nil orgpoint))
+             (set 'match-cons (ada-search-ignore-string-comment
+                               "record" nil orgpoint nil 'word-search-forward))
              t)))
         (if match-cons
             (goto-char (car match-cons)))
-        (+ (current-indentation) ada-indent))
+	(list (save-excursion (back-to-indentation) (point)) 'ada-indent))
        ;;
        ;; for..loop
        ;;
        ((save-excursion
-          (setq match-cons (ada-search-ignore-string-comment
-                            "\\<loop\\>" nil orgpoint)))
+          (set 'match-cons (ada-search-ignore-string-comment
+                            "loop" nil orgpoint nil 'word-search-forward)))
         (goto-char (car match-cons))
         ;;
         ;; indent according to 'loop', if it's first in the line;
         ;; otherwise to 'for'
         ;;
-        (if (not (save-excursion
-                   (back-to-indentation)
-                   (looking-at "\\<loop\\>")))
-            (goto-char pos))
-        (+ (current-indentation) ada-indent label))
+        (unless (save-excursion
+                  (back-to-indentation)
+                  (looking-at "\\<loop\\>"))
+          (goto-char pos))
+	(list (+ (save-excursion (back-to-indentation) (point)) label) 'ada-indent))
        ;;
        ;; for-statement is broken
        ;;
        (t
-        (+ (current-indentation) ada-broken-indent label))))
+	(list (+ (save-excursion (back-to-indentation) (point)) label) 'ada-broken-indent))))
 
      ;;
      ;; 'while'-loop
@@ -2468,8 +2762,8 @@
       ;; while..loop ?
       ;;
       (if (save-excursion
-            (setq match-cons (ada-search-ignore-string-comment
-                              "\\<loop\\>" nil orgpoint)))
+            (set 'match-cons (ada-search-ignore-string-comment
+                              "loop" nil orgpoint nil 'word-search-forward)))
 
           (progn
             (goto-char (car match-cons))
@@ -2477,13 +2771,14 @@
             ;; indent according to 'loop', if it's first in the line;
             ;; otherwise to 'while'.
             ;;
-            (if (not (save-excursion
-                       (back-to-indentation)
-                       (looking-at "\\<loop\\>")))
-                (goto-char pos))
-            (+ (current-indentation) ada-indent label))
-
-        (+ (current-indentation) ada-broken-indent label))))))
+            (unless (save-excursion
+                      (back-to-indentation)
+                      (looking-at "\\<loop\\>"))
+              (goto-char pos))
+	    (list (+ (save-excursion (back-to-indentation) (point)) label) 'ada-indent))
+
+	(list (+ (save-excursion (back-to-indentation) (point)) label)
+	      'ada-broken-indent))))))
 
 
 (defun ada-get-indent-type (orgpoint)
@@ -2496,44 +2791,42 @@
      ;;
      ((save-excursion
         (and
-         (setq match-dat (ada-search-ignore-string-comment "\\<end\\>"
-                                                           nil
-                                                           orgpoint))
+         (set 'match-dat (ada-search-ignore-string-comment
+                          "end" nil orgpoint nil 'word-search-forward))
          (ada-goto-next-non-ws)
          (looking-at "\\<record\\>")
          (forward-word 1)
          (ada-goto-next-non-ws)
-         (looking-at ";")))
+         (= (char-after) ?\;)))
       (goto-char (car match-dat))
-      (current-indentation))
+      (list (save-excursion (back-to-indentation) (point)) 0))
      ;;
      ;; record type
      ;;
      ((save-excursion
-        (setq match-dat (ada-search-ignore-string-comment "\\<record\\>"
-                                                          nil
-                                                          orgpoint)))
+        (set 'match-dat (ada-search-ignore-string-comment
+                         "record" nil orgpoint nil 'word-search-forward)))
       (goto-char (car match-dat))
-      (+ (current-indentation) ada-indent))
+      (list (save-excursion (back-to-indentation) (point)) 'ada-indent))
      ;;
      ;; complete type declaration
      ;;
      ((save-excursion
-        (ada-search-ignore-string-comment ";" nil orgpoint))
-      (current-indentation))
+        (ada-search-ignore-string-comment ";" nil orgpoint nil 'search-forward))
+      (list (save-excursion (back-to-indentation) (point)) 0))
      ;;
      ;; "type ... is", but not "type ... is ...", which is broken
      ;;
      ((save-excursion
-	(and
-	 (ada-search-ignore-string-comment "\\<is\\>" nil orgpoint)
-	 (not (ada-search-ignore-string-comment "[^ \t\n]" nil orgpoint))))
-      (+ (current-indentation) ada-indent))
+        (and
+         (ada-search-ignore-string-comment "is" nil orgpoint nil 'word-search-forward)
+         (not (ada-goto-next-non-ws orgpoint))))
+      (list (save-excursion (back-to-indentation) (point)) 'ada-broken-indent))
      ;;
      ;; broken statement
      ;;
      (t
-      (+ (current-indentation) ada-broken-indent)))))
+      (list (save-excursion (back-to-indentation) (point)) 'ada-broken-indent)))))
 
 
 ;;; ---- support-functions for indentation
@@ -2546,31 +2839,34 @@
   ;; by searching for 'ada-end-stmt-re' and then moving to the
   ;; following non-ws that is not a comment.  LIMIT is actually not
   ;; used by the indentation functions.
+  ;; As a special case, if we are looking back at a closing parenthesis,
+  ;; we just skip the parenthesis
   (let ((match-dat nil)
         (orgpoint (point)))
 
-    (setq match-dat (ada-search-prev-end-stmt limit))
+    (set 'match-dat (ada-search-prev-end-stmt limit))
     (if match-dat
+
         ;;
         ;; found a previous end-statement => check if anything follows
         ;;
-        (progn
-          (if (not
-               (save-excursion
-                 (goto-char (cdr match-dat))
-                 (ada-search-ignore-string-comment
-                  "[^ \t\n]" nil orgpoint)))
+        (unless (looking-at "declare")
+          (progn
+            (unless (save-excursion
+                      (goto-char (cdr match-dat))
+                      (ada-goto-next-non-ws orgpoint))
               ;;
               ;; nothing follows => it's the end-statement directly in
               ;;                    front of point => search again
               ;;
-              (setq match-dat (ada-search-prev-end-stmt limit)))
-          ;;
-          ;; if found the correct end-statement => goto next non-ws
-          ;;
-          (if match-dat
-              (goto-char (cdr match-dat)))
-          (ada-goto-next-non-ws))
+              (set 'match-dat (ada-search-prev-end-stmt limit)))
+            ;;
+            ;; if found the correct end-statement => goto next non-ws
+            ;;
+            (if match-dat
+                (goto-char (cdr match-dat)))
+            (ada-goto-next-non-ws)
+            ))
 
       ;;
       ;; no previous end-statement => we are at the beginning of the
@@ -2581,13 +2877,9 @@
         ;;
         ;; skip to the very first statement, if there is one
         ;;
-        (if (setq match-dat
-                  (ada-search-ignore-string-comment
-                   "[^ \t\n]" nil orgpoint))
-            (goto-char (car match-dat))
+        (unless (ada-goto-next-non-ws orgpoint)
           (goto-char orgpoint))))
 
-
     (point)))
 
 
@@ -2598,36 +2890,39 @@
   ;; certain keywords if they follow 'end', which means they are no
   ;; end-statement there.
   (let ((match-dat nil)
-        (pos nil)
-        (found nil))
+        (found nil)
+        parse)
+
     ;;
     ;; search until found or beginning-of-buffer
     ;;
     (while
         (and
          (not found)
-         (setq match-dat (ada-search-ignore-string-comment ada-end-stmt-re
-                                                           t
-                                                           limit)))
+         (set 'match-dat (ada-search-ignore-string-comment
+                          ada-end-stmt-re t limit)))
 
       (goto-char (car match-dat))
-      (if (not (ada-in-open-paren-p))
-          ;;
-          ;; check if there is an 'end' in front of the match
-          ;;
-          (if (not (and
-                    (looking-at 
-                     "\\<\\(record\\|loop\\|select\\|else\\|then\\)\\>")
-                    (save-excursion
-                      (ada-goto-previous-word)
-                      (looking-at "\\<\\(end\\|or\\|and\\)\\>"))))
-              (save-excursion
-                (goto-char (cdr match-dat))
-                (ada-goto-next-word)
-                (if (not (looking-at "\\<\\(separate\\|new\\)\\>"))
-                    (setq found t)))
-            
-            (forward-word -1)))) ; end of loop
+      (unless (ada-in-open-paren-p)
+        (if (and (looking-at
+                  "\\<\\(record\\|loop\\|select\\|else\\|then\\)\\>")
+                 (save-excursion
+                   (ada-goto-previous-word)
+                   (looking-at "\\<\\(end\\|or\\|and\\)\\>[ \t]*[^;]")))
+            (forward-word -1)
+
+          (save-excursion
+            (goto-char (cdr match-dat))
+            (ada-goto-next-non-ws)
+            (looking-at "(")
+            ;;  words that can go after an 'is'
+            (unless (looking-at
+                     (eval-when-compile
+                       (concat "\\<"
+                               (regexp-opt '("separate" "access" "array" "abstract" "new") t)
+                               "\\>\\|(")))
+              (set 'found t))))
+        ))
 
     (if found
         match-dat
@@ -2635,17 +2930,22 @@
 
 
 (defun ada-goto-next-non-ws (&optional limit)
-  ;; Skips whitespaces, newlines and comments to next non-ws
-  ;; character.  Signals an error if there is no more such character
-  ;; and limit is nil.
-  (let ((match-cons nil))
-    (setq match-cons (ada-search-ignore-string-comment
-                      "[^ \t\n]" nil limit t))
-    (if match-cons
-        (goto-char (car match-cons))
-      (if (not limit)
-          (error "no more non-ws")
-        nil))))
+  "Skips whitespaces, newlines and comments to next non-ws
+character.  Signals an error if there is no more such character
+and limit is nil.
+Do not call this function from within a string."
+  (unless limit
+    (set 'limit (point-max)))
+  (while (and (<= (point) limit)
+              (progn (forward-comment 10000)
+                     (if (and (not (eobp))
+                              (save-excursion (forward-char 1)
+                                              (ada-in-string-p)))
+                         (progn (forward-sexp 1) t)))))
+  (if (< (point) limit)
+      (point)
+    nil)
+  )
 
 
 (defun ada-goto-stmt-end (&optional limit)
@@ -2661,27 +2961,32 @@
   ;; If BACKWARD is non-nil, jump to the beginning of the previous word.
   ;; Returns the new position of point or nil if not found.
   (let ((match-cons nil)
-        (orgpoint (point)))
-    (if (not backward)
-        (skip-chars-forward "_a-zA-Z0-9\\."))
-    (if (setq match-cons
-              (ada-search-ignore-string-comment "\\w" backward nil t))
+        (orgpoint (point))
+        (old-syntax (char-to-string (char-syntax ?_))))
+    (modify-syntax-entry ?_ "w")
+    (unless backward
+      (skip-syntax-forward "w"));;  ??? Used to have . too
+    (if (set 'match-cons
+             (if backward
+                 (ada-search-ignore-string-comment "\\w" t nil t)
+               (ada-search-ignore-string-comment "\\w" nil nil t)))
         ;;
         ;; move to the beginning of the word found
         ;;
         (progn
           (goto-char (car match-cons))
-          (skip-chars-backward "_a-zA-Z0-9")
+          (skip-syntax-backward "w")
           (point))
       ;;
       ;; if not found, restore old position of point
       ;;
-      (progn
-        (goto-char orgpoint)
-        'nil))))
-
-
-(defun ada-goto-previous-word ()
+      (goto-char orgpoint)
+      'nil)
+    (modify-syntax-entry ?_ old-syntax))
+  )
+
+
+(defsubst ada-goto-previous-word ()
   ;; Moves point to the beginning of the previous word of Ada code.
   ;; Returns the new position of point or nil if not found.
   (ada-goto-next-word t))
@@ -2691,8 +2996,8 @@
   ;; Signals an error if matching block start is not KEYWORD.
   ;; Moves point to the matching block start.
   (ada-goto-matching-start 0)
-  (if (not (looking-at (concat "\\<" keyword "\\>")))
-      (error "matching start is not '%s'" keyword)))
+  (unless (looking-at (concat "\\<" keyword "\\>"))
+    (error "matching start is not '%s'" keyword)))
 
 
 (defun ada-check-defun-name (defun-name)
@@ -2706,12 +3011,12 @@
   (if (save-excursion
         (ada-goto-previous-word)
         (looking-at (concat "\\<" defun-name "\\> *:")))
-      t ; do nothing
+      t                                 ; do nothing
     ;;
     ;; 'accept' or 'package' ?
     ;;
-    (if (not (looking-at "\\<\\(accept\\|package\\|task\\|protected\\)\\>"))
-        (ada-goto-matching-decl-start))
+    (unless (looking-at "\\<\\(accept\\|package\\|task\\|protected\\)\\>")
+      (ada-goto-matching-decl-start))
     ;;
     ;; 'begin' of 'procedure'/'function'/'task' or 'declare'
     ;;
@@ -2737,28 +3042,33 @@
       ;;
       ;; should be looking-at the correct name
       ;;
-      (if (not (looking-at (concat "\\<" defun-name "\\>")))
-          (error "matching defun has different name: %s"
-                 (buffer-substring (point)
-                                   (progn (forward-sexp 1) (point))))))))
-
+      (unless (looking-at (concat "\\<" defun-name "\\>"))
+        (error "matching defun has different name: %s"
+               (buffer-substring (point)
+                                 (progn (forward-sexp 1) (point))))))))
 
 (defun ada-goto-matching-decl-start (&optional noerror nogeneric)
   ;; Moves point to the matching declaration start of the current 'begin'.
   ;; If NOERROR is non-nil, it only returns nil if no match was found.
   (let ((nest-count 1)
-        (pos nil)
         (first t)
-        (flag nil))
+        (flag nil)
+        (count-generic nil)
+        )
+
+    (if (or
+         (looking-at "\\<\\(package\\|procedure\\|function\\)\\>")
+         (save-excursion
+           (ada-search-ignore-string-comment "\\<\\(package\\|procedure\\|function\\|generic\\)\\>" t)
+           (looking-at "generic")))
+        (set 'count-generic t))
+
     ;;
     ;; search backward for interesting keywords
     ;;
     (while (and
             (not (zerop nest-count))
-            (ada-search-ignore-string-comment
-             (concat "\\<\\("
-                     "is\\|separate\\|end\\|declare\\|new\\|begin\\|generic"
-                     "\\)\\>") t))
+            (ada-search-ignore-string-comment ada-matching-decl-start-re t))
       ;;
       ;; calculate nest-depth
       ;;
@@ -2766,39 +3076,79 @@
        ;;
        ((looking-at "end")
         (ada-goto-matching-start 1 noerror)
-        (if (looking-at "begin")
-            (setq nest-count (1+ nest-count))))
+
+	;;  In some case, two begin..end block can follow each other closely,
+	;;  which we have to detect, as in
+	;;     procedure P is
+	;;        procedure Q is
+	;;        begin
+	;;        end;
+        ;;     begin    --  here we should go to procedure, not begin
+	;;     end
+
+	(let ((loop-again 0))
+	  (if (looking-at "begin")
+	      (set 'loop-again 1))
+
+	  (save-excursion
+	    (while (not (= loop-again 0))
+	      
+	      ;;  If begin was just there as the beginning of a block (with no
+	      ;;  declare) then do nothing, otherwise just register that we
+	      ;;  have to find the statement that required the begin
+	      
+	      (ada-search-ignore-string-comment
+	       "declare\\|begin\\|end\\|procedure\\|function\\|task\\|package"
+	       t)
+
+	      (if (looking-at "end")
+		  (set 'loop-again (1+ loop-again))
+
+		(set 'loop-again (1- loop-again))
+		(unless (looking-at "begin")
+		    (set 'nest-count (1+ nest-count))))
+	      ))
+	  ))
        ;;
-       ((looking-at "declare\\|generic")
-        (setq nest-count (1- nest-count))
-        (setq first nil))
+       ((looking-at "generic")
+        (if count-generic
+            (progn
+              (set 'first nil)
+              (set 'nest-count (1- nest-count)))))
+       ;;
+       ((looking-at "declare\\|generic\\|if")
+        (set 'nest-count (1- nest-count))
+        (set 'first nil))
        ;;
        ((looking-at "is")
         ;; check if it is only a type definition, but not a protected
         ;; type definition, which should be handled like a procedure.
-        (if (or (looking-at "is +<>")
+        (if (or (looking-at "is[ \t]+<>")
                 (save-excursion
-                  (ada-goto-previous-word)
-                  (skip-chars-backward "a-zA-Z0-9_.'")
-                  (if (save-excursion
-                        (backward-char 1)
-                        (looking-at ")"))
+                  (forward-comment -10000)
+                  (forward-char -1)
+
+                  ;; Detect if we have a closing parenthesis (Could be
+                  ;; either the end of subprogram parameters or (<>)
+                  ;; in a type definition
+                  (if (= (char-after) ?\))
                       (progn
                         (forward-char 1)
                         (backward-sexp 1)
-                        (skip-chars-backward "a-zA-Z0-9_.'")
+                        (forward-comment -10000)
                         ))
+                  (skip-chars-backward "a-zA-Z0-9_.'")
                   (ada-goto-previous-word)
-                  (and 
-                   (looking-at "\\<type\\>")
+                  (and
+                   (looking-at "\\<\\(sub\\)?type\\>")
                    (save-match-data
                      (ada-goto-previous-word)
                      (not (looking-at "\\<protected\\>"))))
-                  )); end of `or'
+                  ))                    ; end of `or'
             (goto-char (match-beginning 0))
           (progn
-            (setq nest-count (1- nest-count))
-            (setq first nil))))
+            (set 'nest-count (1- nest-count))
+            (set 'first nil))))
 
        ;;
        ((looking-at "new")
@@ -2809,27 +3159,26 @@
        ;;
        ((and first
              (looking-at "begin"))
-        (setq nest-count 0)
-        (setq flag t))
+        (set 'nest-count 0)
+        (set 'flag t))
        ;;
        (t
-        (setq nest-count (1+ nest-count))
-        (setq first nil)))
-
-      )  ;; end of loop
+        (set 'nest-count (1+ nest-count))
+        (set 'first nil)))
+
+      );; end of loop
 
     ;; check if declaration-start is really found
-    (if (not
-         (and
-          (zerop nest-count)
-          (not flag)
-          (if (looking-at "is")
-              (ada-search-ignore-string-comment ada-subprog-start-re t)
-            (looking-at "declare\\|generic"))))
-        (if noerror nil
-          (error "no matching proc/func/task/declare/package/protected"))
-      t)))
-
+    (if (and
+         (zerop nest-count)
+         (not flag)
+         (if (looking-at "is")
+             (ada-search-ignore-string-comment ada-subprog-start-re t)
+           (looking-at "declare\\|generic")))
+        t
+      (if noerror nil
+        (error "no matching proc/func/task/declare/package/protected")))
+    ))
 
 (defun ada-goto-matching-start (&optional nest-level noerror gotothen)
   ;; Moves point to the beginning of a block-start.  Which block
@@ -2846,59 +3195,97 @@
     ;;
     (while (and
             (not found)
-            (ada-search-ignore-string-comment
-             (concat "\\<\\("
-                     "end\\|loop\\|select\\|begin\\|case\\|do\\|"
-                     "if\\|task\\|package\\|record\\|protected\\)\\>")
-             t))
-
-      ;;
-      ;; calculate nest-depth
-      ;;
-      (cond
-       ;; found block end => increase nest depth
-       ((looking-at "end")
-        (setq nest-count (1+ nest-count)))
-       ;; found loop/select/record/case/if => check if it starts or
-       ;; ends a block
-       ((looking-at "loop\\|select\\|record\\|case\\|if")
-        (setq pos (point))
-        (save-excursion
+            (ada-search-ignore-string-comment ada-matching-start-re t))
+
+      (unless (and (looking-at "\\<record\\>")
+                   (save-excursion
+                     (forward-word -1)
+                     (looking-at "\\<null\\>")))
+        (progn
           ;;
-          ;; check if keyword follows 'end'
+          ;; calculate nest-depth
           ;;
-          (ada-goto-previous-word)
-          (if (looking-at "\\<end\\> *[^;]")
-              ;; it ends a block => increase nest depth
-              (progn
-                (setq nest-count (1+ nest-count))
-                (setq pos (point)))
-            ;; it starts a block => decrease nest depth
-            (setq nest-count (1- nest-count))))
-        (goto-char pos))
-       ;; found package start => check if it really is a block
-       ((looking-at "package")
-        (save-excursion
-          (ada-search-ignore-string-comment "\\<is\\>")
-          (ada-goto-next-non-ws)
-          ;; ignore it if it is only a declaration with 'new'
-          (if (not (looking-at "\\<new\\>"))
-              (setq nest-count (1- nest-count)))))
-       ;; found task start => check if it has a body
-       ((looking-at "task")
-        (save-excursion
-          (forward-word 1)
-          (ada-goto-next-non-ws)
-          ;; ignore it if it has no body
-          (if (not (looking-at "\\<body\\>"))
-              (setq nest-count (1- nest-count)))))
-       ;; all the other block starts
-       (t
-        (setq nest-count (1- nest-count)))) ; end of 'cond'
-
-      ;; match is found, if nest-depth is zero
-      ;;
-      (setq found (zerop nest-count))) ; end of loop
+          (cond
+           ;; found block end => increase nest depth
+           ((looking-at "end")
+            (set 'nest-count (1+ nest-count)))
+
+           ;; found loop/select/record/case/if => check if it starts or
+           ;; ends a block
+           ((looking-at "loop\\|select\\|record\\|case\\|if")
+            (set 'pos (point))
+            (save-excursion
+              ;;
+              ;; check if keyword follows 'end'
+              ;;
+              (ada-goto-previous-word)
+              (if (looking-at "\\<end\\>[ \t]*[^;]")
+                  ;; it ends a block => increase nest depth
+                  (progn
+                    (set 'nest-count (1+ nest-count))
+                    (set 'pos (point)))
+                ;; it starts a block => decrease nest depth
+                (set 'nest-count (1- nest-count))))
+            (goto-char pos))
+
+           ;; found package start => check if it really is a block
+           ((looking-at "package")
+            (save-excursion
+              ;; ignore if this is just a renames statement
+              (let ((current (point))
+                    (pos (ada-search-ignore-string-comment
+                          "\\<\\(is\\|renames\\|;\\)\\>" nil)))
+                (if pos
+                    (goto-char (car pos))
+                  (error (concat
+                          "No matching 'is' or 'renames' for 'package' at line "
+                          (number-to-string (count-lines (point-min) (1+ current)))))))
+              (unless (looking-at "renames")
+                (progn
+                  (forward-word 1)
+                  (ada-goto-next-non-ws)
+                  ;; ignore it if it is only a declaration with 'new'
+                  (if (not (looking-at "\\<\\(new\\|separate\\)\\>"))
+                      (set 'nest-count (1- nest-count)))))))
+           ;; found task start => check if it has a body
+           ((looking-at "task")
+            (save-excursion
+              (forward-word 1)
+              (ada-goto-next-non-ws)
+              (cond
+               ((looking-at "\\<body\\>"))
+               ((looking-at "\\<type\\>")
+                ;;  In that case, do nothing if there is a "is"
+                (forward-word 2);; skip "type"
+                (ada-goto-next-non-ws);; skip type name
+
+		;; Do nothing if we are simply looking at a simple
+		;; "task type name;" statement with no block
+		(unless (looking-at ";")
+		  (progn
+		    ;; Skip the parameters
+		    (if (looking-at "(")
+			(ada-search-ignore-string-comment ")" nil))
+		    (let ((tmp (ada-search-ignore-string-comment
+				"\\<\\(is\\|;\\)\\>" nil)))
+		      (if tmp
+			  (progn
+			    (goto-char (car tmp))
+			    (if (looking-at "is")
+				(set 'nest-count (1- nest-count)))))))))
+               (t
+		;; Check if that task declaration had a block attached to
+		;; it (i.e do nothing if we have just "task name;")
+		(unless (progn (forward-word 1)
+			       (looking-at "[ \t]*;"))
+		  (set 'nest-count (1- nest-count)))))))
+           ;; all the other block starts
+           (t
+            (set 'nest-count (1- nest-count)))) ; end of 'cond'
+
+          ;; match is found, if nest-depth is zero
+          ;;
+          (set 'found (zerop nest-count))))) ; end of loop
 
     (if found
         ;;
@@ -2914,7 +3301,7 @@
              gotothen
              (looking-at "if")
              (save-excursion
-               (ada-search-ignore-string-comment "\\<then\\>" nil nil)
+               (ada-search-ignore-string-comment "then" nil nil nil 'word-search-forward)
                (back-to-indentation)
                (looking-at "\\<then\\>")))
             (goto-char (match-beginning 0)))
@@ -2922,8 +3309,8 @@
            ;; found 'do' => skip back to 'accept'
            ;;
            ((looking-at "do")
-            (if (not (ada-search-ignore-string-comment "\\<accept\\>" t nil))
-                (error "missing 'accept' in front of 'do'"))))
+            (unless (ada-search-ignore-string-comment "accept" t nil nil 'word-search-backward)
+              (error "missing 'accept' in front of 'do'"))))
           (point))
 
       (if noerror
@@ -2944,8 +3331,11 @@
     (while (and
             (not found)
             (ada-search-ignore-string-comment
-             (concat "\\<\\(end\\|loop\\|select\\|begin\\|case\\|"
-                     "if\\|task\\|package\\|record\\|do\\)\\>")))
+             (eval-when-compile
+               (concat "\\<"
+                       (regexp-opt '("end" "loop" "select" "begin" "case"
+                                     "if" "task" "package" "record" "do") t)
+                       "\\>")) nil))
 
       ;;
       ;; calculate nest-depth
@@ -2954,7 +3344,7 @@
       (cond
        ;; found block end => decrease nest depth
        ((looking-at "\\<end\\>")
-        (setq nest-count (1- nest-count))
+        (set 'nest-count (1- nest-count))
         ;; skip the following keyword
         (if (progn
               (skip-chars-forward "end")
@@ -2963,264 +3353,116 @@
             (forward-word 1)))
        ;; found package start => check if it really starts a block
        ((looking-at "\\<package\\>")
-        (ada-search-ignore-string-comment "\\<is\\>")
+        (ada-search-ignore-string-comment "is" nil nil nil 'word-search-forward)
         (ada-goto-next-non-ws)
         ;; ignore and skip it if it is only a 'new' package
-        (if (not (looking-at "\\<new\\>"))
-            (setq nest-count (1+ nest-count))
-          (skip-chars-forward "new")))
+        (if (looking-at "\\<new\\>")
+            (goto-char (match-end 0))
+          (set 'nest-count (1+ nest-count))))
        ;; all the other block starts
        (t
-        (setq nest-count (1+ nest-count))
-        (forward-word 1))) ; end of 'cond'
+        (set 'nest-count (1+ nest-count))
+        (forward-word 1)))              ; end of 'cond'
 
       ;; match is found, if nest-depth is zero
       ;;
-      (setq found (zerop nest-count))) ; end of loop
-
-    (if (not found)
-        (if noerror
-            nil
-          (error "no matching end"))
-      t)))
-
-
-(defun ada-forward-sexp-ignore-comment ()
-  ;; Skips one sexp forward, ignoring comments.
-  (while (looking-at "[ \t\n]*--")
-    (skip-chars-forward "[ \t\n]")
-    (end-of-line))
-  (forward-sexp 1))
+      (set 'found (zerop nest-count)))  ; end of loop
+
+    (if found
+        t
+      (if noerror
+          nil
+        (error "no matching end")))
+    ))
 
 
 (defun ada-search-ignore-string-comment
-  (search-re &optional backward limit paramlists)
+  (search-re &optional backward limit paramlists search-func )
   ;; Regexp-Search for SEARCH-RE, ignoring comments, strings and
   ;; parameter lists, if PARAMLISTS is nil. Returns a cons cell of
   ;; begin and end of match data or nil, if not found.
-  (let ((found nil)
-        (begin nil)
-        (end nil)
-        (pos nil)
-        (search-func
-         (if backward 're-search-backward
-           're-search-forward)))
+  ;; The search is done using search-func, so that we can choose using
+  ;; regular expression search, basic search, ...
+  ;; Point is moved at the beginning of the search-re
+  (let (found
+        begin
+        end
+        parse-result
+        (previous-syntax-table (syntax-table)))
+
+    (unless search-func
+      (set 'search-func (if backward 're-search-backward 're-search-forward)))
 
     ;;
     ;; search until found or end-of-buffer
+    ;; We have to test that we do not look further than limit
     ;;
+    (set-syntax-table ada-mode-symbol-syntax-table)
     (while (and (not found)
+                (or (not limit)
+                    (or (and backward (<= limit (point)))
+                        (>= limit (point))))
                 (funcall search-func search-re limit 1))
-      (setq begin (match-beginning 0))
-      (setq end (match-end 0))
+      (set 'begin (match-beginning 0))
+      (set 'end (match-end 0))
+
+      (set 'parse-result (parse-partial-sexp
+                          (save-excursion (beginning-of-line) (point))
+                          (point)))
 
       (cond
        ;;
-       ;; found in comment => skip it
+       ;; If inside a string, skip it (and the following comments)
        ;;
-       ((ada-in-comment-p)
-        (if backward
-            (progn
-              (re-search-backward "--" nil 1)
-              (goto-char (match-beginning 0)))
-	  (forward-line 1)
-	  ;; Used to have (beginning-of-line) here,
-	  ;; but that caused trouble at end of buffer with no newline.
-	  ))
+       ((ada-in-string-p parse-result)
+        (if ada-xemacs
+            (search-backward "\"" nil t)
+          (goto-char (nth 8 parse-result)))
+        (unless backward (forward-sexp 1)))
        ;;
-       ;; found in string => skip it
+       ;; If inside a comment, skip it (and the following comments)
+       ;; There is a special code for comments at the end of the file
        ;;
-       ((ada-in-string-p)
-        (if backward
-            (progn
-              (re-search-backward "\"" nil 1) ; "\"\\|#" don't treat #
-              (goto-char (match-beginning 0))))
-        (re-search-forward "\"" nil 1))
+       ((ada-in-comment-p parse-result)
+        (if ada-xemacs
+	    (progn
+	      (forward-line 1)
+	      (beginning-of-line)
+	      (forward-comment -1))
+          (goto-char (nth 8 parse-result)))
+        (unless backward
+          ;;  at the end of the file, it is not possible to skip a comment
+          ;;  so we just go at the end of the line
+          (if (forward-comment 1)
+              (progn
+                (forward-comment 1000)
+                (beginning-of-line))
+            (end-of-line))))
        ;;
-       ;; found character constant => ignore it
+       ;; directly in front of a comment => skip it, if searching forward
        ;;
-       ((save-excursion
-          (setq pos (- (point) (if backward 1 2)))
-          (and (char-after pos)
-               (= (char-after pos) ?')
-               (= (char-after (+ pos 2)) ?')))
-        ())
+       ((and (= (char-after begin) ?-) (= (char-after (1+ begin)) ?-))
+        (unless backward (progn (forward-char -1) (forward-comment 1000))))
+
        ;;
        ;; found a parameter-list but should ignore it => skip it
        ;;
-       ((and (not paramlists)
-             (ada-in-paramlist-p))
+       ((and (not paramlists) (ada-in-paramlist-p))
         (if backward
-            (ada-search-ignore-string-comment "(" t nil t)))
-       ;;
-       ;; directly in front of a comment => skip it, if searching forward
-       ;;
-       ((save-excursion
-          (goto-char begin)
-          (looking-at "--"))
-        (if (not backward)
-            (progn
-              (forward-line 1)
-              (beginning-of-line))))
+            (search-backward "(" nil t)
+          (search-forward ")" nil t)))
        ;;
        ;; found what we were looking for
        ;;
        (t
-        (setq found t)))) ; end of loop
+        (set 'found t))))               ; end of loop
+
+    (set-syntax-table previous-syntax-table)
 
     (if found
         (cons begin end)
       nil)))
 
-
-(defun ada-search-but-not (search-re not-search-re &optional backward limit)
-  ;; Searches SEARCH-RE, ignoring parts of NOT-SEARCH-RE, strings,
-  ;; comments and parameter-lists.
-  (let ((begin nil)
-        (end nil)
-        (begin-not nil)
-        (begin-end nil)
-        (end-not nil)
-        (ret-cons nil)
-        (found nil))
-
-    ;;
-    ;; search until found or end-of-buffer
-    ;;
-    (while (and
-            (not found)
-            (save-excursion
-              (setq ret-cons
-                    (ada-search-ignore-string-comment search-re
-                                                      backward limit))
-              (if (consp ret-cons)
-                  (progn
-                    (setq begin (car ret-cons))
-                    (setq end (cdr ret-cons))
-                    t)
-                nil)))
-
-      (if (or
-           ;;
-           ;; if no NO-SEARCH-RE was found
-           ;;
-           (not
-            (save-excursion
-              (setq ret-cons
-                    (ada-search-ignore-string-comment not-search-re
-                                                      backward nil))
-              (if (consp ret-cons)
-                  (progn
-                    (setq begin-not (car ret-cons))
-                    (setq end-not (cdr ret-cons))
-                    t)
-                nil)))
-           ;;
-           ;;  or this NO-SEARCH-RE is not a part of the SEARCH-RE
-           ;;  found before.
-           ;;
-           (or
-            (<= end-not begin)
-            (>= begin-not end)))
-
-          (setq found t)
-
-        ;;
-        ;; not found the correct match => skip this match
-        ;;
-        (goto-char (if backward
-                       begin
-                     end)))) ; end of loop
-
-    (if found
-        (progn
-          (goto-char begin)
-          (cons begin end))
-      nil)))
-
-
-(defun ada-goto-prev-nonblank-line ( &optional ignore-comment)
-  ;; Moves point to the beginning of previous non-blank line,
-  ;; ignoring comments if IGNORE-COMMENT is non-nil.
-  ;; It returns t if a matching line was found.
-  (let ((notfound t)
-        (newpoint nil))
-
-    (save-excursion
-      ;;
-      ;; backward one line, if there is one
-      ;;
-      (if (zerop (forward-line -1))
-          ;;
-          ;; there is some kind of previous line
-          ;;
-          (progn
-            (beginning-of-line)
-            (setq newpoint (point))
-
-            ;;
-            ;; search until found or beginning-of-buffer
-            ;;
-            (while (and (setq notfound
-                              (or (looking-at "[ \t]*$")
-                                  (and (looking-at "[ \t]*--")
-                                       ignore-comment)))
-                        (not (ada-in-limit-line-p)))
-              (forward-line -1)
-              ;;(beginning-of-line)
-              (setq newpoint (point))) ; end of loop
-
-            )) ; end of if
-
-      ) ; end of save-excursion
-
-    (if notfound nil
-      (progn
-        (goto-char newpoint)
-        t))))
-
-
-(defun ada-goto-next-nonblank-line ( &optional ignore-comment)
-  ;; Moves point to next non-blank line,
-  ;; ignoring comments if IGNORE-COMMENT is non-nil.
-  ;; It returns t if a matching line was found.
-  (let ((notfound t)
-        (newpoint nil))
-
-    (save-excursion
-    ;;
-    ;; forward one line
-    ;;
-      (if (zerop (forward-line 1))
-          ;;
-          ;; there is some kind of previous line
-          ;;
-          (progn
-            (beginning-of-line)
-            (setq newpoint (point))
-
-            ;;
-            ;; search until found or end-of-buffer
-            ;;
-            (while (and (setq notfound
-                              (or (looking-at "[ \t]*$")
-                                  (and (looking-at "[ \t]*--")
-                                       ignore-comment)))
-                        (not (ada-in-limit-line-p)))
-              (forward-line 1)
-              (beginning-of-line)
-              (setq newpoint (point))) ; end of loop
-
-            )) ; end of if
-
-      ) ; end of save-excursion
-
-    (if notfound nil
-      (progn
-        (goto-char newpoint)
-        t))))
-
-
 ;; ---- boolean functions for indentation
 
 (defun ada-in-decl-p ()
@@ -3243,60 +3485,34 @@
 
 
 (defun ada-looking-at-semi-private ()
-  ;; Returns t if looking-at an 'private' following a semicolon.
+  "Returns t if looking-at an 'private' following a semicolon.
+Returns nil if the private is part of the package name, as in
+'private package A is...' (this can only happen at top level)"
   (save-excursion
     (and (looking-at "\\<private\\>")
-         (progn
-           (forward-word 1)
-           (ada-goto-stmt-start)
-           (looking-at "\\<private\\>")))))
-
-
-;;; make a faster??? ada-in-limit-line-p not using count-lines
-(defun ada-in-limit-line-p ()
-  ;; return t if point is in first or last accessible line.
-  (or (save-excursion (beginning-of-line) (= (point-min) (point)))
-      (save-excursion (end-of-line) (= (point-max) (point)))))
-
-
-(defun ada-in-comment-p ()
-  ;; Returns t if inside a comment.
-  (nth 4 (parse-partial-sexp
-          (save-excursion (beginning-of-line) (point))
-          (point))))
-
-
-(defun ada-in-string-p ()
-  ;; Returns t if point is inside a string
-  ;; (Taken from pascal-mode.el, modified by MH).
-  (save-excursion
-    (and
-     (nth 3 (parse-partial-sexp
-             (save-excursion
-               (beginning-of-line)
-               (point)) (point)))
-     ;; check if 'string quote' is only a character constant
-     (progn
-       (re-search-backward "\"" nil t) ; `#' is not taken as a string delimiter
-       (not (= (char-after (1- (point))) ?'))))))
-
-
-(defun ada-in-string-or-comment-p ()
-  ;; Returns t if point is inside a string, a comment, or a character constant.
-  (let ((parse-result (parse-partial-sexp
-                       (save-excursion (beginning-of-line) (point)) (point))))
-    (or ;; in-comment-p
-     (nth 4 parse-result)
-     ;; in-string-p
-     (and
-      (nth 3 parse-result)
-      ;; check if 'string quote' is only a character constant
-      (progn
-        (re-search-backward "\"" nil t) ; `#' not regarded a string delimiter
-        (not (= (char-after (1- (point))) ?'))))
-     ;; in-char-const-p
-     (ada-in-char-const-p))))
-
+         (not (looking-at "\\<private[ \t]*\\(package\\|generic\\)"))
+         (progn (forward-comment -1000)
+                (= (char-before) ?\;)))))
+
+(defsubst ada-in-comment-p (&optional parse-result)
+  "Returns t if inside a comment."
+  (nth 4 (or parse-result
+             (parse-partial-sexp
+              (save-excursion (beginning-of-line) (point)) (point)))))
+
+(defsubst ada-in-string-p (&optional parse-result)
+  "Returns t if point is inside a string.
+if parse-result is non-nil, use is instead of calling parse-partial-sexp"
+  (nth 3 (or parse-result
+             (parse-partial-sexp
+              (save-excursion (beginning-of-line) (point)) (point)))))
+
+(defsubst ada-in-string-or-comment-p (&optional parse-result)
+  "Returns t if inside a comment or string"
+  (set 'parse-result (or parse-result
+                         (parse-partial-sexp
+                          (save-excursion (beginning-of-line) (point)) (point))))
+  (or (ada-in-string-p parse-result) (ada-in-comment-p parse-result)))
 
 (defun ada-in-paramlist-p ()
   ;; Returns t if point is inside a parameter-list
@@ -3305,88 +3521,86 @@
     (and
      (re-search-backward "(\\|)" nil t)
      ;; inside parentheses ?
-     (looking-at "(")
+     (= (char-after) ?\()
      (backward-word 2)
-     ;; right keyword before parenthesis ?
-     (looking-at (concat "\\<\\("
-                         "procedure\\|function\\|body\\|package\\|"
-                         "task\\|entry\\|accept\\)\\>"))
-     (re-search-forward ")\\|:" nil t)
-     ;; at least one ':' inside the parentheses ?
-     (not (backward-char 1))
-     (looking-at ":"))))
-
+     
+     ;; We should ignore the case when the reserved keyword is in a
+     ;; comment (for instance, when we have:
+     ;;    -- .... package
+     ;;    Test (A)
+     ;; we should return nil
+
+     (not (ada-in-string-or-comment-p))
+     
+     ;; right keyword two words before parenthesis ?
+     ;; Type is in this list because of discriminants
+     (looking-at (eval-when-compile
+                   (concat "\\<\\("
+                           "procedure\\|function\\|body\\|"
+                           "task\\|entry\\|accept\\|"
+                           "access[ \t]+procedure\\|"
+                           "access[ \t]+function\\|"
+			   "pragma\\|"
+                           "type\\)\\>"))))))
 
 ;; not really a boolean function ...
 (defun ada-in-open-paren-p ()
-  ;; If point is somewhere behind an open parenthesis not yet closed,
-  ;; it returns the column # of the first non-ws behind this open
-  ;; parenthesis, otherwise nil."
-  (let ((start (if (<= (point) ada-search-paren-char-count-limit)
-                   (point-min)
-                 (save-excursion
-                   (goto-char (- (point) ada-search-paren-char-count-limit))
-                   (beginning-of-line)
-                   (point))))
-        parse-result
-        (col nil))
-    (setq parse-result (parse-partial-sexp start (point)))
-    (if (nth 1 parse-result)
-        (save-excursion
-          (goto-char (1+ (nth 1 parse-result)))
-          (if (save-excursion
-                (re-search-forward "[^ \t]" nil 1)
-                (backward-char 1)
-                (and
-                 (not (looking-at "\n"))
-                 (setq col (current-column))))
-              col
-            (current-column)))
-      nil)))
-
+  "If point is somewhere behind an open parenthesis not yet closed,
+it returns the position of the first non-ws behind that open parenthesis,
+otherwise nil"
+  (save-excursion
+    (let ((parse (parse-partial-sexp
+		  (point)
+		  (or (car (ada-search-ignore-string-comment "\\<\\(;\\|is\\|then\\|loop\\|begin\\|else\\)\\>" t))
+		      (point-min)))))
+      
+      (if (nth 1 parse)
+          (progn
+            (goto-char (1+ (nth 1 parse)))
+            (skip-chars-forward " \t")
+	    (point))))))
 
 
 ;;;----------------------;;;
 ;;; Behaviour Of TAB Key ;;;
 ;;;----------------------;;;
-
 (defun ada-tab ()
-  "Do indenting or tabbing according to `ada-tab-policy'."
+  "Do indenting or tabbing according to `ada-tab-policy'.
+
+In Transient Mark mode, if the mark is active, operate on the contents
+of the region.  Otherwise, operates only on the current line"
   (interactive)
-  (cond ((eq ada-tab-policy 'indent-and-tab) (error "not implemented"))
-        ;; ada-indent-and-tab
-        ((eq ada-tab-policy 'indent-rigidly) (ada-tab-hard))
-        ((eq ada-tab-policy 'indent-auto) (ada-indent-current))
-        ((eq ada-tab-policy 'gei) (ada-tab-gei))
-        ((eq ada-tab-policy 'indent-af) (af-indent-line)) ; GEB
+  (cond ((eq ada-tab-policy 'indent-rigidly) (ada-tab-hard))
+        ((eq ada-tab-policy 'indent-auto)
+         ;;  transient-mark-mode and mark-active are not defined in XEmacs
+         (if (or (and ada-xemacs (region-active-p))
+                 (and (not ada-xemacs)
+                      transient-mark-mode
+                      mark-active))
+             (ada-indent-region (region-beginning) (region-end))
+           (ada-indent-current)))
         ((eq ada-tab-policy 'always-tab) (error "not implemented"))
         ))
 
-
 (defun ada-untab (arg)
   "Delete leading indenting according to `ada-tab-policy'."
   (interactive "P")
   (cond ((eq ada-tab-policy 'indent-rigidly) (ada-untab-hard))
-        ((eq ada-tab-policy 'indent-af) (backward-delete-char-untabify ; GEB
-                                         (prefix-numeric-value arg) ; GEB
-                                         arg)) ; GEB
         ((eq ada-tab-policy 'indent-auto) (error "not implemented"))
         ((eq ada-tab-policy 'always-tab) (error "not implemented"))
         ))
 
-
 (defun ada-indent-current-function ()
   "Ada mode version of the indent-line-function."
   (interactive "*")
   (let ((starting-point (point-marker)))
-    (ada-beginning-of-line)
+    (beginning-of-line)
     (ada-tab)
     (if (< (point) starting-point)
         (goto-char starting-point))
     (set-marker starting-point nil)
     ))
 
-
 (defun ada-tab-hard ()
   "Indent current line to next tab stop."
   (interactive)
@@ -3396,12 +3610,11 @@
   (if (save-excursion (= (point) (progn (beginning-of-line) (point))))
       (forward-char ada-indent)))
 
-
 (defun ada-untab-hard ()
   "indent current line to previous tab stop."
   (interactive)
   (let  ((bol (save-excursion (progn (beginning-of-line) (point))))
-        (eol (save-excursion (progn (end-of-line) (point)))))
+         (eol (save-excursion (progn (end-of-line) (point)))))
     (indent-rigidly bol eol  (- 0 ada-indent))))
 
 
@@ -3411,7 +3624,7 @@
 ;;;---------------;;;
 
 (defun ada-remove-trailing-spaces  ()
- "remove trailing spaces in the whole buffer."
+  "remove trailing spaces in the whole buffer."
   (interactive)
   (save-match-data
     (save-excursion
@@ -3422,19 +3635,6 @@
           (replace-match "" nil nil))))))
 
 
-(defun ada-untabify-buffer ()
-;; change all tabs to spaces
-  (save-excursion
-    (untabify (point-min) (point-max))
-    nil))
-
-
-(defun ada-uncomment-region (beg end)
-  "delete `comment-start' at the beginning of a line in the region."
-  (interactive "r")
-  (comment-region beg end -1))
-
-
 ;; define a function to support find-file.el if loaded
 (defun ada-ff-other-window ()
   "Find other file in other window using `ff-find-other-file'."
@@ -3463,7 +3663,6 @@
 ;;;-------------------------------;;;
 ;;; Moving To Procedures/Packages ;;;
 ;;;-------------------------------;;;
-
 (defun ada-next-procedure ()
   "Moves point to next procedure."
   (interactive)
@@ -3498,208 +3697,296 @@
 
 
 ;;;-----------------------
-;;; define keymap for Ada
+;;; define keymap and menus for Ada
 ;;;-----------------------
 
-(if (not ada-mode-map)
-    (progn
-      (setq ada-mode-map (make-sparse-keymap))
-
-      ;; Indentation and Formatting
-      (define-key ada-mode-map "\C-j"     'ada-indent-newline-indent)
-      (define-key ada-mode-map "\t"       'ada-tab)
-      (define-key ada-mode-map "\C-c\C-l" 'ada-indent-region)
-      (if (ada-xemacs)
-	  (define-key ada-mode-map '(shift tab)    'ada-untab)
-	(define-key ada-mode-map [S-tab]    'ada-untab))
-      (define-key ada-mode-map "\C-c\C-f" 'ada-format-paramlist)
-      (define-key ada-mode-map "\C-c\C-p" 'ada-call-pretty-printer)
-;;; We don't want to make meta-characters case-specific.
-;;;   (define-key ada-mode-map "\M-Q"     'ada-fill-comment-paragraph-justify)
-      (define-key ada-mode-map "\M-\C-q"  'ada-fill-comment-paragraph-postfix)
-
-      ;; Movement
-;;; It isn't good to redefine these.  What should be done instead?  -- rms.
-;;;   (define-key ada-mode-map "\M-e"     'ada-next-package)
-;;;   (define-key ada-mode-map "\M-a"     'ada-previous-package)
-      (define-key ada-mode-map "\M-\C-e"  'ada-next-procedure)
-      (define-key ada-mode-map "\M-\C-a"  'ada-previous-procedure)
-      (define-key ada-mode-map "\C-c\C-a" 'ada-move-to-start)
-      (define-key ada-mode-map "\C-c\C-e" 'ada-move-to-end)
-
-      ;; Compilation
-      (define-key ada-mode-map "\C-c\C-c" 'compile)
-      (define-key ada-mode-map "\C-c\C-v" 'ada-check-syntax)
-      (define-key ada-mode-map "\C-c\C-m" 'ada-make-local)
-
-      ;; Casing
-      (define-key ada-mode-map "\C-c\C-r" 'ada-adjust-case-region)
-      (define-key ada-mode-map "\C-c\C-b" 'ada-adjust-case-buffer)
-
-      (define-key ada-mode-map "\177"     'backward-delete-char-untabify)
-
-      ;; Use predefined function of emacs19 for comments (RE)
-      (define-key ada-mode-map "\C-c;"    'comment-region)
-      (define-key ada-mode-map "\C-c:"    'ada-uncomment-region)
-
-      ;; Change basic functionality
-
-      ;; `substitute-key-definition' is not defined equally in Emacs
-      ;; and XEmacs, you cannot put in an optional 4th parameter in
-      ;; XEmacs.  I don't think it's necessary, so I leave it out for
-      ;; Emacs as well.  If you encounter any problems with the
-      ;; following three functions, please tell me. RE
-      (mapcar (function (lambda (pair)
-			  (substitute-key-definition (car pair) (cdr pair)
-						     ada-mode-map)))
-	      '((beginning-of-line      . ada-beginning-of-line)
-		(end-of-line            . ada-end-of-line)
-		(forward-to-indentation . ada-forward-to-indentation)
-		))
-      ;; else Emacs
-      ;;(mapcar (lambda (pair)
-      ;;             (substitute-key-definition (car pair) (cdr pair)
-      ;;				   ada-mode-map global-map))
-
-      ))
+(defun ada-create-keymap ()
+  "Create the keymap associated with the Ada mode"
+
+  ;; Indentation and Formatting
+  (define-key ada-mode-map "\C-j"     'ada-indent-newline-indent-conditional)
+  (define-key ada-mode-map "\C-m"     'ada-indent-newline-indent-conditional)
+  (define-key ada-mode-map "\t"       'ada-tab)
+  (define-key ada-mode-map "\C-c\t"   'ada-justified-indent-current)
+  (define-key ada-mode-map "\C-c\C-l" 'ada-indent-region)
+  (if ada-xemacs
+      (define-key ada-mode-map '(shift tab)    'ada-untab)
+    (define-key ada-mode-map [S-tab]    'ada-untab))
+  (define-key ada-mode-map "\C-c\C-f" 'ada-format-paramlist)
+  ;; We don't want to make meta-characters case-specific.
+
+  ;; Movement
+  (define-key ada-mode-map "\M-\C-e"  'ada-next-procedure)
+  (define-key ada-mode-map "\M-\C-a"  'ada-previous-procedure)
+  (define-key ada-mode-map "\C-c\C-a" 'ada-move-to-start)
+  (define-key ada-mode-map "\C-c\C-e" 'ada-move-to-end)
+
+  ;; Compilation
+  (unless (lookup-key ada-mode-map "\C-c\C-c")
+    (define-key ada-mode-map "\C-c\C-c" 'compile))
+
+  ;; Casing
+  (define-key ada-mode-map "\C-c\C-b" 'ada-adjust-case-buffer)
+  (define-key ada-mode-map "\C-c\C-t" 'ada-case-read-exceptions)
+  (define-key ada-mode-map "\C-c\C-y" 'ada-create-case-exception)
+
+  (define-key ada-mode-map "\177"     'backward-delete-char-untabify)
+
+  ;; Make body
+  (define-key ada-mode-map "\C-c\C-n" 'ada-make-subprogram-body)
+
+  ;; Use predefined function of emacs19 for comments (RE)
+  (define-key ada-mode-map "\C-c;"    'comment-region)
+  (define-key ada-mode-map "\C-c:"    'ada-uncomment-region)
+
+  )
+
+(defun ada-create-menu ()
+  "Create the ada menu as shown in the menu bar.
+This function is designed to be extensible, so that each compiler-specific file
+can add its own items"
+
+  ;;  Note that the separators must have different length in the submenus
+  (autoload 'easy-menu-define "easymenu")
+  (autoload 'imenu "imenu")
+  (easy-menu-define
+   ada-mode-menu ada-mode-map "Menu keymap for Ada mode"
+   '("Ada"
+     ("Help"
+      ["Ada Mode" (info "ada-mode") t])
+     ["Customize" (customize-group 'ada)  (>= emacs-major-version 20)]
+     ("Goto"
+      ["Next compilation error"  next-error t]
+      ["Previous Package" ada-previous-package t]
+      ["Next Package" ada-next-package t]
+      ["Previous Procedure" ada-previous-procedure t]
+      ["Next Procedure" ada-next-procedure t]
+      ["Goto Start Of Statement" ada-move-to-start t]
+      ["Goto End Of Statement" ada-move-to-end t]
+      ["-" nil nil]
+      ["Other File" ff-find-other-file t]
+      ["Other File Other Window" ada-ff-other-window t])
+     ("Edit"
+      ["Indent Line"  ada-indent-current-function t]
+      ["Justify Current Indentation" ada-justified-indent-current t]
+      ["Indent Lines in Selection" ada-indent-region t]
+      ["Indent Lines in File" (ada-indent-region (point-min) (point-max)) t]
+      ["Format Parameter List" ada-format-paramlist t]
+      ["-" nil nil]
+      ["Comment Selection" comment-region t]
+      ["Uncomment Selection" ada-uncomment-region t]
+      ["--" nil nil]
+      ["Fill Comment Paragraph" fill-paragraph t]
+      ["Fill Comment Paragraph Justify" ada-fill-comment-paragraph-justify t]
+      ["Fill Comment Paragraph Postfix" ada-fill-comment-paragraph-postfix t]
+      ["---" nil nil]
+      ["Adjust Case Selection"  ada-adjust-case-region t]
+      ["Adjust Case Buffer"     ada-adjust-case-buffer t]
+      ["Create Case Exception"  ada-create-case-exception t]
+      ["Reload Case Exceptions" ada-case-read-exceptions t]
+      ["----" nil nil]
+      ["Make body for subprogram" ada-make-subprogram-body t]
+      )
+     ["Index" imenu t]
+     ))
+
+  (if ada-xemacs
+      (progn
+        (easy-menu-add ada-mode-menu ada-mode-map)
+        (define-key ada-mode-map [menu-bar] ada-mode-menu)
+        (set 'mode-popup-menu (cons "Ada mode" ada-mode-menu))
+	)
+    )
+  )
 
 
-;;;-------------------
-;;; define menu 'Ada'
-;;;-------------------
-
-(require 'easymenu)
-
-(defun ada-add-ada-menu ()
-  "Adds the menu 'Ada' to the menu bar in Ada mode."
-  (easy-menu-define ada-mode-menu ada-mode-map "Menu keymap for Ada mode."
-                    '("Ada"
-                      ["Next Package" ada-next-package t]
-                      ["Previous Package" ada-previous-package t]
-                      ["Next Procedure" ada-next-procedure t]
-                      ["Previous Procedure" ada-previous-procedure t]
-                      ["Goto Start" ada-move-to-start t]
-                      ["Goto End" ada-move-to-end t]
-                      ["------------------" nil nil]
-                      ["Indent Current Line (TAB)"
-                       ada-indent-current-function t]
-                      ["Indent Lines in Region" ada-indent-region t]
-                      ["Format Parameter List" ada-format-paramlist t]
-                      ["Pretty Print Buffer" ada-call-pretty-printer t]
-                      ["------------" nil nil]
-                      ["Fill Comment Paragraph"
-                       ada-fill-comment-paragraph t]
-                      ["Justify Comment Paragraph"
-                       ada-fill-comment-paragraph-justify t]
-                      ["Postfix Comment Paragraph"
-                       ada-fill-comment-paragraph-postfix t]
-                      ["------------" nil nil]
-                      ["Adjust Case Region" ada-adjust-case-region t]
-                      ["Adjust Case Buffer" ada-adjust-case-buffer t]
-                      ["----------" nil nil]
-                      ["Comment   Region" comment-region t]
-                      ["Uncomment Region" ada-uncomment-region t]
-                      ["----------------" nil nil]
-                      ["Global Make" compile (fboundp 'compile)]
-                      ["Local Make" ada-make-local t]
-                      ["Check Syntax" ada-check-syntax t]
-                      ["Next Error" next-error (fboundp 'next-error)]
-                      ["---------------" nil nil]
-                      ["Index" imenu (fboundp 'imenu)]
-                      ["--------------" nil nil]
-                      ["Other File Other Window" ada-ff-other-window
-                       (fboundp 'ff-find-other-file)]
-                      ["Other File" ff-find-other-file
-                       (fboundp 'ff-find-other-file)]))
-  (if (ada-xemacs) (progn
-                     (easy-menu-add ada-mode-menu)
-                     (setq mode-popup-menu (cons "Ada mode" ada-mode-menu)))))
-
-
-
-;;;-------------------------------
-;;; Define Some Support Functions
-;;;-------------------------------
-
-(defun ada-beginning-of-line (&optional arg)
+
+
+;;
+;;  The two following calls are provided to enhance the standard
+;;  comment-region function, which only allows uncommenting if the
+;;  comment is at the beginning of a line. If the line have been reindented,
+;;  we are unable to use comment-region, which makes no sense.
+;;
+(defadvice comment-region (before ada-uncomment-anywhere)
+  (if (and arg
+           (< arg 0)
+           (string= mode-name "Ada"))
+      (save-excursion
+        (let ((cs (concat "^[ \t]*" (regexp-quote comment-start))))
+          (goto-char beg)
+          (while (re-search-forward cs end t)
+            (replace-match comment-start))
+          ))))
+
+;;
+;;  Handling of comments
+;;
+
+(defun ada-uncomment-region (beg end &optional arg)
+  "delete `comment-start' at the beginning of a line in the region."
+  (interactive "r\nP")
+  (ad-activate 'comment-region)
+  (comment-region beg end (- (or arg 1)))
+  (ad-deactivate 'comment-region))
+
+(defun ada-fill-comment-paragraph-justify ()
+  "Fills current comment paragraph and justifies each line as well."
+  (interactive)
+  (ada-fill-comment-paragraph 'full))
+
+(defun ada-fill-comment-paragraph-postfix ()
+  "Fills current comment paragraph and justifies each line as well.
+Adds `ada-fill-comment-postfix' at the end of each line"
+  (interactive)
+  (ada-fill-comment-paragraph 'full t))
+
+(defun ada-fill-comment-paragraph (&optional justify postfix)
+  "Fills the current comment paragraph.
+If JUSTIFY is non-nil, each line is justified as well.
+If POSTFIX and JUSTIFY are  non-nil, `ada-fill-comment-postfix' is appended
+to each filled and justified line.
+The paragraph is indented on the first line."
   (interactive "P")
-  (cond
-   ((eq ada-tab-policy 'indent-af) (af-beginning-of-line arg))
-   (t (beginning-of-line arg))
-   ))
-
-(defun ada-end-of-line (&optional arg)
-  (interactive "P")
-  (cond
-   ((eq ada-tab-policy 'indent-af) (af-end-of-line arg))
-   (t (end-of-line arg))
-   ))
-
-(defun ada-current-column ()
-  (cond
-   ((eq ada-tab-policy 'indent-af) (af-current-column))
-   (t (current-column))
-   ))
-
-(defun ada-forward-to-indentation (&optional arg)
-  (interactive "P")
-  (cond
-   ((eq ada-tab-policy 'indent-af) (af-forward-to-indentation arg))
-   (t (forward-to-indentation arg))
-   ))
+
+  ;; check if inside comment or just in front a comment
+  (if (and (not (ada-in-comment-p))
+           (not (looking-at "[ \t]*--")))
+      (error "not inside comment"))
+
+  (let* ((indent)
+         (from)
+         (to)
+         (opos             (point-marker))
+
+	 ;; Sets this variable to nil, otherwise it prevents
+	 ;; fill-region-as-paragraph to work on Emacs <= 20.2
+	 (parse-sexp-lookup-properties nil)
+	 
+         fill-prefix
+         (fill-column (current-fill-column)))
+
+    ;;  Find end of paragraph
+    (back-to-indentation)
+    (while (and (not (eobp)) (looking-at "--[ \t]*[^ \t\n]"))
+      (forward-line 1)
+      (back-to-indentation))
+    (beginning-of-line)
+    (set 'to (point-marker))
+    (goto-char opos)
+
+    ;;  Find beginning of paragraph
+    (back-to-indentation)
+    (while (and (not (bobp)) (looking-at "--[ \t]*[^ \t\n]"))
+      (forward-line -1)
+      (back-to-indentation))
+    (forward-line 1)
+    (beginning-of-line)
+    (set 'from (point-marker))
+
+    ;;  Calculate the indentation we will need for the paragraph
+    (back-to-indentation)
+    (set 'indent (current-column))
+    ;;  unindent the first line of the paragraph
+    (delete-region from (point))
+
+    ;;  Remove the old postfixes
+    (goto-char from)
+    (while (re-search-forward (concat ada-fill-comment-postfix "\n") to t)
+      (replace-match "\n"))
+
+    (goto-char (1- to))
+    (set 'to (point-marker))
+
+    ;;  Indent and justify the paragraph
+    (set 'fill-prefix ada-fill-comment-prefix)
+    (set-left-margin from to indent)
+    (if postfix
+        (set 'fill-column (- fill-column (length ada-fill-comment-postfix))))
+
+    (fill-region-as-paragraph from to justify)
+
+    ;;  Add the postfixes if required
+    (if postfix
+        (save-restriction
+          (goto-char from)
+          (narrow-to-region from to)
+          (while (not (eobp))
+            (end-of-line)
+            (insert-char ?  (- fill-column (current-column)))
+            (insert ada-fill-comment-postfix)
+            (forward-line))
+          ))
+
+    ;;  In Emacs <= 20.2 and XEmacs <=20.4, there is a bug, and a newline is
+    ;;  inserted at the end. Delete it
+    (if (or ada-xemacs
+            (<= emacs-major-version 19)
+            (and (= emacs-major-version 20)
+                 (<= emacs-minor-version 2)))
+        (progn
+          (goto-char to)
+          (end-of-line)
+          (delete-char 1)))
+
+    (goto-char opos)))
 
 ;;;---------------------------------------------------
 ;;; support for find-file.el
 ;;;---------------------------------------------------
 
-
-;;;###autoload
+;;; Note : this function is overwritten when we work with GNAT: we then
+;;; use gnatkrunch
 (defun ada-make-filename-from-adaname (adaname)
-  "Determine the filename of a package/procedure from its own Ada name."
-  ;; this is done simply by calling `gnatkr', when we work with GNAT. It
-  ;; must be a more complex function in other compiler environments.
-  (interactive "s")
-  (let (krunch-buf)
-    (setq krunch-buf (generate-new-buffer "*gkrunch*"))
-    (save-excursion
-      (set-buffer krunch-buf)
-      ;; send adaname to external process `gnatkr'.
-      (call-process "gnatkr" nil krunch-buf nil
-                    adaname ada-krunch-args)
-      ;; fetch output of that process
-      (setq adaname (buffer-substring
-                     (point-min)
-                     (progn
-                       (goto-char (point-min))
-                       (end-of-line)
-                       (point))))
-      (kill-buffer krunch-buf)))
-  (setq adaname adaname) ;; can I avoid this statement?
+  "Determine the filename of a package/procedure from its own Ada name.
+This is a generic function, independant from any compiler."
+  (while (string-match "\\." adaname)
+    (set 'adaname (replace-match "-" t t adaname)))
+  adaname
   )
 
+(defun ada-other-file-name ()
+  "Return the name of the other file (the body if current-buffer is the spec,
+or the spec otherwise."
+  (let ((ff-always-try-to-create nil)
+        (buffer                  (current-buffer))
+        name)
+    (ff-find-other-file nil t);; same window, ignore 'with' lines
+    (if (equal buffer (current-buffer))
+
+        ;;  other file not found
+        ""
+
+      ;; other file found
+      (set 'name (buffer-file-name))
+      (switch-to-buffer buffer)
+      name)))
 
 ;;; functions for placing the cursor on the corresponding subprogram
 (defun ada-which-function-are-we-in ()
   "Determine whether we are on a function definition/declaration.
-If that is the case remember the name of that function."
-
-  (setq ff-function-name nil)
-
+If that is the case remember the name of that function.
+This function is used in support of the find-file.el package"
+
+  (set 'ff-function-name nil)
   (save-excursion
-    (if (re-search-backward ada-procedure-start-regexp nil t)
-	(setq ff-function-name (buffer-substring (match-beginning 0)
-						 (match-end 0)))
-      ; we didn't find a procedure start, perhaps there is a package
-      (if (re-search-backward ada-package-start-regexp nil t)
-	  (setq ff-function-name (buffer-substring (match-beginning 0)
-						   (match-end 0)))
-	))))
-
+    (end-of-line);;  make sure we get the complete name
+    (if (or (re-search-backward ada-procedure-start-regexp nil t)
+            (re-search-backward ada-package-start-regexp nil t))
+        (set 'ff-function-name (match-string 0)))
+    ))
+
+(defun ada-set-point-accordingly ()
+  "Move to the function declaration that was set by `ff-which-function-are-we-in'"
+  (if ff-function-name
+      (progn
+        (goto-char (point-min))
+        (unless (ada-search-ignore-string-comment (concat ff-function-name "\\b") nil)
+          (goto-char (point-min))))))
 
 ;;;---------------------------------------------------
 ;;; support for font-lock
 ;;;---------------------------------------------------
-
 ;; Strings are a real pain in Ada because a single quote character is
 ;; overloaded as a string quote and type/instance delimiter.  By default, a
 ;; single quote is given punctuation syntax in `ada-mode-syntax-table'.
@@ -3708,206 +3995,175 @@
 
 (defconst ada-font-lock-syntactic-keywords
   ;; Mark single quotes as having string quote syntax in 'c' instances.
-  '(("\\(\'\\).\\(\'\\)" (1 (7 . ?\')) (2 (7 . ?\')))))
-
-(defconst ada-font-lock-keywords-1
-  (list
-   ;;
-   ;; handle "type T is access function return S;"
-   ;; 
-   (list "\\<\\(function[ \t]+return\\)\\>" '(1 font-lock-keyword-face) )
-   ;;
-   ;; accept, entry, function, package (body), protected (body|type),
-   ;; pragma, procedure, task (body) plus name.
-   (list (concat
-	  "\\<\\("
-	  "accept\\|"
-	  "entry\\|"
-          "function\\|"
-          "package[ \t]+body\\|"
-          "package\\|"
-          "pragma\\|"
-          "procedure\\|"
-          "protected[ \t]+body\\|"
-          "protected[ \t]+type\\|"
-          "protected\\|"
-;;	  "p\\(\\(ackage\\|rotected\\)\\(\\|[ \t]+\\(body\\|type\\)\\)\
-;;\\|r\\(agma\\|ocedure\\)\\)\\|"
-	  "task[ \t]+body\\|"
-	  "task[ \t]+type\\|"
-	  "task"
-;;	  "task\\(\\|[ \t]+body\\)"
-	  "\\)\\>[ \t]*"
-	  "\\(\\sw+\\(\\.\\sw*\\)*\\)?")
-    '(1 font-lock-keyword-face) '(2 font-lock-function-name-face nil t)))
-  "Subdued level highlighting for Ada mode.")
-
-(defconst ada-font-lock-keywords-2
-  (append ada-font-lock-keywords-1
-   (list
-    ;;
-    ;; Main keywords, except those treated specially below.
-    (concat "\\<\\("
-;    ("abort" "abs" "abstract" "accept" "access" "aliased" "all"
-;     "and" "array" "at" "begin" "case" "declare" "delay" "delta"
-;     "digits" "do" "else" "elsif" "entry" "exception" "exit" "for"
-;     "generic" "if" "in" "is" "limited" "loop" "mod" "not"
-;     "null" "or" "others" "private" "protected"
-;     "range" "record" "rem" "renames" "requeue" "return" "reverse"
-;     "select" "separate" "tagged" "task" "terminate" "then" "until"
-;     "while" "xor")
-            "a\\(b\\(ort\\|s\\(\\|tract\\)\\)\\|cce\\(pt\\|ss\\)\\|"
-            "l\\(iased\\|l\\)\\|nd\\|rray\\|t\\)\\|begin\\|case\\|"
-            "d\\(e\\(clare\\|l\\(ay\\|ta\\)\\)\\|igits\\|o\\)\\|"
-            "e\\(ls\\(e\\|if\\)\\|ntry\\|x\\(ception\\|it\\)\\)\\|for\\|"
-            "generic\\|i[fns]\\|l\\(imited\\|oop\\)\\|mod\\|n\\(ot\\|ull\\)\\|"
-            "o\\(r\\|thers\\|ut\\)\\|pr\\(ivate\\|otected\\)\\|"
-            "r\\(a\\(ise\\|nge\\)\\|e\\(cord\\|m\\|names\\|queue\\|turn\\|verse\\)\\)\\|"
-            "se\\(lect\\|parate\\)\\|"
-            "t\\(agged\\|erminate\\|hen\\)\\|until\\|" ; task removed
-	    "wh\\(ile\\|en\\)\\|xor" ; "when" added
-            "\\)\\>")
-    ;;
-    ;; Anything following end and not already fontified is a body name.
-    '("\\<\\(end\\)\\>\\([ \t]+\\)?\\([a-zA-Z0-9_\\.]+\\)?"
-      (1 font-lock-keyword-face) (3 font-lock-function-name-face nil t))
-    ;;
-    ;; Variable name plus optional keywords followed by a type name.  Slow.
-;    (list (concat "\\<\\(\\sw+\\)\\>[ \t]*:?[ \t]*"
-;                 "\\(access\\|constant\\|in\\|in[ \t]+out\\|out\\)?[ \t]*"
-;                 "\\(\\sw+\\)?")
-;         '(1 font-lock-variable-name-face)
-;         '(2 font-lock-keyword-face nil t) '(3 font-lock-type-face nil t))
-    ;;
-    ;; Optional keywords followed by a type name.
-    (list (concat ; ":[ \t]*"
-                  "\\<\\(access\\|constant\\|in[ \t]+out\\|in\\|out\\)\\>"
-                  "[ \t]*"
-                  "\\(\\sw+\\)?")
-          '(1 font-lock-keyword-face nil t) '(2 font-lock-type-face nil t))
-    ;;
-    ;; Keywords followed by a type or function name.
-    (list (concat "\\<\\("
-                  "new\\|of\\|subtype\\|type"
-                  "\\)\\>[ \t]*\\(\\sw+\\)?[ \t]*\\((\\)?")
-          '(1 font-lock-keyword-face)
-          '(2 (if (match-beginning 4)
-                  font-lock-function-name-face
-                font-lock-type-face) nil t))
-    ;;
-    ;; Keywords followed by a (comma separated list of) reference.
-    (list (concat "\\<\\(goto\\|raise\\|use\\|with\\)\\>" ; "when" removed
-                  ; "[ \t]*\\(\\sw+\\(\\.\\sw*\\)*\\)?") ; RE
-                  "[ \t]*\\([a-zA-Z0-9_\\.\\|, ]+\\)\\W")
-          '(1 font-lock-keyword-face) '(2 font-lock-constant-face nil t))
-    ;;
-    ;; Goto tags.
-    '("<<\\(\\sw+\\)>>" 1 font-lock-constant-face)
+  ;; As a special case, ''' will not be hilighted, but if we do not
+  ;; set this special case, then the rest of the buffer is hilighted as
+  ;; a string
+  ;; This sets the properties of the characters, so that ada-in-string-p
+  ;; correctly handles '"' too...
+  '(("\\('\\)[^'\n]\\('\\)" (1 (7 . ?')) (2 (7 . ?')))
+    ("^[ \t]*\\(#\\(if\\|else\\|elsif\\|end\\)\\)" (1 (11 . ?\n)))
     ))
-  "Gaudy level highlighting for Ada mode.")
-
-(defvar ada-font-lock-keywords ada-font-lock-keywords-1
+
+(defvar ada-font-lock-keywords
+  (eval-when-compile
+    (list
+     ;;
+     ;; handle "type T is access function return S;"
+     (list "\\<\\(function[ \t]+return\\)\\>" '(1 font-lock-keyword-face) )
+
+     ;;  preprocessor line
+     (list "^[ \t]*\\(#.*\n\\)"  '(1 font-lock-type-face t))
+
+     ;;
+     ;; accept, entry, function, package (body), protected (body|type),
+     ;; pragma, procedure, task (body) plus name.
+     (list (concat
+            "\\<\\("
+            "accept\\|"
+            "entry\\|"
+            "function\\|"
+            "package[ \t]+body\\|"
+            "package\\|"
+            "pragma\\|"
+            "procedure\\|"
+            "protected[ \t]+body\\|"
+            "protected[ \t]+type\\|"
+            "protected\\|"
+            "task[ \t]+body\\|"
+            "task[ \t]+type\\|"
+            "task"
+            "\\)\\>[ \t]*"
+            "\\(\\sw+\\(\\.\\sw*\\)*\\)?")
+           '(1 font-lock-keyword-face) '(2 font-lock-function-name-face nil t))
+     ;;
+     ;; Optional keywords followed by a type name.
+     (list (concat                      ; ":[ \t]*"
+            "\\<\\(access[ \t]+all\\|access\\|constant\\|in[ \t]+out\\|in\\|out\\)\\>"
+            "[ \t]*"
+            "\\(\\sw+\\(\\.\\sw*\\)*\\)?")
+           '(1 font-lock-keyword-face nil t) '(2 font-lock-type-face nil t))
+
+     ;;
+     ;; Main keywords, except those treated specially below.
+     (concat "\\<"
+             (regexp-opt
+              '("abort" "abs" "abstract" "accept" "access" "aliased" "all"
+                "and" "array" "at" "begin" "case" "declare" "delay" "delta"
+                "digits" "do" "else" "elsif" "entry" "exception" "exit" "for"
+                "generic" "if" "in" "is" "limited" "loop" "mod" "not"
+                "null" "or" "others" "private" "protected" "raise"
+                "range" "record" "rem" "renames" "requeue" "return" "reverse"
+                "select" "separate" "tagged" "task" "terminate" "then" "until"
+                "when" "while" "xor") t)
+             "\\>")
+     ;;
+     ;; Anything following end and not already fontified is a body name.
+     '("\\<\\(end\\)\\>\\([ \t]+\\)?\\(\\(\\sw\\|[_.]\\)+\\)?"
+       (1 font-lock-keyword-face) (3 font-lock-function-name-face nil t))
+     ;;
+     ;; Keywords followed by a type or function name.
+     (list (concat "\\<\\("
+                   "new\\|of\\|subtype\\|type"
+                   "\\)\\>[ \t]*\\(\\sw+\\(\\.\\sw*\\)*\\)?[ \t]*\\((\\)?")
+           '(1 font-lock-keyword-face)
+           '(2 (if (match-beginning 4)
+                   font-lock-function-name-face
+                 font-lock-type-face) nil t))
+     ;;
+     ;; Keywords followed by a (comma separated list of) reference.
+     (list (concat "\\<\\(goto\\|raise\\|use\\|with\\)\\>" ; "when" removed
+                   "[ \t\n]*\\(\\(\\sw\\|[_.|, \t\n]\\)+\\)\\W")
+           '(1 font-lock-keyword-face) '(2 font-lock-reference-face nil t))
+     ;;
+     ;; Goto tags.
+     '("<<\\(\\sw+\\)>>" 1 font-lock-reference-face)
+     ))
   "Default expressions to highlight in Ada mode.")
 
-
-;; set font-lock properties for XEmacs
-(if (ada-xemacs)
-    (put 'ada-mode 'font-lock-defaults
-         '(ada-font-lock-keywords
-           nil t ((?\_ . "w")(?\. . "w")) beginning-of-line)))
-
-;;;
-;;; support for outline
-;;;
-
-;; used by outline-minor-mode
+;;
+;;  outline-minor-mode support
+
 (defun ada-outline-level ()
-  ;; This so that `current-column' DTRT in otherwise-hidden text.
+  ;; This is so that `current-column` DTRT in otherwise-hidden text
+  ;; patch from Dave Love <fx@gnu.org>
   (let (buffer-invisibility-spec)
     (save-excursion
-      (skip-chars-forward "\t ")
+      (back-to-indentation)
       (current-column))))
 
-;;;
-;;; generate body
-;;;
-(defun ada-gen-comment-until-proc ()
-  ;; comment until spec of a procedure or a function.
-  (forward-line 1)
-  (set-mark-command (point))
-  (if (re-search-forward ada-procedure-start-regexp nil t)
-      (progn (goto-char (match-beginning 1))
-             (comment-region (mark) (point)))
-    (error "No more functions/procedures")))
-
+;;
+;;  Body generation
+;;
 
 (defun ada-gen-treat-proc (match)
   ;; make dummy body of a procedure/function specification.
   ;; MATCH is a cons cell containing the start and end location of the
-  ;; last search for ada-procedure-start-regexp. 
+  ;; last search for ada-procedure-start-regexp.
   (goto-char (car match))
-  (let (proc-found func-found procname functype)
-    (cond
-     ((or (setq proc-found (looking-at "^[ \t]*procedure"))
-	  (setq func-found (looking-at "^[ \t]*function")))
-      ;; treat it as a proc/func
-      (forward-word 2) 
-      (forward-word -1)
-      (setq procname (buffer-substring (point) (cdr match))) ; store  proc name
-
-    ;; goto end of procname
-    (goto-char (cdr match))
-
-    ;; skip over parameterlist
-    (forward-sexp)
-    ;; if function, skip over 'return' and result type.
-    (if func-found
-	(progn
-	  (forward-word 1)
-	  (skip-chars-forward " \t\n")
-	  (setq functype (buffer-substring (point)
-					   (progn 
-					     (skip-chars-forward
-					      "a-zA-Z0-9_\.")
-					     (point))))))
-    ;; look for next non WS
+  (let (func-found procname functype)
     (cond
-     ((looking-at "[ \t]*;")
-      (delete-region (match-beginning 0) (match-end 0)) ;; delete the ';'
-      (ada-indent-newline-indent)
-      (insert " is")
-      (ada-indent-newline-indent)
-      (if func-found
-	  (progn
-	    (insert "Result : ")
-	    (insert functype)
-	    (insert ";")
-	    (ada-indent-newline-indent)))
-      (insert "begin -- ")
-      (insert procname)
-      (ada-indent-newline-indent)
-      (insert "null;")
-      (ada-indent-newline-indent)
+     ((or (looking-at "^[ \t]*procedure")
+          (set 'func-found (looking-at "^[ \t]*function")))
+      ;; treat it as a proc/func
+      (forward-word 2)
+      (forward-word -1)
+      (set 'procname (buffer-substring (point) (cdr match))) ; store  proc name
+
+      ;; goto end of procname
+      (goto-char (cdr match))
+
+      ;; skip over parameterlist
+      (unless (looking-at "[ \t\n]*\\(;\\|return\\)")
+        (forward-sexp))
+
+      ;; if function, skip over 'return' and result type.
       (if func-found
-	  (progn
-	    (insert "return Result;")
-	    (ada-indent-newline-indent)))
-      (insert "end ")
-      (insert procname)
-      (insert ";")
-      (ada-indent-newline-indent)	
-      )
-      ;; else
-     ((looking-at "[ \t\n]*is")
-      ;; do nothing
-      )
-     ((looking-at "[ \t\n]*rename")
-      ;; do nothing
-      )
+          (progn
+            (forward-word 1)
+            (skip-chars-forward " \t\n")
+            (set 'functype (buffer-substring (point)
+                                             (progn
+                                               (skip-chars-forward
+                                                "a-zA-Z0-9_\.")
+                                               (point))))))
+      ;; look for next non WS
+      (cond
+       ((looking-at "[ \t]*;")
+        (delete-region (match-beginning 0) (match-end 0));; delete the ';'
+        (ada-indent-newline-indent)
+        (insert "is")
+        (ada-indent-newline-indent)
+        (if func-found
+            (progn
+              (insert "Result : " functype ";")
+              (ada-indent-newline-indent)))
+        (insert "begin")
+        (ada-indent-newline-indent)
+        (if func-found
+            (insert "return Result;")
+          (insert "null;"))
+        (ada-indent-newline-indent)
+        (insert "end " procname ";")
+        (ada-indent-newline-indent)
+        )
+       ;; else
+       ((looking-at "[ \t\n]*is")
+        ;; do nothing
+        )
+       ((looking-at "[ \t\n]*rename")
+        ;; do nothing
+        )
+       (t
+        (message "unknown syntax"))))
      (t
-      (message "unknown syntax")))
-    ))))
-
+      (if (looking-at "^[ \t]*task")
+          (progn
+            (message "Task conversion is not yet implemented")
+            (forward-word 2)
+            (if (looking-at "[ \t]*;")
+                (forward-line)
+              (ada-move-to-end))
+            ))))))
 
 (defun ada-make-body ()
   "Create an Ada package body in the current buffer.
@@ -3920,27 +4176,104 @@
   (insert-buffer (car (cdr (buffer-list))))
   (ada-mode)
 
-  (let (found)
-    (if (setq found 
-	      (ada-search-ignore-string-comment ada-package-start-regexp))
-	(progn (goto-char (cdr found))
-	       (insert " body")
-	       ;; (forward-line -1)
-	       ;;(comment-region (point-min) (point))
-	       )
+  (let (found ada-procedure-or-package-start-regexp)
+    (if (set 'found
+             (ada-search-ignore-string-comment ada-package-start-regexp nil))
+        (progn (goto-char (cdr found))
+               (insert " body")
+               )
       (error "No package"))
-    
-    ;; (comment-until-proc)
-    ;;   does not work correctly
-    ;;   must be done by hand
-    
-    (while (setq found
-		 (ada-search-ignore-string-comment ada-procedure-start-regexp))
-      (ada-gen-treat-proc found))))
-
-
-;;; provide ourself
-
+
+    (set 'ada-procedure-or-package-start-regexp
+         (concat ada-procedure-start-regexp
+                 "\\|"
+                 ada-package-start-regexp))
+
+    (while (set 'found
+                (ada-search-ignore-string-comment
+                 ada-procedure-or-package-start-regexp nil))
+      (progn
+        (goto-char (car found))
+        (if (looking-at ada-package-start-regexp)
+            (progn (goto-char (cdr found))
+                   (insert " body"))
+          (ada-gen-treat-proc found))))))
+
+(defun ada-make-subprogram-body ()
+  "make one dummy subprogram body from spec surrounding point"
+  (interactive)
+  (let* ((found (re-search-backward ada-procedure-start-regexp nil t))
+         (spec  (match-beginning 0)))
+    (if found
+        (progn
+          (goto-char spec)
+          (if (and (re-search-forward "(\\|;" nil t)
+                   (= (char-before) ?\())
+              (progn
+                (ada-search-ignore-string-comment ")" nil)
+                (ada-search-ignore-string-comment ";" nil)))
+          (set 'spec (buffer-substring spec (point)))
+
+	  ;; If find-file.el was available, use its functions
+	  (if (functionp 'ff-get-file)
+	      (find-file (ff-get-file
+			  ff-search-directories
+			  (ada-make-filename-from-adaname
+			   (file-name-nondirectory
+			    (file-name-sans-extension (buffer-name))))
+			  ada-body-suffixes))
+	    ;; Else emulate it very simply
+	    (find-file (concat (ada-make-filename-from-adaname
+				(file-name-nondirectory
+				 (file-name-sans-extension (buffer-name))))
+			       ".adb")))
+	    
+          (save-restriction
+            (widen)
+            (goto-char (point-max))
+            (forward-comment -10000)
+            (re-search-backward "\\<end\\>" nil t)
+            ;;  Move to the beginning of the elaboration part, if any
+            (re-search-backward "^begin" nil t)
+            (newline)
+            (forward-char -1)
+            (insert spec)
+            (re-search-backward ada-procedure-start-regexp nil t)
+            (ada-gen-treat-proc (cons (match-beginning 0) (match-end 0)))
+            ))
+      (error "Not in subprogram spec"))))
+
+;;  Create the keymap once and for all. If we do that in ada-mode,
+;;  the keys changed in the user's .emacs have to be modified
+;;  every time
+(ada-create-keymap)
+(ada-create-menu)
+
+;;  Create the syntax tables, but do not activate them
+(ada-create-syntax-table)
+
+;;  Add the default extensions (and set up speedbar)
+(ada-add-extensions ".ads" ".adb")
+;; This two files are generated by GNAT when running with -gnatD
+(if (equal ada-which-compiler 'gnat)
+    (ada-add-extensions ".ads.dg" ".adb.dg"))
+
+;;  Read the special cases for exceptions
+(ada-case-read-exceptions)
+
+;; include the other ada-mode files
+
+(if (equal ada-which-compiler 'gnat)
+    (progn
+      ;; The order here is important: ada-xref defines the Project
+      ;; submenu, and ada-prj adds to it.
+      (condition-case nil  (require 'ada-prj) (error nil))
+      (require 'ada-xref)
+      ))
+(condition-case nil (require 'ada-stmt) (error nil))
+
+;;; provide ourselves
 (provide 'ada-mode)
 
 ;;; ada-mode.el ends here
+