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