Emacs/cc-ide: More robust function movement
[emacsstuff.git] / cc-ide / cc-ide.el
1 ;;; cc-ide.el --- C++ IDE
2 ;;
3 ;; $Id$
4 ;;
5 ;; Copyright (C) 2000 Stefan Bund
6
7 ;; cc-ide.el is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published
9 ;; by the Free Software Foundation; either version 2, or (at your
10 ;; option) any later version.
11
12 ;; cc-ide.el is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 ;; General Public License for more details.
16
17 ;;; Commentary:
18
19 ;;; Change-Log:
20
21 ;; $Log$
22 ;;
23
24 ;;; Variables:
25
26 (defvar ccide-compile-opts "DEBUG=1"
27   "*Additional options to make command")
28
29 (defvar ccide-file-vars nil)
30
31 (defvar ccide-default-author "")
32 (defvar ccide-default-copyright "")
33
34 (defvar ccide-all-includes-guard nil)
35
36 (defvar ccide-corba-skel-dir "")
37 (defvar ccide-corba-idl-dir "")
38 (defvar ccide-corba-idl-command "omniidl2 -w")
39
40 (defvar c-user-prefixes '("inline" "static" "prefix_")
41   "*List of possible prefixes for function definitions.")
42
43 (defvar ccide-default-prefix "prefix_"
44   "*Prefix added to every implementation header. Probably eiter empty or 'prefix_'")
45
46 (defvar ccide-gen-throw nil
47   "*If non-nil, generate throw_ specs")
48
49 (defvar ccide-project-root)
50
51 (defconst c-user-prefix-re (regexp-opt c-user-prefixes t))
52
53 (defconst ccide-doxy-tag-re 
54   (concat "\\\\\\(group\\|defgroup\\|see\\|author\\|version\\|id\\|since"
55           "\\|returns?\\|throws?\\|exception\\|raises\\|param\\|li\\|brief"
56           "\\|internal\\|bug\\|fixme\\|todo\\|idea\\|implementation"
57           "\\|note\\|attention\\|warning\\|par\\|code\\|endcode"
58           "\\|post\\|pre\\)\\b"))
59
60 (defconst ccide-special-extensions
61   '(".h" ".hh" ".mpp" ".ih" ".cc" ".cpp" ".ct" ".cti" ".cci" ".dox"))
62
63 (defconst ccide-implementation-extensions
64   '(".h" ".hh" ".ih" ".cc" ".cpp" ".ct" ".cti" ".cci"))
65
66 (defconst ccide-class-defaults-word 
67   "// \\(default\\|no\\|protected\\|private\\|disabled\\|my\\)")
68
69 (defconst  ccide-bindings
70   '(
71     ;; file level
72     ("fc"  ccide-file-comment                 "File comment")
73     ("fs"  ccide-syncronize-includes          "Sync includes")
74     (nil   nil                                separator)
75                                           
76     ;; class level                        
77     ("cc"  ccide-class-comment                "Class comment")
78     ("cg"  ccide-gen-class                    "Generate class")
79     ("cd"  ccide-gen-class-defaults           "Generate class defaults")
80     ("cD"  ccide-gen-class-defaults-impl      "Generate class defaults impl")
81
82     ("csd" ccide-set-class-defaults-default   "Set class defaults comment" "Default")
83     ("csn" ccide-set-class-defaults-no        "Set class defaults comment" "No")
84     ("csp" ccide-set-class-defaults-protected "Set class defaults comment" "Protected")
85     ("csr" ccide-set-class-defaults-private   "Set class defaults comment" "Private")
86     ("csx" ccide-set-class-defaults-disabled  "Set class defaults comment" "Disabled")
87     ("csm" ccide-set-class-defaults-my        "Set class defaults comment" "My")
88
89     ("cS"  ccide-gen-struct-constructors      "Generate structure constructors")
90
91     ("ci"  ccide-class-impl-comment           "Generate class implemenation comment")
92
93     ("ce"  ccide-gen-exception                "Generate an exception class")
94
95     (nil   nil                                separator)
96                                           
97     ;; method level                       
98     ("mc"  ccide-function-comment             "Method comment")
99     ("mp"  ccide-grab-prototype               "Grab prototype")
100     ("mr"  ccide-reformat-defun               "Reformat defun")
101     ("mx"  ccide-replace-defun                "Replace defun")
102     ("mt"  ccide-prefix-defun-type-with-class "Prefix defun type with class")
103     ("mn"  ccide-prefix-defun-type-with-namespace "Prefix defun type with namespace")
104     ("mi"  ccide-grab-inline-decl             "Grab inline decl")
105     ("mA"  ccide-grab-all-inlines             "Grab ALL inline decls")
106     ("mC"  ccide-grab-create-constructor      "Grab CREATE constructor")
107     ("mI"  ccide-grab-create-constructor-impl "Build CREATE cosntructor")
108     ("mf"  ccide-find-implementation          "Find method implementation")
109     ("mT"  ccide-insert-defun-prefix          "Insert current defun prefix at point")
110     (nil   nil                                separator)
111                                           
112     ;; variable level                     
113     ("vc"  ccide-variable-comment             "Variable comment")
114     ("vf"  ccide-grab-access-fn               "Grab access methods")
115     (nil   nil                                separator)
116
117     ;; documentation
118     ("h"  ccide-hide-all-doxy-comments        "Hide all Doxygen comments")
119     ("s"  ccide-show-all-comments             "Show all Doxygen comments")
120                                           
121 ;    ;; CORBA                             
122 ;    ("Cg"  ccide-gen-corba-impl                      "Generate CORBA impl")
123 ;    ("Cm"  ccide-gen-corba-impl-methods       "Generate CORBA impl methods")
124 ;    (nil   nil                               separator)
125                                           
126     ;; templates                          
127 ;    ("ts"  ccide-scan-mantemps               "Scan mantemps")
128 ;    (nil   nil                                separator)
129
130 ;    ;; other
131 ;    ("of"  ccide-open-compilation-frame       "Open *compilation* frame")
132 ;    ("oc"  ccide-compile-compile              "Make -> Compile")
133 ;    ("ox"  ccide-compile-clean                "Make -> Clean")
134 ;    ("od"  ccide-compile-cleandepends         "Make -> Clean depends")
135 ;    ("ok"  ccide-compile-kill                 "Kill compilation")
136 ;    ("oh"  ccide-hide-compilation             "Hide *compilation* buffer")
137
138     ))
139
140 ;;; Code:
141
142 (require 'cc-engine-2)
143 (require 'cc-helper)
144 (require 'c++)
145 (require 'cl)
146 (require 'hideshow)
147 ;(require 'mantemp)
148 (require 'locate)
149 (require 'lucid)
150 (require 'varcmd)
151 (require 'misc-local)
152
153 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
154 ;; utils
155
156 (defsubst ccide-match-string (n)
157   (buffer-substring-no-properties (match-beginning n) (match-end n)))
158
159 (defun ccide-file-macro-name (&optional file-name)
160   (concat (upcase (file-name-extension (or file-name (buffer-file-name))))
161           "_" 
162           (string-replace "\\." "_" (file-name-sans-extension 
163                                      (file-name-nondirectory 
164                                       (or file-name (buffer-file-name))))
165                           t nil t t)
166           "_"))
167
168 (defun ccide-file-name (&optional extension file-name directory)
169   (concat (if directory (file-name-as-directory directory) "")
170           (file-name-sans-extension
171            (file-name-nondirectory 
172             (or file-name (buffer-file-name))))
173           extension))
174
175 (defun ccide-in-doxy-comment ()
176   (save-excursion
177     (back-to-indentation)
178     (let ((lit (c-in-literal)))
179       (if (cond ((eq lit 'c)
180                  (goto-char (car (c-literal-limits)))
181                  (looking-at "/\\*\\*<?[ \t\n\r@]"))
182                 ((eq lit 'c++)
183                  (goto-char (car (c-literal-limits)))
184                  (looking-at "///<?[ \t\n\r@]"))
185                 (t nil))
186           (progn
187             (goto-char (match-end 0))
188             (current-column))))))
189
190 (defun ccide-shell-command (command)
191   (let ((obuf (get-buffer-create "*ccide shell command*"))
192         exit-status)
193     (save-excursion
194       (set-buffer obuf)
195       (erase-buffer)
196       (insert command "\n"))
197     (setq exit-status (call-process shell-file-name nil "*ccide shell command*" nil
198                                     shell-command-switch command))
199     (and exit-status (equal exit-status 0))))
200
201 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
202 ;; file level
203
204 (defun ccide-file-comment ()
205   "Add a comment to this source file."
206   (interactive)
207   (let ((mode "c++")
208         point add-file-vars)
209     (push-mark)
210     (goto-char (point-min))
211     (insert "// Copyright (C) " (number-to-string (nth 5 (decode-time)))
212             " " ccide-default-author "\n"
213             ccide-default-copyright
214             "\n")
215
216     (cond ((string-match "\\.hh?$" (buffer-file-name))
217            (insert "/** \\file\n"
218                    "    \\brief " (ccide-file-name) " public header */\n\n"
219                    "#ifndef " (ccide-file-macro-name) "\n"
220                    "#define " (ccide-file-macro-name) " 1\n\n"
221                    "// Custom includes\n\n"
222                    "//#include \"" (ccide-file-name ".mpp") "\"\n"
223                    "///////////////////////////////hh.p////////////////////////////////////////\n\n")
224            (setq point (point))
225            (goto-char (point-max))
226            (insert "\n\n///////////////////////////////hh.e////////////////////////////////////////\n")
227            (if ccide-all-includes-guard
228                (insert "#endif\n"
229                        "#if !defined(" ccide-all-includes-guard ") && !defined(" (ccide-file-macro-name) "i_)\n"
230                        "#define " (ccide-file-macro-name) "i_\n"))
231            (insert "//#include \"" (ccide-file-name ".cci") "\"\n"
232                    "//#include \"" (ccide-file-name ".ct") "\"\n"
233                    "//#include \"" (ccide-file-name ".cti") "\"\n"
234                    "#endif"))
235
236           ((string-match "\\.mpp$" (buffer-file-name))
237            (insert "/** \\file\n"
238                    "    \\brief " (ccide-file-name) " Boost.Preprocesser external iteration include */\n\n"
239
240
241                    "#if !BOOST_PP_IS_ITERATING && !defined(" (ccide-file-macro-name) ")\n"
242                    "#define " (ccide-file-macro-name) " 1\n\n"
243                    "// Custom includes\n\n\n"
244                    "// ///////////////////////////mpp.p////////////////////////////////////////\n"
245                    "#elif BOOST_PP_IS_ITERATING // ////////////////////////////////////////////\n"
246                    "// ////////////////////////////////////////////////////////////////////////\n"
247                    "// Local Macros\n\n\n"
248                    "// ////////////////////////////////////////////////////////////////////////\n"
249                    "#if BOOST_PP_ITERATION_FLAGS()==1 // //////////////////////////////////////\n"
250                    "// ////////////////////////////////////////////////////////////////////////\n\n")
251            (setq point (point))
252            (goto-char (point-max))
253            (insert "\n\n// ////////////////////////////////////////////////////////////////////////\n"
254                    "#endif // /////////////////////////////////////////////////////////////////\n"
255                    "// ////////////////////////////////////////////////////////////////////////\n"
256                    "// Undefine local Macros\n\n\n"
257                    "// ////////////////////////////////////////////////////////////////////////\n"
258                    "#endif // /////////////////////////////////////////////////////////////////\n"
259                    "// ///////////////////////////mpp.e////////////////////////////////////////"))
260
261           ((string-match "\\.ih$" (buffer-file-name))
262            (insert "/** \\file\n"
263                    "    \\brief " (ccide-file-name) " internal header */\n\n"
264                    "#ifndef " (ccide-file-macro-name) "\n"
265                    "#define " (ccide-file-macro-name) " 1\n\n"
266                    "// Custom includes\n\n"
267                    "///////////////////////////////ih.p////////////////////////////////////////\n\n")
268            (setq point (point))
269            (goto-char (point-max))
270            (insert "\n\n///////////////////////////////ih.e////////////////////////////////////////\n"
271                    "#endif"))
272
273           ((or (string-match "\\.test\\.cc$" (buffer-file-name))
274                (string-match "\\.test\\.cpp$" (buffer-file-name)))
275            (insert "/** \\file\n"
276                    "    \\brief " (ccide-file-name) " unit tests */\n\n"
277                    "//#include \"" (ccide-file-name ".hh") "\"\n"
278                    "//#include \"" (ccide-file-name ".ih") "\"\n\n"
279                    "// Custom includes\n"
280                    "#include \"" (ccide-file-name ".hh" (ccide-file-name)) "\"\n\n"
281                    "#include <boost/test/auto_unit_test.hpp>\n"
282                    "#include <boost/test/test_tools.hpp>\n\n"
283                    "#define prefix_\n"
284                    "///////////////////////////////cc.p////////////////////////////////////////\n\n")
285            (setq point (point))
286            (goto-char (point-max))
287            (insert "\n\n///////////////////////////////cc.e////////////////////////////////////////\n"
288                    "#undef prefix_"))
289
290           ((or (string-match "\\.cc$" (buffer-file-name))
291                (string-match "\\.cpp$" (buffer-file-name)))
292            (insert "/** \\file\n"
293                    "    \\brief " (ccide-file-name) " non-inline non-template implementation */\n\n"
294                    "//#include \"" (ccide-file-name ".hh") "\"\n"
295                    "//#include \"" (ccide-file-name ".ih") "\"\n\n"
296                    "// Custom includes\n\n"
297                    "//#include \"" (ccide-file-name ".mpp") "\"\n"
298                    "#define prefix_\n"
299                    "///////////////////////////////cc.p////////////////////////////////////////\n\n")
300            (setq point (point))
301            (goto-char (point-max))
302            (insert "\n\n///////////////////////////////cc.e////////////////////////////////////////\n"
303                    "#undef prefix_\n"
304                    "//#include \"" (ccide-file-name ".mpp") "\""))
305
306           ((string-match "\\.cci$" (buffer-file-name))
307            (insert "/** \\file\n"
308                    "    \\brief " (ccide-file-name) " inline non-template implementation */\n\n"
309                    "// Custom includes\n\n"
310                    "#define prefix_ inline\n"
311                    "///////////////////////////////cci.p///////////////////////////////////////\n\n")
312            (setq point (point))
313            (goto-char (point-max))
314            (insert "\n\n///////////////////////////////cci.e///////////////////////////////////////\n"
315                    "#undef prefix_"))
316
317           ((string-match "\\.ct$" (buffer-file-name))
318            (insert "/** \\file\n"
319                    "    \\brief " (ccide-file-name) " non-inline template implementation  */\n\n"
320                    "//#include \"" (ccide-file-name ".ih") "\"\n\n"
321                    "// Custom includes\n\n"
322                    "#define prefix_\n"
323                    "///////////////////////////////ct.p////////////////////////////////////////\n\n")
324            (setq point (point))
325            (goto-char (point-max))
326            (insert "\n\n///////////////////////////////ct.e////////////////////////////////////////\n"
327                    "#undef prefix_"))
328
329           ((string-match "\\.cti$" (buffer-file-name))
330            (insert "/** \\file\n"
331                    "    \\brief " (ccide-file-name) " inline template implementation */\n\n"
332                    "//#include \"" (ccide-file-name ".ih") "\"\n\n"
333                    "// Custom includes\n\n"
334                    "#define prefix_ inline\n"
335                    "///////////////////////////////cti.p///////////////////////////////////////\n\n")
336            (setq point (point))
337            (goto-char (point-max))
338            (insert "\n\n///////////////////////////////cti.e///////////////////////////////////////\n"
339                    "#undef prefix_"))
340
341           ((string-match "\\.dox$" (buffer-file-name))
342            (insert "/** \\mainpage\n\n    ")
343            (setq point (point))
344            (insert "\n */")
345            (setq add-file-vars '(( mode . flyspell)
346                                  ( mode . auto-fill))))
347
348           ((string-match "\\.java$" (buffer-file-name))
349            (setq mode "jde")
350            (setq point (point))
351            (goto-char (point-max)))
352
353           (t
354            (setq point (point))
355            (goto-char (point-max))))
356
357     (insert "\n\n\f\n"
358             "// Local Variables:\n"
359             "// mode: " mode "\n")
360     (loop for (var . value) in ccide-file-vars
361           do (insert "// " (symbol-name var) ": " (prin1-to-string value) "\n"))
362     (loop for (var . value) in add-file-vars
363           do (insert "// " (symbol-name var) ": " (prin1-to-string value) "\n"))
364     (insert "// End:\n")
365     (if point
366         (goto-char point))
367     (if (equal mode "jde")
368         (let ((package (file-name-directory (buffer-file-name))))
369           (jdeap-initialize-setup)
370           (if (not (equal jdeap-current-source-directory "."))
371               (if (string-match 
372                    (concat "^" (regexp-quote jdeap-current-source-directory))
373                    package)
374                   (progn
375                     (setq package (substring package 
376                                              (match-end 0)
377                                              (1- (length package))))
378                     (insert "package "
379                             (string-replace "/" "." package t)
380                             ";\n\n"))))
381           (insert "class " (file-name-sans-extension
382                             (file-name-nondirectory 
383                              (buffer-file-name))) "\n{}")
384           (beginning-of-line)))))
385
386 (defun ccide-sync-file-variables ()
387   "Syncronize file variables to the current value of ccide-file-vars"
388   (interactive)
389   (save-excursion
390     (goto-char (point-max))
391     (search-backward "\n\^L" (max (- (point-max) 3000) (point-min)) 'move)
392     (let ((case-fold-search t))
393       (if (search-forward "Local Variables:" nil t)
394           (let (prefix suffix vars)
395             (skip-chars-forward " \t")
396             (or (eolp)
397                 (setq suffix (buffer-substring (point) (progn (end-of-line) (point)))))
398             (goto-char (match-beginning 0))
399             (or (bolp)
400                 (setq prefix (buffer-substring (point) (progn (beginning-of-line) (point)))))
401             (loop do (progn
402                        (forward-line 1)
403                        (if (and prefix (looking-at prefix))
404                            (goto-char (match-end 0)))
405                        (skip-chars-forward " \t"))
406                   while (not (looking-at "end:"))
407                   do (progn
408                        (setq vars (cons (intern (buffer-substring 
409                                                  (point) 
410                                                  (progn (skip-chars-forward "^:\n") (point))))
411                                         vars))))
412             (beginning-of-line)
413             (loop for (var . value) in ccide-file-vars
414                   do (if (not (memq var vars))
415                          (insert (or prefix "")
416                                  (symbol-name var) ": " (prin1-to-string value) 
417                                  (or suffix "") "\n"))))))))
418
419 (defun ccide-syncronize-includes ()
420   "Syncronize include's in all other files"
421   (interactive)
422   (let (buffer-map)
423     (loop for extension in ccide-special-extensions
424           for file-name = (ccide-file-name extension)
425           do (setq buffer-map
426                    (cons (cons file-name
427                                (or (find-buffer-visiting file-name)
428                                    (and (file-readable-p file-name)
429                                         (find-file-noselect file-name))))
430                          buffer-map)))
431     (save-excursion
432       (loop for buffer in buffer-map
433             if (cdr buffer)
434               do (progn 
435                    (set-buffer (cdr buffer))
436                    (save-excursion
437                      (loop for include in buffer-map
438                            do (progn 
439                                 (goto-char (point-min))
440                                 (while (re-search-forward 
441                                         (concat "^\\(//\\)?#\\s-*include \""
442                                                 (regexp-quote (car include))
443                                                 "\"\\s-*$")
444                                         nil t)
445                                   (goto-char (match-beginning 0))
446                                   (if (looking-at "//")
447                                       (if (cdr include)
448                                           (delete-char 2))
449                                     (if (not (cdr include))
450                                         (insert "//")))
451                                   (forward-line 1))))))))))
452
453 (defun ccide-auto-decorate-new-files ()
454   (if (= (point-min) (point-max))
455       (let ((status (buffer-modified-p)))
456         (ccide-file-comment)
457         (set-buffer-modified-p status))))
458
459 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
460 ;; class level
461
462 (defun ccide-class-comment ()
463   "Add comment to start of current class definition"
464   (interactive)
465   (let ((class (c-get-class-at-point)))
466     (if (not class)
467         (error "No class found")
468       (goto-char (or (aref (car class) 3)
469                      (aref (car class) 1)))
470       (if (save-excursion 
471             (forward-line -1)
472             (ccide-in-doxy-comment))
473           (progn
474             (search-backward "/**" nil t)
475             (forward-char 4))
476         (let ((indent (make-string (current-indentation) ? )))
477           (insert "/** \\brief  ")
478           (save-excursion
479             (insert "\n"
480                     indent " */\n"
481                     indent)))))))
482
483 (defun ccide-gen-class (name &optional defns)
484   "Generate class declaration template"
485   (interactive (list (read-string (concat "Class name (default "
486                                           (ccide-file-name)
487                                           "): ")
488                                   nil nil (ccide-file-name))))
489   (insert "class " name)
490   (indent-according-to-mode)
491   (let ((in (make-string c-basic-offset ? ))
492         (ofs (make-string (current-indentation) ? )))
493     (save-excursion
494       (beginning-of-line)
495       (open-line 1)
496       (insert ofs "/** \\brief\n"
497               ofs "  */"))
498     (insert "\n" ofs)
499     (save-excursion
500       (insert "{\n"
501               ofs "public:\n"
502               ofs in "///////////////////////////////////////////////////////////////////////////\n"
503               ofs in "// Types\n\n"
504               ofs in "///////////////////////////////////////////////////////////////////////////\n"
505               ofs in "///\\name Structors and default members\n"
506               ofs in "///@{\n\n"
507               ofs in "// default default constructor\n"
508               ofs in "// default copy constructor\n"
509               ofs in "// default copy assignment\n"
510               ofs in "// default destructor\n\n"
511               ofs in "// no conversion constructors\n\n"
512               ofs in "///@}\n"
513               ofs in "///////////////////////////////////////////////////////////////////////////\n"
514               ofs in "///\\name Accessors\n"
515               ofs in "///@{\n\n"
516               ofs in "///@}\n"
517               ofs in "///////////////////////////////////////////////////////////////////////////\n"
518               ofs in "///\\name Mutators\n"
519               ofs in "///@{\n\n"
520               ofs in "///@}\n\n")
521       (loop for defn in defns
522             do (insert ofs in defn ";\n"))
523       (if defns
524           (insert "\n"))
525       (insert ofs "protected:\n\n"
526               ofs "private:\n\n"
527               ofs "};\n"))))
528
529 (defun ccide-gen-class-defaults ()
530   "Generate signatures of the default functions: default constructor,
531 copy constructor, assignment operator and destructor."
532   (indent-according-to-mode)
533   (let* ((name (c-scope-name (aref (car (c-get-class-at-point)) 1)))
534          (in (make-string c-basic-offset ? ))
535          (ofs (make-string (current-indentation) ? ))
536          (tspec (if ccide-gen-throw (concat "\n" ofs in "throw_(());\n") ";\n"))
537          (colon 0))
538     (while (string-match "::" name colon)
539       (setq colon (match-end 0)))
540     (setq name (substring name colon))
541     (beginning-of-line)
542     (delete-horizontal-space)
543     (loop with exit = nil
544           do (message (concat "1-dflt constr, 2-destr, "
545                               "3-copy constr, 4-copy assmnt, "
546                               "c-all copy, d-all dflt, RET-all/done: "))
547           for ch = (read-event)
548           for first = t then nil
549           do (cond ((eq ch 'return)
550                     (if first
551                         (insert ofs name "()" 
552                                 tspec
553                                 ofs name "(const " name "& other)" 
554                                 tspec
555                                 ofs "~" name "();\n"
556                                 ofs name "& operator=(const " name "& other)"
557                                 tspec))
558                     (setq exit t))
559                    ((eq ch ?1)
560                     (insert ofs name "()" 
561                             tspec))
562                    ((eq ch ?2)
563                     (insert ofs "~" name "();\n"))
564                    ((eq ch ?3)
565                     (insert ofs name "(const " name "& other)" 
566                             tspec))
567                    ((eq ch ?4)
568                     (insert ofs name "& operator=(const " name "& other)"
569                             tspec))
570                    ((eq ch ?c)
571                     (insert ofs name "(const " name "& other)" 
572                             tspec
573                             ofs name "& operator=(const " name "& other)"
574                             tspec))
575                    ((eq ch ?d)
576                     (insert ofs name "()" 
577                             tspec
578                             ofs "~" name "();\n"))
579                    (t (setq unread-command-events (cons ch unread-command-events))
580                       (setq exit t)))
581           while (not exit))))
582
583 (defun ccide-gen-class-defaults-impl ()
584   "Generate default implementations for class default functions"
585   (interactive)
586   (let ((defn (c-build-default-funcions-impl)))
587     (kill-new (cadr defn))
588     (message (concat (car defn) " default members"))))
589
590 (defun ccide-set-class-defaults-comment (word)
591   (save-excursion
592     (back-to-indentation)
593     (if (not (looking-at ccide-class-defaults-word))
594         (message "Not at class defaults commnet")
595       (replace-match word t t nil 1))))
596
597 (defmacro ccide-build-class-defaults-f (sym)
598   (let ((fn (intern (concat "ccide-set-class-defaults-" 
599                             (symbol-name sym)))))
600     `(defun ,fn ()
601        (interactive)
602        (ccide-set-class-defaults-comment ,(symbol-name sym)))))
603
604 (ccide-build-class-defaults-f no)
605 (ccide-build-class-defaults-f default)
606 (ccide-build-class-defaults-f my)
607 (ccide-build-class-defaults-f protected)
608 (ccide-build-class-defaults-f private)
609 (ccide-build-class-defaults-f disabled)
610
611 (defun ccide-gen-struct-constructors ()
612   (save-excursion
613     (beginning-of-line)
614     (open-line 1)
615     (indent-according-to-mode)
616     (let* ((scope (c-get-block-scope))
617            (class (c-parse-class scope))
618            (variables (c-get-variable-members-with-type class))
619            (name (c-scope-name (aref (car (last scope)) 1)))
620            (in (make-string (current-indentation) ? ))
621            (inin (make-string (+ (current-indentation) c-basic-offset) ? )))
622       (insert name "()\n" inin ": ")
623       (indent-according-to-mode)
624       (loop for var in variables
625             for first = t then nil
626             if (not first) do (insert ", ")
627             do (insert (car var) "()"))
628       (insert "\n" in "{}\n"
629               in name "(")
630       (loop for var in variables
631             for first = t then nil
632             if (not first) do (insert ", ")
633             do (insert (cdr var) " " (car var) "_"))
634       (insert ")\n" inin ": ")
635       (loop for var in variables
636             for first = t then nil
637             if (not first) do (insert ", ")
638             do (insert (car var) "(" (car var) "_)"))
639       (insert "\n" in "{}"))))
640
641 (defun ccide-class-impl-comment ()
642   "Get implementation comment for current class"
643   (interactive)
644   (let* ((scope (c-get-block-scope))
645          (name (c-get-full-prefix scope)))
646     (kill-new (concat (make-string 75 ?/) "\n"
647                       "// " name "\n\n"
648                       "// protected\n\n"
649                       "// private\n\n"))
650     (message name)))
651
652 (defun ccide-gen-exception (class &optional description)
653   (interactive "sException name: ")
654   (beginning-of-line)
655   (open-line 1)
656   (indent-according-to-mode)
657   (save-excursion
658     (let ((in (make-string c-basic-offset ? ))
659           (ofs (make-string (current-indentation) ? ))
660           (prefix (c-get-full-prefix (c-get-block-scope)))
661           p)
662       (insert "struct " class " : public std::exception\n"
663               ofs "{ virtual char const * what() const throw() ")
664       (setq p (point))
665       (insert "{ return \"" prefix "::" class "\"; } };")
666       (if (> (current-column) fill-column)
667           (save-excursion
668             (goto-char p)
669             (insert "\n" ofs in in))))))
670
671 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
672 ;; function/method level
673
674 (defun ccide-function-comment ()
675   "Add comment for current function"
676   (interactive)
677   (if (memq (c-in-literal) '(c c++))
678       ; Assume, we are in the functions comment ...
679       (progn
680         (c-forward-out-of-comment)
681         (c-backward-syntactic-ws)
682         (c-backward-sexp)))
683   (c-beginning-of-defun-or-decl)
684   (let ((defun (c-get-defun-state))
685         (indent (make-string comment-column ? ))
686         place)
687     (goto-char (or (aref defun 7) (car (aref defun 6))))
688     (c-backward-syntactic-ws)
689     (if (looking-at "[ \t\n\r]*///<")
690         (progn
691           (delete-region (point) (progn (skip-chars-forward " \t\n\r") (point)))
692           (if (> (current-column) comment-column)
693               (insert "\n"))
694           (indent-to-column comment-column)
695           (search-forward "*/")
696           (forward-char -2))
697       (if (> (current-column) comment-column)
698           (insert "\n"))
699       (indent-to-column comment-column)
700       (insert "///< ")
701       (setq place (point))
702       (insert "\n" 
703               indent "/**< ")
704       (insert             "\\pre \n"
705                           indent "     \\post */")
706       (save-excursion
707         (goto-char (car (aref defun 2)))
708         (setq defun (c-get-defun-state)))
709       (forward-char -2))
710     (ccide-function-comment-adjust defun (concat indent "     "))
711     (if place (goto-char place))))
712
713 (defun ccide-function-comment-grab-args ()
714   (let ((limit (save-excursion
715                  (search-backward "/**" nil t)
716                  (point)))
717         (end  (point))
718         begin start args argend)
719     (setq argend end)
720     (while (or (search-backward "\\param" limit t)
721                (search-backward "\\return" limit t)))
722     (beginning-of-line)
723     (setq start (point))
724     (setq begin start)
725     (while (search-forward "\\param" argend t)
726       (or (search-forward "\\param" argend t)
727           (search-forward "\\return" argend t)
728           (goto-char argend))
729       (beginning-of-line)
730       (setq args (cons (ccide-function-comment-parse-arg start (point))
731                        args))
732       (setq start (point)))
733     (prog1
734         (if (not (search-forward "\return" argend t))
735             (cons nil args)
736           (beginning-of-line)
737           (cons (buffer-substring (point) argend) args))
738       (delete-region begin end))))
739
740 (defun ccide-function-comment-parse-arg (start end)
741   (save-excursion
742     (goto-char start)
743     (re-search-forward "\\\\param\\(\\[[^]]*\\]\\)?\\s-*\\(\\S-*\\)" end t)
744     (cons (match-string 2) 
745           (cons (buffer-substring start (match-beginning 2))
746                 (buffer-substring (match-end 2) end)))))
747   
748 (defun ccide-function-comment-get-throws (defun)
749   (if (aref defun 4)
750       (save-excursion
751         (goto-char (car (aref defun 4)))
752         (if (re-search-forward "\\(throw_\\|throw\\)((?\\s-*\\([^()]*\\))?)" 
753                                (cdr (aref defun 4)) t)
754             (let ((spec (match-string 2)))
755               (if (> (length spec) 0)
756                   spec))))))
757
758 (defun ccide-function-comment-adjust (defun indent)
759   (insert "\n")
760   (let* ((defargs (mapcar (function (lambda (x)
761                                       (c-get-template-argument-name (car x) (cdr x))))
762                           (aref defun 3)))
763          (defret (and (aref defun 1)
764                       (not (string-match (concat "^\\("
765                                                  c-special-key 
766                                                  "\\s-*\\)*\\s-*void$")
767                                          (buffer-substring (car (aref defun 1))
768                                                            (cdr (aref defun 1)))))))
769          (throws (ccide-function-comment-get-throws defun))
770          (xargs (ccide-function-comment-grab-args))
771          (docargs (cdr xargs))
772          (docret (car xargs))
773          (def-in-doc (loop for defarg in defargs always (assoc defarg docargs)))
774          (doc-in-def (loop for docarg in docargs always (member (car docarg) defargs)))
775          (size-eq (= (length defargs) (length docargs))))
776     ;; We differentiate four types changes
777     ;;  - new arguments
778     ;;  - removed arguments
779     ;;  - reordered arguments
780     ;;  - renamed arguments
781     ;; 
782     ;; If the change cannot be described by one of the above, it has
783     ;; to be resolved manually
784     (if throws
785         (insert indent "\\throws " throws "\n"))
786     (cond (doc-in-def
787            ;; reordered arguments or new arguments (or no change)
788            (loop for defarg in defargs
789                  for docarg = (assoc defarg docargs)
790                  do (if docarg
791                         (insert (cadr docarg) (car docarg) (cddr docarg))
792                       (insert indent "\\param " defarg " \n"))))
793           (size-eq ; and (not doc-in-def)
794            ;; renamed arguments
795            (loop for defarg in defargs
796                  for docarg in docargs
797                  do (insert (cadr docarg) defarg (cddr docarg))))
798           (def-in-doc
799             ;; removed arguments
800             (loop for defarg in defargs
801                   for docarg = (assoc defarg docargs)
802                   do (insert (cadr docarg) (car docarg) (cddr docarg))))
803           (t (error "Arg change too complex. Resolve manualy.")))
804     ;; return value is simple
805     (if defret
806         (if docret
807             (insert docret)
808           (insert indent "\\return \n"))))
809   (delete-char -1)
810   (delete-horizontal-space)
811   (insert " "))
812
813 (defun ccide-grab-prototype (&optional prefix)
814   "Grab prototype of function defined or declared at point. Prefix
815 arg, if given, specifies the kind of prefix (inline, static, ...) to use."
816   (interactive "P")
817   (save-excursion
818     (c-beginning-of-defun-or-decl)
819     (let* ((prfx (or (and prefix (nth (prefix-numeric-value prefix) c-user-prefixes))
820                      ccide-default-prefix))
821            (defn (c-build-defun prfx)))
822       (kill-new (concat (cadr defn) "\n{}\n"))
823       (message (concat (or prfx "")
824                        (if prfx " " "")
825                        (car defn))))))
826
827 (defun ccide-reformat-defun ()
828   "Reformat the defn of the current defun."
829   (interactive)
830   (save-excursion
831     (c-beginning-of-defun-or-decl)
832     (let ((defn (c-build-defun nil t)))
833       (delete-region (or (caar (aref (caddr defn) 0))
834                          (car (aref (caddr defn) 1))
835                          (car (aref (caddr defn) 2)))
836                      (or (car (aref (caddr defn) 6))
837                          (aref (caddr defn) 7)))
838       (insert (cadr defn) "\n"))))
839
840 (defun ccide-replace-defun ()
841   "Replace the function header with the one on the top of the kill
842 ring (presumably placed there using c++-grab-prototype)."
843   (interactive)
844   (save-excursion
845     (c-beginning-of-defun-or-decl)
846     (let ((parse (c-parse-defun)))
847       (delete-region (or (aref parse 0)
848                          (aref parse 1)
849                          (aref parse 2))
850                      (or (aref parse 5)
851                          (aref parse 6)
852                          (aref parse 7)))
853       (yank)
854       (delete-char -3))))
855
856 (defun ccide-prefix-defun-type-with-class (&optional strip)
857   "If a non-keyword type symbol is found prefixing the current defun,
858 it will be prefixed with the current class prefix."
859   (interactive "p")
860   (save-excursion
861     (c-beginning-of-defun-or-decl)
862     (let* ((parse (c-parse-defun))
863            (prefix (c-scope-name (aref parse 2) (+ (or strip 0) 0))))
864       (goto-char (aref parse 1))
865       (while (and (or (looking-at c-any-key)
866                       (looking-at c-user-prefix-re)
867                       (not (c-at-symbol-p)))
868                   (< (point) (aref parse 2))
869                   (not (eobp)))
870         (c-forward-token-1)
871         (c-forward-syntactic-ws))
872       (if (and (c-at-symbol-p)
873                (< (point) (aref parse 2))
874                (not (looking-at (regexp-quote prefix))))
875           (let ((pos (string-match "<" prefix)))
876             (if pos
877                 (insert "typename "))
878             (if (and pos (looking-at (concat (substring prefix 0 pos)
879                                              "\\b[^_]")))
880                 (progn
881                   (goto-char (match-end 0))
882                   (c-backward-syntactic-ws)
883                   (insert (substring prefix pos)))
884               (insert prefix "::"))
885             (ccide-reformat-defun))))))
886
887 (defun ccide-prefix-defun-type-with-namespace (&optional strip)
888   (interactive "p")
889   (ccide-prefix-defun-type-with-class (+ (or strip 0) 1)))
890
891 (defun ccide-insert-defun-prefix (&optional strip)
892   "Insert the current defun prefix at point."
893   (interactive "p")
894   (let* ((parse (c-parse-defun))
895          (prefix (c-scope-name (aref parse 2) (+ (or strip 0) 0))))
896     (insert prefix "::")))
897
898 (defun ccide-kill-inline-decl (defn)
899   (save-excursion
900     (if (aref (caddr defn) 6)
901         (progn
902           (goto-char (cdr (aref (caddr defn) 6)))
903           (let ((end-mark (point-marker)))
904             (goto-char (car (aref (caddr defn) 6)))
905             (indent-rigidly (point) end-mark
906                             (- (current-column)))
907             (prog1
908                 (concat (cadr defn)
909                         "\n"
910                         (buffer-substring-no-properties (point) end-mark)
911                         "\n")
912               (when (aref (caddr defn) 5)
913                 (goto-char (caar (aref (caddr defn) 5)))
914                 (c-backward-syntactic-ws)
915                 (skip-chars-backward ":"))
916               (c-backward-syntactic-ws)
917               (delete-region (point) end-mark)
918               (insert ";"))))
919       (concat (cadr defn) "\n{}\n"))))
920
921 (defun ccide-grab-inline-decl ()
922   "Grab the inline decl at point at turn it into an out-of-line inline
923 declaration at the top of the kill ring."
924   (interactive)
925   (let ((defn (c-build-defun (or ccide-default-prefix "inline"))))
926     (kill-new (ccide-kill-inline-decl defn))
927     (message (concat (or ccide-default-prefix "indline") 
928                      " " 
929                      (car defn)))))
930
931 (defun ccide-grab-all-inlines ()
932   "Grab all inline decls in the current class"
933   (interactive)
934   (let ((class (c-parse-class (c-get-block-scope)))
935         defns)
936     (when class
937       (loop for method in (nreverse (aref class 4))
938             do (when (eq (car method) 'method)
939                  (let ((defn (save-excursion
940                                (goto-char (cdr method))
941                                (c-build-defun (or ccide-default-prefix "inline")))))
942                    (if (aref (caddr defn) 6)
943                        (setq defns (nconc defns (list (ccide-kill-inline-decl defn))))))))
944       (kill-new (loop for defn in (nreverse defns)
945                       for next = nil then t
946                       if next concat "\n";
947                       concat defn))
948       (message (format "%d inlines grabed to kill ring" (length defns))))))
949                        
950
951 (defun ccide-grab-create-constructor ()
952   (interactive)
953   (let ((defn (c-build-create-constructor)))
954     (kill-new (cadr defn))
955     (message (car defn))))
956
957 (defun ccide-grab-create-constructor-impl (&optional prefix)
958   (interactive "P")
959   (let* ((prfx (or (and prefix (nth (prefix-numeric-value prefix) c-user-prefixes))
960                    ccide-default-prefix))
961          (defn (c-build-create-constructor-impl prfx)))
962     (kill-new (cadr defn))
963     (message (concat (or prfx "")
964                      (if prfx " " "")
965                      (car defn)))))
966
967 (defun ccide-find-implementation (&optional other-window)
968   "Find implementation of method declared at point."
969   (interactive "P")
970   (let* ((state (c-get-defun-state))
971          (name (c-defun-short-name state))
972          (scoped-name (c-defun-full-name state))
973          (args (ccide-implementation-args state))
974          (targs (ccide-implementation-template-args state))
975          rv fallback)
976
977     (loop for ext in ccide-implementation-extensions
978           for filename = (ccide-file-name ext)
979           while (not rv)
980           do (progn
981                (let ((buf (or (find-buffer-visiting filename)
982                                   (and (file-readable-p filename)
983                                        (find-file-noselect filename)))))
984                  (when buf
985                    (let ((found (save-excursion
986                                   (set-buffer buf)
987                                   (ccide-find-implementation-1 name scoped-name args targs
988                                                                (not (aref state 6))
989                                                                (car (aref state 2))))))
990                      (if found
991                          (if (cdr found)
992                              (setq rv (cons buf found))
993                            (if (not fallback) (setq fallback (cons buf found))))))))))
994     (if (not rv) (setq rv fallback))
995     (if rv
996         (let* ((buf (car rv))
997                (pos (cadr rv))
998                (win (get-buffer-window buf)))
999           (if win 
1000               (select-window win)
1001             (if other-window
1002                 (switch-to-buffer-other-window buf)
1003               (switch-to-buffer buf)))
1004           (goto-char pos)
1005           (forward-char -1)
1006           (c-beginning-of-defun-or-decl))
1007       (message (concat "Implementation of " scoped-name " not found.")))))
1008
1009 (defun ccide-implementation-args (state)
1010   (string-replace "[ \t\n\r]+" ""
1011                   (loop for (start . end) in (aref state 3)
1012                         for sep = "" then ","
1013                         concat sep
1014                         concat (buffer-substring-no-properties 
1015                                 start (save-excursion
1016                                         (goto-char start)
1017                                         (if (search-forward "=" end 'move) (forward-char -1))
1018                                         (point))))
1019                   
1020                   t))
1021
1022 (defun ccide-implementation-template-args (state)
1023   (and (aref state 0)
1024        (string-replace "[ \t\n\r]+" ""
1025                        (loop for (start . end) in   (save-excursion
1026                                                       (goto-char (caar (last (aref state 0))))
1027                                                       (c-parse-template-declaration))
1028                              for sep = "" then ","
1029                              concat sep
1030                              concat (buffer-substring-no-properties 
1031                                      start (save-excursion
1032                                              (goto-char start)
1033                                              (if (search-forward "=" end 'move) (forward-char -1))
1034                                              (point))))
1035                        t)))
1036
1037 (defun ccide-find-implementation-1 (name scoped-name args targs with-body skip-def)
1038   ;; Within the current buffer, search for all implementations of the
1039   ;; given function. The rv is a list of conses. The car holds the
1040   ;; buffer position of the implementation, the cdr is t if the name,
1041   ;; scoped-name and args are matched, otherwise the args did not match.
1042   (save-excursion
1043     (goto-char (point-min))
1044     (let ((re (concat (if (eq (char-syntax (aref name 0)) ?w) "\\<" "")
1045                       (regexp-quote name)
1046                       (if (eq (char-syntax (aref name (1- (length name)))) ?w) "\\>" "")))
1047           fallback rv check-state)
1048       (while (and (not rv) (re-search-forward re nil t))
1049         (if (and (c-at-toplevel-p) 
1050                  (not (c-in-literal))
1051                  (setq check-state (condition-case nil (c-get-defun-state) (error nil)))
1052                  (not (= (car (aref check-state 2)) skip-def)))
1053             (if (string= scoped-name (c-defun-full-name check-state))
1054                 (if (and (if with-body (aref check-state 6) (not (aref check-state 6)))
1055                          (string= args (ccide-implementation-args check-state))
1056                          (string= targs (ccide-implementation-template-args check-state)))
1057                     (setq rv (cons (point) t))
1058                   (if (not fallback) 
1059                       (setq fallback (cons (point) nil)))))))
1060       (or rv fallback))))
1061
1062 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1063 ;; variable/type level
1064   
1065 (defun ccide-variable-comment ()
1066   "Add a comment to current variable declaration."
1067   (interactive)
1068   (c-forward-out-of-comment)
1069   (c-forward-syntactic-ws)
1070   (while (not (looking-at ";"))
1071     (c-forward-sexp)
1072     (c-forward-syntactic-ws))
1073   (forward-char 1)
1074   (if (> (current-column) comment-column)
1075       (insert "\n" (make-string comment-column ? ) "///< ")
1076     (indent-to-column comment-column)
1077     (insert "///< ")))
1078
1079 (defun ccide-grab-access-fn ()
1080   (interactive)
1081   (save-excursion
1082     (beginning-of-line)
1083     (if (looking-at (concat c++-simple-type-regexp "[ \t\n\r][a-zA-Z0-9_]+[ \t\n\r]*;"))
1084         (let ((vardef (match-string 0))
1085               (in (make-string c-basic-offset ? ))
1086               type reftype varname fnname argname ws)
1087           (forward-line -1)
1088           (back-to-indentation)
1089           (string-match "^[ \t\n\r]*\\(.*\\)[ \t\n\r]\\([a-zA-Z0-9_]+\\)[ \t\n\r]*;$"
1090                         vardef)
1091           (setq varname (match-string 2 vardef)
1092                 type (match-string 1 vardef)
1093                 ws (substring vardef 0 (match-beginning 1)))
1094           (if (string-match "_$" varname)
1095               (setq fnname (string-replace "_$" "" varname)
1096                     argname (concat "a_" fnname))
1097             (setq fnname (concat "q_" varname)
1098                   argname (concat "a_" varname)))
1099           (if (string-match "^[ \t\n\r]*" type)
1100               (setq type (substring type (match-end 0))))
1101           (if (string-match "^[A-Z]" type)
1102               (setq reftype (concat type " const &"))
1103             (setq reftype type))
1104           (kill-new (concat ws type " " fnname "(" reftype " " argname ")\n"
1105                             ws in "{\n"
1106                             ws in in type " old" varname " = " varname ";\n"
1107                             ws in in varname " = " argname ";\n"
1108                             ws in in "return old" varname ";\n"
1109                             ws in "}\n\n"
1110                             ws reftype " " fnname "() const\n"
1111                             ws in "{ return " varname "; }\n"))
1112           
1113           (message varname))
1114       (message "No variable found"))))
1115
1116 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1117 ;; doxy comment support functions
1118
1119 (defun ccide-special-indent-function ()
1120   "Function to indent doxy comments correctly"
1121   (let ((indent (ccide-in-doxy-comment)))
1122     (if indent
1123         (let ((lim (save-excursion
1124                      (back-to-indentation)
1125                      (c-literal-limits)))
1126               (pos (- (point-max) (point))))
1127           (save-excursion
1128             (back-to-indentation)
1129             (if (looking-at "*/")
1130                 (incf indent -3)
1131               (let ((para (or (save-excursion (re-search-backward "^\\s-*$" (car lim) t))
1132                               (car lim))))
1133                 (if (and (not (looking-at ccide-doxy-tag-re))
1134                          (re-search-backward (concat "^\\s-*"
1135                                                      ccide-doxy-tag-re)
1136                                              para t))
1137                     (incf indent 4)))))
1138           (delete-region (progn (beginning-of-line) (point))
1139                          (progn (back-to-indentation) (point)))
1140           (indent-to indent)
1141           (if (> (- (point-max) pos) (point))
1142               (goto-char (- (point-max) pos)))))))
1143   
1144 (defun ccide-fill-function ()
1145   "auto-fill function for doxy comments"
1146   (if (do-auto-fill)
1147       (if (not fill-prefix)
1148           (indent-according-to-mode))))
1149
1150 (defun ccide-hide-all-doxy-comments ()
1151   "Hide all doxy comments"
1152   (interactive)
1153   (save-excursion
1154     (goto-char (point-min))
1155     (while (re-search-forward "^\\s-*/\\*\\*" nil t)
1156       (beginning-of-line)
1157       (forward-line -1)
1158       (if (not (looking-at "\\s-*$"))
1159           (forward-line 1))
1160       (forward-char -1)
1161       (let ((start (point)))
1162         (if (re-search-forward "\\*/" nil t)
1163             (progn
1164               (if (looking-at "\\s-*\n")
1165                   (forward-line 1))
1166               (forward-char -1)
1167               (let ((overlay (make-overlay start (point))))
1168                 (overlay-put overlay 'intangible 'hs)
1169                 (overlay-put overlay 'invisible 'hs)))))))
1170   (message "Done."))
1171
1172 (defun ccide-show-all-comments ()
1173   "Show all comments"
1174   (interactive)
1175   (save-excursion
1176     (goto-char (point-min))
1177     (while (not (eobp))
1178       (goto-char (next-overlay-change (point)))
1179       (loop for overlay in (overlays-at (point))
1180             if (eq (overlay-get overlay 'invisible) 'hs)
1181             do (delete-overlay overlay))))
1182   (message "Done."))
1183
1184 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1185 ;; CORBA support (omniORB2)
1186
1187 (defun ccide-get-corba-headers ()
1188   (let (files)
1189     (save-excursion
1190       (goto-char (point-min))
1191       (while (re-search-forward "#include\\s-*[\"<]\\([^\">]*\\)\\.hh[\">]" nil t)
1192         (setq files (cons (ccide-match-string 1) files)))
1193       (nreverse files))))
1194
1195 (defun ccide-corba-maybe-build-hh (file)
1196   (let ((skel (ccide-file-name ".hh" file ccide-corba-skel-dir))
1197         (idl (ccide-file-name ".idl" file ccide-corba-idl-dir)))
1198     (if (and (file-readable-p idl)
1199              (or (not (file-readable-p skel))
1200                  (file-newer-than-file-p idl skel)))
1201         (let ((buffer (find-buffer-visiting (ccide-file-name ".hh" file))))
1202           (if buffer
1203               (kill-buffer buffer))
1204           (message "Please wait ... building %s" (ccide-file-name ".hh" file))
1205           (if (ccide-shell-command (concat "cd " 
1206                                            (real-path-name ccide-corba-skel-dir) 
1207                                            " && " 
1208                                            ccide-corba-idl-command 
1209                                            (if (> (length ccide-corba-idl-dir) 0)
1210                                                (concat " -I" ccide-corba-idl-dir))
1211                                            " " 
1212                                            idl))
1213               ()
1214             (display-buffer (get-buffer-create "*ccide shell command*"))
1215             (error "Generation of %s failed" (ccide-file-name ".hh")))))
1216     (if (not (file-readable-p skel))
1217         (error "No file %s or %s" 
1218                (ccide-file-name ".hh" file) (ccide-file-name ".idl" file)))))
1219
1220 (defun ccide-corba-list-skeletons-1 (hh-file)
1221   (ccide-corba-maybe-build-hh hh-file)
1222   (let ((hh-buf (find-file-noselect (ccide-file-name ".hh" hh-file)))
1223         skels)
1224     (save-excursion
1225       (set-buffer hh-buf)
1226       (save-excursion
1227         (goto-char (point-min))
1228         (while (re-search-forward "^\\s-*class\\s-+_sk_\\([a-zA-Z0-9_]+\\)\\s-+:"
1229                                   nil t)
1230           (setq skels (cons (ccide-match-string 1) skels)))))
1231     (mapcar (function (lambda (x) (cons x hh-file)))
1232             (sort skels 'string-lessp))))
1233
1234 (defun ccide-corba-list-skeletons ()
1235   (let ((files (ccide-get-corba-headers)))
1236     (loop for file in files
1237           append (ccide-corba-list-skeletons-1 file))))
1238
1239 (defun ccide-gen-corba-impl (class)
1240   (interactive (list (completing-read "Class name of skeleton: "
1241                                       (ccide-corba-list-skeletons)
1242                                       nil t)))
1243   (let* ((skels (ccide-corba-list-skeletons))
1244          (hh-file (ccide-file-name ".hh" (cdr (assoc class skels))
1245                                    ccide-corba-skel-dir))
1246          (hh-buf (find-file-noselect (ccide-file-name ".hh" hh-file
1247                                                       ccide-corba-skel-dir))))
1248     (ccide-gen-class (concat class "_i"))
1249     (insert (make-string c-basic-offset ? ) ": public virtual _sk_" class "\n")
1250     (save-excursion
1251       (search-forward "protected:" nil t)
1252       (forward-line -1)
1253       (ccide-gen-corba-impl-methods)
1254       (insert "\n"))))
1255
1256 (defun ccide-get-corba-defns (hh-file class)
1257   (let ((hh-buf (find-file-noselect hh-file))
1258         defns)
1259     (save-excursion
1260       (set-buffer hh-buf)
1261       (save-excursion
1262         (goto-char (point-min))
1263         (if (not (re-search-forward (concat "^\\s-*class\\s-+_sk_" class "\\s-+:")
1264                                     nil t))
1265             (error "CORBA skeleton class not found.")
1266           (search-forward "{")
1267           (forward-char -1)
1268           (let ((end (save-excursion (forward-sexp) (point))))
1269             (while (and (< (point) end)
1270                         (< (forward-line 1) 1))
1271               (if (looking-at "\\s-+virtual\\s-+\\(.*)\\)\\s-*=\\s-*0;\\s-*$")
1272                   (setq defns (cons (match-string 1) defns))))))))
1273     (nreverse defns)))
1274
1275 (defun ccide-gen-corba-impl-methods ()
1276   (interactive)
1277   (let* ((class (c-get-class-at-point))
1278          (point (point)))
1279     (if (not class)
1280         (error "No class at point."))
1281     (save-excursion
1282       (goto-char (aref (car class) 1))
1283       (if (not (re-search-forward ":\\s-*public\\s-*virtual\\s-*_sk_\\([^ \t\n\r{},:]*\\)"
1284                                   nil t))
1285           (error "No CORBA impl at point."))
1286       (let* ((name (ccide-match-string 1))
1287              (skels (ccide-corba-list-skeletons))
1288              (hh-file (ccide-file-name ".hh" (cdr (assoc name skels))
1289                                        ccide-corba-skel-dir))
1290              (defns (ccide-get-corba-defns hh-file name))
1291              end)
1292         (goto-char (aref (car class) 2))
1293         (save-excursion
1294           (c-forward-sexp)
1295           (setq end (point)))
1296         (if (re-search-forward "^\\s-*// CORBA$" end t)
1297             (let ((start (match-beginning 0)))
1298               (if (re-search-forward "^\\s-*// END-CORBA$" end t)
1299                   (let ((eend (match-end 0)))
1300                     (goto-char start)
1301                     (forward-line 1)
1302                     (if (re-search-forward "/\\*\\|//" (match-beginning 0) t)
1303                         (if (y-or-n-p "Remove CORBA Funktion comments? (y/n)")
1304                             (delete-region start (1+ eend))
1305                           (goto-char eend)
1306                           (beginning-of-line)
1307                           (delete-region (point) (progn 
1308                                                    (end-of-line)
1309                                                    (1+ (point))))
1310                           (save-excursion
1311                             (goto-char start)
1312                             (delete-region (point) (progn 
1313                                                      (end-of-line)
1314                                                      (1+ (point)))))
1315                           (insert "\n"))
1316                       (delete-region start (1+ eend))))))
1317           (goto-char point))
1318         (indent-according-to-mode)
1319         (insert "// CORBA\n")
1320         (loop for defn in defns
1321               do (progn
1322                    (save-excursion (insert defn ";"))
1323                    (indent-according-to-mode)
1324                    (let ((start (point)) end)
1325                      (end-of-line)
1326                      (setq end (point))
1327                      (goto-char start)
1328                      (while (re-search-forward "\\s-+" end t)
1329                        (replace-match " ")
1330                        (setq end (- end (- (match-end 0) (match-beginning 0) 1))))
1331                      (end-of-line)
1332                      (loop with done = nil
1333                            while (> (current-column) c-max-def-column)
1334                            do (while (and (> (current-column) c-max-def-column)
1335                                           (search-backward "," start t)))
1336                            do (if (looking-at ",")
1337                                   (progn
1338                                     (forward-char 1)
1339                                     (insert "\n")
1340                                     (open-line 1)
1341                                     (indent-according-to-mode)
1342                                     (delete-char 2)
1343                                     (setq start (point))
1344                                     (end-of-line))
1345                                 (setq done t))
1346                            while (not done)))
1347                    (insert "\n")))
1348         (indent-according-to-mode)
1349         (insert "// END-CORBA\n")))))
1350
1351 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1352 ;; template support
1353
1354 (defun ccide-scan-mantemps ()
1355   "Scan *compilation* buffer for errors and generate manual template
1356 instatiations at point."
1357   (interactive)
1358   (save-excursion
1359     (set-buffer "*compilation*")
1360     (goto-char (point-min)))
1361   (save-excursion
1362     (set-buffer (get-buffer-create "*mantemps*"))
1363     (erase-buffer)
1364     (loop for temp = (ccide-get-mantemp)
1365           while temp
1366           do (insert temp "\n"))
1367     (mantemp-make-mantemps-buffer)
1368     (goto-char (point-min))
1369     (while (progn
1370              (ccide-fix-mantemp)
1371              (< (forward-line 1) 1))))
1372   (insert-buffer-substring "*mantemps*"))
1373
1374 (defun ccide-get-mantemp ()
1375   (save-excursion
1376     (set-buffer "*compilation*")
1377     (if (search-forward "undefined reference to `" nil t)
1378         (let ((start (point)))
1379           (end-of-line)
1380           (search-backward "'" nil t)
1381           (buffer-substring start (point))))))
1382
1383 (defun ccide-fix-mantemp ()
1384   (let ((end (save-excursion
1385                (end-of-line) (point))))
1386     (if (and (save-excursion (search-forward "(" end t))
1387              (search-forward " class" end t))
1388         (progn
1389           (forward-char -6)
1390           (delete-char 6)))))
1391       
1392 (provide 'cc-ide)
1393
1394 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1395 ;; other stuff
1396
1397 (defun ccide-open-compilation-frame ()
1398   (interactive)
1399   (let ((c-frame (selected-frame))
1400         (compilation-frame (make-frame '((minibuffer . nil) 
1401                                          (unsplittable . t) 
1402                                          (menu-bar-lines . 0) 
1403                                          (top . -87) 
1404                                          (left . 36) 
1405                                          (width . 169) 
1406                                          (height . 9)))))
1407     (select-frame compilation-frame)
1408     (switch-to-buffer "*compilation*")
1409     (set-window-dedicated-p (selected-window) t)))
1410
1411 (defun ccide-compile (command)
1412   (delete-other-windows)
1413   (split-window-horizontally)
1414   (compile command)
1415   (save-excursion
1416     (set-buffer "*compilation*")
1417     (let ((point (point-max)))
1418       (goto-char point)
1419       (loop for window in (get-buffer-window-list "*compilation*" nil t)
1420             do (set-window-point window point)))))
1421
1422 (defun ccide-compile-compile ()
1423   (interactive)
1424   (ccide-compile (concat "make -k " ccide-compile-opts)))
1425
1426 (defun ccide-compile-clean ()
1427   (interactive)
1428   (ccide-compile (concat "make -k " ccide-compile-opts " clean")))
1429
1430 (defun ccide-compile-cleandepends ()
1431   (interactive)
1432   (ccide-compile (concat "make -k " ccide-compile-opts " cleandepends")))
1433
1434 (defun ccide-compile-kill ()
1435   (interactive)
1436   (set-buffer "*compilation*")
1437   (kill-compilation))
1438
1439 (defun ccide-hide-compilation ()
1440   (interactive)
1441   (let ((active (selected-window)))
1442     (unwind-protect
1443         (loop for window in (get-buffer-window-list "*compilation*")
1444               do (progn (select-window window)
1445                         (switch-to-buffer (other-buffer "*compilation*"))))
1446       (select-window active))))
1447
1448 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1449 ;; keymap and installation
1450
1451 (defun ccide-bind-keys (prefix map)
1452   (loop for binding in ccide-bindings
1453         do (apply 'vcmd-define-key
1454                   map
1455                   (concat prefix (car binding))
1456                   (cadr binding)
1457                   "IDE"
1458                   (cddr binding))))
1459
1460 (defun ccide-install-it ()
1461   (save-excursion
1462     (hs-minor-mode 1)
1463     (hs-show-all))
1464   (local-unset-key "\C-c;")
1465   (local-unset-key [menu-bar IDE])
1466   (ccide-bind-keys "\C-c;" (current-local-map))
1467   (local-set-key "\C-cC" 'ccide-hide-all-doxy-comments)
1468   (local-set-key "\C-cS" 'ccide-show-all-comments)
1469   (set (make-local-variable 'auto-fill-function) 'ccide-fill-function)
1470   (set (make-local-variable 'paragraph-start) (concat "[ \t\f]*$\\|[ \t\f]*" ccide-doxy-tag-re))
1471   (set (make-local-variable 'paragraph-separate) "[ \t\f]*$")
1472   (auto-fill-mode -1)
1473   (ccide-project-load-config)
1474   (ccide-directory-load-config)
1475   (ccide-auto-decorate-new-files))
1476
1477 (defun ccide-project-load-config ()
1478   (let ((conf (ccide-project-search-upwards "project.el" (file-name-directory (buffer-file-name)))))
1479     (when conf
1480       (set (make-local-variable 'ccide-project-root) (file-name-directory conf))
1481       (load-file conf))))
1482
1483 (defun ccide-project-search-upwards (file &optional dir)
1484   "Search for FILE in all directories starting at DIR and going up the directory hierarchy.
1485 DIR defaults to ccide-project-root"
1486   (let (conf last-dir)
1487     (setq dir (expand-file-name "x" (or dir ccide-project-root)))
1488     (while (and (not (string= (setq last-dir dir 
1489                                     dir (directory-file-name (file-name-directory dir))) last-dir))
1490                 (setq conf (expand-file-name file dir))
1491                 (not (file-readable-p conf))))
1492     (and (file-readable-p conf) conf)))
1493
1494 (defun ccide-directory-load-config ()
1495   (if (file-readable-p ".dir.el")
1496       (load-file ".dir.el")))
1497
1498 (add-hook 'c-mode-hook 'ccide-install-it)
1499 (add-hook 'c++-mode-hook 'ccide-install-it)
1500 (add-hook 'c-special-indent-hook 'ccide-special-indent-function)
1501
1502 (loop for extension in ccide-special-extensions
1503       for re = (concat (regexp-quote extension) "$")
1504       if (not (assoc re auto-mode-alist))
1505         do (setq auto-mode-alist (append auto-mode-alist
1506                                          (list (cons re 'c++-mode)))))
1507
1508 (defadvice c-indent-line (after c-indent-less compile disable) ;activate
1509   ;; new indent function for c-mode: do standard indentation first. If line
1510   ;; is to long using standard indentation, just indent by c-basic-indentation.
1511   (let ((cc (save-excursion (end-of-line) (current-column)))
1512         indent)
1513     (if (> cc  85)
1514         (let ((pos (- (point-max) (point))))
1515           (beginning-of-line)
1516           (let ((point (point))
1517                 (line (1+ (count-lines 1 (point))))
1518                 indent)
1519             (c-beginning-of-statement-2)
1520             (if (and (not (c-crosses-statement-barrier-p (point) point))
1521                      (not (eq (+ (count-lines 1 (point))
1522                                  (if (bolp) 1 0))
1523                               line)))
1524                 (progn
1525                   (setq indent (+ (current-indentation) c-basic-offset))
1526                   (goto-char point)
1527                   (if (< indent (current-indentation))
1528                       (progn
1529                         (setq ad-return-value
1530                               (+ ad-return-value
1531                                  (- (current-indentation) indent)))
1532                         (delete-region (c-point 'bol) (c-point 'boi))
1533                         (indent-to indent))))))
1534           (if (< (point) (c-point 'boi))
1535               (back-to-indentation)
1536             (if (> (- (point-max) pos) (point))
1537                 (goto-char (- (point-max) pos))))))))
1538
1539
1540 \f
1541 ;;; Local Variables:
1542 ;;; elisp-project-autoload-file-name: "cc-autoload.el"
1543 ;;; End: