   (forward-line -1)
   (yacas-tab))
 
-(defun yacas-send-filter (proc string)
-  "The filter for a Yacas process.
-It will tell when the process has stopped (by looking for the prompt)."
-     (let ((old-buffer (current-buffer)))
-       (unwind-protect
-	   (let (moving)
-	     (set-buffer (process-buffer proc))
-	     (setq moving (= (point) (process-mark proc)))
-	     (save-excursion
-	       ;; Insert the text, moving the process-marker.
-	       (goto-char (process-mark proc))
-	       (insert string)
-	       (set-marker (process-mark proc) (point)))
-	     (if moving (goto-char (process-mark proc))))
-	 (set-buffer old-buffer)
-	 (if (not (< (length string) yacas-prompt-width))
-	     (if 
-		 (string= 
-		  (substring string (- yacas-prompt-width)) 
-		  yacas-input-prompt-string)
-		 (setq yacas-send-filter-active nil))))))
 
 ;;; Invoking Yacas in an inferior shell.
 
-(defun yacas (&optional arg)
-  "Run yacas in a buffer, without shell. Exiting yacas will kill the buffer.
-The buffer is called *Yacas*. The buffer is put in shell-mode with
-a yacas-syntax-table."
-  (interactive)
-  (if (get-buffer "*Yacas*")
-      nil
-    (yacas-start-shell))
-  (switch-to-buffer "*Yacas*")
-  (if arg
-      nil
-    (delete-other-windows)))
-
-(defvar yacas-shell-map nil
-  "Keymap used in the *Yacas* buffer")
-
-(defun yacas-start-shell ()
-  "Start a Yacas shell."
-  (require 'shell)
+(defvar inferior-yacas-mode-map nil)
+
+(if inferior-yacas-mode-map ()
+  (let ((map (copy-keymap comint-mode-map)))
+    (define-key map "\C-c\C-k"    'yacas-stop) 
+    (define-key map "\C-a" 'comint-bol)
+    (define-key map "\C-c\C-h" 'yacas-help)
+    (define-key map [up] 'comint-previous-input)
+    (define-key map [down] 'comint-next-input)    
+    (define-key map [(control up)] 'previous-line)
+    (define-key map [(control down)] 'next-line)
+    (define-key map (kbd "M-TAB") 'yacas-complete)
+    (define-key map (kbd "C-TAB") 'yacas-dynamic-complete)
+    (setq inferior-yacas-mode-map map)))
+    
+(defun inferior-yacas-mode ()
+  " "
+  (interactive)
+  (comint-mode)
+  (setq major-mode 'inferior-yacas-mode)
+  (setq mode-name "Inferior Yacas")
+  (setq mode-line-process '(": %s"))
+  (use-local-map inferior-yacas-mode-map)
+  (make-local-variable 'comint-process-echoes)
+  (setq comint-process-echoes nil)
+  (make-local-variable 'comint-scroll-show-maximum-output)
+  (setq comint-scroll-show-maximum-output t)
+  (make-local-variable 'comint-prompt-regexp)
+  (setq comint-prompt-regexp (concat "^" yacas-input-prompt-string))
+  (set-syntax-table yacas-mode-syntax-table)
+  (inferior-yacas-menu-install-menus)
+  (add-hook 'kill-buffer-hook
+            (function
+             (lambda ()
+               (if (processp inferior-yacas-process)
+                   (delete-process inferior-yacas-process))
+               (setq inferior-yacas-process nil)
+               (run-hooks 'inferior-yacas-exit-hook))) t t)
+  (run-hooks 'inferior-yacas-mode-hook))
+
+;;;; Interacting with the Yacas process
+
+;;;; Starting and stopping
+
+(defun yacas ()
+  "Run yacas interactively inside a buffer."
+  (interactive)
+  (yacas-start)
+  (switch-to-buffer (process-buffer inferior-yacas-process)))
+
+(defun yacas-start ()
+  "Start a Yacas process."
+  (interactive)
+  (if (processp inferior-yacas-process)
+      (unless (eq (process-status inferior-yacas-process) 'run)
+        (delete-process inferior-yacas-process)
+        (save-excursion
+          (set-buffer "*yacas*")
+          (erase-buffer))
+        (setq inferior-yacas-process nil)))
+  (unless (processp inferior-yacas-process)
+    (setq yacas-input-end 0)
+    (let ((ybuf (make-comint "yacas" yacas-command nil yacas-args)))
+      (save-excursion
+        (set-buffer ybuf)
+        (setq inferior-yacas-process (get-buffer-process ybuf))
+        (while (not (yacas-new-prompt-p))
+          (sleep-for 0.100))
+        (inferior-yacas-mode)))))
+
+(defun yacas-stop (&optional arg)
+  "Kill the currently running Maxima process."
+  (interactive "P")
+  (if (processp inferior-yacas-process)
+      (if arg
+	  (progn 
+	    (delete-process inferior-yacas-process)
+	    (kill-buffer "*yacas*")
+	    (setq inferior-yacas-process nil))
+	(if (y-or-n-p "Really quit Yacas? ")
+	    (progn
+	      (delete-process inferior-yacas-process)
+	      (kill-buffer "*yacas*")
+	      (setq inferior-yacas-process nil))))))
+
+;;;; Sending information to the process
+
+(defun yacas-strip-string (string)
+  "Remove any spaces or newlines at the beginning and end of the string"
+  (while (or
+          (string= "\n" (substring string -1))
+          (string= " " (substring string -1)))
+    (setq string (substring string 0 -1)))
+  (while (or
+          (string= "\n" (substring string 0 1))
+          (string= " " (substring string 0 1)))
+    (setq string (substring string 1)))
+  string)
+
+(defun yacas-prompt ()
+  "Return the point of the last prompt in the yacas process buffer."
   (save-excursion
-    (setq yacas-process (start-process "yacas" "*Yacas*"
-				       yacas-command yacas-args))
-    (if yacas-use-filter
-	(set-process-filter yacas-process 'yacas-send-filter))
-    (set-buffer "*Yacas*")
-    (shell-mode)
-    (make-local-variable 'comint-process-echoes)
-    (setq comint-process-echoes nil)
-    (make-local-variable 'comint-scroll-show-maximum-output)
-    (setq comint-scroll-show-maximum-output t)
-    (make-local-variable 'shell-prompt-pattern)
-    (setq shell-prompt-pattern yacas-prompt-regexp)
-    (make-local-variable 'comint-prompt-regexp)
-    (setq comint-prompt-regexp (concat "^" yacas-input-prompt-string))
-    (set-syntax-table yacas-mode-syntax-table)
-    (setq yacas-shell-map (copy-keymap shell-mode-map))
-    (define-key yacas-shell-map "\M-\C-k"    'yacas-kill-job) 
-    (define-key yacas-shell-map (kbd "M-TAB") 'yacas-complete)
-    (define-key yacas-shell-map "\C-c=" 'yacas-recenter-output-buffer)
-    (define-key yacas-shell-map "\C-a" 'comint-bol)
-    (define-key yacas-shell-map "\C-c\C-h" 'yacas-help)
-    (define-key yacas-shell-map [up] 'comint-previous-input)
-    (define-key yacas-shell-map [down] 'comint-next-input)    
-    (define-key yacas-shell-map [(control up)] 'previous-line)
-    (define-key yacas-shell-map [(control down)] 'next-line)
-    (use-local-map yacas-shell-map)
-    (make-local-variable 'font-lock-defaults)
-    (setq yacas-shell-font-lock-keywords
-	  (cons '("\\(In> \\|Out> \\)" 0 font-lock-keyword-face nil)
-		yacas-font-lock-keywords))
-    (setq yacas-shell-font-lock-keywords
-	  (cons '(
-"\\(To exit Yacas, enter  Exit(); or quit or Ctrl-c. Type \\?\\? for help.\\|Or type \\?function for help on a function.\\|Type 'restart' to restart Yacas.\\|To see example commands, keep typing Example();\\|Numeric mode:\\)"
-0 font-lock-keyword-face nil) yacas-shell-font-lock-keywords))
-    (setq font-lock-defaults '(yacas-shell-font-lock-keywords nil))
-    (yacas-shell-menu-install-menus)
-    (run-hooks 'yacas-start-shell-hooks)))
-
-(defun yacas-wait ()
-  "Wait until Yacas is through with the current computation."
-  (if yacas-use-filter
-      (while yacas-send-filter-active
-	(sleep-for 1))))
-
-(defun yacas-start-process ()
-  "Start a Yacas process"
-  (interactive)
-  (setq yacas-send-filter-active t)
-  (if (not (processp yacas-process)) 
-      (progn
-	(yacas-start-shell)
-	(yacas-wait)))
-;  (yacas-wait)
-;  (setq yacas-send-filter-active t)
-;  (yacas-string "PrettyPrinter(\"PrettyForm\");")
-;  (yacas-wait)
-  (if yacas-show-yacas-buffer
-      (yacas-recenter-output-buffer nil)))
+    (set-buffer (process-buffer inferior-yacas-process))
+    (goto-char (point-max))
+    (re-search-backward (concat "^" yacas-input-prompt-string))
+    (match-end 0)))
+
+(defun yacas-new-prompt-p ()
+  "Check to see if there is a new prompt after the last input."
+  (save-excursion
+    (set-buffer (process-buffer inferior-yacas-process))
+    (goto-char yacas-input-end)
+    (or
+     (re-search-forward (concat "^" yacas-input-prompt-string) (point-max) t)
+     (re-search-forward "Process yacas finished" (point-max) t))))
+
+(defun yacas-finished-p ()
+  "Check to see if the Yacas process has halted"
+  (not (yacas-running)))
+
+(defun yacas-single-command (string)
+  "Send a command to the Yacas process."
+  (setq string (yacas-strip-string string))
+  (yacas-start)
+  (save-excursion
+        (set-buffer (process-buffer inferior-yacas-process))
+        (goto-char (point-max))
+        (insert string)
+        (setq yacas-input-end (point))
+        (comint-send-input))
+  (while (not (yacas-new-prompt-p))
+    (sit-for 0.100)))
+
+(defun yacas-send-block (stuff)
+  "Send a block of code to Yacas."
+  (yacas-start)
+  (while (string-match ";" stuff)
+    (setq end (1+ (string-match ";" stuff)))
+    (yacas-single-command (substring stuff 0 end))
+    (setq stuff (substring stuff end))))
+
+;;; Sending information to the process should be done through these
+;; next four commands
+
+(defun yacas-string (string)
+  "Send a string to the Yacas process."
+  (setq inferior-yacas-computing-p t)
+  (yacas-send-block string)
+  (yacas-display-buffer))
+
+(defun yacas-string-nodisplay (string)
+  "Send a string to the Yacas process."
+  (setq inferior-yacas-computing-p t)
+  (yacas-send-block string))
+    
+(defun yacas-region (beg end)
+  "Send the region to the Yacas process."
+  (interactive "r")
+  (yacas-string
+   (buffer-substring-no-properties beg end)))
+
+(defun yacas-region-nodisplay (beg end)
+  "Send the region to the Yacas process,
+do not display the yacas buffer."
+  (yacas-string-nodisplay
+   (buffer-substring-no-properties beg end)))
 
 (defun yacas-reset ()
   "Reset the Yacas session without restarting it."

      (indent-rigidly beg end di))))

;; Control constructs
(defun yacas-while ()
  "Build skeleton while statment, prompting for the conditional."
  (interactive)

menus after nil in the list will be displayed flushright in the
menubar.")

(defun inferior-yacas-menu-global-menubar ()
  (if yacas-running-xemacs
      (default-value 'default-menubar)
    (lookup-key (current-global-map) [menu-bar])))

(defvar inferior-yacas-mode-menu-map nil)

(defun inferior-yacas-menu-initialize-inferior-yacas-mode-menu-map ()
  (if (null inferior-yacas-mode-menu-map)
      (let ((map (make-sparse-keymap))
	    (dummy (make-sparse-keymap)))
	(require 'easymenu)
	;; initialize all the inferior-yacas-menu-*-menu variables
	;; with the menus.
	(easy-menu-define inferior-yacas-menu-yacas-menu (list dummy) nil
			  inferior-yacas-menu-yacas)
	(easy-menu-define inferior-yacas-menu-quit-menu (list dummy) nil
			  inferior-yacas-menu-quit)
	(easy-menu-define inferior-yacas-menu-arithmetic-menu (list dummy) nil
			  inferior-yacas-menu-arithmetic)
	(easy-menu-define inferior-yacas-menu-functions-menu (list dummy) nil
			  inferior-yacas-menu-functions)
	(easy-menu-define inferior-yacas-menu-linalg-menu (list dummy) nil
			  inferior-yacas-menu-linalg)
	(easy-menu-define inferior-yacas-menu-calculus-menu (list dummy) nil
			  inferior-yacas-menu-calculus)
	(easy-menu-define inferior-yacas-menu-simplify-menu (list dummy) nil
			  inferior-yacas-menu-simplify)
	(easy-menu-define inferior-yacas-menu-solve-menu (list dummy) nil
			  inferior-yacas-menu-solve)
	(easy-menu-define inferior-yacas-menu-poly-menu (list dummy) nil
			  inferior-yacas-menu-poly)
	(easy-menu-define inferior-yacas-menu-lists-menu (list dummy) nil
			  inferior-yacas-menu-lists)
	(easy-menu-define inferior-yacas-menu-config-menu (list dummy) nil
			  inferior-yacas-menu-config)
	(easy-menu-define inferior-yacas-menu-prog-menu (list dummy) nil
			  inferior-yacas-menu-prog)
	(easy-menu-define inferior-yacas-menu-others-menu (list dummy) nil
			  inferior-yacas-menu-others)
	(easy-menu-define inferior-yacas-menu-help-menu (list dummy) nil
			  inferior-yacas-menu-help)
	;; block the global menubar entries in the map so that YACAS
	;; can take over the menubar if necessary.
	(define-key map [rootmenu] (make-sparse-keymap))
	(define-key map [rootmenu inferior-yacas] 
	        (cons "Yacas Shell" (make-sparse-keymap "Yacas Shell")))
	(define-key map [rootmenu inferior-yacas file] 'undefined)	
	(define-key map [rootmenu inferior-yacas files] 'undefined)	
	(define-key map [rootmenu inferior-yacas edit] 'undefined)	
	(define-key map [rootmenu inferior-yacas options] 'undefined)	
	(define-key map [rootmenu inferior-yacas search] 'undefined)
	(define-key map [rootmenu inferior-yacas buffer] 'undefined)
	(define-key map [rootmenu inferior-yacas completion] 'undefined)	
	(define-key map [rootmenu inferior-yacas signals] 'undefined)	
	(define-key map [rootmenu inferior-yacas inout] 'undefined)	
	(define-key map [rootmenu inferior-yacas mule] 'undefined)
	(define-key map [rootmenu inferior-yacas tools] 'undefined)
	(define-key map [rootmenu inferior-yacas help] 'undefined)
	(define-key map [rootmenu inferior-yacas help-menu] 'undefined)
	;; now build YACAS's menu tree.
	(let ((menu-alist
	       '(
		 (arithmetic
		  (cons "Arith" inferior-yacas-menu-arithmetic-menu))
		 (yacas
		    (cons "Yacas>>" inferior-yacas-menu-yacas-menu))
		 (quit
		  (cons "Quit" inferior-yacas-menu-quit-menu))
		 (functions
		  (cons "Functions" inferior-yacas-menu-functions-menu))
		 (linalg
		  (cons "LinAlg" inferior-yacas-menu-linalg-menu))
		 (calculus
		  (cons "Calc" inferior-yacas-menu-calculus-menu))
		 (simplify
		  (cons "Simp" inferior-yacas-menu-simplify-menu))
		 (solve
		  (cons "Solve" inferior-yacas-menu-solve-menu))
		 (poly
		  (cons "Poly" inferior-yacas-menu-poly-menu))
		 (lists
		  (cons "Lists" inferior-yacas-menu-lists-menu))
		 (config
		  (cons "Config" inferior-yacas-menu-config-menu))
		 (progm
		  (cons "Prog" inferior-yacas-menu-prog-menu))
		 (others
		  (cons "Others" inferior-yacas-menu-others-menu))
		 (help
		  (cons "Help" inferior-yacas-menu-help-menu))))
	      cons
	      (vec (vector 'rootmenu 'inferior-yacas nil))
	      ;; menus appear in the opposite order that we
	      ;; define-key them.
	      (menu-list 
	       (if (consp inferior-yacas-use-menus)
		   (reverse inferior-yacas-use-menus)
		 (list nil 'help 'config 'progm 'others 'lists 'poly 
		       'solve 'simplify 'calculus 'linalg 'functions 
		       'arithmetic 'quit))))
	  (while menu-list
	    (if (null (car menu-list))
		nil;; no flushright support in FSF Emacs
	      (aset vec 2 (intern (concat "inferior-yacas-menu-"
					  (symbol-name
					   (car menu-list)) "-menu")))
	      (setq cons (assq (car menu-list) menu-alist))
	      (if cons
		  (define-key map vec (eval (car (cdr cons))))))
	    (setq menu-list (cdr menu-list))))
	(setq inferior-yacas-mode-menu-map map)
	(run-hooks 'inferior-yacas-menu-setup-hook))))

(defun inferior-yacas-menu-make-xemacs-menubar ()
  (let ((menu-alist
	 '((yacas    . inferior-yacas-menu-yacas)
	   (arithmetic  . inferior-yacas-menu-arithmetic)
	   (functions    . inferior-yacas-menu-functions)
	   (linalg     . inferior-yacas-menu-linalg)
	   (calculus     . inferior-yacas-menu-calculus)
	   (simplify     . inferior-yacas-menu-simplify)
	   (solve     . inferior-yacas-menu-solve)
	   (poly     . inferior-yacas-menu-poly)
	   (lists     . inferior-yacas-menu-lists)
	   (config     . inferior-yacas-menu-config)
	   (progm     . inferior-yacas-menu-prog)
	   (others     . inferior-yacas-menu-others)
	   (help . inferior-yacas-menu-help))
	 )
	cons
	(menubar nil)
	(menu-list inferior-yacas-use-menus))
    (while menu-list
      (cond
       ((null (car menu-list))
