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