]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/idlw-shell.el
(ada-prj-display-page): Use `mapc' rather than `mapcar'.
[gnu-emacs] / lisp / progmodes / idlw-shell.el
index 787b9249ad75df45eff8f176c23cef0b53ff0c1c..f903d490565df844d681aba55ce4232b84a6b349 100644 (file)
@@ -1,18 +1,20 @@
 ;; idlw-shell.el --- run IDL as an inferior process of Emacs.
 ;; idlw-shell.el --- run IDL as an inferior process of Emacs.
-;; Copyright (c) 1999,2000,2001,2002,2003,2004 Free Software Foundation
+
+;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+;;    Free Software Foundation, Inc.
 
 ;; Authors: J.D. Smith <jdsmith@as.arizona.edu>
 ;;          Carsten Dominik <dominik@astro.uva.nl>
 ;;          Chris Chase <chase@att.com>
 ;; Maintainer: J.D. Smith <jdsmith@as.arizona.edu>
 
 ;; Authors: J.D. Smith <jdsmith@as.arizona.edu>
 ;;          Carsten Dominik <dominik@astro.uva.nl>
 ;;          Chris Chase <chase@att.com>
 ;; Maintainer: J.D. Smith <jdsmith@as.arizona.edu>
-;; Version: 5.5
+;; Version: 6.1_em22
 ;; Keywords: processes
 
 ;; This file is part of GNU Emacs.
 
 ;; GNU Emacs is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
 ;; Keywords: processes
 
 ;; This file is part of GNU Emacs.
 
 ;; GNU Emacs is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 
 ;; 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
 
 ;; 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.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 ;;
 ;; This mode is for IDL version 5 or later.  It should work on
 ;; Emacs>20.3 or XEmacs>20.4.
 ;;
 
 ;;; Commentary:
 ;;
 ;; This mode is for IDL version 5 or later.  It should work on
 ;; Emacs>20.3 or XEmacs>20.4.
 ;;
-;; Runs IDL as an inferior process of Emacs, much like the emacs
+;; Runs IDL as an inferior process of Emacs, much like the Emacs
 ;; `shell' or `telnet' commands.  Provides command history and
 ;; searching.  Provides debugging commands available in buffers
 ;; visiting IDL procedure files, e.g., breakpoint setting, stepping,
 ;; `shell' or `telnet' commands.  Provides command history and
 ;; searching.  Provides debugging commands available in buffers
 ;; visiting IDL procedure files, e.g., breakpoint setting, stepping,
   :prefix "idlwave-shell"
   :group 'idlwave)
 
   :prefix "idlwave-shell"
   :group 'idlwave)
 
-(defcustom idlwave-shell-prompt-pattern "^ ?IDL> "
+(defcustom idlwave-shell-prompt-pattern "^\r? ?IDL> "
   "*Regexp to match IDL prompt at beginning of a line. 
   "*Regexp to match IDL prompt at beginning of a line. 
-For example, \"^IDL> \" or \"^WAVE> \". 
-The \"^\" means beginning of line, and is required.
+For example, \"^\r?IDL> \" or \"^\r?WAVE> \". 
+The \"^\r?\" is needed, to indicate the beginning of the line, with
+optional return character (which IDL seems to output randomly).
 This variable is used to initialize `comint-prompt-regexp' in the 
 process buffer.
 
 This variable is used to initialize `comint-prompt-regexp' in the 
 process buffer.
 
@@ -136,6 +139,11 @@ process output is made by surrounding this name with `*'s."
 
 ;; (defcustom idlwave-shell-automatic-start...)  See idlwave.el
 
 
 ;; (defcustom idlwave-shell-automatic-start...)  See idlwave.el
 
+(defcustom idlwave-shell-use-dedicated-window nil
+  "*Non-nil means, never replace the shell frame with another buffer."
+  :group 'idlwave-shell-general-setup
+  :type 'boolean) 
+
 (defcustom idlwave-shell-use-dedicated-frame nil
   "*Non-nil means, IDLWAVE should use a special frame to display shell buffer."
   :group 'idlwave-shell-general-setup
 (defcustom idlwave-shell-use-dedicated-frame nil
   "*Non-nil means, IDLWAVE should use a special frame to display shell buffer."
   :group 'idlwave-shell-general-setup
@@ -245,7 +253,7 @@ to set this option to nil."
   :group 'idlwave-shell-general-setup
   :type 'boolean)
 
   :group 'idlwave-shell-general-setup
   :type 'boolean)
 
-(defcustom idlwave-shell-file-name-chars "~/A-Za-z0-9+:_.$#%={}\\-"
+(defcustom idlwave-shell-file-name-chars "~/A-Za-z0-9+:_.$#%={}\\- "
   "The characters allowed in file names, as a string.
 Used for file name completion. Must not contain `'', `,' and `\"'
 because these are used as separators by IDL."
   "The characters allowed in file names, as a string.
 Used for file name completion. Must not contain `'', `,' and `\"'
 because these are used as separators by IDL."
@@ -311,8 +319,15 @@ the copious shell traffic to be displayed."
               (const :tag "All debug and stepping commands"       debug)
               (const :tag "Close, window, retall, etc. commands"  misc))))
 
               (const :tag "All debug and stepping commands"       debug)
               (const :tag "Close, window, retall, etc. commands"  misc))))
 
