Kde/Utils: Add krunscript tool
[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 pos
806                 (insert "typename "))
807             (if (and pos (looking-at (concat (substring prefix 0 pos)
808                                              "\\b[^_]")))
809                 (progn
810                   (goto-char (match-end 0))
811                   (c-backward-syntactic-ws)
812                   (insert (substring prefix pos)))
813               (insert prefix "::"))
814             (ccide-reformat-defun))))))
815
816 (defun ccide-prefix-defun-type-with-namespace (&optional strip)
817   (interactive "p")
818   (ccide-prefix-defun-type-with-class (+ (or strip 0) 1)))
819
820 (defun ccide-insert-defun-prefix (&optional strip)
821   "Insert the current defun prefix at point."
822   (interactive "p")
823   (let* ((parse (c-parse-defun))
824          (prefix (c-scope-name (aref parse 2) (+ (or strip 0) 0))))
825     (insert prefix "::")))
826
827 (defun ccide-kill-inline-decl (defn)
828   (save-excursion
829     (if (aref (caddr defn) 6)
830         (progn
831           (goto-char (cdr (aref (caddr defn) 6)))
832           (let ((end-mark (point-marker)))
833             (goto-char (car (aref (caddr defn) 6)))
834             (indent-rigidly (point) end-mark
835                             (- (current-column)))
836             (prog1
837                 (concat (cadr defn)
838                         "\n"
839                         (buffer-substring-no-properties (point) end-mark)
840                         "\n")
841               (when (aref (caddr defn) 5)
842                 (goto-char (caar (aref (caddr defn) 5)))
843                 (c-backward-syntactic-ws)
844                 (skip-chars-backward ":"))
845               (c-backward-syntactic-ws)
846               (delete-region (point) end-mark)
847               (insert ";"))))
848       (concat (cadr defn) "\n{}\n"))))
849
850 (defun ccide-grab-inline-decl ()
851   "Grab the inline decl at point at turn it into an out-of-line inline
852 declaration at the top of the kill ring."
853   (interactive)
854   (let ((defn (c-build-defun (or ccide-default-prefix "inline"))))
855     (kill-new (ccide-kill-inline-decl defn))
856     (message (concat (or ccide-default-prefix "indline") 
857                      " " 
858                      (car defn)))))
859
860 (defun ccide-grab-all-inlines ()
861   "Grab all inline decls in the current class"
862   (interactive)
863   (let ((class (c-parse-class (c-get-block-scope)))
864         defns)
865     (when class
866       (loop for method in (nreverse (aref class 4))
867             do (when (eq (car method) 'method)
868                  (let ((defn (save-excursion
869                                (goto-char (cdr method))
870                                (c-build-defun (or ccide-default-prefix "inline")))))
871                    (if (aref (caddr defn) 6)
872                        (setq defns (nconc defns (list (ccide-kill-inline-decl defn))))))))
873       (kill-new (loop for defn in (nreverse defns)
874                       for next = nil then t
875                       if next concat "\n";
876                       concat defn))
877       (message (format "%d inlines grabed to kill ring" (length defns))))))
878                        
879
880 (defun ccide-grab-create-constructor ()
881   (interactive)
882   (let ((defn (c-build-create-constructor)))
883     (kill-new (cadr defn))
884     (message (car defn))))
885
886 (defun ccide-grab-create-constructor-impl (&optional prefix)
887   (interactive "P")
888   (let* ((prfx (or (and prefix (nth (prefix-numeric-value prefix) c-user-prefixes))
889                    ccide-default-prefix))
890          (defn (c-build-create-constructor-impl prfx)))
891     (kill-new (cadr defn))
892     (message (concat (or prfx "")
893                      (if prfx " " "")
894                      (car defn)))))
895
896 ;; (defun ccide-find-implementation (&optional other-window)
897 ;;   "Find implementation of method declared at point."
898 ;;   (interactive "P")
899 ;;   (let ((def (c-build-defun))
900 ;;      match pos)
901 ;;     (setq match (concat (regexp-quote (car def)) "[ \t\n\r]*("))
902 ;;     (setq match (string-replace "::" "::[ \t\n\r]*" match t nil t t))
903 ;;     (message match)
904 ;;     (loop for ext in ccide-implementation-extensions
905 ;;        do (let* ((filename (ccide-file-name ext))
906 ;;                  (buf (and (file-readable-p filename) (find-file-noselect filename))))
907 ;;             (if buf
908 ;;                 (save-excursion
909 ;;                   (set-buffer buf)
910 ;;                   (goto-char (point-min))
911 ;;                   (if (loop while (search-forward-regexp match nil t)
912 ;;                             do (forward-char -1)
913 ;;                             thereis (c-at-toplevel-p))
914 ;;                       (setq pos (cons buf (point)))))))
915 ;;        until pos)
916 ;;     (if pos
917 ;;      (let ((win (get-buffer-window (car pos))))
918 ;;           (if win
919 ;;               (select-window win)
920 ;;             (if other-window
921 ;;                 (switch-to-buffer-other-window (car pos))
922 ;;               (switch-to-buffer (car pos))))
923 ;;        (goto-char (cdr pos))
924 ;;        (forward-char -1)
925 ;;        (c-beginning-of-defun-or-decl))
926 ;;       (message (concat "Implementation of " (car def) " not found.")))))
927
928 (defun ccide-find-implementation (&optional other-window)
929   "Find implementation of method declared at point."
930   (interactive "P")
931   (let* ((state (c-get-defun-state))
932          (name (c-defun-short-name state))
933          (scoped-name (c-defun-full-name state))
934          (args (ccide-implementation-args state))
935          (targs (ccide-implementation-template-args state))
936          rv fallback)
937
938     (loop for ext in ccide-implementation-extensions
939           for filename = (ccide-file-name ext)
940           while (not rv)
941           do (progn
942                (let ((buf (or (find-buffer-visiting filename)
943                                   (and (file-readable-p filename)
944                                        (find-file-noselect filename)))))
945                  (when buf
946                    (let ((found (save-excursion
947                                   (set-buffer buf)
948                                   (ccide-find-implementation-1 name scoped-name args targs
949                                                                (not (aref state 6))
950                                                                (car (aref state 2))))))
951                      (if found
952                          (if (cdr found)
953                              (setq rv (cons buf found))
954                            (if (not fallback) (setq fallback (cons buf found))))))))))
955     (if (not rv) (setq rv fallback))
956     (if rv
957         (let* ((buf (car rv))
958                (pos (cadr rv))
959                (win (get-buffer-window buf)))
960           (if win 
961               (select-window win)
962             (if other-window
963                 (switch-to-buffer-other-window buf)
964               (switch-to-buffer buf)))
965           (goto-char pos)
966           (forward-char -1)
967           (c-beginning-of-defun-or-decl))
968       (message (concat "Implementation of " scoped-name " not found.")))))
969
970 (defun ccide-implementation-args (state)
971   (string-replace "[ \t\n\r]+" ""
972                   (loop for (start . end) in (aref state 3)
973                         for sep = "" then ","
974                         concat sep
975                         concat (buffer-substring-no-properties 
976                                 start (save-excursion
977                                         (goto-char start)
978                                         (if (search-forward "=" end 'move) (forward-char -1))
979                                         (point))))
980                   
981                   t))
982
983 (defun ccide-implementation-template-args (state)
984   (and (aref state 0)
985        (string-replace "[ \t\n\r]+" ""
986                        (loop for (start . end) in   (save-excursion
987                                                       (goto-char (caar (last (aref state 0))))
988                                                       (c-parse-template-declaration))
989                              for sep = "" then ","
990                              concat sep
991                              concat (buffer-substring-no-properties 
992                                      start (save-excursion
993                                              (goto-char start)
994                                              (if (search-forward "=" end 'move) (forward-char -1))
995                                              (point))))
996                        t)))
997
998 (defun ccide-find-implementation-1 (name scoped-name args targs with-body skip-def)
999   ;; Within the current buffer, search for all implementations of the
1000   ;; given function. The rv is a list of conses. The car holds the
1001   ;; buffer position of the implementation, the cdr is t if the name,
1002   ;; scoped-name and args are matched, otherwise the args did not match.
1003   (save-excursion
1004     (goto-char (point-min))
1005     (let ((re (concat (if (eq (char-syntax (aref name 0)) ?w) "\\<" "")
1006                       (regexp-quote name)
1007                       (if (eq (char-syntax (aref name (1- (length name)))) ?w) "\\>" "")))
1008           fallback rv check-state)
1009       (while (and (not rv) (re-search-forward re nil t))
1010         (if (and (c-at-toplevel-p) 
1011                  (not (c-in-literal))
1012                  (setq check-state (condition-case nil (c-get-defun-state) (error nil)))
1013                  (not (= (car (aref check-state 2)) skip-def)))
1014             (if (string= scoped-name (c-defun-full-name check-state))
1015                 (if (and (if with-body (aref check-state 6) (not (aref check-state 6)))
1016                          (string= args (ccide-implementation-args check-state))
1017                          (string= targs (ccide-implementation-template-args check-state)))
1018                     (setq rv (cons (point) t))
1019                   (if (not fallback) 
1020                       (setq fallback (cons (point) nil)))))))
1021       (or rv fallback))))
1022
1023 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1024 ;; variable/type level
1025   
1026 (defun ccide-variable-comment ()
1027   "Add a comment to current variable declaration."
1028   (interactive)
1029   (push-mark)
1030   (beginning-of-line)
1031   (open-line 1)
1032   (insert "/// ")
1033   (indent-according-to-mode))
1034
1035 (defun ccide-grab-access-fn ()
1036   (interactive)
1037   (save-excursion
1038     (beginning-of-line)
1039     (if (looking-at (concat c++-simple-type-regexp "[ \t\n\r][a-zA-Z0-9_]+[ \t\n\r]*;"))
1040         (let ((vardef (match-string 0))
1041               (in (make-string c-basic-offset ? ))
1042               type varname ws doc)
1043           (forward-line -1)
1044           (back-to-indentation)
1045           (if (looking-at "///[ \t\n\r]*")
1046               (setq doc (buffer-substring (match-end 0)
1047                                           (progn (end-of-line) (point)))))
1048           (string-match "^[ \t\n\r]*\\(.*\\)[ \t\n\r]\\([a-zA-Z0-9_]+\\)[ \t\n\r]*;$"
1049                         vardef)
1050           (setq varname (match-string 2 vardef)
1051                 type (match-string 1 vardef)
1052                 ws (substring vardef 0 (match-beginning 1)))
1053           (if (string-match "^[ \t\n\r]*" type)
1054               (setq type (substring type (match-end 0))))
1055           (kill-new (concat (if doc
1056                                 (concat ws "/** Setze " doc ".\n\n"
1057                                         ws "    @param _" varname " neu: " doc "\n"
1058                                         ws "    @return alt: " doc "\n"
1059                                         ws " */\n")
1060                               "")
1061                             ws type " q_" varname "(" type " _" varname ")\n"
1062                             ws in "{\n"
1063                             ws in in type " old" varname " = " varname ";\n"
1064                             ws in in varname " = _" varname ";\n"
1065                             ws in in "return(old" varname ");\n"
1066                             ws in "}\n\n"
1067                             (if doc
1068                                 (concat ws "/** Hole " doc ".\n\n"
1069                                         ws "    @return " doc "\n"
1070                                         ws "*/\n")
1071                               "")
1072                             ws type " q_" varname "(void) const\n"
1073                             ws in "{ return(" varname "); }\n"))
1074           
1075           (message varname))
1076       (message "No variable found"))))
1077
1078 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1079 ;; doxy comment support functions
1080
1081 (defun ccide-special-indent-function ()
1082   "Function to indent doxy comments correctly"
1083   (let ((indent (ccide-in-doxy-comment)))
1084     (if indent
1085         (let ((lim (save-excursion
1086                      (back-to-indentation)
1087                      (c-literal-limits)))
1088               (pos (- (point-max) (point))))
1089           (save-excursion
1090             (back-to-indentation)
1091             (if (looking-at "*/")
1092                 (incf indent -3)
1093               (let ((para (or (save-excursion (re-search-backward "^\\s-*$" (car lim) t))
1094                               (car lim))))
1095                 (if (and (not (looking-at ccide-doxy-tag-re))
1096                          (re-search-backward (concat "^\\s-*"
1097                                                      ccide-doxy-tag-re)
1098                                              para t))
1099                     (incf indent 4)))))
1100           (delete-region (progn (beginning-of-line) (point))
1101                          (progn (back-to-indentation) (point)))
1102           (indent-to indent)
1103           (if (> (- (point-max) pos) (point))
1104               (goto-char (- (point-max) pos)))))))
1105   
1106 (defun ccide-fill-function ()
1107   "auto-fill function for doxy comments"
1108   (if (do-auto-fill)
1109       (if (not fill-prefix)
1110           (indent-according-to-mode))))
1111
1112 (defun ccide-hide-all-doxy-comments ()
1113   "Hide all doxy comments"
1114   (interactive)
1115   (save-excursion
1116     (goto-char (point-min))
1117     (while (re-search-forward "^\\s-*/\\*\\*" nil t)
1118       (beginning-of-line)
1119       (forward-line -1)
1120       (if (not (looking-at "\\s-*$"))
1121           (forward-line 1))
1122       (forward-char -1)
1123       (let ((start (point)))
1124         (if (re-search-forward "\\*/" nil t)
1125             (progn
1126               (if (looking-at "\\s-*\n")
1127                   (forward-line 1))
1128               (forward-char -1)
1129               (let ((overlay (make-overlay start (point))))
1130                 (overlay-put overlay 'intangible 'hs)
1131                 (overlay-put overlay 'invisible 'hs)))))))
1132   (message "Done."))
1133
1134 (defun ccide-show-all-comments ()
1135   "Show all comments"
1136   (interactive)
1137   (save-excursion
1138     (goto-char (point-min))
1139     (while (not (eobp))
1140       (goto-char (next-overlay-change (point)))
1141       (loop for overlay in (overlays-at (point))
1142             if (eq (overlay-get overlay 'invisible) 'hs)
1143             do (delete-overlay overlay))))
1144   (message "Done."))
1145
1146
1147
1148 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1149 ;; CORBA support (omniORB2)
1150
1151 (defun ccide-get-corba-headers ()
1152   (let (files)
1153     (save-excursion
1154       (goto-char (point-min))
1155       (while (re-search-forward "#include\\s-*[\"<]\\([^\">]*\\)\\.hh[\">]" nil t)
1156         (setq files (cons (ccide-match-string 1) files)))
1157       (nreverse files))))
1158
1159 (defun ccide-corba-maybe-build-hh (file)
1160   (let ((skel (ccide-file-name ".hh" file ccide-corba-skel-dir))
1161         (idl (ccide-file-name ".idl" file ccide-corba-idl-dir)))
1162     (if (and (file-readable-p idl)
1163              (or (not (file-readable-p skel))
1164                  (file-newer-than-file-p idl skel)))
1165         (let ((buffer (find-buffer-visiting (ccide-file-name ".hh" file))))
1166           (if buffer
1167               (kill-buffer buffer))
1168           (message "Please wait ... building %s" (ccide-file-name ".hh" file))
1169           (if (ccide-shell-command (concat "cd " 
1170                                            (real-path-name ccide-corba-skel-dir) 
1171                                            " && " 
1172                                            ccide-corba-idl-command 
1173                                            (if (> (length ccide-corba-idl-dir) 0)
1174                                                (concat " -I" ccide-corba-idl-dir))
1175                                            " " 
1176                                            idl))
1177               ()
1178             (display-buffer (get-buffer-create "*ccide shell command*"))
1179             (error "Generation of %s failed" (ccide-file-name ".hh")))))
1180     (if (not (file-readable-p skel))
1181         (error "No file %s or %s" 
1182                (ccide-file-name ".hh" file) (ccide-file-name ".idl" file)))))
1183
1184 (defun ccide-corba-list-skeletons-1 (hh-file)
1185   (ccide-corba-maybe-build-hh hh-file)
1186   (let ((hh-buf (find-file-noselect (ccide-file-name ".hh" hh-file)))
1187         skels)
1188     (save-excursion
1189       (set-buffer hh-buf)
1190       (save-excursion
1191         (goto-char (point-min))
1192         (while (re-search-forward "^\\s-*class\\s-+_sk_\\([a-zA-Z0-9_]+\\)\\s-+:"
1193                                   nil t)
1194           (setq skels (cons (ccide-match-string 1) skels)))))
1195     (mapcar (function (lambda (x) (cons x hh-file)))
1196             (sort skels 'string-lessp))))
1197
1198 (defun ccide-corba-list-skeletons ()
1199   (let ((files (ccide-get-corba-headers)))
1200     (loop for file in files
1201           append (ccide-corba-list-skeletons-1 file))))
1202
1203 (defun ccide-gen-corba-impl (class)
1204   (interactive (list (completing-read "Class name of skeleton: "
1205                                       (ccide-corba-list-skeletons)
1206                                       nil t)))
1207   (let* ((skels (ccide-corba-list-skeletons))
1208          (hh-file (ccide-file-name ".hh" (cdr (assoc class skels))
1209                                    ccide-corba-skel-dir))
1210          (hh-buf (find-file-noselect (ccide-file-name ".hh" hh-file
1211                                                       ccide-corba-skel-dir))))
1212     (ccide-gen-class (concat class "_i"))
1213     (insert (make-string c-basic-offset ? ) ": public virtual _sk_" class "\n")
1214     (save-excursion
1215       (search-forward "protected:" nil t)
1216       (forward-line -1)
1217       (ccide-gen-corba-impl-methods)
1218       (insert "\n"))))
1219
1220 (defun ccide-get-corba-defns (hh-file class)
1221   (let ((hh-buf (find-file-noselect hh-file))
1222         defns)
1223     (save-excursion
1224       (set-buffer hh-buf)
1225       (save-excursion
1226         (goto-char (point-min))
1227         (if (not (re-search-forward (concat "^\\s-*class\\s-+_sk_" class "\\s-+:")
1228                                     nil t))
1229             (error "CORBA skeleton class not found.")
1230           (search-forward "{")
1231           (forward-char -1)
1232           (let ((end (save-excursion (forward-sexp) (point))))
1233             (while (and (< (point) end)
1234                         (< (forward-line 1) 1))
1235               (if (looking-at "\\s-+virtual\\s-+\\(.*)\\)\\s-*=\\s-*0;\\s-*$")
1236                   (setq defns (cons (match-string 1) defns))))))))
1237     (nreverse defns)))
1238
1239 (defun ccide-gen-corba-impl-methods ()
1240   (interactive)
1241   (let* ((class (c-get-class-at-point))
1242          (point (point)))
1243     (if (not class)
1244         (error "No class at point."))
1245     (save-excursion
1246       (goto-char (aref (car class) 1))
1247       (if (not (re-search-forward ":\\s-*public\\s-*virtual\\s-*_sk_\\([^ \t\n\r{},:]*\\)"
1248                                   nil t))
1249           (error "No CORBA impl at point."))
1250       (let* ((name (ccide-match-string 1))
1251              (skels (ccide-corba-list-skeletons))
1252              (hh-file (ccide-file-name ".hh" (cdr (assoc name skels))
1253                                        ccide-corba-skel-dir))
1254              (defns (ccide-get-corba-defns hh-file name))
1255              end)
1256         (goto-char (aref (car class) 2))
1257         (save-excursion
1258           (c-forward-sexp)
1259           (setq end (point)))
1260         (if (re-search-forward "^\\s-*// CORBA$" end t)
1261             (let ((start (match-beginning 0)))
1262               (if (re-search-forward "^\\s-*// END-CORBA$" end t)
1263                   (let ((eend (match-end 0)))
1264                     (goto-char start)
1265                     (forward-line 1)
1266                     (if (re-search-forward "/\\*\\|//" (match-beginning 0) t)
1267                         (if (y-or-n-p "Remove CORBA Funktion comments? (y/n)")
1268                             (delete-region start (1+ eend))
1269                           (goto-char eend)
1270                           (beginning-of-line)
1271                           (delete-region (point) (progn 
1272                                                    (end-of-line)
1273                                                    (1+ (point))))
1274                           (save-excursion
1275                             (goto-char start)
1276                             (delete-region (point) (progn 
1277                                                      (end-of-line)
1278                                                      (1+ (point)))))
1279                           (insert "\n"))
1280                       (delete-region start (1+ eend))))))
1281           (goto-char point))
1282         (indent-according-to-mode)
1283         (insert "// CORBA\n")
1284         (loop for defn in defns
1285               do (progn
1286                    (save-excursion (insert defn ";"))
1287                    (indent-according-to-mode)
1288                    (let ((start (point)) end)
1289                      (end-of-line)
1290                      (setq end (point))
1291                      (goto-char start)
1292                      (while (re-search-forward "\\s-+" end t)
1293                        (replace-match " ")
1294                        (setq end (- end (- (match-end 0) (match-beginning 0) 1))))
1295                      (end-of-line)
1296                      (loop with done = nil
1297                            while (> (current-column) c-max-def-column)
1298                            do (while (and (> (current-column) c-max-def-column)
1299                                           (search-backward "," start t)))
1300                            do (if (looking-at ",")
1301                                   (progn
1302                                     (forward-char 1)
1303                                     (insert "\n")
1304                                     (open-line 1)
1305                                     (indent-according-to-mode)
1306                                     (delete-char 2)
1307                                     (setq start (point))
1308                                     (end-of-line))
1309                                 (setq done t))
1310                            while (not done)))
1311                    (insert "\n")))
1312         (indent-according-to-mode)
1313         (insert "// END-CORBA\n")))))
1314
1315 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1316 ;; template support
1317
1318 (defun ccide-scan-mantemps ()
1319   "Scan *compilation* buffer for errors and generate manual template
1320 instatiations at point."
1321   (interactive)
1322   (save-excursion
1323     (set-buffer "*compilation*")
1324     (goto-char (point-min)))
1325   (save-excursion
1326     (set-buffer (get-buffer-create "*mantemps*"))
1327     (erase-buffer)
1328     (loop for temp = (ccide-get-mantemp)
1329           while temp
1330           do (insert temp "\n"))
1331     (mantemp-make-mantemps-buffer)
1332     (goto-char (point-min))
1333     (while (progn
1334              (ccide-fix-mantemp)
1335              (< (forward-line 1) 1))))
1336   (insert-buffer-substring "*mantemps*"))
1337
1338 (defun ccide-get-mantemp ()
1339   (save-excursion
1340     (set-buffer "*compilation*")
1341     (if (search-forward "undefined reference to `" nil t)
1342         (let ((start (point)))
1343           (end-of-line)
1344           (search-backward "'" nil t)
1345           (buffer-substring start (point))))))
1346
1347 (defun ccide-fix-mantemp ()
1348   (let ((end (save-excursion
1349                (end-of-line) (point))))
1350     (if (and (save-excursion (search-forward "(" end t))
1351              (search-forward " class" end t))
1352         (progn
1353           (forward-char -6)
1354           (delete-char 6)))))
1355       
1356 (provide 'cc-ide)
1357
1358 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1359 ;; other stuff
1360
1361 (defun ccide-open-compilation-frame ()
1362   (interactive)
1363   (let ((c-frame (selected-frame))
1364         (compilation-frame (make-frame '((minibuffer . nil) 
1365                                          (unsplittable . t) 
1366                                          (menu-bar-lines . 0) 
1367                                          (top . -87) 
1368                                          (left . 36) 
1369                                          (width . 169) 
1370                                          (height . 9)))))
1371     (select-frame compilation-frame)
1372     (switch-to-buffer "*compilation*")
1373     (set-window-dedicated-p (selected-window) t)))
1374
1375 (defun ccide-compile (command)
1376   (delete-other-windows)
1377   (split-window-horizontally)
1378   (compile command)
1379   (save-excursion
1380     (set-buffer "*compilation*")
1381     (let ((point (point-max)))
1382       (goto-char point)
1383       (loop for window in (get-buffer-window-list "*compilation*" nil t)
1384             do (set-window-point window point)))))
1385
1386 (defun ccide-compile-compile ()
1387   (interactive)
1388   (ccide-compile (concat "make -k " ccide-compile-opts)))
1389
1390 (defun ccide-compile-clean ()
1391   (interactive)
1392   (ccide-compile (concat "make -k " ccide-compile-opts " clean")))
1393
1394 (defun ccide-compile-cleandepends ()
1395   (interactive)
1396   (ccide-compile (concat "make -k " ccide-compile-opts " cleandepends")))
1397
1398 (defun ccide-compile-kill ()
1399   (interactive)
1400   (set-buffer "*compilation*")
1401   (kill-compilation))
1402
1403 (defun ccide-hide-compilation ()
1404   (interactive)
1405   (let ((active (selected-window)))
1406     (unwind-protect
1407         (loop for window in (get-buffer-window-list "*compilation*")
1408               do (progn (select-window window)
1409                         (switch-to-buffer (other-buffer "*compilation*"))))
1410       (select-window active))))
1411
1412 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1413 ;; keymap and installation
1414
1415 (defun ccide-bind-keys (prefix map)
1416   (loop for binding in ccide-bindings
1417         do (apply 'vcmd-define-key
1418                   map
1419                   (concat prefix (car binding))
1420                   (cadr binding)
1421                   "IDE"
1422                   (cddr binding))))
1423
1424 (defun ccide-install-it ()
1425   (save-excursion
1426     (hs-minor-mode 1)
1427     (hs-show-all))
1428   (local-unset-key "\C-c;")
1429   (local-unset-key [menu-bar IDE])
1430   (ccide-bind-keys "\C-c;" (current-local-map))
1431   (local-set-key "\C-cC" 'ccide-hide-all-doxy-comments)
1432   (local-set-key "\C-cS" 'ccide-show-all-comments)
1433   (set (make-local-variable 'auto-fill-function) 'ccide-fill-function)
1434   (set (make-local-variable 'paragraph-start) (concat "[ \t\f]*$\\|[ \t\f]*" ccide-doxy-tag-re))
1435   (set (make-local-variable 'paragraph-separate) "[ \t\f]*$")
1436   (auto-fill-mode -1)
1437   (ccide-project-load-config)
1438   (ccide-auto-decorate-new-files))
1439
1440 (defun ccide-project-load-config ()
1441   (let ((conf (ccide-project-search-upwards "project.el" (file-name-directory (buffer-file-name)))))
1442     (when conf
1443       (set (make-local-variable 'ccide-project-root) (file-name-directory conf))
1444       (load-file conf))))
1445
1446 (defun ccide-project-search-upwards (file &optional dir)
1447   "Search for FILE in all directories starting at DIR and going up the directory hierarchy.
1448 DIR defaults to ccide-project-root"
1449   (let (conf last-dir)
1450     (setq dir (expand-file-name "x" (or dir ccide-project-root)))
1451     (while (and (not (string= (setq last-dir dir 
1452                                     dir (directory-file-name (file-name-directory dir))) last-dir))
1453                 (setq conf (expand-file-name file dir))
1454                 (not (file-readable-p conf))))
1455     (and (file-readable-p conf) conf)))
1456
1457 (add-hook 'c-mode-hook 'ccide-install-it)
1458 (add-hook 'c++-mode-hook 'ccide-install-it)
1459 (add-hook 'c-special-indent-hook 'ccide-special-indent-function)
1460
1461 (loop for extension in ccide-special-extensions
1462       for re = (concat (regexp-quote extension) "$")
1463       if (not (assoc re auto-mode-alist))
1464         do (setq auto-mode-alist (append auto-mode-alist
1465                                          (list (cons re 'c++-mode)))))
1466
1467 (defadvice c-indent-line (after c-indent-less compile disable) ;activate
1468   ;; new indent function for c-mode: do standard indentation first. If line
1469   ;; is to long using standard indentation, just indent by c-basic-indentation.
1470   (let ((cc (save-excursion (end-of-line) (current-column)))
1471         indent)
1472     (if (> cc  85)
1473         (let ((pos (- (point-max) (point))))
1474           (beginning-of-line)
1475           (let ((point (point))
1476                 (line (1+ (count-lines 1 (point))))
1477                 indent)
1478             (c-beginning-of-statement-2)
1479             (if (and (not (c-crosses-statement-barrier-p (point) point))
1480                      (not (eq (+ (count-lines 1 (point))
1481                                  (if (bolp) 1 0))
1482                               line)))
1483                 (progn
1484                   (setq indent (+ (current-indentation) c-basic-offset))
1485                   (goto-char point)
1486                   (if (< indent (current-indentation))
1487                       (progn
1488                         (setq ad-return-value
1489                               (+ ad-return-value
1490                                  (- (current-indentation) indent)))
1491                         (delete-region (c-point 'bol) (c-point 'boi))
1492                         (indent-to indent))))))
1493           (if (< (point) (c-point 'boi))
1494               (back-to-indentation)
1495             (if (> (- (point-max) pos) (point))
1496                 (goto-char (- (point-max) pos))))))))
1497
1498
1499 \f
1500 ;;; Local Variables:
1501 ;;; elisp-project-autoload-file-name: "cc-autoload.el"
1502 ;;; End: