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