GNU   davin.50webs.com/research
Bringing to you notes for the ages

       Main Menu          Research Projects         Photo Album            Curriculum Vitae      The Greatest Artists
    Email Address       Computer Games          Web Design          Java Training Wheels      The Fly (A Story)   
  Political Activism   Scruff the Cat       My Life Story          Smoking Cessation          Other Links      
Debugging Macros     String Class I     Linked List System I Java for C Programmers Naming Convention
    String Class II         How I use m4              Strings III                 Symmetrical I/O             Linked Lists II     
Run-Time Type Info   Virtual Methods      An Array System        Science & Religion            Submodes       
  Nested Packages      Memory Leaks    Garbage Collection      Internet & Poverty      What is Knowledge?
Limits of Evolution   Emacs Additions      Function Plotter           Romantic Love        The Next Big Thing
    Science Fiction     Faster Compilation Theory of Morality         Elisp Scoping               Elisp Advice      
  S.O.G.M. Pattern       Safe Properties         School Bullying          Charisma Control          Life and Death    
     Splitting Java          Multiple Ctors       Religious Beliefs         Conversation 1           Conversation 2    
   J.T.W. Language    Emacs Additions II      Build Counter             Relation Plotter          Lisp++ Language  
  Memory Leaks II   Super Constructors CRUD Implementation Order a Website Form There Is An Afterlife
More Occam's Razor C to Java Translator Theory of Morality II


cbrow.el

    

;;; cbrow.el --- A C++ class browser

;; Copyright (C) 2006-2011 Davin Pearson

;; Author/Maintainer: Davin Max Pearson <http://davin.50webs.com>
;; Keywords: C++ Code Browser
;; Version: 1.0

;;; Commentary:

;; This file is not part of GNU Emacs.

;; Pressing f5 inside a method of a source file (e.g. *.cpp or *.cc)
;; takes you to corresponding line for that function in the the header
;; file for that class (e.g. *.hh) Pressing enter at this point takes
;; you back to the source file. Otherwise pressing f5 takes you to a
;; summary list of all the classes in your program. At this point,
;; pressing enter takes you back to the class browswer.  See the
;; following Website for a diagram that clarifies this text:
;;
;; To use this code, you will need to customise the function
;; cbrow--init and the variable cbrow--footer which can be both found
;; at the end of cbrow.el.

;;; Limitation of Warranty

;; 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 3 of the License, 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 GNU Emacs, see the file COPYING.  If not, see:
;;
;; <http://www.gnu.org/licenses/gpl-3.0.txt>.


;;; Install Instructions:
;; See the following URL for the latest info and a tarball:
;;
;; <http://davin.50webs.com/research/2006/mopa2e.html#cbrow>
;;
;; Then untar the tarball to a folder pointed to by the Emacs variable
;; load-path and add the following line to your ~/.emacs file.
;;
;; (require 'cbrow)

;;; Known Bugs:

;; None so far!

;;; Code:

(setq cbrow--buffer-name "*Class Browser*")
(setq cbrow--buffer      nil)

;;; debugging functions...

(global-set-key [kp-enter] (function (lambda () (interactive)
                                       (message "cbrow--inside-method=%s"
                                                (cbrow--inside-method)))))

(global-set-key [kp-enter] (function (lambda () (interactive)
                                       (message "cbrow--inside-class=%s"
                                                (cbrow--inside-class)))))

;;(cbrow--inside-namespace-p1-and-p2)
(defun cbrow--inside-namespace-p1-and-p2 ()
  (save-match-data
    (save-excursion
      (let (orig squiggly result)
        (setq orig (point))
        (setq result (cons nil nil))
        (when (re-search-backward "^{" nil t)
          (setq squiggly (point))
          (forward-line -1)
          (beginning-of-line)
          (when (looking-at "^namespace _*[a-zA-Z][a-zA-Z0-9_]*[ \t]*$")
            (goto-char squiggly)
            ;;(debug "Apple")
            (forward-sexp 1)
            (if (< orig (point))
                (setq result (cons squiggly (point))))))
        (if (not (car result)) (setcar result (point-min)))
        (if (not (cdr result)) (setcdr result (point-max)))
        result
        ))))

;;(cbrow--inside-class-p1-and-p2)
(defun cbrow--inside-class-p1-and-p2 ()
  (save-match-data
    (save-excursion
      (let (orig squiggly result)
        (setq result (cons nil nil))
        (setq orig (point))
        ;; BEGIN COND!
        (cond
         ((save-excursion
            (beginning-of-line)
            (looking-at (if *namespace* "^[ ][ ][ ]{" "^{")))
          (setq squiggly (point))
          (forward-sexp 1)
          (when (< orig (point))
            (setq result (cons squiggly (point)))))
         ((save-excursion
            (beginning-of-line)
            (when (looking-at (concat
                               (if *namespace* "^[ ][ ][ ]" "^")
                               "\\([A-Z]+ \\)*class \\(_*[a-zA-Z][a-zA-Z0-9_]*\\)"))
              (forward-line 1)
              (looking-at (if *namespace* "^[ ][ ][ ]{" "^{"))
              (setq squiggly (point))
              (forward-sexp 1)
              (when (< orig (point))
                (setq result (cons squiggly (point)))))))
         ((save-excursion
            (re-search-backward (if *namespace* "^[ ][ ][ ]{" "^{") nil t)
            (setq squiggly (point))
            (forward-sexp 1)
            (when (< orig (point))
              (setq result (cons squiggly (point))))))
         )
         ;; END COND!
        (if (not (car result)) (setcar result (point-min)))
        (if (not (cdr result)) (setcdr result (point-max)))
        result
        ))))

(defun cbrow--inside-method-p1-and-p2--inner ()
  (cond
   ((and *namespace* *class*) "^[ ][ ][ ][ ][ ][ ]{")
   ((or *namespace* *class*)  "^[ ][ ][ ]{")
   (t                         "^{")))

(defun cbrow--inside-method-p1-and-p2 ()
  (save-match-data
    (save-excursion
      (let (orig squiggly space-squigglies result p)
        (setq *namespace*      (cbrow--inside-namespace))
        (setq *class*          (cbrow--inside-class))
        (setq orig             (point))
        (setq space-squigglies (cbrow--inside-method-p1-and-p2--inner))
        (setq result           (cons nil nil))
        (cond
         ((save-excursion
            (when (looking-at space-squigglies)
              (setq squiggly (point))
              (forward-sexp -1) ;; SKIP ARGS!
              (beginning-of-line)
              (when (looking-at (concat "^[ \t]*" cbrow--inside-method--regexp "("))
                (setq p (point))
                (goto-char squiggly)
                (forward-sexp 1) ;; SKIP SQUIGGLIES!
                ;;(debug "Nectarine")
                (when (< orig (point))
                  (setq result (cons p (point)))
                  ;;(debug "Hole in two")
                  result))))
            ;;(debug "line 0")
          result)
         ((save-excursion
           (when (re-search-backward space-squigglies nil t)
             (setq squiggly (point))
             ;;(debug "Carrot Parrot")
             (forward-sexp -1) ;; SKIP ARGS!
             (beginning-of-line)
             (setq p (point))
             (when (looking-at (concat "^[ \t]*" cbrow--inside-method--regexp ")"))
               (goto-char squiggly)
               (forward-sexp 1) ;; SKIP SQUIGGLIES!
               ;;(debug "Apricot")
               (when (< orig (point))
                 (setq result (cons p (point)))
                 ;;(debug "Hole in three")
                 result
                 ))))
          ;;(debug "line 1")
           result)
         ((save-excursion
            ;;(debug "Carrot Parrot")
            (when (re-search-forward space-squigglies nil t)
              (forward-char -1)
              (setq squiggly (point))
              (forward-sexp 1) ;; SKIP SQUIGGLIES!
              (setq squiggly-end (point))
              ;;(debug "Holy Smoke!")
              (goto-char squiggly)
              (forward-sexp -1) ;; SKIP ARGS!
              (beginning-of-line)
              (if (looking-at (concat "^[ \t]*" cbrow--inside-method--regexp "("))
                  (setq result (cons (point) squiggly-end)))
                ))
          result))
        (if (not (car result)) (setcar result (point-min)))
        (if (not (cdr result)) (setcdr result (point-max)))
        result))))

(defun cbrow--inside-namespace ()
  (save-match-data
    (save-excursion
      (let ((namespace nil)
            (oldp      (point)))
        (if (re-search-backward "^{" nil t)
            (progn
              (forward-line -1)
              (when (looking-at "namespace[ \t]+\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)")
                (setq namespace (buffer-substring-no-properties (match-beginning 1) (match-end 1)))
                (forward-line 1)
                (forward-sexp 1)
                ;;(debug "Foo")
                (if (> (point) oldp)
                    namespace))))))))

(defun cbrow--inside-class ()
  ;;(interactive)
  (save-match-data
    (save-excursion
      (let ((oldp        (point))
            ;;(*namespace*   (cbrow--inside-namespace))
            (class-point nil)
            (p1          nil)
            (p2          nil)
            (*class*     nil)
            (*namespace* (cbrow--inside-namespace))
            (meth-class  nil))
        (cond
         ((save-excursion
            (beginning-of-line)
            (looking-at (concat (if *namespace* "^[ ][ ][ ]" "^") "\\([A-Z]+[ \t]+\\)*class[ \t][a-zA-Z0-9_:]+")))
          ;;(debug 123)
          (beginning-of-line)
          (forward-line 1)
          (when (save-excursion
                  (beginning-of-line)
                  (looking-at "^-+$"))
            (beginning-of-line)
            (forward-line 2))
          (forward-line 1)
          ;;(debug 123)
          )
         ((save-excursion
            (beginning-of-line)
            (looking-at "^-+$"))
          (beginning-of-line)
          (forward-line 2)
          ;;(debug 456)
          )
         ((save-excursion
            (beginning-of-line)
            (looking-at (if *namespace* "^[ ][ ][ ]{" "{")))
          (beginning-of-line)
          (forward-line 1)
          ;;(debug 789)
          )
         (t
          (forward-line 1)
          ;;(debug "green eggs and ham")
          )
         )
        (when (re-search-backward (if *namespace* "^[ ][ ][ ]{" "^{") nil t)
          (setq class-point (point))
          (skip-chars-forward " \t")
          (if 123 (forward-sexp 1))
          (when (> (point) oldp)
            (goto-char class-point)
            (forward-line -1)
            (while (looking-at "^-+$")
              (forward-line -1)
              (beginning-of-line))
            (beginning-of-line)
            ;;(debug "Salami")
            (if (looking-at (concat "^"
                                    (if *namespace* "[ ][ ][ ]")
                                    "\\([A-Z0-9_]+[ \t]+\\)*class[ \t]\\([a-zA-Z0-9_:]+\\)"))
                (progn
                  ;;(if (and (match-beginning 2) (match-end 2))
                  ;;    (setq *namespace* (buffer-substring-no-properties (match-beginning 2) (match-end 2)))
                  ;;(debug "not beg")
                  (setq meth-class (buffer-substring-no-properties (match-beginning 2) (match-end 2))))
              ;;(debug "Antelope")
              (setq meth-class nil)
              )
            ;;(debug "Red Hot Chilli Peppers")
            (if (and *namespace* meth-class)
                (concat *namespace* "::" meth-class)
              meth-class)))))))

(setq cbrow--inside-class--regexp "^\\([A-Z]+[ \t]+\\)?class \\(_*[a-zA-Z][a-zA-Z0-9_]*::\\)?\\([A-Za-z][A-Za-z0-9_]*\\)[^;\n]*\n")

(setq cbrow--identifier--chars "~A-Za-z0-9_")

(setq cbrow--inside-method--regexp
      (concat "\\(_*[a-zA-Z][A-Za-z0-9_<]*[> ]*[&*]*[ \t]+\\)*"
              "\\(_*[a-zA-Z][~a-zA-Z0-9_:]*\\)"))

;; (cbrow--number-of-commas method)
(defun cbrow--number-of-commas (method)
  (let ((count 0) (method-2 method))
    (while (string-match "," method-2)
      (incf count)
      (setq method-2 (concat
                      (substring method-2 0 (match-beginning 0))
                      "."
                      (substring method-2 (match-end 0)))))
    count))

;; (cbrow--remove-spaces "abc\ndef\nghi")
;; (cbrow--remove-spaces "abc   def   \tghi")
(defun cbrow--remove-spaces (s)
  (let ((len (length s))
        (i   0)
        (answer ""))
    ;;(debug "Zenzi")
    (while (< i len)
      (let ((ch (aref s i)))
        (if (or (= ch ?\t)
                (= ch ?\r)
                (= ch ?\n))
            (setq ch ? ))
        (setq answer (format "%s%c"  answer ch)))
      (if (cbrow--is-space s i)
          (while (and (< i len)
                      (cbrow--is-space s i))
            (incf i))
        (incf i))
      )
    answer))

(defun cbrow--trim-spaces-in-args (method)
  (progn
    (while (string-match "( " method)
      (setq method (concat (substring method 0 (match-beginning 0))
                           "("
                           (substring method (match-end 0)))))
    (while (string-match ", " method)
      (setq method (concat (substring method 0 (match-beginning 0))
                           ","
                           (substring method (match-end 0)))))
    (while (string-match " )" method)
      (setq method (concat (substring method 0 (match-beginning 0))
                           ")"
                           (substring method (match-end 0)))))
    method))

;; (setq old-method (cbrow--inside-method))
;; (setq method old-method)
;; (setq method "(int*** i, ptr<Foo_A>&&&* j, const char**** str = null)")
;; (cbrow--trim-spaces-in-args method)
;; (cbrow--change-args method)
(defun cbrow--change-args (method)
  ;;method)
  (when (not (string-match "()" method))
    (let (count beg end len len+1)
      (progn
        (setq count  0)
        (setq method (cbrow--remove-spaces method))
        (setq method (cbrow--trim-spaces-in-args method))
        (setq len    (cbrow--number-of-commas method))
        (setq len+1  (1+ len))
        (while (< count len+1)
          (progn
            (if (= count 0)
                (setq beg "(")
              (setq beg ","))
            (if (= count len)
                (setq end ")")
              (setq end ","))
            (cons beg end))
          (when ;;(string-match (concat "\\(" beg "[^,]+ +\\( = ?[a-zA-Z0-9]+\\)?\\)\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)" end) method)
              (string-match (concat beg
                                    "\\(\\(const \\|unsigned \\|signed\\)*[a-zA-Z0-9_<:]+[ >]*[&*]*\\) "
                                    "\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)\\(\\( ?= ?_*[a-zA-Z][a-zA-Z0-9_]*\\)?\\)"
                                    end)
                            method)
            ;;(d-beeps "count=%s" count)
            (setq method (concat (substring method 0 (match-end 1))
                                 (substring method (match-end 4))
                                 )))
          ;;(setq method (concat (substring method 0 (match-end 1)) (substring method (match-end 3)))))
          (incf count)))
      )
    )
  method
  )

