;;; hm--elisp-menu.el: 
;;; v1.30; 30 Jun 1993
;;; Copyright (C) 1993  Heiko Muenkel
;;; email: muenkel@tnt.uni-hannover.de
;;;
;;;  This program is free software; you can redistribute it and/or modify
;;;  it under the terms of the GNU General Public License as published by
;;;  the Free Software Foundation; either version 1, or (at your option)
;;;  any later version.
;;;
;;;  This program is distributed in the hope that it will be useful,
;;;  but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;;  GNU General Public License for more details.
;;;
;;;  You should have received a copy of the GNU General Public License
;;;  along with this program; if not, write to the Free Software
;;;  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
;;;
;;; 
;;; Description:
;;;
;;;	This file provides the "Programming" menu (a pulldown and a
;;;	popup menu) for the lisp modes "emacs-lisp-mode", "lisp-mode"
;;;	and "lisp-interaction-mode" in the lemacs. There is also a
;;;	popup menu for the edebug mode. 
;;;     You need also the following lisp files:
;;;		hm--menu.el
;;;		hm--programming-menu.el
;;;		edebug.el
;;;		c++-mode.el
;;;
;;;	The last two files should be in the standart lemacs distribution !
;;; 
;;; Installation: 
;;;   
;;;	Put the following line in your .emacs:
;;;		(load-library "hm--elisp-menu")
;;;
;;;	Put the file hm--elisp-menu.el or (.elc) in one of your lisp
;;;	load-path directories (i.e. in .../lisp/packages).
;;;
;;;	Set the environment variable LISP_GNU_HEADER to an file which
;;;	includes a GNU lisp header (a header like this one).
;;;	For example:
;;;		setenv  LISP_GNU_HEADER ~/data/emacs/header/lisp-gnu-header
;;;


