;;;
;;; Narrowing commands...
;;;
(defun narrow-to-function ()
  "Narrows to the function that you are presently in."
  (interactive)
  (save-match-data
    (save-excursion
      (let (min)
        (re-search-backward "^[ \t]*.*[a-zA-Z0-9_](.*).*[\n\r]?.*{")
        (setq min (point))
        (search-forward "{")
        (backward-char)
        (forward-sexp)
        (narrow-to-region min (point))))))

(global-set-key "\C-xnf" 'narrow-to-function)

(defun narrow-to-class ()
  "Narrows to the class that you are presently in."
  (interactive)
  (save-match-data
    (save-excursion
      (let (min)
        (re-search-backward "^class")
        (setq min (point))
        (search-forward "{")
        (backward-char)
        (forward-sexp)
        (narrow-to-region min (point))))))

(global-set-key "\C-xnc" 'narrow-to-class)


;;;
;;; ----------------------------------------------
;;; finding function definitions in Lisp files...
;;; ----------------------------------------------

(autoload 'find-tag-default "etags")
;;(require 'etags) ;;  so we can access find-tag-default.

(defun get-name ()
  (interactive)
  (format "%s" (find-tag-default)))

(defun find-lisp-definition ()
;;  (interactive (get-name )))
  (interactive)
  (save-match-data
    (let ((name (get-name))
          ;;(read-from-minibuffer "Find Lisp Definition: " (get-name)))
          (pt (point)))
      (push-mark)
      (goto-char (point-min))
      (if (re-search-forward (concat "(defun \\<" (regexp-quote name) "\\>") nil t)
          (beginning-of-line)
        (goto-char pt)
        (error "Can't find definition of \"%s\" in this file!" name)))))

;;;
;;; ----------------------------------------------
;;; finding function definitions in C/C++ files...
;;; ----------------------------------------------

(defvar cfind-temp nil)

(defun cfind-first-function ()
  "Scans the current line for a function call, then finds the first
definition of that function in this file.  Assumes that if/do/while
constructs are written with a space, like so: if (, do (, while (
and that function calls are written without a space."
  (interactive)
  (save-match-data
    (save-excursion
      (let ((max (re-search-forward "[a-zA-Z_][a-zA-Z0-9_]*(" (point-at-eol) t))
            (min (or (re-search-backward "[^a-zA-Z0-9_ (]"        (point-at-bol) t)
                     (point-at-bol))))
        (if (and min max)
            (setq cfind-temp (buffer-substring-no-properties (1+ min) (1- max)))
          (error "No function call on this line"))))
    (if (string-match "[a-zA-Z0-9_]*(\\([a-zA-Z0-9_]*\\)" cfind-temp)
        (setq cfind-temp (substring cfind-temp (match-beginning 1) (match-end 1))))
    (if (string-match "[ \t]*\\([a-zA-Z0-9_]*\\)" cfind-temp)
        (setq cfind-temp (substring cfind-temp (match-beginning 1) (match-end 1))))
    (let ((found (save-excursion (beginning-of-buffer)
                                 (cfind-next-function))))
      (push-mark)
      (goto-char found))))

(defun cfind-next-function ()
  (interactive)
  (save-match-data
    (save-excursion
      (forward-line 1)
      (if (not (re-search-forward
                (concat "^[ \t]*\\([a-zA-Z_][a-zA-Z0-9_]*\\**[ \t]+\\)*"
                        "\\(\\sw+::\\)?"
                        cfind-temp "(")
                nil t))
          (progn
            (forward-line -1)
            (error "Not found: %s" cfind-temp))
        (beginning-of-line))
      (point)
      )))

(defvar d-tags-location-stack nil)

(defun d-find-tag ()
  (interactive)
  (save-match-data
    (save-excursion
      (let ((m (point-marker)))
        (let ((tag (read-from-minibuffer
                    "Find tag: " (format "%s" (current-word)))))
          (if (string= "" tag)
              (error "No tag specified!"))
          (find-tag (setq d-last-tag tag)))
        (setq d-tags-location-stack (cons m d-tags-location-stack))))))

(defun d-find-next-tag ()
  (interactive)
  (let ((m (point-marker)))
    (find-tag d-last-tag t)
    (setq d-tags-location-stack (cons m d-tags-location-stack))))

(global-set-key [(shift f5)]
                (function
                 (lambda () (interactive)
                   (if (null d-tags-location-stack)
                       (error "Tags stack empty"))
                   (let ((m (car d-tags-location-stack)))
                     (setq d-tags-location-stack (cdr d-tags-location-stack))
                     (switch-to-buffer (marker-buffer m))
                     (goto-char (marker-position m))
                     (set-marker m nil)
                     ))))


(provide 'd-key-find)
;;; d-key-find.el ends here
