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