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