]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/octave-mod.el
Romain Francoise's and Ami Fischman's bugfixes.
[gnu-emacs] / lisp / progmodes / octave-mod.el
index f91a268f832e6dbd8b8bce1771daa26858fe26b6..281edfd693efb2bcc4e91b323aedcce9c6735ada 100644 (file)
@@ -1,6 +1,6 @@
-;; octave-mod.el --- editing Octave source files under Emacs
+;;; octave-mod.el --- editing Octave source files under Emacs
 
-;;; Copyright (C) 1997 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2003 Free Software Foundation, Inc.
 
 ;; Author: Kurt Hornik <Kurt.Hornik@ci.tuwien.ac.at>
 ;; Author: John Eaton <jwe@bevo.che.wisc.edu>
 ;; `run-octave' for further information on usage and customization.
 
 ;;; Code:
+(require 'custom)
+
+(defgroup octave nil
+  "Major mode for editing Octave source files."
+  :group 'languages)
+
+(defvar inferior-octave-output-list nil)
+(defvar inferior-octave-output-string nil)
+(defvar inferior-octave-receive-in-progress nil)
 
 (defconst octave-maintainer-address
-  "Kurt Hornik <Kurt.Hornik@ci.tuwien.ac.at>, bug-gnu-emacs@prep.ai.mit.edu" 
+  "Kurt Hornik <Kurt.Hornik@ci.tuwien.ac.at>, bug-gnu-emacs@gnu.org"
   "Current maintainer of the Emacs Octave package.")
 
 (defvar octave-abbrev-table nil
   "Abbrev table for Octave's reserved words.
-Used in octave-mode and inferior-octave-mode buffers.
+Used in `octave-mode' and inferior-octave-mode buffers.
 All Octave abbrevs start with a grave accent (`).")
-(if octave-abbrev-table
-    ()
+(unless octave-abbrev-table
   (let ((ac abbrevs-changed))
     (define-abbrev-table 'octave-abbrev-table ())
-    (define-abbrev octave-abbrev-table "`a" "all_va_args" nil)
-    (define-abbrev octave-abbrev-table "`b" "break" nil)
-    (define-abbrev octave-abbrev-table "`cs" "case" nil)
-    (define-abbrev octave-abbrev-table "`ca" "catch" nil)
-    (define-abbrev octave-abbrev-table "`c" "continue" nil)
-    (define-abbrev octave-abbrev-table "`el" "else" nil)
-    (define-abbrev octave-abbrev-table "`eli" "elseif" nil)
-    (define-abbrev octave-abbrev-table "`et" "end_try_catch" nil)
-    (define-abbrev octave-abbrev-table "`eu" "end_unwind_protect" nil)
-    (define-abbrev octave-abbrev-table "`ef" "endfor" nil)
-    (define-abbrev octave-abbrev-table "`efu" "endfunction" nil)
-    (define-abbrev octave-abbrev-table "`ei" "endif" nil)
-    (define-abbrev octave-abbrev-table "`es" "endswitch" nil)
-    (define-abbrev octave-abbrev-table "`ew" "endwhile" nil)
-    (define-abbrev octave-abbrev-table "`f" "for" nil)
-    (define-abbrev octave-abbrev-table "`fu" "function" nil)
-    (define-abbrev octave-abbrev-table "`gl" "global" nil)
-    (define-abbrev octave-abbrev-table "`gp" "gplot" nil)
-    (define-abbrev octave-abbrev-table "`gs" "gsplot" nil)
-    (define-abbrev octave-abbrev-table "`if" "if ()" nil)
-    (define-abbrev octave-abbrev-table "`o" "otherwise" nil)
-    (define-abbrev octave-abbrev-table "`rp" "replot" nil)
-    (define-abbrev octave-abbrev-table "`r" "return" nil)
-    (define-abbrev octave-abbrev-table "`s" "switch" nil)
-    (define-abbrev octave-abbrev-table "`t" "try" nil)
-    (define-abbrev octave-abbrev-table "`up" "unwind_protect" nil)
-    (define-abbrev octave-abbrev-table "`upc" "unwind_protect_cleanup" nil)
-    (define-abbrev octave-abbrev-table "`w" "while ()" nil)
+    (define-abbrev octave-abbrev-table "`a" "all_va_args" nil 0 t)
+    (define-abbrev octave-abbrev-table "`b" "break" nil 0 t)
+    (define-abbrev octave-abbrev-table "`cs" "case" nil 0 t)
+    (define-abbrev octave-abbrev-table "`ca" "catch" nil 0 t)
+    (define-abbrev octave-abbrev-table "`c" "continue" nil 0 t)
+    (define-abbrev octave-abbrev-table "`el" "else" nil 0 t)
+    (define-abbrev octave-abbrev-table "`eli" "elseif" nil 0 t)
+    (define-abbrev octave-abbrev-table "`et" "end_try_catch" nil 0 t)
+    (define-abbrev octave-abbrev-table "`eu" "end_unwind_protect" nil 0 t)
+    (define-abbrev octave-abbrev-table "`ef" "endfor" nil 0 t)
+    (define-abbrev octave-abbrev-table "`efu" "endfunction" nil 0 t)
+    (define-abbrev octave-abbrev-table "`ei" "endif" nil 0 t)
+    (define-abbrev octave-abbrev-table "`es" "endswitch" nil 0 t)
+    (define-abbrev octave-abbrev-table "`ew" "endwhile" nil 0 t)
+    (define-abbrev octave-abbrev-table "`f" "for" nil 0 t)
+    (define-abbrev octave-abbrev-table "`fu" "function" nil 0 t)
+    (define-abbrev octave-abbrev-table "`gl" "global" nil 0 t)
+    (define-abbrev octave-abbrev-table "`gp" "gplot" nil 0 t)
+    (define-abbrev octave-abbrev-table "`gs" "gsplot" nil 0 t)
+    (define-abbrev octave-abbrev-table "`if" "if ()" nil 0 t)
+    (define-abbrev octave-abbrev-table "`o" "otherwise" nil 0 t)
+    (define-abbrev octave-abbrev-table "`rp" "replot" nil 0 t)
+    (define-abbrev octave-abbrev-table "`r" "return" nil 0 t)
+    (define-abbrev octave-abbrev-table "`s" "switch" nil 0 t)
+    (define-abbrev octave-abbrev-table "`t" "try" nil 0 t)
+    (define-abbrev octave-abbrev-table "`up" "unwind_protect" nil 0 t)
+    (define-abbrev octave-abbrev-table "`upc" "unwind_protect_cleanup" nil 0 t)
+    (define-abbrev octave-abbrev-table "`w" "while ()" nil 0 t)
     (setq abbrevs-changed ac)))
 
 (defvar octave-comment-char ?#
   "Character to start an Octave comment.")
 (defvar octave-comment-start
-  (concat (make-string 1 octave-comment-char) " ")
+  (string octave-comment-char ?\ )
   "String to insert to start a new Octave in-line comment.")
 (defvar octave-comment-start-skip "\\s<+\\s-*"
   "Regexp to match the start of an Octave comment up to its body.")