(provide 'hm--elisp-menu)
(require 'hm--menu)
(require 'hm--programming-menu)

;;
;; Menue "Programming" für Lisp
;;


(defvar hm--lisp-programming-menu nil "*Liste mit dem Menue Programming.")


(setq hm--lisp-programming-menu
      '("Programming Menu"
	("Eval lisp"
	 ["Last sexp" eval-last-sexp t]
	 ["Print last sexp" eval-print-last-sexp t]
	 ["Function" eval-defun t] 
	 ["Region" (eval-region 
			   (region-beginning)
			   (region-end))
	  t]
	 ["Buffer" eval-current-buffer t]
	 "-----"
	 ["Edebug defuns ON" hm--elisp-toggle-edebug-all-defuns t]
	 )
	("File"
	 ["Load file..." load-file t]
	 ["Byte compile file..." byte-compile-file t]
	 ["Insert GNU Header" (insert-file 
			       (getenv "LISP_GNU_HEADER")) t]
	 )
	("Misc"
	 ["Disassemble..." disassemble t]
	 )
	"----"
	("Syntax Expr Cmds"
	 ["Forward sexp" forward-sexp t]
	 ["Backward sexp" backward-sexp t]
	 ["Kill sexp" kill-sexp t]
	 ["Mark sexp" mark-sexp t]
	 )
	("Indent/Comment"
	 ["Indent region" indent-region t]
	 ["Indent sexp" indent-sexp t]
	 "----"
	 ["Comment region" c++-comment-region t]
	 ["Uncomment region" c++-uncomment-region t]
	 )
	("Mode Properties"
	 ["Font lock mode" font-lock-mode t]
	 ["Fontify buffer" font-lock-fontify-buffer t]
	 "----"
	 ["Init blinking parenthesis" hm--init-blinking-parenthesis t]
	 ["No open parenthesis match" hm--unset-matching-open-parenthesis t]
	 )
	))


(defun hm--install-lisp-programming-menu ()
  (if (and current-menubar (not (assoc "Programming" current-menubar)))
      (progn
	(hm--set-popup-menu 'hm--lisp-programming-menu)
	(set-buffer-menubar (copy-sequence current-menubar))
	(add-menu nil "Programming" (cdr hm--lisp-programming-menu)))))


(setq hm--elisp-edebug-all-defuns nil)  ; wenn t => eval = edebug


(defun hm--elisp-toggle-edebug-all-defuns ()
  "Calls the function edebug-all-defuns and changes the lisp programming
menu. Therefor it uses the variable hm--elisp-edebug-all-defuns. Don't
change this variable by hand !"
  (interactive)
  (if (not (user-variable-p 'edebug-all-defuns))
      (hm--lisp-load-edebug))
  (if hm--elisp-edebug-all-defuns 
      (if edebug-all-defuns
	  ; Menu shows that eval is edebug
	  ; and that is true
	  (progn
	    (edebug-all-defuns)  ; eval is eval
	    (setq hm--elisp-edebug-all-defuns nil)
	    (relabel-menu-item '("Programming" "Edebug lisp") "Eval lisp")
	    (relabel-menu-item '("Programming" 
				 "Eval lisp"
				 "Eval defuns ON") "Edebug defuns ON"))
	; Menu shows that eval is edebug
	; but that is wrong
	(setq hm--elisp-edebug-all-defuns nil)
	(relabel-menu-item '("Programming" "Edebug lisp") "Eval lisp")
	(relabel-menu-item '("Programming" 
			     "Edebug lisp"
			     "Eval defuns ON") "Edebug defuns ON"))
    (if edebug-all-defuns
        ; Menu shows that eval is eval
        ; but that is wrong
	(progn
	  (setq hm--elisp-edebug-all-defuns t)
	  (relabel-menu-item '("Programming" "Eval lisp") "Edebug lisp")
	  (relabel-menu-item '("Programming" 
			       "Edebug lisp"
			       "Edebug defuns ON") "Eval defuns ON"))
      ; Menu shows that eval is eval
      ; and that is true
      (edebug-all-defuns)
	  (setq hm--elisp-edebug-all-defuns t)
	  (relabel-menu-item '("Programming" "Eval lisp") "Edebug lisp")
	  (relabel-menu-item '("Programming" 
			       "Edebug lisp"
			       "Edebug defuns ON") "Eval defuns ON"))
      ))
	

(add-hook 'emacs-lisp-mode-hook 'hm--install-lisp-programming-menu)
(add-hook 'lisp-mode-hook 'hm--install-lisp-programming-menu)
(add-hook 'lisp-interaction-mode-hook 'hm--install-lisp-programming-menu)


;;
;; Menue for edebug
;;

(defvar hm--lisp-edebug-menu nil "*The lisp edebug menu.")


(setq hm--lisp-edebug-menu
      '("Edebug Menu"
	("Forward"
	 ["Step" edebug-step-through-mode t]
	 ["Step in" edebug-step-in t]
	 ["Step out" edebug-step-out t]
	 ["Forward expressioin" edebug-forward-sexp t]
	 "----"
	 ["Continue" edebug-continue-mode t]
	 ["Continue fast" edebug-Continue-fast-mode t]
	 "----"
	 ["Go" edebug-go-mode t]
	 ["Go nonstop" edebug-Go-nonstop-mode t]
	 ["Go to here" edebug-goto-here t]
	 )
	("Tracing"
	 ["Stop" edebug-stop t]
	 ["Trace" edebug-trace-mode t]
	 ["Trace fast" edebug-Trace-fast-mode t]
	 ["Backtrace" edebug-backtrace t]
	 )
	("Breakpoints"
	 ["Set breakpoint" edebug-set-breakpoint t]
	 ["Set conditional breakpoint" edebug-set-conditional-breakpoint t]
	 ["Unset breakpoint" edebug-unset-breakpoint t]
	 "----"
	 ["Next breakpoint" edebug-next-breakpoint t]
	 )
	"----"
	("Display"
	 ["Redisplay previous result" edebug-previous-result t]
	 ["Visit eval list" edebug-visit-eval-list t]
	 "----"
	 ["Where is the debug point" edebug-where t]
	 ["Bounce point" edebug-bounce-point t]
	 ["View outside" edebug-view-outside t]
	 "----"
	 ["Toggle save windows" edebug-toggle-save-windows t]
	 "----"
	 ["Eval expression..." edebug-eval-expression t]
	 )
	("Abort"
	 ["Abort all debug level" top-level t]
	 ["Abort one debug level" abort-recursive-edit t]
	 )
	"----"
	["Help" edebug-help t]
	))


(defun hm--lisp-edebug-mouse-right (event)
  "Perform commands bound to right mouse button."
  (interactive "@e")
  (popup-menu 'hm--lisp-edebug-menu))


;; The following must be used, because there is no load-hook for the edebug.el
;; File. So you should load the edebug.el only with the following function.

(defun hm--lisp-load-edebug ()
  "This function should be used to load the edebug.el file, because there is
no load-hook for this file."
  (interactive)
  (load-library "edebug")
  (define-key edebug-mode-map '(button3) 'hm--lisp-edebug-mouse-right)
  (define-key edebug-mode-map '(button2) 'edebug-step-through-mode))
  

;;; autoload


(autoload 
 'c++-comment-region 
 "c++-mode" 
 "Comment out all lines in a region between mark and current point by
inserting comment-start in front of each line." 
 t)


(autoload
 'c++-uncomment-region
 "c++-mode"
 "Uncomment all lines in region between mark and current point by deleting
the leading \"// \" from each line, if any."
 t)


(autoload
 'edebug-defun
 "edebug"
 "Evaluate defun or defmacro, like eval-defun, but with edebug calls.
Print its name in the minibuffer and leave point where it is,
or if an error occurs, leave point after it with mark at the original point.")