+(defcustom idlwave-shell-max-print-length 200
+  "Maximum number of array elements to print when examining."
+  :group 'idlwave-shell-command-setup
+  :type 'integer)
+
 (defcustom idlwave-shell-examine-alist 
 (defcustom idlwave-shell-examine-alist 
-  '(("Print"           . "print,___")
+  `(("Print"           . ,(concat "idlwave_print_safe,___," 
+                                  (number-to-string 
+                                   idlwave-shell-max-print-length)))
     ("Help"            . "help,___")
     ("Structure Help"          . "help,___,/STRUCTURE")
     ("Dimensions"      . "print,size(___,/DIMENSIONS)")
     ("Help"            . "help,___")
     ("Structure Help"          . "help,___,/STRUCTURE")
     ("Dimensions"      . "print,size(___,/DIMENSIONS)")
@@ -320,6 +335,7 @@ the copious shell traffic to be displayed."
     ("N_Elements"      . "print,n_elements(___)")
     ("All Size Info"   . "help,(__IWsz__=size(___,/STRUCTURE)),/STRUCTURE & print,__IWsz__.DIMENSIONS")
     ("Ptr Valid"       . "print,ptr_valid(___)")
     ("N_Elements"      . "print,n_elements(___)")
     ("All Size Info"   . "help,(__IWsz__=size(___,/STRUCTURE)),/STRUCTURE & print,__IWsz__.DIMENSIONS")
     ("Ptr Valid"       . "print,ptr_valid(___)")
+    ("Arg Present"      . "print,arg_present(___)")
     ("Widget Valid"     . "print,widget_info(___,/VALID)")
     ("Widget Geometry"  . "help,widget_info(___,/GEOMETRY)"))
   "Alist of special examine commands for popup selection.  
     ("Widget Valid"     . "print,widget_info(___,/VALID)")
     ("Widget Geometry"  . "help,widget_info(___,/GEOMETRY)"))
   "Alist of special examine commands for popup selection.  
@@ -344,7 +360,8 @@ expression being examined."
 (defcustom idlwave-shell-comint-settings
   '((comint-scroll-to-bottom-on-input . t)
     (comint-scroll-to-bottom-on-output . t)
 (defcustom idlwave-shell-comint-settings
   '((comint-scroll-to-bottom-on-input . t)
     (comint-scroll-to-bottom-on-output . t)
-    (comint-scroll-show-maximum-output . nil))
+    (comint-scroll-show-maximum-output . nil)
+    (comint-prompt-read-only . t))
 
   "Alist of special settings for the comint variables in the IDLWAVE Shell.
 Each entry is a cons cell with the name of a variable and a value.
 
   "Alist of special settings for the comint variables in the IDLWAVE Shell.
 Each entry is a cons cell with the name of a variable and a value.
@@ -428,6 +445,16 @@ end"
          (regexp :tag "Char-mode regexp")
          (regexp :tag "Line-mode regexp")))
 
          (regexp :tag "Char-mode regexp")
          (regexp :tag "Line-mode regexp")))
 
+(defcustom idlwave-shell-breakpoint-popup-menu t
+  "*If non-nil, provide a menu on mouse-3 on breakpoint lines, and
+popup help text on the line."
+  :group 'idlwave-shell-command-setup
+  :type 'boolean)
+
+(defcustom idlwave-shell-reset-no-prompt nil
+  "If non-nil, skip the yes/no prompt when resetting the IDL session."
+  :group 'idlwave-shell-command-setup
+  :type 'boolean)
 
 ;; Breakpoint Overlays etc
 (defgroup idlwave-shell-highlighting-and-faces nil
 
 ;; Breakpoint Overlays etc
 (defgroup idlwave-shell-highlighting-and-faces nil
@@ -437,7 +464,7 @@ end"
 
 (defcustom idlwave-shell-mark-stop-line t
   "*Non-nil means, mark the source code line where IDL is currently stopped.
 
 (defcustom idlwave-shell-mark-stop-line t
   "*Non-nil means, mark the source code line where IDL is currently stopped.
-Value decides about the method which is used to mark the line.  Legal values
+Value decides about the method which is used to mark the line.  Valid values
 are:
 
 nil       Do not mark the line
 are:
 
 nil       Do not mark the line
@@ -480,11 +507,11 @@ line where IDL is stopped.  See also `idlwave-shell-mark-stop-line'."
 
 (defcustom idlwave-shell-electric-stop-line-face 
   (prog1
 
 (defcustom idlwave-shell-electric-stop-line-face 
   (prog1
-      (copy-face 'modeline 'idlwave-shell-electric-stop-line-face)
-    (set-face-background 'idlwave-shell-electric-stop-line-face 
+      (copy-face 'modeline 'idlwave-shell-electric-stop-line)
+    (set-face-background 'idlwave-shell-electric-stop-line 
                         idlwave-shell-electric-stop-color)
     (condition-case nil
                         idlwave-shell-electric-stop-color)
     (condition-case nil
-       (set-face-foreground 'idlwave-shell-electric-stop-line-face nil)
+       (set-face-foreground 'idlwave-shell-electric-stop-line nil)
       (error nil)))
   "*The face for `idlwave-shell-stop-line-overlay' when in electric debug mode.
 Allows you to choose the font, color and other properties for the line
       (error nil)))
   "*The face for `idlwave-shell-stop-line-overlay' when in electric debug mode.
 Allows you to choose the font, color and other properties for the line
@@ -494,7 +521,7 @@ where IDL is stopped, when in Electric Debug Mode."
 
 (defcustom idlwave-shell-mark-breakpoints t
   "*Non-nil means, mark breakpoints in the source files.
 
 (defcustom idlwave-shell-mark-breakpoints t
   "*Non-nil means, mark breakpoints in the source files.
-Legal values are:
+Valid values are:
 nil        Do not mark breakpoints.
 'face      Highlight line with `idlwave-shell-breakpoint-face'.
 'glyph     Red dot at the beginning of line.  If the display does not
 nil        Do not mark breakpoints.
 'face      Highlight line with `idlwave-shell-breakpoint-face'.
 'glyph     Red dot at the beginning of line.  If the display does not
@@ -510,40 +537,40 @@ t          Glyph when possible, otherwise face (same effect as 'glyph)."
 (defvar idlwave-shell-use-breakpoint-glyph t
   "Obsolete variable.  See `idlwave-shell-mark-breakpoints.")
 
 (defvar idlwave-shell-use-breakpoint-glyph t
   "Obsolete variable.  See `idlwave-shell-mark-breakpoints.")
 
-(defcustom idlwave-shell-breakpoint-face 'idlwave-shell-bp-face
+(defcustom idlwave-shell-breakpoint-face 'idlwave-shell-bp
   "*The face for breakpoint lines in the source code.
 Allows you to choose the font, color and other properties for
 lines which have a breakpoint.  See also `idlwave-shell-mark-breakpoints'."
   :group 'idlwave-shell-highlighting-and-faces
   :type 'symbol)
 
   "*The face for breakpoint lines in the source code.
 Allows you to choose the font, color and other properties for
 lines which have a breakpoint.  See also `idlwave-shell-mark-breakpoints'."
   :group 'idlwave-shell-highlighting-and-faces
   :type 'symbol)
 
-(if idlwave-shell-have-new-custom
-    ;; We have the new customize - use it to define a customizable face
-    (defface idlwave-shell-bp-face
-      '((((class color)) (:foreground "Black" :background "Pink"))
-       (t (:underline t)))
-      "Face for highlighting lines with breakpoints."
-      :group 'idlwave-shell-highlighting-and-faces)
-  ;; Just copy the underline face to be on the safe side.
-  (copy-face 'underline 'idlwave-shell-bp-face))
+(if (not idlwave-shell-have-new-custom)
+    ;; Just copy the underline face to be on the safe side.
+    (copy-face 'underline 'idlwave-shell-bp)
+  ;; We have the new customize - use it to define a customizable face
+  (defface idlwave-shell-bp
+    '((((class color)) (:foreground "Black" :background "Pink"))
+      (t (:underline t)))
+    "Face for highlighting lines with breakpoints."
+    :group 'idlwave-shell-highlighting-and-faces))
 
 (defcustom idlwave-shell-disabled-breakpoint-face 
 
 (defcustom idlwave-shell-disabled-breakpoint-face 
-  'idlwave-shell-disabled-bp-face
+  'idlwave-shell-disabled-bp
   "*The face for disabled breakpoint lines in the source code.
 Allows you to choose the font, color and other properties for
 lines which have a breakpoint.  See also `idlwave-shell-mark-breakpoints'."
   :group 'idlwave-shell-highlighting-and-faces
   :type 'symbol)
 
   "*The face for disabled breakpoint lines in the source code.
 Allows you to choose the font, color and other properties for
 lines which have a breakpoint.  See also `idlwave-shell-mark-breakpoints'."
   :group 'idlwave-shell-highlighting-and-faces
   :type 'symbol)
 
-(if idlwave-shell-have-new-custom
-    ;; We have the new customize - use it to define a customizable face
-    (defface idlwave-shell-disabled-bp-face
-      '((((class color)) (:foreground "Black" :background "gray"))
-       (t (:underline t)))
-      "Face for highlighting lines with breakpoints."
-      :group 'idlwave-shell-highlighting-and-faces)
-  ;; Just copy the underline face to be on the safe side.
-  (copy-face 'underline 'idlwave-shell-disabled-bp-face))
+(if (not idlwave-shell-have-new-custom)
+    ;; Just copy the underline face to be on the safe side.
+    (copy-face 'underline 'idlwave-shell-disabled-bp)
+  ;; We have the new customize - use it to define a customizable face
+  (defface idlwave-shell-disabled-bp
+    '((((class color)) (:foreground "Black" :background "gray"))
+      (t (:underline t)))
+    "Face for highlighting lines with breakpoints."
+    :group 'idlwave-shell-highlighting-and-faces))
 
 
 (defcustom idlwave-shell-expression-face 'secondary-selection
 
 
 (defcustom idlwave-shell-expression-face 'secondary-selection
@@ -645,7 +672,7 @@ the directory stack.")
   "The overlay for where IDL is currently stopped.")
 (defvar idlwave-shell-is-stopped nil)
 (defvar idlwave-shell-expression-overlay nil
   "The overlay for where IDL is currently stopped.")
 (defvar idlwave-shell-is-stopped nil)
 (defvar idlwave-shell-expression-overlay nil
-  "The overlay for where IDL is currently stopped.")
+  "The overlay for the examined expression.")
 (defvar idlwave-shell-output-overlay nil
   "The overlay for the last IDL output.")
 
 (defvar idlwave-shell-output-overlay nil
   "The overlay for the last IDL output.")
 
@@ -693,10 +720,21 @@ the directory stack.")
 (setq idlwave-shell-expression-overlay (make-overlay 1 1))
 (overlay-put idlwave-shell-expression-overlay
             'face idlwave-shell-expression-face)
 (setq idlwave-shell-expression-overlay (make-overlay 1 1))
 (overlay-put idlwave-shell-expression-overlay
             'face idlwave-shell-expression-face)
+(overlay-put idlwave-shell-expression-overlay
+            'priority 1)
 (setq idlwave-shell-output-overlay (make-overlay 1 1))
 (overlay-put idlwave-shell-output-overlay
             'face idlwave-shell-output-face)
 
 (setq idlwave-shell-output-overlay (make-overlay 1 1))
 (overlay-put idlwave-shell-output-overlay
             'face idlwave-shell-output-face)
 
+(copy-face idlwave-shell-stop-line-face 
+          'idlwave-shell-pending-stop)
+(copy-face idlwave-shell-electric-stop-line-face 
+          'idlwave-shell-pending-electric-stop)
+(set-face-background 'idlwave-shell-pending-stop "gray70")
+(set-face-background 'idlwave-shell-pending-electric-stop "gray70")
+
+
+
 (defvar idlwave-shell-bp-query "help,/breakpoints"
   "Command to obtain list of breakpoints")
 
 (defvar idlwave-shell-bp-query "help,/breakpoints"
   "Command to obtain list of breakpoints")
 
@@ -742,9 +780,6 @@ with `*'s."
 (defvar idlwave-shell-ready nil
   "If non-nil can send next command to IDL process.")
 
 (defvar idlwave-shell-ready nil
   "If non-nil can send next command to IDL process.")
 
-(defvar idlwave-shell-wait-for-output nil
-  "Whether to wait for output to accumulate.")
-
 ;;; The following are the types of messages we attempt to catch to
 ;;; resync our idea of where IDL execution currently is.
 ;;; 
 ;;; The following are the types of messages we attempt to catch to
 ;;; resync our idea of where IDL execution currently is.
 ;;; 
@@ -819,6 +854,7 @@ IDL has currently stepped.")
   ?          Help on expression near point or in region ([C-u ?]).
   x          Examine expression near point or in region ([C-u x]) with 
              letter completion of the examine type.
   ?          Help on expression near point or in region ([C-u ?]).
   x          Examine expression near point or in region ([C-u x]) with 
              letter completion of the examine type.
+  e          Prompt for an expression to print.
 
  Miscellaneous:
   q         Quit - end debugging session and return to the Shell's main level.
 
  Miscellaneous:
   q         Quit - end debugging session and return to the Shell's main level.
@@ -988,15 +1024,15 @@ IDL has currently stepped.")
   (set-marker comint-last-input-end (point))
   (setq idlwave-idlwave_routine_info-compiled nil)
   (setq idlwave-shell-ready nil)
   (set-marker comint-last-input-end (point))
   (setq idlwave-idlwave_routine_info-compiled nil)
   (setq idlwave-shell-ready nil)
-  (setq idlwave-shell-wait-for-output nil)
   (setq idlwave-shell-bp-alist nil)
   (idlwave-shell-update-bp-overlays) ; Throw away old overlays
   (setq idlwave-shell-bp-alist nil)
   (idlwave-shell-update-bp-overlays) ; Throw away old overlays
-  (setq idlwave-shell-sources-alist nil)
+  (setq idlwave-shell-post-command-hook nil ;clean up any old stuff
+       idlwave-shell-sources-alist nil)
   (setq idlwave-shell-default-directory default-directory)
   (setq idlwave-shell-hide-output nil)
 
   ;; NB: `make-local-hook' needed for older/alternative Emacs compatibility
   (setq idlwave-shell-default-directory default-directory)
   (setq idlwave-shell-hide-output nil)
 
   ;; NB: `make-local-hook' needed for older/alternative Emacs compatibility
-  ;;(make-local-hook 'kill-buffer-hook)
+  ;; (make-local-hook 'kill-buffer-hook)
   (add-hook 'kill-buffer-hook 'idlwave-shell-kill-shell-buffer-confirm
            nil 'local)
   (add-hook 'kill-buffer-hook 'idlwave-shell-delete-temp-files nil 'local)
   (add-hook 'kill-buffer-hook 'idlwave-shell-kill-shell-buffer-confirm
            nil 'local)
   (add-hook 'kill-buffer-hook 'idlwave-shell-delete-temp-files nil 'local)
@@ -1040,7 +1076,7 @@ IDL has currently stepped.")
   (setq abbrev-mode t)
 
   ;; NB: `make-local-hook' needed for older/alternative Emacs compatibility
   (setq abbrev-mode t)
 
   ;; NB: `make-local-hook' needed for older/alternative Emacs compatibility
-  ;;(make-local-hook 'post-command-hook)
+  ;; make-local-hook 'post-command-hook)
   (add-hook 'post-command-hook 'idlwave-command-hook nil t)
 
   ;; Read the command history?
   (add-hook 'post-command-hook 'idlwave-command-hook nil t)
 
   ;; Read the command history?
@@ -1055,31 +1091,32 @@ IDL has currently stepped.")
   (set (make-local-variable 'tool-bar-map) nil)
 
   ;; Run the hooks.
   (set (make-local-variable 'tool-bar-map) nil)
 
   ;; Run the hooks.
-  (run-hooks 'idlwave-shell-mode-hook)
+  (run-mode-hooks 'idlwave-shell-mode-hook)
   (idlwave-shell-send-command idlwave-shell-initial-commands nil 'hide)
   ;; Turn off IDL's ^d interpreting, and define a system
   ;; variable which knows the version of IDLWAVE
   (idlwave-shell-send-command 
   (idlwave-shell-send-command idlwave-shell-initial-commands nil 'hide)
   ;; Turn off IDL's ^d interpreting, and define a system
   ;; variable which knows the version of IDLWAVE
   (idlwave-shell-send-command 
-   (format "defsysv,'!idlwave_version','%s',1" 
-          idlwave-mode-version)
+   (format "defsysv,'!idlwave_version','%s',1" idlwave-mode-version)
    nil 'hide)
    nil 'hide)
-  ;; Get the paths if they weren't read in from file
-  (if (and (not idlwave-path-alist)
-          (or (not (stringp idlwave-system-directory))
-              (eq (length idlwave-system-directory) 0)))
-      (idlwave-shell-send-command idlwave-shell-path-query
-                                 'idlwave-shell-get-path-info
-                                 'hide)))
+  ;; Read the paths, and save if they changed
+  (idlwave-shell-send-command idlwave-shell-path-query
+                             'idlwave-shell-get-path-info
+                             'hide))
 
 
+(defvar idlwave-system-directory)
 (defun idlwave-shell-get-path-info (&optional no-write)
   "Get the path lists, writing to file unless NO-WRITE is set."
   (let* ((rpl (idlwave-shell-path-filter))
         (sysdir (car rpl))
         (dirs (cdr rpl))
 (defun idlwave-shell-get-path-info (&optional no-write)
   "Get the path lists, writing to file unless NO-WRITE is set."
   (let* ((rpl (idlwave-shell-path-filter))
         (sysdir (car rpl))
         (dirs (cdr rpl))
-        (old-path-alist idlwave-path-alist))
+        (old-path-alist idlwave-path-alist)
+        (old-sys-dir idlwave-system-directory)
+        path-changed sysdir-changed)
     (when sysdir
       (setq idlwave-system-directory sysdir)
     (when sysdir
       (setq idlwave-system-directory sysdir)
-      (put 'idlwave-system-directory 'from-shell t))
+      (if (setq sysdir-changed 
+               (not (string= idlwave-system-directory old-sys-dir)))
+         (put 'idlwave-system-directory 'from-shell t)))
     ;; Preserve any existing flags
     (setq idlwave-path-alist 
          (mapcar (lambda (x)
     ;; Preserve any existing flags
     (setq idlwave-path-alist 
          (mapcar (lambda (x)
@@ -1088,11 +1125,13 @@ IDL has currently stepped.")
                          (cons x (cdr old-entry))
                        (list x))))
                  dirs))
                          (cons x (cdr old-entry))
                        (list x))))
                  dirs))
-    (put 'idlwave-path-alist 'from-shell t)
+    (if (setq path-changed (not (equal idlwave-path-alist old-path-alist)))
+       (put 'idlwave-path-alist 'from-shell t))
     (if idlwave-path-alist 
     (if idlwave-path-alist 
-       (if (and idlwave-auto-write-paths
-                (not idlwave-library-path)
-                (not no-write) )
+       (if (and (not no-write)
+                idlwave-auto-write-paths
+                (or sysdir-changed path-changed)
+                (not idlwave-library-path))
            (idlwave-write-paths))
       ;; Fall back
       (setq idlwave-path-alist old-path-alist))))
            (idlwave-write-paths))
       ;; Fall back
       (setq idlwave-path-alist old-path-alist))))
@@ -1201,12 +1240,14 @@ See also the variable `idlwave-shell-prompt-pattern'.
          (current-window (selected-window)))
       (select-window window)
       (goto-char (point-max))
          (current-window (selected-window)))
       (select-window window)
       (goto-char (point-max))
+      (if idlwave-shell-use-dedicated-window
+         (set-window-dedicated-p window t))
       (select-window current-window)
       (if idlwave-shell-ready
          (raise-frame (window-frame window)))
       (if (eq (selected-frame) (window-frame window))
          (select-window window))))
       (select-window current-window)
       (if idlwave-shell-ready
          (raise-frame (window-frame window)))
       (if (eq (selected-frame) (window-frame window))
          (select-window window))))
-  ;; Save the paths at the end
+  ;; Save the paths at the end, if they are from the Shell and new.
   (add-hook 'idlwave-shell-sentinel-hook 
            (lambda ()
              (if (and 
   (add-hook 'idlwave-shell-sentinel-hook 
            (lambda ()
              (if (and 
@@ -1263,7 +1304,7 @@ output to complete and the next prompt to arrive before returning
 \(useful if you need an answer now\). IDL is considered ready if the
 prompt is present and if `idlwave-shell-ready' is non-nil.  
 
 \(useful if you need an answer now\). IDL is considered ready if the
 prompt is present and if `idlwave-shell-ready' is non-nil.  
 
-If SHOW-IF-ERROR is non-nil, show the output it it contains an error
+If SHOW-IF-ERROR is non-nil, show the output if it contains an error
 message, independent of what HIDE is set to."
 
 ;  (setq hide nil)  ;  FIXME: turn this on for debugging only
 message, independent of what HIDE is set to."
 
 ;  (setq hide nil)  ;  FIXME: turn this on for debugging only
@@ -1271,7 +1312,7 @@ message, independent of what HIDE is set to."
 ;      (progn
 ;      (message "SENDING Pending commands: %s" 
 ;               (prin1-to-string idlwave-shell-pending-commands)))
 ;      (progn
 ;      (message "SENDING Pending commands: %s" 
 ;               (prin1-to-string idlwave-shell-pending-commands)))
-;    (message "SENDING %s|||%s" cmd pcmd))
+;  (message "SENDING %s|||%s" cmd pcmd))
   (if (and (symbolp idlwave-shell-show-commands) 
           (eq idlwave-shell-show-commands 'everything))
       (setq hide nil))
   (if (and (symbolp idlwave-shell-show-commands) 
           (eq idlwave-shell-show-commands 'everything))
       (setq hide nil))
@@ -1335,9 +1376,11 @@ message, independent of what HIDE is set to."
              (set-marker comint-last-input-end (point))
              (comint-simple-send proc cmd)
              (setq idlwave-shell-ready nil)
              (set-marker comint-last-input-end (point))
              (comint-simple-send proc cmd)
              (setq idlwave-shell-ready nil)
-             (when (equal preempt 'wait) ; Get all the output at once
-               (setq idlwave-shell-wait-for-output t)
-               (accept-process-output proc))))
+             (if (equal preempt 'wait) ; Get all the output at once
+               (while (not idlwave-shell-ready)
+                 (when (not (accept-process-output proc 6)) ; long wait
+                   (setq idlwave-shell-pending-commands nil)
+                   (error "Process timed out"))))))
        (goto-char save-point))
       (set-buffer save-buffer))))
 
        (goto-char save-point))
       (set-buffer save-buffer))))
 
@@ -1430,11 +1473,7 @@ Otherwise just move the line.  Move down unless UP is non-nil."
     (if (eq t idlwave-shell-arrows-do-history) (goto-char proc-pos))
     (if (and idlwave-shell-arrows-do-history
             (>= (1+ (save-excursion (end-of-line) (point))) proc-pos))
     (if (eq t idlwave-shell-arrows-do-history) (goto-char proc-pos))
     (if (and idlwave-shell-arrows-do-history
             (>= (1+ (save-excursion (end-of-line) (point))) proc-pos))
-       (progn
-         ;;(goto-char proc-pos)
-         (goto-char (point-max))
-         ;;(and (not (eolp)) (kill-line nil))
-         (comint-previous-input arg))
+       (comint-previous-input arg)
       (previous-line arg))))
 
 (defun idlwave-shell-up-or-history (&optional arg)
       (previous-line arg))))
 
 (defun idlwave-shell-up-or-history (&optional arg)
@@ -1483,120 +1522,111 @@ error messages, etc."
 When the IDL prompt is received executes `idlwave-shell-post-command-hook'
 and then calls `idlwave-shell-send-command' for any pending commands."
   ;; We no longer do the cleanup here - this is done by the process sentinel
 When the IDL prompt is received executes `idlwave-shell-post-command-hook'
 and then calls `idlwave-shell-send-command' for any pending commands."
   ;; We no longer do the cleanup here - this is done by the process sentinel
-  (when (eq (process-status idlwave-shell-process-name) 'run)
-    ;; OK, process is still running, so we can use it.
-    (let ((data (match-data)) p full-output)
-      (unwind-protect
-          (progn
-           ;; Ring the bell if necessary
-           (while (setq p (string-match "\C-G" string))
-             (ding)
-             (aset string p ?\C-j ))
-            (if idlwave-shell-hide-output
-               (save-excursion
-                 (while (setq p (string-match "\C-M" string))
-                   (aset string p ?\  ))
-                 (set-buffer
-                  (get-buffer-create idlwave-shell-hidden-output-buffer))
-                 (goto-char (point-max))
-                 (insert string))
-             (idlwave-shell-comint-filter proc string))
-            ;; Watch for magic - need to accumulate the current line
-            ;; since it may not be sent all at once.
-            (if (string-match "\n" string)
-               (progn
-                 (if idlwave-shell-use-input-mode-magic
-                     (idlwave-shell-input-mode-magic
-                      (concat idlwave-shell-accumulation string)))
-                 (setq idlwave-shell-accumulation
-                       (substring string 
-                                  (progn (string-match "\\(.*[\n\r]+\\)*" 
-                                                       string)
-                                         (match-end 0)))))
-              (setq idlwave-shell-accumulation
-                    (concat idlwave-shell-accumulation string)))
+  (if (eq (process-status idlwave-shell-process-name) 'run)
+      ;; OK, process is still running, so we can use it.
+      (let ((data (match-data)) p full-output)
+       (unwind-protect
+           (progn
+             ;; Ring the bell if necessary
+             (while (setq p (string-match "\C-G" string))
+               (ding)
+               (aset string p ?\C-j ))
+             (if idlwave-shell-hide-output
+                 (save-excursion
+                   (while (setq p (string-match "\C-M" string))
+                     (aset string p ?\  ))
+                   (set-buffer
+                    (get-buffer-create idlwave-shell-hidden-output-buffer))
+                   (goto-char (point-max))
+                   (insert string))
+               (idlwave-shell-comint-filter proc string))
+             ;; Watch for magic - need to accumulate the current line
+             ;; since it may not be sent all at once.
+             (if (string-match "\n" string)
+                 (progn
+                   (if idlwave-shell-use-input-mode-magic
+                       (idlwave-shell-input-mode-magic
+                        (concat idlwave-shell-accumulation string)))
+                   (setq idlwave-shell-accumulation
+                         (substring string 
+                                    (progn (string-match "\\(.*[\n\r]+\\)*" 
+                                                         string)
+                                           (match-end 0)))))
+               (setq idlwave-shell-accumulation
+                     (concat idlwave-shell-accumulation string)))
            
            
 ;;; Test/Debug code
            
            
 ;;; Test/Debug code
-;            (save-excursion (set-buffer
-;                             (get-buffer-create "*idlwave-shell-output*"))
-;                            (goto-char (point-max))
-;                            (insert "\nSTRING===>\n" string "\n<====\n"))
+             ;(with-current-buffer
+             ;   (get-buffer-create "*idlwave-shell-output*")
+             ; (goto-char (point-max))
+             ; (insert "\nReceived STRING\n===>\n" string "\n<====\n"))
            
            
-           ;; Check for prompt in current accumulating output
-           (if (setq idlwave-shell-ready
-                     (string-match idlwave-shell-prompt-pattern
-                                   idlwave-shell-accumulation))
-               (progn
-                 ;; Gather the command output
+             ;; Check for prompt in current accumulating output
+             (when (setq idlwave-shell-ready
+                         (string-match idlwave-shell-prompt-pattern
+                                       idlwave-shell-accumulation))
+               ;; Gather the command output
+               (if idlwave-shell-hide-output
+                   (save-excursion
+                     (set-buffer idlwave-shell-hidden-output-buffer)
+                     (setq full-output (buffer-string))
+                     (goto-char (point-max))
+                     (re-search-backward idlwave-shell-prompt-pattern nil t)
+                     (goto-char (match-end 0))
+                     (setq idlwave-shell-command-output
+                           (buffer-substring-no-properties 
+                            (point-min) (point)))
+                     (delete-region (point-min) (point)))
+                 (setq idlwave-shell-command-output
+                       (with-current-buffer (process-buffer proc)
+                       (buffer-substring-no-properties
+                        (save-excursion
+                          (goto-char (process-mark proc))
+                          (forward-line 0) ; Emacs 21 (beginning-of-line nil)
+                          (point))
+                        comint-last-input-end))))
+
+               ;; Scan for state and do post commands - bracket
+               ;; them with idlwave-shell-ready=nil since they may
+               ;; call idlwave-shell-send-command themselves.
+               (let ((idlwave-shell-ready nil))
+                 (idlwave-shell-scan-for-state)
+                 ;; Show the output in the shell if it contains an error
                  (if idlwave-shell-hide-output
                  (if idlwave-shell-hide-output
-                     (save-excursion
-                       (set-buffer idlwave-shell-hidden-output-buffer)
-                       (setq full-output (buffer-string))
-                       (goto-char (point-max))
-                       (re-search-backward idlwave-shell-prompt-pattern nil t)
-                       (goto-char (match-end 0))
-                       (setq idlwave-shell-command-output
-                             (buffer-substring (point-min) (point)))
-                       (delete-region (point-min) (point)))
-                    (setq idlwave-shell-command-output
-                         (with-current-buffer (process-buffer proc)
-                           (buffer-substring
-                            (save-excursion
-                              (goto-char (process-mark proc))
-                              (beginning-of-line nil)
-                              (point))
-                            comint-last-input-end))))
-
-                  ;; Scan for state and do post commands - bracket
-                  ;; them with idlwave-shell-ready=nil since they may
-                  ;; call idlwave-shell-send-command themselves.
-                  (let ((idlwave-shell-ready nil))
-                   (idlwave-shell-scan-for-state)
-                   ;; Show the output in the shell if it contains an error
-                   (if idlwave-shell-hide-output
-                       (if (and idlwave-shell-show-if-error
-                                (eq idlwave-shell-current-state 'error))
-                           (idlwave-shell-comint-filter proc full-output)
-                         ;; If it's only *mostly* hidden, filter % lines, 
-                         ;; and show anything that remains
-                         (if (eq idlwave-shell-hide-output 'mostly)
-                             (let ((filtered
-                                    (idlwave-shell-filter-hidden-output 
-                                     full-output)))
-                               (if filtered 
-                                   (idlwave-shell-comint-filter 
-                                    proc filtered))))))
+                     (if (and idlwave-shell-show-if-error
+                              (eq idlwave-shell-current-state 'error))
+                         (idlwave-shell-comint-filter proc full-output)
+                       ;; If it's only *mostly* hidden, filter % lines, 
+                       ;; and show anything that remains
+                       (if (eq idlwave-shell-hide-output 'mostly)
+                           (let ((filtered
+                                  (idlwave-shell-filter-hidden-output 
+                                   full-output)))
+                             (if filtered 
+                                 (idlwave-shell-comint-filter 
+                                  proc filtered))))))
                    
                    
-                   ;; Call the post-command hook
-                    (if (listp idlwave-shell-post-command-hook)
-                        (progn
-                         ;(message "Calling list")
-                         ;(prin1 idlwave-shell-post-command-hook)
-                         (eval idlwave-shell-post-command-hook))
-                     ;(message "Calling command function")
-                      (funcall idlwave-shell-post-command-hook))
-
-                   ;; Reset to default state for next command.
-                    ;; Also we do not want to find this prompt again.
-                    (setq idlwave-shell-accumulation nil
-                          idlwave-shell-command-output nil
-                          idlwave-shell-post-command-hook nil
-                          idlwave-shell-hide-output nil
-                         idlwave-shell-show-if-error nil
-                         idlwave-shell-wait-for-output nil))
-                  ;; Done with post command. Do pending command if
-                  ;; any.
-                  (idlwave-shell-send-command))
-             ;; We didn't get the prompt yet... maybe accept more output
-             (when idlwave-shell-wait-for-output
-;;; Test/Debug code
-;              (save-excursion (set-buffer
-;                               (get-buffer-create "*idlwave-shell-output*"))
-;                              (goto-char (point-max))
-;                              (insert "\n<=== WAITING ON OUTPUT ==>\n"))
-                 (accept-process-output proc 1))))
-        (store-match-data data)))))
+                 ;; Call the post-command hook
+                 (if (listp idlwave-shell-post-command-hook)
+                     (progn
+                       ;;(message "Calling list")
+                       ;;(prin1 idlwave-shell-post-command-hook)
+                       (eval idlwave-shell-post-command-hook))
+                   ;;(message "Calling command function")
+                   (funcall idlwave-shell-post-command-hook))
+
+                 ;; Reset to default state for next command.
+                 ;; Also we do not want to find this prompt again.
+                 (setq idlwave-shell-accumulation nil
+                       idlwave-shell-command-output nil
+                       idlwave-shell-post-command-hook nil
+                       idlwave-shell-hide-output nil
+                       idlwave-shell-show-if-error nil))
+               ;; Done with post command. Do pending command if
+               ;; any.
+               (idlwave-shell-send-command)))
+         (store-match-data data)))))
 
 (defun idlwave-shell-sentinel (process event)
   "The sentinel function for the IDLWAVE shell process."
 
 (defun idlwave-shell-sentinel (process event)
   "The sentinel function for the IDLWAVE shell process."
@@ -1678,6 +1708,8 @@ The 5th group is the file name.
 All parts may contain linebreaks surrounded by spaces.  This is important
 in IDL5 which inserts random linebreaks in long module and file names.")
 
 All parts may contain linebreaks surrounded by spaces.  This is important
 in IDL5 which inserts random linebreaks in long module and file names.")
 
+(defvar idlwave-shell-electric-debug-mode) ; defined by easy-mmode
+
 (defun idlwave-shell-scan-for-state ()
   "Scan for state info.  Looks for messages in output from last IDL
 command indicating where IDL has stopped. The types of messages we are
 (defun idlwave-shell-scan-for-state ()
   "Scan for state info.  Looks for messages in output from last IDL
 command indicating where IDL has stopped. The types of messages we are
@@ -1698,9 +1730,8 @@ the above."
                     idlwave-shell-command-output)
        (string-match idlwave-shell-other-error
                     idlwave-shell-command-output))
                     idlwave-shell-command-output)
        (string-match idlwave-shell-other-error
                     idlwave-shell-command-output))
-      (save-excursion
-       (set-buffer
-        (get-buffer-create idlwave-shell-error-buffer))
+      (with-current-buffer
+         (get-buffer-create idlwave-shell-error-buffer)
        (erase-buffer)
        (insert idlwave-shell-command-output)
        (goto-char (point-min))
        (erase-buffer)
        (insert idlwave-shell-command-output)
        (goto-char (point-min))
@@ -1733,8 +1764,10 @@ the above."
             (substring idlwave-shell-command-output (match-end 0))))
       (setq idlwave-shell-current-state 'halt)
       ;; Don't debug trace messages
             (substring idlwave-shell-command-output (match-end 0))))
       (setq idlwave-shell-current-state 'halt)
       ;; Don't debug trace messages
-      (idlwave-shell-display-line (idlwave-shell-pc-frame) nil
-                                 (if trace 'no-debug)))
+      (idlwave-shell-display-line 
+       (idlwave-shell-pc-frame) nil
+       (if trace 'disable
+        (if idlwave-shell-electric-debug-mode 'force))))
      
      ;; Fourth Priority: Breakpoints 
      ((string-match idlwave-shell-break-message
      
      ;; Fourth Priority: Breakpoints 
      ((string-match idlwave-shell-break-message
@@ -1771,30 +1804,31 @@ the above."
      ;; Otherwise, no particular state
      (t (setq idlwave-shell-current-state nil)))))
 
      ;; Otherwise, no particular state
      (t (setq idlwave-shell-current-state nil)))))
 
+
 (defun idlwave-shell-parse-line (string &optional skip-main)
 (defun idlwave-shell-parse-line (string &optional skip-main)
-  "Parse IDL message for the subroutine, file name and line number.
-We need to work hard here to remove the stupid line breaks inserted by
-IDL5.  These line breaks can be right in the middle of procedure
-or file names.
-It is very difficult to come up with a robust solution.  This one seems
-to be pretty good though.  
-
-Here is in what ways it improves over the previous solution:
-
-1. The procedure name can be split and will be restored.
-2. The number can be split.  I have never seen this, but who knows.
-3. We do not require the `.pro' extension for files.
-
-This function can still break when the file name ends on a end line
-and the message line contains an additional line with garbage.  Then
-the first part of that garbage will be added to the file name.
-However, the function checks the existence of the files with and
-without this last part - thus the function only breaks if file name
-plus garbage match an existing regular file.  This is hopefully very
-unlikely.
-
-If optional arg SKIP-MAIN is non-nil, don't parse $MAIN$ routine stop
-statements."
+  "Parse IDL message for the subroutine, file name and line number."
+;We need to work hard here to remove the stupid line breaks inserted by
+;IDL5.  These line breaks can be right in the middle of procedure
+;or file names.
+;It is very difficult to come up with a robust solution.  This one seems
+;to be pretty good though.  
+;
+;Here is in what ways it improves over the previous solution:
+;
+;1. The procedure name can be split and will be restored.
+;2. The number can be split.  I have never seen this, but who knows.
+;3. We do not require the `.pro' extension for files.
+;
+;This function can still break when the file name ends on an end line
+;and the message line contains an additional line with garbage.  Then
+;the first part of that garbage will be added to the file name.
+;However, the function checks the existence of the files with and
+;without this last part - thus the function only breaks if file name
+;plus garbage match an existing regular file.  This is hopefully very
+;unlikely.
+;
+;If optional arg SKIP-MAIN is non-nil, don't parse $MAIN$ routine stop
+;statements.
 
   (let (number procedure file)
     (when (and (not (if skip-main (string-match ":\\s-*\\$MAIN" string)))
 
   (let (number procedure file)
     (when (and (not (if skip-main (string-match ":\\s-*\\$MAIN" string)))
@@ -1811,7 +1845,7 @@ statements."
       ;; If we have a file, return the frame list
       (if file
          (list (idlwave-shell-file-name file)
       ;; If we have a file, return the frame list
       (if file
          (list (idlwave-shell-file-name file)
-               (string-to-int number)
+               (string-to-number number)
                procedure)
        ;; No success finding a file
        nil))))
                procedure)
        ;; No success finding a file
        nil))))
@@ -1935,14 +1969,17 @@ CLOSE, /ALL
 HEAP_GC, /VERBOSE"
   ;; OBJ_DESTROY, OBJ_VALID()  FIXME: should this be added?
   (interactive "P")
 HEAP_GC, /VERBOSE"
   ;; OBJ_DESTROY, OBJ_VALID()  FIXME: should this be added?
   (interactive "P")
-  (message "Resetting IDL")
-  (setq idlwave-shell-calling-stack-index 0)
-  (idlwave-shell-send-command "retall" nil hidden)
-  (idlwave-shell-send-command "widget_control,/reset" nil hidden)
-  (idlwave-shell-send-command "close,/all" nil hidden)
-  ;; (idlwave-shell-send-command "obj_destroy, obj_valid()" nil hidden)
-  (idlwave-shell-send-command "heap_gc,/verbose" nil hidden)
-  (idlwave-shell-display-line nil))
+  (when (or idlwave-shell-reset-no-prompt 
+           (yes-or-no-p "Really Reset IDL and discard current session? "))
+    (message "Resetting IDL")
+    (setq idlwave-shell-calling-stack-index 0)
+    ;; Give widget exit handlers a chance
+    (idlwave-shell-send-command "retall" nil hidden)
+    (idlwave-shell-send-command "widget_control,/reset" nil hidden)
+    (idlwave-shell-send-command "close,/all" nil hidden)
+    ;; (idlwave-shell-send-command "obj_destroy, obj_valid()" nil hidden)
+    (idlwave-shell-send-command "heap_gc,/verbose" nil hidden)
+    (idlwave-shell-display-line nil)))
 
 (defun idlwave-shell-path-filter ()
   ;; Convert the output of the path query into a list of directories
 
 (defun idlwave-shell-path-filter ()
   ;; Convert the output of the path query into a list of directories
@@ -1987,9 +2024,6 @@ HEAP_GC, /VERBOSE"
          (message 
           "Routine Info warning: No match for END line in \n>>>\n%s\n<<<\n" 
           idlwave-shell-command-output)))
          (message 
           "Routine Info warning: No match for END line in \n>>>\n%s\n<<<\n" 
           idlwave-shell-command-output)))
-    (if (string-match "\\S-" text)
-       ;; Obviously, the pro worked.  Make a note that we have it now.
-       (setq idlwave-idlwave_routine_info-compiled t))
     ;; Match the output lines
     (while (string-match "^IDLWAVE-\\(PRO\\|FUN\\): \\(.*\\)" text start)
       (setq start (match-end 0))
     ;; Match the output lines
     (while (string-match "^IDLWAVE-\\(PRO\\|FUN\\): \\(.*\\)" text start)
       (setq start (match-end 0))
@@ -2070,7 +2104,7 @@ HEAP_GC, /VERBOSE"
 Change the default directory for the process buffer to concur."
   (save-excursion
     (set-buffer (idlwave-shell-buffer))
 Change the default directory for the process buffer to concur."
   (save-excursion
     (set-buffer (idlwave-shell-buffer))
-    (if (string-match ",___cur[\n\r]\\(\\S-*\\) *[\n\r]"
+    (if (string-match ",___cur[\n\r ]+\\([^\n\r]+\\)[\n\r]"
                      idlwave-shell-command-output)
        (let ((dir (substring idlwave-shell-command-output 
                              (match-beginning 1) (match-end 1))))
                      idlwave-shell-command-output)
        (let ((dir (substring idlwave-shell-command-output 
                              (match-beginning 1) (match-end 1))))
@@ -2098,7 +2132,8 @@ Change the default directory for the process buffer to concur."
     (when (not (string= expression ""))
       (setq idlwave-shell-get-object-class nil)
       (idlwave-shell-send-command
     (when (not (string= expression ""))
       (setq idlwave-shell-get-object-class nil)
       (idlwave-shell-send-command
-       (concat "print,obj_class(" expression ")")
+       (concat "if obj_valid(" expression ") then print,obj_class(" 
+              expression ")")
        'idlwave-shell-parse-object-class
        'hide 'wait)
       ;; If we don't know anything about the class, update shell routines
        'idlwave-shell-parse-object-class
        'hide 'wait)
       ;; If we don't know anything about the class, update shell routines
@@ -2110,13 +2145,10 @@ Change the default directory for the process buffer to concur."
 
 (defun idlwave-shell-parse-object-class ()
   "Parse the output of the obj_class command."
 
 (defun idlwave-shell-parse-object-class ()
   "Parse the output of the obj_class command."
-  (let ((match "print,obj_class([^\n\r]+[\n\r ]"))
-    (if (and
-        (not (string-match (concat match match "\\s-*^[\n\r]+"
-                                   "% Syntax error")
-                           idlwave-shell-command-output))
-        (string-match (concat match "\\([A-Za-z_0-9]+\\)")
-                      idlwave-shell-command-output))
+  (let ((match "obj_class([^\n\r]+[\n\r ]"))
+    (if (string-match (concat match "\\([A-Za-z_0-9]+\\) *[\n\r]\\(" 
+                             idlwave-shell-prompt-pattern "\\)")
+                     idlwave-shell-command-output)
        (setq idlwave-shell-get-object-class 
              (match-string 1 idlwave-shell-command-output)))))
 
        (setq idlwave-shell-get-object-class 
              (match-string 1 idlwave-shell-command-output)))))
 
@@ -2269,14 +2301,14 @@ overlays."
     (setq idlwave-shell-calling-stack-routine 
          (nth 2 (nth idlwave-shell-calling-stack-index stack)))
 
     (setq idlwave-shell-calling-stack-routine 
          (nth 2 (nth idlwave-shell-calling-stack-index stack)))
 
-    ;; only edebug if in that mode already
+    ;; force edebug for this frame if we're in that mode already
     (idlwave-shell-display-line 
      (nth idlwave-shell-calling-stack-index stack) nil
     (idlwave-shell-display-line 
      (nth idlwave-shell-calling-stack-index stack) nil
-     (unless idlwave-shell-electric-debug-mode 'no-debug)) 
-    (message (or message 
-                (format "In routine %s (stack level %d)"
-                        idlwave-shell-calling-stack-routine
-                        (- idlwave-shell-calling-stack-index))))))
+     (if idlwave-shell-electric-debug-mode 'force))
+    (message "%s" (or message 
+                     (format "In routine %s (stack level %d)"
+                             idlwave-shell-calling-stack-routine
+                             (- idlwave-shell-calling-stack-index))))))
 
 (defun idlwave-shell-stack-up ()
   "Display the source code one step up the calling stack."
 
 (defun idlwave-shell-stack-up ()
   "Display the source code one step up the calling stack."
@@ -2312,30 +2344,38 @@ used.  Does nothing if the resulting frame is nil."
   "Check that frame is for an existing file."
   (file-readable-p (car frame)))
 
   "Check that frame is for an existing file."
   (file-readable-p (car frame)))
 
-(defvar idlwave-shell-suppress-electric-debug nil)
-(defun idlwave-shell-display-line (frame &optional col no-debug)
-  "Display FRAME file in other window with overlay arrow.
+(defun idlwave-shell-stop-line-pending ()
+  ;; Temporarily change the color of the stop line overlay
+  (if idlwave-shell-stop-line-overlay
+      (overlay-put idlwave-shell-stop-line-overlay 'face
+                  (if idlwave-shell-electric-debug-mode
+                      'idlwave-shell-pending-electric-stop
+                    'idlwave-shell-pending-stop))))
 
 
-FRAME is a list of file name, line number, and subroutine name.  If
-FRAME is nil then remove overlay.  If COL is set, move point to that
-column in the line.  If NO-DEBUG is non-nil, do *not* toggle the electric
-debug mode."
+(defvar idlwave-shell-suppress-electric-debug nil)
+(defun idlwave-shell-display-line (frame &optional col debug)
+  "display frame file in other window with overlay arrow.
+
+frame is a list of file name, line number, and subroutine name.  if
+frame is nil then remove overlay.  if col is set, move point to that
+column in the line.  if debug is non-nil, enable the electric debug
+mode.  if it is 'disable, do not enable no matter what the setting of
+'idlwave-shell-automatic-electric-debug'.  if it is 'force, enable no
+matter what the settings of that variable."
   (if (not frame)
   (if (not frame)
-      ;; Remove stop-line overlay from old position
+      ;; remove stop-line overlay from old position
       (progn 
         (setq overlay-arrow-string nil)
        (setq idlwave-shell-mode-line-info nil)
        (setq idlwave-shell-is-stopped nil)
         (if idlwave-shell-stop-line-overlay
             (delete-overlay idlwave-shell-stop-line-overlay))
       (progn 
         (setq overlay-arrow-string nil)
        (setq idlwave-shell-mode-line-info nil)
        (setq idlwave-shell-is-stopped nil)
         (if idlwave-shell-stop-line-overlay
             (delete-overlay idlwave-shell-stop-line-overlay))
-       ;; Turn off electric debug everywhere, if it's on
-       (if (and (not no-debug)
-                idlwave-shell-automatic-electric-debug)
-           (idlwave-shell-electric-debug-all-off)))
+       ;; turn off electric debug everywhere, if it's on
+       (idlwave-shell-electric-debug-all-off))
     (if (not (idlwave-shell-valid-frame frame))
     (if (not (idlwave-shell-valid-frame frame))
-       ;; FIXME: errors are dangerous in shell filters.  But I think I
+       ;; fixme: errors are dangerous in shell filters.  but i think i
        ;; have never encountered this one.
        ;; have never encountered this one.
-        (error (concat "Invalid frame - unable to access file: " (car frame)))
+        (error (concat "invalid frame - unable to access file: " (car frame)))
 ;;;
 ;;; buffer : the buffer to display a line in.
 ;;; select-shell: current buffer is the shell.
 ;;;
 ;;; buffer : the buffer to display a line in.
 ;;; select-shell: current buffer is the shell.
@@ -2349,15 +2389,15 @@ debug mode."
              (select-shell (equal (buffer-name) (idlwave-shell-buffer)))
              window pos electric)
 
              (select-shell (equal (buffer-name) (idlwave-shell-buffer)))
              window pos electric)
 
-       ;; First make sure the shell window is visible
+       ;; first make sure the shell window is visible
        (idlwave-display-buffer (idlwave-shell-buffer)
                                nil (idlwave-shell-shell-frame))
 
        (idlwave-display-buffer (idlwave-shell-buffer)
                                nil (idlwave-shell-shell-frame))
 
-       ;; Now display the buffer and remember which window it is.
+       ;; now display the buffer and remember which window it is.
        (setq window (idlwave-display-buffer buffer
                                             nil (idlwave-shell-source-frame)))
 
        (setq window (idlwave-display-buffer buffer
                                             nil (idlwave-shell-source-frame)))
 
-       ;; Enter the buffer and mark the line
+       ;; enter the buffer and mark the line
         (save-excursion
           (set-buffer buffer)
           (save-restriction
         (save-excursion
           (set-buffer buffer)
           (save-restriction
@@ -2368,45 +2408,53 @@ debug mode."
            (setq idlwave-shell-is-stopped t)
            
             (if idlwave-shell-stop-line-overlay
            (setq idlwave-shell-is-stopped t)
            
             (if idlwave-shell-stop-line-overlay
-                ;; Move overlay
-               (move-overlay idlwave-shell-stop-line-overlay
-                             (point) (save-excursion (end-of-line) (point))
-                             (current-buffer))
-             ;; Use the arrow instead, but only if marking is wanted.
+                (progn
+                 ;; restore face and move overlay 
+                 (overlay-put idlwave-shell-stop-line-overlay 'face
+                              (if idlwave-shell-electric-debug-mode
+                                   idlwave-shell-electric-stop-line-face 
+                                 idlwave-shell-stop-line-face))
+                 (move-overlay idlwave-shell-stop-line-overlay
+                               (point) (save-excursion (end-of-line) (point))
+                               (current-buffer)))
+             ;; use the arrow instead, but only if marking is wanted.
              (if idlwave-shell-mark-stop-line
                  (setq overlay-arrow-string idlwave-shell-overlay-arrow))
               (or overlay-arrow-position  ; create the marker if necessary
                   (setq overlay-arrow-position (make-marker)))
              (set-marker overlay-arrow-position (point) buffer)))
 
              (if idlwave-shell-mark-stop-line
                  (setq overlay-arrow-string idlwave-shell-overlay-arrow))
               (or overlay-arrow-position  ; create the marker if necessary
                   (setq overlay-arrow-position (make-marker)))
              (set-marker overlay-arrow-position (point) buffer)))
 
-         ;; If the point is outside the restriction, widen the buffer.
+         ;; if the point is outside the restriction, widen the buffer.
           (if (or (< pos (point-min)) (> pos (point-max)))
              (progn
                (widen)
                (goto-char pos)))
 
           (if (or (< pos (point-min)) (> pos (point-max)))
              (progn
                (widen)
                (goto-char pos)))
 
-         ;; If we have the column of the error, move the cursor there.
+         ;; if we have the column of the error, move the cursor there.
           (if col (move-to-column col))
           (setq pos (point))
          
           (if col (move-to-column col))
           (setq pos (point))
          
-         ;; Enter electric debug mode, if not prohibited and not in
+         ;; enter electric debug mode, if not prohibited and not in
          ;; it already
          ;; it already
-         (when (and (or 
-                     (eq idlwave-shell-automatic-electric-debug t)
-                     (and 
-                      (eq idlwave-shell-automatic-electric-debug 'breakpoint)
-                      (not (eq idlwave-shell-current-state 'error))))
-                    (not no-debug)
-                    (not idlwave-shell-suppress-electric-debug)
-                    (not idlwave-shell-electric-debug-mode))
-           (idlwave-shell-electric-debug-mode)
-           (setq electric t)))
+         (when  (and (not idlwave-shell-electric-debug-mode)
+                     (or (eq debug 'force)
+                         (and 
+                          (not (eq debug 'disable)) ;; explicitly disabled
+                          (or 
+                           (eq idlwave-shell-automatic-electric-debug t)
+                           (and 
+                            (eq idlwave-shell-automatic-electric-debug 
+                                'breakpoint)
+                            (not (eq idlwave-shell-current-state 'error))))
+                          (not idlwave-shell-suppress-electric-debug))))
+           (idlwave-shell-electric-debug-mode t))
+         (setq electric idlwave-shell-electric-debug-mode))
        
        ;; Make sure pos is really displayed in the window.
        (set-window-point window pos)
        
        ;; If we came from the shell, go back there.  Otherwise select 
        
        ;; Make sure pos is really displayed in the window.
        (set-window-point window pos)
        
        ;; If we came from the shell, go back there.  Otherwise select 
-       ;; the window where the error is displayed.
+       ;; the window where the error/halt is displayed.
         (if (or (and idlwave-shell-electric-zap-to-file electric)
                (and (equal (buffer-name) (idlwave-shell-buffer)) 
                     (not select-shell)))
         (if (or (and idlwave-shell-electric-zap-to-file electric)
                (and (equal (buffer-name) (idlwave-shell-buffer)) 
                     (not select-shell)))
@@ -2418,6 +2466,7 @@ debug mode."
   (interactive "p")
   (or (not arg) (< arg 1)
       (setq arg 1))
   (interactive "p")
   (or (not arg) (< arg 1)
       (setq arg 1))
+  (idlwave-shell-stop-line-pending)
   (idlwave-shell-send-command 
    (concat ".s " (if (integerp arg) (int-to-string arg) arg))
    nil (if (idlwave-shell-hide-p 'debug) 'mostly) nil t))
   (idlwave-shell-send-command 
    (concat ".s " (if (integerp arg) (int-to-string arg) arg))
    nil (if (idlwave-shell-hide-p 'debug) 'mostly) nil t))
@@ -2429,11 +2478,13 @@ Uses IDL's stepover executive command which does not enter called functions."
   (interactive "p")
   (or (not arg) (< arg 1)
       (setq arg 1))
   (interactive "p")
   (or (not arg) (< arg 1)
       (setq arg 1))
+  (idlwave-shell-stop-line-pending)
   (idlwave-shell-send-command 
    (concat ".so " (if (integerp arg) (int-to-string arg) arg))
    nil (if (idlwave-shell-hide-p 'debug) 'mostly) nil t))
 
   (idlwave-shell-send-command 
    (concat ".so " (if (integerp arg) (int-to-string arg) arg))
    nil (if (idlwave-shell-hide-p 'debug) 'mostly) nil t))
 
-(defun idlwave-shell-break-here (&optional count cmd condition no-show)
+(defun idlwave-shell-break-here (&optional count cmd condition disabled 
+                                          no-show)
   "Set breakpoint at current line.  
 
 If Count is nil then an ordinary breakpoint is set.  We treat a count
   "Set breakpoint at current line.  
 
 If Count is nil then an ordinary breakpoint is set.  We treat a count
@@ -2441,9 +2492,9 @@ of 1 as a temporary breakpoint using the ONCE keyword.  Counts greater
 than 1 use the IDL AFTER=count keyword to break only after reaching
 the statement count times.
 
 than 1 use the IDL AFTER=count keyword to break only after reaching
 the statement count times.
 
-Optional argument CMD is a list or function to evaluate upon reaching 
-the breakpoint."
-  
+Optional argument CMD is a list or function to evaluate upon reaching
+the breakpoint.  CONDITION is a break condition, and DISABLED, if
+non-nil disables the breakpoint"
   (interactive "P")
   (when (listp count)
     (if (equal (car count) 4) 
   (interactive "P")
   (when (listp count)
     (if (equal (car count) 4) 
@@ -2452,7 +2503,7 @@ the breakpoint."
   (idlwave-shell-set-bp
    ;; Create breakpoint
    (idlwave-shell-bp (idlwave-shell-current-frame)
   (idlwave-shell-set-bp
    ;; Create breakpoint
    (idlwave-shell-bp (idlwave-shell-current-frame)
-                    (list count cmd condition nil)
+                    (list count cmd condition disabled)
                     (idlwave-shell-current-module))
    no-show))
 
                     (idlwave-shell-current-module))
    no-show))
 
@@ -2462,32 +2513,36 @@ This is run on `idlwave-shell-post-command-hook'.
 Offers to recompile the procedure if we failed.  This usually fixes
 the problem with not being able to set the breakpoint."
   ;; Scan for message
 Offers to recompile the procedure if we failed.  This usually fixes
 the problem with not being able to set the breakpoint."
   ;; Scan for message
-  (if (and idlwave-shell-command-output
-           (string-match "% BREAKPOINT: *Unable to find code"
-                         idlwave-shell-command-output))
-      ;; Offer to recompile
-      (progn
+  (if idlwave-shell-command-output
+      (cond
+       ((string-match "% BREAKPOINT: *Unable to find code"
+                     idlwave-shell-command-output)
+       ;; Offer to recompile
         (if (progn
               (beep)
               (y-or-n-p 
                (concat "Okay to recompile file "
         (if (progn
               (beep)
               (y-or-n-p 
                (concat "Okay to recompile file "
-                       (idlwave-shell-bp-get bp 'file) " ")))
+                       (idlwave-shell-bp-get bp 'file) "?")))
             ;; Recompile
             (progn
               ;; Clean up before retrying
               (idlwave-shell-command-failure)
               (idlwave-shell-send-command
             ;; Recompile
             (progn
               ;; Clean up before retrying
               (idlwave-shell-command-failure)
               (idlwave-shell-send-command
-               (concat ".run " (idlwave-shell-bp-get bp 'file)) nil 
+               (concat ".run \"" (idlwave-shell-bp-get bp 'file) "\"") nil 
               (if (idlwave-shell-hide-p 'run) 'mostly) nil t)
               ;; Try setting breakpoint again
               (idlwave-shell-set-bp bp))
           (beep)
           (message "Unable to set breakpoint.")
               (if (idlwave-shell-hide-p 'run) 'mostly) nil t)
               ;; Try setting breakpoint again
               (idlwave-shell-set-bp bp))
           (beep)
           (message "Unable to set breakpoint.")
-          (idlwave-shell-command-failure)
-          )
-        ;; return non-nil if no error found
-        nil)
-    'okay))
+          (idlwave-shell-command-failure))
+       nil)
+
+       ((string-match "% Syntax error" idlwave-shell-command-output)
+       (message "Syntax error in condition.")
+       (idlwave-shell-command-failure)
+       nil)
+       
+       (t 'okay))))
 
 (defun idlwave-shell-command-failure ()
   "Do any necessary clean up when an IDL command fails.
 
 (defun idlwave-shell-command-failure ()
   "Do any necessary clean up when an IDL command fails.
@@ -2501,6 +2556,7 @@ breakpoint can not be set."
 (defun idlwave-shell-cont (&optional no-show)
   "Continue executing."
   (interactive)
 (defun idlwave-shell-cont (&optional no-show)
   "Continue executing."
   (interactive)
+  (idlwave-shell-stop-line-pending)
   (idlwave-shell-send-command ".c" (unless no-show 
                                     '(idlwave-shell-redisplay 'hide))
                              (if (idlwave-shell-hide-p 'debug) 'mostly) 
   (idlwave-shell-send-command ".c" (unless no-show 
                                     '(idlwave-shell-redisplay 'hide))
                              (if (idlwave-shell-hide-p 'debug) 'mostly) 
@@ -2509,6 +2565,7 @@ breakpoint can not be set."
 (defun idlwave-shell-go ()
   "Run .GO.  This starts the main program of the last compiled file."
   (interactive)
 (defun idlwave-shell-go ()
   "Run .GO.  This starts the main program of the last compiled file."
   (interactive)
+  (idlwave-shell-stop-line-pending)
   (idlwave-shell-send-command ".go" '(idlwave-shell-redisplay 'hide)
                              (if (idlwave-shell-hide-p 'debug) 'mostly)
                              nil t))
   (idlwave-shell-send-command ".go" '(idlwave-shell-redisplay 'hide)
                              (if (idlwave-shell-hide-p 'debug) 'mostly)
                              nil t))
@@ -2516,6 +2573,7 @@ breakpoint can not be set."
 (defun idlwave-shell-return ()
   "Run .RETURN (continue to next return, but stay in subprogram)."
   (interactive)
 (defun idlwave-shell-return ()
   "Run .RETURN (continue to next return, but stay in subprogram)."
   (interactive)
+  (idlwave-shell-stop-line-pending)
   (idlwave-shell-send-command ".return" '(idlwave-shell-redisplay 'hide)
                              (if (idlwave-shell-hide-p 'debug) 'mostly)
                              nil t))
   (idlwave-shell-send-command ".return" '(idlwave-shell-redisplay 'hide)
                              (if (idlwave-shell-hide-p 'debug) 'mostly)
                              nil t))
@@ -2523,11 +2581,12 @@ breakpoint can not be set."
 (defun idlwave-shell-skip ()
   "Run .SKIP (skip one line, then step)."
   (interactive)
 (defun idlwave-shell-skip ()
   "Run .SKIP (skip one line, then step)."
   (interactive)
+  (idlwave-shell-stop-line-pending)  
   (idlwave-shell-send-command ".skip" '(idlwave-shell-redisplay 'hide)
                              (if (idlwave-shell-hide-p 'debug) 'mostly)
                              nil t))
 
   (idlwave-shell-send-command ".skip" '(idlwave-shell-redisplay 'hide)
                              (if (idlwave-shell-hide-p 'debug) 'mostly)
                              nil t))
 
-(defun idlwave-shell-clear-bp (bp)
+(defun idlwave-shell-clear-bp (bp &optional no-query)
   "Clear breakpoint BP.
 Clears in IDL and in `idlwave-shell-bp-alist'."
   (let ((index (idlwave-shell-bp-get bp)))
   "Clear breakpoint BP.
 Clears in IDL and in `idlwave-shell-bp-alist'."
   (let ((index (idlwave-shell-bp-get bp)))
@@ -2536,7 +2595,7 @@ Clears in IDL and in `idlwave-shell-bp-alist'."
           (idlwave-shell-send-command
            (concat "breakpoint,/clear," (int-to-string index))
           nil (idlwave-shell-hide-p 'breakpoint) nil t)
           (idlwave-shell-send-command
            (concat "breakpoint,/clear," (int-to-string index))
           nil (idlwave-shell-hide-p 'breakpoint) nil t)
-         (idlwave-shell-bp-query)))))
+         (unless no-query (idlwave-shell-bp-query))))))
 
 (defun idlwave-shell-current-frame ()
   "Return a list containing the current file name and line point is in.
 
 (defun idlwave-shell-current-frame ()
   "Return a list containing the current file name and line point is in.
@@ -2563,7 +2622,10 @@ Returns nil if unable to obtain a module name."
       (widen)
       (save-excursion
         (if (idlwave-prev-index-position)
       (widen)
       (save-excursion
         (if (idlwave-prev-index-position)
-            (upcase (idlwave-unit-name)))))))
+           (let* ((module (idlwave-what-module))
+                  (name (idlwave-make-full-name (nth 2 module) (car module)))
+                  (type (nth 1 module)))
+             (list (upcase name) type)))))))
 
 (defun idlwave-shell-clear-current-bp ()
   "Remove breakpoint at current line.
 
 (defun idlwave-shell-clear-current-bp ()
   "Remove breakpoint at current line.
@@ -2576,7 +2638,10 @@ at a breakpoint."
 
 (defun idlwave-shell-toggle-enable-current-bp (&optional bp force
                                                         no-update)
 
 (defun idlwave-shell-toggle-enable-current-bp (&optional bp force
                                                         no-update)
-  "Disable or enable current bp."
+  "Disable or enable current breakpoint or a breakpoint passed in BP.
+If FORCE is 'disable or 'enable, for that condition instead of
+toggling.  If NO-UPDATE is non-nil, don't update the breakpoint
+list after toggling."
   (interactive)
   (let* ((bp (or bp (idlwave-shell-find-current-bp)))
         (disabled (idlwave-shell-bp-get bp 'disabled)))
   (interactive)
   (let* ((bp (or bp (idlwave-shell-find-current-bp)))
         (disabled (idlwave-shell-bp-get bp 'disabled)))
@@ -2608,8 +2673,9 @@ If ENABLE is non-nil, enable them instead."
 (defun idlwave-shell-to-here ()
   "Set a breakpoint with count 1 then continue."
   (interactive)
 (defun idlwave-shell-to-here ()
   "Set a breakpoint with count 1 then continue."
   (interactive)
+  ;; temporarily disable all other breakpoints
   (let ((disabled (idlwave-shell-enable-all-bp 'disable 'no-update)))
   (let ((disabled (idlwave-shell-enable-all-bp 'disable 'no-update)))
-    (idlwave-shell-break-here 1 nil nil 'no-show)
+    (idlwave-shell-break-here 1 nil nil nil 'no-show)
     (idlwave-shell-cont 'no-show)
     (idlwave-shell-enable-all-bp 'enable 'no-update disabled))
   (idlwave-shell-redisplay)) ; sync up everything at the end
     (idlwave-shell-cont 'no-show)
     (idlwave-shell-enable-all-bp 'enable 'no-update disabled))
   (idlwave-shell-redisplay)) ; sync up everything at the end
@@ -2626,27 +2692,30 @@ The command looks for an identifier near point and sets a breakpoint
 for the first line of the corresponding module.  If MODULE is `t', set
 in the current routine."
   (interactive)
 for the first line of the corresponding module.  If MODULE is `t', set
 in the current routine."
   (interactive)
-  (let (module)
-    (save-excursion
-      (skip-chars-backward "a-zA-Z0-9_$")
-      (if (looking-at idlwave-identifier)
-         (setq module (match-string 0))
-       (error "No identifier at point")))
-    (idlwave-shell-send-command
-     idlwave-shell-sources-query
-     `(progn
-       (idlwave-shell-sources-filter)
-       (idlwave-shell-set-bp-in-module ,module))
-     'hide)))
-
-(defun idlwave-shell-set-bp-in-module (module)
+  (let* ((module (idlwave-fix-module-if-obj_new (idlwave-what-module)))
+        (type (nth 1 module))
+        (name (car module))
+        (class (nth 2 module)))
+    (if module
+       (progn 
+         (setq module (idlwave-make-full-name class name))
+         (idlwave-shell-module-source-query module type)
+         (idlwave-shell-set-bp-in-module name type class))
+      (error "No identifier at point"))))
+
+
+(defun idlwave-shell-set-bp-in-module (name type class)
   "Set breakpoint in module.  Assumes that `idlwave-shell-sources-alist'
 contains an entry for that module."
   "Set breakpoint in module.  Assumes that `idlwave-shell-sources-alist'
 contains an entry for that module."
-  (let ((source-file (car-safe 
-                     (cdr-safe
-                      (assoc (upcase module)
-                             idlwave-shell-sources-alist))))
-       buf)
+  (let* ((module (idlwave-make-full-name class name))
+        (source-file 
+         (car-safe (cdr-safe
+                    (or
+                     (assoc (upcase module)
+                            idlwave-shell-sources-alist)
+                     (nth 3 (idlwave-best-rinfo-assoc name type class 
+                                                      (idlwave-routines)))))))
+        buf)
     (if (or (not source-file)
            (not (file-regular-p source-file))
            (not (setq buf
     (if (or (not source-file)
            (not (file-regular-p source-file))
            (not (setq buf
@@ -2733,7 +2802,7 @@ Runs to the last statement and then steps 1 statement.  Use the .out command."
             (funcall orig-func cur-line orig-bp-line)
             (or (not bp-line) (funcall closer-func cur-line bp-line)))
            (setq bp-line cur-line))))
             (funcall orig-func cur-line orig-bp-line)
             (or (not bp-line) (funcall closer-func cur-line bp-line)))
            (setq bp-line cur-line))))
-    (unless bp-line (error "No further breakpoints."))
+    (unless bp-line (error "No further breakpoints"))
     (goto-line bp-line)))
 
 ;; Examine Commands ------------------------------------------------------
     (goto-line bp-line)))
 
 ;; Examine Commands ------------------------------------------------------
@@ -2748,13 +2817,18 @@ Runs to the last statement and then steps 1 statement.  Use the .out command."
   `(lambda (event)
      "Expansion function for expression examination."
      (interactive "e")
   `(lambda (event)
      "Expansion function for expression examination."
      (interactive "e")
-     (let ((transient-mark-mode t)
-          (zmacs-regions t)
-          (tracker (if (featurep 'xemacs) 
-                       (if (fboundp 'default-mouse-track-event-is-with-button)
-                           'idlwave-xemacs-hack-mouse-track
-                         'mouse-track)
-                     'mouse-drag-region)))
+     (let* ((drag-track (fboundp 'mouse-drag-track))
+           (transient-mark-mode t)
+           (zmacs-regions t)
+           (tracker (if (featurep 'xemacs) 
+                        (if (fboundp 
+                             'default-mouse-track-event-is-with-button)
+                            'idlwave-xemacs-hack-mouse-track
+                          'mouse-track)
+                      ;; Emacs 22 no longer completes the drag with
+                      ;; mouse-drag-region, without an additional
+                      ;; event.  mouse-drag-track does so.
+                      (if drag-track 'mouse-drag-track 'mouse-drag-region))))
        (funcall tracker event)
        (idlwave-shell-print (if (idlwave-region-active-p) '(4) nil)
                            ,help ,ev))))
        (funcall tracker event)
        (idlwave-shell-print (if (idlwave-region-active-p) '(4) nil)
                            ,help ,ev))))
@@ -2765,13 +2839,15 @@ Runs to the last statement and then steps 1 statement.  Use the .out command."
   t)
 
 (defun idlwave-xemacs-hack-mouse-track (event)
   t)
 
 (defun idlwave-xemacs-hack-mouse-track (event)
-  (let ((oldfunc (symbol-function 'default-mouse-track-event-is-with-button)))
-    (unwind-protect
-       (progn
-         (fset 'default-mouse-track-event-is-with-button 
-               'idlwave-default-mouse-track-event-is-with-button)
-         (mouse-track event))
-      (fset 'default-mouse-track-event-is-with-button oldfunc))))
+  (if (featurep 'xemacs)
+      (let ((oldfunc (symbol-function 
+                     'default-mouse-track-event-is-with-button)))
+       (unwind-protect
+           (progn
+             (fset 'default-mouse-track-event-is-with-button 
+                   'idlwave-default-mouse-track-event-is-with-button)
+             (mouse-track event))
+         (fset 'default-mouse-track-event-is-with-button oldfunc)))))
 ;;; End terrible hack section
 
 (defun idlwave-shell-mouse-print (event)
 ;;; End terrible hack section
 
 (defun idlwave-shell-mouse-print (event)
@@ -2830,6 +2906,11 @@ idlw-shell-examine-alist from which to select the help command text.
 If instead COMPLETE-HELP-TYPE is non-nil, choose from
 idlw-shell-examine-alist via mini-buffer shortcut key."
   (interactive "P")
 If instead COMPLETE-HELP-TYPE is non-nil, choose from
 idlw-shell-examine-alist via mini-buffer shortcut key."
   (interactive "P")
+
+  ;; For speed: assume the helper routine hasn't been lost, e.g. with
+  ;; .FULL_RESET_SESSION.  We'll recover if necessary
+  (unless idlwave-idlwave_routine_info-compiled
+    (idlwave-shell-compile-helper-routines))
   (save-excursion
     (let* ((process (get-buffer-process (current-buffer)))
           (process-mark (if process (process-mark process)))
   (save-excursion
     (let* ((process (get-buffer-process (current-buffer)))
           (process-mark (if process (process-mark process)))
@@ -2839,7 +2920,7 @@ idlw-shell-examine-alist via mini-buffer shortcut key."
                (format "  [-%d:%s]" 
                        idlwave-shell-calling-stack-index 
                        idlwave-shell-calling-stack-routine)))
                (format "  [-%d:%s]" 
                        idlwave-shell-calling-stack-index 
                        idlwave-shell-calling-stack-routine)))
-          expr beg end cmd examine-hook)
+          expr beg end cmd)
       (cond
        ((equal arg '(16))
        (setq expr (read-string "Expression: ")))
       (cond
        ((equal arg '(16))
        (setq expr (read-string "Expression: ")))
@@ -2882,10 +2963,6 @@ idlw-shell-examine-alist via mini-buffer shortcut key."
                      (current-buffer))
        (add-hook 'pre-command-hook 
                  'idlwave-shell-delete-expression-overlay))
                      (current-buffer))
        (add-hook 'pre-command-hook 
                  'idlwave-shell-delete-expression-overlay))
-      (setq examine-hook 
-           (if idlwave-shell-separate-examine-output
-               'idlwave-shell-examine-display
-             'idlwave-shell-examine-highlight))
       (add-hook 'pre-command-hook
                'idlwave-shell-delete-output-overlay)
       
       (add-hook 'pre-command-hook
                'idlwave-shell-delete-output-overlay)
       
@@ -2893,7 +2970,7 @@ idlw-shell-examine-alist via mini-buffer shortcut key."
       (while (string-match "\n[ \t]*\\(;.*\\)?\r*\n" expr)
        (setq expr (replace-match "\n" t t expr)))
       ;; Concatenate continuation lines
       (while (string-match "\n[ \t]*\\(;.*\\)?\r*\n" expr)
        (setq expr (replace-match "\n" t t expr)))
       ;; Concatenate continuation lines
-      (while (string-match "[ \t]*\\$.*\\(;.*\\)?\\(\n[ \t]*\\|$\\)" expr)
+      (while (string-match "[ \t]*\\$[ \t]*\\(;.*\\)?\\(\n[ \t]*\\|$\\)" expr)
        (setq expr (replace-match "" t t expr)))
       ;; Remove final newline
       (if (string-match "\n[ \t\r]*\\'" expr)
        (setq expr (replace-match "" t t expr)))
       ;; Remove final newline
       (if (string-match "\n[ \t\r]*\\'" expr)
@@ -2947,7 +3024,7 @@ idlw-shell-examine-alist via mini-buffer shortcut key."
        ;;(idlwave-shell-recenter-shell-window)
        (idlwave-shell-send-command 
         cmd 
        ;;(idlwave-shell-recenter-shell-window)
        (idlwave-shell-send-command 
         cmd 
-        examine-hook 
+        'idlwave-shell-check-compiled-and-display
         (if idlwave-shell-separate-examine-output 'hide))))))
 
 (defvar idlwave-shell-examine-window-alist nil
         (if idlwave-shell-separate-examine-output 'hide))))))
 
 (defvar idlwave-shell-examine-window-alist nil
@@ -2957,6 +3034,15 @@ idlw-shell-examine-alist via mini-buffer shortcut key."
 (define-key idlwave-shell-examine-map "q" 'idlwave-shell-examine-display-quit)
 (define-key idlwave-shell-examine-map "c" 'idlwave-shell-examine-display-clear)
 
 (define-key idlwave-shell-examine-map "q" 'idlwave-shell-examine-display-quit)
 (define-key idlwave-shell-examine-map "c" 'idlwave-shell-examine-display-clear)
 
+
+(defun idlwave-shell-check-compiled-and-display ()
+  "Check examine output for warning about undefined procedure/function."
+  (if (string-match "% Attempt to call undefined" idlwave-shell-command-output)
+      (idlwave-shell-compile-helper-routines))
+  (if idlwave-shell-separate-examine-output
+      (idlwave-shell-examine-display)
+    (idlwave-shell-examine-highlight)))
+
 (defun idlwave-shell-examine-display ()
   "View the examine command output in a separate buffer."
   (let (win cur-beg cur-end)
 (defun idlwave-shell-examine-display ()
   "View the examine command output in a separate buffer."
   (let (win cur-beg cur-end)
@@ -3067,7 +3153,7 @@ routine_names, there is no guarantee that this will work with future
 versions of IDL."
   (let ((fetch (- 0 level))
        (start 0)
 versions of IDL."
   (let ((fetch (- 0 level))
        (start 0)
-        var rnvar pre post)
+        var fetch-start fetch-end pre post)
 
     ;; FIXME: In the following we try to find the variables in expression
     ;; This is quite empirical - I don't know in what situations this will
 
     ;; FIXME: In the following we try to find the variables in expression
     ;; This is quite empirical - I don't know in what situations this will
@@ -3078,25 +3164,47 @@ versions of IDL."
     (while (string-match
            "\\(\\`\\|[^a-zA-Z0-9$_][ \t]*\\)\\([a-zA-Z][a-zA-Z0-9$_]*\\)\\([ \t]*[^a-zA-Z0-9$_]\\|\\'\\)" expr start)
       (setq var (match-string 2 expr)
     (while (string-match
            "\\(\\`\\|[^a-zA-Z0-9$_][ \t]*\\)\\([a-zA-Z][a-zA-Z0-9$_]*\\)\\([ \t]*[^a-zA-Z0-9$_]\\|\\'\\)" expr start)
       (setq var (match-string 2 expr)
-           start (match-beginning 2)
+           start (match-end 2)
            pre (substring expr 0 (match-beginning 2))
            post (substring expr (match-end 2)))
            pre (substring expr 0 (match-beginning 2))
            post (substring expr (match-end 2)))
-      (cond
-       ;; Exclude identifiers which are not variables
-       ((string-match ",[ \t]*/\\'" pre))        ;; a `/' KEYWORD
-       ((and (string-match "[,(][ \t]*\\'" pre)
-            (string-match "\\`[ \t]*=" post)))  ;; a `=' KEYWORD
-       ((string-match "\\`(" post))              ;; a function
-       ((string-match "->[ \t]*\\'" pre))        ;; a method
-       ((string-match "\\.\\'" pre))             ;; structure member
+      (cond 
+       ((or
+       ;; Exclude identifiers which are not variables
+        (string-match ",[ \t$\n]*/\\'" pre)        ;; a `/' KEYWORD
+        (and (string-match "[,(][ \t\n]*\\'" pre)
+             (string-match "\\`[ \t]*=" post))  ;; a `=' KEYWORD
+        (string-match "\\`(" post)              ;; a function
+        (string-match "->[ \t]*\\'" pre)        ;; a method
+        (string-match "\\.\\'" pre)))             ;; structure member
+
+       ;; Skip over strings
        ((and (string-match "\\([\"\']\\)[^\1]*$" pre)
             (string-match (concat "^[^" (match-string 1 pre) "]*" 
        ((and (string-match "\\([\"\']\\)[^\1]*$" pre)
             (string-match (concat "^[^" (match-string 1 pre) "]*" 
-                                  (match-string 1 pre)) post)))
-       (t ;; seems to be a variable - replace its name in the
-         ;; expression with the fetch.
-       (setq rnvar (format "(routine_names('%s',fetch=%d))" var fetch)
-             expr  (concat pre rnvar post)
-             start (+ start (length rnvar))))))
+                                  (match-string 1 pre)) post))
+       (setq start (+ start (match-end 0))))
+
+       
+       ;; seems to be a variable - delimit its name
+       (t 
+       (put-text-property start (- start (length var)) 'fetch t expr))))
+
+    (setq start 0)
+    (while (setq fetch-start
+                (next-single-property-change start 'fetch expr))
+      (if (get-text-property start 'fetch expr) ; it's on in range
+         (setq fetch-end fetch-start ;it's off in range
+               fetch-start start)
+       (setq fetch-end (next-single-property-change fetch-start 'fetch expr)))
+      (unless fetch-end (setq fetch-end (length expr)))
+      (remove-text-properties fetch-start fetch-end '(fetch) expr)
+      (setq expr (concat (substring expr 0 fetch-start)
+                        (format "(routine_names('%s',fetch=%d))" 
+                                (substring expr fetch-start fetch-end)
+                                fetch)
+                        (substring expr fetch-end)))
+      (setq start fetch-end))
+    (if (get-text-property 0 'fetch expr) ; Full expression, left over
+       (setq expr (format "(routine_names('%s',fetch=%d))" expr fetch)))
     expr))
 
 
     expr))
 
 
@@ -3107,13 +3215,16 @@ HELP can be non-nil for `help,', nil for 'print,' or any string into which
 to insert expression in place of the marker ___, e.g.: print,
 size(___,/DIMENSIONS)"
   (cond
 to insert expression in place of the marker ___, e.g.: print,
 size(___,/DIMENSIONS)"
   (cond
-   ((null help) (concat "print, " expr))
+   ((null help)
+    (concat "idlwave_print_safe, " expr "," 
+           (number-to-string idlwave-shell-max-print-length)))
    ((stringp help) 
     (if (string-match "\\(^\\|[^_]\\)\\(___\\)\\([^_]\\|$\\)" help)
        (concat (substring help 0 (match-beginning 2))
                expr
                (substring help (match-end 2)))))
    ((stringp help) 
     (if (string-match "\\(^\\|[^_]\\)\\(___\\)\\([^_]\\|$\\)" help)
        (concat (substring help 0 (match-beginning 2))
                expr
                (substring help (match-end 2)))))
-   (t (concat "help, " expr))))
+   (t 
+    (concat "help, " expr))))
    
 
 (defun idlwave-shell-examine-highlight ()
    
 
 (defun idlwave-shell-examine-highlight ()
@@ -3207,7 +3318,8 @@ If there is a prefix argument, display IDL process."
                  (idlwave-look-at "\\<end\\>")))
           (insert "\nend\n"))
       (save-buffer 0)))
                  (idlwave-look-at "\\<end\\>")))
           (insert "\nend\n"))
       (save-buffer 0)))
-  (idlwave-shell-send-command (concat ".run " idlwave-shell-temp-pro-file)
+  (idlwave-shell-send-command (concat ".run \"" 
+                                     idlwave-shell-temp-pro-file "\"")
                              nil 
                              (if (idlwave-shell-hide-p 'run) 'mostly)
                              nil t)
                              nil 
                              (if (idlwave-shell-hide-p 'run) 'mostly)
                              nil t)
@@ -3278,12 +3390,12 @@ Queries IDL using the string in `idlwave-shell-bp-query'."
                              'hide))
 
 (defun idlwave-shell-bp-get (bp &optional item)
                              'hide))
 
 (defun idlwave-shell-bp-get (bp &optional item)
-  "Get a value for a breakpoint.  
-BP has the form of elements in idlwave-shell-bp-alist.  Optional
-second arg ITEM is the particular value to retrieve.  ITEM can be
-'file, 'line, 'index, 'module, 'count, 'cmd, 'condition, 'disabled or
-'data.  'data returns a list of 'count, 'cmd and 'condition.  Defaults
-to 'index."
+  "Get a value for a breakpoint.  BP has the form of elements in
+idlwave-shell-bp-alist.  Optional second arg ITEM is the
+particular value to retrieve.  ITEM can be 'file, 'line, 'index,
+'module, 'count, 'cmd, 'condition, 'disabled, 'type, or
+'data.  'data returns a list of 'count, 'cmd and 'condition.
+Defaults to 'index."
   (cond
    ;; Frame
    ((eq item 'line) (nth 1 (car bp)))
   (cond
    ;; Frame
    ((eq item 'line) (nth 1 (car bp)))
@@ -3295,7 +3407,12 @@ to 'index."
    ((eq item 'condition) (nth 2 (cdr (cdr bp))))
    ((eq item 'disabled) (nth 3 (cdr (cdr bp))))
    ;; IDL breakpoint info
    ((eq item 'condition) (nth 2 (cdr (cdr bp))))
    ((eq item 'disabled) (nth 3 (cdr (cdr bp))))
    ;; IDL breakpoint info
-   ((eq item 'module) (nth 1 (car (cdr bp))))
+   ((eq item 'module) 
+    (let ((module (nth 1 (car (cdr bp)))))
+      (if (listp module) (car module) module)))
+   ((eq item 'type)
+    (let ((module (nth 1 (car (cdr bp)))))
+      (if (listp module) (nth 1 module))))
    ;;    index - default
    (t (nth 0 (car (cdr bp))))))
 
    ;;    index - default
    (t (nth 0 (car (cdr bp))))))
 
@@ -3339,14 +3456,14 @@ breakpoint overlays."
                       indmap '(1 6 2 16)))) ; index module line file
        ;; There seems to be a breakpoint listing here, parse breakpoint lines.
        (while (re-search-forward bp-re nil t)
                       indmap '(1 6 2 16)))) ; index module line file
        ;; There seems to be a breakpoint listing here, parse breakpoint lines.
        (while (re-search-forward bp-re nil t)
-         (setq index (string-to-int (match-string (nth 0 indmap)))
+         (setq index (string-to-number (match-string (nth 0 indmap)))
                module (match-string (nth 1 indmap))
                module (match-string (nth 1 indmap))
-               line (string-to-int (match-string (nth 2 indmap)))
+               line (string-to-number (match-string (nth 2 indmap)))
                file (idlwave-shell-file-name (match-string (nth 3 indmap))))
          (if (eq bp-re bp-re55)
              (setq count (if (match-string 10) 1 
                            (if (match-string 8)
                file (idlwave-shell-file-name (match-string (nth 3 indmap))))
          (if (eq bp-re bp-re55)
              (setq count (if (match-string 10) 1 
                            (if (match-string 8)
-                               (string-to-int (match-string 8))))
+                               (string-to-number (match-string 8))))
                    condition (match-string 13)
                    disabled (not (null (match-string 15)))))
                    
                    condition (match-string 13)
                    disabled (not (null (match-string 15)))))
                    
@@ -3388,7 +3505,9 @@ If BP frame is in `idlwave-shell-bp-alist' updates the breakpoint data."
 and third args, DATA and MODULE, are optional.  Returns a breakpoint
 of the format used in `idlwave-shell-bp-alist'.  Can be used in commands
 attempting match a breakpoint in `idlwave-shell-bp-alist'."
 and third args, DATA and MODULE, are optional.  Returns a breakpoint
 of the format used in `idlwave-shell-bp-alist'.  Can be used in commands
 attempting match a breakpoint in `idlwave-shell-bp-alist'."
-  (cons frame (cons (list nil module) data)))
+  (cons frame ;; (file line)
+       (cons (list nil module) ;; (index_id (module type) | module)
+             data)))           ;; (count command condition disabled)
 
 (defvar idlwave-shell-old-bp nil
   "List of breakpoints previous to setting a new breakpoint.")
 
 (defvar idlwave-shell-old-bp nil
   "List of breakpoints previous to setting a new breakpoint.")
@@ -3401,7 +3520,8 @@ Otherwise return the filename in bp."
       ((bp-file (idlwave-shell-bp-get bp 'file))
        (bp-module (idlwave-shell-bp-get bp 'module))
        (internal-file-list 
       ((bp-file (idlwave-shell-bp-get bp 'file))
        (bp-module (idlwave-shell-bp-get bp 'module))
        (internal-file-list 
-       (cdr (assoc bp-module idlwave-shell-sources-alist))))
+       (if bp-module
+           (cdr (assoc bp-module idlwave-shell-sources-alist)))))
     (if (and internal-file-list
             (equal bp-file (nth 0 internal-file-list)))
         (nth 1 internal-file-list)
     (if (and internal-file-list
             (equal bp-file (nth 0 internal-file-list)))
         (nth 1 internal-file-list)
@@ -3421,56 +3541,51 @@ specified.  If NO-SHOW is non-nil, don't do any updating."
      (idlwave-shell-filter-bp (quote ,no-show))
      (setq idlwave-shell-old-bp idlwave-shell-bp-alist))
    'hide)
      (idlwave-shell-filter-bp (quote ,no-show))
      (setq idlwave-shell-old-bp idlwave-shell-bp-alist))
    'hide)
-  ;; Get sources for IDL compiled procedures followed by setting
-  ;; breakpoint.
-  (idlwave-shell-send-command
-   idlwave-shell-sources-query
-   `(progn
-     (idlwave-shell-sources-filter)
-     (idlwave-shell-set-bp2 (quote ,bp) (quote ,no-show)))
-   'hide))
 
 
-(defun idlwave-shell-set-bp2 (bp &optional no-show)
-  "Use results of breakpoint and sources query to set bp.
-Use the count argument with IDLs breakpoint command.
-We treat a count of 1 as a temporary breakpoint. 
-Counts greater than 1 use the IDL AFTER=count keyword to break
-only after reaching the statement count times."
+  ;; Get sources for this routine in the sources list
+  (idlwave-shell-module-source-query (idlwave-shell-bp-get bp 'module)
+                                    (idlwave-shell-bp-get bp 'type))
   (let*
   (let*
-      ((arg (idlwave-shell-bp-get bp 'count))
-       (key (cond
-              ((not (and arg (numberp arg))) "")
-              ((= arg 1)
-               ",/once")
-              ((> arg 1)
-               (format ",after=%d" arg))))
+      ((count (idlwave-shell-bp-get bp 'count))
        (condition (idlwave-shell-bp-get bp 'condition))
        (condition (idlwave-shell-bp-get bp 'condition))
-       (key (concat key 
-                   (if condition (concat ",CONDITION=\"" condition "\""))))
+       (disabled (idlwave-shell-bp-get bp 'disabled))
+       (key (concat (if (and count (numberp count))
+                       (cond
+                        ((= count 1) ",/once")
+                        ((> count 1) (format ",after=%d" count))))
+                   (if condition (concat ",CONDITION=\"" condition "\""))
+                   ;; IDL can't simultaneously set a condition/count
+                   ;; and disable a breakpoint, but it does keep both
+                   ;; of these when resetting the same BP.  We assume
+                   ;; DISABLE and CONDITION/COUNT are not set
+                   ;; together for a newly created breakpoint.
+                   (if (and disabled (not condition) (not count))
+                           ",/DISABLE")))
        (line (idlwave-shell-bp-get bp 'line)))
     (idlwave-shell-send-command
      (concat "breakpoint,'" 
             (idlwave-shell-sources-bp bp) "',"
             (if (integerp line) (setq line (int-to-string line)))
             key)
        (line (idlwave-shell-bp-get bp 'line)))
     (idlwave-shell-send-command
      (concat "breakpoint,'" 
             (idlwave-shell-sources-bp bp) "',"
             (if (integerp line) (setq line (int-to-string line)))
             key)
-     ;; Check for failure and look for breakpoint in IDL's list
+     ;; Check for failure and adjust breakpoint to match IDL's list
      `(progn
        (if (idlwave-shell-set-bp-check (quote ,bp))
      `(progn
        (if (idlwave-shell-set-bp-check (quote ,bp))
-           (idlwave-shell-set-bp3 (quote ,bp) (quote ,no-show))))
+           (idlwave-shell-set-bp-adjust (quote ,bp) (quote ,no-show))))
      ;; hide output?
      (idlwave-shell-hide-p 'breakpoint)
      'preempt t)))
 
      ;; hide output?
      (idlwave-shell-hide-p 'breakpoint)
      'preempt t)))
 
-(defun idlwave-shell-set-bp3 (bp &optional no-show)
+(defun idlwave-shell-set-bp-adjust (bp &optional no-show)
   "Find the breakpoint in IDL's internal list of breakpoints."
   "Find the breakpoint in IDL's internal list of breakpoints."
-  (idlwave-shell-send-command idlwave-shell-bp-query
-                             `(progn
-                                (idlwave-shell-filter-bp (quote ,no-show))
-                                (idlwave-shell-new-bp (quote ,bp))
-                                (unless (quote ,no-show)
-                                  (idlwave-shell-update-bp-overlays)))
-                             'hide
-                             'preempt))
+  (idlwave-shell-send-command 
+   idlwave-shell-bp-query
+   `(progn
+      (idlwave-shell-filter-bp 'no-show)
+      (idlwave-shell-new-bp (quote ,bp))
+      (unless (quote ,no-show)
+       (idlwave-shell-update-bp-overlays)))
+   'hide
+   'preempt))
 
 (defun idlwave-shell-find-bp (frame)
   "Return breakpoint from `idlwave-shell-bp-alist' for frame.
 
 (defun idlwave-shell-find-bp (frame)
   "Return breakpoint from `idlwave-shell-bp-alist' for frame.
@@ -3521,10 +3636,14 @@ considered the new breakpoint if the file name of frame matches."
   "Alist of overlays marking breakpoints")
 (defvar idlwave-shell-bp-glyph)
 
   "Alist of overlays marking breakpoints")
 (defvar idlwave-shell-bp-glyph)
 
+(defvar idlwave-shell-debug-line-map (make-sparse-keymap))
+(define-key idlwave-shell-debug-line-map 
+  (if (featurep 'xemacs) [button3] [mouse-3])
+  'idlwave-shell-mouse-active-bp)
+
 (defun idlwave-shell-update-bp-overlays ()
   "Update the overlays which mark breakpoints in the source code.
 Existing overlays are recycled, in order to minimize consumption."
 (defun idlwave-shell-update-bp-overlays ()
   "Update the overlays which mark breakpoints in the source code.
 Existing overlays are recycled, in order to minimize consumption."
-  ;(message "Updating Overlays")
   (when idlwave-shell-mark-breakpoints
     (let ((ov-alist (copy-alist idlwave-shell-bp-overlays))
          (bp-list idlwave-shell-bp-alist)
   (when idlwave-shell-mark-breakpoints
     (let ((ov-alist (copy-alist idlwave-shell-bp-overlays))
          (bp-list idlwave-shell-bp-alist)
@@ -3568,12 +3687,19 @@ Existing overlays are recycled, in order to minimize consumption."
                  (delq nil
                        (list
                         (if count
                  (delq nil
                        (list
                         (if count
-                            (concat "n=" (int-to-string count)))
+                            (concat "after:" (int-to-string count)))
                         (if condition
                         (if condition
-                            (concat "condition: " condition))
+                            (concat "condition:" condition))
                         (if disabled "disabled"))))
                         (if disabled "disabled"))))
-                (help-text (if help-list 
-                               (mapconcat 'identity help-list ",")))
+                (help-text (concat 
+                            "BP " 
+                            (int-to-string (idlwave-shell-bp-get bp))
+                            (if help-list 
+                                (concat 
+                                 " - " 
+                                 (mapconcat 'identity help-list ", ")))
+                            (if (and (not count) (not condition))
+                                " (use mouse-3 for breakpoint actions)")))
                 (full-type (if disabled
                                (intern (concat (symbol-name type)
                                                "-disabled"))
                 (full-type (if disabled
                                (intern (concat (symbol-name type)
                                                "-disabled"))
@@ -3581,9 +3707,10 @@ Existing overlays are recycled, in order to minimize consumption."
                 (ov-existing (assq full-type ov-alist))
                 (ov (or (and (cdr ov-existing)
                              (pop (cdr ov-existing)))
                 (ov-existing (assq full-type ov-alist))
                 (ov (or (and (cdr ov-existing)
                              (pop (cdr ov-existing)))
-                        (idlwave-shell-make-new-bp-overlay 
-                         type disabled help-text)))
+                        (idlwave-shell-make-new-bp-overlay type disabled)))
                 match)
                 match)
+           (if idlwave-shell-breakpoint-popup-menu
+               (overlay-put ov 'help-echo help-text))
            (move-overlay ov beg end)
            (if (setq match (assq full-type idlwave-shell-bp-overlays))
                (push ov (cdr match))
            (move-overlay ov beg end)
            (if (setq match (assq full-type idlwave-shell-bp-overlays))
                (push ov (cdr match))
@@ -3595,26 +3722,29 @@ Existing overlays are recycled, in order to minimize consumption."
                (setq old-buffers (delq (current-buffer) old-buffers)))
            (if (fboundp 'set-specifier) ;; XEmacs
                (set-specifier left-margin-width (cons (current-buffer) 2))
                (setq old-buffers (delq (current-buffer) old-buffers)))
            (if (fboundp 'set-specifier) ;; XEmacs
                (set-specifier left-margin-width (cons (current-buffer) 2))
-             (setq left-margin-width 2))
-           (if (setq win (get-buffer-window (current-buffer) t))
-               (set-window-buffer win (current-buffer))))))
+             (if (< left-margin-width 2)
+                 (setq left-margin-width 2)))
+           (let ((window (get-buffer-window (current-buffer) 0)))
+             (if window
+                 (set-window-margins 
+                  window left-margin-width right-margin-width))))))
       (if use-glyph
          (while (setq buf (pop old-buffers))
            (with-current-buffer buf
              (if (fboundp 'set-specifier) ;; XEmacs
                  (set-specifier left-margin-width (cons (current-buffer) 0))
                (setq left-margin-width 0))
       (if use-glyph
          (while (setq buf (pop old-buffers))
            (with-current-buffer buf
              (if (fboundp 'set-specifier) ;; XEmacs
                  (set-specifier left-margin-width (cons (current-buffer) 0))
                (setq left-margin-width 0))
-             (if (setq win (get-buffer-window buf t))
-                 (set-window-buffer win buf))))))))
-
+             (let ((window (get-buffer-window buf 0)))
+               (if window
+                   (set-window-margins 
+                    window left-margin-width right-margin-width)))))))))
 
 
-(defun idlwave-shell-make-new-bp-overlay (&optional type disabled help)
+(defun idlwave-shell-make-new-bp-overlay (&optional type disabled)
   "Make a new overlay for highlighting breakpoints.  
 
 This stuff is strongly dependant upon the version of Emacs.  If TYPE
 is passed, make an overlay of that type ('bp or 'bp-cond, currently
   "Make a new overlay for highlighting breakpoints.  
 
 This stuff is strongly dependant upon the version of Emacs.  If TYPE
 is passed, make an overlay of that type ('bp or 'bp-cond, currently
-only for glyphs).  If HELP is set, use it to make a tooltip with that
-text popup."
+only for glyphs)."
   (let ((ov (make-overlay 1 1))
        (use-glyph (and (memq idlwave-shell-mark-breakpoints '(t glyph))
                        idlwave-shell-bp-glyph))
   (let ((ov (make-overlay 1 1))
        (use-glyph (and (memq idlwave-shell-mark-breakpoints '(t glyph))
                        idlwave-shell-bp-glyph))
@@ -3625,6 +3755,10 @@ text popup."
     (if (featurep 'xemacs)
        ;; This is XEmacs
        (progn
     (if (featurep 'xemacs)
        ;; This is XEmacs
        (progn
+         (when idlwave-shell-breakpoint-popup-menu
+           (set-extent-property ov 'mouse-face 'highlight)
+           (set-extent-property ov 'keymap idlwave-shell-debug-line-map))
+
          (cond 
           ;; tty's cannot display glyphs
           ((eq (console-type) 'tty)
          (cond 
           ;; tty's cannot display glyphs
           ((eq (console-type) 'tty)
@@ -3645,6 +3779,9 @@ text popup."
           (t nil))
          (set-extent-priority ov -1))  ; make stop line face prevail
       ;; This is Emacs
           (t nil))
          (set-extent-priority ov -1))  ; make stop line face prevail
       ;; This is Emacs
+      (when idlwave-shell-breakpoint-popup-menu
+       (overlay-put ov 'mouse-face 'highlight)
+       (overlay-put ov 'keymap idlwave-shell-debug-line-map))
       (cond
        (window-system
        (if use-glyph
       (cond
        (window-system
        (if use-glyph
@@ -3658,9 +3795,7 @@ text popup."
                   (propertize "@" 
                               'display 
                               (list (list 'margin 'left-margin)
                   (propertize "@" 
                               'display 
                               (list (list 'margin 'left-margin)
-                                    image-props)
-                              'mouse-face 'highlight
-                              'help-echo help))
+                                    image-props)))
              (overlay-put ov 'before-string string))
          ;; just the face
          (overlay-put ov 'face face)))
              (overlay-put ov 'before-string string))
          ;; just the face
          (overlay-put ov 'face face)))
@@ -3673,6 +3808,54 @@ text popup."
        (t nil)))
     ov))
 
        (t nil)))
     ov))
 
+(defun idlwave-shell-mouse-active-bp (ev)
+  "Does right-click mouse action on breakpoint lines."
+  (interactive "e")
+  (if ev (mouse-set-point ev))
+  (let ((bp (idlwave-shell-find-bp (idlwave-shell-current-frame)))
+       index condition count select cmd disabled)
+    (unless bp
+      (error "Breakpoint not found"))
+    (setq index (int-to-string (idlwave-shell-bp-get bp))
+         condition (idlwave-shell-bp-get bp 'condition)
+         cmd (idlwave-shell-bp-get bp 'cmd)
+         count (idlwave-shell-bp-get bp 'count)
+         disabled (idlwave-shell-bp-get bp 'disabled))
+    (setq select (idlwave-popup-select 
+                 ev 
+                 (delq nil 
+                       (list (if disabled "Enable" "Disable")
+                             "Clear"
+                             "Clear All"
+                             (if condition "Remove Condition" "Add Condition")
+                             (if condition "Change Condition")
+                             (if count "Remove Repeat Count" 
+                               "Add Repeat Count")
+                             (if count "Change Repeat Count")))
+                 (concat "BreakPoint " index)))
+    (if select 
+       (cond 
+        ((string-equal select "Clear All")
+         (idlwave-shell-clear-all-bp))
+        ((string-equal select "Clear")
+         (idlwave-shell-clear-current-bp))
+        ((string-match "Condition" select)
+         (idlwave-shell-break-here count cmd 
+                                   (if (or (not condition)
+                                           (string-match "Change" select))
+                                     (read-string "Break Condition: "))
+                                   disabled))
+        ((string-match "Count" select)
+         (idlwave-shell-break-here (if (or (not count)
+                                           (string-match "Change" select))
+                                       (string-to-number
+                                        (read-string "Break After Count: ")))
+                                   cmd condition disabled))
+        ((string-match "able$" select)
+         (idlwave-shell-toggle-enable-current-bp))
+        (t 
+         (message "Unimplemented: %s" select))))))
+  
 (defun idlwave-shell-edit-default-command-line (arg)
   "Edit the current execute command."
   (interactive "P")
 (defun idlwave-shell-edit-default-command-line (arg)
   "Edit the current execute command."
   (interactive "P")
@@ -3753,8 +3936,11 @@ handled by this command."
                       ((eq action 'compile) ".compile ")
                       ((eq action 'batch)   "@")
                       (t (error "Unknown action %s" action)))
                       ((eq action 'compile) ".compile ")
                       ((eq action 'batch)   "@")
                       (t (error "Unknown action %s" action)))
-                idlwave-shell-last-save-and-action-file)
-        'idlwave-shell-maybe-update-routine-info
+                "\""
+                idlwave-shell-last-save-and-action-file
+                "\"")
+        `(idlwave-shell-maybe-update-routine-info nil
+          ,idlwave-shell-last-save-and-action-file)
         (if (idlwave-shell-hide-p 'run) 'mostly) nil t)
        (idlwave-shell-bp-query))
     (let ((msg (format "No such file %s" 
         (if (idlwave-shell-hide-p 'run) 'mostly) nil t)
        (idlwave-shell-bp-query))
     (let ((msg (format "No such file %s" 
@@ -3762,14 +3948,14 @@ handled by this command."
       (setq idlwave-shell-last-save-and-action-file nil)
       (error msg))))
 
       (setq idlwave-shell-last-save-and-action-file nil)
       (error msg))))
 
-(defun idlwave-shell-maybe-update-routine-info (&optional wait)
+(defun idlwave-shell-maybe-update-routine-info (&optional wait file)
   "Update the routine info if the shell is not stopped at an error."
   (if (and (not idlwave-shell-is-stopped)
           (or (eq t idlwave-auto-routine-info-updates)
               (memq 'compile-buffer idlwave-auto-routine-info-updates))
           idlwave-query-shell-for-routine-info
           idlwave-routines)
   "Update the routine info if the shell is not stopped at an error."
   (if (and (not idlwave-shell-is-stopped)
           (or (eq t idlwave-auto-routine-info-updates)
               (memq 'compile-buffer idlwave-auto-routine-info-updates))
           idlwave-query-shell-for-routine-info
           idlwave-routines)
-      (idlwave-shell-update-routine-info t nil wait)))
+      (idlwave-shell-update-routine-info t nil wait file)))
 
 (defvar idlwave-shell-sources-query "help,/source,/full"
   "IDL command to obtain source files for compiled procedures.")
 
 (defvar idlwave-shell-sources-query "help,/source,/full"
   "IDL command to obtain source files for compiled procedures.")
@@ -3780,10 +3966,36 @@ Elements of the alist have the form:
 
   (module name . (source-file-truename idlwave-internal-filename)).")
 
 
   (module name . (source-file-truename idlwave-internal-filename)).")
 
+(defun idlwave-shell-module-source-query (module &optional type)
+  "Determine the source file for a given module.
+Query as a function if TYPE set to something beside 'pro."
+  (if module
+      (idlwave-shell-send-command 
+       (format "print,(routine_info('%s',/SOURCE%s)).PATH" module
+              (if (eq type 'pro) "" ",/FUNCTIONS"))
+       `(idlwave-shell-module-source-filter ,module)
+       'hide 'wait)))
+
+(defun idlwave-shell-module-source-filter (module)
+  "Get module source, and update idlwave-shell-sources-alist."
+  (let ((old (assoc (upcase module) idlwave-shell-sources-alist))
+       filename)
+    (when (string-match "\.PATH *[\n\r]\\([^%][^\r\n]+\\)[\n\r]"
+                       idlwave-shell-command-output)
+      (setq filename (substring idlwave-shell-command-output 
+                               (match-beginning 1) (match-end 1)))
+      (if old
+         (setcdr old (list (idlwave-shell-file-name filename) filename))
+       (setq idlwave-shell-sources-alist
+             (append idlwave-shell-sources-alist 
+                     (list (cons (upcase module)
+                                 (list (idlwave-shell-file-name filename) 
+                                       filename)))))))))
+  
 (defun idlwave-shell-sources-query ()
 (defun idlwave-shell-sources-query ()
-  "Determine source files for IDL compiled procedures.
+  "Determine source files for all IDL compiled procedures.
 Queries IDL using the string in `idlwave-shell-sources-query'."
 Queries IDL using the string in `idlwave-shell-sources-query'."
-'  (interactive)
+  (interactive)
   (idlwave-shell-send-command idlwave-shell-sources-query
                              'idlwave-shell-sources-filter
                              'hide))
   (idlwave-shell-send-command idlwave-shell-sources-query
                              'idlwave-shell-sources-filter
                              'hide))
@@ -3848,7 +4060,9 @@ list elements of the form:
    idlwave-shell-bp-query
    '(progn
       (idlwave-shell-filter-bp)
    idlwave-shell-bp-query
    '(progn
       (idlwave-shell-filter-bp)
-      (mapcar 'idlwave-shell-clear-bp idlwave-shell-bp-alist))
+      (mapcar (lambda (x) (idlwave-shell-clear-bp x 'no-query))
+             idlwave-shell-bp-alist)
+      (idlwave-shell-bp-query))
    'hide))
 
 (defun idlwave-shell-list-all-bp ()
    'hide))
 
 (defun idlwave-shell-list-all-bp ()
@@ -3877,7 +4091,7 @@ list elements of the form:
                      (idlwave-shell-file-name
                       (buffer-substring (match-beginning 1 ) 
                                        (match-end 1))))
                      (idlwave-shell-file-name
                       (buffer-substring (match-beginning 1 ) 
                                        (match-end 1))))
-                   (string-to-int
+                   (string-to-number
                     (buffer-substring (match-beginning 2)
                                       (match-end 2)))))
             ;; Try to find the column of the error
                     (buffer-substring (match-beginning 2)
                                       (match-end 2)))))
             ;; Try to find the column of the error
@@ -3889,7 +4103,7 @@ list elements of the form:
       (setq idlwave-shell-error-last (point)))
     (if frame
         (progn
       (setq idlwave-shell-error-last (point)))
     (if frame
         (progn
-          (idlwave-shell-display-line frame col 'no-debug))
+          (idlwave-shell-display-line frame col 'disable))
       (beep)
       (message "No more errors."))))
 
       (beep)
       (message "No more errors."))))
 
@@ -3920,13 +4134,16 @@ Otherwise, just expand the file name."
 
 ;(define-key idlwave-shell-mode-map "\M-?" 'comint-dynamic-list-completions)
 ;(define-key idlwave-shell-mode-map "\t" 'comint-dynamic-complete)
 
 ;(define-key idlwave-shell-mode-map "\M-?" 'comint-dynamic-list-completions)
 ;(define-key idlwave-shell-mode-map "\t" 'comint-dynamic-complete)
+
+(define-key idlwave-shell-mode-map "\C-w"     'comint-kill-region)
 (define-key idlwave-shell-mode-map "\t"       'idlwave-shell-complete)
 (define-key idlwave-shell-mode-map "\M-\t"    'idlwave-shell-complete)
 (define-key idlwave-shell-mode-map "\C-c\C-s" 'idlwave-shell)
 (define-key idlwave-shell-mode-map "\C-c?"    'idlwave-routine-info)
 (define-key idlwave-shell-mode-map "\C-g"     'idlwave-keyboard-quit)
 (define-key idlwave-shell-mode-map "\M-?"     'idlwave-context-help)
 (define-key idlwave-shell-mode-map "\t"       'idlwave-shell-complete)
 (define-key idlwave-shell-mode-map "\M-\t"    'idlwave-shell-complete)
 (define-key idlwave-shell-mode-map "\C-c\C-s" 'idlwave-shell)
 (define-key idlwave-shell-mode-map "\C-c?"    'idlwave-routine-info)
 (define-key idlwave-shell-mode-map "\C-g"     'idlwave-keyboard-quit)
 (define-key idlwave-shell-mode-map "\M-?"     'idlwave-context-help)
-(define-key idlwave-shell-mode-map [(control meta ?\?)] 'idlwave-online-help)
+(define-key idlwave-shell-mode-map [(control meta ?\?)] 
+  'idlwave-help-assistant-help-with-topic)
 (define-key idlwave-shell-mode-map "\C-c\C-i" 'idlwave-update-routine-info)
 (define-key idlwave-shell-mode-map "\C-c\C-y" 'idlwave-shell-char-mode-loop)
 (define-key idlwave-shell-mode-map "\C-c\C-x" 'idlwave-shell-send-char)
 (define-key idlwave-shell-mode-map "\C-c\C-i" 'idlwave-update-routine-info)
 (define-key idlwave-shell-mode-map "\C-c\C-y" 'idlwave-shell-char-mode-loop)
 (define-key idlwave-shell-mode-map "\C-c\C-x" 'idlwave-shell-send-char)
@@ -4064,6 +4281,8 @@ Otherwise, just expand the file name."
   'idlwave-shell-stack-down)
 (define-key idlwave-shell-electric-debug-mode-map "_" 
   'idlwave-shell-stack-down)
   'idlwave-shell-stack-down)
 (define-key idlwave-shell-electric-debug-mode-map "_" 
   'idlwave-shell-stack-down)
+(define-key idlwave-shell-electric-debug-mode-map "e" 
+  '(lambda () (interactive) (idlwave-shell-print '(16))))
 (define-key idlwave-shell-electric-debug-mode-map "q" 'idlwave-shell-retall)
 (define-key idlwave-shell-electric-debug-mode-map "t" 
   '(lambda () (interactive) (idlwave-shell-send-command "help,/TRACE")))
 (define-key idlwave-shell-electric-debug-mode-map "q" 'idlwave-shell-retall)
 (define-key idlwave-shell-electric-debug-mode-map "t" 
   '(lambda () (interactive) (idlwave-shell-send-command "help,/TRACE")))
@@ -4087,15 +4306,16 @@ Otherwise, just expand the file name."
   ;; session until we return or hit $MAIN$.  Cancel this suppression
   ;; if it's explicitly turned on.
   (if idlwave-shell-electric-debug-mode
   ;; session until we return or hit $MAIN$.  Cancel this suppression
   ;; if it's explicitly turned on.
   (if idlwave-shell-electric-debug-mode
-      (setq idlwave-shell-suppress-electric-debug t)
-    (setq idlwave-shell-suppress-electric-debug nil))
-  (idlwave-shell-electric-debug-mode))
+      (progn ;; Turn it off, and make sure it stays off.
+       (setq idlwave-shell-suppress-electric-debug t)
+       (idlwave-shell-electric-debug-mode 0))
+    (setq idlwave-shell-suppress-electric-debug nil)
+    (idlwave-shell-electric-debug-mode t)))
 
 
-(defvar idlwave-shell-electric-debug-mode) ; defined by easy-mmode
 (defvar idlwave-shell-electric-debug-read-only) 
 (defvar idlwave-shell-electric-debug-buffers nil)
 
 (defvar idlwave-shell-electric-debug-read-only) 
 (defvar idlwave-shell-electric-debug-buffers nil)
 
-(easy-mmode-define-minor-mode idlwave-shell-electric-debug-mode
+(define-minor-mode idlwave-shell-electric-debug-mode
   "Toggle Electric Debug mode.
 With no argument, this command toggles the mode. 
 Non-null prefix argument turns on the mode.
   "Toggle Electric Debug mode.
 With no argument, this command toggles the mode. 
 Non-null prefix argument turns on the mode.
@@ -4144,6 +4364,7 @@ idlwave-shell-electric-debug-mode-map)
   (force-mode-line-update))
 
 ;; Turn it off in all relevant buffers
   (force-mode-line-update))
 
 ;; Turn it off in all relevant buffers
+(defvar idlwave-shell-electric-debug-buffers nil)
 (defun idlwave-shell-electric-debug-all-off ()
   (setq idlwave-shell-suppress-electric-debug nil)
   (let ((buffers idlwave-shell-electric-debug-buffers)
 (defun idlwave-shell-electric-debug-all-off ()
   (setq idlwave-shell-suppress-electric-debug nil)
   (let ((buffers idlwave-shell-electric-debug-buffers)
@@ -4155,7 +4376,7 @@ idlwave-shell-electric-debug-mode-map)
          (when (and (eq major-mode 'idlwave-mode)
                     buffer-file-name
                     idlwave-shell-electric-debug-mode)
          (when (and (eq major-mode 'idlwave-mode)
                     buffer-file-name
                     idlwave-shell-electric-debug-mode)
-           (idlwave-shell-electric-debug-mode))))))
+           (idlwave-shell-electric-debug-mode 0))))))
   (setq idlwave-shell-electric-debug-buffers nil))
 
 ;; Show the help text
   (setq idlwave-shell-electric-debug-buffers nil))
 
 ;; Show the help text
@@ -4201,11 +4422,11 @@ idlwave-shell-electric-debug-mode-map)
      ["Edit Default Cmd" idlwave-shell-edit-default-command-line t])
     ("Breakpoints"
      ["Set Breakpoint" idlwave-shell-break-here 
      ["Edit Default Cmd" idlwave-shell-edit-default-command-line t])
     ("Breakpoints"
      ["Set Breakpoint" idlwave-shell-break-here 
-      :keys "C-c C-d C-c" :active (eq major-mode 'idlwave-mode)]
+      :keys "C-c C-d C-b" :active (eq major-mode 'idlwave-mode)]
      ("Set Special Breakpoint"
       ["Set After Count Breakpoint"
        (progn
      ("Set Special Breakpoint"
       ["Set After Count Breakpoint"
        (progn
-       (let ((count (string-to-int (read-string "Break after count: "))))
+       (let ((count (string-to-number (read-string "Break after count: "))))
              (if (integerp count) (idlwave-shell-break-here count))))
        :active (eq major-mode 'idlwave-mode)]
       ["Set Condition Breakpoint"
              (if (integerp count) (idlwave-shell-break-here count))))
        :active (eq major-mode 'idlwave-mode)]
       ["Set Condition Breakpoint"