comparison lisp/cc-mode/cc-cmds.el @ 165:5a88923fcbfe r20-3b9

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