@@ -167,7 +175,9 @@ parenthetical grouping.")
         'font-lock-keyword-face)
    ;; Fontify all builtin operators.
    (cons "\\(&\\||\\|<=\\|>=\\|==\\|<\\|>\\|!=\\|!\\)"
-        'font-lock-reference-face)
+        (if (boundp 'font-lock-builtin-face)
+            'font-lock-builtin-face
+          'font-lock-preprocessor-face))
    ;; Fontify all builtin variables.
    (cons (concat "\\<\\("
                 (mapconcat 'identity octave-variables "\\|")
@@ -179,8 +189,10 @@ parenthetical grouping.")
         '(3 font-lock-function-name-face nil t)))
   "Additional Octave expressions to highlight.")
 
-(defvar inferior-octave-buffer "*Inferior Octave*"
-  "*Name of buffer for running an inferior Octave process.")
+(defcustom inferior-octave-buffer "*Inferior Octave*"
+  "*Name of buffer for running an inferior Octave process."
+  :type 'string
+  :group 'octave-inferior)
 
 (defvar inferior-octave-process nil)
 \f
@@ -195,34 +207,41 @@ parenthetical grouping.")
     (define-key map "\n" 'octave-reindent-then-newline-and-indent)
     (define-key map "\t" 'indent-according-to-mode)
     (define-key map "\e;" 'octave-indent-for-comment)
-    (define-key map "\e\n" 'octave-indent-new-comment-line)  
+    (define-key map "\e\n" 'octave-indent-new-comment-line)
     (define-key map "\e\t" 'octave-complete-symbol)
     (define-key map "\M-\C-a" 'octave-beginning-of-defun)
     (define-key map "\M-\C-e" 'octave-end-of-defun)
     (define-key map "\M-\C-h" 'octave-mark-defun)
-    (define-key map "\M-\C-q" 'octave-indent-defun)  
+    (define-key map "\M-\C-q" 'octave-indent-defun)
     (define-key map "\C-c;" 'octave-comment-region)
-    (define-key map "\C-c:" 'octave-uncomment-region)  
+    (define-key map "\C-c:" 'octave-uncomment-region)
     (define-key map "\C-c\C-b" 'octave-submit-bug-report)
     (define-key map "\C-c\C-p" 'octave-previous-code-line)
     (define-key map "\C-c\C-n" 'octave-next-code-line)
     (define-key map "\C-c\C-a" 'octave-beginning-of-line)
-    (define-key map "\C-c\C-e" 'octave-end-of-line)  
+    (define-key map "\C-c\C-e" 'octave-end-of-line)
     (define-key map "\C-c\M-\C-n" 'octave-forward-block)
     (define-key map "\C-c\M-\C-p" 'octave-backward-block)
     (define-key map "\C-c\M-\C-u" 'octave-backward-up-block)
     (define-key map "\C-c\M-\C-d" 'octave-down-block)
     (define-key map "\C-c\M-\C-h" 'octave-mark-block)
     (define-key map "\C-c]" 'octave-close-block)
-    (define-key map "\C-cf" 'octave-insert-defun)
+    (define-key map "\C-c\C-f" 'octave-insert-defun)
     (define-key map "\C-c\C-h" 'octave-help)
-    (define-key map "\C-cil" 'octave-send-line)
-    (define-key map "\C-cib" 'octave-send-block)
-    (define-key map "\C-cif" 'octave-send-defun)
-    (define-key map "\C-cir" 'octave-send-region)  
-    (define-key map "\C-cis" 'octave-show-process-buffer)
-    (define-key map "\C-cih" 'octave-hide-process-buffer)
-    (define-key map "\C-cik" 'octave-kill-process)
+    (define-key map "\C-c\C-il" 'octave-send-line)
+    (define-key map "\C-c\C-ib" 'octave-send-block)
+    (define-key map "\C-c\C-if" 'octave-send-defun)
+    (define-key map "\C-c\C-ir" 'octave-send-region)
+    (define-key map "\C-c\C-is" 'octave-show-process-buffer)
+    (define-key map "\C-c\C-ih" 'octave-hide-process-buffer)
+    (define-key map "\C-c\C-ik" 'octave-kill-process)
+    (define-key map "\C-c\C-i\C-l" 'octave-send-line)
+    (define-key map "\C-c\C-i\C-b" 'octave-send-block)
+    (define-key map "\C-c\C-i\C-f" 'octave-send-defun)
+    (define-key map "\C-c\C-i\C-r" 'octave-send-region)
+    (define-key map "\C-c\C-i\C-s" 'octave-show-process-buffer)
+    (define-key map "\C-c\C-i\C-h" 'octave-hide-process-buffer)
+    (define-key map "\C-c\C-i\C-k" 'octave-kill-process)
     (setq octave-mode-map map)))
 
 (defvar octave-mode-menu
@@ -268,10 +287,7 @@ parenthetical grouping.")
        ["Lookup Octave Index"          octave-help t])
   "Menu for Octave mode.")
 
-(defvar octave-mode-syntax-table nil
-  "Syntax table in use in octave-mode buffers.")
-(if octave-mode-syntax-table
-    ()
+(defvar octave-mode-syntax-table
   (let ((table (make-syntax-table)))
     (modify-syntax-entry ?\r " "  table)
     (modify-syntax-entry ?+ "."   table)
@@ -290,20 +306,32 @@ parenthetical grouping.")
     (modify-syntax-entry ?\" "\"" table)
     (modify-syntax-entry ?. "w"   table)
     (modify-syntax-entry ?_ "w"   table)
-    (modify-syntax-entry ?\% "."  table)
+    (modify-syntax-entry ?\% "<"  table)
     (modify-syntax-entry ?\# "<"  table)
     (modify-syntax-entry ?\n ">"  table)
-    (setq octave-mode-syntax-table table)))
+    table)
+  "Syntax table in use in `octave-mode' buffers.")
 
-(defvar octave-auto-newline nil
-  "*Non-nil means automatically newline after a semicolon in Octave mode.")
+(defcustom octave-auto-indent nil
+  "*Non-nil means indent line after a semicolon or space in Octave mode."
+  :type 'boolean
+  :group 'octave)
 
-(defvar octave-blink-matching-block t
+(defcustom octave-auto-newline nil
+  "*Non-nil means automatically newline after a semicolon in Octave mode."
+  :type 'boolean
+  :group 'octave)
+
+(defcustom octave-blink-matching-block t
   "*Control the blinking of matching Octave block keywords.
 Non-nil means show matching begin of block when inserting a space,
-newline or semicolon after an else or end keyword.")
-(defvar octave-block-offset 2
-  "*Extra indentation applied to statements in Octave block structures.")
+newline or semicolon after an else or end keyword."
+  :type 'boolean
+  :group 'octave)
+(defcustom octave-block-offset 2
+  "*Extra indentation applied to statements in Octave block structures."
+  :type 'integer
+  :group 'octave)
 
 (defvar octave-block-begin-regexp
   (concat "\\<\\("
@@ -325,7 +353,7 @@ newline or semicolon after an else or end keyword.")
   '(("for" . ("end" "endfor"))
     ("function" . ("end" "endfunction"))
     ("if" . ("else" "elseif" "end" "endif"))
-    ("switch" . ("case" "end" "endswitch" "otherwise"))
+    ("switch" . ("case" "otherwise" "end" "endswitch"))
     ("try" . ("catch" "end" "end_try_catch"))
     ("unwind_protect" . ("unwind_protect_cleanup" "end"
                         "end_unwind_protect"))
@@ -338,18 +366,22 @@ end keywords as associated values.")
   (concat (make-string 2 octave-comment-char) " ")
   "String to insert to start a new Octave comment on an empty line.")
 
-(defvar octave-continuation-offset 4
-  "*Extra indentation applied to Octave continuation lines.")
+(defcustom octave-continuation-offset 4
+  "*Extra indentation applied to Octave continuation lines."
+  :type 'integer
+  :group 'octave)
 (defvar octave-continuation-regexp
   "[^#%\n]*\\(\\\\\\|\\.\\.\\.\\)\\s-*\\(\\s<.*\\)?$")
-(defvar octave-continuation-string "\\"
-  "*Character string used for Octave continuation lines.  Normally \\.")
+(defcustom octave-continuation-string "\\"
+  "*Character string used for Octave continuation lines.  Normally \\."
+  :type 'string
+  :group 'octave)
 
 (defvar octave-completion-alist nil
   "Alist of Octave symbols for completion in Octave mode.
 Each element looks like (VAR . VAR), where the car and cdr are the same
 symbol (an Octave command or variable name).
-Currently, only builtin variables can be completed.") 
+Currently, only builtin variables can be completed.")
 
 (defvar octave-mode-imenu-generic-expression
   (list
@@ -357,19 +389,29 @@ Currently, only builtin variables can be completed.")
    (list nil octave-function-header-regexp 3))
   "Imenu expression for Octave mode.  See `imenu-generic-expression'.")
 
-(defvar octave-mode-startup-message t
-  "*Nil means do not display the Octave mode startup message.")
-
-(defvar octave-mode-hook nil
-  "*Hook to be run when Octave mode is started.")
-
-(defvar octave-send-show-buffer t
-  "*Non-nil means display `inferior-octave-buffer' after sending to it.")
-(defvar octave-send-line-auto-forward t
+(defcustom octave-mode-startup-message t
+  "*nil means do not display the Octave mode startup message."
+  :type 'boolean
+  :group 'octave)
+
+(defcustom octave-mode-hook nil
+  "*Hook to be run when Octave mode is started."
+  :type 'hook
+  :group 'octave)
+
+(defcustom octave-send-show-buffer t
+  "*Non-nil means display `inferior-octave-buffer' after sending to it."
+  :type 'boolean
+  :group 'octave)
+(defcustom octave-send-line-auto-forward t
   "*Control auto-forward after sending to the inferior Octave process.
-Non-nil means always go to the next Octave code line after sending.")
-(defvar octave-send-echo-input t
-  "*Non-nil means echo input sent to the inferior Octave process.")
+Non-nil means always go to the next Octave code line after sending."
+  :type 'boolean
+  :group 'octave)
+(defcustom octave-send-echo-input t
+  "*Non-nil means echo input sent to the inferior Octave process."
+  :type 'boolean
+  :group 'octave)
 
 \f
 ;;;###autoload
@@ -401,6 +443,10 @@ Keybindings
 Variables you can use to customize Octave mode
 ==============================================
 
+octave-auto-indent
+  Non-nil means indent current line after a semicolon or space.
+  Default is nil.
+
 octave-auto-newline
   Non-nil means auto-insert a newline and indent after a semicolon.
   Default is nil.
@@ -422,7 +468,7 @@ octave-continuation-string
   Default is a backslash.
 
 octave-mode-startup-message
-  Nil means do not display the Octave mode startup message.
+  nil means do not display the Octave mode startup message.
   Default is t.
 
 octave-send-echo-input
@@ -468,16 +514,16 @@ including a reproducible test case and send the message."
   (setq mode-name "Octave")
   (setq local-abbrev-table octave-abbrev-table)
   (set-syntax-table octave-mode-syntax-table)
-  
+
   (make-local-variable 'indent-line-function)
   (setq indent-line-function 'octave-indent-line)
 
-  (make-local-variable 'comment-start)  
+  (make-local-variable 'comment-start)
   (setq comment-start octave-comment-start)
   (make-local-variable 'comment-end)
   (setq comment-end "")
   (make-local-variable 'comment-column)
-  (setq comment-column 32)    
+  (setq comment-column 32)
   (make-local-variable 'comment-start-skip)
   (setq comment-start-skip "\\s<+\\s-*")
   (make-local-variable 'comment-indent-function)
@@ -504,7 +550,8 @@ including a reproducible test case and send the message."
   (setq font-lock-defaults '(octave-font-lock-keywords nil nil))
 
   (make-local-variable 'imenu-generic-expression)
-  (setq imenu-generic-expression octave-mode-imenu-generic-expression)
+  (setq imenu-generic-expression octave-mode-imenu-generic-expression
+        imenu-case-fold-search nil)
 
   (octave-add-octave-menu)
   (octave-initialize-completions)
@@ -516,33 +563,21 @@ including a reproducible test case and send the message."
   (interactive)
   (describe-function major-mode))
 
-(defun octave-point (position)
-  "Returns the value of point at certain positions." 
-  (save-excursion
-    (cond
-     ((eq position 'bol)  (beginning-of-line))
-     ((eq position 'eol)  (end-of-line))
-     ((eq position 'boi)  (back-to-indentation))
-     ((eq position 'bonl) (forward-line 1))
-     ((eq position 'bopl) (forward-line -1))
-     (t (error "unknown buffer position requested: %s" position)))
-    (point)))
-
 (defsubst octave-in-comment-p ()
   "Returns t if point is inside an Octave comment, nil otherwise."
   (interactive)
   (save-excursion
-    (nth 4 (parse-partial-sexp (octave-point 'bol) (point)))))
+    (nth 4 (parse-partial-sexp (line-beginning-position) (point)))))
 
 (defsubst octave-in-string-p ()
   "Returns t if point is inside an Octave string, nil otherwise."
   (interactive)
   (save-excursion
-    (nth 3 (parse-partial-sexp (octave-point 'bol) (point)))))
+    (nth 3 (parse-partial-sexp (line-beginning-position) (point)))))
 
 (defsubst octave-not-in-string-or-comment-p ()
   "Returns t iff point is not inside an Octave string or comment."
-  (let ((pps (parse-partial-sexp (octave-point 'bol) (point))))
+  (let ((pps (parse-partial-sexp (line-beginning-position) (point))))
     (not (or (nth 3 pps) (nth 4 pps)))))
 
 (defun octave-in-block-p ()
@@ -576,6 +611,18 @@ the end keyword."
                 (error nil))
               (< pos (point)))))))
 
+(defun octave-maybe-insert-continuation-string ()
+  (if (or (octave-in-comment-p)
+         (save-excursion
+           (beginning-of-line)
+           (looking-at octave-continuation-regexp)))
+      nil
+    (delete-horizontal-space)
+    (insert (concat " " octave-continuation-string))))
+
+(defvar octave-xemacs-p
+  (string-match "XEmacs\\|Lucid" emacs-version))
+
 ;;; Comments
 (defun octave-comment-region (beg end &optional arg)
   "Comment or uncomment each line in the region as Octave code.
@@ -583,7 +630,7 @@ See `comment-region'."
   (interactive "r\nP")
   (let ((comment-start (char-to-string octave-comment-char)))
     (comment-region beg end arg)))
-  
+
 (defun octave-uncomment-region (beg end &optional arg)
   "Uncomment each line in the region as Octave code."
   (interactive "r\nP")
@@ -621,7 +668,7 @@ level."
              (back-to-indentation)
              (setq icol (current-column))
              (let ((bot (point))
-                   (eol (octave-point 'eol)))
+                   (eol (line-end-position)))
                (while (< (point) eol)
                  (if (octave-not-in-string-or-comment-p)
                      (cond
@@ -648,7 +695,8 @@ level."
        ((and (looking-at octave-block-end-regexp)
             (octave-not-in-string-or-comment-p))
        (setq icol (- icol (octave-block-end-offset))))
-       ((looking-at "\\s<\\s<\\s<\\S<")
+       ((or (looking-at "\\s<\\s<\\s<\\S<")
+           (octave-before-magic-comment-p))
        (setq icol (list 0 icol)))
        ((looking-at "\\s<\\S<")
        (setq icol (list comment-column icol)))))
@@ -660,8 +708,14 @@ level."
     (* octave-block-offset
        (if (string-match (match-string 0) "switch") 2 1))))
 
+(defun octave-before-magic-comment-p ()
+  (save-excursion
+    (beginning-of-line)
+    (and (bobp) (looking-at "\\s-*#!"))))
+
 (defun octave-comment-indent ()
-  (if (looking-at "\\s<\\s<\\s<")
+  (if (or (looking-at "\\s<\\s<\\s<")
+         (octave-before-magic-comment-p))
       0
     (if (looking-at "\\s<\\s<")
        (calculate-octave-indent)
@@ -672,8 +726,8 @@ level."
 (defun octave-indent-for-comment ()
   "Maybe insert and indent an Octave comment.
 If there is no comment already on this line, create a code-level comment
-(started by two comment characters) if the line is empty, or an in-line
-comment (started by one comment character) otherwise. 
+\(started by two comment characters) if the line is empty, or an in-line
+comment (started by one comment character) otherwise.
 Point is left after the start of the comment which is properly aligned."
   (interactive)
   (indent-for-comment)
@@ -699,8 +753,8 @@ fixed goal column."
 (defun octave-indent-new-comment-line ()
   "Break Octave line at point, continuing comment if within one.
 If within code, insert `octave-continuation-string' before breaking the
-line.  If within a string, signal an error.   
-The new line is properly indented." 
+line.  If within a string, signal an error.
+The new line is properly indented."
   (interactive)
   (delete-horizontal-space)
   (cond
@@ -740,7 +794,7 @@ On success, return 0.  Otherwise, go as far as possible and return -1."
        (setq n (forward-line inc)))
       (setq arg (- arg inc)))
     n))
-      
+
 (defun octave-previous-code-line (&optional arg)
   "Move ARG lines of Octave code backward (forward if ARG is negative).
 Skips past all empty and comment lines.  Default for ARG is 1.
@@ -795,7 +849,7 @@ does not end in `...' or `\\' or is inside an open parenthesis list."
                          (looking-at octave-continuation-regexp)))
                    (zerop (forward-line 1)))))
     (end-of-line)))
-  
+
 (defun octave-scan-blocks (from count depth)
   "Scan from character number FROM by COUNT Octave begin-end blocks.
 Returns the character number of the position thus found.
@@ -949,7 +1003,7 @@ Signal an error if the keywords are incompatible."
                (buffer-substring-no-properties
                 (match-beginning 0) pos)
                pos (+ pos 1)
-               eol (octave-point 'eol)
+               eol (line-end-position)
                bb-arg
                (save-excursion
                  (save-restriction
@@ -1000,7 +1054,7 @@ An end of a function occurs right after the end keyword matching the
   (interactive "p")
   (or arg (setq arg 1))
   (and (< arg 0) (skip-syntax-backward "w"))
-  (and (> arg 0) (skip-syntax-forward "w"))  
+  (and (> arg 0) (skip-syntax-forward "w"))
   (if (octave-in-defun-p)
       (setq arg (- arg 1)))
   (if (= arg 0) (setq arg -1))
@@ -1023,28 +1077,74 @@ The function marked is the one containing point or following point."
          (exchange-point-and-mark))
       (goto-char pos)
       (message "No function to mark found"))))
-  
+
 \f
 ;;; Filling
 (defun octave-auto-fill ()
-  "Perform auto-fill in Octave mode."
-  (if (> (current-column) (current-fill-column))
-      (if (octave-in-comment-p)
-         (do-auto-fill)
-       (if (> (current-column) (current-fill-column))
-           (let ((fill-column (- (current-fill-column)
-                                 (length octave-continuation-string))))
-             (do-auto-fill)
-             (save-excursion
-               (forward-line -1)
-               (end-of-line)
-               (insert (concat " " octave-continuation-string)))
-             (indent-according-to-mode))))))
+  "Perform auto-fill in Octave mode.
+Returns nil if no feasible place to break the line could be found, and t
+otherwise."
+  (let (fc give-up)
+    (if (or (null (setq fc (current-fill-column)))
+           (save-excursion
+             (beginning-of-line)
+             (and auto-fill-inhibit-regexp
+                  (looking-at auto-fill-inhibit-regexp))))
+       nil                             ; Can't do anything
+      (if (and (not (octave-in-comment-p))
+              (> (current-column) fc))
+         (setq fc (- fc (+ (length octave-continuation-string) 1))))
+      (while (and (not give-up) (> (current-column) fc))
+       (let* ((opoint (point))
+              (fpoint
+               (save-excursion
+                 (move-to-column (+ fc 1))
+                 (skip-chars-backward "^ \t\n")
+                 ;; If we're at the beginning of the line, break after
+                 ;; the first word
+                 (if (bolp)
+                     (re-search-forward "[ \t]" opoint t))
+                 ;; If we're in a comment line, don't break after the
+                 ;; comment chars
+                 (if (save-excursion
+                       (skip-syntax-backward " <")
+                       (bolp))
+                     (re-search-forward "[ \t]" (line-end-position)
+                                        'move))
+                 ;; If we're not in a comment line and just ahead the
+                 ;; continuation string, don't break here.
+                 (if (and (not (octave-in-comment-p))
+                          (looking-at
+                           (concat "\\s-*"
+                                   (regexp-quote
+                                    octave-continuation-string)
+                                   "\\s-*$")))
+                     (end-of-line))
+                 (skip-chars-backward " \t")
+                 (point))))
+         (if (save-excursion
+               (goto-char fpoint)
+               (not (or (bolp) (eolp))))
+             (let ((prev-column (current-column)))
+               (if (save-excursion
+                     (skip-chars-backward " \t")
+                     (= (point) fpoint))
+                   (progn
+                     (octave-maybe-insert-continuation-string)
+                     (indent-new-comment-line t))
+                 (save-excursion
+                   (goto-char fpoint)
+                   (octave-maybe-insert-continuation-string)
+                   (indent-new-comment-line t)))
+               (if (>= (current-column) prev-column)
+                   (setq give-up t)))
+           (setq give-up t))))
+      (not give-up))))
 
 (defun octave-fill-paragraph (&optional arg)
  "Fill paragraph of Octave code, handling Octave comments."
  (interactive "P")
- (save-excursion 
+ (save-excursion
    (let ((end (progn (forward-paragraph) (point)))
         (beg (progn
                (forward-paragraph -1)
@@ -1076,7 +1176,7 @@ The function marked is the one containing point or following point."
                         (beginning-of-line)
                         (looking-at "^\\s-*\\s<+\\s-*$"))))
             ;; This is a nonempty comment line which does not extend
-            ;; past the fill column.  If it is followed by an nonempty
+            ;; past the fill column.  If it is followed by a nonempty
             ;; comment line with the same comment prefix, try to
             ;; combine them, and repeat this until either we reach the
             ;; fill-column or there is nothing more to combine.
@@ -1104,13 +1204,16 @@ The function marked is the one containing point or following point."
                 (delete-region (match-beginning 0) (match-end 0))
                 (fixup-whitespace)
                 (move-to-column cfc))))
+        ;; We might also try to combine continued code lines>  Perhaps
+        ;; some other time ...
         (skip-chars-forward "^ \t\n")
         (delete-horizontal-space)
         (if (or (< (current-column) cfc)
                 (and (= (current-column) cfc) (eolp)))
             (forward-line 1)
           (if (not (eolp)) (insert " "))
-          (octave-auto-fill))))
+          (or (octave-auto-fill)
+              (forward-line 1)))))
      t)))
 
 \f
@@ -1146,7 +1249,7 @@ variables."
           (let ((list (all-completions string octave-completion-alist))
                 (conf (current-window-configuration)))
             ;; Taken from comint.el
-            (message "Making completion list...")             
+            (message "Making completion list...")
             (with-output-to-temp-buffer "*Completions*"
               (display-completion-list list))
             (message "Hit space to flush")
@@ -1167,7 +1270,7 @@ variables."
                     (set-window-configuration conf)
                   (setq unread-command-events
                         (listify-key-sequence key))))))))))
-              
+
 \f
 ;;; Electric characters && friends
 (defun octave-reindent-then-newline-and-indent ()
@@ -1185,22 +1288,25 @@ If Abbrev mode is on, expand abbrevs first."
 
 (defun octave-electric-semi ()
   "Insert a semicolon in Octave mode.
-Always reindent the line.  Insert a newline if `octave-auto-newline' is
-non-nil."
+Maybe expand abbrevs and blink matching block open keywords.
+Reindent the line of `octave-auto-indent' is non-nil.
+Insert a newline if `octave-auto-newline' is non-nil."
   (interactive)
   (if (not (octave-not-in-string-or-comment-p))
       (insert ";")
     (if abbrev-mode (expand-abbrev))
     (if octave-blink-matching-block
        (octave-blink-matching-block-open))
-    (indent-according-to-mode)    
+    (if octave-auto-indent
+       (indent-according-to-mode))
     (insert ";")
     (if octave-auto-newline
        (newline-and-indent))))
 
 (defun octave-electric-space ()
   "Insert a space in Octave mode.
-Maybe expand abbrevs and blink matching block open keywords."
+Maybe expand abbrevs and blink matching block open keywords.
+Reindent the line of `octave-auto-indent' is non-nil."
   (interactive)
   (setq last-command-char ? )
   (if (not (octave-not-in-string-or-comment-p))
@@ -1210,9 +1316,10 @@ Maybe expand abbrevs and blink matching block open keywords."
     (if abbrev-mode (expand-abbrev))
     (if octave-blink-matching-block
        (octave-blink-matching-block-open))
-    (if (save-excursion
-         (skip-syntax-backward " ")
-         (not (bolp)))
+    (if (and octave-auto-indent
+            (save-excursion
+              (skip-syntax-backward " ")
+              (not (bolp))))
        (indent-according-to-mode))
     (self-insert-command 1)))
 
@@ -1227,9 +1334,12 @@ Note that all Octave mode abbrevs start with a grave accent."
       (self-insert-command 1)
     (let (c)
       (insert last-command-char)
-      (if (or (eq (setq c (read-event)) ??)
-             (eq c help-char))
-         (let ((abbrev-table-name-list '(octave-mode-abbrev-table)))
+      (if (if octave-xemacs-p
+             (or (eq (event-to-character (setq c (next-event))) ??)
+                 (eq (event-to-character c) help-char))
+           (or (eq (setq c (read-event)) ??)
+               (eq c help-char)))
+         (let ((abbrev-table-name-list '(octave-abbrev-table)))
            (list-abbrevs))
        (setq unread-command-events (list c))))))
 
@@ -1259,21 +1369,21 @@ entered without parens)."
     (indent-according-to-mode)
     (newline 2)
     (insert prefix "usage: " string)
-    (reindent-then-newline-and-indent)    
+    (reindent-then-newline-and-indent)
     (insert prefix)
-    (reindent-then-newline-and-indent)    
+    (reindent-then-newline-and-indent)
     (insert prefix)
     (indent-according-to-mode)
     (save-excursion
       (newline 2)
       (insert "endfunction")
       (indent-according-to-mode))))
-             
+
 \f
 ;;; Menu
 (defun octave-add-octave-menu ()
   "Adds the `Octave' menu to the menu bar in Octave mode."
-  (require 'easymenu)  
+  (require 'easymenu)
   (easy-menu-define octave-mode-menu-map octave-mode-map
                    "Menu keymap for Octave mode." octave-mode-menu)
   (easy-menu-add octave-mode-menu-map octave-mode-map))
@@ -1307,7 +1417,7 @@ entered without parens)."
 (defun octave-send-region (beg end)
   "Send current region to the inferior Octave process."
   (interactive "r")
-  (inferior-octave t)  
+  (inferior-octave t)
   (let ((proc inferior-octave-process)
        (string (buffer-substring-no-properties beg end))
        line)
@@ -1335,7 +1445,7 @@ entered without parens)."
       (display-buffer inferior-octave-buffer)))
 
 (defun octave-send-block ()
-  "Send current Octave block to the inferior Octave process."  
+  "Send current Octave block to the inferior Octave process."
   (interactive)
   (save-excursion
     (octave-mark-block)
@@ -1374,7 +1484,7 @@ code line."
        (print-escape-newlines nil)
        (opoint (point)))
     (terpri)
-    (prin1    
+    (prin1
      (save-excursion
        (forward-sexp -1)
        (inferior-octave-send-list-and-digest
@@ -1394,6 +1504,7 @@ code line."
     octave-maintainer-address
     (concat "Emacs version " emacs-version)
     (list
+     'octave-auto-indent
      'octave-auto-newline
      'octave-blink-matching-block
      'octave-block-offset
@@ -1410,4 +1521,5 @@ code line."
 
 (provide 'octave-mod)
 
+;;; arch-tag: 05f1ce09-be87-4c00-803e-4919ffa26c23
 ;;; octave-mod.el ends here