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