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