]> code.delx.au - gnu-emacs/blob - lisp/progmodes/cc-cmds.el
(objc-mode): Bind imenu-create-index-function
[gnu-emacs] / lisp / progmodes / cc-cmds.el
1 ;;; cc-cmds.el --- user level commands for CC Mode
2
3 ;; Copyright (C) 1985,87,92,93,94,95,96,97 Free Software Foundation, Inc.
4
5 ;; Authors: 1992-1997 Barry A. Warsaw
6 ;; 1987 Dave Detlefs and Stewart Clamen
7 ;; 1985 Richard M. Stallman
8 ;; Maintainer: cc-mode-help@python.org
9 ;; Created: 22-Apr-1997 (split from cc-mode.el)
10 ;; Version: 5.17
11 ;; Keywords: c languages oop
12
13 ;; This file is part of GNU Emacs.
14
15 ;; GNU Emacs is free software; you can redistribute it and/or modify
16 ;; it under the terms of the GNU General Public License as published by
17 ;; the Free Software Foundation; either version 2, or (at your option)
18 ;; any later version.
19
20 ;; GNU Emacs is distributed in the hope that it will be useful,
21 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
22 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 ;; GNU General Public License for more details.
24
25 ;; You should have received a copy of the GNU General Public License
26 ;; along with GNU Emacs; see the file COPYING. If not, write to the
27 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
28 ;; Boston, MA 02111-1307, USA.
29
30 (eval-when-compile
31 (require 'cc-defs))
32
33 \f
34 (defun c-calculate-state (arg prevstate)
35 ;; Calculate the new state of PREVSTATE, t or nil, based on arg. If
36 ;; arg is nil or zero, toggle the state. If arg is negative, turn
37 ;; the state off, and if arg is positive, turn the state on
38 (if (or (not arg)
39 (zerop (setq arg (prefix-numeric-value arg))))
40 (not prevstate)
41 (> arg 0)))
42
43 ;; Auto-newline and hungry-delete
44 (defun c-toggle-auto-state (arg)
45 "Toggle auto-newline feature.
46 Optional numeric ARG, if supplied turns on auto-newline when positive,
47 turns it off when negative, and just toggles it when zero.
48
49 When the auto-newline feature is enabled (as evidenced by the `/a' or
50 `/ah' on the modeline after the mode name) newlines are automatically
51 inserted after special characters such as brace, comma, semi-colon,
52 and colon."
53 (interactive "P")
54 (setq c-auto-newline (c-calculate-state arg c-auto-newline))
55 (c-update-modeline)
56 (c-keep-region-active))
57
58 (defun c-toggle-hungry-state (arg)
59 "Toggle hungry-delete-key feature.
60 Optional numeric ARG, if supplied turns on hungry-delete when positive,
61 turns it off when negative, and just toggles it when zero.
62
63 When the hungry-delete-key feature is enabled (as evidenced by the
64 `/h' or `/ah' on the modeline after the mode name) the delete key
65 gobbles all preceding whitespace in one fell swoop."
66 (interactive "P")
67 (setq c-hungry-delete-key (c-calculate-state arg c-hungry-delete-key))
68 (c-update-modeline)
69 (c-keep-region-active))
70
71 (defun c-toggle-auto-hungry-state (arg)
72 "Toggle auto-newline and hungry-delete-key features.
73 Optional numeric ARG, if supplied turns on auto-newline and
74 hungry-delete when positive, turns them off when negative, and just
75 toggles them when zero.
76
77 See `c-toggle-auto-state' and `c-toggle-hungry-state' for details."
78 (interactive "P")
79 (setq c-auto-newline (c-calculate-state arg c-auto-newline))
80 (setq c-hungry-delete-key (c-calculate-state arg c-hungry-delete-key))
81 (c-update-modeline)
82 (c-keep-region-active))
83
84 \f
85 ;; Electric keys
86
87 ;; Note: In XEmacs 20.3 the Delete and BackSpace keysyms have been
88 ;; separated and "\177" is no longer an alias for both keys. Also,
89 ;; the variable delete-key-deletes-forward controls in which direction
90 ;; the Delete keysym deletes characters. The functions
91 ;; c-electric-delete and c-electric-backspace attempt to deal with
92 ;; this new functionality. For Emacs 19 and XEmacs 19 backwards
93 ;; compatibility, the old behavior has moved to c-electric-backspace
94 ;; and c-backspace-function.
95
96 (defun c-electric-backspace (arg)
97 "Deletes preceding character or whitespace.
98 If `c-hungry-delete-key' is non-nil, as evidenced by the \"/h\" or
99 \"/ah\" string on the mode line, then all preceding whitespace is
100 consumed. If however an ARG is supplied, or `c-hungry-delete-key' is
101 nil, or point is inside a literal then the function in the variable
102 `c-backspace-function' is called.
103
104 See also \\[c-electric-delete]."
105 (interactive "P")
106 (if (or (not c-hungry-delete-key)
107 arg
108 (c-in-literal))
109 (funcall c-backspace-function (prefix-numeric-value arg))
110 (let ((here (point)))
111 (skip-chars-backward " \t\n")
112 (if (/= (point) here)
113 (delete-region (point) here)
114 (funcall c-backspace-function 1)
115 ))))
116
117 (defun c-electric-delete (arg)
118 "Deletes preceding or following character or whitespace.
119
120 The behavior of this function depends on the variable
121 `delete-key-deletes-forward'. If this variable is nil (or does not
122 exist, as in older Emacsen), then this function behaves identical to
123 \\[c-electric-backspace].
124
125 If `delete-key-deletes-forward' is non-nil, then deletion occurs in
126 the forward direction. So if `c-hungry-delete-key' is non-nil, as
127 evidenced by the \"/h\" or \"/ah\" string on the mode line, then all
128 following whitespace is consumed. If however an ARG is supplied, or
129 `c-hungry-delete-key' is nil, or point is inside a literal then the
130 function in the variable `c-delete-function' is called."
131 (interactive "P")
132 (if (and (boundp 'delete-key-deletes-forward)
133 delete-key-deletes-forward)
134 (if (or (not c-hungry-delete-key)
135 arg
136 (c-in-literal))
137 (funcall c-delete-function (prefix-numeric-value arg))
138 (let ((here (point)))
139 (skip-chars-forward " \t\n")
140 (if (/= (point) here)
141 (delete-region (point) here)
142 (funcall c-delete-function 1))))
143 ;; act just like c-electric-backspace
144 (c-electric-backspace arg)))
145
146 (defun c-electric-pound (arg)
147 "Electric pound (`#') insertion.
148 Inserts a `#' character specially depending on the variable
149 `c-electric-pound-behavior'. If a numeric ARG is supplied, or if
150 point is inside a literal, nothing special happens."
151 (interactive "P")
152 (if (or (c-in-literal)
153 arg
154 (not (memq 'alignleft c-electric-pound-behavior)))
155 ;; do nothing special
156 (self-insert-command (prefix-numeric-value arg))
157 ;; place the pound character at the left edge
158 (let ((pos (- (point-max) (point)))
159 (bolp (bolp)))
160 (beginning-of-line)
161 (delete-horizontal-space)
162 (insert-char last-command-char 1)
163 (and (not bolp)
164 (goto-char (- (point-max) pos)))
165 )))
166
167 (defun c-electric-brace (arg)
168 "Insert a brace.
169
170 If the auto-newline feature is turned on, as evidenced by the \"/a\"
171 or \"/ah\" string on the mode line, newlines are inserted before and
172 after braces based on the value of `c-hanging-braces-alist'.
173
174 Also, the line is re-indented unless a numeric ARG is supplied, there
175 are non-whitespace characters present on the line after the brace, or
176 the brace is inserted inside a literal."
177 (interactive "P")
178 (let* ((c-state-cache (c-parse-state))
179 (safepos (c-safe-position (point) c-state-cache))
180 (literal (c-in-literal safepos)))
181 ;; if we're in a literal, or we're not at the end of the line, or
182 ;; a numeric arg is provided, or auto-newlining is turned off,
183 ;; then just insert the character.
184 (if (or literal arg
185 ; (not c-auto-newline)
186 (not (looking-at "[ \t]*$")))
187 (self-insert-command (prefix-numeric-value arg))
188 (let* ((syms '(class-open class-close defun-open defun-close
189 inline-open inline-close brace-list-open brace-list-close
190 brace-list-intro brace-list-entry block-open block-close
191 substatement-open statement-case-open
192 extern-lang-open extern-lang-close))
193 ;; we want to inhibit blinking the paren since this will
194 ;; be most disruptive. we'll blink it ourselves later on
195 (old-blink-paren blink-paren-function)
196 blink-paren-function
197 (insertion-point (point))
198 delete-temp-newline
199 (preserve-p (and (not (bobp))
200 (eq ?\ (char-syntax (char-before)))))
201 ;; shut this up too
202 (c-echo-syntactic-information-p nil)
203 (syntax (progn
204 ;; only insert a newline if there is
205 ;; non-whitespace behind us
206 (if (save-excursion
207 (skip-chars-backward " \t")
208 (not (bolp)))
209 (progn (newline)
210 (setq delete-temp-newline t)))
211 (self-insert-command (prefix-numeric-value arg))
212 ;; state cache doesn't change
213 (c-guess-basic-syntax)))
214 (newlines (and
215 c-auto-newline
216 (or (c-lookup-lists syms syntax c-hanging-braces-alist)
217 '(ignore before after)))))
218 ;; If syntax is a function symbol, then call it using the
219 ;; defined semantics.
220 (if (and (not (consp (cdr newlines)))
221 (functionp (cdr newlines)))
222 (let ((c-syntactic-context syntax))
223 (setq newlines
224 (funcall (cdr newlines) (car newlines) insertion-point))))
225 ;; does a newline go before the open brace?
226 (if (memq 'before newlines)
227 ;; we leave the newline we've put in there before,
228 ;; but we need to re-indent the line above
229 (let ((pos (- (point-max) (point)))
230 (here (point))
231 (c-state-cache c-state-cache))
232 (forward-line -1)
233 ;; we may need to update the cache. this should still be
234 ;; faster than recalculating the state in many cases
235 (save-excursion
236 (save-restriction
237 (narrow-to-region here (point))
238 (if (and (c-safe (progn (backward-up-list -1) t))
239 (memq (char-before) '(?\) ?}))
240 (progn (widen)
241 (c-safe (progn (forward-sexp -1) t))))
242 (setq c-state-cache
243 (c-hack-state (point) 'open c-state-cache))
244 (if (and (car c-state-cache)
245 (not (consp (car c-state-cache)))
246 (<= (point) (car c-state-cache)))
247 (setq c-state-cache (cdr c-state-cache))
248 ))))
249 (let ((here (point))
250 (shift (c-indent-line)))
251 (setq c-state-cache (c-adjust-state (c-point 'bol) here
252 (- shift) c-state-cache)))
253 (goto-char (- (point-max) pos))
254 ;; if the buffer has changed due to the indentation, we
255 ;; need to recalculate syntax for the current line, but
256 ;; we won't need to update the state cache.
257 (if (/= (point) here)
258 (setq syntax (c-guess-basic-syntax))))
259 ;; must remove the newline we just stuck in (if we really did it)
260 (and delete-temp-newline
261 (save-excursion
262 ;; if there is whitespace before point, then preserve
263 ;; at least one space.
264 (delete-indentation)
265 (just-one-space)
266 (if (not preserve-p)
267 (delete-char -1))))
268 ;; since we're hanging the brace, we need to recalculate
269 ;; syntax. Update the state to accurately reflect the
270 ;; beginning of the line. We punt if we cross any open or
271 ;; closed parens because its just too hard to modify the
272 ;; known state. This limitation will be fixed in v5.
273 (save-excursion
274 (let ((bol (c-point 'bol)))
275 (if (zerop (car (parse-partial-sexp bol (1- (point)))))
276 (setq c-state-cache (c-whack-state bol c-state-cache)
277 syntax (c-guess-basic-syntax))
278 ;; gotta punt. this requires some horrible kludgery
279 (beginning-of-line)
280 (makunbound 'c-state-cache)
281 (setq c-state-cache (c-parse-state)
282 syntax nil))))
283 )
284 ;; now adjust the line's indentation. don't update the state
285 ;; cache since c-guess-basic-syntax isn't called when the
286 ;; syntax is passed to c-indent-line
287 (let ((here (point))
288 (shift (c-indent-line syntax)))
289 (setq c-state-cache (c-adjust-state (c-point 'bol) here
290 (- shift) c-state-cache)))
291 ;; Do all appropriate clean ups
292 (let ((here (point))
293 (pos (- (point-max) (point)))
294 mbeg mend)
295 ;; clean up empty defun braces
296 (if (and c-auto-newline
297 (memq 'empty-defun-braces c-cleanup-list)
298 (eq last-command-char ?\})
299 (c-intersect-lists '(defun-close class-close inline-close)
300 syntax)
301 (progn
302 (forward-char -1)
303 (skip-chars-backward " \t\n")
304 (eq (char-before) ?\{))
305 ;; make sure matching open brace isn't in a comment
306 (not (c-in-literal)))
307 (delete-region (point) (1- here)))
308 ;; clean up brace-else-brace
309 (if (and c-auto-newline
310 (memq 'brace-else-brace c-cleanup-list)
311 (eq last-command-char ?\{)
312 (re-search-backward "}[ \t\n]*else[ \t\n]*{" nil t)
313 (progn
314 (setq mbeg (match-beginning 0)
315 mend (match-end 0))
316 (= mend here))
317 (not (c-in-literal)))
318 (progn
319 (delete-region mbeg mend)
320 (insert "} else {")))
321 ;; clean up brace-elseif-brace
322 (if (and c-auto-newline
323 (memq 'brace-elseif-brace c-cleanup-list)
324 (eq last-command-char ?\{)
325 (re-search-backward "}[ \t\n]*else[ \t\n]+if[ \t\n]*" nil t)
326 (save-excursion
327 (goto-char (match-end 0))
328 (c-safe (forward-sexp 1))
329 (skip-chars-forward " \t\n")
330 (setq mbeg (match-beginning 0)
331 mend (match-end 0))
332 (= here (1+ (point))))
333 (not (c-in-literal)))
334 (progn
335 (delete-region mbeg mend)
336 (insert "} else if ")))
337 (goto-char (- (point-max) pos))
338 )
339 ;; does a newline go after the brace?
340 (if (memq 'after newlines)
341 (progn
342 (newline)
343 ;; update on c-state-cache
344 (let* ((bufpos (- (point) 2))
345 (which (if (eq (char-after bufpos) ?{) 'open 'close))
346 (c-state-cache (c-hack-state bufpos which c-state-cache)))
347 (c-indent-line))))
348 ;; blink the paren
349 (and (eq last-command-char ?\})
350 old-blink-paren
351 (save-excursion
352 (c-backward-syntactic-ws safepos)
353 (funcall old-blink-paren)))
354 ))))
355
356 (defun c-electric-slash (arg)
357 "Insert a slash character.
358
359 Indent the line as a comment, if:
360
361 1. The slash is second of a `//' line oriented comment introducing
362 token and we are on a comment-only-line, or
363
364 2. The slash is part of a `*/' token that closes a block oriented
365 comment.
366
367 If numeric ARG is supplied or point is inside a literal, indentation
368 is inhibited."
369 (interactive "P")
370 (let* ((ch (char-before))
371 (indentp (and (not arg)
372 (eq last-command-char ?/)
373 (or (and (eq ch ?/)
374 (not (c-in-literal)))
375 (and (eq ch ?*)
376 (c-in-literal)))
377 ))
378 ;; shut this up
379 (c-echo-syntactic-information-p nil))
380 (self-insert-command (prefix-numeric-value arg))
381 (if indentp
382 (c-indent-line))))
383
384 (defun c-electric-star (arg)
385 "Insert a star character.
386 If the star is the second character of a C style comment introducing
387 construct, and we are on a comment-only-line, indent line as comment.
388 If numeric ARG is supplied or point is inside a literal, indentation
389 is inhibited."
390 (interactive "P")
391 (self-insert-command (prefix-numeric-value arg))
392 ;; if we are in a literal, or if arg is given do not re-indent the
393 ;; current line, unless this star introduces a comment-only line.
394 (if (and (not arg)
395 (memq (c-in-literal) '(c))
396 (eq (char-before) ?*)
397 (save-excursion
398 (forward-char -1)
399 (skip-chars-backward "*")
400 (if (eq (char-before) ?/)
401 (forward-char -1))
402 (skip-chars-backward " \t")
403 (bolp)))
404 ;; shut this up
405 (let (c-echo-syntactic-information-p)
406 (c-indent-line))
407 ))
408
409 (defun c-electric-semi&comma (arg)
410 "Insert a comma or semicolon.
411 When the auto-newline feature is turned on, as evidenced by the \"/a\"
412 or \"/ah\" string on the mode line, a newline might be inserted. See
413 the variable `c-hanging-semi&comma-criteria' for how newline insertion
414 is determined.
415
416 When semicolon is inserted, the line is re-indented unless a numeric
417 arg is supplied, point is inside a literal, or there are
418 non-whitespace characters on the line following the semicolon."
419 (interactive "P")
420 (let* ((lim (c-most-enclosing-brace (c-parse-state)))
421 (literal (c-in-literal lim))
422 (here (point))
423 ;; shut this up
424 (c-echo-syntactic-information-p nil))
425 (if (or literal
426 arg
427 (not (looking-at "[ \t]*$")))
428 (self-insert-command (prefix-numeric-value arg))
429 ;; do some special stuff with the character
430 (self-insert-command (prefix-numeric-value arg))
431 ;; do all cleanups, reindentations, and newline insertions, but
432 ;; only if c-auto-newline is turned on
433 (if (not c-auto-newline) nil
434 ;; clean ups
435 (let ((pos (- (point-max) (point))))
436 (if (and (or (and
437 (eq last-command-char ?,)
438 (memq 'list-close-comma c-cleanup-list))
439 (and
440 (eq last-command-char ?\;)
441 (memq 'defun-close-semi c-cleanup-list)))
442 (progn
443 (forward-char -1)
444 (skip-chars-backward " \t\n")
445 (eq (char-before) ?}))
446 ;; make sure matching open brace isn't in a comment
447 (not (c-in-literal lim)))
448 (delete-region (point) here))
449 (goto-char (- (point-max) pos)))
450 ;; re-indent line
451 (c-indent-line)
452 ;; check to see if a newline should be added
453 (let ((criteria c-hanging-semi&comma-criteria)
454 answer add-newline-p)
455 (while criteria
456 (setq answer (funcall (car criteria)))
457 ;; only nil value means continue checking
458 (if (not answer)
459 (setq criteria (cdr criteria))
460 (setq criteria nil)
461 ;; only 'stop specifically says do not add a newline
462 (setq add-newline-p (not (eq answer 'stop)))
463 ))
464 (if add-newline-p
465 (progn (newline)
466 (c-indent-line)))
467 )))))
468
469 (defun c-electric-colon (arg)
470 "Insert a colon.
471
472 If the auto-newline feature is turned on, as evidenced by the \"/a\"
473 or \"/ah\" string on the mode line, newlines are inserted before and
474 after colons based on the value of `c-hanging-colons-alist'.
475
476 Also, the line is re-indented unless a numeric ARG is supplied, there
477 are non-whitespace characters present on the line after the colon, or
478 the colon is inserted inside a literal.
479
480 This function cleans up double colon scope operators based on the
481 value of `c-cleanup-list'."
482 (interactive "P")
483 (let* ((bod (c-point 'bod))
484 (literal (c-in-literal bod))
485 syntax newlines
486 ;; shut this up
487 (c-echo-syntactic-information-p nil))
488 (if (or literal
489 arg
490 (not (looking-at "[ \t]*$")))
491 (self-insert-command (prefix-numeric-value arg))
492 ;; insert the colon, then do any specified cleanups
493 (self-insert-command (prefix-numeric-value arg))
494 (let ((pos (- (point-max) (point)))
495 (here (point)))
496 (if (and c-auto-newline
497 (memq 'scope-operator c-cleanup-list)
498 (eq (char-before) ?:)
499 (progn
500 (forward-char -1)
501 (skip-chars-backward " \t\n")
502 (eq (char-before) ?:))
503 (not (c-in-literal))
504 (not (eq (char-after (- (point) 2)) ?:)))
505 (delete-region (point) (1- here)))
506 (goto-char (- (point-max) pos)))
507 ;; lets do some special stuff with the colon character
508 (setq syntax (c-guess-basic-syntax)
509 ;; some language elements can only be determined by
510 ;; checking the following line. Lets first look for ones
511 ;; that can be found when looking on the line with the
512 ;; colon
513 newlines
514 (and c-auto-newline
515 (or (c-lookup-lists '(case-label label access-label)
516 syntax c-hanging-colons-alist)
517 (c-lookup-lists '(member-init-intro inher-intro)
518 (prog2
519 (insert "\n")
520 (c-guess-basic-syntax)
521 (delete-char -1))
522 c-hanging-colons-alist))))
523 ;; indent the current line
524 (c-indent-line syntax)
525 ;; does a newline go before the colon? Watch out for already
526 ;; non-hung colons. However, we don't unhang them because that
527 ;; would be a cleanup (and anti-social).
528 (if (and (memq 'before newlines)
529 (save-excursion
530 (skip-chars-backward ": \t")
531 (not (bolp))))
532 (let ((pos (- (point-max) (point))))
533 (forward-char -1)
534 (newline)
535 (c-indent-line)
536 (goto-char (- (point-max) pos))))
537 ;; does a newline go after the colon?
538 (if (memq 'after (cdr-safe newlines))
539 (progn
540 (newline)
541 (c-indent-line)))
542 )))
543
544 (defun c-electric-lt-gt (arg)
545 "Insert a less-than, or greater-than character.
546 When the auto-newline feature is turned on, as evidenced by the \"/a\"
547 or \"/ah\" string on the mode line, the line will be re-indented if
548 the character inserted is the second of a C++ style stream operator
549 and the buffer is in C++ mode.
550
551 The line will also not be re-indented if a numeric argument is
552 supplied, or point is inside a literal."
553 (interactive "P")
554 (let ((indentp (and (not arg)
555 (eq (char-before) last-command-char)
556 (not (c-in-literal))))
557 ;; shut this up
558 (c-echo-syntactic-information-p nil))
559 (self-insert-command (prefix-numeric-value arg))
560 (if indentp
561 (c-indent-line))))
562
563
564 \f
565 ;; better movement routines for ThisStyleOfVariablesCommonInCPlusPlus
566 ;; originally contributed by Terry_Glanfield.Southern@rxuk.xerox.com
567 (defun c-forward-into-nomenclature (&optional arg)
568 "Move forward to end of a nomenclature section or word.
569 With arg, to it arg times."
570 (interactive "p")
571 (let ((case-fold-search nil))
572 (if (> arg 0)
573 (re-search-forward "\\W*\\([A-Z]*[a-z0-9]*\\)" (point-max) t arg)
574 (while (and (< arg 0)
575 (re-search-backward
576 "\\(\\(\\W\\|[a-z0-9]\\)[A-Z]+\\|\\W\\w+\\)"
577 (point-min) 0))
578 (forward-char 1)
579 (setq arg (1+ arg)))))
580 (c-keep-region-active))
581
582 (defun c-backward-into-nomenclature (&optional arg)
583 "Move backward to beginning of a nomenclature section or word.
584 With optional ARG, move that many times. If ARG is negative, move
585 forward."
586 (interactive "p")
587 (c-forward-into-nomenclature (- arg))
588 (c-keep-region-active))
589
590 (defun c-scope-operator ()
591 "Insert a double colon scope operator at point.
592 No indentation or other \"electric\" behavior is performed."
593 (interactive)
594 (insert "::"))
595
596 \f
597 (defun c-beginning-of-statement (&optional count lim sentence-flag)
598 "Go to the beginning of the innermost C statement.
599 With prefix arg, go back N - 1 statements. If already at the
600 beginning of a statement then go to the beginning of the preceding
601 one. If within a string or comment, or next to a comment (only
602 whitespace between), move by sentences instead of statements.
603
604 When called from a program, this function takes 3 optional args: the
605 repetition count, a buffer position limit which is the farthest back
606 to search, and a flag saying whether to do sentence motion when in a
607 comment."
608 (interactive (list (prefix-numeric-value current-prefix-arg)
609 nil t))
610 (let ((here (point))
611 (count (or count 1))
612 (lim (or lim (c-point 'bod)))
613 state)
614 (save-excursion
615 (goto-char lim)
616 (setq state (parse-partial-sexp (point) here nil nil)))
617 (if (and sentence-flag
618 (or (nth 3 state)
619 (nth 4 state)
620 ;; skipping forward into a comment?
621 (and (> 0 count)
622 (save-excursion
623 (skip-chars-forward " \t\n")
624 (or (eobp)
625 (looking-at comment-start-skip))))
626 (and (< 0 count)
627 (save-excursion
628 (skip-chars-backward " \t\n")
629 (goto-char (- (point) 2))
630 (looking-at "\\*/")))))
631 (forward-sentence (- count))
632 (while (> count 0)
633 (c-beginning-of-statement-1 lim)
634 (setq count (1- count)))
635 (while (< count 0)
636 (c-end-of-statement-1)
637 (setq count (1+ count))))
638 ;; its possible we've been left up-buf of lim
639 (goto-char (max (point) lim))
640 )
641 (c-keep-region-active))
642
643 (defun c-end-of-statement (&optional count lim sentence-flag)
644 "Go to the end of the innermost C statement.
645
646 With prefix arg, go forward N - 1 statements. Move forward to end of
647 the next statement if already at end. If within a string or comment,
648 move by sentences instead of statements.
649
650 When called from a program, this function takes 3 optional args: the
651 repetition count, a buffer position limit which is the farthest back
652 to search, and a flag saying whether to do sentence motion when in a
653 comment."
654 (interactive (list (prefix-numeric-value current-prefix-arg)
655 nil t))
656 (c-beginning-of-statement (- (or count 1)) lim sentence-flag)
657 (c-keep-region-active))
658
659 \f
660 ;; set up electric character functions to work with pending-del,
661 ;; (a.k.a. delsel) mode. All symbols get the t value except
662 ;; the functions which delete, which gets 'supersede.
663 (mapcar
664 (function
665 (lambda (sym)
666 (put sym 'delete-selection t) ; for delsel (Emacs)
667 (put sym 'pending-delete t))) ; for pending-del (XEmacs)
668 '(c-electric-pound
669 c-electric-brace
670 c-electric-slash
671 c-electric-star
672 c-electric-semi&comma
673 c-electric-lt-gt
674 c-electric-colon))
675 (put 'c-electric-delete 'delete-selection 'supersede) ; delsel
676 (put 'c-electric-delete 'pending-delete 'supersede) ; pending-del
677 (put 'c-electric-backspace 'delete-selection 'supersede) ; delsel
678 (put 'c-electric-backspace 'pending-delete 'supersede) ; pending-del
679
680 \f
681 ;; This is used by indent-for-comment to decide how much to indent a
682 ;; comment in C code based on its context.
683 (defun c-comment-indent ()
684 (if (looking-at (concat "^\\(" c-comment-start-regexp "\\)"))
685 0 ;Existing comment at bol stays there.
686 (let ((opoint (point))
687 placeholder)
688 (save-excursion
689 (beginning-of-line)
690 (cond
691 ;; CASE 1: A comment following a solitary close-brace should
692 ;; have only one space.
693 ((looking-at (concat "[ \t]*}[ \t]*\\($\\|"
694 c-comment-start-regexp
695 "\\)"))
696 (search-forward "}")
697 (1+ (current-column)))
698 ;; CASE 2: 2 spaces after #endif
699 ((or (looking-at "^#[ \t]*endif[ \t]*")
700 (looking-at "^#[ \t]*else[ \t]*"))
701 7)
702 ;; CASE 3: when comment-column is nil, calculate the offset
703 ;; according to c-offsets-alist. E.g. identical to hitting
704 ;; TAB.
705 ((and c-indent-comments-syntactically-p
706 (save-excursion
707 (skip-chars-forward " \t")
708 (or (looking-at comment-start)
709 (eolp))))
710 (let ((syntax (c-guess-basic-syntax)))
711 ;; BOGOSITY ALERT: if we're looking at the eol, its
712 ;; because indent-for-comment hasn't put the comment-start
713 ;; in the buffer yet. this will screw up the syntactic
714 ;; analysis so we kludge in the necessary info. Another
715 ;; kludge is that if we're at the bol, then we really want
716 ;; to ignore any anchoring as specified by
717 ;; c-comment-only-line-offset since it doesn't apply here.
718 (if (save-excursion
719 (beginning-of-line)
720 (skip-chars-forward " \t")
721 (eolp))
722 (c-add-syntax 'comment-intro))
723 (let ((c-comment-only-line-offset
724 (if (consp c-comment-only-line-offset)
725 c-comment-only-line-offset
726 (cons c-comment-only-line-offset
727 c-comment-only-line-offset))))
728 (apply '+ (mapcar 'c-get-offset syntax)))))
729 ;; CASE 4: use comment-column if previous line is a
730 ;; comment-only line indented to the left of comment-column
731 ((save-excursion
732 (beginning-of-line)
733 (and (not (bobp))
734 (forward-line -1))
735 (skip-chars-forward " \t")
736 (prog1
737 (looking-at c-comment-start-regexp)
738 (setq placeholder (point))))
739 (goto-char placeholder)
740 (if (< (current-column) comment-column)
741 comment-column
742 (current-column)))
743 ;; CASE 5: If comment-column is 0, and nothing but space
744 ;; before the comment, align it at 0 rather than 1.
745 ((progn
746 (goto-char opoint)
747 (skip-chars-backward " \t")
748 (and (= comment-column 0) (bolp)))
749 0)
750 ;; CASE 6: indent at comment column except leave at least one
751 ;; space.
752 (t (max (1+ (current-column))
753 comment-column))
754 )))))
755
756 \f
757 ;; for proposed new variable comment-line-break-function
758 (defun c-comment-line-break-function (&optional soft)
759 ;; we currently don't do anything with soft line breaks
760 (let ((literal (c-in-literal)))
761 (cond
762 ((eq literal 'string))
763 ((or (not c-comment-continuation-stars)
764 (not literal))
765 (indent-new-comment-line soft))
766 (t (let ((here (point))
767 (leader c-comment-continuation-stars))
768 (back-to-indentation)
769 ;; are we looking at a block or lines style comment?
770 (if (and (looking-at (concat "\\(" c-comment-start-regexp
771 "\\)[ \t]+"))
772 (string-equal (match-string 1) "//"))
773 ;; line style
774 (setq leader "// "))
775 (goto-char here)
776 (delete-region (progn (skip-chars-backward " \t") (point))
777 (progn (skip-chars-forward " \t") (point)))
778 (newline)
779 ;; to avoid having an anchored comment that c-indent-line will
780 ;; trip up on
781 (insert " " leader)
782 (c-indent-line))))))
783
784 ;; advice for indent-new-comment-line for older Emacsen
785 (if (boundp 'comment-line-break-function)
786 nil
787 (require 'advice)
788 (defadvice indent-new-comment-line (around c-line-break-advice activate)
789 (if (or (not c-buffer-is-cc-mode)
790 (not (c-in-literal))
791 (not c-comment-continuation-stars))
792 ad-do-it
793 (c-comment-line-break-function (ad-get-arg 0)))))
794
795 ;; used by outline-minor-mode
796 (defun c-outline-level ()
797 (save-excursion
798 (skip-chars-forward "\t ")
799 (current-column)))
800
801 \f
802 (defun c-up-conditional (count)
803 "Move back to the containing preprocessor conditional, leaving mark behind.
804 A prefix argument acts as a repeat count. With a negative argument,
805 move forward to the end of the containing preprocessor conditional.
806 When going backwards, `#elif' is treated like `#else' followed by
807 `#if'. When going forwards, `#elif' is ignored."
808 (interactive "p")
809 (c-forward-conditional (- count) t)
810 (c-keep-region-active))
811
812 (defun c-backward-conditional (count &optional up-flag)
813 "Move back across a preprocessor conditional, leaving mark behind.
814 A prefix argument acts as a repeat count. With a negative argument,
815 move forward across a preprocessor conditional."
816 (interactive "p")
817 (c-forward-conditional (- count) up-flag)
818 (c-keep-region-active))
819
820 (defun c-forward-conditional (count &optional up-flag)
821 "Move forward across a preprocessor conditional, leaving mark behind.
822 A prefix argument acts as a repeat count. With a negative argument,
823 move backward across a preprocessor conditional."
824 (interactive "p")
825 (let* ((forward (> count 0))
826 (increment (if forward -1 1))
827 (search-function (if forward 're-search-forward 're-search-backward))
828 (new))
829 (save-excursion
830 (while (/= count 0)
831 (let ((depth (if up-flag 0 -1)) found)
832 (save-excursion
833 ;; Find the "next" significant line in the proper direction.
834 (while (and (not found)
835 ;; Rather than searching for a # sign that
836 ;; comes at the beginning of a line aside from
837 ;; whitespace, search first for a string
838 ;; starting with # sign. Then verify what
839 ;; precedes it. This is faster on account of
840 ;; the fastmap feature of the regexp matcher.
841 (funcall search-function
842 "#[ \t]*\\(if\\|elif\\|endif\\)"
843 nil t))
844 (beginning-of-line)
845 ;; Now verify it is really a preproc line.
846 (if (looking-at "^[ \t]*#[ \t]*\\(if\\|elif\\|endif\\)")
847 (let ((prev depth))
848 ;; Update depth according to what we found.
849 (beginning-of-line)
850 (cond ((looking-at "[ \t]*#[ \t]*endif")
851 (setq depth (+ depth increment)))
852 ((looking-at "[ \t]*#[ \t]*elif")
853 (if (and forward (= depth 0))
854 (setq found (point))))
855 (t (setq depth (- depth increment))))
856 ;; If we are trying to move across, and we find an
857 ;; end before we find a beginning, get an error.
858 (if (and (< prev 0) (< depth prev))
859 (error (if forward
860 "No following conditional at this level"
861 "No previous conditional at this level")))
862 ;; When searching forward, start from next line so
863 ;; that we don't find the same line again.
864 (if forward (forward-line 1))
865 ;; If this line exits a level of conditional, exit
866 ;; inner loop.
867 (if (< depth 0)
868 (setq found (point))))
869 ;; else
870 (if forward (forward-line 1))
871 )))
872 (or found
873 (error "No containing preprocessor conditional"))
874 (goto-char (setq new found)))
875 (setq count (+ count increment))))
876 (push-mark)
877 (goto-char new))
878 (c-keep-region-active))
879
880 \f
881 ;; commands to indent lines, regions, defuns, and expressions
882 (defun c-indent-command (&optional whole-exp)
883 "Indent current line as C code, and/or insert some whitespace.
884
885 If `c-tab-always-indent' is t, always just indent the current line.
886 If nil, indent the current line only if point is at the left margin or
887 in the line's indentation; otherwise insert some whitespace[*]. If
888 other than nil or t, then some whitespace[*] is inserted only within
889 literals (comments and strings) and inside preprocessor directives,
890 but the line is always reindented.
891
892 A numeric argument, regardless of its value, means indent rigidly all
893 the lines of the expression starting after point so that this line
894 becomes properly indented. The relative indentation among the lines
895 of the expression are preserved.
896
897 [*] The amount and kind of whitespace inserted is controlled by the
898 variable `c-insert-tab-function', which is called to do the actual
899 insertion of whitespace. Normally the function in this variable
900 just inserts a tab character, or the equivalent number of spaces,
901 depending on the variable `indent-tabs-mode'."
902
903 (interactive "P")
904 (let ((bod (c-point 'bod)))
905 (if whole-exp
906 ;; If arg, always indent this line as C
907 ;; and shift remaining lines of expression the same amount.
908 (let ((shift-amt (c-indent-line))
909 beg end)
910 (save-excursion
911 (if (eq c-tab-always-indent t)
912 (beginning-of-line))
913 (setq beg (point))
914 (forward-sexp 1)
915 (setq end (point))
916 (goto-char beg)
917 (forward-line 1)
918 (setq beg (point)))
919 (if (> end beg)
920 (indent-code-rigidly beg end (- shift-amt) "#")))
921 ;; No arg supplied, use c-tab-always-indent to determine
922 ;; behavior
923 (cond
924 ;; CASE 1: indent when at column zero or in lines indentation,
925 ;; otherwise insert a tab
926 ((not c-tab-always-indent)
927 (if (save-excursion
928 (skip-chars-backward " \t")
929 (not (bolp)))
930 (funcall c-insert-tab-function)
931 (c-indent-line)))
932 ;; CASE 2: just indent the line
933 ((eq c-tab-always-indent t)
934 (c-indent-line))
935 ;; CASE 3: if in a literal, insert a tab, but always indent the
936 ;; line
937 (t
938 (if (c-in-literal bod)
939 (funcall c-insert-tab-function))
940 (c-indent-line)
941 )))))
942
943 (defun c-indent-exp (&optional shutup-p)
944 "Indent each line in balanced expression following point.
945 Optional SHUTUP-P if non-nil, inhibits message printing and error checking."
946 (interactive "P")
947 (let ((here (point))
948 end progress-p)
949 (unwind-protect
950 (let ((c-echo-syntactic-information-p nil) ;keep quiet for speed
951 (start (progn
952 ;; try to be smarter about finding the range of
953 ;; lines to indent. skip all following
954 ;; whitespace. failing that, try to find any
955 ;; opening brace on the current line
956 (skip-chars-forward " \t\n")
957 (if (memq (char-after) '(?\( ?\[ ?\{))
958 (point)
959 (let ((state (parse-partial-sexp (point)
960 (c-point 'eol))))
961 (and (nth 1 state)
962 (goto-char (nth 1 state))
963 (memq (char-after) '(?\( ?\[ ?\{))
964 (point)))))))
965 ;; find balanced expression end
966 (setq end (and (c-safe (progn (forward-sexp 1) t))
967 (point-marker)))
968 ;; sanity check
969 (and (not start)
970 (not shutup-p)
971 (error "Cannot find start of balanced expression to indent."))
972 (and (not end)
973 (not shutup-p)
974 (error "Cannot find end of balanced expression to indent."))
975 (c-progress-init start end 'c-indent-exp)
976 (setq progress-p t)
977 (goto-char start)
978 (beginning-of-line)
979 (while (< (point) end)
980 (if (not (looking-at "[ \t]*$"))
981 (c-indent-line))
982 (c-progress-update)
983 (forward-line 1)))
984 ;; make sure marker is deleted
985 (and end
986 (set-marker end nil))
987 (and progress-p
988 (c-progress-fini 'c-indent-exp))
989 (goto-char here))))
990
991 (defun c-indent-defun ()
992 "Re-indents the current top-level function def, struct or class declaration."
993 (interactive)
994 (let ((here (point-marker))
995 (c-echo-syntactic-information-p nil)
996 (brace (c-least-enclosing-brace (c-parse-state))))
997 (if brace
998 (goto-char brace)
999 (beginning-of-defun))
1000 ;; if we're sitting at b-o-b, it might be because there was no
1001 ;; least enclosing brace and we were sitting on the defun's open
1002 ;; brace.
1003 (if (and (bobp) (not (eq (char-after) ?\{)))
1004 (goto-char here))
1005 ;; if defun-prompt-regexp is non-nil, b-o-d might not leave us at
1006 ;; the open brace. I consider this an Emacs bug.
1007 (and (boundp 'defun-prompt-regexp)
1008 defun-prompt-regexp
1009 (looking-at defun-prompt-regexp)
1010 (goto-char (match-end 0)))
1011 ;; catch all errors in c-indent-exp so we can 1. give more
1012 ;; meaningful error message, and 2. restore point
1013 (unwind-protect
1014 (c-indent-exp)
1015 (goto-char here)
1016 (set-marker here nil))))
1017
1018 (defun c-indent-region (start end)
1019 ;; Indent every line whose first char is between START and END inclusive.
1020 (save-excursion
1021 (goto-char start)
1022 ;; Advance to first nonblank line.
1023 (skip-chars-forward " \t\n")
1024 (beginning-of-line)
1025 (let (endmark)
1026 (unwind-protect
1027 (let ((c-tab-always-indent t)
1028 ;; shut up any echo msgs on indiv lines
1029 (c-echo-syntactic-information-p nil)
1030 fence)
1031 (c-progress-init start end 'c-indent-region)
1032 (setq endmark (copy-marker end))
1033 (while (and (bolp)
1034 (not (eobp))
1035 (< (point) endmark))
1036 ;; update progress
1037 (c-progress-update)
1038 ;; Indent one line as with TAB.
1039 (let (nextline sexpend sexpbeg)
1040 ;; skip blank lines
1041 (skip-chars-forward " \t\n")
1042 (beginning-of-line)
1043 ;; indent the current line
1044 (c-indent-line)
1045 (setq fence (point))
1046 (if (save-excursion
1047 (beginning-of-line)
1048 (looking-at "[ \t]*#"))
1049 (forward-line 1)
1050 (save-excursion
1051 ;; Find beginning of following line.
1052 (setq nextline (c-point 'bonl))
1053 ;; Find first beginning-of-sexp for sexp extending past
1054 ;; this line.
1055 (beginning-of-line)
1056 (while (< (point) nextline)
1057 (condition-case nil
1058 (progn
1059 (forward-sexp 1)
1060 (setq sexpend (point)))
1061 (error (setq sexpend nil)
1062 (goto-char nextline)))
1063 (c-forward-syntactic-ws))
1064 (if sexpend
1065 (progn
1066 ;; make sure the sexp we found really starts on the
1067 ;; current line and extends past it
1068 (goto-char sexpend)
1069 (setq sexpend (point-marker))
1070 (c-safe (backward-sexp 1))
1071 (setq sexpbeg (point))))
1072 (if (and sexpbeg (< sexpbeg fence))
1073 (setq sexpbeg fence)))
1074 ;; check to see if the next line starts a
1075 ;; comment-only line
1076 (save-excursion
1077 (forward-line 1)
1078 (skip-chars-forward " \t")
1079 (if (looking-at c-comment-start-regexp)
1080 (setq sexpbeg (c-point 'bol))))
1081 ;; If that sexp ends within the region, indent it all at
1082 ;; once, fast.
1083 (condition-case nil
1084 (if (and sexpend
1085 (> sexpend nextline)
1086 (<= sexpend endmark))
1087 (progn
1088 (goto-char sexpbeg)
1089 (c-indent-exp 'shutup)
1090 (c-progress-update)
1091 (goto-char sexpend)))
1092 (error
1093 (goto-char sexpbeg)
1094 (c-indent-line)))
1095 ;; Move to following line and try again.
1096 (and sexpend
1097 (markerp sexpend)
1098 (set-marker sexpend nil))
1099 (forward-line 1)
1100 (setq fence (point))))))
1101 (set-marker endmark nil)
1102 (c-progress-fini 'c-indent-region)
1103 (c-echo-parsing-error)
1104 ))))
1105
1106 (defun c-mark-function ()
1107 "Put mark at end of a C, C++, or Objective-C defun, point at beginning."
1108 (interactive)
1109 (let ((here (point))
1110 ;; there should be a c-point position for 'eod
1111 (eod (save-excursion (end-of-defun) (point)))
1112 (state (c-parse-state))
1113 brace)
1114 (while state
1115 (setq brace (car state))
1116 (if (consp brace)
1117 (goto-char (cdr brace))
1118 (goto-char brace))
1119 (setq state (cdr state)))
1120 (if (eq (char-after) ?{)
1121 (progn
1122 (forward-line -1)
1123 (while (not (or (bobp)
1124 (looking-at "[ \t]*$")))
1125 (forward-line -1)))
1126 (forward-line 1)
1127 (skip-chars-forward " \t\n"))
1128 (push-mark here)
1129 (push-mark eod nil t)))
1130
1131 \f
1132 ;; for progress reporting
1133 (defvar c-progress-info nil)
1134
1135 (defun c-progress-init (start end context)
1136 ;; start the progress update messages. if this emacs doesn't have a
1137 ;; built-in timer, just be dumb about it
1138 (if (not (fboundp 'current-time))
1139 (message "indenting region... (this may take a while)")
1140 ;; if progress has already been initialized, do nothing. otherwise
1141 ;; initialize the counter with a vector of:
1142 ;; [start end lastsec context]
1143 (if c-progress-info
1144 ()
1145 (setq c-progress-info (vector start
1146 (save-excursion
1147 (goto-char end)
1148 (point-marker))
1149 (nth 1 (current-time))
1150 context))
1151 (message "indenting region..."))))
1152
1153 (defun c-progress-update ()
1154 ;; update progress
1155 (if (not (and c-progress-info c-progress-interval))
1156 nil
1157 (let ((now (nth 1 (current-time)))
1158 (start (aref c-progress-info 0))
1159 (end (aref c-progress-info 1))
1160 (lastsecs (aref c-progress-info 2)))
1161 ;; should we update? currently, update happens every 2 seconds,
1162 ;; what's the right value?
1163 (if (< c-progress-interval (- now lastsecs))
1164 (progn
1165 (message "indenting region... (%d%% complete)"
1166 (/ (* 100 (- (point) start)) (- end start)))
1167 (aset c-progress-info 2 now)))
1168 )))
1169
1170 (defun c-progress-fini (context)
1171 ;; finished
1172 (if (or (eq context (aref c-progress-info 3))
1173 (eq context t))
1174 (progn
1175 (set-marker (aref c-progress-info 1) nil)
1176 (setq c-progress-info nil)
1177 (message "indenting region...done"))))
1178
1179
1180 \f
1181 ;;; This page handles insertion and removal of backslashes for C macros.
1182
1183 (defun c-backslash-region (from to delete-flag)
1184 "Insert, align, or delete end-of-line backslashes on the lines in the region.
1185 With no argument, inserts backslashes and aligns existing backslashes.
1186 With an argument, deletes the backslashes.
1187
1188 This function does not modify blank lines at the start of the region.
1189 If the region ends at the start of a line, it always deletes the
1190 backslash (if any) at the end of the previous line.
1191
1192 You can put the region around an entire macro definition and use this
1193 command to conveniently insert and align the necessary backslashes."
1194 (interactive "r\nP")
1195 (save-excursion
1196 (goto-char from)
1197 (let ((column c-backslash-column)
1198 (endmark (make-marker)))
1199 (move-marker endmark to)
1200 ;; Compute the smallest column number past the ends of all the lines.
1201 (if (not delete-flag)
1202 (while (< (point) to)
1203 (end-of-line)
1204 (if (eq (char-before) ?\\)
1205 (progn (forward-char -1)
1206 (skip-chars-backward " \t")))
1207 (setq column (max column (1+ (current-column))))
1208 (forward-line 1)))
1209 ;; Adjust upward to a tab column, if that doesn't push past the margin.
1210 (if (> (% column tab-width) 0)
1211 (let ((adjusted (* (/ (+ column tab-width -1) tab-width) tab-width)))
1212 (if (< adjusted (window-width))
1213 (setq column adjusted))))
1214 ;; Don't modify blank lines at start of region.
1215 (goto-char from)
1216 (while (and (< (point) endmark) (eolp))
1217 (forward-line 1))
1218 ;; Add or remove backslashes on all the lines.
1219 (while (< (point) endmark)
1220 (if (and (not delete-flag)
1221 ;; Un-backslashify the last line
1222 ;; if the region ends right at the start of the next line.
1223 (save-excursion
1224 (forward-line 1)
1225 (< (point) endmark)))
1226 (c-append-backslash column)
1227 (c-delete-backslash))
1228 (forward-line 1))
1229 (move-marker endmark nil)))
1230 (c-keep-region-active))
1231
1232 (defun c-append-backslash (column)
1233 (end-of-line)
1234 (if (eq (char-before) ?\\)
1235 (progn (forward-char -1)
1236 (delete-horizontal-space)
1237 (indent-to column))
1238 (indent-to column)
1239 (insert "\\")))
1240
1241 (defun c-delete-backslash ()
1242 (end-of-line)
1243 (or (bolp)
1244 (progn
1245 (forward-char -1)
1246 (if (looking-at "\\\\")
1247 (delete-region (1+ (point))
1248 (progn (skip-chars-backward " \t") (point)))))))
1249
1250 \f
1251 (defun c-fill-paragraph (&optional arg)
1252 "Like \\[fill-paragraph] but handles C and C++ style comments.
1253 If any of the current line is a comment or within a comment,
1254 fill the comment or the paragraph of it that point is in,
1255 preserving the comment indentation or line-starting decorations.
1256
1257 Optional prefix ARG means justify paragraph as well."
1258 (interactive "P")
1259 (let* (comment-start-place
1260 (first-line
1261 ;; Check for obvious entry to comment.
1262 (save-excursion
1263 (beginning-of-line)
1264 (skip-chars-forward " \t\n")
1265 (and (looking-at comment-start-skip)
1266 (setq comment-start-place (point)))))
1267 (re1 "\\|[ \t]*/\\*[ \t]*$\\|[ \t]*\\*/[ \t]*$\\|[ \t/*]*$"))
1268 (if (save-excursion
1269 (beginning-of-line)
1270 (looking-at ".*//"))
1271 (let ((fill-prefix fill-prefix)
1272 ;; Lines containing just a comment start or just an end
1273 ;; should not be filled into paragraphs they are next
1274 ;; to.
1275 (paragraph-start (concat paragraph-start re1))
1276 (paragraph-separate (concat paragraph-separate re1)))
1277 (save-excursion
1278 (beginning-of-line)
1279 ;; Move up to first line of this comment.
1280 (while (and (not (bobp))
1281 (looking-at "[ \t]*//[ \t]*[^ \t\n]"))
1282 (forward-line -1))
1283 (if (not (looking-at ".*//[ \t]*[^ \t\n]"))
1284 (forward-line 1))
1285 ;; Find the comment start in this line.
1286 (re-search-forward "[ \t]*//[ \t]*")
1287 ;; Set the fill-prefix to be what all lines except the first
1288 ;; should start with. But do not alter a user set fill-prefix.
1289 (if (null fill-prefix)
1290 (setq fill-prefix (buffer-substring (match-beginning 0)
1291 (match-end 0))))
1292 (save-restriction
1293 ;; Narrow down to just the lines of this comment.
1294 (narrow-to-region (c-point 'bol)
1295 (save-excursion
1296 (forward-line 1)
1297 (while (looking-at fill-prefix)
1298 (forward-line 1))
1299 (point)))
1300 (fill-paragraph arg)
1301 t)))
1302 ;; else C style comments
1303 (if (or first-line
1304 ;; t if we enter a comment between start of function and
1305 ;; this line.
1306 (eq (c-in-literal) 'c)
1307 ;; t if this line contains a comment starter.
1308 (setq first-line
1309 (save-excursion
1310 (beginning-of-line)
1311 (prog1
1312 (re-search-forward comment-start-skip
1313 (save-excursion (end-of-line)
1314 (point))
1315 t)
1316 (setq comment-start-place (point))))))
1317 ;; Inside a comment: fill one comment paragraph.
1318 (let ((fill-prefix
1319 ;; The prefix for each line of this paragraph
1320 ;; is the appropriate part of the start of this line,
1321 ;; up to the column at which text should be indented.
1322 (save-excursion
1323 (beginning-of-line)
1324 (if (looking-at "[ \t]*/\\*.*\\*/")
1325 (progn (re-search-forward comment-start-skip)
1326 (make-string (current-column) ?\ ))
1327 (if first-line (forward-line 1))
1328
1329 (let ((line-width (progn (end-of-line) (current-column))))
1330 (beginning-of-line)
1331 (prog1
1332 (buffer-substring
1333 (point)
1334
1335 ;; How shall we decide where the end of the
1336 ;; fill-prefix is?
1337 (progn
1338 (beginning-of-line)
1339 (skip-chars-forward " \t*" (c-point 'eol))
1340 ;; kludge alert, watch out for */, in
1341 ;; which case fill-prefix should *not*
1342 ;; be "*"!
1343 (if (and (eq (char-after) ?/)
1344 (eq (char-before) ?*))
1345 (forward-char -1))
1346 (point)))
1347
1348 ;; If the comment is only one line followed
1349 ;; by a blank line, calling move-to-column
1350 ;; above may have added some spaces and tabs
1351 ;; to the end of the line; the fill-paragraph
1352 ;; function will then delete it and the
1353 ;; newline following it, so we'll lose a
1354 ;; blank line when we shouldn't. So delete
1355 ;; anything move-to-column added to the end
1356 ;; of the line. We record the line width
1357 ;; instead of the position of the old line
1358 ;; end because move-to-column might break a
1359 ;; tab into spaces, and the new characters
1360 ;; introduced there shouldn't be deleted.
1361
1362 ;; If you can see a better way to do this,
1363 ;; please make the change. This seems very
1364 ;; messy to me.
1365 (delete-region (progn (move-to-column line-width)
1366 (point))
1367 (progn (end-of-line) (point))))))))
1368
1369 ;; Lines containing just a comment start or just an end
1370 ;; should not be filled into paragraphs they are next
1371 ;; to.
1372 (paragraph-start (concat paragraph-start re1))
1373 (paragraph-separate (concat paragraph-separate re1))
1374 (chars-to-delete 0)
1375 )
1376 (save-restriction
1377 ;; Don't fill the comment together with the code
1378 ;; following it. So temporarily exclude everything
1379 ;; before the comment start, and everything after the
1380 ;; line where the comment ends. If comment-start-place
1381 ;; is non-nil, the comment starter is there. Otherwise,
1382 ;; point is inside the comment.
1383 (narrow-to-region (save-excursion
1384 (if comment-start-place
1385 (goto-char comment-start-place)
1386 (search-backward "/*"))
1387 (if (and (not c-hanging-comment-starter-p)
1388 (looking-at
1389 (concat c-comment-start-regexp
1390 "[ \t]*$")))
1391 (forward-line 1))
1392 ;; Protect text before the comment
1393 ;; start by excluding it. Add
1394 ;; spaces to bring back proper
1395 ;; indentation of that point.
1396 (let ((column (current-column)))
1397 (prog1 (point)
1398 (setq chars-to-delete column)
1399 (insert-char ?\ column))))
1400 (save-excursion
1401 (if comment-start-place
1402 (goto-char (+ comment-start-place 2)))
1403 (search-forward "*/" nil 'move)
1404 (forward-line 1)
1405 (point)))
1406 (fill-paragraph arg)
1407 (save-excursion
1408 ;; Delete the chars we inserted to avoid clobbering
1409 ;; the stuff before the comment start.
1410 (goto-char (point-min))
1411 (if (> chars-to-delete 0)
1412 (delete-region (point) (+ (point) chars-to-delete)))
1413 ;; Find the comment ender (should be on last line of
1414 ;; buffer, given the narrowing) and don't leave it on
1415 ;; its own line, unless that's the style that's desired.
1416 (goto-char (point-max))
1417 (forward-line -1)
1418 (search-forward "*/" nil 'move)
1419 (beginning-of-line)
1420 (if (and c-hanging-comment-ender-p
1421 (looking-at "[ \t]*\\*/"))
1422 ;(delete-indentation)))))
1423 (let ((fill-column (+ fill-column 9999)))
1424 (forward-line -1)
1425 (fill-region-as-paragraph (point) (point-max))))))
1426 t)))))
1427
1428 \f
1429 (provide 'cc-cmds)
1430 ;;; cc-cmds.el ends here