comment fix
[bpt/emacs.git] / lisp / progmodes / cc-cmds.el
CommitLineData
0ec8351b 1;;; cc-cmds.el --- user level commands for CC Mode
785eecbb 2
b8ded794 3;; Copyright (C) 1985,1987,1992-2000 Free Software Foundation, Inc.
785eecbb 4
b8ded794
GM
5;; Authors: 2000- Martin Stjernholm
6;; 1998-1999 Barry A. Warsaw and Martin Stjernholm
0ec8351b 7;; 1992-1997 Barry A. Warsaw
785eecbb
RS
8;; 1987 Dave Detlefs and Stewart Clamen
9;; 1985 Richard M. Stallman
0ec8351b 10;; Maintainer: bug-cc-mode@gnu.org
785eecbb 11;; Created: 22-Apr-1997 (split from cc-mode.el)
a7c7b186 12;; Version: See cc-mode.el
785eecbb
RS
13;; Keywords: c languages oop
14
15;; This file is part of GNU Emacs.
16
17;; GNU Emacs is free software; you can redistribute it and/or modify
18;; it under the terms of the GNU General Public License as published by
19;; the Free Software Foundation; either version 2, or (at your option)
20;; any later version.
21
22;; GNU Emacs is distributed in the hope that it will be useful,
23;; but WITHOUT ANY WARRANTY; without even the implied warranty of
24;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25;; GNU General Public License for more details.
26
27;; You should have received a copy of the GNU General Public License
28;; along with GNU Emacs; see the file COPYING. If not, write to the
29;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
30;; Boston, MA 02111-1307, USA.
31
0ec8351b 32(eval-when-compile
51f606de
GM
33 (let ((load-path
34 (if (and (boundp 'byte-compile-current-file)
35 (stringp byte-compile-current-file))
36 (cons (file-name-directory byte-compile-current-file)
37 load-path)
38 load-path)))
39 (load "cc-defs" nil t)))
40(require 'cc-engine)
0ec8351b 41
51f606de 42\f
785eecbb
RS
43(defun c-calculate-state (arg prevstate)
44 ;; Calculate the new state of PREVSTATE, t or nil, based on arg. If
45 ;; arg is nil or zero, toggle the state. If arg is negative, turn
46 ;; the state off, and if arg is positive, turn the state on
47 (if (or (not arg)
48 (zerop (setq arg (prefix-numeric-value arg))))
49 (not prevstate)
50 (> arg 0)))
51
52;; Auto-newline and hungry-delete
53(defun c-toggle-auto-state (arg)
54 "Toggle auto-newline feature.
55Optional numeric ARG, if supplied turns on auto-newline when positive,
56turns it off when negative, and just toggles it when zero.
57
58When the auto-newline feature is enabled (as evidenced by the `/a' or
59`/ah' on the modeline after the mode name) newlines are automatically
60inserted after special characters such as brace, comma, semi-colon,
61and colon."
62 (interactive "P")
63 (setq c-auto-newline (c-calculate-state arg c-auto-newline))
64 (c-update-modeline)
65 (c-keep-region-active))
66
67(defun c-toggle-hungry-state (arg)
68 "Toggle hungry-delete-key feature.
69Optional numeric ARG, if supplied turns on hungry-delete when positive,
70turns it off when negative, and just toggles it when zero.
71
72When the hungry-delete-key feature is enabled (as evidenced by the
73`/h' or `/ah' on the modeline after the mode name) the delete key
74gobbles all preceding whitespace in one fell swoop."
75 (interactive "P")
76 (setq c-hungry-delete-key (c-calculate-state arg c-hungry-delete-key))
77 (c-update-modeline)
78 (c-keep-region-active))
79
80(defun c-toggle-auto-hungry-state (arg)
81 "Toggle auto-newline and hungry-delete-key features.
82Optional numeric ARG, if supplied turns on auto-newline and
83hungry-delete when positive, turns them off when negative, and just
84toggles them when zero.
85
86See `c-toggle-auto-state' and `c-toggle-hungry-state' for details."
87 (interactive "P")
88 (setq c-auto-newline (c-calculate-state arg c-auto-newline))
89 (setq c-hungry-delete-key (c-calculate-state arg c-hungry-delete-key))
90 (c-update-modeline)
91 (c-keep-region-active))
92
93\f
94;; Electric keys
95
96;; Note: In XEmacs 20.3 the Delete and BackSpace keysyms have been
97;; separated and "\177" is no longer an alias for both keys. Also,
98;; the variable delete-key-deletes-forward controls in which direction
99;; the Delete keysym deletes characters. The functions
100;; c-electric-delete and c-electric-backspace attempt to deal with
101;; this new functionality. For Emacs 19 and XEmacs 19 backwards
102;; compatibility, the old behavior has moved to c-electric-backspace
103;; and c-backspace-function.
104
105(defun c-electric-backspace (arg)
106 "Deletes preceding character or whitespace.
107If `c-hungry-delete-key' is non-nil, as evidenced by the \"/h\" or
108\"/ah\" string on the mode line, then all preceding whitespace is
109consumed. If however an ARG is supplied, or `c-hungry-delete-key' is
110nil, or point is inside a literal then the function in the variable
111`c-backspace-function' is called.
112
113See also \\[c-electric-delete]."
28c236de 114 (interactive "*P")
785eecbb
RS
115 (if (or (not c-hungry-delete-key)
116 arg
117 (c-in-literal))
118 (funcall c-backspace-function (prefix-numeric-value arg))
119 (let ((here (point)))
120 (skip-chars-backward " \t\n")
121 (if (/= (point) here)
122 (delete-region (point) here)
123 (funcall c-backspace-function 1)
124 ))))
125
126(defun c-electric-delete (arg)
127 "Deletes preceding or following character or whitespace.
128
129The behavior of this function depends on the variable
130`delete-key-deletes-forward'. If this variable is nil (or does not
131exist, as in older Emacsen), then this function behaves identical to
132\\[c-electric-backspace].
133
28c236de
RS
134If `delete-key-deletes-forward' is non-nil and is supported in your
135Emacs, then deletion occurs in the forward direction. So if
136`c-hungry-delete-key' is non-nil, as evidenced by the \"/h\" or
137\"/ah\" string on the mode line, then all following whitespace is
138consumed. If however an ARG is supplied, or `c-hungry-delete-key' is
139nil, or point is inside a literal then the function in the variable
140`c-delete-function' is called."
141 (interactive "*P")
0ec8351b
BW
142 (if (or (and (fboundp 'delete-forward-p) ;XEmacs 21
143 (delete-forward-p))
144 (and (boundp 'delete-key-deletes-forward) ;XEmacs 20
145 delete-key-deletes-forward))
785eecbb
RS
146 (if (or (not c-hungry-delete-key)
147 arg
148 (c-in-literal))
149 (funcall c-delete-function (prefix-numeric-value arg))
150 (let ((here (point)))
151 (skip-chars-forward " \t\n")
152 (if (/= (point) here)
153 (delete-region (point) here)
154 (funcall c-delete-function 1))))
155 ;; act just like c-electric-backspace
156 (c-electric-backspace arg)))
157
158(defun c-electric-pound (arg)
159 "Electric pound (`#') insertion.
160Inserts a `#' character specially depending on the variable
161`c-electric-pound-behavior'. If a numeric ARG is supplied, or if
162point is inside a literal, nothing special happens."
28c236de 163 (interactive "*P")
0ec8351b
BW
164 (if (or arg
165 (not (memq 'alignleft c-electric-pound-behavior))
166 (save-excursion (skip-chars-backward " \t") (not (bolp)))
167 (c-in-literal))
785eecbb
RS
168 ;; do nothing special
169 (self-insert-command (prefix-numeric-value arg))
170 ;; place the pound character at the left edge
171 (let ((pos (- (point-max) (point)))
172 (bolp (bolp)))
173 (beginning-of-line)
174 (delete-horizontal-space)
175 (insert-char last-command-char 1)
176 (and (not bolp)
177 (goto-char (- (point-max) pos)))
178 )))
179
180(defun c-electric-brace (arg)
181 "Insert a brace.
182
183If the auto-newline feature is turned on, as evidenced by the \"/a\"
184or \"/ah\" string on the mode line, newlines are inserted before and
185after braces based on the value of `c-hanging-braces-alist'.
186
187Also, the line is re-indented unless a numeric ARG is supplied, there
b8ded794
GM
188are non-whitespace characters present on the line after the brace, the
189brace is inserted inside a literal, or `c-syntactic-indentation' is
190nil.
0ec8351b
BW
191
192This function does various newline cleanups based on the value of
193`c-cleanup-list'."
28c236de 194 (interactive "*P")
785eecbb
RS
195 (let* ((c-state-cache (c-parse-state))
196 (safepos (c-safe-position (point) c-state-cache))
197 (literal (c-in-literal safepos)))
198 ;; if we're in a literal, or we're not at the end of the line, or
199 ;; a numeric arg is provided, or auto-newlining is turned off,
200 ;; then just insert the character.
0ec8351b
BW
201 (if (or literal
202 arg
785eecbb
RS
203 (not (looking-at "[ \t]*$")))
204 (self-insert-command (prefix-numeric-value arg))
28c236de
RS
205 (let* ((syms
206 ;; This is the list of brace syntactic symbols that can
207 ;; hang. If any new ones are added to c-offsets-alist,
208 ;; they should be added here as well.
209 '(class-open class-close defun-open defun-close
210 inline-open inline-close
211 brace-list-open brace-list-close
0ec8351b 212 brace-list-intro brace-entry-open
28c236de
RS
213 block-open block-close
214 substatement-open statement-case-open
215 extern-lang-open extern-lang-close
216 namespace-open namespace-close
0ec8351b 217 inexpr-class-open inexpr-class-close
28c236de 218 ))
785eecbb
RS
219 ;; we want to inhibit blinking the paren since this will
220 ;; be most disruptive. we'll blink it ourselves later on
221 (old-blink-paren blink-paren-function)
222 blink-paren-function
223 (insertion-point (point))
224 delete-temp-newline
811fd07a
RS
225 (preserve-p (and (not (bobp))
226 (eq ?\ (char-syntax (char-before)))))
785eecbb
RS
227 ;; shut this up too
228 (c-echo-syntactic-information-p nil)
229 (syntax (progn
230 ;; only insert a newline if there is
231 ;; non-whitespace behind us
232 (if (save-excursion
233 (skip-chars-backward " \t")
234 (not (bolp)))
235 (progn (newline)
236 (setq delete-temp-newline t)))
b8ded794
GM
237 (if (eq last-command-char ?{)
238 (setq c-state-cache (cons (point) c-state-cache)))
785eecbb
RS
239 (self-insert-command (prefix-numeric-value arg))
240 ;; state cache doesn't change
241 (c-guess-basic-syntax)))
242 (newlines (and
243 c-auto-newline
0ec8351b
BW
244 (or (c-lookup-lists
245 syms
246 ;; Substitute inexpr-class and class-open
247 ;; or class-close with inexpr-class-open
248 ;; or inexpr-class-close.
249 (if (assq 'inexpr-class syntax)
250 (cond ((assq 'class-open syntax)
251 '((inexpr-class-open)))
252 ((assq 'class-close syntax)
253 '((inexpr-class-close)))
254 (t syntax))
255 syntax)
256 c-hanging-braces-alist)
785eecbb 257 '(ignore before after)))))
0ec8351b
BW
258 ;; Do not try to insert newlines around a special (Pike-style)
259 ;; brace list.
260 (if (and c-special-brace-lists
261 (c-intersect-lists '(brace-list-open brace-list-close
262 brace-list-intro brace-entry-open)
263 syntax)
264 (save-excursion
265 (c-safe (if (= (char-before) ?{)
266 (forward-char -1)
267 (c-forward-sexp -1))
268 (c-looking-at-special-brace-list))))
269 (setq newlines nil))
785eecbb
RS
270 ;; If syntax is a function symbol, then call it using the
271 ;; defined semantics.
272 (if (and (not (consp (cdr newlines)))
273 (functionp (cdr newlines)))
274 (let ((c-syntactic-context syntax))
275 (setq newlines
276 (funcall (cdr newlines) (car newlines) insertion-point))))
277 ;; does a newline go before the open brace?
278 (if (memq 'before newlines)
279 ;; we leave the newline we've put in there before,
280 ;; but we need to re-indent the line above
281 (let ((pos (- (point-max) (point)))
0ec8351b 282 (here (point)))
785eecbb 283 (forward-line -1)
0ec8351b
BW
284 (let ((c-state-cache (c-whack-state (point) c-state-cache)))
285 ;; we may need to update the cache. this should
286 ;; still be faster than recalculating the state
287 ;; in many cases
288 (save-excursion
289 (save-restriction
290 (narrow-to-region here (point))
291 (if (and (c-safe (progn (backward-up-list -1) t))
292 (memq (char-before) '(?\) ?}))
293 (progn (widen)
294 (c-safe (progn (c-forward-sexp -1)
295 t))))
296 (setq c-state-cache
297 (c-hack-state (point) 'open c-state-cache)))))
b8ded794
GM
298 (if c-syntactic-indentation
299 (c-indent-line)))
0ec8351b
BW
300 (setq c-state-cache (c-adjust-state (c-point 'bol) here
301 (- (point) (c-point 'bol))
302 c-state-cache))
785eecbb
RS
303 (goto-char (- (point-max) pos))
304 ;; if the buffer has changed due to the indentation, we
305 ;; need to recalculate syntax for the current line, but
306 ;; we won't need to update the state cache.
307 (if (/= (point) here)
308 (setq syntax (c-guess-basic-syntax))))
309 ;; must remove the newline we just stuck in (if we really did it)
310 (and delete-temp-newline
311 (save-excursion
312 ;; if there is whitespace before point, then preserve
313 ;; at least one space.
314 (delete-indentation)
315 (just-one-space)
b8ded794 316 (setq c-state-cache (c-whack-state (point) c-state-cache))
785eecbb
RS
317 (if (not preserve-p)
318 (delete-char -1))))
319 ;; since we're hanging the brace, we need to recalculate
320 ;; syntax. Update the state to accurately reflect the
321 ;; beginning of the line. We punt if we cross any open or
322 ;; closed parens because its just too hard to modify the
323 ;; known state. This limitation will be fixed in v5.
324 (save-excursion
325 (let ((bol (c-point 'bol)))
326 (if (zerop (car (parse-partial-sexp bol (1- (point)))))
b8ded794 327 (setq syntax (c-guess-basic-syntax))
785eecbb
RS
328 ;; gotta punt. this requires some horrible kludgery
329 (beginning-of-line)
330 (makunbound 'c-state-cache)
331 (setq c-state-cache (c-parse-state)
332 syntax nil))))
333 )
334 ;; now adjust the line's indentation. don't update the state
335 ;; cache since c-guess-basic-syntax isn't called when the
336 ;; syntax is passed to c-indent-line
0ec8351b
BW
337 (let* ((here (point)))
338 (c-indent-line syntax)
785eecbb 339 (setq c-state-cache (c-adjust-state (c-point 'bol) here
0ec8351b
BW
340 (- (c-point 'boi) (c-point 'bol))
341 c-state-cache)))
785eecbb
RS
342 ;; Do all appropriate clean ups
343 (let ((here (point))
344 (pos (- (point-max) (point)))
51f606de 345 mbeg mend tmp)
785eecbb
RS
346 ;; clean up empty defun braces
347 (if (and c-auto-newline
348 (memq 'empty-defun-braces c-cleanup-list)
349 (eq last-command-char ?\})
350 (c-intersect-lists '(defun-close class-close inline-close)
351 syntax)
352 (progn
353 (forward-char -1)
354 (skip-chars-backward " \t\n")
355 (eq (char-before) ?\{))
356 ;; make sure matching open brace isn't in a comment
357 (not (c-in-literal)))
358 (delete-region (point) (1- here)))
51f606de
GM
359 ;; clean up brace-else-brace and brace-elseif-brace
360 (when (and c-auto-newline
361 (eq last-command-char ?\{)
362 (not (c-in-literal)))
363 (cond
364 ((and (memq 'brace-else-brace c-cleanup-list)
785eecbb
RS
365 (re-search-backward "}[ \t\n]*else[ \t\n]*{" nil t)
366 (progn
367 (setq mbeg (match-beginning 0)
368 mend (match-end 0))
51f606de
GM
369 (eq (match-end 0) here)))
370 (delete-region mbeg mend)
371 (insert "} else {"))
372 ((and (memq 'brace-elseif-brace c-cleanup-list)
373 (progn
374 (goto-char (1- here))
375 (setq mend (point))
376 (skip-chars-backward " \t\n")
377 (setq mbeg (point))
378 (eq (char-before) ?\)))
379 (= (c-backward-token-1 1 t) 0)
380 (eq (char-after) ?\()
381 (progn
382 (setq tmp (point))
383 (re-search-backward "}[ \t\n]*else[ \t\n]+if[ \t\n]*"
384 nil t))
385 (eq (match-end 0) tmp))
386 (delete-region mbeg mend)
387 (goto-char mbeg)
388 (insert " "))))
785eecbb
RS
389 (goto-char (- (point-max) pos))
390 )
391 ;; does a newline go after the brace?
392 (if (memq 'after newlines)
393 (progn
394 (newline)
395 ;; update on c-state-cache
396 (let* ((bufpos (- (point) 2))
397 (which (if (eq (char-after bufpos) ?{) 'open 'close))
398 (c-state-cache (c-hack-state bufpos which c-state-cache)))
399 (c-indent-line))))
400 ;; blink the paren
401 (and (eq last-command-char ?\})
402 old-blink-paren
403 (save-excursion
404 (c-backward-syntactic-ws safepos)
405 (funcall old-blink-paren)))
406 ))))
0ec8351b 407
785eecbb
RS
408(defun c-electric-slash (arg)
409 "Insert a slash character.
0fc3821e
RS
410
411Indent the line as a comment, if:
412
413 1. The slash is second of a `//' line oriented comment introducing
414 token and we are on a comment-only-line, or
415
416 2. The slash is part of a `*/' token that closes a block oriented
417 comment.
418
b8ded794
GM
419If a numeric ARG is supplied, point is inside a literal, or
420`c-syntactic-indentation' is nil, indentation is inhibited."
28c236de 421 (interactive "*P")
0fc3821e 422 (let* ((ch (char-before))
b8ded794
GM
423 (indentp (and c-syntactic-indentation
424 (not arg)
0fc3821e
RS
425 (eq last-command-char ?/)
426 (or (and (eq ch ?/)
427 (not (c-in-literal)))
428 (and (eq ch ?*)
429 (c-in-literal)))
430 ))
431 ;; shut this up
432 (c-echo-syntactic-information-p nil))
785eecbb
RS
433 (self-insert-command (prefix-numeric-value arg))
434 (if indentp
435 (c-indent-line))))
436
437(defun c-electric-star (arg)
438 "Insert a star character.
439If the star is the second character of a C style comment introducing
440construct, and we are on a comment-only-line, indent line as comment.
b8ded794
GM
441If a numeric ARG is supplied, point is inside a literal, or
442`c-syntactic-indentation' is nil, indentation is inhibited."
28c236de 443 (interactive "*P")
785eecbb
RS
444 (self-insert-command (prefix-numeric-value arg))
445 ;; if we are in a literal, or if arg is given do not re-indent the
446 ;; current line, unless this star introduces a comment-only line.
b8ded794
GM
447 (if (and c-syntactic-indentation
448 (not arg)
785eecbb
RS
449 (memq (c-in-literal) '(c))
450 (eq (char-before) ?*)
451 (save-excursion
452 (forward-char -1)
453 (skip-chars-backward "*")
454 (if (eq (char-before) ?/)
455 (forward-char -1))
456 (skip-chars-backward " \t")
457 (bolp)))
458 ;; shut this up
459 (let (c-echo-syntactic-information-p)
460 (c-indent-line))
461 ))
462
463(defun c-electric-semi&comma (arg)
464 "Insert a comma or semicolon.
465When the auto-newline feature is turned on, as evidenced by the \"/a\"
466or \"/ah\" string on the mode line, a newline might be inserted. See
467the variable `c-hanging-semi&comma-criteria' for how newline insertion
468is determined.
469
470When semicolon is inserted, the line is re-indented unless a numeric
471arg is supplied, point is inside a literal, or there are
b8ded794
GM
472non-whitespace characters on the line following the semicolon, or
473`c-syntactic-indentation' is nil.
0ec8351b
BW
474
475Based on the value of `c-cleanup-list', this function cleans up commas
476following brace lists and semicolons following defuns."
28c236de 477 (interactive "*P")
785eecbb
RS
478 (let* ((lim (c-most-enclosing-brace (c-parse-state)))
479 (literal (c-in-literal lim))
480 (here (point))
481 ;; shut this up
482 (c-echo-syntactic-information-p nil))
483 (if (or literal
484 arg
485 (not (looking-at "[ \t]*$")))
486 (self-insert-command (prefix-numeric-value arg))
487 ;; do some special stuff with the character
488 (self-insert-command (prefix-numeric-value arg))
0ec8351b
BW
489 ;; do all cleanups and newline insertions if c-auto-newline is
490 ;; turned on
491 (if (not c-auto-newline)
b8ded794
GM
492 (if c-syntactic-indentation
493 (c-indent-line))
785eecbb
RS
494 ;; clean ups
495 (let ((pos (- (point-max) (point))))
496 (if (and (or (and
497 (eq last-command-char ?,)
498 (memq 'list-close-comma c-cleanup-list))
499 (and
500 (eq last-command-char ?\;)
501 (memq 'defun-close-semi c-cleanup-list)))
502 (progn
503 (forward-char -1)
504 (skip-chars-backward " \t\n")
505 (eq (char-before) ?}))
506 ;; make sure matching open brace isn't in a comment
507 (not (c-in-literal lim)))
508 (delete-region (point) here))
509 (goto-char (- (point-max) pos)))
510 ;; re-indent line
b8ded794
GM
511 (if c-syntactic-indentation
512 (c-indent-line))
785eecbb
RS
513 ;; check to see if a newline should be added
514 (let ((criteria c-hanging-semi&comma-criteria)
515 answer add-newline-p)
516 (while criteria
517 (setq answer (funcall (car criteria)))
518 ;; only nil value means continue checking
519 (if (not answer)
520 (setq criteria (cdr criteria))
521 (setq criteria nil)
522 ;; only 'stop specifically says do not add a newline
523 (setq add-newline-p (not (eq answer 'stop)))
524 ))
525 (if add-newline-p
526 (progn (newline)
527 (c-indent-line)))
528 )))))
529
530(defun c-electric-colon (arg)
531 "Insert a colon.
532
533If the auto-newline feature is turned on, as evidenced by the \"/a\"
534or \"/ah\" string on the mode line, newlines are inserted before and
535after colons based on the value of `c-hanging-colons-alist'.
536
537Also, the line is re-indented unless a numeric ARG is supplied, there
b8ded794
GM
538are non-whitespace characters present on the line after the colon, the
539colon is inserted inside a literal, or `c-syntactic-indentation' is
540nil.
785eecbb
RS
541
542This function cleans up double colon scope operators based on the
543value of `c-cleanup-list'."
28c236de 544 (interactive "*P")
785eecbb
RS
545 (let* ((bod (c-point 'bod))
546 (literal (c-in-literal bod))
28c236de 547 syntax newlines is-scope-op
785eecbb
RS
548 ;; shut this up
549 (c-echo-syntactic-information-p nil))
550 (if (or literal
551 arg
552 (not (looking-at "[ \t]*$")))
553 (self-insert-command (prefix-numeric-value arg))
554 ;; insert the colon, then do any specified cleanups
555 (self-insert-command (prefix-numeric-value arg))
556 (let ((pos (- (point-max) (point)))
557 (here (point)))
558 (if (and c-auto-newline
559 (memq 'scope-operator c-cleanup-list)
560 (eq (char-before) ?:)
561 (progn
562 (forward-char -1)
563 (skip-chars-backward " \t\n")
564 (eq (char-before) ?:))
565 (not (c-in-literal))
566 (not (eq (char-after (- (point) 2)) ?:)))
28c236de
RS
567 (progn
568 (delete-region (point) (1- here))
569 (setq is-scope-op t)))
785eecbb
RS
570 (goto-char (- (point-max) pos)))
571 ;; lets do some special stuff with the colon character
572 (setq syntax (c-guess-basic-syntax)
573 ;; some language elements can only be determined by
574 ;; checking the following line. Lets first look for ones
575 ;; that can be found when looking on the line with the
576 ;; colon
577 newlines
578 (and c-auto-newline
579 (or (c-lookup-lists '(case-label label access-label)
580 syntax c-hanging-colons-alist)
581 (c-lookup-lists '(member-init-intro inher-intro)
0ec8351b
BW
582 (let ((buffer-undo-list t))
583 (insert "\n")
584 (unwind-protect
585 (c-guess-basic-syntax)
586 (delete-char -1)))
785eecbb 587 c-hanging-colons-alist))))
b8ded794
GM
588 ;; indent the current line if it's done syntactically.
589 (if c-syntactic-indentation
590 (c-indent-line syntax))
785eecbb
RS
591 ;; does a newline go before the colon? Watch out for already
592 ;; non-hung colons. However, we don't unhang them because that
593 ;; would be a cleanup (and anti-social).
594 (if (and (memq 'before newlines)
28c236de 595 (not is-scope-op)
785eecbb
RS
596 (save-excursion
597 (skip-chars-backward ": \t")
598 (not (bolp))))
599 (let ((pos (- (point-max) (point))))
600 (forward-char -1)
601 (newline)
602 (c-indent-line)
603 (goto-char (- (point-max) pos))))
604 ;; does a newline go after the colon?
28c236de
RS
605 (if (and (memq 'after (cdr-safe newlines))
606 (not is-scope-op))
785eecbb
RS
607 (progn
608 (newline)
609 (c-indent-line)))
610 )))
611
612(defun c-electric-lt-gt (arg)
613 "Insert a less-than, or greater-than character.
0ec8351b
BW
614The line will be re-indented if the character inserted is the second
615of a C++ style stream operator and the buffer is in C++ mode.
b8ded794
GM
616Exceptions are when a numeric argument is supplied, point is inside a
617literal, or `c-syntactic-indentation' is nil, in which case the line
618will not be re-indented."
28c236de 619 (interactive "*P")
b8ded794
GM
620 (let ((indentp (and c-syntactic-indentation
621 (not arg)
785eecbb
RS
622 (eq (char-before) last-command-char)
623 (not (c-in-literal))))
624 ;; shut this up
625 (c-echo-syntactic-information-p nil))
626 (self-insert-command (prefix-numeric-value arg))
627 (if indentp
628 (c-indent-line))))
629
0ec8351b
BW
630(defun c-electric-paren (arg)
631 "Insert a parenthesis.
632
633If the auto-newline feature is turned on, as evidenced by the \"/a\"
634or \"/ah\" string on the mode line, some newline cleanups are done if
635appropriate; see the variable `c-cleanup-list'.
636
637Also, the line is re-indented unless a numeric ARG is supplied, there
51f606de 638are non-whitespace characters present on the line after the
b8ded794
GM
639parenthesis, the parenthesis is inserted inside a literal, or
640`c-syntactic-indentation' is nil."
0ec8351b
BW
641 (interactive "*P")
642 (let (;; shut this up
643 (c-echo-syntactic-information-p nil))
644 (if (or arg
645 (not (looking-at "[ \t]*$"))
646 (c-in-literal (c-point 'bod)))
647 (self-insert-command (prefix-numeric-value arg))
648 ;; do some special stuff with the character
649 (let* (;; We want to inhibit blinking the paren since this will
650 ;; be most disruptive. We'll blink it ourselves
651 ;; afterwards.
652 (old-blink-paren blink-paren-function)
653 blink-paren-function)
654 (self-insert-command (prefix-numeric-value arg))
b8ded794
GM
655 (if c-syntactic-indentation
656 (c-indent-line))
0ec8351b
BW
657 (when c-auto-newline
658 ;; Do all appropriate clean ups
659 (let ((here (point))
660 (pos (- (point-max) (point)))
661 mbeg mend)
662 ;; clean up brace-elseif-brace
663 (if (and (memq 'brace-elseif-brace c-cleanup-list)
664 (eq last-command-char ?\()
665 (re-search-backward "}[ \t\n]*else[ \t\n]+if[ \t\n]*("
666 nil t)
667 (save-excursion
668 (setq mbeg (match-beginning 0)
669 mend (match-end 0))
670 (= mend here))
671 (not (c-in-literal)))
672 (progn
673 (delete-region mbeg mend)
674 (insert "} else if (")))
675 ;; clean up brace-catch-brace
676 (if (and (memq 'brace-catch-brace c-cleanup-list)
677 (eq last-command-char ?\()
678 (re-search-backward "}[ \t\n]*catch[ \t\n]*(" nil t)
679 (save-excursion
680 (setq mbeg (match-beginning 0)
681 mend (match-end 0))
682 (= mend here))
683 (not (c-in-literal)))
684 (progn
685 (delete-region mbeg mend)
686 (insert "} catch (")))
687 (goto-char (- (point-max) pos))
688 ))
51f606de
GM
689 (if old-blink-paren
690 (funcall old-blink-paren))))))
0ec8351b 691
785eecbb
RS
692
693\f
694;; better movement routines for ThisStyleOfVariablesCommonInCPlusPlus
695;; originally contributed by Terry_Glanfield.Southern@rxuk.xerox.com
696(defun c-forward-into-nomenclature (&optional arg)
697 "Move forward to end of a nomenclature section or word.
698With arg, to it arg times."
699 (interactive "p")
700 (let ((case-fold-search nil))
701 (if (> arg 0)
702 (re-search-forward "\\W*\\([A-Z]*[a-z0-9]*\\)" (point-max) t arg)
703 (while (and (< arg 0)
704 (re-search-backward
705 "\\(\\(\\W\\|[a-z0-9]\\)[A-Z]+\\|\\W\\w+\\)"
706 (point-min) 0))
707 (forward-char 1)
708 (setq arg (1+ arg)))))
709 (c-keep-region-active))
710
711(defun c-backward-into-nomenclature (&optional arg)
712 "Move backward to beginning of a nomenclature section or word.
713With optional ARG, move that many times. If ARG is negative, move
714forward."
715 (interactive "p")
716 (c-forward-into-nomenclature (- arg))
717 (c-keep-region-active))
718
719(defun c-scope-operator ()
720 "Insert a double colon scope operator at point.
721No indentation or other \"electric\" behavior is performed."
28c236de 722 (interactive "*")
785eecbb
RS
723 (insert "::"))
724
28c236de
RS
725(defun c-beginning-of-defun (&optional arg)
726 "Move backward to the beginning of a defun.
727With argument, do it that many times. Negative arg -N
728means move forward to Nth following beginning of defun.
729Returns t unless search stops due to beginning or end of buffer.
730
731Unlike the built-in `beginning-of-defun' this tries to be smarter
732about finding the char with open-parenthesis syntax that starts the
733defun."
734 (interactive "p")
51f606de 735 (unless arg (setq arg 1))
28c236de
RS
736 (if (< arg 0)
737 (c-end-of-defun (- arg))
738 (while (> arg 0)
739 (let ((state (nreverse (c-parse-state)))
740 prevbod bod)
741 (while (and state (not bod))
742 (setq bod (car state)
743 state (cdr state))
744 (if (consp bod)
745 (setq prevbod (car bod)
746 bod nil)))
747 (cond
748 (bod (goto-char bod))
749 (prevbod (goto-char prevbod))
51f606de
GM
750 (t (goto-char (point-min))
751 (setq arg 0)))
752 (setq arg (1- arg))))
753 (c-keep-region-active)
754 (= arg 0)))
28c236de
RS
755
756(defun c-end-of-defun (&optional arg)
757 "Move forward to next end of defun. With argument, do it that many times.
758Negative argument -N means move back to Nth preceding end of defun.
51f606de 759Returns t unless search stops due to beginning or end of buffer.
28c236de
RS
760
761An end of a defun occurs right after the close-parenthesis that matches
762the open-parenthesis that starts a defun; see `beginning-of-defun'."
763 (interactive "p")
0ec8351b
BW
764 (if (not arg)
765 (setq arg 1))
28c236de
RS
766 (if (< arg 0)
767 (c-beginning-of-defun (- arg))
768 (while (> arg 0)
51f606de
GM
769 (let ((pos (point))
770 eol)
771 (while (and (c-safe (down-list 1) t)
772 (not (eq (char-before) ?{)))
773 ;; skip down into the next defun-block
774 (forward-char -1)
775 (c-forward-sexp))
776 (c-beginning-of-defun 1)
777 (setq eol (c-point 'eol))
778 (c-forward-sexp)
779 (if (< eol (point))
780 ;; Don't move to next line for one line defuns.
781 (forward-line 1))
782 (when (<= (point) pos)
783 (goto-char (point-max))
784 (setq arg 0))
785 (setq arg (1- arg))))
786 (c-keep-region-active)
787 (= arg 0)))
28c236de 788
785eecbb
RS
789\f
790(defun c-beginning-of-statement (&optional count lim sentence-flag)
791 "Go to the beginning of the innermost C statement.
792With prefix arg, go back N - 1 statements. If already at the
28c236de
RS
793beginning of a statement then go to the beginning of the closest
794preceding one, moving into nested blocks if necessary (use
795\\[backward-sexp] to skip over a block). If within a comment, or next
796to a comment (only whitespace between), move by sentences instead of
797statements.
785eecbb
RS
798
799When called from a program, this function takes 3 optional args: the
800repetition count, a buffer position limit which is the farthest back
801to search, and a flag saying whether to do sentence motion when in a
802comment."
803 (interactive (list (prefix-numeric-value current-prefix-arg)
804 nil t))
28c236de
RS
805 (let* ((count (or count 1))
806 here
807 (range (c-collect-line-comments (c-literal-limits lim))))
808 (while (and (/= count 0)
809 (or (not lim) (> (point) lim)))
810 (setq here (point))
811 (if (and (not range) sentence-flag)
812 (save-excursion
813 ;; Find the comment next to point if we're not in one.
814 (if (> count 0)
51f606de
GM
815 (setq range (if (c-forward-comment -1)
816 (cons (point)
817 (progn (c-forward-comment 1) (point)))))
28c236de
RS
818 (skip-chars-forward " \t\n")
819 (setq range (point))
51f606de 820 (setq range (if (c-forward-comment 1)
28c236de
RS
821 (cons range (point))
822 nil)))
823 (setq range (c-collect-line-comments range))))
824 (if (and (< count 0) (= here (point-max)))
825 ;; Special case because eob might be in a literal.
826 (setq range nil))
827 (if range
828 (if (and sentence-flag
829 (/= (char-syntax (char-after (car range))) ?\"))
51f606de
GM
830 (let* ((lit-type (c-literal-type range))
831 (beg (save-excursion
832 (goto-char (car range))
833 (looking-at (if (eq lit-type 'c)
834 comment-start-skip
835 (concat "\\("
836 c-comment-prefix-regexp
837 "\\)[ \t]*")))
838 (goto-char (match-end 0))
839 (point)))
840 (end (save-excursion
841 (goto-char (- (cdr range)
842 (if (eq lit-type 'c) 2 1)))
843 (point))))
28c236de
RS
844 ;; move by sentence, but not past the limit of the literal
845 (save-restriction
51f606de
GM
846 (narrow-to-region beg end)
847 (c-safe (forward-sentence (if (< count 0) 1 -1)))
848 (if (and (memq lit-type '(c c++))
849 ;; Check if we stopped due to a comment
850 ;; prefix and not a sentence end.
851 (/= (point) beg)
852 (save-excursion
853 (beginning-of-line)
854 (looking-at (concat "[ \t]*\\("
855 c-comment-prefix-regexp
856 "\\)[ \t]*")))
857 (>= (point) (match-beginning 0))
858 (/= (match-beginning 1) (match-end 1))
859 (or (< (point) (match-end 0))
860 (and
861 (= (point) (match-end 0))
862 ;; The comment prefix may contain
863 ;; characters that is regarded as end
864 ;; of sentence.
865 (or (eolp)
866 (and
867 (save-excursion
868 (forward-paragraph -1)
869 (< (point) (match-beginning 0)))
870 (save-excursion
871 (beginning-of-line)
872 (or (not (re-search-backward
873 sentence-end
874 (c-point 'bopl)
875 t))
876 (< (match-end 0)
877 (c-point 'eol)))))))))
878 (setq count (+ count (if (< count 0) -1 1)))
879 (if (< count 0)
880 (progn
881 ;; In block comments, if there's only
882 ;; horizontal ws between the text and the
883 ;; comment ender, stop before it. Stop after
884 ;; the ender if there's either nothing or
885 ;; newlines between.
886 (when (and (eq lit-type 'c) (eq (point) end))
887 (widen)
888 (skip-chars-backward " \t")
889 (when (or (eq (point) end) (bolp))
890 (goto-char (cdr range)))))
891 (when (and (eq (point) beg) (looking-at "[ \t]*$"))
892 ;; Stop before instead of after the comment
893 ;; starter if nothing follows it.
894 (widen)
895 (goto-char (car range))))))
28c236de
RS
896 ;; See if we should escape the literal.
897 (if (> count 0)
898 (if (< (point) here)
899 (setq count (1- count))
900 (goto-char (car range))
901 (setq range nil))
902 (if (> (point) here)
903 (setq count (1+ count))
904 (goto-char (cdr range))
905 (setq range nil))))
906 (goto-char (if (> count 0) (car range) (cdr range)))
907 (setq range nil))
908 ;; Below we do approximately the same as
51f606de 909 ;; c-beginning-of-statement-1 and c-end-of-statement-1, and
28c236de
RS
910 ;; perhaps they should be changed, but that'd likely break a
911 ;; lot in cc-engine.
912 (goto-char here)
28c236de 913 (if (> count 0)
51f606de
GM
914 (condition-case nil
915 ;; Stop before `{' and after `;', `{', `}' and `};'
916 ;; when not followed by `}' or `)', but on the other
917 ;; side of the syntactic ws. Move by sexps and move
918 ;; into parens. Also stop before `#' when it's first
919 ;; on a line.
920 (let ((comment-pos (not sentence-flag))
921 (large-enough (- (point-max)))
922 last last-below-line)
28c236de 923 (catch 'done
51f606de
GM
924 (while t
925 (setq last (point))
926 (when (and (looking-at "{\\|^#") (/= here last))
927 (unless (and c-special-brace-lists
928 (eq (char-after) ?{)
929 (c-looking-at-special-brace-list))
930 (if (and (eq (char-after) ?#)
931 (numberp last-below-line)
932 (not (eq last-below-line here)))
933 (goto-char last-below-line))
934 (throw 'done t)))
935 (if comment-pos
936 (c-forward-comment large-enough)
937 (when (c-forward-comment -1)
938 ;; Record position of first comment.
939 (save-excursion
940 (c-forward-comment 1)
941 (setq comment-pos (point)))
942 (c-forward-comment large-enough)))
943 (unless last-below-line
944 (if (save-excursion
945 (re-search-forward "\\(^\\|[^\\]\\)$" last t))
946 (setq last-below-line last)))
947 (cond ((bobp) ; Must handle bob specially.
948 (if (= here last)
949 (throw 'done t)
950 (goto-char last)
951 (throw 'done t)))
952 ((progn (backward-char)
953 (looking-at "[;{}]"))
954 (if (and c-special-brace-lists
955 (eq (char-after) ?{)
956 (c-looking-at-special-brace-list))
957 (skip-syntax-backward "w_") ; Speedup only.
0ec8351b 958 (if (or (= here last)
51f606de
GM
959 (memq (char-after last) '(?\) ?})))
960 (if (and (eq (char-before) ?})
961 (eq (char-after) ?\;))
962 (backward-char))
28c236de 963 (goto-char last)
51f606de
GM
964 (throw 'done t))))
965 ((= (char-syntax (char-after)) ?\")
966 (forward-char)
967 (c-backward-sexp))
968 (t (skip-syntax-backward "w_")) ; Speedup only.
969 )))
970 (if (and (numberp comment-pos)
971 (< (point) comment-pos))
972 ;; We jumped over a comment that should be investigated.
973 (goto-char comment-pos)
974 (setq count (1- count))))
975 (error
976 (goto-char (point-min))
977 (setq count 0)))
978 (condition-case nil
979 ;; Stop before `{', `}', and `#' when it's first on a
980 ;; line, but on the other side of the syntactic ws, and
981 ;; after `;', `}' and `};'. Only stop before `{' if at
982 ;; top level or inside braces, though. Move by sexps
983 ;; and move into parens. Also stop at eol of lines
984 ;; starting with `#'.
985 (let ((comment-pos (not sentence-flag))
986 (large-enough (point-max))
987 last)
988 (catch 'done
989 (while t
990 (setq last (point))
991 (if comment-pos
992 (c-forward-comment large-enough)
993 (if (progn
994 (skip-chars-forward " \t\n\r\f")
995 ;; Record position of first comment.
996 (setq comment-pos (point))
997 (c-forward-comment 1))
998 (c-forward-comment large-enough)
999 (setq comment-pos nil)))
1000 (cond ((and (eq (char-after) ?{)
1001 (not (and c-special-brace-lists
1002 (c-looking-at-special-brace-list)))
1003 (/= here last)
1004 (save-excursion
1005 (or (not (c-safe (up-list -1) t))
1006 (= (char-after) ?{))))
1007 (goto-char last)
1008 (throw 'done t))
1009 ((and c-special-brace-lists
1010 (eq (char-after) ?})
1011 (save-excursion
1012 (and (c-safe (up-list -1) t)
1013 (c-looking-at-special-brace-list))))
1014 (forward-char 1)
1015 (skip-syntax-forward "w_")) ; Speedup only.
1016 ((and (eq (char-after) ?})
1017 (/= here last))
1018 (goto-char last)
1019 (throw 'done t))
1020 ((looking-at "^#")
1021 (if (= here last)
1022 (or (re-search-forward "\\(^\\|[^\\]\\)$" nil t)
1023 (goto-char (point-max)))
1024 (goto-char last))
1025 (throw 'done t))
1026 ((looking-at ";\\|};?")
1027 (goto-char (match-end 0))
1028 (throw 'done t))
1029 ((= (char-syntax (char-after)) ?\")
1030 (c-forward-sexp))
1031 (t
1032 (forward-char 1)
1033 (skip-syntax-forward "w_")) ; Speedup only.
1034 )))
1035 (if (and (numberp comment-pos)
1036 (> (point) comment-pos))
1037 ;; We jumped over a comment that should be investigated.
1038 (goto-char comment-pos)
1039 (setq count (1+ count))))
1040 (error
1041 (goto-char (point-max))
1042 (setq count 0)))
1043 ))
28c236de 1044 ;; If we haven't moved we're near a buffer limit.
51f606de 1045 (when (and (not (zerop count)) (= (point) here))
28c236de
RS
1046 (goto-char (if (> count 0) (point-min) (point-max)))
1047 (setq count 0)))
785eecbb 1048 ;; its possible we've been left up-buf of lim
28c236de 1049 (if lim (goto-char (max (point) lim))))
785eecbb
RS
1050 (c-keep-region-active))
1051
1052(defun c-end-of-statement (&optional count lim sentence-flag)
1053 "Go to the end of the innermost C statement.
28c236de
RS
1054With prefix arg, go forward N - 1 statements. Move forward to the end
1055of the next statement if already at end, and move into nested blocks
1056\(use \\[forward-sexp] to skip over a block). If within a comment, or
1057next to a comment (only whitespace between), move by sentences instead
1058of statements.
785eecbb
RS
1059
1060When called from a program, this function takes 3 optional args: the
1061repetition count, a buffer position limit which is the farthest back
1062to search, and a flag saying whether to do sentence motion when in a
1063comment."
1064 (interactive (list (prefix-numeric-value current-prefix-arg)
1065 nil t))
1066 (c-beginning-of-statement (- (or count 1)) lim sentence-flag)
1067 (c-keep-region-active))
1068
1069\f
1070;; set up electric character functions to work with pending-del,
1071;; (a.k.a. delsel) mode. All symbols get the t value except
c93a62d8 1072;; the functions which delete, which gets 'supersede.
785eecbb
RS
1073(mapcar
1074 (function
1075 (lambda (sym)
1076 (put sym 'delete-selection t) ; for delsel (Emacs)
1077 (put sym 'pending-delete t))) ; for pending-del (XEmacs)
1078 '(c-electric-pound
1079 c-electric-brace
1080 c-electric-slash
1081 c-electric-star
1082 c-electric-semi&comma
1083 c-electric-lt-gt
0ec8351b
BW
1084 c-electric-colon
1085 c-electric-paren))
c93a62d8
RS
1086(put 'c-electric-delete 'delete-selection 'supersede) ; delsel
1087(put 'c-electric-delete 'pending-delete 'supersede) ; pending-del
1088(put 'c-electric-backspace 'delete-selection 'supersede) ; delsel
1089(put 'c-electric-backspace 'pending-delete 'supersede) ; pending-del
785eecbb
RS
1090
1091\f
1092;; This is used by indent-for-comment to decide how much to indent a
1093;; comment in C code based on its context.
1094(defun c-comment-indent ()
1095 (if (looking-at (concat "^\\(" c-comment-start-regexp "\\)"))
1096 0 ;Existing comment at bol stays there.
1097 (let ((opoint (point))
1098 placeholder)
1099 (save-excursion
1100 (beginning-of-line)
1101 (cond
1102 ;; CASE 1: A comment following a solitary close-brace should
1103 ;; have only one space.
1104 ((looking-at (concat "[ \t]*}[ \t]*\\($\\|"
1105 c-comment-start-regexp
1106 "\\)"))
1107 (search-forward "}")
1108 (1+ (current-column)))
1109 ;; CASE 2: 2 spaces after #endif
1110 ((or (looking-at "^#[ \t]*endif[ \t]*")
1111 (looking-at "^#[ \t]*else[ \t]*"))
1112 7)
0ec8351b
BW
1113 ;; CASE 3: when c-indent-comments-syntactically-p is t,
1114 ;; calculate the offset according to c-offsets-alist.
1115 ;; E.g. identical to hitting TAB.
785eecbb
RS
1116 ((and c-indent-comments-syntactically-p
1117 (save-excursion
1118 (skip-chars-forward " \t")
0ec8351b 1119 (or (looking-at c-comment-start-regexp)
785eecbb
RS
1120 (eolp))))
1121 (let ((syntax (c-guess-basic-syntax)))
1122 ;; BOGOSITY ALERT: if we're looking at the eol, its
1123 ;; because indent-for-comment hasn't put the comment-start
1124 ;; in the buffer yet. this will screw up the syntactic
1125 ;; analysis so we kludge in the necessary info. Another
1126 ;; kludge is that if we're at the bol, then we really want
1127 ;; to ignore any anchoring as specified by
1128 ;; c-comment-only-line-offset since it doesn't apply here.
1129 (if (save-excursion
1130 (beginning-of-line)
1131 (skip-chars-forward " \t")
1132 (eolp))
1133 (c-add-syntax 'comment-intro))
1134 (let ((c-comment-only-line-offset
1135 (if (consp c-comment-only-line-offset)
1136 c-comment-only-line-offset
1137 (cons c-comment-only-line-offset
1138 c-comment-only-line-offset))))
1139 (apply '+ (mapcar 'c-get-offset syntax)))))
51f606de
GM
1140 ;; CASE 4: If previous line is a comment-only line, use its
1141 ;; indentation if it's greater than comment-column. Leave at
1142 ;; least one space between the comment and the last nonblank
1143 ;; character in any case.
785eecbb
RS
1144 ((save-excursion
1145 (beginning-of-line)
1146 (and (not (bobp))
1147 (forward-line -1))
1148 (skip-chars-forward " \t")
1149 (prog1
1150 (looking-at c-comment-start-regexp)
51f606de
GM
1151 (setq placeholder (current-column))))
1152 (goto-char opoint)
1153 (skip-chars-backward " \t")
1154 (max (if (bolp) 0 (1+ (current-column)))
1155 placeholder
1156 comment-column))
785eecbb
RS
1157 ;; CASE 5: If comment-column is 0, and nothing but space
1158 ;; before the comment, align it at 0 rather than 1.
1159 ((progn
1160 (goto-char opoint)
1161 (skip-chars-backward " \t")
1162 (and (= comment-column 0) (bolp)))
1163 0)
1164 ;; CASE 6: indent at comment column except leave at least one
1165 ;; space.
1166 (t (max (1+ (current-column))
1167 comment-column))
1168 )))))
1169
fd3b1ef6 1170\f
785eecbb
RS
1171;; used by outline-minor-mode
1172(defun c-outline-level ()
51f606de
GM
1173 (save-excursion
1174 (skip-chars-forward "\t ")
1175 (current-column)))
785eecbb
RS
1176
1177\f
1178(defun c-up-conditional (count)
1179 "Move back to the containing preprocessor conditional, leaving mark behind.
1180A prefix argument acts as a repeat count. With a negative argument,
1181move forward to the end of the containing preprocessor conditional.
51f606de
GM
1182
1183`#elif' is treated like `#else' followed by `#if', so the function
1184stops at them when going backward, but not when going forward."
1185 (interactive "p")
1186 (c-forward-conditional (- count) -1)
1187 (c-keep-region-active))
1188
1189(defun c-up-conditional-with-else (count)
1190 "Move back to the containing preprocessor conditional, including `#else'.
1191Just like `c-up-conditional', except it also stops at `#else'
1192directives."
1193 (interactive "p")
1194 (c-forward-conditional (- count) -1 t)
1195 (c-keep-region-active))
1196
1197(defun c-down-conditional (count)
1198 "Move forward into the next preprocessor conditional, leaving mark behind.
1199A prefix argument acts as a repeat count. With a negative argument,
1200move backward into the previous preprocessor conditional.
1201
1202`#elif' is treated like `#else' followed by `#if', so the function
1203stops at them when going forward, but not when going backward."
785eecbb 1204 (interactive "p")
51f606de 1205 (c-forward-conditional count 1)
785eecbb
RS
1206 (c-keep-region-active))
1207
51f606de
GM
1208(defun c-down-conditional-with-else (count)
1209 "Move forward into the next preprocessor conditional, including `#else'.
1210Just like `c-down-conditional', except it also stops at `#else'
1211directives."
1212 (interactive "p")
1213 (c-forward-conditional count 1 t)
1214 (c-keep-region-active))
1215
1216(defun c-backward-conditional (count &optional target-depth with-else)
785eecbb
RS
1217 "Move back across a preprocessor conditional, leaving mark behind.
1218A prefix argument acts as a repeat count. With a negative argument,
1219move forward across a preprocessor conditional."
1220 (interactive "p")
51f606de 1221 (c-forward-conditional (- count) target-depth with-else)
785eecbb
RS
1222 (c-keep-region-active))
1223
51f606de 1224(defun c-forward-conditional (count &optional target-depth with-else)
785eecbb
RS
1225 "Move forward across a preprocessor conditional, leaving mark behind.
1226A prefix argument acts as a repeat count. With a negative argument,
51f606de
GM
1227move backward across a preprocessor conditional.
1228
1229`#elif' is treated like `#else' followed by `#if', except that the
1230nesting level isn't changed when tracking subconditionals.
1231
1232The optional argument TARGET-DEPTH specifies the wanted nesting depth
1233after each scan. I.e. if TARGET-DEPTH is -1, the function will move
1234out of the enclosing conditional. A non-integer non-nil TARGET-DEPTH
1235counts as -1.
1236
1237If the optional argument WITH-ELSE is non-nil, `#else' directives are
1238treated as conditional clause limits. Normally they are ignored."
785eecbb
RS
1239 (interactive "p")
1240 (let* ((forward (> count 0))
1241 (increment (if forward -1 1))
1242 (search-function (if forward 're-search-forward 're-search-backward))
1243 (new))
51f606de
GM
1244 (unless (integerp target-depth)
1245 (setq target-depth (if target-depth -1 0)))
785eecbb
RS
1246 (save-excursion
1247 (while (/= count 0)
51f606de
GM
1248 (let ((depth 0)
1249 ;; subdepth is the depth in "uninteresting" subtrees,
1250 ;; i.e. those that takes us farther from the target
1251 ;; depth instead of closer.
1252 (subdepth 0)
1253 found)
785eecbb
RS
1254 (save-excursion
1255 ;; Find the "next" significant line in the proper direction.
1256 (while (and (not found)
1257 ;; Rather than searching for a # sign that
1258 ;; comes at the beginning of a line aside from
1259 ;; whitespace, search first for a string
1260 ;; starting with # sign. Then verify what
1261 ;; precedes it. This is faster on account of
1262 ;; the fastmap feature of the regexp matcher.
1263 (funcall search-function
51f606de 1264 "#[ \t]*\\(if\\|elif\\|endif\\|else\\)"
785eecbb
RS
1265 nil t))
1266 (beginning-of-line)
1267 ;; Now verify it is really a preproc line.
51f606de
GM
1268 (if (looking-at "^[ \t]*#[ \t]*\\(if\\|elif\\|endif\\|else\\)")
1269 (let (dchange (directive (match-string 1)))
1270 (cond ((string= directive "if")
1271 (setq dchange (- increment)))
1272 ((string= directive "endif")
1273 (setq dchange increment))
1274 ((= subdepth 0)
1275 ;; When we're not in an "uninteresting"
1276 ;; subtree, we might want to act on "elif"
1277 ;; and "else" too.
1278 (if (cond (with-else
1279 ;; Always move toward the target depth.
1280 (setq dchange
1281 (if (> target-depth 0) 1 -1)))
1282 ((string= directive "elif")
1283 (setq dchange (- increment))))
1284 ;; Ignore the change if it'd take us
1285 ;; into an "uninteresting" subtree.
1286 (if (eq (> dchange 0) (<= target-depth 0))
1287 (setq dchange nil)))))
1288 (when dchange
1289 (when (or (/= subdepth 0)
1290 (eq (> dchange 0) (<= target-depth 0)))
1291 (setq subdepth (+ subdepth dchange)))
1292 (setq depth (+ depth dchange))
1293 ;; If we are trying to move across, and we find an
1294 ;; end before we find a beginning, get an error.
1295 (if (and (< depth target-depth) (< dchange 0))
1296 (error (if forward
1297 "No following conditional at this level"
1298 "No previous conditional at this level"))))
785eecbb
RS
1299 ;; When searching forward, start from next line so
1300 ;; that we don't find the same line again.
1301 (if forward (forward-line 1))
51f606de
GM
1302 ;; We found something if we've arrived at the
1303 ;; target depth.
1304 (if (and dchange (= depth target-depth))
785eecbb
RS
1305 (setq found (point))))
1306 ;; else
51f606de 1307 (if forward (forward-line 1)))))
785eecbb
RS
1308 (or found
1309 (error "No containing preprocessor conditional"))
1310 (goto-char (setq new found)))
1311 (setq count (+ count increment))))
1312 (push-mark)
1313 (goto-char new))
1314 (c-keep-region-active))
1315
1316\f
1317;; commands to indent lines, regions, defuns, and expressions
b8ded794 1318(defun c-indent-command (&optional arg)
785eecbb
RS
1319 "Indent current line as C code, and/or insert some whitespace.
1320
1321If `c-tab-always-indent' is t, always just indent the current line.
1322If nil, indent the current line only if point is at the left margin or
1323in the line's indentation; otherwise insert some whitespace[*]. If
1324other than nil or t, then some whitespace[*] is inserted only within
1325literals (comments and strings) and inside preprocessor directives,
1326but the line is always reindented.
1327
b8ded794
GM
1328If `c-syntactic-indentation' is t, indentation is done according to
1329the syntactic context. If it's nil, the line is just indented one
1330step according to `c-basic-offset'. In this mode, a numeric argument
1331indents a number of such steps, positive or negative, and an empty
1332prefix argument is equivalent to -1.
1333
1334If `c-syntactic-indentation' is t, then a numeric argument, regardless
1335of its value, means indent rigidly all the lines of the expression
1336starting after point so that this line becomes properly indented. The
1337relative indentation among the lines of the expression is preserved.
785eecbb
RS
1338
1339 [*] The amount and kind of whitespace inserted is controlled by the
1340 variable `c-insert-tab-function', which is called to do the actual
1341 insertion of whitespace. Normally the function in this variable
1342 just inserts a tab character, or the equivalent number of spaces,
1343 depending on the variable `indent-tabs-mode'."
1344
b8ded794
GM
1345 (interactive "p")
1346 (let ((bod (c-point 'bod))
1347 (indent-function
1348 (if c-syntactic-indentation
1349 (symbol-function 'c-indent-line)
1350 (lambda ()
1351 (let ((steps (cond ((not current-prefix-arg) 1)
1352 ((equal current-prefix-arg '(4)) -1)
1353 (t arg))))
1354 (c-shift-line-indentation (* steps c-basic-offset)))
1355 ))))
1356 (if (and c-syntactic-indentation current-prefix-arg)
1357 ;; If c-syntactic-indentation and got arg, always indent this
1358 ;; line as C and shift remaining lines of expression the same
1359 ;; amount.
785eecbb
RS
1360 (let ((shift-amt (c-indent-line))
1361 beg end)
1362 (save-excursion
1363 (if (eq c-tab-always-indent t)
1364 (beginning-of-line))
1365 (setq beg (point))
0ec8351b 1366 (c-forward-sexp 1)
785eecbb
RS
1367 (setq end (point))
1368 (goto-char beg)
1369 (forward-line 1)
1370 (setq beg (point)))
1371 (if (> end beg)
1372 (indent-code-rigidly beg end (- shift-amt) "#")))
b8ded794 1373 ;; Else use c-tab-always-indent to determine behavior.
785eecbb
RS
1374 (cond
1375 ;; CASE 1: indent when at column zero or in lines indentation,
1376 ;; otherwise insert a tab
1377 ((not c-tab-always-indent)
1378 (if (save-excursion
1379 (skip-chars-backward " \t")
1380 (not (bolp)))
1381 (funcall c-insert-tab-function)
b8ded794 1382 (funcall indent-function)))
785eecbb
RS
1383 ;; CASE 2: just indent the line
1384 ((eq c-tab-always-indent t)
b8ded794 1385 (funcall indent-function))
785eecbb
RS
1386 ;; CASE 3: if in a literal, insert a tab, but always indent the
1387 ;; line
1388 (t
1389 (if (c-in-literal bod)
1390 (funcall c-insert-tab-function))
b8ded794 1391 (funcall indent-function)
785eecbb
RS
1392 )))))
1393
1394(defun c-indent-exp (&optional shutup-p)
b8ded794 1395 "Indent each line in balanced expression following point syntactically.
785eecbb 1396Optional SHUTUP-P if non-nil, inhibits message printing and error checking."
28c236de 1397 (interactive "*P")
51f606de 1398 (let ((here (point-marker))
785eecbb 1399 end progress-p)
51f606de 1400 (set-marker-insertion-type here t)
785eecbb
RS
1401 (unwind-protect
1402 (let ((c-echo-syntactic-information-p nil) ;keep quiet for speed
1403 (start (progn
1404 ;; try to be smarter about finding the range of
1405 ;; lines to indent. skip all following
1406 ;; whitespace. failing that, try to find any
1407 ;; opening brace on the current line
1408 (skip-chars-forward " \t\n")
1409 (if (memq (char-after) '(?\( ?\[ ?\{))
1410 (point)
1411 (let ((state (parse-partial-sexp (point)
1412 (c-point 'eol))))
1413 (and (nth 1 state)
1414 (goto-char (nth 1 state))
1415 (memq (char-after) '(?\( ?\[ ?\{))
1416 (point)))))))
1417 ;; find balanced expression end
0ec8351b 1418 (setq end (and (c-safe (progn (c-forward-sexp 1) t))
785eecbb
RS
1419 (point-marker)))
1420 ;; sanity check
1421 (and (not start)
1422 (not shutup-p)
1423 (error "Cannot find start of balanced expression to indent."))
1424 (and (not end)
1425 (not shutup-p)
1426 (error "Cannot find end of balanced expression to indent."))
1427 (c-progress-init start end 'c-indent-exp)
1428 (setq progress-p t)
1429 (goto-char start)
1430 (beginning-of-line)
1431 (while (< (point) end)
1432 (if (not (looking-at "[ \t]*$"))
1433 (c-indent-line))
1434 (c-progress-update)
1435 (forward-line 1)))
1436 ;; make sure marker is deleted
1437 (and end
1438 (set-marker end nil))
1439 (and progress-p
1440 (c-progress-fini 'c-indent-exp))
51f606de
GM
1441 (goto-char here)
1442 (set-marker here nil))))
785eecbb
RS
1443
1444(defun c-indent-defun ()
b8ded794
GM
1445 "Re-indents the current top-level function def, struct or class declaration
1446syntactically."
28c236de 1447 (interactive "*")
785eecbb
RS
1448 (let ((here (point-marker))
1449 (c-echo-syntactic-information-p nil)
1450 (brace (c-least-enclosing-brace (c-parse-state))))
28c236de 1451 (goto-char (or brace (c-point 'bod)))
785eecbb
RS
1452 ;; if we're sitting at b-o-b, it might be because there was no
1453 ;; least enclosing brace and we were sitting on the defun's open
1454 ;; brace.
1455 (if (and (bobp) (not (eq (char-after) ?\{)))
1456 (goto-char here))
1457 ;; if defun-prompt-regexp is non-nil, b-o-d might not leave us at
1458 ;; the open brace. I consider this an Emacs bug.
1459 (and (boundp 'defun-prompt-regexp)
1460 defun-prompt-regexp
1461 (looking-at defun-prompt-regexp)
1462 (goto-char (match-end 0)))
1463 ;; catch all errors in c-indent-exp so we can 1. give more
1464 ;; meaningful error message, and 2. restore point
1465 (unwind-protect
1466 (c-indent-exp)
1467 (goto-char here)
1468 (set-marker here nil))))
1469
1470(defun c-indent-region (start end)
1471 ;; Indent every line whose first char is between START and END inclusive.
1472 (save-excursion
1473 (goto-char start)
1474 ;; Advance to first nonblank line.
1475 (skip-chars-forward " \t\n")
1476 (beginning-of-line)
1477 (let (endmark)
1478 (unwind-protect
1479 (let ((c-tab-always-indent t)
1480 ;; shut up any echo msgs on indiv lines
1481 (c-echo-syntactic-information-p nil)
1482 fence)
1483 (c-progress-init start end 'c-indent-region)
1484 (setq endmark (copy-marker end))
1485 (while (and (bolp)
1486 (not (eobp))
1487 (< (point) endmark))
1488 ;; update progress
1489 (c-progress-update)
1490 ;; Indent one line as with TAB.
1491 (let (nextline sexpend sexpbeg)
1492 ;; skip blank lines
1493 (skip-chars-forward " \t\n")
1494 (beginning-of-line)
1495 ;; indent the current line
1496 (c-indent-line)
1497 (setq fence (point))
1498 (if (save-excursion
1499 (beginning-of-line)
1500 (looking-at "[ \t]*#"))
1501 (forward-line 1)
1502 (save-excursion
1503 ;; Find beginning of following line.
1504 (setq nextline (c-point 'bonl))
1505 ;; Find first beginning-of-sexp for sexp extending past
1506 ;; this line.
1507 (beginning-of-line)
1508 (while (< (point) nextline)
1509 (condition-case nil
1510 (progn
0ec8351b 1511 (c-forward-sexp 1)
785eecbb
RS
1512 (setq sexpend (point)))
1513 (error (setq sexpend nil)
1514 (goto-char nextline)))
1515 (c-forward-syntactic-ws))
1516 (if sexpend
0ec8351b 1517 (progn
785eecbb
RS
1518 ;; make sure the sexp we found really starts on the
1519 ;; current line and extends past it
1520 (goto-char sexpend)
1521 (setq sexpend (point-marker))
0ec8351b 1522 (c-safe (c-backward-sexp 1))
785eecbb
RS
1523 (setq sexpbeg (point))))
1524 (if (and sexpbeg (< sexpbeg fence))
1525 (setq sexpbeg fence)))
51f606de
GM
1526 ;; Since we move by sexps we might have missed
1527 ;; comment-only lines.
1528 (if sexpbeg
1529 (save-excursion
1530 (while (progn
1531 (forward-line 1)
1532 (skip-chars-forward " \t")
1533 (< (point) sexpbeg))
1534 (if (looking-at c-comment-start-regexp)
1535 (setq sexpbeg (c-point 'bol))))))
785eecbb
RS
1536 ;; If that sexp ends within the region, indent it all at
1537 ;; once, fast.
1538 (condition-case nil
1539 (if (and sexpend
1540 (> sexpend nextline)
1541 (<= sexpend endmark))
1542 (progn
1543 (goto-char sexpbeg)
1544 (c-indent-exp 'shutup)
1545 (c-progress-update)
1546 (goto-char sexpend)))
1547 (error
1548 (goto-char sexpbeg)
1549 (c-indent-line)))
1550 ;; Move to following line and try again.
1551 (and sexpend
1552 (markerp sexpend)
1553 (set-marker sexpend nil))
1554 (forward-line 1)
1555 (setq fence (point))))))
1556 (set-marker endmark nil)
1557 (c-progress-fini 'c-indent-region)
1558 (c-echo-parsing-error)
1559 ))))
1560
1561(defun c-mark-function ()
0ec8351b 1562 "Put mark at end of current top-level defun, point at beginning."
785eecbb
RS
1563 (interactive)
1564 (let ((here (point))
0ec8351b
BW
1565 (eod (c-point 'eod))
1566 (state (c-parse-state)))
1567 ;; Are we sitting at the top level, someplace between either the
1568 ;; beginning of buffer, or the nearest preceding defun? If so,
1569 ;; try first to figure out whether we're sitting on the
1570 ;; introduction to a top-level defun, in which case we want to
1571 ;; mark the entire defun we're sitting on.
1572 ;;
1573 ;; If we're sitting on anything else at the top-level, we want to
1574 ;; just mark the statement that we're on
1575 (if (or (and (consp (car state))
1576 (= (length state) 1))
1577 (null state))
1578 ;; Are we in the whitespace after the nearest preceding defun?
1579 (if (and state
1580 (looking-at "[ \t]*$")
1581 (= (save-excursion
1582 (c-backward-syntactic-ws)
1583 (skip-chars-backward ";")
1584 (point))
1585 (cdar state)))
1586 (progn
1587 (setq eod (point))
1588 (goto-char (caar state))
1589 (c-beginning-of-statement-1))
1590 (if (= ?{ (save-excursion
1591 (c-end-of-statement-1)
1592 (char-before)))
1593 ;; We must be in a defuns's introduction
1594 (progn
1595 (c-end-of-statement-1)
1596 (skip-chars-backward "{")
1597 (c-beginning-of-statement-1)
1598 (c-forward-syntactic-ws))
1599 ;; Just mark the statement
1600 (c-end-of-statement-1)
1601 (forward-line 1)
1602 (setq eod (point))
1603 (c-beginning-of-statement-1)))
1604 ;; We are inside some enclosing brace structure, so we first
1605 ;; need to find our way to the least enclosing brace. Then, in
1606 ;; both cases, we to mark the region from the beginning of the
1607 ;; current statement, until the end of the next following defun
1608 (while (and state)
1609 (or (consp (car state))
1610 (goto-char (car state)))
1611 (setq state (cdr state)))
1612 (c-beginning-of-statement-1))
785eecbb
RS
1613 (push-mark here)
1614 (push-mark eod nil t)))
1615
0ec8351b
BW
1616(defun c-indent-line-or-region ()
1617 "When the region is active, indent it. Otherwise indent the current line."
1618 ;; Emacs has a variable called mark-active, XEmacs uses region-active-p
1619 (interactive)
1620 (if (c-region-is-active-p)
1621 (c-indent-region (region-beginning) (region-end))
1622 (c-indent-command)))
1623
785eecbb
RS
1624\f
1625;; for progress reporting
1626(defvar c-progress-info nil)
1627
1628(defun c-progress-init (start end context)
a7c7b186
KH
1629 (cond
1630 ;; Be silent
1631 ((not c-progress-interval))
1632 ;; Start the progress update messages. If this Emacs doesn't have
1633 ;; a built-in timer, just be dumb about it.
1634 ((not (fboundp 'current-time))
1635 (message "indenting region... (this may take a while)"))
1636 ;; If progress has already been initialized, do nothing. otherwise
1637 ;; initialize the counter with a vector of:
1638 ;; [start end lastsec context]
1639 (c-progress-info)
1640 (t (setq c-progress-info (vector start
785eecbb
RS
1641 (save-excursion
1642 (goto-char end)
1643 (point-marker))
1644 (nth 1 (current-time))
1645 context))
a7c7b186
KH
1646 (message "indenting region..."))
1647 ))
785eecbb
RS
1648
1649(defun c-progress-update ()
1650 ;; update progress
1651 (if (not (and c-progress-info c-progress-interval))
1652 nil
1653 (let ((now (nth 1 (current-time)))
1654 (start (aref c-progress-info 0))
1655 (end (aref c-progress-info 1))
1656 (lastsecs (aref c-progress-info 2)))
1657 ;; should we update? currently, update happens every 2 seconds,
1658 ;; what's the right value?
1659 (if (< c-progress-interval (- now lastsecs))
1660 (progn
1661 (message "indenting region... (%d%% complete)"
1662 (/ (* 100 (- (point) start)) (- end start)))
1663 (aset c-progress-info 2 now)))
1664 )))
1665
1666(defun c-progress-fini (context)
1667 ;; finished
a7c7b186
KH
1668 (if (not c-progress-interval)
1669 nil
1670 (if (or (eq context (aref c-progress-info 3))
1671 (eq context t))
1672 (progn
1673 (set-marker (aref c-progress-info 1) nil)
1674 (setq c-progress-info nil)
1675 (message "indenting region...done")))))
785eecbb
RS
1676
1677
1678\f
1679;;; This page handles insertion and removal of backslashes for C macros.
1680
1681(defun c-backslash-region (from to delete-flag)
1682 "Insert, align, or delete end-of-line backslashes on the lines in the region.
1683With no argument, inserts backslashes and aligns existing backslashes.
1684With an argument, deletes the backslashes.
1685
1686This function does not modify blank lines at the start of the region.
1687If the region ends at the start of a line, it always deletes the
1688backslash (if any) at the end of the previous line.
0ec8351b 1689
785eecbb
RS
1690You can put the region around an entire macro definition and use this
1691command to conveniently insert and align the necessary backslashes."
28c236de 1692 (interactive "*r\nP")
785eecbb
RS
1693 (save-excursion
1694 (goto-char from)
1695 (let ((column c-backslash-column)
1696 (endmark (make-marker)))
1697 (move-marker endmark to)
1698 ;; Compute the smallest column number past the ends of all the lines.
1699 (if (not delete-flag)
1700 (while (< (point) to)
1701 (end-of-line)
1702 (if (eq (char-before) ?\\)
1703 (progn (forward-char -1)
1704 (skip-chars-backward " \t")))
1705 (setq column (max column (1+ (current-column))))
1706 (forward-line 1)))
1707 ;; Adjust upward to a tab column, if that doesn't push past the margin.
1708 (if (> (% column tab-width) 0)
1709 (let ((adjusted (* (/ (+ column tab-width -1) tab-width) tab-width)))
1710 (if (< adjusted (window-width))
1711 (setq column adjusted))))
1712 ;; Don't modify blank lines at start of region.
1713 (goto-char from)
1714 (while (and (< (point) endmark) (eolp))
1715 (forward-line 1))
1716 ;; Add or remove backslashes on all the lines.
1717 (while (< (point) endmark)
1718 (if (and (not delete-flag)
1719 ;; Un-backslashify the last line
1720 ;; if the region ends right at the start of the next line.
1721 (save-excursion
1722 (forward-line 1)
1723 (< (point) endmark)))
1724 (c-append-backslash column)
1725 (c-delete-backslash))
1726 (forward-line 1))
28c236de 1727 (move-marker endmark nil))))
785eecbb
RS
1728
1729(defun c-append-backslash (column)
1730 (end-of-line)
1731 (if (eq (char-before) ?\\)
1732 (progn (forward-char -1)
1733 (delete-horizontal-space)
1734 (indent-to column))
1735 (indent-to column)
1736 (insert "\\")))
1737
1738(defun c-delete-backslash ()
1739 (end-of-line)
1740 (or (bolp)
1741 (progn
1742 (forward-char -1)
1743 (if (looking-at "\\\\")
1744 (delete-region (1+ (point))
1745 (progn (skip-chars-backward " \t") (point)))))))
1746
51f606de 1747
785eecbb 1748\f
51f606de
GM
1749;;; Line breaking and paragraph filling.
1750
1751;; The filling code is based on a simple theory; leave the intricacies
1752;; of the text handling to the currently active mode for that
1753;; (e.g. adaptive-fill-mode or filladapt-mode) and do as little as
1754;; possible to make them work correctly wrt the comment and string
1755;; separators, one-line paragraphs etc. Unfortunately, when it comes
1756;; to it, there's quite a lot of special cases to handle which makes
1757;; the code anything but simple. The intention is that it will work
1758;; with any well-written text filling package that preserves a fill
1759;; prefix.
1760;;
1761;; We temporarily mask comment starters and enders as necessary for
1762;; the filling code to do its job on a seemingly normal text block.
1763;; We do _not_ mask the fill prefix, so it's up to the filling code to
1764;; preserve it correctly (especially important when filling C++ style
1765;; line comments). By default, we set up and use adaptive-fill-mode,
1766;; which is standard in all supported Emacs flavors.
1767
1768(defun c-guess-fill-prefix (lit-limits lit-type)
1769 ;; Determine the appropriate comment fill prefix for a block or line
1770 ;; comment. Return a cons of the prefix string and the column where
1771 ;; it ends. If fill-prefix is set, it'll override. Note that this
1772 ;; function also uses the value of point in some heuristics.
1773 (let* ((here (point))
1774 (prefix-regexp (concat "[ \t]*\\("
1775 c-comment-prefix-regexp
1776 "\\)[ \t]*"))
1777 (comment-start-regexp (if (eq lit-type 'c++)
1778 prefix-regexp
1779 comment-start-skip))
1780 prefix-line comment-prefix res)
1781 (cond
1782 (fill-prefix
1783 (setq res (cons fill-prefix
1784 ;; Ugly way of getting the column after the fill
1785 ;; prefix; it'd be nice with a current-column
1786 ;; that works on strings..
1787 (let ((buffer-modified (buffer-modified-p))
1788 (buffer-undo-list t)
1789 (start (point)))
1790 (unwind-protect
1791 (progn
1792 (insert ?\n fill-prefix)
1793 (current-column))
1794 (delete-region start (point))
1795 (set-buffer-modified-p buffer-modified))))))
1796 ((eq lit-type 'c++)
1797 (save-excursion
1798 ;; Set fallback for comment-prefix if none is found.
1799 (setq comment-prefix "// ")
1800 (beginning-of-line)
1801 (if (> (point) (car lit-limits))
1802 ;; The current line is not the comment starter, so the
1803 ;; comment has more than one line, and it can therefore be
1804 ;; used to find the comment fill prefix.
1805 (setq prefix-line (point))
1806 (goto-char (car lit-limits))
1807 (if (and (= (forward-line 1) 0)
1808 (< (point) (cdr lit-limits)))
1809 ;; The line after the comment starter is inside the
1810 ;; comment, so we can use it.
1811 (setq prefix-line (point))
1812 ;; The comment is only one line. Take the comment prefix
1813 ;; from it and keep the indentation.
1814 (goto-char (car lit-limits))
1815 (if (looking-at prefix-regexp)
1816 (goto-char (match-end 0))
1817 (forward-char 2)
1818 (skip-chars-forward " \t"))
1819 (setq res
1820 (if (eq (c-point 'boi) (car lit-limits))
1821 ;; There is only whitespace before the comment
1822 ;; starter; take the prefix straight from this
1823 ;; line.
1824 (cons (buffer-substring-no-properties
1825 (c-point 'bol) (point))
1826 (current-column))
1827 ;; There is code before the comment starter, so we
1828 ;; have to temporarily insert and indent a new
1829 ;; line to get the right space/tab mix in the
1830 ;; indentation.
1831 (let ((buffer-modified (buffer-modified-p))
1832 (buffer-undo-list t)
1833 (prefix-len (- (point) (car lit-limits)))
1834 tmp)
1835 (unwind-protect
1836 (progn
1837 (goto-char (car lit-limits))
1838 (indent-to (prog1 (current-column)
1839 (insert ?\n)))
1840 (setq tmp (point))
1841 (forward-char prefix-len)
1842 (cons (buffer-substring-no-properties
1843 (c-point 'bol) (point))
1844 (current-column)))
1845 (delete-region (car lit-limits) tmp)
1846 (set-buffer-modified-p buffer-modified))))
1847 )))))
1848 (t
1849 (save-excursion
1850 (beginning-of-line)
1851 (if (and (> (point) (car lit-limits))
1852 (not (and (looking-at "[ \t]*\\*/")
1853 (eq (cdr lit-limits) (match-end 0)))))
1854 ;; The current line is not the comment starter and
1855 ;; contains more than just the ender, so it's good enough
1856 ;; to be used for the comment fill prefix.
1857 (setq prefix-line (point))
1858 (goto-char (car lit-limits))
1859 (if (or (/= (forward-line 1) 0)
1860 (>= (point) (cdr lit-limits))
1861 (and (looking-at "[ \t]*\\*/")
1862 (eq (cdr lit-limits) (match-end 0)))
1863 (and (looking-at prefix-regexp)
1864 (<= (1- (cdr lit-limits)) (match-end 0)))
1865 (and (< here (point))
1866 (or (not (match-beginning 0))
1867 (looking-at "[ \t]*$"))))
1868 ;; The comment is either one line or the next line
1869 ;; contains just the comment ender. Also, if point is
1870 ;; on the comment opener line and the following line is
1871 ;; empty or doesn't match c-comment-prefix-regexp we
1872 ;; assume that this is in fact a not yet closed one line
1873 ;; comment, so we shouldn't look for the comment prefix
1874 ;; on the next line. In these cases we have no
1875 ;; information about a suitable comment prefix, so we
1876 ;; resort to c-block-comment-prefix.
1877 (setq comment-prefix (or c-block-comment-prefix "")
1878 res (let ((buffer-modified (buffer-modified-p))
1879 (buffer-undo-list t)
1880 tmp-pre tmp-post)
1881 ;; The comment doesn't give any information
1882 ;; about the indentation column. We'll have to
1883 ;; temporarily insert a new comment line and
1884 ;; indent it to find the correct column.
1885 (unwind-protect
1886 (progn
1887 (goto-char (car lit-limits))
1888 (if (looking-at comment-start-regexp)
1889 (goto-char (match-end 0))
1890 (forward-char 2)
1891 (skip-chars-forward " \t"))
1892 (when (eq (char-syntax (char-before)) ?\ )
1893 ;; If there's ws on the current
1894 ;; line, we'll use it instead of
1895 ;; what's ending comment-prefix.
1896 (setq comment-prefix
1897 (concat (substring comment-prefix
1898 0 (string-match
1899 "\\s *\\'"
1900 comment-prefix))
1901 (buffer-substring-no-properties
1902 (save-excursion
1903 (skip-chars-backward " \t")
1904 (point))
1905 (point)))))
1906 (setq tmp-pre (point-marker))
1907 ;; We insert an extra non-whitespace
1908 ;; character before the line break and
1909 ;; after comment-prefix in case it's
1910 ;; "" or ends with whitespace.
1911 (insert "x\n" comment-prefix ?x)
1912 (setq tmp-post (point-marker))
1913 (c-indent-line)
1914 (goto-char (1- tmp-post))
1915 (cons (buffer-substring-no-properties
1916 (c-point 'bol) (point))
1917 (current-column)))
1918 (when tmp-post
1919 (delete-region tmp-pre tmp-post)
1920 (set-marker tmp-pre nil)
1921 (set-marker tmp-post nil))
1922 (set-buffer-modified-p buffer-modified))))
1923 ;; Otherwise the line after the comment starter is good
1924 ;; enough to find the prefix in.
1925 (setq prefix-line (point)))))))
1926 (or res
1927 (save-excursion
1928 ;; prefix-line is the bol of a line on which we should try
1929 ;; to find the prefix.
1930 (let* (fb-string fb-endpos ; Contains any fallback prefix found.
1931 (test-line
1932 (lambda ()
1933 (when (and (looking-at prefix-regexp)
1934 (< (match-end 0) (1- (cdr lit-limits))))
1935 (unless fb-string
1936 (setq fb-string (buffer-substring-no-properties
1937 (match-beginning 0) (match-end 0))
1938 fb-endpos (match-end 0)))
1939 (unless (eq (match-end 0) (c-point 'eol))
1940 (throw 'found t))
1941 t))))
1942 (if (catch 'found
1943 ;; Search for a line which has text after the prefix
1944 ;; so that we get the proper amount of whitespace
1945 ;; after it. We start with the current line, then
1946 ;; search backwards, then forwards.
1947 (goto-char prefix-line)
1948 (when (and (funcall test-line)
1949 (/= (match-end 1) (match-end 0)))
1950 ;; If the current line doesn't have text but do
1951 ;; have whitespace after the prefix, we'll use it.
1952 (throw 'found t))
1953 (while (and (zerop (forward-line -1))
1954 (> (point) (car lit-limits)))
1955 (funcall test-line))
1956 (goto-char prefix-line)
1957 (while (and (zerop (forward-line 1))
1958 (< (point) (cdr lit-limits)))
1959 (funcall test-line))
1960 nil)
1961 ;; A good line with text after the prefix was found.
1962 (cons (buffer-substring-no-properties (point) (match-end 0))
1963 (progn (goto-char (match-end 0)) (current-column)))
1964 (if fb-string
1965 ;; A good line wasn't found, but at least we have a
1966 ;; fallback that matches the comment prefix regexp.
1967 (cond ((string-match "\\s \\'" fb-string)
1968 ;; There are ws after the prefix, so let's use it.
1969 (cons fb-string
1970 (progn (goto-char fb-endpos) (current-column))))
1971 ((progn
1972 ;; Check if there's any whitespace padding
1973 ;; on the comment start line that we can
1974 ;; use after the prefix.
1975 (goto-char (car lit-limits))
1976 (if (looking-at comment-start-regexp)
1977 (goto-char (match-end 0))
1978 (forward-char 2)
1979 (skip-chars-forward " \t"))
1980 (eq (char-syntax (char-before)) ?\ ))
1981 (setq fb-string (buffer-substring-no-properties
1982 (save-excursion
1983 (skip-chars-backward " \t")
1984 (point))
1985 (point)))
1986 (goto-char fb-endpos)
1987 (skip-chars-backward " \t")
1988 (let ((buffer-modified (buffer-modified-p))
1989 (buffer-undo-list t)
1990 (tmp (point)))
1991 ;; Got to mess in the buffer once again to
1992 ;; ensure the column gets correct. :P
1993 (unwind-protect
1994 (progn
1995 (insert fb-string)
1996 (cons (buffer-substring-no-properties
1997 (c-point 'bol)
1998 (point))
1999 (current-column)))
2000 (delete-region tmp (point)))))
2001 (t
2002 ;; Last resort: Just add a single space after
2003 ;; the prefix.
2004 (cons (concat fb-string " ")
2005 (progn (goto-char fb-endpos)
2006 (1+ (current-column))))))
2007 ;; The line doesn't match the comment prefix regexp.
2008 (if comment-prefix
2009 ;; We have a fallback for line comments that we must use.
2010 (cons (concat (buffer-substring-no-properties
2011 prefix-line (c-point 'boi))
2012 comment-prefix)
2013 (progn (back-to-indentation)
2014 (+ (current-column) (length comment-prefix))))
2015 ;; Assume we are dealing with a "free text" block
2016 ;; comment where the lines doesn't have any comment
2017 ;; prefix at all and we should just fill it as
2018 ;; normal text.
2019 '("" . 0)))))))
2020 ))
2021
785eecbb
RS
2022(defun c-fill-paragraph (&optional arg)
2023 "Like \\[fill-paragraph] but handles C and C++ style comments.
51f606de
GM
2024If any of the current line is a comment or within a comment, fill the
2025comment or the paragraph of it that point is in, preserving the
2026comment indentation or line-starting decorations (see the
2027`c-comment-prefix-regexp' and `c-block-comment-prefix' variables for
2028details).
785eecbb 2029
f23da29a
RS
2030If point is inside multiline string literal, fill it. This currently
2031does not respect escaped newlines, except for the special case when it
2032is the very first thing in the string. The intended use for this rule
2033is in situations like the following:
2034
2035char description[] = \"\\
2036A very long description of something that you want to fill to make
2037nicely formatted output.\"\;
2038
2039If point is in any other situation, i.e. in normal code, do nothing.
2040
785eecbb 2041Optional prefix ARG means justify paragraph as well."
28c236de 2042 (interactive "*P")
51f606de
GM
2043 (let (lit-limits lit-type fill
2044 ;; beg and end limits the region to be filled. end is a marker.
2045 beg end
2046 ;; tmp-pre and tmp-post marks strings that are temporarily
2047 ;; inserted at the start and end of the region. tmp-pre is a
2048 ;; cons of the positions of the prepended string. tmp-post is
2049 ;; a marker pointing to the single character of the appended
2050 ;; string.
2051 tmp-pre tmp-post
2052 hang-ender-stuck)
2053 ;; Restore point on undo. It's necessary since we do a lot of
2054 ;; hidden inserts and deletes below that should be as transparent
2055 ;; as possible.
2056 (if (and buffer-undo-list (not (eq buffer-undo-list t)))
2057 (setq buffer-undo-list (cons (point) buffer-undo-list)))
2058 (save-excursion
2059 (save-restriction
2060 ;; Widen to catch comment limits correctly.
2061 (widen)
2062 (setq lit-limits (c-collect-line-comments (c-literal-limits nil t))
2063 lit-type (c-literal-type lit-limits)))
2064 (forward-paragraph)
2065 (setq end (point-marker))
2066 (backward-paragraph)
2067 (setq beg (point)))
2068 (when (and (>= (point) beg) (<= (point) end))
2069 (unwind-protect
2070 (progn
2071 (cond
2072 ((eq lit-type 'c++) ; Line comment.
f23da29a 2073 (save-excursion
51f606de
GM
2074 ;; Fill to the comment or paragraph end, whichever
2075 ;; comes first.
2076 (set-marker end (min end (cdr lit-limits)))
2077 (when (<= beg (car lit-limits))
2078 ;; The region to be filled includes the comment
2079 ;; starter, so we must check it.
2080 (goto-char (car lit-limits))
2081 (back-to-indentation)
2082 (if (eq (point) (car lit-limits))
2083 ;; Include the first line in the fill.
2084 (setq beg (c-point 'bol))
2085 ;; The first line contains code before the
2086 ;; comment. We must fake a line that doesn't.
2087 (setq tmp-pre t)))
2088 ))
2089 ((eq lit-type 'c) ; Block comment.
785eecbb 2090 (save-excursion
51f606de
GM
2091 (when (>= end (cdr lit-limits))
2092 ;; The region to be filled includes the comment ender.
2093 (goto-char (cdr lit-limits))
2094 (beginning-of-line)
2095 (if (and (looking-at (concat "[ \t]*\\("
2096 c-comment-prefix-regexp
2097 "\\)\\*/"))
2098 (eq (cdr lit-limits) (match-end 0)))
2099 ;; Leave the comment ender on its own line.
2100 (set-marker end (point))
2101 ;; The comment ender should hang. Replace all
2102 ;; cruft between it and the last word with a 'x'
2103 ;; and include it in the fill. We'll change it
2104 ;; back to a space afterwards.
2105 (let ((ender-start (progn
2106 (goto-char (cdr lit-limits))
2107 (skip-syntax-backward "^w ")
bcf90db9
GM
2108 (point)))
2109 spaces)
51f606de
GM
2110 (goto-char (cdr lit-limits))
2111 (setq tmp-post (point-marker))
2112 (insert ?\n)
2113 (set-marker end (point))
785eecbb 2114 (forward-line -1)
bcf90db9 2115 (if (and (looking-at (concat "[ \t]*\\(\\("
51f606de 2116 c-comment-prefix-regexp
bcf90db9 2117 "\\)[ \t]*\\)"))
51f606de
GM
2118 (eq ender-start (match-end 0)))
2119 ;; The comment ender is prefixed by nothing
2120 ;; but a comment line prefix. Remove it
2121 ;; along with surrounding ws.
bcf90db9 2122 (setq spaces (- (match-end 1) (match-end 2)))
51f606de 2123 (goto-char ender-start))
bcf90db9 2124 (skip-chars-backward " \t\r\n")
51f606de 2125 (when (/= (point) ender-start)
bcf90db9
GM
2126 ;; Keep one or two spaces between the text and
2127 ;; the ender, depending on how many there are now.
2128 (unless spaces (setq spaces (- ender-start (point))))
2129 (setq spaces (max (min spaces 2) 1))
2130 ; Insert the filler first to keep marks right.
2131 (insert (make-string spaces ?x))
2132 (delete-region (point) (+ ender-start spaces))
2133 (setq hang-ender-stuck spaces)))))
51f606de
GM
2134 (when (<= beg (car lit-limits))
2135 ;; The region to be filled includes the comment starter.
2136 (goto-char (car lit-limits))
2137 (if (looking-at (concat "\\(" comment-start-skip "\\)$"))
2138 ;; Begin filling with the next line.
2139 (setq beg (c-point 'bonl))
2140 ;; Fake the fill prefix in the first line.
2141 (setq tmp-pre t)))
2142 ))
2143 ((eq lit-type 'string) ; String.
2144 (save-excursion
2145 (when (>= end (cdr lit-limits))
2146 (goto-char (1- (cdr lit-limits)))
2147 (setq tmp-post (point-marker))
2148 (insert ?\n)
2149 (set-marker end (point)))
2150 (when (<= beg (car lit-limits))
2151 (goto-char (1+ (car lit-limits)))
2152 (setq beg (if (looking-at "\\\\$")
2153 ;; Leave the start line if it's
2154 ;; nothing but an escaped newline.
2155 (1+ (match-end 0))
2156 (point))))))
2157 (t (setq beg nil)))
2158 (when tmp-pre
2159 ;; Temporarily insert the fill prefix after the comment
2160 ;; starter so that the first line looks like any other
2161 ;; comment line in the narrowed region.
2162 (setq fill (c-guess-fill-prefix lit-limits lit-type))
2163 (unless (string-match (concat "\\`[ \t]*\\("
2164 c-comment-prefix-regexp
2165 "\\)[ \t]*\\'")
2166 (car fill))
2167 ;; Oops, the prefix doesn't match the comment prefix
2168 ;; regexp. This could produce very confusing
2169 ;; results with adaptive fill packages together with
2170 ;; the insert prefix magic below, since the prefix
2171 ;; often doesn't appear at all. So let's warn about
2172 ;; it.
2173 (message "\
2174Warning: `c-comment-prefix-regexp' doesn't match the comment prefix %S"
2175 (car fill)))
2176 ;; Find the right spot on the line, break it, insert
2177 ;; the fill prefix and make sure we're back in the
2178 ;; same column by temporarily prefixing the first word
2179 ;; with a number of 'x'.
2180 (save-excursion
2181 (goto-char (car lit-limits))
2182 (if (looking-at (if (eq lit-type 'c++)
2183 c-comment-prefix-regexp
2184 comment-start-skip))
2185 (goto-char (match-end 0))
2186 (forward-char 2)
2187 (skip-chars-forward " \t"))
2188 (while (< (current-column) (cdr fill)) (forward-char 1))
2189 (let ((col (current-column)))
2190 (setq beg (1+ (point))
2191 tmp-pre (list (point)))
2192 (unwind-protect
2193 (progn
2194 (insert ?\n (car fill))
2195 (insert (make-string (- col (current-column)) ?x)))
2196 (setcdr tmp-pre (point))))))
2197 (when beg
2198 (let ((fill-paragraph-function
2199 ;; Avoid infinite recursion.
2200 (if (not (eq fill-paragraph-function 'c-fill-paragraph))
2201 fill-paragraph-function))
2202 (fill-prefix
2203 (or fill-prefix
2204 (when (and (eq lit-type 'c++)
2205 (not (string-match
2206 "\\`[ \t]*//"
2207 (or (fill-context-prefix beg end)
2208 ""))))
2209 ;; Kludge: If the function that adapts the
2210 ;; fill prefix doesn't produce the required
2211 ;; comment starter for line comments, then
2212 ;; force it by setting fill-prefix.
2213 (car (or fill (c-guess-fill-prefix
2214 lit-limits lit-type)))))))
2215 ;; Preparations finally done! Now we can call the
2216 ;; real fill function.
2217 (save-restriction
2218 (narrow-to-region beg end)
2219 (fill-paragraph arg)))))
2220 (when (consp tmp-pre)
2221 (delete-region (car tmp-pre) (cdr tmp-pre)))
2222 (when tmp-post
2223 (save-excursion
2224 (goto-char tmp-post)
2225 (delete-char 1)
2226 (when hang-ender-stuck
2227 (skip-syntax-backward "^w ")
bcf90db9
GM
2228 (forward-char (- hang-ender-stuck))
2229 (insert (make-string hang-ender-stuck ?\ ))
2230 (delete-char hang-ender-stuck))
51f606de
GM
2231 (set-marker tmp-post nil)))))
2232 (set-marker end nil))
2233 ;; Always return t. This has the effect that if filling isn't done
2234 ;; above, it isn't done at all, and it's therefore effectively
2235 ;; disabled in normal code.
2236 t)
2237
2238(defun c-do-auto-fill ()
2239 ;; Do automatic filling if not inside a context where it should be
2240 ;; ignored.
2241 (let ((c-auto-fill-prefix
2242 ;; The decision whether the line should be broken is actually
2243 ;; done in c-indent-new-comment-line, which do-auto-fill
2244 ;; calls to break lines. We just set this special variable
2245 ;; so that we'll know when we're called from there. It's
2246 ;; also used to detect whether fill-prefix is user set or
2247 ;; generated automatically by do-auto-fill.
2248 fill-prefix))
2249 (do-auto-fill)))
2250
2251(defun c-indent-new-comment-line (&optional soft)
2252 "Break line at point and indent, continuing comment if within one.
2253If inside a comment and `comment-multi-line' is non-nil, the
2254indentation and line prefix are preserved (see the
2255`c-comment-prefix-regexp' and `c-block-comment-prefix' variables for
b8ded794
GM
2256details). If inside a single line comment and `comment-multi-line' is
2257nil, a new comment of the same type is started on the next line and
2258indented as appropriate for comments.
51f606de
GM
2259
2260If a fill prefix is specified, it overrides all the above."
2261 (interactive)
2262 (let ((fill-prefix fill-prefix)
2263 (do-line-break
2264 (lambda ()
2265 (delete-region (progn (skip-chars-backward " \t") (point))
2266 (progn (skip-chars-forward " \t") (point)))
2267 (if soft (insert-and-inherit ?\n) (newline 1))))
2268 ;; Already know the literal type and limits when called from
2269 ;; c-context-line-break.
2270 (c-lit-limits (if (boundp 'c-lit-limits) c-lit-limits))
2271 (c-lit-type (if (boundp 'c-lit-type) c-lit-type)))
2272 (when (boundp 'c-auto-fill-prefix)
2273 ;; Called from do-auto-fill.
2274 (unless c-lit-limits
2275 (setq c-lit-limits (c-literal-limits nil nil t)))
2276 (unless c-lit-type
2277 (setq c-lit-type (c-literal-type c-lit-limits)))
2278 (if (memq (cond ((eq c-lit-type 'pound)
2279 ;; Come to think about it, "pound" is a bit
2280 ;; of a misnomer, so call it "cpp" instead
2281 ;; in user interaction.
2282 'cpp)
2283 ((null c-lit-type) 'code)
2284 (t c-lit-type))
2285 c-ignore-auto-fill)
2286 (setq fill-prefix t) ; Used as flag in the cond.
b8ded794
GM
2287 (if (and (null c-auto-fill-prefix)
2288 (eq c-lit-type 'c)
2289 (<= (c-point 'bol) (car c-lit-limits)))
2290 ;; The adaptive fill function has generated a prefix, but
2291 ;; we're on the first line in a block comment so it'll be
2292 ;; wrong. Ignore it to guess a better one below.
2293 (setq fill-prefix nil)
2294 (when (and (eq c-lit-type 'c++)
2295 (not (string-match "\\`[ \t]*//" (or fill-prefix ""))))
2296 ;; Kludge: If the function that adapted the fill prefix
2297 ;; doesn't produce the required comment starter for line
2298 ;; comments, then we ignore it.
2299 (setq fill-prefix nil)))
2300 ))
51f606de
GM
2301 (cond ((eq fill-prefix t)
2302 ;; A call from do-auto-fill which should be ignored.
2303 )
2304 (fill-prefix
2305 ;; A fill-prefix overrides anything.
2306 (funcall do-line-break)
2307 (insert-and-inherit fill-prefix))
2308 ((progn
2309 (unless c-lit-limits
2310 (setq c-lit-limits (c-literal-limits nil nil t)))
2311 (unless c-lit-type
2312 (setq c-lit-type (c-literal-type c-lit-limits)))
2313 (memq c-lit-type '(c c++)))
b8ded794
GM
2314 (if (or comment-multi-line
2315 (save-excursion
2316 (goto-char (car c-lit-limits))
2317 (end-of-line)
2318 (< (point) (cdr c-lit-limits))))
51f606de
GM
2319 ;; Inside a comment that should be continued.
2320 (let ((fill (c-guess-fill-prefix
2321 (setq c-lit-limits
2322 (c-collect-line-comments c-lit-limits))
2323 c-lit-type))
2324 (pos (point)))
2325 (if (save-excursion
2326 (back-to-indentation)
2327 (> (point) (car c-lit-limits))
2328 (looking-at c-comment-prefix-regexp))
2329 (progn
2330 ;; Skip forward past the fill prefix in case
2331 ;; we're standing in it.
2332 (while (and (< (current-column) (cdr fill))
2333 (not (eolp)))
2334 (forward-char 1))
2335 (if (> (point) (if (and (eq c-lit-type 'c)
2336 (save-excursion
2337 (forward-char -2)
2338 (looking-at "\\*/")))
2339 (- (cdr c-lit-limits) 2)
2340 (cdr c-lit-limits)))
2341 (progn
2342 ;; The skip takes us out of the comment;
2343 ;; insert the fill prefix at bol instead
2344 ;; and keep the position.
2345 (setq pos (copy-marker pos t))
2346 (beginning-of-line)
2347 (insert-and-inherit (car fill))
2348 (if soft (insert-and-inherit ?\n) (newline 1))
2349 (goto-char pos)
2350 (set-marker pos nil))
2351 (funcall do-line-break)
2352 (insert-and-inherit (car fill))))
2353 (funcall do-line-break)
2354 (insert-and-inherit (car fill))))
2355 ;; Inside a comment that should be broken.
2356 (let ((comment-start comment-start)
2357 (comment-end comment-end)
2358 col)
2359 (if (eq c-lit-type 'c)
2360 (unless (string-match "[ \t]*/\\*" comment-start)
2361 (setq comment-start "/* " comment-end " */"))
2362 (unless (string-match "[ \t]*//" comment-start)
2363 (setq comment-start "// " comment-end "")))
2364 (setq col (save-excursion
2365 (back-to-indentation)
2366 (current-column)))
2367 (funcall do-line-break)
2368 (when (and comment-end (not (equal comment-end "")))
2369 (forward-char -1)
2370 (insert-and-inherit comment-end)
2371 (forward-char 1))
2372 ;; c-comment-indent may look at the current
2373 ;; indentation, so let's start out with the same
2374 ;; indentation as the previous one.
2375 (indent-to col)
2376 (insert-and-inherit comment-start)
2377 (indent-for-comment))))
2378 (t
2379 ;; Somewhere else in the code.
2380 (let ((col (save-excursion
2381 (while (progn (back-to-indentation)
2382 (and (looking-at "^\\s *$")
2383 (= (forward-line -1) 0))))
2384 (current-column))))
2385 (funcall do-line-break)
2386 (indent-to col))))))
2387
2388(defalias 'c-comment-line-break-function 'c-indent-new-comment-line)
2389(make-obsolete 'c-comment-line-break-function 'c-indent-new-comment-line)
2390
2391;; advice for indent-new-comment-line for older Emacsen
2392(unless (boundp 'comment-line-break-function)
2393 (defadvice indent-new-comment-line (around c-line-break-advice
2394 activate preactivate)
2395 "Call `c-indent-new-comment-line' if in CC Mode."
2396 (if (or (boundp 'c-inside-line-break-advice)
2397 (not c-buffer-is-cc-mode))
2398 ad-do-it
2399 (let (c-inside-line-break-advice)
2400 (c-indent-new-comment-line (ad-get-arg 0))))))
2401
2402(defun c-context-line-break ()
2403 "Do a line break suitable to the context.
2404
2405When point is outside a comment, insert a newline and indent according
2406to the syntactic context.
2407
2408When point is inside a comment, continue it with the appropriate
2409comment prefix (see the `c-comment-prefix-regexp' and
2410`c-block-comment-prefix' variables for details). The end of a
2411C++-style line comment doesn't count as inside the comment, though."
2412 (interactive "*")
2413 (let* ((c-lit-limits (c-literal-limits nil nil t))
2414 (c-lit-type (c-literal-type c-lit-limits)))
2415 (if (or (eq c-lit-type 'c)
2416 (and (eq c-lit-type 'c++)
2417 (< (point)
2418 (1- (cdr (setq c-lit-limits
2419 (c-collect-line-comments c-lit-limits)))))))
2420 (let ((comment-multi-line t)
2421 (fill-prefix nil))
2422 (c-indent-new-comment-line))
2423 (delete-region (point) (progn (skip-chars-backward " \t") (point)))
2424 (newline)
2425 ;; c-indent-line may look at the current indentation, so let's
2426 ;; start out with the same indentation as the previous line.
2427 (let ((col (save-excursion
2428 (forward-line -1)
2429 (while (progn (back-to-indentation)
2430 (and (looking-at "^\\s *$")
2431 (= (forward-line -1) 0))))
2432 (current-column))))
2433 (indent-to col))
2434 (c-indent-line))))
785eecbb
RS
2435
2436\f
2437(provide 'cc-cmds)
2438;;; cc-cmds.el ends here