(defun cbrow--space-regexp ()
  (cond
   ((and *namespace* *class*)
    "^[ ][ ][ ][ ][ ][ ]{"
    )
   ((or *namespace* *class*)
    "^[ ][ ][ ]{")
   (t
    "^{")))

(defun cbrow--sqiggly-regexp ()
  (cond
   ((and *namespace* *class*)
    "^[ ][ ][ ][ ][ ][ ]{"
    )
   ((or *namespace* *class*)
    "^[ ][ ][ ]{")
   (t
    "^{")))

(defun cbrow--inside-method ()
  (save-match-data
    (save-excursion
      (let ((orig (point)) p *namespace* *class* found squiggly result namespace-ps class-ps)

(beginning-of-line)

(setq *namespace* (cbrow--inside-namespace))
        (setq *class*     (cbrow--inside-class))

(if *namespace*
            (setq namespace-ps (cbrow--inside-namespace-p1-and-p2)))
        (if *class*
            (setq class-ps     (cbrow--inside-class-p1-and-p2)))

        ;;(debug "Salami Sandwiches")

        (if (and *class* (string-match (concat "\\(" *namespace* "::\\)") *class*))
            (setq *class* (substring *class* (match-end 1))))

        ;;(debug "Bitter question")

        ;; BEGIN COND!
        (cond
         ((save-excursion
            ;;(forward-line -1)
            ;;(setq p (point))
            ;;(forward-line 1)
            (beginning-of-line)
            ;;(debug "weather forecast")
            (when (looking-at (cbrow--space-regexp))
              ;;(debug "would you?")
              (setq squiggly (point))
              (forward-sexp -1) ;; SKIP ARGS!
              (beginning-of-line)
              (setq p (point))
              (goto-char squiggly)
              (forward-sexp 1) ;;; SKIP SQUIGGLIES!
              (when (< orig (point))
                (goto-char p)
                (when (re-search-forward (concat (cbrow--space-regexp) cbrow--inside-method--regexp "(")
                                         (if *namespace* (cdr namespace-ps) (cdr class-ps))
                                         t)
                  (setq found (buffer-substring-no-properties (match-beginning 2) (match-end 2)))
                  (forward-char -1)
                  (setq p (point))
                  (forward-sexp 1) ;; SKIP ARGS!
                  (setq found (concat found (cbrow--change-args (buffer-substring-no-properties p (point)))))
                  ;;(debug 123)
                  found))))
          found)
         ((save-excursion
            (beginning-of-line)
            (when (re-search-forward (cbrow--sqiggly-regexp)
                                     (cond
                                      ((and namespace-ps class-ps)
                                       (min (cdr namespace-ps) (cdr class-ps)))
                                      (namespace-ps
                                       (cdr namespace-ps))
                                      (class-ps
                                       (cdr class-ps))
                                      (t
                                       nil)) t)
              (forward-char -1)
              (setq squiggly (point))
              (forward-sexp -1) ;; SKIP ARGS!
              (beginning-of-line)
              (setq p (point))
              (goto-char squiggly)
              ;;(debug "Would you #2")
              (forward-sexp 1) ;; SKIP SQUIGGLIES!
              (when (< orig (point))
                ;;(debug "Rocket")
                (goto-char squiggly)
                (if 'foomatic (forward-sexp -1)) ;; SKIP ARGS!
                (beginning-of-line)
                (when (re-search-forward (concat (cbrow--space-regexp) cbrow--inside-method--regexp "(")
                                         (if *namespace* (cdr namespace-ps) (cdr class-ps) )
                                         t)
                  (setq found (buffer-substring-no-properties (match-beginning 2) (match-end 2)))
                  ;;(debug "Would you $100")
                  (forward-char -1)
                  (setq p (point))
                  (forward-sexp 1) ;; SKIP ARGS!
                  (setq found (concat found (cbrow--change-args (buffer-substring-no-properties p (point)))))
                  ;;(d-beeps "456")
                  found))))
          found)
         ((save-excursion
            (when (re-search-backward (cbrow--sqiggly-regexp) nil t)
              (setq squiggly (point))
              (if 'mac (forward-sexp -1)) ;; SKIP ARGS!
              (beginning-of-line)
              ;;(debug "Would you #3")
              (setq p (point))
              ;;(debug 789)
              (goto-char squiggly)
              (forward-sexp 1) ;; SKIP SQUIGGLIES!
              (when (< orig (point))
                (goto-char p)
                (when (re-search-forward (concat (cbrow--space-regexp) cbrow--inside-method--regexp "(")
                                         (if *namespace* (cdr namespace-ps) (cdr class-ps))
                                         t)
                  (setq found (buffer-substring-no-properties (match-beginning 2) (match-end 2)))
                  (forward-char -1)
                  (setq p (point))
                  (forward-sexp 1) ;; SKIP ARGS!
                  (setq found (concat found (cbrow--change-args (buffer-substring-no-properties p (point)))))
                  ;;(debug 789)
                  found
                  ))))
          ;; END SAVE-EXCURSION!
          found)
         ((save-excursion
            (and (not *namespace*)
                 (prog1
                     (re-search-backward (if *class* "^[ ][ ][ ]{" "^{")
                                         (car class-ps)
                                         t)
                   (setq squiggly (point)))
                 (progn
                   ;;(debug "Would you #4")
                   ;;(forward-line -1)
                   ;;(end-of-line)
                   (if 'args (forward-sexp -1)) ;; SKIP ARGS!
                   (beginning-of-line)
                   (setq p (point))
                   ;;(forward-line 1)
                   (goto-char squiggly)
                   ;;(beginning-of-line)
                   (if 'zed (forward-sexp 1)) ;; SKIP SQUIGGLIES!
                   (when (< orig (point))
                     (goto-char p)
                     ;;(debug "smeg")
                     (when (re-search-forward (concat (if *class* "^[ ][ ][ ]" "^")
                                                      cbrow--inside-method--regexp "(") (point-at-eol) t)
                       (setq found (buffer-substring-no-properties (match-beginning 2) (match-end 2)))
                       ;;(debug "PI")
                       )))))
          found)
         ((save-excursion
            (and (not *namespace*)
                 (progn
                   (beginning-of-line)
                   ;;(debug "Roger Ramjet")
                   (when (setq result (re-search-forward (if *class* "^[ ][ ][ ]{" "^{")
                                                         (if *namespace* (cdr namespace-ps) (cdr class-ps))
                                                         t))
                     (forward-char -1)
                     (setq squiggly (point))
                     result))
                 (progn
                   ;;(beginning-of-line)
                   (forward-line -1)
                   (end-of-line)
                   (if 'banana (forward-sexp -1))
                   (beginning-of-line)
                   (setq p (point))
                   (goto-char squiggly)
                   ;;(forward-line 1)
                   (if 'id (forward-sexp 1))
                   ;;(debug "would you #5")
                   (when (< orig (point))
                     (goto-char p)
                     ;;(debug 456)
                     (when (re-search-forward (concat (if *class* "^[ ][ ][ ]" "^")
                                                      cbrow--inside-method--regexp "(") (point-at-eol) t)
                       ;;(debug 789)
                       (setq found (buffer-substring-no-properties (match-beginning 2) (match-end 2)))
                       ;;(d-beeps "Zippo Lighters")
                  (forward-char -1)
                  (setq p (point))
                  (forward-sexp 1) ;; SKIP ARGS!
                  (setq found (concat found (cbrow--change-args (buffer-substring-no-properties p (point)))))
                  found)))))
          found)
         )
        ;; END COND!
        ;;(debug "Fynall Bynall")
        (if found
            (concat (if *namespace* (concat *namespace* "::"))
                    (if *class*     (concat *class* "::"))
                    found))
        ;;(debug "Cold Potatoes")
        )
      )
    )
  )

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; BEGIN: cbrow generic functions
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defun cbrow--current-line-as-string ()
  (buffer-substring-no-properties (point-at-bol)
                                  (point-at-eol)))

(defun cbrow--skip-word (word)
  (assert (looking-at word))
  (let ((i 0)
        (len (length word)))
  (while (< i len)
    (assert (eq (char-after) (aref word i)))
    (incf i)
    (forward-char 1))))

(defun cbrow--is-space (string index)
  (or (= (aref string index) ? )
      (= (aref string index) ?\t)
      (= (aref string index) ?\n)
      (= (aref string index) ?\r)))

(defun cbrow--trim-left (s)
  (let (i len ch)
    (setq i 0)
    (setq len (length s))
    (while (and (< i len)
                (setq ch (aref s i))
                (or (eq ch ?\ )
                    (eq ch ?\t)
                    (eq ch ?\r)
                    (eq ch ?\n)))
      (incf i))
    (setq s (substring s i)))
  s)

(defun cbrow--trim-right (s)
  (let (i ch)
    (setq i (1- (length s)))
    (while (and (>= i 0)
                (setq ch (aref s i))
                (or (eq ch ?\ )
                    (eq ch ?\t)
                    (eq ch ?\r)
                    (eq ch ?\n)))
      ;;(setq s (substring s 0 i))
      (decf i))
    (setq s (substring s 0 (1+ i)))
    )
  )

(defun cbrow--trim-string (s)
  (if (or (not s) (string= s ""))
      ""
    (if s (d-trim-left (d-trim-right s)))))

;;(cbrow--trim-return-value "  void    abc(int i, char**** str, ptr<Foo_A> foo)")
(defun cbrow--trim-return-value (method-spec)
  (if (string-match "\\(^[ \t]*\\)\\([a-zA-Z0-9_<>]+[ >]*[&*]*[ \t]+\\)*\\([~a-zA-Z0-9_:]+(\\)" method-spec)
      (setq method-spec (substring method-spec (match-beginning 3)))))

(defun cbrow--what-line ()
  "Different from what-line in that it returns the result rather than printing it"
  (save-excursion
    (beginning-of-line)
    (1+ (count-lines 1 (point)))))

(defun cbrow--message (string)
  (message "Class Browser: %s" string)
  ;;(beep)
  ;;(sit-for .2)
  ;;(beep)
  )

;;(cbrow--tail (setq string "///\n/// Tile Mode functions\n///abc"))
(defun cbrow--tail (string)
  (while ;;(string-match "^[\r\n]+[^\r\n]*[\r\n]+$" string)
      (string-match "[\r\n]+[^\r\n]*[\r\n]+" string)
    (setq string (substring string (match-end 0)))
    )
  string)

(defun cbrow--log--simple (string)
  (save-excursion
    (set-buffer cbrow--buffer-name)
    (goto-char (point-max))
    (if (not (null string))
        (insert string))))

(defun cbrow--log--complex (string &optional not-here)
  ;;(d-beeps "cbrow--log--complex string=%s" string)
  ;;(message "*** string=%s" string)
  ;;(when (and (not (string= "" string))
  ;;           (not (string-match "^[\r\n]$" string)))
  (let ((what-line        (cbrow--what-line))
        (spaces           0)
        (string-last-line nil))
    (while (and (> (length string) 0)
                (= (aref string 0) ?\n))
      ;;(save-excursion
      ;;(set-buffer cbrow--buffer)
      ;;(goto-char (point-max))
      ;;(insert "\n")
      (setq string (substring string 1)))

    ;;(if (or (string= "" string) (string= "\n" string))
    ;;    (debug "Toilet paper"))

    ;;(if (string-match "foomatic" string) (debug "Carrot"))
    (if (and (not (string= "" string))
             ;;(not (string-match "//" string))
             ;;(not (string=      "" string))
             (not (string-match "{$"                        string))
             (not (string-match "[\r\n]+$"                  string))
             (not (string-match "^class[ \t][a-zA-Z0-9_:]+" string))
             (not (string-match "^public:"                  string))
             (not (string-match "^private:"                 string))
             (not (string-match "^protected:"               string))
             (not (string-match "^#"                        string)))
        ;;(debug "foo"))
        (when (/= (aref string (1- (length string))) ?\;)
          ;;(debug "Bar")
          (setq string (concat string ";"))
          ))

(when (string-match "\\([\r\n]+$\\)" string)
      (setq string (substring string 0 (match-beginning 0))))

    ;;(if (string-match "Tile Mode functions" string)
    ;;    (debug "foomatic"))

    ;;(setq string "/// abc\n///def ghi\n/// foomatic")
    ;;(if (string-match "[\r\n]+\\([^\r\n]+\\)$" string)
    (setq string-last-line (cbrow--tail string))

(progn
      (setq f-w (frame-width))
      (setq spaces
            (if (<= (length string-last-line) f-w)
                (make-string (max 0 (- f-w 20 (length string-last-line))) ? )
              " "))
      (setq string (concat string spaces)))

(if not-here
        (setq string (concat string "//LINE:" (format "%d" what-line)  " NOT HERE!"))
      (setq string (concat string "//LINE:" (format "%d" what-line))))

(save-excursion
      (set-buffer cbrow--buffer)
      (goto-char (point-max))
      ;;(insert "KKK:" string ":LLL\n")
      (insert string "\n")
      )
    )
    ;;(if (string-match "respond(" string)
    ;;    (debug "Pencil neck"))
    ;;(if (string= "\n" string)
    ;;   (debug "Zipper"))
    ;;(debug "Cactus")
  )

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; END: cbrow generic functions
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defun cbrow--scan-comment--this-line ()
  (save-match-data
    (let ((comment-end   nil)
          (comment-start nil)
          (answer        nil))
      (save-excursion
        (forward-line -1)
        (beginning-of-line)
        (while (string-match "^[ \t]*$" (cbrow--current-line-as-string))
          (forward-line -1))
        (forward-line 1)
        (setq comment-end (point-at-bol))
        (forward-line -1)
        (while (and (looking-at (concat (if *namespace* "^[ ][ ][ ][ ][ ][ ]" "^[ ][ ][ ]") "//[^\n\r]*$"))
                    ;;(looking-at "^   //[^\n\r]*$")
                    (not (bobp)))
          (forward-line -1)
          (beginning-of-line))
        (forward-line 1)
        (setq comment-start (point))
        (setq answer (buffer-substring-no-properties comment-start comment-end))
        ;;(if (string-match "//" answer) (debug "Bastard"))
        ;;(error "smeg")
        answer))))

;; (cbrow--scan-method)
(defun cbrow--scan-method ()
  (save-excursion
    (save-match-data
      (if (string= (buffer-substring-no-properties (point-min) (point-max)) "")
          (error "*Class Browser* is empty"))
      ;;(d-beeps "Current Buffer=%s" (current-buffer))
      ;;(if *namespace*
      (let* (str)
        (setq str (buffer-substring-no-properties
                   (point-at-bol)
                   (if (progn
                         (beginning-of-line)
                         (search-forward "(" (point-at-eol) t))
                       (progn
                         (backward-char 1)
                         (forward-sexp 1)
                         (point-at-eol))
                     (point-at-eol))))
        ;;(concat "   " (cbrow--remove-spaces str))
        (cbrow--change-args str)
        )
      )
    )
  )

;; (cbrow--scan-property--this-line)
(defun cbrow--scan-property--this-line ()
  (save-match-data
    (let ((str (buffer-substring-no-properties
                (point-at-bol)
                (save-excursion
                  (progn
                    (beginning-of-line)
                    (search-forward ";")
                    (point)
                    )))))
      ;; fixes job down by remove-spaces
      (concat "  " (cbrow--remove-spaces str))
      )))

;;; (setq class-max (point-max))
(defun cbrow--found-a-method (class-max)
  (save-match-data
    (let* (;;(*namespace* (cbrow--inside-namespace))
           (f1 (save-excursion
                 (re-search-forward
                  (concat (if *namespace* "^[ ][ ][ ][ ][ ][ ]" "^[ ][ ][ ]")
                          "\\(_*[a-zA-Z][a-zA-Z0-9_:<]*[ >]*[*&]*[ \t]+\\)*~?\\([a-zA-Z][a-zA-Z0-9_]*\\)(")
                  class-max
                  t)))
           (f2 (save-excursion
                 (re-search-forward
                  (concat (if *namespace* "^[ ][ ][ ][ ][ ][ ]" "^[ ][ ][ ]")
                          "\\(_*[a-zA-Z][a-zA-Z0-9_:<]*[ >]*[*&]*[ \t]+\\)*operator[ \t]+"
                          "\\(=\\|==\\|!=\\|+\\|+=\\|-\\|-=\\|<<\\|<<=\\|>>\\|>>=\\)[ \t]+(")
                  class-max
                  t))))
      (cond
       ((and (numberp f1) (numberp f2))
        (min f1 f2))
       ((numberp f1)
        f1)
       ((numberp f2)
        f2)
       nil))))

(defun cbrow--found-a-property (class-max)
  (save-match-data
    (save-excursion
      (re-search-forward (concat (if *namespace* "^[ ][ ][ ][ ][ ][ ]" "^[ ][ ][ ]")
                                 "\\([a-zA-Z_][a-zA-Z0-9_<>:]*[> ]*[&*]*[ \t]+\\)*"
                                 "[a-zA-Z_][a-zA-Z0-9_]*\\([ \t]*=[^;]+\\)?;")
                         class-max
                         t))))

(defun cbrow--found-a-template (class-max)
  (save-match-data
    (save-excursion
      (re-search-forward (concat (if *namespace* "^[ ][ ][ ][ ][ ][ ]" "^[ ][ ][ ]")
                                 "template.*;")
                         class-max
                         t))))

(defun cbrow--found-an-outer-template ()
  (cond
   ((looking-at "^class")
    (setq p (point)))
   ((save-excursion
      (prog2
          (forward-line -1)
          (looking-at "^class")
        (setq p (point)))))
   ((save-excursion
      (prog1
          (re-search-backward "^class" nil t)
        (setq p (point))))))
  (save-excursion
    (goto-char p)
    (forward-line -1)
    (if (looking-at "^template.*$")
        (concat (cbrow--current-line-as-string) "\n"))))

;;(cbrow--found-a-hash)
(defun cbrow--found-a-hash (class-max)
  (save-match-data
    (save-excursion
      (re-search-forward "^#.*$" class-max t))))
(progn
  (setq *verbose*   nil)
  ;;(setq *namespace* nil)
  ;;(setq *class*     nil)
  )

(defun cbrow--found-a-public (class-max)
  (save-match-data
    (save-excursion
      (re-search-forward (if *namespace* "^   public:" "^public:") class-max t))))

(defun cbrow--found-a-private (class-max)
  (save-match-data
    (save-excursion
      (re-search-forward (if *namespace* "^   private:" "^private:") class-max t))))

(defun cbrow--found-a-protected (class-max)
  (save-match-data
    (save-excursion
      (re-search-forward (if *namespace* "^   protected:" "^protected:") class-max t))))

(defun cbrow--found-empty-line (class-max)
  (save-match-data
    (save-excursion
      (re-search-forward "^[ \t]*$" class-max t))))

(defun cbrow--found-a-friend (class-max)
  (save-match-data
    (save-excursion
      (re-search-forward (concat (if *namespace*
                                     "^[ ][ ][ ][ ][ ][ ]friend[ \t]"
                                   "^[ ][ ][ ]friend[ \t]")
                                 ".*$") class-max t))
    ))

;;;
;;; strictly don't need this function
;;; as it is only called once...
;;;
(defun cbrow--generate-browser-inner (*class* class-min class-max)
  ;;(d-beeps "min=%s max=%s" class-min class-max)
  (save-match-data
    (save-excursion
      ;;(debug)
      ;;(assert (looking-at "ABSTRACT"))
      (goto-char class-min)
      (forward-line -1)
      (cbrow--log--simple (cbrow--found-an-outer-template))

      ;;(debug "Dance of the dolphins")

      (if (string-match "^_*[a-zA-Z][a-zA-Z0-9_]*::\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)" *class*)
          (setq class-only (substring *class* (match-beginning 1))))

(cbrow--log--complex (concat "class " (if *namespace* (concat *namespace* "::" class-only) *class*)))
      (cbrow--log--simple
       "---------------------------------------------------------------------------------------\n")
      (cbrow--log--complex "{")

      ;;(debug "Spinster")

      (let ((found-friend     nil)
            (found-method     nil)
            (found-property   nil)
            (found-public     nil)
            (found-private    nil)
            (found-protected  nil)
            (found-template   nil)
            (found-hash       nil)
            ;;(found-empty-line nil)
            (comment          nil)
            (min              nil))

(while (progn (setq found-friend     (cbrow--found-a-friend    class-max))
                      (setq found-method     (cbrow--found-a-method    class-max))
                      (setq found-property   (cbrow--found-a-property  class-max))
                      (setq found-public     (cbrow--found-a-public    class-max))
                      (setq found-private    (cbrow--found-a-private   class-max))
                      (setq found-protected  (cbrow--found-a-protected class-max))
                      (setq found-template   (cbrow--found-a-template  class-max))
                      (setq found-hash       (cbrow--found-a-hash      class-max))
                      ;;(setq found-empty-line (cbrow--found-empty-line  class-max))
                      (or found-friend
                          found-method
                          found-property
                          found-public
                          found-private
                          found-protected
                          found-template
                          ;;found-empty-line
                          ))
          ;;(if (string-match "protected:" (cbrow--current-line-as-string))
          ;;   (debug "*** line=%s" (cbrow--current-line-as-string)))
          ;;(if (string-match "draw_inner(" (cbrow--current-line-as-string))
          ;;    (debug "Earl of Spencer"))
          ;;(if found-method   (message "*** found-method=%s" found-method))
          ;;(if found-property (message "*** found-property=%s" found-property))
          (if (not found-friend)    (setq found-friend    1e100))
          (if (not found-method)    (setq found-method    1e100))
          (if (not found-property)  (setq found-property  1e100))
          (if (not found-public)    (setq found-public    1e100))
          (if (not found-private)   (setq found-private   1e100))
          (if (not found-protected) (setq found-protected 1e100))
          (if (not found-template)  (setq found-template  1e100))
          (if (not found-hash)      (setq found-hash      1e100))
          ;;(if (not found-empty-line) (setq found-empty-line 1e100))

          (setq min (min found-friend
                         found-method
                         found-property
                         found-public
                         found-private
                         found-protected
                         found-template
                         found-hash
                         ;;found-empty-line
                         ))

(cond
           ;;((= min found-empty-line)
           ;; (cbrow--log--simple "\n")
           ;; (forward-line 1))

           ((= min found-friend)
            (goto-char found-friend)
            (cbrow--log--complex (concat
                                  "   "
                                  (if *verbose* "friend:")
                                  (cbrow--trim-string (cbrow--current-line-as-string)))))

((= min found-method)
            (let ((method-name    nil)
                  (method-comment nil))
              (goto-char found-method)
              (setq method-name (cbrow--scan-method))
              (setq method-comment (cbrow--scan-comment--this-line))
              (cbrow--log--simple method-comment)
              ;;(debug "Hot potatoes")
              ;;(if (string-match "^[\r\n]" method-name)
              ;;    (debug "Toadstools"))

              (if (eq ?\; (aref method-name (1- (length method-name))))
                  (cbrow--log--complex (concat "   "
                                               (if *verbose* "METHOD NOT HERE:")
                                               (cbrow--trim-string method-name)
                                               ) 'not-here)
                (cbrow--log--complex   (concat "   "
                                               (if *verbose* "METHOD HERE:")
                                               (cbrow--trim-string method-name)))
                )
              ;;(debug "Texas Chainsaw Massacre")
              ;;(if (string-match "ctor(" method-name)
              ;;    (debug "Smell you later"))
              ))

((= min found-property)
            (let ((property-name nil)
                  (property-comment nil))
              (goto-char found-property)
              (setq property-name    (cbrow--scan-property--this-line))
              (setq property-comment (cbrow--scan-comment--this-line))
              ;;(debug)
              (cbrow--log--simple property-comment)
              (cbrow--log--complex (concat
                                    "   "
                                    (if *verbose* "PROPERTY:")
                                    (cbrow--trim-string property-name)
                                    ))
              ;;(debug 123)
              ))

((= min found-public)
            (goto-char found-public)
            (setq comment (cbrow--scan-comment--this-line))
            ;;(debug 123)
            (cbrow--log--complex comment)
            (cbrow--log--complex "\npublic:"))

((= min found-private)
            (goto-char found-private)
            (setq comment (save-excursion
                            ;;(forward-line -1)
                            (cbrow--scan-comment--this-line)))
            (cbrow--log--complex comment)
            (cbrow--log--complex "\nprivate:")
            ;;(debug "Doughnut")
            )

((= min found-protected)
            (goto-char found-protected)
            (setq comment (cbrow--scan-comment--this-line))
            (cbrow--log--complex comment)
            (cbrow--log--complex "\nprotected:")
            )

((= min found-template)
            (goto-char found-template)
            (setq comment (cbrow--scan-comment--this-line))
            (cbrow--log--complex comment)
            (cbrow--log--complex (cbrow--current-line-as-string)))

((= min found-hash)
            (goto-char found-hash)
            (setq comment (cbrow--scan-comment--this-line))
            (cbrow--log--complex comment)
            (cbrow--log--complex (cbrow--current-line-as-string)))

           ;;((= min found-empty-line)
           ;; (goto-char found-empty-line)
           ;; (setq comment (cbrow--scan-comment--this-line))
           ;; (cbrow--log--complex comment)
           ;; (cbrow--log--complex (cbrow--current-line-as-string)))

           (t
            (error "Function cbrow--generate-browser-inner: should never happen")))

)
        (re-search-forward (if *namespace* "^[ ][ ][ ]}" "^}") nil t)
        ;;(debug "Pencil")
        (cbrow--log--simple (cbrow--scan-comment--this-line))
        (cbrow--log--simple "};\n\n")
        (cbrow--level--begin-or-end 1 "END" *class*)
        ))))

(defun cbrow--line-ptr ()
  (save-match-data
    (save-excursion
      (beginning-of-line)
      (if (re-search-forward "LINE:" (point-at-eol) t)
          (read-str (buffer-substring-no-properties (point) (save-excursion
                                                              (skip-chars-forward "0-9")
                                                              (point))))
        1e100))))

;;(defvar cbrow--class--local nil)

(defun cbrow--level--begin-or-end (level begin-or-end *class*)
  (cbrow--log--simple         (concat (make-string (frame-width) ?/) "\n"))
  (cbrow--log--simple         "///\n")
  (cbrow--log--simple (concat "/// CLASS BROWSER LEVEL "
                              (format "%d" level)
                              " "
                              begin-or-end
                              " : "
                              *class*
                              " "
                              (cadr (assoc *class* cbrow--header-alist))
                              "\n"
                              ))
  (cbrow--log--simple         "///\n")
  (cbrow--log--simple         (concat (make-string (frame-width) ?/) "\n"))
)

;;;; vvvvv

;;;
;;; NOT NEEDED: (set-syntax-table c++-mode-syntax-table)
;;;
(defun cbrow--generate-browser (*class* line-or-method-or-class)
  ;;(debug 123)
  ;;(assert (eq line-or-method-or-class '*class*))
  ;;(d-beeps "*class*=%s" *class*)
  ;;(debug "Foo!")
  ;;(assert (numberp line-or-method-or-class))
  (save-match-data
    (save-excursion
      (setq *namespace* (cbrow--inside-namespace))
      (if (get-buffer cbrow--buffer-name)
          (kill-buffer cbrow--buffer-name))
      (setq cbrow--buffer (generate-new-buffer cbrow--buffer-name))
      (unwind-protect
          ;; BEGIN LET!
          (let ((header           nil)
                (buf              nil)
                (extra            nil)
                (case-fold-search nil)
                (found            nil)
                )
            (setq header (cadr (assoc *class* cbrow--header-alist)))
            (cond
             ((not header)
              (error "(1) Header file is nil for class %s" *class*))
             ((not (file-exists-p header))
              (error "(2) Header file %s not found for class %s" header *class*))
             (t
              ;;
              ;; FIXED BUG! if header is the same buffer as the current buffer...
              ;;
              ;; NOTE: safe to kill the buffer as it has been saved and from now on it is read-only
              ;;
              ;;(save-buffer (setq buf (find-file-read-only header)))
              (setq buf (find-file header))
              (goto-char (point-min))
              ;;(error "smeg")
              ))

(cbrow--level--begin-or-end 1 "BEGIN" *class*)

            ;;(setq *class* "dmp::string_buffer")
            (let* ((ptr (cdr (assoc *class* cbrow--superclass-alist)))
                   (len (length ptr)))
              (while ptr
                (cbrow--log--simple (concat "SUPERCLASS: " (car ptr) "\n"))
                (setq ptr (cdr ptr)))
              (if (/= len 0)
                  (cbrow--log--simple "\n")))

(let* ((ptr (cdr (assoc *class* cbrow--subclass-alist)))
                   (len (length ptr)))
              (while ptr
                (cbrow--log--simple (concat "SUBCLASS: " (car ptr) "\n"))
                (setq ptr (cdr ptr)))
              (if (/= len 0)
                  (cbrow--log--simple "\n")))

            ;;(debug "Hairy Lemon")

            (if (string-match "[a-zA-Z0-9_]*::\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)" *class*)
                (setq class-only (substring *class* (match-beginning 1) (match-end 1)))
              (setq class-only *class*))

            ;;(debug "Scary Movie")

            ;;(cbrow--log--simple "sex\n")
            (setq strobe 0)
            (cond
             ((progn
                (goto-char (point-min))
                (re-search-forward (concat "^\\(\\([A-Z]+[ \t]+\\)*\\)class[ \t]+"
                                           *class*
                                           "\\([ \t].*[\r\n]\\|[\r\n]+\\){") nil t))
              (progn
                ;;(debug "Summer Holiday")
                (setq strobe 1)
                (setq *namespace* nil)
                (setq extra (buffer-substring-no-properties (match-beginning 1) (match-end 1)))))

((progn
                (goto-char (point-min))
                (re-search-forward (concat "^[ ][ ][ ]\\(\\([A-Z]+[ \t]+\\)*\\)class[ \t]+"
                                           *class*
                                           "\\([ \t].*[\r\n]\\|[\r\n]+\\)[ ][ ][ ]{") nil t))
              (progn
                (setq strobe 2)
                (setq *namespace* (cbrow--inside-namespace))
                (setq extra (buffer-substring-no-properties (match-beginning 1) (match-end 1)))))

((progn
                (goto-char (point-min))
                (re-search-forward (concat "^\\(\\([A-Z]+[ \t]+\\)*\\)*class*[ \t]+"
                                           class-only
                                           "\\([ \t].*[\r\n]\\|[\r\n]+\\){") nil t))
              (progn
                ;;(debug "Summer Holiday")
                (setq strobe 3)
                (setq *namespace* nil)
                (setq extra (buffer-substring-no-properties (match-beginning 1) (match-end 1)))))

((progn
                (goto-char (point-min))
                (re-search-forward (concat "^[ ][ ][ ]\\(\\([A-Z]+[ \t]+\\)*\\)class[ \t]+"
                                           class-only
                                           "\\([ \t].*[\r\n]\\|[\r\n]+\\)[ ][ ][ ]{") nil t))
              (progn
                (setq strobe 4)
                (setq *namespace* (cbrow--inside-namespace))
                (setq extra (buffer-substring-no-properties (match-beginning 1) (match-end 1)))))

((progn
                (goto-char (point-min))
                (setq strobe 5)
                (setq *namespace* (cbrow--inside-namespace))
                (re-search-forward (cond
                                    ((and *namespace* *class*)
                                     "^[ ][ ][ ][ ][ ][ ]{")
                                    ((or *namespace* *class*)
                                     "^[ ][ ][ ]{")
                                    (t
                                     "^{")) nil t)))
             (t
              (error "(3) Class %s not found in namespace %s in header file %s" *class* *namespace* header)))
            ;;(message "extra=%s" (prin1-to-string extra))
            ;;(sit-for 1)
            ;;(debug)
            ;; log ABSTRACT or final
            (cbrow--log--simple (concat extra (if (string= extra "") nil "\n")))
            ;;(d-beeps "buf=%s" (current-buffer))
            ;;(if (not (bobp))
            (forward-char -1)
            (assert (looking-at "{"))
            ;;(error "foo")
            (let ((p1 nil)
                  (p2 nil))
              (setq p1 (point))
              (setq p2 (save-excursion
                         (forward-sexp 1) ;; SKIP CLASS!
                         (point)))
              (cbrow--generate-browser-inner *class* p1 p2)
              ;;(debug "Calamansi")
              ;;(kill-buffer buf)
              ))
            ;; END LET!
        ;;(debug "Cabbage")
        (switch-to-buffer cbrow--buffer) ;;;; <--------- switch to buffer
        (cond
         ((numberp line-or-method-or-class)
          ;;
          ;; NOTE: line-or-method-or-class is a line number
          ;;
          (let ((orig-line line-or-method-or-class))
            ;;(debug "Regina")
            (progn
              ;;(setq orig-line nil)
              (goto-char (point-max))
              (while (and (not (bobp))
                          (< orig-line (cbrow--line-ptr))) ;;;   LINE:333
                (forward-line -1))
              (if (bobp)
                  (error "(5) Function cbrow--generate-browser: Line %s not found" orig-line)
                (setq found t)))
            )
          )

((stringp line-or-method-or-class)
          ;;
          ;; NOTE: line-or-method-or-class is the name of a method
          ;;
          (let ((orig-method line-or-method-or-class))
            ;;(debug "Foo!")
            (goto-char (point-min))
            (re-search-forward "^-+$")
            (beginning-of-line)
            (forward-line 1)
            (re-search-forward (concat "\\($\\|[ \t]\\)" orig-method "(")) ;;; WHY? [^~] ???
            (beginning-of-line)
            (setq found t)
            ))
         ;;
         ;; NOTE: line-or-method-or-class is bound to 'class
         ;;
         ((eq 'class line-or-method-or-class)
          (goto-char (point-min))
          ;;(debug "Lambada")
          (re-search-forward (concat "class[ \t]+" *class*) nil t)
          ;;(debug "Line Reef")
          (beginning-of-line)
          (setq found t)
          )

         ;; PUTBACK:
         (t (error "(6) Function cbrow--generate-browser: should never happen"))
         )
        (when (eq (current-buffer) (get-buffer cbrow--buffer))
          (switch-to-buffer cbrow--buffer)
          (c++-mode)
          (use-local-map cbrow--map1)
          (read-only-mode 1)
          (set (make-local-variable 'truncate-lines) t)
          ;;(debug "Scream II")
          (when (not found)
            (goto-char (point-min))
            (if (and *namespace* (not (string-match "_*[a-zA-Z][a-zA-Z0-9_]*::_*[a-zA-Z][a-zA-Z0-9_]*" *class*)))
                (re-search-forward (concat "^class " *namespace* "::" *class*) nil t)
              (re-search-forward (concat "^class " *class* "\\>") nil t))
            (beginning-of-line))
          (cbrow--message "Level 1")
          ;;(debug "Spencer")
          )))))

;;;
;;; control-n narrow to sexp
;;;
(defun cbrow--global--f5 ()
  (interactive)
  (let (line
        line2
        *namespace*
        *class*
        *method*
        result
        found
        namespace-class-method
        class-method
        class-only
        class-2
        method-only
        args
        method-args
        class-method-args-quoted
        namespace-ps
        class-ps
        method-ps)

(if (not cbrow--init-done)
        (cbrow--init))

(setq *namespace* (cbrow--inside-namespace))
    ;;(debug "Jing Jia")
    (setq cbrow--file  (buffer-file-name (current-buffer)))
    (setq cbrow--point (point))

(if (eq major-mode 'c++-mode)
        ;; BEGIN SAVE-EXCURSION!
        (save-excursion
          ;;(setq line (cbrow--what-line))
          (setq namespace-ps (cbrow--inside-namespace-p1-and-p2))
          (setq class-ps     (cbrow--inside-class-p1-and-p2))
          (setq method-ps    (cbrow--inside-method-p1-and-p2))
          ;;(when (not (save-excursion
          ;;             (beginning-of-line)
          ;;             (looking-at (concat "\\(^\\|[ \t\r\n]+\\)"
            ;;                                 cbrow--inside-method--regexp
            ;;                                 ;;"[a-zA-Z0-9_<]+[> ]*[&*]*"
            ;;                                 ;;"\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)::"
            ;;                                 ;;"\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)"
            ;;                                 ))))
            ;;  ;;(setq found t)
            ;;  ;;(debug 123)
            ;;  )
            ;;(beginning-of-line)
            ;;(forward-line 2)
            (setq *method* (cbrow--inside-method))
            ;;(debug "Sausage Sandwiches")
            ;;(forward-sexp -1)
            ;;(setq *method* (cbrow--scan-method))
            (setq *class* (cbrow--inside-class))
            ;;(debug "Skimpy Skirts: *method*=%s" *method*)

            ;;(assert *method*)
            (when *method*

(when (string-match (concat "\\(^\\|[ \t\r\n]\\)" cbrow--inside-method--regexp "(") *method*)
                (setq namespace-class-method (substring *method* (match-beginning 3) (match-end 3)))
                (when (string-match "\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)::\\([~a-zA-Z0-9_]+\\)" *method*)
                  (setq class-method (concat (substring *method* (match-beginning 1) (match-end 2))))))

(when (string-match "\\(^\\|[ \t\r\n]\\)\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)::\\([~a-zA-Z0-9_]+\\)" *method*)
                (setq class-method (substring *method* (match-beginning 2) (match-end 3)))
                (setq class-only (substring *method* (match-beginning 2) (match-end 2))))

(when (string-match "\\(_*[a-zA-Z][a-zA-Z0-9_]*::\\)\\([~a-zA-Z0-9_]+\\)" *method*)
                (setq method-only (substring *method* (match-beginning 2) (match-end 2))))

              ;;(if (and *class* (string-match "^_*[a-zA-Z][a-zA-Z0-9_]*::\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)$" *class*))
              ;;    (setq class-only (substring *class* (match-beginning 1) (match-end 1)))
              ;;  (setq class-only *class*))

              ;;(debug "toilet paper")

              (when (and (not *class*) class-method (string-match "\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)::" class-method))
                ;;(setq *class*    (substring class-method (match-beginning 1) (match-end 1)))
                (setq class-only (substring class-method (match-beginning 1) (match-end 1))))
              ;;(debug "Snake Oil")
              )

            ;;(debug "Middle of cbrow--global--f5")

            (cond
             ((save-excursion
                (beginning-of-line)
                (looking-at "^ *\\([A-Z]+ \\)*class _*[a-zA-Z][a-zA-Z0-9_]*"))
              (setq class-2 (cbrow--inside-class))
              (when (and class-2 456)
                ;;(debug "First cond in cbrow--global--f5")
                (cbrow--generate-browser class-2 'class)
                (goto-char (point-min))
                (re-search-forward "class " nil t)
                (beginning-of-line)
                ))

(*method*
              (cond
               ((and *namespace*
                     *class*
                     (string-match (concat "\\(" *namespace* "\\)::\\(" *class* "\\)::\\(.*\\)(") *method*))
                (setq class-method (substring *method*
                                              (match-beginning 2)
                                              (match-end 3)))
                (setq method-only (substring *method*
                                             (match-beginning 2)
                                             (match-end 2))))
               ((and *class* (string-match (concat "\\(" *class* "\\)::\\(.*\\)(") *method*))
                (setq class-method (substring *method*
                                              (match-beginning 1)
                                              (match-end 2)))
                (setq method-only (substring *method*
                                             (match-beginning 2)
                                             (match-end 2))))
               ((string-match "\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)::\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)::\\([~a-zA-Z0-9_]+\\)(" *method*)
                (setq *namespace* (substring *method*
                                             (match-beginning 1)
                                             (match-end 1)))
                (setq *class* (substring *method*
                                         (match-beginning 1)
                                         (match-end 2)))
                (setq class-only (substring *method*
                                            (match-beginning 2)
                                            (match-end 2)))
                (setq class-method (substring *method*
                                              (match-beginning 1)
                                              (match-end 2)))
                (setq method-only (substring *method*
                                             (match-beginning 3)
                                             (match-end 3)))
                )
               ((string-match "\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)::\\([~a-zA-Z0-9_]+\\)(" *method*)
                (setq *class* (concat *namespace*
                                      (substring *method*
                                                 (match-beginning 1)
                                                 (match-end 1))))
                (setq class-only (substring *method*
                                            (match-beginning 1)
                                            (match-end 1)))
                (setq class-method (substring *method*
                                              (match-beginning 1)
                                              (match-end 2)))
                (setq method-only (substring *method*
                                             (match-beginning 2)
                                             (match-end 2)))
                ))

(when (string-match "(.*)" *method*)
                (setq args (substring *method*
                                      (match-beginning 0)
                                      (match-end 0)))
                (setq method-args (concat method-only args)))

(when (and (not *class*) (not (string-match "\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)::\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)" *method*)))
                ;;(debug "Cannot find a class for a function")
                (cbrow--message "Cannot find a class for a function"))

(if (and (not *class*) (string-match "\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)::\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)" *method*))
                  (setq *class* (substring *method* (match-beginning 1) (match-end 1))))

(when *class*

                ;;(debug "Middle of cbrow--global--f5")

                (if 'cat (cbrow--generate-browser *class* 'class))
                (progn
                  (switch-to-buffer cbrow--buffer-name)
                  (goto-char (point-min))
                ;;(debug "Lancer")
                  (re-search-forward (if (= (aref method-only 0) ?~)
                                         (regexp-quote method-args)
                                       (concat "\\<" (regexp-quote method-args))))
                  (beginning-of-line)
                  )
                ;;(debug "Smells like teen spirit")
                )
              ;;(debug "Smell ya later")
              )

((setq class-2 (cbrow--inside-class))
              ;;(setq class-ps (cbrow--inside-class-p1-and-p2))
              ;;(setq line (cbrow--what-line))
              (if 456 (cbrow--generate-browser class-2 (cbrow--what-line)))
              ;;(debug "Valencia")
              ;;(switch-to-buffer cbrow--buffer-name)
              ;;              (goto-char (point-min))
              ;;              (setq found nil)
              ;;              (while (and (not found) (re-search-forward "//LINE:\\([0-9]+\\)" (cdr class-ps) t))
              ;;                (setq line-found (read-str (buffer-substring-no-properties (match-beginning 1) (match-end 1))))
              ;;                (if (= line-found line)
              ;;                    (setq found t)))
              ;;(debug "Feng shui")
              (setq found t)
              )
             (*class*
              ;;(debug "Tomato")
              ;;(setq line (cbrow--what-line))
              (if 789 (cbrow--generate-browser (if *namespace*
                                                   (concat *namespace* "::" class-only)
                                                 *class*) 'class))
              (switch-to-buffer cbrow--buffer-name)
              (goto-line (point-min))
              (re-search-forward "^class" nil t)
              (forward-line 2)
              (re-search-forward method-only nil t)
              (beginning-of-line)
              (debug "sausages")
              ;;(switch-to-buffer cbrow--buffer-name)
              ;;(goto-char (point-min))
              ;;(re-search-forward (concat "\\<" method-only "(") nil t)
              ;;(beginning-of-line)
              ;;(set-buffer cbrow--buffer)
              ;;(d-beeps "line=%s" line)
              ;;(goto-char (point-min))
              ;;(debug "789")
              )
             ;;(t
             ;; (find-file cbrow--file)
             ;; (goto-char cbrow--point))
             (t
              ;;(error "cbrow--global--f5: Not inside a *class* or inside an outer *method*")
              ;;(debug "Melon")
              ;;(debug "123")
              ;;(switch-to-buffer cbrow--buffer-name)
              (setq result (cbrow--inside-method))
              (when (string-match "^\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)::\\([a-zA-Z0-9]+\\)::\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)$" result)
                (setq *namespace* (substring result (match-beginning 1) (match-end 1)))
                (setq *class*     (substring result (match-beginning 2) (match-end 2)))
                (setq *method*    (substring result (match-beginning 3) (match-end 3)))
                )
              (when (string-match "^\\([a-zA-Z0-9]+\\)::\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)$" result)
                (setq *class*     (substring result (match-beginning 1) (match-end 1)))
                (setq *method*    (substring result (match-beginning 2) (match-end 2)))
                )
              (when (and *class* *method*)
                (set-buffer (find-file (cadr (assoc *class* cbrow--header-alist))))
                (setq meth (cbrow--trim-return-value *method*))
                (re-search-forward meth nil t)
                (beginning-of-line)
                (if 1230 (cbrow--generate-browser *class* meth))
                (debug "Tom Clancy")
                )
              )
             )
            )
      ;; END SAVE-EXCURSION!
      (if 123 (cbrow--map1--f5))
      ;;(debug "Roger Dodger")
      )))

;; (assoc "Dipper" cbrow--header-alist)
(defun cbrow--map1--enter ()
  (interactive)
  (let (*class* class-only *namespace* file line)
    (setq *class*     (cbrow--inside-class))
    (setq *namespace* (cbrow--inside-namespace))
    ;;(debug "Hairy Tomato")
    (d-quote if (save-excursion
                  (re-search-forward "//LINE:" (point-at-eol) t))
             (setq line (save-excursion
                          (re-search-forward "//LINE:\\([0-9]+\\)" (point-at-eol) t)
                          (read-str (buffer-substring-no-properties (match-beginning 1) (match-end 1))))))
    ;; BEGIN COND!
    (cond
     ((save-excursion
        (beginning-of-line)
        (looking-at "^\\(SUPERCLASS\\|SUBCLASS\\): "))
      ;;(debug "Ratipo")
      (save-excursion
        ;;(d-beeps "Foomatic")
        (beginning-of-line)
        (skip-chars-forward "A-Z") ;;; skip SUPERCLASS or SUBCLASS
        (skip-chars-forward ":")
        (skip-chars-forward " \t")
        (setq *class* (buffer-substring-no-properties (point) (save-excursion
                                                              (skip-chars-forward (concat cbrow--identifier--chars ":"))
                                                              (point))))
        (if (string-match "^_*[a-zA-Z][a-zA-Z0-9_]*::\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)$" *class*)
            (setq class-only (substring *class* (match-beginning 1) (match-end 1))))

(setq file (cadr (assoc *class* cbrow--header-alist)))
        (if file
            (cbrow--generate-browser *class* 'class)
          (setq file (cadr (assoc class-only cbrow--header-alist)))
          (if file
              (cbrow--generate-browser class-only 'class)
            (if 'nerd (error "No header file for class %s" *class*))))
        ;;(debug "Smeg")
        ;;(debug "Salami")
        ;;(message *class*)
        ))

((save-excursion
        (re-search-forward "=[ \t]*null;" (point-at-eol) t))
      (cbrow--message "Cannot browse a pure virtual function"))

((save-excursion
        (re-search-forward "NOT HERE!" (point-at-eol) t))
      (let ((method                 nil)
            (method-signature       nil)
            (method-only            nil)
            (class-method           nil)
            (namespace-class-method nil)
            (class-only             nil)
            (file                   nil))
        (progn
          (setq method-signature (cbrow--trim-string (cbrow--current-line-as-string)))
          ;;(setq method (cbrow--inside-method))

          (if (string-match "\\(operator[ \t]+[^;]+\\)[ \t](" method-signature)
              (setq method-only (substring method-signature (match-beginning 1) (match-end 1)))

(assert (string-match "\\([^ ]*\\)(" method-signature))
            (setq method-only (substring method-signature
                                         (match-beginning 1)
                                         (match-end 1)))

(assert *class*)

(setq method (concat *class* "::" method-only))

            ;;(if (string-match "\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)" *class*)
            ;;    (setq class-only (substring *class* (match-beginning 1) (match-end 1))))

            (when (string-match "\\(_*[a-zA-Z][a-zA-Z0-9_]*::\\)?\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)" *class*)
              (setq class-only (substring *class* (match-beginning 2) (match-end 2)))
              ;;(setq *class* class-only)
              )

(setq class-method (concat class-only "::" method-only))
            (if *namespace*
                (setq namespace-class-method (concat *namespace* *class* "::" method-only))
              (setq namespace-class-method class-method))

(progn
              ;;(kill-buffer)
              (setq file (cadr (assoc (if *namespace* (concat *namespace* "::" class-only) *class*)
                                      cbrow--header-alist)))
              (if (cbrow--find-file file *class*)
                  ;;(debug "Found here")
                'foo
                (setq file (cadr (assoc (if *namespace* (concat *namespace* "::" class-only) class-only)
                                        cbrow--footer-alist))))
              ;;(debug "file=%s" file)
              (when (not (cbrow--find-file file *class*))
                (d-beeps "Tags file search")
                (if (string-match "\\(friend\\|operator\\)" method-signature)
                    (tags-search method-only)
                  (tags-search class-method))
                (beginning-of-line)))))))

((save-excursion
        (re-search-forward "//LINE:" (point-at-eol) t))
      (let ((what-line nil)
            (file      nil))
        (save-excursion
          (re-search-forward "//LINE:" (point-at-eol) t)
          (setq what-line (read (buffer-substring-no-properties (point)
                                                                (save-excursion
                                                                  (skip-chars-forward "0-9")
                                                                  (point)))))
          (setq file (cadr (assoc *class* cbrow--header-alist)))
          ;;(debug)
          )

(if (not file)
            (if 123 (error "Variable file is nil")))

(if (not (file-exists-p file))
            (if 456 (error "Header file %s for class %s does not exist" file *class*)))

(if 'ibm-computers (find-file file))
        (goto-line what-line)
        (recenter)
        (message "Here it is in the header file")
        (read-only-mode -1)
        ))

(t
      (beep)
      )
     )
    ;; END COND!
    )
  )

(defun cbrow--find-file (file *class*)
  (let ((found           nil)
        (found-namespace nil)
        (*namespace*     nil)
        ;;args
        ;;namespace-only
        ;;class-only
        ;;class-method
        ;;class-method-args
        ;;class-method-args-quoted
        line
        line2)
    ;;(debug "Rocket fuel")
    ;; BEGIN COND!
    (cond
     ((not file)
      (setq found nil))
     ((not (file-exists-p file))
      (setq found nil))
     ((progn
        (find-file file)
        (goto-char (point-min))
        ;;(debug "Challenger")

        (when (string-match "([^()]*)" method-signature)
          (setq args (substring method-signature (match-beginning 0) (match-end 0)))
          (setq args (cbrow--change-args args))
          )

(when (string-match "\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)::\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)" *class*)
          (setq namespace-only (substring *class* (match-beginning 1) (match-end 1)))
          (setq class-only     (substring *class* (match-beginning 2) (match-end 2)))
          )

(setq class-method             (concat (if class-only (concat class-only "::")) method-only))
        (setq class-method-args        (concat (if class-only (concat class-only "::")) method-only args))
        (setq class-method-args-quoted (regexp-quote class-method-args))

        ;; BEGIN COND!
        (cond
         ((string= method-only class-only)
          ;;
          ;; NOTE: it's a constructor!
          ;;
          ;;(debug "It's a ctor!")
          (while (and (not found) (re-search-forward (concat class-method "(") nil t))
            ;;(beginning-of-line)
            (setq line  (cbrow--scan-method))
            (setq line2 (cbrow--trim-return-value line))
            (when (string-match "([^()]*)" method-signature)
              (setq args (substring method-signature (match-beginning 0) (match-end 0)))
              (setq args (cbrow--change-args args))
              )
            (when (string-match class-method-args-quoted line2)
              ;;(debug "Found is true")
              (setq found t)))
          (beginning-of-line)
          ;;(debug "It's a ctor!")
          found)

((eq (aref method-only 0) ?~)
          ;;
          ;; NOTE: it's a destructor!
          ;;
          (re-search-forward (concat class-method "("))
          (beginning-of-line)
          ;;(debug "It's a dtor!")
          (setq found t)
          )

(t
          ;;
          ;; NOTE: just a method!
          ;;
          ;;(debug "Stay at home dad")
          (progn
            (setq found nil)
            ;;(if (string-match "\\.ch$" file) (debug "Hole in one"))
            ;;(debug "Middle of cbrow--find-file")
            (while (and (not found) (re-search-forward (concat class-method "(") nil t))
              (setq line (cbrow--scan-method))
              (setq line (cbrow--trim-return-value line))
              ;;(cbrow--trim-return-value "   int*** function()")
              ;;(debug "toilet seat")
              (setq found-namespace t)
              (beginning-of-line)
              (if (progn
                    (beginning-of-line)
                    (re-search-forward (concat *namespace* "::") (point-at-eol) t))
                  (setq found-namespace t)
                (setq found-namespace nil))
              (when (string= *namespace* (cbrow--inside-namespace))
                (setq found-namespace t))
              (if (not found-namespace) (debug "Anchor milk"))
              (when found-namespace
                ;;(if (/= (aref line2 (1- (length line2))) ?\;)
                ;;    (setq line2 (concat line2 ";")))
                ;;(setq line (cbrow--trim-return-value line))
                ;;(if (string-match (concat "^" (regexp-quote "Bar::function(int***);") "$") line2)
                ;;(if (string= "Bar::function(int***);" line2) )
                (when (string-match class-method-args-quoted line)
                  ;;(debug "Found is true")
                  (setq found t))))
            ;;(debug "It's the spitz")
            (beginning-of-line))))
        ;; END COND!
        )))
    ;; END COND!
    (if (not found)
        (kill-buffer)
      ;;(d-beeps "Here it is in file %s" file)
      (message "Here it is in file %s" file))
    ;;(debug "Not found")
    found))

(defun cbrow--map1--f5 ()
  (interactive)
  (let* ((list    nil)
         (ptr     cbrow--header-alist)
         (*class* (cbrow--inside-class))
         (result  nil))
    ;;(debug "Tiger Woods")
    (assert (boundp '*class*))
    (while ptr
      (setq list (cons (caar ptr) list))
      (setq ptr (cdr ptr)))
    ;;(debug "Smegulator")
    (progn
      (if (get-buffer cbrow--buffer-name)
          (kill-buffer cbrow--buffer-name))
      ;;(debug "Hole in one")
      (switch-to-buffer (generate-new-buffer cbrow--buffer-name))
      (c++-mode)
      ;;(setq list (reverse list))
      ;;(setq list (cbrow--bubble-sort list 'cbrow--less-than))
      (cbrow--level--begin-or-end 2 "BEGIN" nil)
      (setq ptr list)
      (while ptr
        (goto-char (point-max))

(let (class)
          ;; NOTE: adds <T> to class spec
          (setq class (car ptr))
          ;;(if (string-match "Xyd_A" *class*) (debug "Tomato soup"))
          (setq *template* (cadr (assoc class cbrow--template-list))))

(let* ((c (car ptr))
               (r (cadr (assoc c cbrow--rest-alist))))
          (insert (concat "class " (if *template* *template* c)))
          (insert (if r (concat " : " r "\n") "\n"))
          ;;(if (string-match "\\(dmp::\\)?Reader$" c)
          ;;    (debug "Ten pin bowling"))
          ;;(debug)
          ;;(if (cadr (assoc c cbrow--rest-alist))
          ;;(insert (cadr (assoc c cbrow--rest-alist)))
          )
        (backward-delete-char 1)
        (insert "\n")
        (setq ptr (cdr ptr)))

(let ((sort-fold-case t))
        (sort-lines nil (save-excursion (goto-char (point-min))
                                        (re-search-forward "class" nil t)
                                        (forward-line -1)
                                        (point)) (point-max))
        ;;(debug "Carroty")
        )

(cbrow--level--begin-or-end 2 "END" nil)
      ;;(save-excursion (goto-char (point-max)) (re-search-backward "////" nil t) (point)))
      ;;(goto-char (point-min))
      ;;(goto-char (point-max))

      (goto-char (point-min))
      (re-search-forward "class")
      ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
      ;;;
      ;;; Here is how to do a condition-case statement:
      ;;;
      ;;;      (condition-case nil
      ;;;          (error "smeg")
      ;;;        (error (setq i "ren")))
      ;;;
      ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
      ;;;
      ;;; TODO: condition-case here
      ;;;
      ;;(debug "Viagra")
      (if (not *class*)
          (progn
            (cbrow--message "Class is nil")
            ;;(debug "Helicopter")
            )
        (if (string-match (concat "^" *namespace* "::") *class*)
            (setq result *class*)
          (setq result (concat (if *namespace* (concat *namespace* "::")) *class*)))

(goto-char (point-min))
        (let ((search (concat "class[ \t]+" result "\\([ \t<>]\\|$\\)")))
          (if (not (re-search-forward search nil t))
              (error (format "*** Cbrow Search failed: %s" *class*))
            (cbrow--message "Level 2"))))

(beginning-of-line)
      (use-local-map cbrow--map2)
      (read-only-mode 1)
      ;;(debug "Foomatic")
      ))
  )

(defun cbrow--map2--enter ()
  (interactive)
  (save-excursion
    (let (*class* class-only)
      (beginning-of-line)
      (cbrow--skip-word "class")
      (skip-chars-forward " \t")
      (cond
       ((looking-at "\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)::\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)")
        (setq *namespace* (buffer-substring-no-properties
                           (match-beginning 1)
                           (match-end 1)))
        (setq *class* (buffer-substring-no-properties
                     (match-beginning 1)
                     (match-end 2)))
        (setq class-only (buffer-substring-no-properties
                          (match-beginning 2)
                          (match-end 2))))
      ((looking-at "\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)")
       (setq *class* (buffer-substring-no-properties (match-beginning 1)
                                                   (match-end 1))))
      )
      ;;(setq file (cadr (assoc *class* cbrow--header-alist)))
      ;;(if (string-match "[a-z]::\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)" *class*)
      ;;    (setq *class* (substring *class* (match-beginning 1) (match-end 1))))
      ;;(debug "Splatter film")
      (if 'banana (cbrow--generate-browser ;;(if *namespace* (concat *namespace* *class*) *class*)
                   *class*
                   'class))
      ;;(debug "Suzy Salmon")
      ;;(message class)
      )
    )
  )

(defun cbrow--map2--f5 ()
  (interactive)
  ;;(bury-buffer)
  (if (not cbrow--file)
      (bury-buffer)
    (find-file cbrow--file)
    (goto-char cbrow--point))
  (cbrow--message "Back to editing")
  ;;(d-beeps "Can't go back any further")
  )

(defvar cbrow--map1 (make-keymap))
(define-key cbrow--map1 "\C-m" 'cbrow--map1--enter)
(define-key cbrow--map1 [f5]   'cbrow--map1--f5)
(global-set-key [f5] 'cbrow--global--f5)

(defvar cbrow--map2 (make-keymap))
(define-key cbrow--map2 "\C-m" 'cbrow--map2--enter)
(define-key cbrow--map2 [f5]   'cbrow--map2--f5)

;; (setq list '("abc" "def" "abc" "def" "zed"))
;; (setq list (delete-duplicates list :test 'string=))
;; (cbrow--init--header-alist)
(defun cbrow--init--header-alist ()
  (let* ((search-list (reverse cbrow--headers))
         (ptr         search-list))
    (setq cbrow--header-alist nil)
    (setq cbrow--template-list nil)
    (while ptr

      ;;(if (string= (car ptr) "~/zallegro/2005/dd/mesh.cc")

      ;;
      ;; NOTE: loads it in fundamental mode if not already in memory,
      ;; else keeps it in the current mode...
      ;;
      (let ((auto-mode-alist (cons '("" . fundamental-mode) auto-mode-alist)))
      ;; NOTE: safe to kill the buffer as it has been saved and from now on it is read-only
        (save-buffer (find-file-read-only (car ptr))))

      ;;(debug "Phlegm")

      (let ((class-list nil))
        (goto-char (point-min))
        (while (re-search-forward "^[ ][ ][ ]\\([A-Z]+[ \t]+\\)?class" nil t)
          ;;(debug "Xenophobe")
          (if (setq *namespace* (cbrow--inside-namespace))
              (when (progn
                      (forward-line 1)
                      (looking-at "^[ ][ ][ ]{"))
                (forward-line -1)
                ;;(debug "Point max")
                (skip-chars-forward " \t")
                (skip-chars-forward "A-Z")
                (skip-chars-forward " \t")
                (cbrow--skip-word "class")
                (skip-chars-forward " \t")
                ;;(debug "Hot tamale")
                ;;(if (string= (buffer-name) "string.hh")
                ;;    (debug "Plaster board"))
                (let ((*class* (buffer-substring-no-properties
                                   (point) (save-excursion
                                             (skip-chars-forward (concat cbrow--identifier--chars ":"))
                                             (point))))
                      (template (buffer-substring-no-properties
                                 (save-excursion
                                   (forward-line -1)
                                   (beginning-of-line)
                                   (point))
                                 (save-excursion
                                   (forward-line -1)
                                   (end-of-line)
                                   (point)))))
                  ;;(if (string-match "Vector" *class*)
                  ;;    (debug "found Vector_2d_Cartesian<T>"))
                  (if (string-match "template<class \\(_*[a-zA-Z][a-zA-Z0-9_]*\\)>" template)
                      (progn
                        ;;(debug "Found template")
                        (setq template (concat *class*
                                               "<"
                                               (substring template (match-beginning 1) (match-end 1))
                                               ">")))
                    (setq template nil))
                  (setq cbrow--template-list (cons (list *class* template) cbrow--template-list))
                  ;;(debug "Splatter gun")
                  (setq class-list (cons (concat (if *namespace* (concat *namespace* "::"))
                                                 *class*) class-list))))))
        ;; END while!
        (goto-char (point-min))
        (while (re-search-forward "^\\([A-Z]+[ \t]+\\)?class" nil t)
          (when (progn
                  (forward-line 1)
                  (looking-at "^{"))
            (forward-line -1)
            (skip-chars-forward "A-Z")
            (skip-chars-forward " \t")
            (cbrow--skip-word "class")
            (skip-chars-forward " \t")
            (let ((class-only (buffer-substring-no-properties
                               (point) (save-excursion
                                         (skip-chars-forward (concat cbrow--identifier--chars ":"))
                                         (point))))
                  (template (buffer-substring-no-properties
                             (save-excursion
                               (forward-line -1)
                               (beginning-of-line)
                               (point))
                             (save-excursion
                               (forward-line -1)
                               (end-of-line)
                               (point)))))
                  ;;(if (string-match "Vector" class-only)
                  ;;    (debug "found Vector_2d_Cartesian<T>"))
                  (if (string-match "template<class \\(_*[a-zA-Z][a-zA-Z0-9_]*\\)>" template)
                      (progn
                        ;;(debug "Found template")
                        (setq template (concat class-only
                                               "<"
                                               (substring template (match-beginning 1) (match-end 1))
                                               ">")))
                    (setq template nil))
                  (setq cbrow--template-list (cons (list class-only template) cbrow--template-list))

                  ;;(if (not (string-match "_*[a-zA-Z][a-zA-Z0-9_]*\\(::_*[a-zA-Z][a-zA-Z0-9_]*\\)" *class*))
                  ;;    (setq *class* (concat "::" *class*)))
                  ;;(setq *class* (substring *class* (match-beginning 1) (match-end 1))))
                  ;;(debug "Zip skip")
                  (setq class-list (cons class-only class-list))
                  )))
        ;; END while!
        ;;(setq class-list (reverse class-list))
        (let ((ptr2 class-list))
          (setq ptr2 class-list)
          (while ptr2
            (setq cbrow--header-alist (cons (list (car ptr2) (car ptr)) cbrow--header-alist))
            ;; (assoc "A1" cbrow--header-alist)
            (setq ptr2 (cdr ptr2)))))
      ;;(setq class-list (delete-duplicates class-list :test 'string=))
      (kill-buffer (find-file (car ptr)))
      (setq ptr (cdr ptr)))
    cbrow--header-alist)
  )
;;(cbrow--init--header-alist)

;;(cbrow--init--footer-alist)
(defun cbrow--init--footer-alist ()
  ;;(setq ptr cbrow--header-alist)
  ;;(setq header-file (cadar ptr))
  ;;(setq footer-file (concat (substring header-file (match-beginning 1) (match-end 1)) cbrow--footer-regexp))
  (let ((ptr cbrow--header-alist))
    (setq cbrow--footer-alist nil)
    (while ptr
      (let ((*class*       (caar ptr))
            (header-file (cadar ptr)))
        (if (string-match "^\\(.*\\)\\.hh$" header-file)
          (let ((footer-file (concat (substring header-file (match-beginning 1) (match-end 1)) cbrow--footer)))
            (setq cbrow--footer-alist (cons (list *class* footer-file) cbrow--footer-alist))))
        ;;(insert (prin1-to-string (car ptr)))
        (setq ptr (cdr ptr))))
    (setq cbrow--footer-alist (reverse cbrow--footer-alist))
    )
  )
;; (cbrow--init--footer-alist)
;; (cbrow--split-string (setq string " public A1 , A2 "))
;; (cbrow--split-string (setq string " public A1 , A2"))
;; (cbrow--split-string (setq string "public A1 , A2"))
;; (cbrow--split-string (setq string "abc def , hif"))
;; (cbrow--split-string (setq string "abc , def"))
;; (cbrow--split-string (setq string " public A1 , A2 , private A3, A4"))
;; (cbrow--split-string (setq string "public Public1 , Public2, private Private1, Private2"))

(defun cbrow--split-string (string)
  (let* ((string      (format "%s%c" string ? ))
         (len         (length string))
         (i           0)
         (buf         "")
         (answer-list nil))
    (while (< i len)
      (let ((ch (aref string i)))
        (if (and (not (= ch ? ))
                 (not (= ch ?\t))
                 (not (= ch ?,)))
            (setq buf (format "%s%c" buf ch))
          (setq answer-list (cons buf answer-list))
          (setq buf "")))
      (incf i))
    ;; NOTE: remove crud from list
    ;; (setq answer-list '("public" "abc" "" "def"))
    (setq answer-list (delete "" answer-list))
    (setq answer-list (delete "public" answer-list))
    (setq answer-list (delete "private" answer-list))
    (setq answer-list (delete "protected" answer-list))
    (reverse answer-list)
    )
  )

;; (setq ptr (list (assoc "A" cbrow--header-alist)))
;; cbrow--superclass-alist
;; (cbrow--init--superclass-alist)
(defun cbrow--init--superclass-alist ()
  (let ((ptr cbrow--header-alist))
    (setq cbrow--superclass-alist nil)
    (setq cbrow--rest-alist nil)
    (while ptr
      (let ((*class*      (caar ptr))
            (file         (cadar ptr))
            (rest         nil)
            (superclasses nil)
            (class-only   nil))
        (if (string-match "\\(<[a-zA-Z0-9]+>\\)" *class*)
            (setq *class* (substring *class* 0 (match-beginning 0))))
        (if (string-match "^[a-zA-Z0-9_]*::\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)$" *class*)
            (setq class-only (substring *class* (match-beginning 1) (match-end 1)))
          (setq class-only *class*))
        (save-excursion
          (let ((auto-mode-alist (cons '("" . fundamental-mode) auto-mode-alist)))
            (save-buffer (find-file-read-only file))) ;;; allows us to safely kill the buffer
          (goto-char (point-min))
          ;;(debug "Viagra")
          (cond
           ;;((re-search-forward (concat "^\\([A-Z]+[ \t]+\\)*class[ \t]+" class-only "\\($\\|[ \t]*$\\)") nil t)
           ;; (beginning-of-line)
           ;; (forward-line 1)
           ;; (assert (looking-at "^[ \t]*{"))
           ;; (forward-line -1)
           ;; )
           ((re-search-forward (concat "^\\([A-Z]+[ \t]+\\)?class[ \t]+" class-only "\\($\\|[ \t][^;\n\r]*$\\)") nil t)
            (beginning-of-line)
            (forward-line 1)
            (assert (looking-at "{"))
            (forward-line -1))
           ((re-search-forward (concat "^   \\([A-Z]+[ \t]+\\)?class[ \t]+" class-only "\\($\\|[ \t][^\n\r;]*$\\)") nil t)
            (beginning-of-line)
            (forward-line 1)
            (skip-chars-forward " \t")
            (if 123 (assert (looking-at "{")))
            (forward-line -1)
            (beginning-of-line)
            ;;(Debug "Everest")
            )
           ((re-search-forward (concat "^\\([A-Z]+[ \t]+\\)?class[ \t]+" *class* "\\($\\|[ \t][^;\n\r]*$\\)") nil t)
            (beginning-of-line)
            (forward-line 1)
            (assert (looking-at "{"))
            (forward-line -1))
           ((re-search-forward (concat "^   \\([A-Z]+[ \t]+\\)?class[ \t]+" *class* "\\($\\|[ \t][^\n\r;]*$\\)") nil t)
            (beginning-of-line)
            (forward-line 1)
            (skip-chars-forward " \t")
            (if 123 (assert (looking-at "{")))
            (forward-line -1)
            (beginning-of-line)
            ;;(Debug "Everest")
            )
           (t
            (error "(123) Class %s not found in file %s" *class* file)))
          (skip-chars-forward " \t")
          (skip-chars-forward "A-Z")
          (skip-chars-forward " \t")

          ;;(if (string= *class* "Writer")
          ;;    (debug "Smegulator"))

          (assert (looking-at "class"))
          (cbrow--skip-word "class")
          (skip-chars-forward " \t")
          (assert (looking-at "\\(\\(_*[a-zA-Z][a-zA-Z0-9_]*::\\)?\\(_*[a-zA-Z][a-zA-Z0-9_]*\\)\\)"))
          ;;(setq *class* (buffer-substring-no-properties (match-beginning 1) (match-end 1)))
          (skip-chars-forward "a-zA-Z0-9_:")
          (if (re-search-forward ":" (point-at-eol) t)
              (progn
                (setq *namespace* (cbrow--inside-namespace))
                (skip-chars-forward " \t")
                (let* ((rest         (buffer-substring-no-properties (point) (point-at-eol)))
                       (superclasses (cbrow--split-string rest)))

                  ;;(debug "Spagetti")
                  (defun add-prefix (x)
                    (concat (if *namespace* (concat *namespace* "::")) x))
                  (setq superclasses (mapcar 'add-prefix superclasses))

                  ;;(if (string-match "public" rest) (debug "Watermelon"))

                  ;;                  (while (string-match "\\(public\\|private\\|protected\\) " rest)
                  ;;                    (setq rest (concat (substring rest 0 (match-beginning 1))
                  ;;                                       (substring rest (match-beginning 1) (match-end 1))
                  ;;                                       (if *namespace* (concat *namespace* "::"))
                  ;;                                       (substring rest (match-end 0)))))
                  ;;
                  ;;                  (while (string-match (concat "\\(public\\|private\\|protected\\)"
                  ;;                                               (if *namespace*
                  ;;                                                   (concat "\\(" *namespace* "::\\)")
                  ;;                                                 "\\([a-zA-Z0-9_]\\)")) rest)
                  ;;                    (setq rest (concat (substring rest 0 (match-end 1))
                  ;;                                       " ";; (if *namespace* (concat *namespace* "::"))
                  ;;                                       (substring rest (match-beginning 2)))))
                  (setq cbrow--superclass-alist (cons (cons *class* superclasses) cbrow--superclass-alist))
                  ;;(debug)
                  (setq cbrow--rest-alist (cons (list *class* rest) cbrow--rest-alist))
                  ;;(if (or (string= "Reader" *class*) (string= "Reader" class-only))
                  ;;(if (string-match "^::_*[a-zA-Z][a-zA-Z0-9_]*" *class*)
                  ;;(if (string-match "dmp::string" rest)
                  ;;  (debug "Cactus"))
                  )
                )
            ;;(setq cbrow--rest-alist (cons (list *class* "") cbrow--rest-alist))
            )
          (kill-buffer (find-file file))
          ))
      (setq ptr (cdr ptr))))
  )

;;; Cbrow--subclass-alist
;;; (cbrow--init--subclass-alist)
(defun cbrow--init--subclass-alist ()
  (let ((ptr cbrow--superclass-alist))
    (setq cbrow--subclass-alist nil)
    (while ptr
      (let ((ptr2     nil)
            (subclass nil))
        (setq ptr2 (car ptr))      ;;; set first element
        (setq subclass (car ptr2))
        (setq ptr2 (cdr ptr2))     ;;; skip over first element
        (while ptr2
          (let* ((superclass (car ptr2))
                 (a          (assoc superclass cbrow--subclass-alist)))
            ;;(insert superclass " has subclass " subclass "\n")
            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
            (if (not a)
                (setq cbrow--subclass-alist (cons (list superclass subclass)
                                                  cbrow--subclass-alist))
              (setcdr (last a) (list subclass))))
            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
          (setq ptr2 (cdr ptr2))))
      (setq ptr (cdr ptr))))
  )

(defvar cbrow--footer ".cc")
(defvar cbrow--init-done nil)

(defun cbrow--init ()
  (interactive)
  (let (list1 list2 list3 list4 list5)
    (setq list1 (directory-files "~/lisp++-projects/2006/Tritus-II/"      t "\\.hh$"))
    (setq list2 (directory-files "~/lisp++-projects/2006/Tritus-II/level-editor/" t "\\.hh$"))
    (setq list3 (directory-files "~/lisp++-projects/2006/gui-menus/"      t "\\.hh$"))
    (setq list4 (directory-files "~/lisp++-projects/2006/gui-widgets/"    t "\\.hh$"))
    (setq list5 (directory-files "~/lisp++-projects/2006/libd/"           t "\\.hh$"))
    (setq cbrow--headers (append list1 list2 list3 list4 list5)))

(cbrow--init--header-alist)     ;;; cbrow--header-alist
  (cbrow--init--footer-alist)     ;;; cbrow--footer-alist
  (cbrow--init--superclass-alist) ;;; cbrow--superclass-alist
  (cbrow--init--subclass-alist)   ;;; cbrow--subclass-alist
  (setq cbrow--init-done t)
  (message "cbrow--init done")
  )

;;(cbrow--init)

(provide 'cbrow)
Back
| Main Menu | Research Projects | Photo Album | Curriculum Vitae | The Greatest Artists |
| Email Address | Computer Games | Web Design | Java Training Wheels | The Fly (A Story) |
| Political Activism | Scruff the Cat | My Life Story | Smoking Cessation | Other Links |
| Debugging Macros | String Class I | Linked List System I | Java for C Programmers | Naming Convention |
| String Class II | How I use m4 | Strings III | Symmetrical I/O | Linked Lists II |
| Run-Time Type Info | Virtual Methods | An Array System | Science & Religion | Submodes |
| Nested Packages | Memory Leaks | Garbage Collection | Internet & Poverty | What is Knowledge? |
| Limits of Evolution | Emacs Additions | Function Plotter | Romantic Love | The Next Big Thing |
| Science Fiction | Faster Compilation | Theory of Morality | Elisp Scoping | Elisp Advice |
| S.O.G.M. Pattern | Safe Properties | School Bullying | Charisma Control | Life and Death |
| Splitting Java | Multiple Ctors | Religious Beliefs | Conversation 1 | Conversation 2 |
| J.T.W. Language | Emacs Additions II | Build Counter | Relation Plotter | Lisp++ Language |
| Memory Leaks II | Super Constructors | CRUD Implementation | Order a Website Form | There Is An Afterlife |
| More Occam's Razor | C to Java Translator | Theory of Morality II
Last modified: Sat Apr 29 18:38:29 NZST 2017
Best viewed at 800x600 or above resolution.
© Copyright 1999-2017 Davin Pearson.
Please report any broken links to