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