]> 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.
-;; 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>
-;; 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
-;; 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,
 
 ;; 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.
 ;;
-;; 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,
   :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. 
-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.
 
@@ -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-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
@@ -245,7 +253,7 @@ to set this option to nil."
   :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."
@@ -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))))
 
+(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 
-  '(("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)")
@@ -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(___)")
+    ("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.  
@@ -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)
-    (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.
@@ -428,6 +445,16 @@ end"
          (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
@@ -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.
-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
@@ -480,11 +507,11 @@ line where IDL is stopped.  See also `idlwave-shell-mark-stop-line'."
 
 (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
-       (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
@@ -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.
-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
@@ -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.")
 
-(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)
 
-(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 
-  '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)
 
-(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
@@ -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.")
+  "The overlay for the examined expression.")
 (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)
+(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)
 
+(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")
 
@@ -742,9 +780,6 @@ with `*'s."
 (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.
 ;;; 
@@ -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.
+  e          Prompt for an expression to print.
 
  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)
-  (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-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
-  ;;(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)
@@ -1040,7 +1076,7 @@ IDL has currently stepped.")
   (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?
@@ -1055,31 +1091,32 @@ IDL has currently stepped.")
   (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 
-   (format "defsysv,'!idlwave_version','%s',1" 
-          idlwave-mode-version)
+   (format "defsysv,'!idlwave_version','%s',1" idlwave-mode-version)
    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))
-        (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)
-      (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)
@@ -1088,11 +1125,13 @@ IDL has currently stepped.")
                          (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 (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))))
@@ -1201,12 +1240,14 @@ See also the variable `idlwave-shell-prompt-pattern'.
          (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))))
-  ;; 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 
@@ -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.  
 
-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
@@ -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)))
-;    (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))
@@ -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)
-             (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))))
 
@@ -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))
-       (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)
@@ -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 (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
-;            (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
-                     (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."
@@ -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.")
 
+(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
@@ -1698,9 +1730,8 @@ the above."
                     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))
@@ -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
-      (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
@@ -1771,30 +1804,31 @@ the above."
      ;; Otherwise, no particular state
      (t (setq idlwave-shell-current-state nil)))))
 
+
 (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)))
@@ -1811,7 +1845,7 @@ statements."
       ;; 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))))
@@ -1935,14 +1969,17 @@ CLOSE, /ALL
 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
@@ -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)))
-    (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))
@@ -2070,7 +2104,7 @@ HEAP_GC, /VERBOSE"
 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))))
@@ -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
-       (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
@@ -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."
-  (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)))))
 
@@ -2269,14 +2301,14 @@ overlays."
     (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
-     (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."
@@ -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)))
 
-(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)
-      ;; 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))
-       ;; 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))
-       ;; 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.
-        (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.
@@ -2349,15 +2389,15 @@ debug mode."
              (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))
 
-       ;; 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)))
 
-       ;; Enter the buffer and mark the line
+       ;; enter the buffer and mark the line
         (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
-                ;; 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 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 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))
          
-         ;; Enter electric debug mode, if not prohibited and not in
+         ;; enter electric debug mode, if not prohibited and not in
          ;; 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 
-       ;; 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)))
@@ -2418,6 +2466,7 @@ debug mode."
   (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))
@@ -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))
+  (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))
 
-(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
@@ -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.
 
-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) 
@@ -2452,7 +2503,7 @@ the breakpoint."
   (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))
 
@@ -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
-  (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 "
-                       (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
-               (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.")
-          (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.
@@ -2501,6 +2556,7 @@ breakpoint can not be set."
 (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) 
@@ -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)
+  (idlwave-shell-stop-line-pending)
   (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)
+  (idlwave-shell-stop-line-pending)
   (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)
+  (idlwave-shell-stop-line-pending)  
   (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)))
@@ -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-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.
@@ -2563,7 +2622,10 @@ Returns nil if unable to obtain a module name."
       (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.
@@ -2576,7 +2638,10 @@ at a breakpoint."
 
 (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)))
@@ -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)
+  ;; temporarily disable all other breakpoints
   (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
@@ -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)
-  (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."
-  (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
@@ -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))))
-    (unless bp-line (error "No further breakpoints."))
+    (unless bp-line (error "No further breakpoints"))
     (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")
-     (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))))
@@ -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)
-  (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)
@@ -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")
+
+  ;; 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)))
@@ -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)))
-          expr beg end cmd examine-hook)
+          expr beg end cmd)
       (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))
-      (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)
       
@@ -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 "[ \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)
@@ -2947,7 +3024,7 @@ idlw-shell-examine-alist via mini-buffer shortcut key."
        ;;(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
@@ -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)
 
+
+(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)
@@ -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)
-        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
@@ -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)
-           start (match-beginning 2)
+           start (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) "]*" 
-                                  (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))
 
 
@@ -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
-   ((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)))))
-   (t (concat "help, " expr))))
+   (t 
+    (concat "help, " expr))))
    
 
 (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-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)
@@ -3278,12 +3390,12 @@ Queries IDL using the string in `idlwave-shell-bp-query'."
                              '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)))
@@ -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 '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))))))
 
@@ -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)
-         (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))
-               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)
-                               (string-to-int (match-string 8))))
+                               (string-to-number (match-string 8))))
                    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'."
-  (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.")
@@ -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 
-       (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)
@@ -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)
-  ;; 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*
-      ((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))
-       (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)
-     ;; 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))
-           (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)))
 
-(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."
-  (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.
@@ -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)
 
+(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."
-  ;(message "Updating Overlays")
   (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
-                            (concat "n=" (int-to-string count)))
+                            (concat "after:" (int-to-string count)))
                         (if condition
-                            (concat "condition: " condition))
+                            (concat "condition:" condition))
                         (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"))
@@ -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)))
-                        (idlwave-shell-make-new-bp-overlay 
-                         type disabled help-text)))
+                        (idlwave-shell-make-new-bp-overlay type disabled)))
                 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))
@@ -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 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 (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
-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))
@@ -3625,6 +3755,10 @@ text popup."
     (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)
@@ -3645,6 +3779,9 @@ text popup."
           (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
@@ -3658,9 +3795,7 @@ text popup."
                   (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)))
@@ -3673,6 +3808,54 @@ text popup."
        (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")
@@ -3753,8 +3936,11 @@ handled by this command."
                       ((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" 
@@ -3762,14 +3948,14 @@ handled by this command."
       (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)
-      (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.")
@@ -3780,10 +3966,36 @@ Elements of the alist have the form:
 
   (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 ()
-  "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'."
-'  (interactive)
+  (interactive)
   (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)
-      (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 ()
@@ -3877,7 +4091,7 @@ list elements of the form:
                      (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
@@ -3889,7 +4103,7 @@ list elements of the form:
       (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."))))
 
@@ -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 "\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 [(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)
@@ -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)
+(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")))
@@ -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
-      (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)
 
-(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.
@@ -4144,6 +4364,7 @@ idlwave-shell-electric-debug-mode-map)
   (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)
@@ -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)
-           (idlwave-shell-electric-debug-mode))))))
+           (idlwave-shell-electric-debug-mode 0))))))
   (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 
-      :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
-       (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"