Mercurial > emacs
changeset 83407:37d0562504bf
Merged in changes from CVS trunk.
Patches applied:
* miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-664
Update from CVS
* miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-665
Update from CVS
* miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-666
Update from CVS
git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-447
author | Karoly Lorentey <lorentey@elte.hu> |
---|---|
date | Sat, 10 Dec 2005 21:18:28 +0000 |
parents | 8e25aa911e3e (current diff) 13ebe78ad942 (diff) |
children | 39bb10ce301a |
files | admin/FOR-RELEASE lisp/ChangeLog lisp/Makefile.in lisp/allout.el lisp/files.el lisp/font-lock.el lisp/frame.el lisp/international/mule-cmds.el lisp/progmodes/gdb-ui.el lisp/progmodes/idlw-shell.el lisp/simple.el lisp/subr.el lisp/url/url-cookie.el lisp/url/url-history.el lisp/url/url.el lispref/ChangeLog man/ChangeLog man/cc-mode.texi src/buffer.c src/fileio.c src/keymap.c src/minibuf.c src/window.c src/xfns.c src/xterm.h |
diffstat | 95 files changed, 21595 insertions(+), 12224 deletions(-) [+] |
line wrap: on
line diff
--- a/admin/FOR-RELEASE Sat Dec 10 21:12:12 2005 +0000 +++ b/admin/FOR-RELEASE Sat Dec 10 21:18:28 2005 +0000 @@ -48,7 +48,7 @@ * BUGS ** Fix window resizing bug: -C-x 2, C-x 3, C-x 2. Now try to move the bottom of the +C-x 2, C-x 3, C-x 2. Now try to move the bottom of the second window to the left. ** TCP server processes do not work on Windows. @@ -122,7 +122,7 @@ man/calendar.texi joakim@verona.se Chong Yidong man/cmdargs.texi Chong Yidong "Luc Teirlinck" man/commands.texi "Luc Teirlinck" Chong Yidong -man/custom.texi Chong Yidong +man/custom.texi Chong Yidong "Luc Teirlinck" man/dired.texi Chong Yidong joakim@verona.se man/display.texi "Luc Teirlinck" Chong Yidong man/emacs.texi "Luc Teirlinck" Lute Kamstra
--- a/etc/ChangeLog Sat Dec 10 21:12:12 2005 +0000 +++ b/etc/ChangeLog Sat Dec 10 21:18:28 2005 +0000 @@ -1,3 +1,7 @@ +2005-12-02 Jay Belanger <belanger@truman.edu> + + * NEWS: Add comment about the Calc prefix. + 2005-11-28 Thien-Thi Nguyen <ttn@gnu.org> * MORE.STUFF: Add entry: "Go in a buffer: Go Text Protocol client".
--- a/etc/NEWS Sat Dec 10 21:12:12 2005 +0000 +++ b/etc/NEWS Sat Dec 10 21:18:28 2005 +0000 @@ -268,6 +268,12 @@ to the text before point. If there is text in the buffer after point, it remains unchanged. +** When Emacs prompts for file names, SPC no longer completes the file name. +This is so filenames with embedded spaces could be input without the +need to quote the space with a C-q. The underlying changes in the +keymaps that are active in the minibuffer are described below under +"New keymaps for typing file names". + +++ ** M-o now is the prefix key for setting text properties; M-o M-o requests refontification. @@ -1526,9 +1532,11 @@ ** Calc is now part of the Emacs distribution. Calc is an advanced desk calculator and mathematical tool written in -Emacs Lisp. Its documentation is in a separate manual; within Emacs, -type "C-h i m calc RET" to read that manual. A reference card is -available in `etc/calccard.tex' and `etc/calccard.ps'. +Emacs Lisp. The prefix for Calc has been changed to `C-x *' and Calc +can be started with `C-x * *'. The Calc manual is separate from the +Emacs manual; within Emacs, type "C-h i m calc RET" to read the +manual. A reference card is available in `etc/calccard.tex' and +`etc/calccard.ps'. --- ** The new package ibuffer provides a powerful, completely @@ -1744,9 +1752,9 @@ can generate a table source in typesetting and markup languages such as latex and html from the visually laid out text table. -+++ -** The thumbs.el package allows you to preview image files as thumbnails -and can be invoked from a Dired buffer. +** The tumme.el package allows you to easily view, tag and in other ways +manipulate image files and their thumbnails, using dired as the main interface. +Tumme provides functionality to generate simple image galleries. +++ ** Tramp is now part of the distribution. @@ -1997,6 +2005,54 @@ +++ ** CC mode changes. +*** The CC Mode manual has been extensively revised. +The information about using CC Mode has been separated from the larger +and more difficult chapters about configuration. + +*** Changes in Key Sequences +**** c-toggle-auto-hungry-state is no longer bound to C-c C-t. + +**** c-toggle-hungry-state is no longer bound to C-c C-d. +This binding has been taken over by c-hungry-delete-forwards. + +**** c-toggle-auto-state (C-c C-t) has been renamed to c-toggle-auto-newline. +c-toggle-auto-state remains as an alias. + +**** The new commands c-hungry-backspace and c-hungry-delete-forwards +have key bindings C-c C-DEL (or C-c DEL, for the benefit of TTYs) and +C-c C-d (or C-c C-<delete> or C-c <delete>) respectively. These +commands delete entire blocks of whitespace with a single +key-sequence. [N.B. "DEL" is the <backspace> key.] + +**** The new command c-toggle-electric-mode is bound to C-c C-l. + +**** The new command c-subword-mode is bound to C-c C-w. + +*** C-c C-s (`c-show-syntactic-information') now highlights the anchor +position(s). + +*** New Minor Modes +**** Electric Minor Mode toggles the electric action of non-alphabetic keys. +The new command c-toggle-electric-mode is bound to C-c C-l. Turning the +mode off can be helpful for editing chaotically indented code and for +users new to CC Mode, who sometimes find electric indentation +disconcerting. Its current state is displayed in the mode line with an +'l', e.g. "C/al". + +**** Subword Minor Mode makes Emacs recognize word boundaries at upper case +letters in StudlyCapsIdentifiers. You enable this feature by C-c C-w. It can +also be used in non-CC Mode buffers. :-) Contributed by Masatake YAMATO. + +*** New clean-ups + +**** `comment-close-slash'. +With this clean-up, a block (i.e. c-style) comment can be terminated by +typing a slash at the start of a line. + +**** `c-one-liner-defun' +This clean-up compresses a short enough defun (for example, an AWK +pattern/action pair) onto a single line. "Short enough" is configurable. + *** Font lock support. CC Mode now provides font lock support for all its languages. This supersedes the font lock patterns that have been in the core font lock @@ -2016,11 +2072,10 @@ variable font-lock-maximum-decoration. Note that the most demanding font lock level has been tuned with lazy -fontification in mind, i.e. there should be a support mode that waits -with the fontification until the text is actually shown -(e.g. Just-in-time Lock mode, which is the default, or Lazy Lock -mode). Fontifying a file with several thousand lines in one go can -take the better part of a minute. +fontification in mind; Just-In-Time-Lock mode should be enabled for +the highest font lock level (by default, it is). Fontifying a file +with several thousand lines in one go can take the better part of a +minute. **** The (c|c++|objc|java|idl|pike)-font-lock-extra-types variables are now used by CC Mode to recognize identifiers that are certain to @@ -2035,10 +2090,11 @@ language, so it's possible to e.g. turn on Javadoc font locking in C buffers. See the variable c-doc-comment-style for details. -Currently two kinds of doc comment styles are recognized: Suns Javadoc -and Autodoc which is used in Pike. This is by no means a complete -list of the most common tools; if your doc comment extractor of choice -is missing then please drop a note to bug-cc-mode@gnu.org. +Currently three kinds of doc comment styles are recognized: Sun's +Javadoc, Autodoc (which is used in Pike) and GtkDoc (used in C). (The +last was contributed by Masatake YAMATO). This is by no means a +complete list of the most common tools; if your doc comment extractor +of choice is missing then please drop a note to bug-cc-mode@gnu.org. **** Better handling of C++ templates. As a side effect of the more accurate font locking, C++ templates are @@ -2073,14 +2129,9 @@ are normally placed under the start of the respective pattern, function definition, or structured statement. -The predefined indentation functions haven't yet been adapted for AWK -mode, though some of them may work serendipitously. There shouldn't be -any problems writing custom indentation functions for AWK mode. - -The command C-c C-q (c-indent-defun) hasn't yet been adapted for AWK, -though in practice it works properly nearly all the time. Should it -fail, explicitly set the region around the function (using C-u C-SPC: -C-M-h probably won't work either) then do C-M-\ (indent-region). +The predefined line-up functions haven't yet been adapted for AWK +mode, though some of them may work serendipitously. There shouldn't +be any problems writing custom indentation functions for AWK mode. **** Font Locking There is a single level of font locking in AWK mode, rather than the @@ -2088,24 +2139,16 @@ idiosyncrasies in AWK mode's font-locking due to the peculiarities of the AWK language itself. -**** Comment Commands -M-; (indent-for-comment) works fine. None of the other CC Mode -comment formatting commands have yet been adapted for AWK mode. - -**** Movement Commands -Most of the movement commands work in AWK mode. The most important -exceptions are M-a (c-beginning-of-statement) and M-e -(c-end-of-statement) which haven't yet been adapted. - -The notion of "defun" has been augmented to include AWK pattern-action -pairs. C-M-a (c-awk-beginning-of-defun) and C-M-e (c-awk-end-of-defun) -recognize these pattern-action pairs, as well as user defined -functions. - -**** Auto-newline Insertion and Clean-ups -Auto-newline insertion hasn't yet been adapted for AWK. Some of -the clean-ups can actually convert good AWK code into syntactically -invalid code. These features are best disabled in AWK buffers. +**** Comment and Movement Commands +These commands all work for AWK buffers. The notion of "defun" has +been augmented to include AWK pattern-action pairs - the standard +"defun" commands on key sequences C-M-a, C-M-e, and C-M-h use this +extended definition. + +**** "awk" style, Auto-newline Insertion and Clean-ups +A new style, "awk" has been introduced, and this is now the default +style for AWK code. With auto-newline enabled, the clean-up +c-one-liner-defun (see above) is useful. *** New syntactic symbols in IDL mode. The top level constructs "module" and "composition" (from CIDL) are @@ -2114,8 +2157,10 @@ composition-close, and incomposition. *** New functions to do hungry delete without enabling hungry delete mode. -The functions `c-hungry-backspace' and `c-hungry-delete-forward' can be -bound to keys to get this feature without toggling a mode. +The new functions `c-hungry-backspace' and `c-hungry-delete-forward' +provide hungry deletion without having to toggle a mode. They are +bound to C-c C-DEL and C-c C-d (and several variants, for the benefit +of different keyboard setups. See "Changes in key sequences" above). *** Better control over `require-final-newline'. @@ -2143,10 +2188,11 @@ In some cases there are more than one position given for a syntactic symbol. -This change might affect code that call `c-guess-basic-syntax' directly, -and custom lineup functions if they use `c-syntactic-context'. However, -the argument given to lineup functions is still a single cons cell -with nil or an integer in the cdr. +This change might affect code that calls `c-guess-basic-syntax' +directly, and custom lineup functions if they use +`c-syntactic-context'. However, the argument given to lineup +functions is still a single cons cell with nil or an integer in the +cdr. *** API changes for derived modes. @@ -2157,7 +2203,8 @@ Mode with less risk of such problems in the future. **** New language variable system. -See the comment blurb near the top of cc-langs.el. +These are variables whose values vary between CC Mode's different +languages. See the comment blurb near the top of cc-langs.el. **** New initialization functions. The initialization procedure has been split up into more functions to @@ -2207,15 +2254,15 @@ **** Better alignment of line continuation backslashes. `c-backslash-region' tries to adapt to surrounding backslashes. New -variable `c-backslash-max-column' which put a limit on how far out +variable `c-backslash-max-column' puts a limit on how far out backslashes can be moved. **** Automatic alignment of line continuation backslashes. This is controlled by the new variable `c-auto-align-backslashes'. It affects `c-context-line-break', `c-context-open-line' and newlines inserted in Auto-Newline mode. + **** Line indentation works better inside macros. - Regardless whether syntactic indentation and syntactic indentation inside macros are enabled or not, line indentation now ignores the line continuation backslashes. This is most noticeable when syntactic @@ -2224,10 +2271,10 @@ *** indent-for-comment is more customizable. The behavior of M-; (indent-for-comment) is now configurable through -the variable `c-indent-comment-alist'. The indentation behavior based -on the preceding code on the line, e.g. to get two spaces after #else -and #endif but indentation to `comment-column' in most other cases -(something which was hardcoded earlier). +the variable `c-indent-comment-alist'. The indentation behavior is +based on the preceding code on the line, e.g. to get two spaces after +#else and #endif but indentation to `comment-column' in most other +cases (something which was hardcoded earlier). *** New function `c-context-open-line'. It's the open-line equivalent of `c-context-line-break'. @@ -4156,6 +4203,15 @@ +++ ** Enhancements to keymaps. +*** New keymaps for typing file names + +Two new keymaps, `minibuffer-local-filename-completion-map' and +`minibuffer-local-must-match-filename-map', apply whenever +Emacs reads a file name in the minibuffer. These key maps override +the usual binding of SPC to `minibuffer-complete-word' (so that file +names with embedded spaces could be typed without the need to quote +the spaces). + *** Cleaner way to enter key sequences. You can enter a constant key sequence in a more natural format, the
--- a/etc/orgcard.ps Sat Dec 10 21:12:12 2005 +0000 +++ b/etc/orgcard.ps Sat Dec 10 21:18:28 2005 +0000 @@ -10,7 +10,7 @@ %DVIPSWebPage: (www.radicaleye.com) %DVIPSCommandLine: dvips -t landscape -o orgcard.ps orgcard.dvi %DVIPSParameters: dpi=600, compressed -%DVIPSSource: TeX output 2005.11.24:1542 +%DVIPSSource: TeX output 2005.12.06:1143 %%BeginProcSet: texc.pro %! /TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S @@ -352,210 +352,207 @@ CCBD1F58ABBF1F53AD21E3BFF25EEEB046F66A924E5F431EBD7228050BE2DF43 0B9B538DAAD511EED97630CD9A9C05CC49DC251325A93EA842C6D07B44BE620F 08E66B611F54314B0177E299304F2294F8DEDE9914736944F125A50B5007373E -588AD80D9983CE7824DA30CEE5DC3114D69D7ACEC0758D8201805B82925EF3C2 -C87A1A169C5ADE44B561EC1660E617FB39D1B1547B33C0FEB33C3A1D7340A62A -CD9CEFA49481F19B39A704A53A0B98A11744143CDDA0E668E6325935C6497A9F -AFF471194932AFECBF25B441AD55A43751FBAB76F3E544C4254AEC4BEB5CFE4C -C1318C3A0FAD0E8C1BABEE20B203E1DD9412E66BC55BEBD6FBBEBA84F56604FD -85D50F733D9794611F4137EC10ACB4C4ECA5A81CAACC45213E92ED3C26726BBE -91430E7633A2BDB8EA3D0C55259D7DBE468AC0964A63728C9B8EA4E15CF0EEA3 -2E754B9170EAE6B8818DCCDDAD643B9F6C91C3C5B245CD442358C60AF390DC76 -342E659D4EC45552626F069F346F46B18062CE26D5912336C6B29FCBFA5C3113 -ED86E44B529CD95B7B5B934D899762C4F3457F56ACCC763BCCD5BD08975EB5F1 -C5216DA4CBF3409EC71054B0145183F7DFB31517D199EB16D4C6DB0AF05E5720 -10B06F395BE3C8C59CEEBCEA1E00F9EA3FD880AC197508CEC11E33B6B6EABE3C -0FAEBF246743F62D280875D052656696AA88DABB918F793CB2994A1ACCFA0CAE -AF6FDDF489109DEF07F93B5B0078FC5FD9829DD296F62F23400F5DD6CB096557 -EDA737413C744FDBB0615BD40A79EA2929EB7AC767E58D886B310700733D2895 -3925911133631F28291974294AACF4A35F92A5E5262DCF33810A6F9C51E9D141 -F84B0C26B5ADECB44B646C79DD1C656529B7122739C0459B2B47A2C357EF9A36 -2B376DDF54F1F4F133419EF14CCC6010D360DFA8A7B122FFC5A4C560ED184F16 -057D3F76B6B2E935B31B17FC4066916FFBA0B9AFF287D251985AB3FC3D0D7E9A -91F094356B3D6CDBCB2D74A3FDE23526B22C223EA35C9E5054053B23AF004324 -80F023FCDFDFA6B8F0E03A799D87FC2690C5D1ABB9C52B03402E37309091A1FC -1D66EB48FE3E4BD326AA65839A9A7276C876F8079C11F2F3A7CBFDAB5AD3D4A3 -8377AE4862F390039E3FBE5D79B5318774B0A9B1321AAFCE8E87568C0AD0E82F -D4DCEEA5DD4EFDB2E89D336174E76036DA08DE4A26FC63560057B87FDE9E060A -3AA30E1B447B1E8EF31762C0998DF24B2860CF8B589FCE1050CC259171420306 -F4DAC090E032E4C3E0DD43305541155C1EB135B2093F7E23106387AB7A3DA0E6 -1A835F6D058227003A8C974907CC073F2ADE33AA774165BB24381E65DF19FD6E -F15BB66BBAB0129C79A80CF32E542B68FFAD1BCBF6A4D867933FBBFA82771E7F -1B2E677040596B7872A038FF8F23511C33E23D362CED5E303736D1CA28D78AA2 -20701B83020AE62003DC59413C6A2413C593CDC819644742F8CDF60D541710C6 -5A23FFCE6F6CF6AE26953CA4F01A62D6F7DB8F122B30506891DA023D16E56BE4 -84D72EC9DE3B16197B3BF97EB8A840BD2C17861583477317DEA062693B2EA959 -5F5233B416B4E1D63C6014BB96D0718DD9D81A885793F315402E91C274122E5D -96AF9A05E10DA6276A33E861C006807BBA6B005583CD961491D5F183B62EA558 -C50F25F2F6B211BD3723FF98E01167C48C0A6CCEA0477895D21519AE86FEB4D7 -47C77202688775B4C86882C20D24EBF7AC98A3B9BCBFF750433E17824A4425C5 -7444E5201F1313A4C9FF361FCD9ECB1597C1F0605FEA98DD109C636433920603 -6671529E0E7AE2EC8A7D196FCA784D3CD2F88190B3F150533BAF3CFE15247D01 -864A2552F602D65088AA7F0D87C02768D8FA62930E18702F98558982C5A202AC -111C6B0359273116F1DF9E5610AC46B99995425144D1352A881C79D9E0042850 -B51B2375DA55C34A47510C7D7435FAE7D391BAEC1F8BC0C93B866E7CE261384C -6B277C66E817BF006B636AB133309384FE0985DBC34190E1E1ABB3A63892361C -9970FC5732C7A4259809EEF348E6D3BC6AAB5BB012A098A02E33F9BDDA250A8A -421EE4EBA46B82C10A5A6ADB2390A7B363CF16A0FFEFAAD7F6D2A80FE4720095 -BD78A6E4B95D6FC7DA4196E61C5FD0F9F37537E6BA581496E38625EF0B7826DF -F021663E6D5DF3C93C5EC2C5B510867ABFC5404F490C683337EE7B22D3CBE7DC -8EB4F9F2C25034C8779010A6835ACED2B05B9CF9753760A803073509C71A6372 -3634DB39F894B6EBAA9A34511357F3C106E42E9A6A592C1B49BB0AF668C95448 -9E0968CE39754452648068F82C53CA2ABE392713979634E7DD66819E7B3FF5D3 -A8890FA876857F4560A44029389A6E425ED8DBB25BFDDCFB510C071414760191 -A36723D251F10830B03E21B6FD61C1E92BD630B5EFD283AF248DA69C537D6F0C -1CDC58032A7A91E836FF66810D886A73453A28044F55F754CD70A9B3EB5D27DF -51D6E57085AC4487C5D015FC51F840F7DBB1733500062C608802C556F8A4623D -0F94B67BC91E07FC2AD7E067F3C033E53216804B7371498113125A8CFC63D450 -4760B98ED1397A8862A8FA5D13923D22ABDF48B7F502916EF7C7D6BC52EBA5F7 -AD95E37E4979B7417C8C0E2599E4BB85883AF9E9A3C9DA432859AF9C909DDA53 -8ED9C0B3DC6BF49C5FB81780078209D21E6B54A8E669212B6E3569B615502ECA -D67BC610E59409178B640ECD0A125371ECAA360FDD5843892BCBD22BF4D640EB -99515496E12E2C68567610FC8F6E03C176D14B692A9A23BE3B50C2EB30BCE5F4 -481500B293CA54AAE5CA0A85C221493792B967423418E870C4DC7344E07A7E52 -1B2DED4C2FED4C602DCF37065FEE9BDE6D1FD95FEC1F30A5E3A1833B09E6B1DA -D6A41C57493D4C1D8D87C8BE2443D2B917A0E3D26C324CA101E84369AFA73586 -E499C3627661DCFABF7478DCEF651E33C666957BE759F9DCB9F263AD3FA48BBF -B47A84A914CFD8297141FF5AD0186753DADAD79315D14C68C19305D73DE6E4DB -56BDDF037DA982E956F9C3B554E0746178294ABF6F46D1669D1675AEB8C924EB -F9966956C8AC25940640B8C9DE9A76B36D04806A918FB4F7160503031AEB7DD4 -61C04BD3F6711F09EC71FEB6EA3904FD8AF75054659ECE0DAAEA1A614AAC6574 -9098FB7BD891E65552583AA519C7E4F9E6B5531B2215300CB262F42763BFDF5D -FA2E6EB7E7F6585C80CD880ABAE340087A781C7EABD56C59A14EC17920FA7AE3 -049BA2DE8D5BB77ADECA23767F842642B7C0CC9AA177990CF0DD00A9DD8458CA -5506DD3A5E5BCF2329047F560F0E30FCA7CA304594B738A0C7C70D8FE364AF59 -620E6527C061B6FECEBEEF0841969656F1A7A27731338B640A3AF243F58FBBF8 -E8ADA1CCD8DE701243EBA2E1F44C732143BFC4FA89B24B3B473CDC022111D477 -ADDB77AAA600B6C6948133D05EF0838BD1E1EA1C747BDBA8A0BBF92DADE753EE -9F556D938E16961C2D13E7534B2B5F9EFEB2AFD65FADA831E81237BEDE73F7FA -B076E562E08D57555B3830834B64E4C1E0E1F89D9A5BFB959032106B1EFEE431 -DC828EB4EF66DEA434DAF191E92F1EFDC31954D055DDD87B1A2762DAD6AE5994 -322DC4FA2FCA4AADC293158C75900C540BC85384340B29A4B25F486145C311D0 -4296CA91BB16569CDAFDC9047D9FC8C26792828DD3CA18E045A2F9B473491501 -CD3ADB57FB1D94C1A0353861EAC98E1630E14BEA6DFB04A5B3FAE97F4EA3C792 -2C9ACBF61A5C14605AC9D0DA7E4D9904C6C6FDFF564723FDE4E72413067055C7 -22946CD598266AE7FBC63FF62068CA4F40B80C8EF9961503F7894AF2A392B595 -376F0CA48B4B23AB7112453DA02274095741C7102733C553B6EFB43A6E1DB0AC -C320C44357C4C7E98B96B30D9FEE86B7083080F0B6262FD69E07557FD018C1E4 -2CF6A276E789A63A9CEBCC8867E12C60D78B81F7C1AB5592E4AFE1AB1C8ADF1C -FE8A4773FDC6FC01BF698E5D46B4282983FF16F028D14104423D07047AC7003E -6B5CD6FC2D30DD0E6162498FF67D4091D68AC65A4658215B845AF706F4B74262 -C3A28732A7E1E786006F544853CCCED8B530ECE3460B11E11CC87B22DC0AB93A -AB7EC47BCE2BAEF0FC23C9A15C0D421D75AD13D931B8669F1018A207D8C57228 -028FEBB6453827DE33B1CDD0527CC4815CA2CF05CDF4735A1EFB79DED9AA8AC5 -A074DA91B9B860EE88F5269AC4C604DE488C269959A108FC5175637DFFB08DBD -2AE093CFF20E15AA2624D8E2A141EC3290852E27FBAC6BE21B65CD8036221193 -9967C4A6AD631F2374582F8DA277621961DE7EA41FA110782DD3E1E7CFC51058 -C961948FDBF02A2E7BF0A299EE696F0B98A0C4ABB7CB67AB28A2EF50D3D212AC -1C51DF3909E484FC3430FF1AB2CD9CE667A9EB489A981A9A02F8F999D9215F5A -DD609F5DF9519DA3410867680942AAFF2275D255709997653E88CB23D16A110D -C5C65DC18750D868C8F60E64265C81DD7CD7C2036D13532E3DC7D12600FAAFDE -EC32EB7989458A220339D451A25E3C4B2D52D265875F06465C913FD75BA30285 -AC61B32BD2C307FCBAF38E14FF6A64C6A5C874A2D7DFE3025E3CD30BA9C60D89 -00BE5411544E97D9791949722F76A99D549D344BC1EB88C9B8BFEB74EC94D190 -F5DE00D2EA0003DECDD4FDEDC0834053AFE3EFF04193E360460A286794D02FDD -A174E3CE72C69D32C7C4EF33B97CAB2929A26662E4E3C2313469ACB6BD21CAFD -8C81FBAB0EE7C26BC5B40AC9880623CB5D595A4351BF7848CA3212D74AE449CB -35BE1BE2C6C795B56D2731C0BC9C5DBCC652F025212C35C50B3937212871472C -7B6AA7AA075FCE6068BCF7474EE3FCA088733439E5AB06D78F62A574157DFCDC -43990D8A9673300AF0D2450C2B9B9000BDC9C4A5CE57764A7236370458E8A0D5 -0D777DC1156A9D82D070FFE0DEA2DED3854CB7A09FD34F1B3513821C26FB6F6E -F3BA660EBB0C08D8B976CB89B4E05C95A20EB2F74F4C1DA67E783E9C936A749A -E20866E646774E132A0A12BD5907BA8D7FCBACC83004895110BD65223C4A2821 -02C709F5A8E1E9EE3C0C2430D6CDD4AAC32F45093EEB1AE961B1BCAA823E7F55 -0B9E5614DF4B2703532E2260B70062E33F40463B176D7645168DD4AF226B39E5 -8B74BCA01988FCF9475B9935412016704A09A331365D2E745E778331ACAED5E9 -AF662A9D5C7A5FECE76F73EE20E2BBD0647304E75161347291906E7ADB3F2446 -9769F36EEBCEC59167199793122D96428A44A2D8C9B704802543B0569C140134 -8F180AFAAEDC8550B566E6D460544DB84402A9AF79D8A315C53FAFA3A5898B26 -CF8D7EAEF6B7E19B9DDF927B7DAEA9249FFF69872A6C3F4289546E6969D29360 -0A8684B1D5025DDEBF2554248AF53EE9D53F9412CA89F004911834BE96221C1E -8582F51F1A345ADAD0537938A96E73E35063A2207FF7FFCC55C9F7AEF734D089 -A0693D41848236FCE67E85AD5372C73B61BF5B58CC2D9616FB78144198E65267 -6940C7E3E3381C91C877B7F78B4747F46D12CF347E20C1A2A78BFAF96C42D81F -16715D7E1FE7E671242791DA7D84D5D885F905093969F3836299BF6874A8B12E -9E1F3A05D940BFABFDD7D3085AF8A4FD01092C88CB75F4060BD85F2F958DB0A6 -64145DC3DCA6903E0E018A7594BD7114F336D12C61AE4E29138A0165FE21BE5C -C2F4B9D496ACE81861919BB69DC06E5AEABD3F5E5BDFF3F507BDA4E366BDD481 -05558CE1213A6D28CC2D5D2E5265A754141E312F42B64EA2D51C79C71DA5BC92 -920821C437120A19F9EA3BC48F16073251D458BA53C4C7DDF0035ABB32939C11 -4842DA0E489C7C2025B432B66352C56D78BB8391DA79E75DDEC29588C596BB4D -67EDF9492B91B83D9F1F26444094D60329A5D3F1BDE976DB2E71B6E4CA9B8EA4 -BF43C91A16A2D9D23E5448C2FA38B8D24D142549E45572A29655C9BD31755718 -A58C3DC4964C0B49791F36809863835CD8E4B196CE8D18D714B2B3AE2BE90C4D -65C1210B9E3A8F248BAFB0CC5579302F6FC26FC3E197076891FB758B0595DC4E -7F1EEC99FFB654D46736BCE43BF37DB7681CF7655DF55592B7A494EA541AFFC5 -CE5815E1D989D9E1CE87E116DA4BCB7E16AFAD2327C434AC71EC756B96476BBC -0C997DC8C439E839EC939B55BEA698E3435BD911258234B6993B3890077DADCA -4DE92B37E94166A24DABCEAC3BB808557FE09FAAFD6DD316F44952A6710B4824 -6F5B5D4AE9F8A14DD207DFB697D5DC67FC3EBAE49A1A339525ED5ADBFFE58333 -43E8AAD4030869427226950AEEBD11A07815D9C3BBF2570A51D6C0249CCE9026 -B12ECEBAF112069547DBD47B7C8869523AFA7177F6E87F534A5425693DB8AD79 -497B95A90B056F61B6B4A89A7BB23B4F93BF5DAF637D71DDF4F48E34CF347EB4 -12173D9A72526C9B561F6CB2C3D43B0487E09B2C7B1822E9CF5D2D3836553AE5 -5A71793EFB52216CAA4948C203E1EA410B3BA72B6E2059AD04B5ADF54B6A5BD6 -33EDE67267334D9170FF9E7F9802516295D91F1A63EA8433F696E3565EBDDB1F -1055025C16B5EB6708479CBDE2188D8371EE8863CBCD8533DE37E0242842C0AD -114045C8B131BA3790146335EE07690C8DCAFE2F61824BE4F109F33486663D45 -24391006E700052BC8E90098BE7B5F13EF5412DAF6BDF0DFE9775FDC185369B1 -C53AAAEB34A9727AF997415595F8EED263C0B1B9448119E705396F6143E8276C -C6C586E5FA8FF1C6B701578D1399211EA9398DB2A6397F68C7B7E0B6434DD516 -E4F039207D1BE48AD5F63C3E804C2DCEB39E97DA8D1D6E8C73180A916D8923FB -5EA2430412C28ADEE42F3B6390ADD6159BE501FE3252B6EDE96AAD8035E2C8DA -B00C25B07488F2BCD84508719DA8D309F8191B86CDC22E73730C9C91B7CD6062 -86032E22F92B948647A3351A31DABAD5F5F8D2C9911892C359471026AC047E49 -BFCC10C17712C6B7123EC9FE3BDF0ADFBA2BEC0A69B18DA231B43BE20694139C -D6C856E3B7C6907F8BFEAFD753BDD5B50F8B25ACC61C778FE96B229CA7F891C6 -07EAA8551B790D6CAB23C80436A3E2A7F24FE4CDA84AB81AF8D4105E2386F3EF -D77DD83730332F0F4B176E0C4ABF39ACC995CE3EECCE76C6363557C08F0DC723 -5E2B680D852174AF6BADB73DAF19EB4F921AC61E1FCE16EACABEB591173F687A -DDD0909654D7A243F4105F8201B6343221DAA1589DB4C496C1F702E0BD3CE68D -75071205B4D8ED2DF85276A3E53AAA46573771E0868482A2BC805C6A9D6C5480 -E23F690D6FA9CA9600A9F42F7F0EC92853C8FF64E2F137DB193543F78356EC5D -A090542039B0501650B6184093DDA5CDD52B6F8CE4460AC781C2F93EA339F10C -4921774575EDAB301E387C5A9200679ED86127611043364A319CB0C68B6FE176 -B0BA672AB3DE3F2B14A9E7C8CEA1DF76C716FD53CBFE583D1D0D20D0062A3DE2 -689408AE3D527703C591BA8C9982607CC08384A1049A1B328846A719FCA05D38 -087619AE510325FBDC54307AA468827EC8D84A19376740210EE95E5844872259 -7E2A055BFDC40D3C12946ACFE8CF26095719C3E10670A10417679DA5639B4175 -9DF86246392C78E114D745B9FCBE5D4D33E4E5935E6D4EB9F00F408045AAAB98 -47E445AE32BFAFF24107A37EDE0E9BA08934370E212F39035BA2AA51E2D711F4 -6D7215A05F5AD11422C9E8F65B80405D29CCDEE79165F59EBED93F9EB264792D -35F8C1FD095F18511EB516DB40AC15B6045D2A24A2B910EF3A632278208A0D66 -E19963591F45FD61AC0183CD5D4C5C1C8D69020874EF6079376801145636901B -D9EA1E35EF1E6B37D257D5B90862CED7C0D1F1B32C5324A28716EAC93B556BE4 -C2716C85ACD7AF85D52DA2E33312C42A6B7F28797BE80102E37B7F9C933BBE85 -121C64FCA542C6D5B7FA7FCB7CD0C41295625FA2D99E6FFC4D08450EE7C1EE81 -BC356927FF6F5AB869D083929EC1A643515702F602AB140A410378A65A721DE8 -1BE9F270589F468D5D2003FAC662A907296302C873DE919466A128FBECF122AE -6259456457D21A217D359EFFF23758BB537BD97472F22EC4EBE932F762884EAB -5D59AAC0097E2EE5A9EF77B1E0376AECE3AA529E5E518A24569007F5DB2F27BB -776BFF2348E9B2E9AB0B07B9BDBCA49E37E11E2980754CEF43ADCBBF32B9575A -C611F4AEBEB5A718524AB25FEA08E9E913E24FD94AB4E2E4FEFEF29C7A70055B -5FA0FA771D485CADF65EFFDD9B6897F675598532D8E974CB042BC7DD6B5A4B99 -F5D36E27D80AAA8417465223649E44E28D5AFABE693265DED4FE7711BB4BA083 -DC71244042798FE7E1965A469B8F8202DEB7C563F43A7E17A088FA36180AEDDE -345A2D7705A5ECEE8E305218791D9956DB2E848E422291D7E2E249329246BE92 -892554EBAC59949D310F38819EDCCAB09F4DCB80144604F8F1F43447138B311C -FCA400AD225FEF31D3B0F6A5E8DF91E4FBC39C93DDD11A2E54D1B8ECF5F386B8 -FD0DA95AE3E981FB36D9FA0344D6D41CCBE8F2320539411FA23360B88ECB4D38 -FADCAABE8049B06887D053FBF3ECC8A89BDE4A9F1ED7F6629866FA14ABAA2924 -9BDB9D6C93F6080593A4BBC0CE2567813B2AD04C99FB09443A684E644BA51B9E -9480AE4AB2148A081F6BCE154261D4B0F03864C6F79DBD622EF471A844048766 -6A872C8E99A82CB468B6FA50260CDD90B81CCB48A6F3BCE3865AE56A86569E23 -16B13DD6114D98293C0DF2585F4E2D01E5EC8E43DD6FFE027E2F0C9CC360BE2B -823DAB713978E73D7AA80DF69CADA74D8E23D902B9DA35EA2BC9D03AEF265D54 -79E86089AC4E8312FB9CE325D8DC9E4DB22BC048CD1F0EFCD64E62B785D97685 -6A34EB62E657BB2F3658B1EA87B4C07C45C8D8283BD35634EC67399AB00AA2F4 -A15A723E8EF9AD000007ADE862D7ADFF32A907D40BF9491FE05BCEADFDB83187 -2825ABF2EF18608411F9E31C3306B37E245F1571155D5651BA291AE16EBC0390 -FEEF8EDA9B9EAB02F1D3BABA0C4DE4FD20FEBC2DDA743FA0C32F7A746FBFAB22 -27B2B8547359B5EC413F98024A5574F48349213502D0F1C71093EF2AF2A7EE88 -67332DDCB9D9652B705E9D2ED1BEF1B9699D84F9B8520DDE2609F752E8D77F8D -ECF010C2F18EA526B4E2EAE1694834494990A4AFAF57286E171E4053788F3B2A -B7A2DDF04308E47448A06C66E987C2BEE43B5FD8890A1E11FCF4E0548E201941 -8437B4BC7A92174B7D5D8F4E9E98F48779968F00803F2FF59B1764EE197873EE -D1DFF6B12B54459FB5A6864CA9D73B89ADCBDBCA2DAAD3B42C4A9175F503F21D -C48D5145E2C6AA7D7FD787BC0D +588AD80D9983CE7824DA30CEE5DC3114D69D7ACEC0758D8201805B82925EF3C1 +3A6757674B84D9B585F981DDFFB42163EADF90346248E014A74E3FB3E6276FC1 +B4289FCDB4FDBE9C70CAF38E410965A3610F649DF8F81C73B87FBE27D44A3CA6 +D7883821CA22795E3EED184F4F59AC687AC06DC4DE7FD098E0EA61C494A5E960 +643D78025B1D18B4B7FBACCE2DEA453E35C08A6AC093F45FA0B1DE132F743CBA +75F2E7BE0311132C0E63C69D5182B98AEFC610F61D1E1EA51120D8A9F5DFFA8C +37C0ECCA2120E1DF7A551343BD7573FA24144A8D59CA684FF9FCC1E023A3401E +9797D658E92CED2255A273E429FAF43B0355E27EC83974BA4675520B2DC70DDA +DF783452C679BB77759479CB02FF3377BCCD8580E3D87D34CD579AA3F89AAB44 +E526EE761B0D371E27B5A02A5C494C5169651FA79795D332045B3E7F2CA100FA +FA8ADA74DCA851DA1BC7531E58EE08FC22F2F35E94D5DA013A4C9669B2825D26 +021982566B4347E518E82602B0CE5CBA1CD38E8B3CEBBFDF9E9811C896313F37 +51D5F7162441E4B2DF18A7A34326114950BE85B3E5AB465D54652575AAC03DF3 +E50E9FE8D184D33534E12AB92DF20BD72DC129A86CCC24981FF82E297D0B0F9E +0B66137443B501B5FA711C7DF380DB1F64404DA241D1EF5F2D012A0293405302 +F828BF879F46962DFAF75F44D4A394DB9D42E4874477097FF6F8DB9BC8712BC8 +661A95A2467073355FE697CBE1D8E298569935E5405C22555C40DB775A808F54 +642939D8E4F76C61B2FE966F4FB55319873127C8EEB0572023C36D7624E7B0B4 +EDC15EC6E697D900271A4A20C5D357ADAA313C4F7717EB32258DC6C8C298109C +B80F85F201C0E5366A259304EF113C9C4DD3110BC88F76744C8337B201E8D546 +E69D1328A06F23255AF9F6AFEE6E17FB36B75C80C4E1AE1BF7CCC3C779B3264C +2185266C84CBF559883C6074F8B71BB04D8AE260EDBB86146FBF41E6DA64FD10 +D7982F9EA6A15D7FB61FEE3CA2E4571F8FE6D37967776E22C71C0ACD260DF10B +255BCC7E8521B60EFEEF9529B5D4B5A5B366EC9D4E55342297E4E6BDD3B4A6E2 +B929A4F670CF051869BE77438C78DE9DA89764614B1F6E76A331BBBAAD3EAB0B +66E6D4F1564028019F420E47804B4EAE7F08B9A6338BEF7FE8B5D81583EA5C48 +375796372085876CADB21502E77F66764F67C11F69FF205DD706653ED40DAE7F +2E817457C6EFA10FCEC0ABFFF46ED0B112A515A1C5ECE4016683D24AE4234933 +03142D3F5408D6B4347DF87D6DB6D843164701408CD5388BFF0234CDE46DA53B +1060EC8FC73A31E10053A53CAEFC90C96DB930F7E2FBD5039387A15F4CC5C197 +BC2FCA011971EBC13844C370CBA676162715E6B66038B342F9EBC6E278965958 +2950EFFFBF10886CD3EE43741B66EE71976215F5C090D6FCDAFA0F09FCE2C56C +F7173B885FA1B6883057AFEAC9923BB22BA085E74426F4DD57E0E59A7E245A9E +DED2D1CECA852F57EF4037FF66D51ECD30FC6EBC95E0192ACE4A4926841D64AC +5384D1AAD0FA9DB932E199F0271DA68F9A3AB951B65EE7DC0711DDA07C92E153 +012EFC4CB575702DAE0C7CB6666A9F44DC4F965F6079F94FD34B6EA6E79B4EE6 +7751BEE8B721F16F8C28DF7EFE4A67751B642FD7E4460CD770A7112211513C67 +F934EEB3A95C5FA1D66A73B388DE69380A40D3566E883E89D0B292FD8AF4B063 +19900CBA3E1DADB33A64F1462156977764A7832E74241F9378F0BEEDC2454535 +54B334D4B71F4E13FE7FC588D8475812464AA709476E1E3807B385499C6BD992 +9689235FC42C207A3877F7D5982A87C47EED577CA1FD1ADB133094868DBF49B0 +E0FA7D2736793756CE915E2F8855D11807C51F2BFB36583525C6C74E15849493 +DB1B673D7CA0B9B5A42FD5635F509E8249141229087995C982AD8CEAA5CAFD2B +46FBEAE379FE49FB1B55BA76076DC69BEC64F2AA719FF103318B45F367A90D98 +A34B2519B8C82E8F51E4961A40BDB2ED188D231E94CBB9F8594C18D1D5A41A66 +C04BE3C0E42C23033775FAB6E617813B891963166390794D8C048F86422FED88 +67BDF4A60D6AA66DC0E8E6A8E2BDACFF68FD55ED78F74F36D055A479CE24E2C8 +BC2B57DC809FEE856ED1EB1078FE6D5CE4959E44305276AC319839C53D9ED91A +DEB117759DD3BD4F1D4E67DF5943DB41DDE35CCF7E6A4D3BE6CF3830B7117022 +3099E42EAB2C1FEBA35DEEC194C18B77437CBB61DF968C4AAFBB70C1019CCAF3 +79E1EC1F5708B8DBA167D4370DDEA7ADD3BBA6A0C1F8E20058CDDAC1CD380676 +0B7DB158FA947AA7F3A02B41EF46836E01FB741F91B420247BB9C8744608FC37 +0AF67329F7978F142DBF659B8A8F0D592046EFFB7F3124667DF9562AEAAD6E0C +A13ABFFC85BBC9806A2DB76B9311484D1D8A400C89C86DB8C678CD3BBA36463B +2F01F3B91D58D3078EE300BCB8D7318288BF602368FD70E95267C2879ABA5AEF +BAA8B067472FFEFE32CF213BB0BCEB53A9EEF07731C7FA6E399A59681A71EA5F +C3A5D118CE6D7107E8BF350DFA0A80B18C2BB265E74806ED288871925E4CAC07 +BB7465B0CAF4AC1FA6A4DC966480038E8B46024BBDC9D725CC03D2B93A4326F3 +4C020B091438DBCF6320897643DB1232CF6CA9BFF9CE7EFDA8491FA0ED29A77C +F3F65B317C4F1694B0FD10DD7BE362887BE4EEC67173752A2F0729E18BC64AF6 +01002D8979E937F336588281BA04688904CE31C370BB9E6117C4E640EFF6C71D +47C98933ED5CBBBE0C9B1FC7B5878A624756490220C82913D7FFFE788F5913F0 +513DF7AE4F71ECF422E02D643B4920E08FA3623A1B54AD852A402762E6845883 +3C3D12E45E287BBA870C4366A13BA3D21B0D25733322A4659459F4B2D7C0C5A3 +7E57B0CEAA8346399418A54BB6676FE800F66DC3438EE48B6F220849AB9F3577 +FBFB7469A40FD2E4BBB12254B27EDA9C05EF6D99D45FA79FDC5E14CEEA23FEE1 +C1CD4C26D9C4D00A8D7BF5E9830CA971CBD857C9B832225B1A5736406259D91C +D6D5CB1817EC7255FFB0CC7D83E2EE23ADB05F1CEC026D6B2350D806004DD810 +B92F80C827323F56E668ED87B0F442D59BEA68246DDE64610D5AA53B6C7FCE4E +F79A27ED30BA0BF128EB09AA2F74C2FB745CD3303B47727C093816C4B99AA55A +73804DBB5CCCA241923C0998A565031C185C63BC348FB7A77D51371F0598C0E2 +A24B2D4F0D4CE6F6A6EC0C14432DD6C88B4361ABB0D6E3BB813F6625B18D1666 +EB9A382D7EF05E692CA5CE9C94A8E90036D693CB11C54252718CA093A1C6646C +7B6956CF2BFA3C0568DBAADD9F604B2AED8F0F963764F8E0E327C5929434BB40 +A0319C748381E5211012925CFD7EE914469E0A00CD7CC1A6C6DA8D1C7B30D3D8 +8E6C8E3C8B248ACA15A1B462C3A6C8B2ED701F336D65D45B560F30CC580E957F +73F06F636EF85567A48295FDD23341ACDDB6CD86A5E8F1FF6AD6910E8E221A66 +CEEB2B614CC23178C033F6D135BBA8278244340E119E6C82A4AE60286FE02D60 +7295FB5048291C2A655A20FF265D5357E6F3DA06564A410A97832C7079164F3C +6D193F267729A247D7B96E647758F458D0F6F494F8FC284DD73F413E1225E9E1 +2F6A917D8099C41822F84416FE47D4313DE9DCA3BF3D2D5E85CE4CAC70E0C1DD +DA64EB3692C90C1608C8FEAA0263ED74ECF5F758BD3BB0E595709944CFE77145 +D5E5B03C9E15F022AC53DA6680CB14362CF7F35E914F6DA5E3C40CA98ED01EE2 +64F3709D9A4B7CC60B6651E094EE51A72A2E6EF80357E8899028BF4E25DF47CC +A92B51E8A3C517D558D2F4A369BBE8A33FDA6F3A9B51B57CBD161832E5F2B28B +A7B4F445BBCFCB658FF4ED9AA299D37394C80923DB7A315B022A22B5A341F858 +A25F772684BF0781E80CDF15393188797DF2E8608C9A48B849E27F5A58F80F04 +E90E1572652E92FED49E65DDE13C0D61E0D6B912DEDCA5B156B94B4C4A347148 +6CF516119A9FA728767201F1D0EAC329957FE795D5B9AF1E709FCEC0D578D9D0 +21D2F8F40A67F3E3529CC7D0440738FFF94C0FC1BC4209ED743885DBEA970325 +184BA629A5DECB34AA558730B77A5401124495094F127C9512B8DA883BBD23D3 +05C37C5B4C5CC8C762E8BCBFC9CC89F4AC1DF4861E96762E8F5BF196E58B544E +005BF4AB1A2E4F0226B8EE5F487AE6458B4312C63CE169AB0E32BF92FCC346AE +ACDEC572CA5BB2FF6A3A7D24DB0429BFED712FA4166581BD5B1D02FA35BEAEA2 +25083FCD9F3F238FECA1032CDA403097F05E6FBB905A26E8408B95742DBCC2CB +41A11E63166829B856767F91AD47289F2685734C6E95FD1513C121060C33CBFA +1DF5DBCF55199D7EB4D4DEF001830895AB27C74C2599A805E5CD9F93D0915166 +D4B46F68E2071025CF7D20E382995054D346EF5C3B1C308686DB495A356B1A85 +171A56C79C443757FD2E6505A4DF3C605A7E1D0CAA353F2D6D1035E5A1264F11 +8AC28DBDFCD0DE25AD0B0A5E925C8726A430A07AFE252D24D901C6178850440E +EBDE3E8A0F136B8A644FC16D5B02D2DE66E6486404C0402691643519A0E01F9B +55D2911E41E64DEDA8F1531A840E458C7BBFE061637128167712B922183B3D40 +5BA3E23873239A62E090BF06174683D2706967C84DB0E6AD95687C189B1F14B6 +8D093E1D89C131589B091E903AB2FE30961A638ADE54576C8B6BE3E80FD8C606 +3CDF0D132180627000FB587B4957FE8B65A91CD3D784036824E7FD60C16EFCB7 +114B26A392E24C58458EE510A6969A034CCB9178E82C46B067500AE85ED02305 +B00E94E4173EE1D733B7B60FE5B0223C21DB47E4FBAE6D590A0A789F004F974C +D1B95DD1FD7EE0B64ED316F8F3485D684EEE187B4E08B8F589DB88A8EC55F413 +9880BAB80CB43EF24C742F48148B4942C78E399940DC86D8BF84B88A5EC89E5F +BD9A2DDE0DD69B40FEFF423FDAE8226F7E18CC5E9F14F03DE0F486A4CCA21FC6 +6793081C69D63CEF16B92860F56F3966309F06B729FCBE1F86FDA8BDFE94962B +7062011520CF6929FCD531AB79606209BE467FD3274A1E87548D92E3F7862610 +9BD97EBB6B544F04E76E22B15B4E106690BAF9F37C243DC028451AE203DDA893 +D5F8A0C6AD763F8973B5063F0B3EB0CFA7663C6F308C256778A8E14A005050BB +BBA147B795C6D680CD425392B0A57988AE673EF0D997A204EA7136D26139FB7C +1C356AF9EEAED3980CB27231D9835571DEFC3498991FB2942638D86186AF73BC +FD55FEC65A66A35557BFD8114C10FD8F872EE976F0F231B40FB7320B92A0BFB1 +596391CD560BC7C28EAC9F342700671354A221326522B70DC5E832AE3F39685D +E6453C1110F0A7D0918E8E413BCAC5DD5A09524C059E5BD9C132586538F2EB52 +972B7D2C89D5A43B3D9697D23DD431F66768765B871CDB5FA608685C65B71A62 +1065B21A81192026F2BA728D35112C40704DD9E8332D8E374C986A6A48E4A30E +8C46AAA96718FF84A04A96949E7E6A653DD2556ACAA4E3B42E787EC539975B71 +309BF31D6ABA17C37CBCB4E4E0CB25F0BC09E2C307FBB375C1DF1D258544F5AE +2CF1819D249283EFE28203C1ADCF39CA6DE74F89AB5159680DF2992F6CD631F4 +A1185EBF7588211686B1DDF915270563B238D03CA0BA3C60676FF08259852BB7 +20B1D958E12BBCA69228FBA42E65969D02DB2A37F3C39B07CF455F473A449711 +7D7023F4D994E55DEFCF0406D8669EBBC92E3EE1050A2D24B1B5D4DA393AB9C3 +0ED709A039AB7E5F82099517E8B70417510BCB6AC6662A78D37C8733D8C4B27D +69E643F58935BA3043DDB9DE4D78CA38D7A965E6B797EAF65DF5E6E0E825AEFC +5DA53C3E50ECDAF26EDA4FE61FEB99E5900F61BD827C8F1C1CA156ABE502B2FA +548C30594DFA196183B2B27D04B4EEB2B63CA5F47C6263FECF253F8114496D21 +278A8DF5C172A66E60FDDF596254D729F67C4779420AB74A39D5E5ADEE663EB6 +E0D65ADBB179625BB93C569C166E53E831875219AD377F6EA835354C7F263F0E +A93C51E43F591BED9DA28122831BB5DCDE46D6B0BB91DB34BE123B75BC583DCA +3719935F02FFC65283B01DC6BE4D06280134E6C7E1EB87028071EC9AAC1B6CBD +4C8651ED2B26213533372B226198CDCCD42AE24CBB79E0FEC2DB57D40B4D4983 +20055205F06ACD3C1E345357EEA95492766B103EFD28E23A91850AAF157FD34A +9F25A59B8D807B37829CC139226F81A336E16124416CA69165A1D58000A582EF +DD388863B47EBFA763C31A82E0BDD6A0C9E2E7CDB418B5B21D607C6A2EC40299 +FA8E69DF37DF5EB775CDFD8AC0FB199C6E11739B644909CEAFE4D2123828DDD7 +FE23B3098C1B25394574D44FA5436574F34DD6963AA246E3B0C17108B4573B78 +8DC32286E9A466D15AC01E0470E60261C362F237096E8627CA4F87DC1AFD83AF +54C3CBB610E1B97A3CC046F83C1E99EE5BCAC6B90687A9FA6A402D6BB917567A +B4E347A7AFF8027E9A118F5B8905EDD930BA4A87E7115A3272ED8CEEE0195963 +6ACF972FFF29B2FECA6E38CF77B3BA25B9058BF64DCB2FB5122D7CEBB7201921 +617F419A92CBEBC15A8A4EF253F294E8CEAA76DA2149212E3519F233EE0FB983 +EC681C89E6403B5D852426C94FEC5E2CD93CFC8B15CB99243105F21415FE2273 +D0463CC70E5E1F45F559E3D544D6B81FBD5358CE5562AAEE8AB43A33FC4EDE84 +1E028C5B4F39771F9BF65141AD73990530E2A739CDD75DE47D38B55F66763604 +2D7B5A6630F46D2C6B8D3CF40FF01A6397D19BADBA8C4766D9BE10EA73A4EDDF +BE40B3572AC0533176CA444FCDE3BEC2F1907C63F6E92971A861AADB0191E6C4 +8ED6E10C231D438D6505D9393104204F5FD0DDD9058B7E04E5732C8FC17814A1 +10A1463B5EE58F33672B5F97CCD7BC6936AE5A49719BD68B1CEDFD8E5592C122 +3749B86FD0E373AECC1188A639723D4CEB42B142062534AB42E766BC3B709986 +57E70E68B9740AC5F284F04BAB28239B5DC8AF12BD5E39A31C9A2E1C9A519D5A +60A966DF2A68BE4A5EDF5392AB2CC26D3D3274119B1FFE40795C9D097541BD8E +BB1B65E7A2B94AA25AE5C57031959F0861F5DE27C61C371704B3855DA678468F +2A9337DCFEBD02EFAF984D01B5369177B0301646C57625ED4C455A4219CC042F +C6BE63A086360AE4A9DD5B37949F4176E5F5601DBE7533BC590CFEED94B31EAB +A68B6741B5E32C610F6345620B94E87F14B79B1D15F8F3A638C94E9A9B7AE4AC +FD1A5FBCEFCA8015ABD25EE55312DF3FC193F68515619DBBABDC301E09399425 +9F15C1D4FEADF2912C676267DB8D5D7594719A5DAC965C08812FE51C4905E2EB +0CA991DF28FFE9D5BEAD055656608714092626632613CD297E11B629ED77AD75 +BDB8892C98DA992489FB138543CEE8D294B2AC6F924E2A622C40059A180665A6 +698EA5BC74994374B85FE9D541DD4C9A7782F66F0D5FB928555616CF6B9523B4 +4780DC444B4D3CD2B9C2B2F255F8B2C926093F9F80BECEA3DF2301DA26B87FEF +CEFD179713B1EA0C8CE779CE59191D468613F0D708A14225B26DD97A64AEF55A +AA6134FD3473888724BB3F34D2171BF6F2E3DB28EE4945BADB0B5B5A4D83D087 +920EEC92A5B85F1DAB6176F44A8A36A503685A83928836E7FC4079F929C29269 +F7ED0F93B67E1EA9D0C3055F16305152DAA2E79E08A89D6A29D686836A43F5BC +6283FB2C37ECE9B467B6DF24E68062D1DCB25ECA8AC9C4BC3D846F3F95D91712 +B90B7727D06B9143C4F215B04C126CCE6F38A8512F39B14A94BA956EB696549E +5A795B86BC82C8BEC872D9F3D0B4909DCCA395F3065D7AB72B5DFF4AFD6B1B6D +8E75CE3316230349FC4F3E889A81F2452534AA3AF82C5768C77C1229975197DD +B8D26C9B94921A80A399BB6B292EA56D7E2217E8E6E8FDD817E8A2DCB986D1D0 +4F3BA37C60C6CD745A1F33F7507818676EB53F2A7E4B0F97A30013820BF6DF15 +31DF184711F646B7B9CAF27B396B8C218036A7B668F15EBB0808D9E8DA1B7871 +3FD447EA00E5629CF2A6DE3F411AFFD4296B36F8DA06D040FA763E0AF241ED62 +80468F92A98E9FA82EB534897362208DC3FC4B268BF646EF99518430FC3D13F0 +9F0501EB8540FF16596A894A6C7DA4119D473647E4E2CC534EDCA764138ACE8D +426D6FEDFA065F9235A8DD34019FE0922B06DD75F967C8331ADDF79C1D7B1A11 +B68A43DF4797C9A81C1D3EB9EEEAE7D8A9EEA3C08C13F48C33FEF4C5493C4270 +5EEA2BAEEE9CC40D07F1883BD193B11EAF9E0CAA3214B3C34BBB3C27FAFFD949 +1BB4CAE77B627E300325CE0141854BDAF24E73CF535C952997168E5DF594C269 +DCC646A460CE417967E3C09A63E9125E01EE2770DFF73A2694D94549EA71799D +C086B5FF88292D1B6E7F3FB425809E6B0BC2671CF26397BF3DCC756DBB1920FE +470B6D9239E3BD4DECB5EBEA0D1289734E80D8D4544DE8957E66306E4B638557 +212699F0E892892570AC8C060EB37A64B471DB2CBF05CEF4418F787A7D96F04A +8B55B4234948AAAC51F8B34792AAD1A75956A4642ECED3731E34742BDB338CCB +0ABBA52FE5901663ACE4E026CEFFCAA5EF6BD97A4316877C7A976E5523BA4A9D +82F6717666FA6F765F51E414148A4666C293B24F6283FB94E63F9CE245CFFF5A +3C6B620EAD4BBF2C45C1CFCBCD758DF350D0CC4C972C72CDF4A19465BFBA4E60 +ABE57C22DDC94E22A4A396A3A99362FF311AB63EA2E790E0BED6F62AF8CAD265 +DD6923A736C427086275A4E2DBFF09AFF176D01D43F5229F311E0DAE01E57F54 +A8406CB7843847FF1901EE9B0F6B915B4D6A4DFF13F469AFABF2BAAC8F54AF0C +01F66A4169950F247441B5DBCB35D23A063FE9907FF9653BFBBAC43680C35791 +D2FB66355B28C577D8D553071664685A1763DC2C18074A5FC1FFFE2BB4E36525 +067A907027F1EA6303D866DD5DB69C4457C01FA0A1859C1C80133BAA88D7DA6B +E04146BB1C3FAFDB2B9E60F582BDE0E73AA446F9008C97BCCE66D53130A26727 +4C52271A6CCCAF062E550A4318C940BDCD0F17FC4FB5F0FE8BE15311199852C7 +20 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 @@ -1672,209 +1669,212 @@ 16B955D4A1EB29BAD152EC888572C3D4E2F02309DC60E94272D2F2EBCFE32969 5180EDCE322BDD38E3B34D24819E03ED61C913A9FAFE2DA1822A660C246B1132 D2C18F76CC413D4AD1BB8F7A6719FDC7C7E54307495BC0E671CC6F4257C82574 -5FFC9C7EACE612207FC80AD04F0CE33A9308DD615A4307677F9ADF6B98D66A77 -2510BB8B5C985DA4658F7637BB4C7643AC9CC424E2571EE4CF5C15C7EDD306DA -C41DED0B1339553A5F8265DBD9DA06374B37D77A9C9E4AEBCB4ACA8B909E9C48 -70C16A5A042CBC8825CF675BF574B16254541B69E203D5E3CE29C339C907D11B -28F9AD8DF700C945FF11B0C99172FE6B25D131526C31E19D5637FF4249440651 -86C1D4C8A7B60CCA184FAA3E27F7244698A99CCF94E9135769C726307F940449 -48239486ED7BA4B8DCAF87EB1D2A8D1753E7EFA9468924DC0BEEA33484830DF0 -2CC726EB379B5668550B61B2D401C5D1012B16B9E2BF0A336073544F65124481 -F23611E8675B40FB28F393A1A8DFFDC13AD08A67AF396D454E3CCE141925D9A7 -9CCCA2D829E4DB2467F2F8CA1BE3FDC5E13120BFCDD7F0DDCA66E65FA69CC475 -866C8A62DBD00D09D867D0040BD804A1D7F17F3B8AAAB21FD48B11BD96C13774 -0BCB85CBA1E12A459B221ABEA106D74BC0EAED03ACBC0120CD47294D9D0F3B96 -CB570779E46519DA8854697AB48089B56025D3787243666855333F0AF2625DAC -502DEDFD5529924E50B1740A93E8B58C54DE09BEDA69B4FDA8A37AA6E32F1ED9 -B323763F9DA9A59BD9F179A567BAD612B8634FB8463FFB073184294038307E22 -BD0D05B160331B848E7D7243DC7EFAF26F8E6518855F679372B94938E90E7D40 -9A45E12A3203ED0047D4E2CBAF8D5AF2191EAE42CCF2E2939022FAA57FA90CEE -1FAE7BE6E23C4E32D372908E149B2096D480B82C143A26C604AF950FFACF596E -3CBD6C5C86EDE699622F50FF70D278E11741D18CBC6EC804F7803FA00BB693CE -2CBA9437C5041EE62CDDA5B5E4DA501C6841614AB271633E748AEEF52AB40E2E -245080043BF749542EDA7FF6B74C41FA8B61640E4DBA1C44226785F2E3DDC7D3 -B6B33B44E511C0152B679FADE241F0857C3CFDA8FF5E0FA4A7BA26A1A428387E -1CE83E956CD8AC28EE4F4A818B2F64C72FC65D4D5054781B6177E54C75AE1396 -505E5562B7F6CABC9515CAC5670A69AB00668ED859DFDB673378080BB5539A18 -8D347ED0D06DF019859CED07566B5B51376C5AF5876D3232DE8DADE7909B13CC -8086DAA5B7AC78759D0998A0AC451CB7B9491A681A58D4FC3CD45555B20EB170 -31466D6B09ED870E735606D2E91201F85809A24027035B2BC5761B71FDF655B2 -63FA45D0633E9A8D6890B6C4CE4A5E237CB48B72A2A2BD8D2176408BD8F6B2E5 -A39668D92EF921178190DB989A5C6E3FE318A56D799CC42B6B58DCF3FE6E8ABC -7662CAC717B368F886D44F0ACACCC4AB8E8C24D35869D9BAA91C64917796D2CF -DEB05E44A43074F1A53ABDE558457687B2D9FFF1AD7A33E64625B35E994FC613 -5F66CE83ECFE45777AFDF7C9DE3284C06670B8BE2C7CA2DC73244378FA73CDFB -02C7DA8AE1E57FD5FB6F41707D4D90C2A4E3D0E77D78867976FC53589FE4D0B7 -DD6AC71C010C15B3A8FEC1E5673EA53D928D9A90040FF6E3C30BABAC5CF8BBAC -5BBF3814E9709FF2C8B59C7C732B0C7BA597E00E61232B4B433A74646203F260 -CF694D67E878159FB571D766C398AC5755082BBA1B2A5E71546FCC94999E4262 -F18BE1A41E919FA7A53013621A6399A39C74181FEE13D4003468C7A343BDD085 -FFCF2E1EFEC20119FD923E97CE26A66780BD8BF09D66DAD588ED91DC369B0863 -C22BB347374EF5FD616A70CA07C91E5F48849D09F4823C8A02A6D80E4DA5DCEB -33D190D72702A78FBF7328A7D5ECC822D907B7908CA44BAB4A959F21ACD2A1C4 -6C6069DEE6B2F208628DF65FC40A05ECD8956505D43F883E7992A2B7621551FD -34C580D14136445DB52C9843BBF00F92537A65704B0DD575B1BA7863F971F2EE -479A9657AAE6627A321309A4A12DEAFA0C0B2EF5EE8C0F75ECACDD58E610938A -5907433061E78FC48581B87AFDA9226ED79555ADF9F0443D60996A1084B0B4B4 -C9E01EC092279E300CED0D34EDFD946C5660ED85CC0512F8A8982A7DF771E24A -D57B07A67D2745521178BE4C259EB3DEE7D6F820C40A2D939A4A484559207C1E -0719083EACBA076020776AF7C45DA52CB7173B54237942CC063E5491B8527185 -15E7B30ECAAA49124B9915D9AFEDDB98513CC30EFC161C9D1F2371D8E0BAAAD7 -44AD4BA2CE425A0B8ADDE7A5056645F9FF0F305E43E8CCB0869E03F0F510FC75 -EDA9CA416F5E14E6FF577CEA44706C2BDBCE79E7C692DDB097BD6A852A33925C -8A30E83FC93CA7FF3D60062F06DCBDC9AB390622768B7F2370D4FBCAD40CFC1F -061899B30F760D58E9787EA232AF7305F2E178BB101FE1C172D5011378B93437 -D19B7F3505A8A758C9B0C2E395EB48F13A5DE5B81C085344E3E57EE6FDC6BF35 -6CE8B2B48A59AAA519D2014818724948FDE669EFA9DD4BFA76319E84B6928C00 -CCCF36793E1A533E3E9822684C4F0B1A60297EAF24D79FD1B728145C2F2EB2D7 -7F0CEA0F72B6ADE7E8AB02501EF56772DA610E1A6D855AE4BC828BFB3F36E5DF -E1087B9732BADC3DCF7B72C1FA15A1517DE3DB6360630E55952A0DE142EC11C7 -0DA0B033C405457DE4F619647B623EDEDA588A29D9D457C835320A1FE2E879AA -18E5125E95D48EA5E1886C7C8B353CC3B5C3C91333E48EE9E6866E23107C24D7 -738BA7F34A9B9AE25C3DF1DDB072AF68202EE17413929E4B39C0F165441BA9CE -7587D7C6F181EDC1F55C51B7D8D04FFC47CB79038680FA609360A9BDD44F3787 -14CFBDB4F730BECB4876871DCF0811991151113C3C8F27BE0651F0B97FA21B6F -CCD040F39A945AA4549C0327A380F6F2D498CD074168EE3180DC205D18EEA359 -C24E06EEAA49F08474F7E441F4A2C7B11C6BE15FF0777661064B66A33DD45EAC -63B97B312E4B93C10F8E583D3827E6CB814EF8B73A6AABF11D638C707750A765 -92D5BF3C59B961569D9BC007DA19AC308EB09045F79D29BD970C4943E4ECBD7C -0C9148378BFC202102B297A6511E956BDDAF5A64B84BCC16BB6C4C747BA8D422 -508DF34DBB3F36B9EC0188EBE1A1288C1E3AA548B0D799D73DBD6584FC4F795E -1A4B0DE9D930B4ABFC9CB303CC0380C8664F21595EB9EA9983B21A4F3FB46D1B -E5A16D5C58C12323CBE9CA9AB79DF7A2776E1993CF3AB4A6177BCCF147117DEA -5304FEEC5903A4982A77793C4B360453F865540F5B0EADD4FDD40F85C72712C5 -07A6F447BE494A85494BA59B241540E84510B3BDF3B6927E69B006567C04BA6F -AC056E315F53971769687A314C874D8E62A383394A8C1359C9254432CE771A3A -61655E881B22D7FA0BCBE24C46EAC022992FD5904555D84612A168BDED0B365C -EE54FD4CDB9DBD9AFBC3EB392400446D3A125D3C375EDAB7D551876345FF6343 -1D31E6A4E82AC340B16B1266D9E90418E8F3796F1A43DDB762F03F828981CA31 -2DFB4BE9ACCEB2FBAA4882520B01D36B1A7A98602E9D3951B23D3E5634EFB973 -485C863847E780463B29F61C4FAA11250331A5C0D4A2E03A1FDA25D8FB40E464 -5384691A0CF3B929561C6F3E225DFE52C651B541B719FD7D60F1D23C8405741A -70FA5024A86039E1B2BC64DC37AD27464ADA20B980ADF292B0F53BC7E5E2F9D3 -C40C4D5FF6EB094A1CA0159EC547F0A19020E580A94A4833F4CA7B94190D5DB2 -20530215E33B34AC25C7BB38158C9369EA2EEA2EAB6A29499DEABDAFE5243255 -CDE450920F62BCD0C8B6455C3EF9BB44D987A2754B8D5253D1E02DBBF3A740D9 -A502CDADF38BDC4ED9CBF33E966CA6D81CD9DDE1DBA86A768EA720868AE9FEFA -3586048721720633D9B73F16A5E0BA13644A44D64C8C7F2E7B22E488D77B9177 -F27E7A960A65DB9674C9471175F136E436E908D10DE577F8E318769DE0934EB5 -15C9AC907F2799A2123A745D3813FD5CFBC260A454797E8EDAABC2A727B23DE8 -96026CE2CD0FD891197D1751AD87F1DD61F2B5406B3390E67AA7A942FE0F746D -0444E21D51A6A103FECFE2FD2863EB1BF9FB55BC75EDE6D3192FCEB8267C656D -7186ADE66BA749E1AE37BCF784A1E467D0B83C73ABE2550510AA57007771DE91 -04485B4601D14ACBD97C4BE879FDDF748AF1429ACBF3D41FD918A4D238D26F95 -9F86669789C9D03A04FAB2308419482DAAA77C47EE164B276257F0114D370F41 -82D109A24A95107695F87C6459A7EA5A28A83CA6F45029E32DE497E76DA7F99B -2A87C4936275DE2DFD7DA865B8FF52668493ACCBA80AD419443D1B2C0659EA69 -D16680F63A27DB05409EAA1E94613A6100E0CC78F8EA507144C9BB13E29CB482 -5A813BDA35C973616778E273A01943FD5FDDDF7489FA4D49C50396B07A06C86C -F2CDA26CEDB033B50E06F817A4F0631E0659E49726DC4A88F6A4D3A355F9966F -AAF445EA2B16C547B1EFF050879B3EABAF2B868613E9B47AF1AE7E90847123A9 -F4E09E7D25D6778A87011AF3E42B8F05AAA2989AE67FD8DB9A560D4C75E79196 -602996F939A0121A321DD323706068FE1CB46B0E95DC45845F14C06D9437EE31 -2BCE925B8742D0A1A226F225D7EC6A7A807DC1977C9195D91771BF8A5B2BE31A -15D4D206107421213AD41CA456E3025F069432F21C4AB291D9A548C65A49EC2F -7A1C5A640FF17D8BC4C04487D0CAD2E08DF0F0524B67CE49379A1E81DA971A8C -CC237FBBA08A90BD4A882DA93F915C7F3248569BA03794B9C2F12D51691B4CFB -CA5AA67E71599B33585E21593CA83ECB9CFDD5C547DD87694206B0AE32372B06 -8825223E060F1BECE3FCF5E76B5C0F963B7637EF59EB389F12B5B0CC5DD91286 -0673258290FDD422C4450B4A9329D0017FC2105E09DC969232489507B76CF9F7 -E18550397EAF067B3A9E0347970994A6507C177EDB973A69EF7C382A941E69DD -BFDB14F5B3299BDFAE7CCC331CFB83FCCEEA55026AAF4757121A2F577F2EF618 -ED54EF62FADDB76D4FBCE11FBDDB7F4FD6B919E046B5A0346A0539C598CD9A22 -BD414EA34E25FAB77D3769E05EEB5A0FD51EA9C7A2433DB5AE9955127C403910 -2B6A66262BC8B0657A3973F1482138AF77E9F8774C2658F15645660C90973B23 -9C30EA7DA830BA0C55671AEDFAF0FD96AD60098E768EAD067F0A63E06B0CEA3B -B7E6B4F2D00F575DB0A6B078962B4CB9709A343EA520E57E826C9E89375D7F4C -1231463A236751F69E097A994E4043DBA8692D7E9B16E214575D0F2978518E66 -397FCA66BEFE1F4A7A1B7CB123DD85A90E1A0E88185EED105D7995D0EBB936A5 -76CDD7B4791AE48A7368912404F3A34A2AD049E694CE9B3F3C648143C7C2D6C6 -E78B173E08B7129A1C443B6D4A307341184919EC3FACAA11B3DE39B10E855749 -99FF4ABB58030091CE8F975FF327D2A824B95437D993702700EDD7850A7A01EE -3DDC985BE66619EEADDCD13B328CA490DE02087FDC35C1290C2F5D58E1ECE85D -2BF79955108608606229028ADDC9EB448CCC54D7381C7EA8F9590E1BE3551FD8 -8D8BEF116597CD277E1A6DA692F84C83513E4E671D6F48EE46A78B7BD2056948 -CFA4DD257747BFD38E6813A3D83FAF54FE128ADCCAE38D74CD0486ACFA15A6B0 -1D8469984101347A4F34DE18417F089C197DAE1E9E3CD5D8D8FF7A09DB77BD00 -986359424222FFA593449F7CE00221DAD4731B341B11066FD3DB5138D163EC82 -9D89F5CEA8EBD5B9BC2FF6A7577E696A3787B6A07A8562648EBF9C1435B0272D -995814A9B100631205ED935D0A50866E74A8E332E31654A57C031541B0DA849D -9B8221773B03527FC9B32F327842CC6285BDC49350501D8F7B728CCA5AE742CF -010F8A859E411DEA98F1ACEEB0F27890157F804AC9CD2B3DF5BBD1EA4C72BB26 -0133A4E0B21D07277D7792E076D7F11EBE47E673972DF8A2AB1DC562B0CBD324 -712A40198D448E0E5AC50F6AF123DDA23DF6AD4587030AE9AB358A64E3D175F7 -D278603073AA2DCB65626788B2919F675A5D41432DB8DC56B946D2EAD7D29B7F -A564E0CA7E8D37EE506C87D574B56E32503734D1A8B90BB97E47CB057FE58799 -603EC3F828B7A5AC3863CC169C0D8B40C204716528F4FF3BB206DA9CF7A0C325 -176939038B142297A349CB7BFD48022CD351FB7C99D2827A5F51F4772C437B6D -8BC7DFFF5A46DCAC13BBF46CF14A5D8F1E9CE23FF35614F408BFC9DE7F36EE5F -4947F4F664D5CF47E53377A4F9179C83D62EB8BD87F133BF2E4DA3E4443D8BE1 -2F206585D371003CEFC9BADC4547C28D21773D2853459EA4E7790743E1D0A144 -56C80938A89879D0724B79C8F883896099B9399BA2D7696225332A1EAF8C1365 -D582481D1F93A28459D60DA6220F602CF121CE16F62C22B4F98F379CA401ABB6 -1843F2A4E7096D3982CCB6DB6DDB9ABE784EE9B2762D3A8E5768558755C63698 -7F02DECF75D2FCC99CD93494E8C5021D3B48F10E153020A5E1EB547311E3265F -109263954E7DB3409462351B6311ACF63053ED32904B98701A6B99F59915E9B6 -2AD813EDA9523A4BF3E430D8793D10E830E6E620892CCBA72BF9D437EBBDAC7B -B237AC58DDF7A684F5A338713C78396FFD6B92816647444BE9BCDD8CA0BB2E56 -4531639B3D74D2C2B369A79AE166109F5FE26A55AC2E4F7FB25A0D4FABD0FE99 -621A447278BE95EE1D72D60B5B5572CD302B01989DBA8056CF701E4C59FAE8A8 -D8853CD5E21952882001BC6CEDD8E195DE5EFEAD54C7CD2B4D1E0AE4893BFED3 -6F5A4E156D3B4415EB827F7515405C825CA42C75B9E9761FD797078A81997863 -99D1A40F45A65BEADEFF5B1818C8DF726B7129E984C33516CE9DC16547C158CD -9DBDA49082C9693C10A08C3B623ED921EA5F4BF064CA812607AD44B779C9ADBF -5C7EA8BD6F0DBA23B2F8505EE65D2DC384ACFF2D1ACEA8E6C6B6F18149D48D19 -96B365FA505B474B7C9292701736A0D48EDFA11152F622178EB33156291EB6B9 -BA958F5ECB78F96BCEA8D7DAC90803001513FF64E4251C48FA3F4AECB8CECA8F -A3247EE067044CF459EE80D7DAD8F02BD6608C27A6FD5BB9880514A7B1FDB33A -9AB70A3700CC5DE44973D1103EAAC669DE3B41E53F9D6F40F65580FC1365E0A9 -6303A8545B34A00A20AFC15851942FE866CC3F1FCEBB71C9673B5B5A086108A8 -FFE0B0B51DB22813E11BBBC2EA53383DCF2D7B719680795E05541B026B41B6C9 -CDE5B88522A362C908D0E65A1FE1073068507C63AB8FF157832AEE7228BDCF26 -7207EFB3A82CED3A2411064B24C50A24579A2A66A6FC70B7AE48E544B790D375 -7317DA0432E4893F70087D68F8B382FAF770C3B0AE74119A7474265BD6356FEF -CF9AB053E9F2F53E49E800969C7D6F128C69DBFABE01D464494CA06C24E0DDD6 -93FC8E0C026D68DFD3FF29A6F6D5D40928E1DE1351D457A6750F1A75DDBB0B13 -343B3EA6791AC35A8D72E685073B01C0DDBCA8E07D8ED48EBA8E6EA2CB380118 -6D65D5C3D1C081058FC9CC54E9F49EA02A8FAB4CC126CF85E51960C402CD7A55 -E8FFE2F22EDB8D6458F97E48A901CDB89BBCA78AC0DC93C1AF4D4A91D730FDA0 -577B7F5E5540528E36DC29A5EA4E99C3D8A3D95B2E9926CFE3B29FEF6D55333E -B87C4B28FFA9A582203ACC9528DACF226E78041B2E675AFCB823ED7B01619F5C -7E5EE4F4B800040F96F2693CB79F41A375D8C502E1253D74210ACC226BDE60CA -F7431720D00720D3C900098D13D9775A4E94A91801C5D460DFF396319F49AC57 -D9318CD4DA5B30FE4A2AF67CFC34961EEA35B985D02F41B4AF51679CF1131327 -78C0A045D5D259494F86B486767B0835259C9976314CDB29F0E70DA314611903 -BB43B448C7E0FDDCE42BD623D2919B0EB1B0D5C92C0C6D44FF220B12612A6E9D -087D4EC32DC0164C3C1EEBB4D42C24403DDFA87BD9397B34F4129BBC1F5DCED2 -EC698ABBBCD76137BA92DC8FF989299B5AE9B0C9FE7A7C4C6AB9A98BB4D9F86B -EBB1A5ECCBA6633459814589DB7BEE88CEC1C1C4BE0792027C736C74AE0ABBA9 -B7AB5AD51FAEADA4A53684D2BC12E6F60C3C19899D6DA7A0691CAE19306FEE5E -C3E3AF07D6D6D1921DC57C02DF25F3CEFFC56AA2A284FA26C99C467A603F410C -38642DDBDA66623FD2FCF0A3BF49252E1F3B1EDCA0C39D6466998A06ED2D59D6 -33984620E4C5190365AC6A15852E9F114B7C6BE44631184E620CFC547B061DC1 -B0F28EA6198560D45E951FE8CC2F375B3F29954C14E7DC2F1804218C28AFF3A8 -B01643302DA4D47DD87E5C54BC270A012E3109526E5E78406DAEF9D91F410B7B -06400A2A08E2096A391AA15D3863A7D276AC17FD6936833A707395DADB969E29 -ADD9E78E54BDD88E66292953ED2783010B32CCF920349E866428533680CCE907 -F6F0E92F2747FB8A090F33B2ABE187D25DFE64B65B333CC84D730A58DD47BD30 -D55755AF60625D867503C5E5E5AE2B2526E7CFC602754DD6AC4CB2BA2B81F160 -10147BE356D1F8DCAF71FBBCE217456605FC236B8CD696B617E4091889DD5481 -FD861F9571C92DF7B4BDBA694A36B23FECCBBB8D44E51FBF37ACED02CA5C9409 -2E8ED9A632E1DC490D7166A23F71572EE8670C8A718DFC74ACA4A28409EE1A67 -FE3CEFA903307D670CE1C938D2958E26ED0497F4BFBA845EF1EC62A3C97AFAC9 -D37A9785B4F9C6CA19BD85D5166C4035FB1806A7480451D6AEAFA0D64803792C -E0B184FAC3BF110C337218585C4EA31D4E76E292328A93194BA54AE22515FCF4 -EFCCD3A6BB35164AE4DAFFF7CCC786D9E90BFA2478566F41A5ECCD277DA32B7A -10ED094F6E7F054393986B8B7E1A08179F6FA3935BEA925CC8C7EB0661105B64 -07F9A35DD203B9D5688A1DBE7E4F52A57F439EB54401D191F0AF6F9B73E45FC7 -0409361F3A7608C499DE7BDDDF831D4FC1C7442E1E713AB71A4D38210B3612B6 -15F9AB3921999286C3CE9271F36D738EF691E06468B06E3FFD19CA3181CF5693 -A0E7C2CCE9B01724AB154D6510343784B3EF0DA3316E65CB37EEE337BA295447 -7ADFA6BE5D314DB0F596999279BD833E280FF84A94EFA52030033023A42F932E -CA1F9A2177C83A6E9F7ED2FB89D4AAE5BE8F2C4175FFA039B8DD7FD9604DA38F -8F1A2D98B7143D09A27CB1AE73E58DC9FF4CE1971E6ACB3FE713D3DFA13E7C53 -B2454417A5DAFDAFB094C0811D9A12AD6B212A4FA2DE5A09E4FEC5D99BEC5222 -F8BE9EB2B7 +5FFC9C7EACE612207FC80AD04F0CE33A9308DAF6F02EA444F581D7EC9637BA31 +D088D619ED30DD76E1A2D4F2450E4E7470C9ACF7E73441A9C1F627CDA0F32DE0 +B7FE8F7DD39AE7D4C671D775FA71CAC0E3537BEC8956C46DD81C4B29B4C65873 +DC053BC3827D0947EBB8CC1DF80DAB12135E54AF6C489598B58A687011F2019B +3A6ED5AA1797B6F58F3BE160573274624A55B69129AC4C86B33404FDE406D5F9 +76D0E54A25FE781008B57DB7C863AE75212D25AE5B959DA89CB28A299656B276 +36D7113C9E7417E647E1FBBB332C0B838B6C082598D7C606E50D7E2419EC543D +73E361E9683B599A2C1050C5B73BF815A467CD414AD37F41BA211B4BECC383CE +F8FC5696278F0AE855A1101E512572FD3F30D60BAE1A0165A568B53BFF23CFA0 +1CB2B26C973E5A2E0B5FC41C5A617CE7773DDF19EB06A6472357F18F5FB5B813 +9F7D3975EE660040E0A6005FBF0EDAC846F282D26F0017681F4BFB857C85AE34 +484871CF8D84C81D069D8A1E39F4D593987A2310D39647AC136EBD7A3E3F33DC +5D56C33299287F3C7D0185C63C3A461DFF50DDDF11B60C4F5295EAFFBDAC7509 +876C1FF578FF9C735AAD06B20557CE5145E26D92B5D243066B90929ECE3699A2 +42D917A060AA52156666C2EEBC8DAE499A76517D1B446B248A6FC4CEDC702AB8 +1E7EB23B316194FEE46978631540C3E03F894A7B1F455AEF9B68F03B60F65C53 +1D145E11BA5A69005CA707CD5A40A6139F79E9CE2358861325CB6F8A415A581E +17894B6015061EF692007635A2A07B45C5643B472F5D643E9370CA65A9600375 +BD48A9F386D97E7EF73E5ACDF01C002D6EE4DBC308C6DF6A1C245AB275E82710 +5ED190872415C399EC6EAEDFC8112DEAF3A676CF5EA79EF0ECC1D0A282FD25B0 +483A086E80D6FA1FE0667F9966B4F5210F4795109BB464B9D9E65A4CFAD7C76A +65C58E1E17410AD287C718BB31F45CF07DA667FE54D204BB249CA405CE1911BC +DB78A66EAAE856F78B9E845F4A2308F26A3FD357754C7FF2CB3E67620AAC7A94 +D68FDBBB4CC2EDF8A16C1CEA9CFEAB6F365697A2DB8C81EB1AB24AA61B2B9E11 +1F14AF667211FE2EA12A3752961D4703837DBAD5FD3B166360E3030E4551B229 +9877545DEE34797938D735C433F6D1A5DBFE270697080CD2A37A0CD58FDC2709 +2D0C0DE31EB495BA7BEFA3EAC8684AAA7335548B76BBDB4DD582363EFCF31683 +6000D53A40FD1A58DDEF046F0FB6EAB9CC1ABB4EF43BE3290BC5FF3CA697058C +467D8152088D39D43FE419B827E3C871CDDFA5D45D187D06CA3AAA955FFA82B6 +493A56CA4C09B8BD8B81B2708CEF273DC837B3FBCE3C4F65108C3485EB3B1A45 +FD8C8B349DE0E7850A34D6310E51DAF1770D851EB10718FD76224ECBC0743903 +6AC4FC0B2C9129FA25BDA33FC2A4CA79DDF407D6779292C62461E803C999A03B +02FC759C1AC63A85BE4E9777CAB832739FCC2D90E042B0D45417DD1E60A0EE16 +DDEEBCA50554BBE14B80B55FAECAFCBD1D06EF02673AC032D935B86D67EF2182 +FC9EF29733413073B7C8D12B2D8D2946F86B59F4B959AA5B0E67C3466BB68C83 +DF22FFC1A1401E53406F11D1A37871991E653AF8963B7811268DBC09A81C2CBF +F923C5B77FB4154A2B639FE3A2C0ACAF8CE91DA065AF06B5B038199CF7AFDB0C +849F57D9BD583A842EA47DF51A4E55636149C9FC96042B25C1D58862C9A7BAF3 +14E7E9CA614300125C7402CF26EF183AC60B5492C5B0434EA03EA166CC830A26 +341D91F19CE201A56F6C31FBD0099875C164824B4E6A20218CE74E70B924D73F +2597FC32271966F0B0CC099C4D80D291113AF321CC73ED180DB48ECEA10F975D +B6519F1FAA8B24A0851C2BAA1725E3EE1BDAEB900F354179EACFD9DFC4D84C9A +7CC3C400B42725AA7EA24E69C48A4E909E1170A484E8D836EE18B44F765181F1 +240815E42C4FC2ADC7811DC3B4B22450A410DF068FB76354E89518A4C22DFA78 +87CAE6D8FE0AA3C77AE9AEB76FEF037622B7530539FEC470BE8E76087772E35E +F5433A47B031CF604B95085B6DADFAC82391246703B7A34C9A14A296B29D5635 +FDDC90C029E76A042F505114CEDE5172F4261FFF4A4BE84A7A20CC9A9995D292 +0DB8BC24A9E50C0CDF1871074F86FFC52216583DB2BB7812A768C04B7C0C02C4 +4ECED1325EDE241AA7202EE8B39060CB39A29F71444A8296C71BCE0327D4E439 +A3752B13C5C32E88D3E298137A0C7503FC5570FBF79195A7B656485640209E48 +688663702F80021E9BDF9769EB5FB4A3935C5AEFA1F326DFFDD8C8B3FE77F74F +7DD1CB7EA7C30BD10464F5E63333863AA12D70C1CAE49A0741B3A0FF1BBF665D +49A38693258FC9A722DF2EA1E220E66F8225D462AEA02855F32C598BF160643E +38D7AAA68789A9931F015ADACB819F18FF061C136E8BFD9FE028508AE8871566 +646CB448BC49FC14D2B84FD3781870D2F3C78901A8352C67BF2DC8292CB90013 +F9B1BA4458A4A20F119D4BEC340846CA83A57685278E8F864F561C3EDB1D4CF7 +A4E5EA475721E33350EF7C979AF260A0BD6B790A0869D138EB8A730F2D5701B7 +7AD4E3CC0D90FEFDA2296FB036CA35F9BF11DA136DA4FC094B7E2F767B7841FF +7A7C7DDDDC20C43B293EDB47A6F5C6210200B05753B7EF7A6B9F830283A7D7BA +2A86036CFECE1B8DF87A60A920DD49FF9C6D2A74469DE8416FE86B1762DB624F +FB1606998C2301214F13125C3F5FDE94D53BB20ECE1AA75D70CC7BB7A315B704 +4CC3557F9AFC782BF947292D29076A8AE7C52D8F01372FD207CF90870EAECBEC +D9B48039B2D3DA67DC479AEAB7B67D11D4A2712F7A9C3CC81911564F43EF3AD6 +6783FF1DEB9F369208C7DC7C49EDBF9CE337DE885D70F07DEE03239562446635 +4603F240D27BA90774A102D009F77DF7FCA23B447038FDE325DCBE35CDEF04F9 +56075BA6537DABAE012A088709F0186630BB2C756F9AD4826836D4620D1E475E +F441E5EB7C04DEAB39B06ABC33954A261AB1E9282EDCBBA9F62AA5A7096569D8 +3A6A782CD1F7D854D9F98178A5AB443F09EC7A0A8CDE31A9D1F1E1CD92AB3D42 +7E5E2C137397E8E47D182A9462105D10D7F20B57FAB1EBF65B63AA09030C5090 +DDF53E4371462EA3607831D51364DDBF29E9D8B66D0EF27C4F858100D3746039 +A47DB60BD35200049B80782CFD3E156DADA50ABD445B315F26DFFBDCE640A0E6 +EAB0B79BF78D8F32B9BC288FCEC94AD49FE622D24B9C8A7F1921179976C5E449 +601D34C7160B9D9D342E78D0DA3C00ACB48BC78267E2A7D6CDAB86E06EAC9E99 +E97D129DD5798A617E3CDEE079ECDD29D2BBD4548AFBB4F6BD5F580EE5C7C5B3 +15F42A98733F1D10EACE99D9E2E4568C245F3C03A243E7723C875D275D244F86 +97126117319CBF89B6D57159C0C97E4281734C12D6DA5D756E484AE8EC628AC9 +78C8B0E49CF86C2568D6B5750AA9E8B3BFE77B018DF1AA8632302097885F264E +385DB9C64DC178A31D2269204C78875705FEB7D845C813639739023CD378FF6D +28AEFDFB2B30640594E74BAE5D665C7D464D6346C316F2C82DC088A66183DE9A +365F21267322440203E832F52FF1050AD3661B850CDCFEAA89266E2010164EE6 +49B6C049DE557787500AD1EAA3A4FFE04813739B93EAD90D8AF4A901BD7D88F3 +4B57284EC8A9C81DD2C74E8BF9FC97B06FF5885E2296C86D00C7E6C99928E403 +8654E11820AB502B19070D3D4A1540E7F8627E3F1C921427DEED9BB053D34039 +3086BD5D33F1854AB736BA455479D9184DA55660C162E9922FE3C6D332614771 +B50D6CBA54AC8D901BB425A2E72BCF38F406E94A2AC948C9028229C371660FA3 +B2CE5D94D82B5559AA234F98747E60DFCC6CB50074584D09CDC1F122C1A53B12 +04F0E28E635BA0850ED6242200FED58C7E99B8F8BD385DE3C616765B66B7165E +1B088557DC0C20A107F805F129C052CC6EC4654826B6567AB7D9BAC23D343BE0 +E030E86195C3576E8FA2F005843CF59555B7ABFBF05B07D0E34E6C64CDFEBF64 +3147364746BD2083CB68B30C677BE23C278918A73E955DBE0578C42472C4060D +BE090E710A84F29AF4576E4F9E5F324B71B75C6635F52F8E68CC98FCEC5A6392 +8812A856BF3D9975503089AB0277594D85DC4387C3FA402A3FEEA2F3016F0303 +351146DE4C2C05F857A8172E78458C0D906EB513AC04634C1ACD171E09440DFA +BDC2BBCF0BE2F17258DF3E580A4C07EF36A67FEE2AA8CB6F21359B223A3C1F0B +D4BEBC10F1F14FDB555F3889543419CA01CD5FA51AF80BB6F08C67C432880FCA +5C922A7689EE4F6117D5DCD30858B0B9ED62F26167CD06639ABCC6C8452239E0 +C9747A97B023C51579B8CE639DF0B1F932D0E39FE6C0CC8100B21007AD07800A +2A68A95A68DACD1E311952FA9FBC544BC1180EBF3FADA486D8A8FB310183FA75 +A0217363F38D41A2A58B783ACAEBD59B75C9045359D1A42A1821717F7AEBA454 +3CD0289BD7474ADCC2F76EE6A056EE469834A7FBAC024EB49ABC18C1C96706E4 +CA1D426A6548EDA2B8A51DD4DE9F19F8B80B21BD41B3961E9AE59894FAB49C72 +198284AAD6D067ACB681798BFDF4AA25E550EF0E5A1B5E3180643B119E041865 +30E3CBBAF84F339FC734DC002A4ACE57CBA33AC903033ACC2A56319AF2C2961F +B5AA4B4E6D58D86D18EB268A9B4E806C13D9526D00F129E700F7561B1CA11F7F +6D0516B05FBCE8BAE2F29A6E75104061A253CAE53D6E4E6458BB45AE5EC7D8C2 +1FB57B4B2F8D1781808CDE1D549FCDBED939A07BC30F0FBF40C48FD1BA6D4CAD +97707201F0CF12D1B15E5C04F99E37EF95C722343DA6D303D1821DFF3BDA65A7 +1B86B0399FCA317CE0B92BF144515F332A40707676EB91B9E1A8FC283678EBE7 +16E85A8F29FD9197937D5D4900D8BDF772399E6FF176520E0CA4824969979C3D +CFCE27E0B95D9E9C55007626E9BBCAB579F4371932BC707A5E6D6F375449AA71 +3DF51A75DA2F7EACD19FB990CC40428F089364511C47402471E56159F7F20E64 +5DE1BDDAAD025CABE92E9FEACA2EF5AF5C85BF7AE461138EF7FEC3066F42C825 +E0AABAC179F9A609641AB2B1C0DAC92D4C2E8FD882590135233E7BC37CFF2DA9 +622F8B8A0946E32AAC35A3069D0FB90BD7B1ECDFD87D07DDBEE2857C74522BF4 +EAAFE072801F32374D3FB53A99160C3A3027CE745EAA94B3160D2EE677B4DF7F +D51C49063A552B5E6FBD03E78213EE97A394866DCEEEBB6308BB4D34B7F4DBEE +36FA3514D35254AA86CC3EFAE88C3F30D3C38CFEDCDCA8E0CA34C96145729C23 +7A2D623AF4F40A254C1C9DDAEBA83F464B7832423864B63F31AA58837C920804 +011A9768A77E87DD0822CB832707B51E840E13E06E6002DB41A3C9A6B6536146 +62CF68AE69F040A09E09E2AE5ABFF2A26D606CD08E1A180CDC1E439CB5C10B98 +1C6117987410DE057BAA2E7FCFB468F7115BA70164DC1DAE8EEB95C46C65BBCC +A63461B170D55832036A9CFE1333C56BBEFCAFDBD1EE68E5BA97E80C3587910C +47154BA2D06EF77AE06CFED0716D0F4A82932AE35AA4724C069C718E7A974DDF +386016899CB303777F997EFF71A1957B7BF017266C49AB7668C570451C1A8614 +0E4741C7A8BCA2078463A1D131F3E75CBBB575AC13FB139D01097C32FA14DB10 +798B803F36C905A5434E3201AE098FB39EC87294676C015C8F1E682C4499EE47 +7715B8F336DFA57D50C6C307006A9B734F936A6AE904B728829B3800D08EF5AC +99A90FD030FC88053E218989D6914630F711CA04FF17790130953C2044B3B51A +19CB91E5C6F671FE54BE8513389A681A32BA96A2184DAE7D7EA2770FF366CA22 +8536CB888DB331F9C069196BDD7A24F51A1C08693BCA30398008FE06FD01F251 +858D94FCD90870940E02D5CBD987596D82133D0732D12D62FAEAF6B27AB3839E +3BD4D724B33D4C2A5B400E929E6292EB3D54C7A256D7BDD7E5FBBE4C48D59E75 +585F946317FE740A4C835EBE7A006E74FA3B81D971104E6E87FE06B2DAAB9978 +35F1A8410A92ACA69548E84FB24970BC74D751742E8839C8E048462C38467064 +7242571A5804C1E69A090810A28642C144A6237776FF83601301B56E56C25FB3 +433DF2B03C8FEDCF6B0CC6F303F0C02E5F680A909A35C9BDC54BA2FE743AAD43 +30F9FFA5B9D073D840725B4C4D20FAB7B1C1F1AEDD9194DA893820C7F7DAA694 +68704F954ABDB8F27BE1E500E054F7A39A6433A2EC8B0ACABC41C07B902BF4BF +CC2E9F151C9B2F422077A99AA9E968C5438D4A1B11A55F8A1AE2633C998D6ECC +2388A7EBCE3C28147E8D867C2BA32D05C4CE3956C2093045473531C423FD4767 +BC1E5CC4F5742D262FCF797DDAC8CCF9D93C226C6E4680E614D7AE7D455B3632 +712DE0B77A46D6D634EE59B47D332766B8C2CAD4EDF3E30A3383A65A99CDDDDF +FA835C88D4CB7ED8FA11C3915B3DDD2375164EB617C1B14B019017BDA88F33F3 +97E717C7F4C415B1D7DCAADAEA62FEDD19ADD6BB14419EDD81740CDFB4AE3976 +F0013BC0574AE73178CA81CEBE438A847A885E9FF066FDC7C1AC4700283F404B +3869A901B2DBD29BE3E406922FD161496ABC3C17A094706517B2CA7F37DE0675 +4A6D6B9B893F98BF45137DBB898654F9DE9A4DD0CBA62BF3D3BB64CA731D075C +91F0573471AB57FA92350C5C685AEF0832AE4B2B6505C1361D4664BB37FEB482 +79B3E073D9CA0018C658E29E6C453ADA6A09B83D85A7C69814F439C96899E977 +8D66E375ADD165785106098FD562E204D9BEE5720D7AA0945DCD54EC39B0FA45 +F22CCDB717B137AF0472E1574CE886A6A536ECF5D6E56B02B1C9E824D66FC7FA +3F19BC401D3B79303B140C57775A3ED6A2B2731901F3B1DB215E6FA70BE03E7E +AAEF27B80B1C24523A3FAEFE16E510C1CD4BBA185D6817494946B997490420FA +A0F9868A42BEAD43395BD3D7AD45FD9CD8C7A4B8564587D3A0BD81D9141C5CF7 +D926334CB619FB45AB3E7A6D8BA9EEC58D5DF5DCB390D357DD439821E92B499B +868141358B5C0B99849BD7DB88F76119C83CF32D1F401A04C9D64722F3CCD410 +8AD0354234DEAC8916E88823FEA829F495F9AFEA7B78DE1C8A8FEF579F4976A2 +DE3F9F42B31B0866993643D7DD004D77FFC8D615B189B0A7BA4B11C0639C19A1 +ECA51D8C703FC01C17EA58621AF7815C1516216A90D4B88BC695547F7523DED5 +E46C085230B299992D46DE6CBAD5E9C095C42EC4F0AAFCC92C829758D4B76884 +27E48604749D7BCC57773D42AD2A8B759890536277A37AF23F261F3DB229E863 +9F4F4BB7E6AFC22A24ABE77886C05155760443A474D462377002F899328B8777 +1EAAA7809D6363F9BCBF1FC07A373829214BCDBB0902C1E65769F300D48A647B +A4E6DBCB93AFEBB315CE63072C4EC02B77CD57501135B8660554E51D18A08D4B +A2E78E3325AD08C8B0A24F6184ABD29242F05594C8A15D9E29F94D9ADF24D314 +55D407AFE4BD54B30EFB115091B1C261A2C3B504F1B47BEC757590445255B48A +D6F32E37444ABB5A63F5416423DBFB1F272351426B6E31CFE2E9672B83DF88F4 +0AF206849A3706D23B2AEF8235FFD2B48A31403F0AE014FB71ED0ADDD536C82B +A0A1A735423F1EF228DE2DDB3528D8DB5E5F501CFB13013CA491AD85E634DEBA +6AA2E2547ABE84FE25109997224EC3C8480D941521FBB5AC610963A9B2D60D38 +02993AA55ED964B4D6672A08343292D75F52EE8C6F2797F25C5DB17ACB8805E0 +5A4194FC3FD5529FF27CC9C2710B9BC8574220729E4E2C530D7817D814839FC2 +677720259841D034E5C449F42C0A5183B64A9DE959A40BFC7E76A480F65EA665 +2EEE2E558893A536A4F1E2D20B905943AE8CDB2BDC5D2FFD010375AA4337A75A +4C5C4A1BB5792E33AEDC93FF050802F521805F14D6E37365A0B3DA848BF18DB8 +77C99B5971F4B55E3F342DC7AE1FAC79DF955827876C5237FE22449DDF27A26C +AE32A85D051D4FF70DCCC70DF46985613E4864C9874B1B747550D455F133126C +BD3CCC12CE621638C42661EC231CE8D2CE153E143838C54C6F90D514E2D671DC +CE713CA984ACCDCAEA27F59B1AD73722B4D572784973E835577281A4C48ADB3A +D028D22548112083B6CBE43E6405158D3D0C4BC6C104BA72D382E96096C2BC67 +BD61A30CA0FB181D7C93782CE53DA7AB2DE1C1290BBAAC579A116137E9278245 +8572B1D5B9FC7A0ED4F3F55B79094A76A00EFD7AD167EC7DB148DA03E67C80B1 +D3D202E1C96B9F94499D896F8B975C07A25F1E75D7C69292C4F071439D52FB5E +8CFF4E333A9144F713F8D013828992D12CD0342F9E0701CCF52FCF584F8420AF +75EA7B4BFD6B3E9D8358AAC14CDE6A35D5C80E50EF63E1FE616DE7DC0657C1A7 +E0237C1487977880A4BA55F2A77A8723076844469F278228A4550C7590626C5D +15A8A0817887D3A07831CC0ECB5698AFB5668BA61AA099B573D87CBBD6F1C293 +ABA99F331285C688AB7DC85E3D25D39B6A5AA6A18699C0398C00AB0A65F0FA03 +2D996D834B88915F2B7225336A052FDE88AF0E4FDB08F959664C7647AB62AFA1 +0E03E94D1111CF809DD4464E663916C8E0CF5F293CC307D8CD1FF2719F26081C +8E523EDD8CC5FB2F8FC2395802440FC0EC2ADCDCAA72A75FBC011659024B4F85 +FEE2880A7E80F8BE4C538B404DF81A2122657D4D07A9EA53F6660FF757C377F7 +B7281F501EE7C71E486C8AA6AE5A22F7694F08E8593E926FB5CE60132DBDA6A6 +8635654FBD68B9B15E5183B08F8BC9C57F87F37B627463094A4C1597A40FEBDA +CEDF9F0FE9B7C34F67D477ED61DDE142B94AE7EE452C0C4FECFDE7103C3D4567 +68DF28E6CE328CB202230BF8D10691C0F0B42FFC2595B29F125B816EE0DF694B +DC0CDDDAE09586330591BD4E9C7F515F11B86C06C44BC13A79374771448DE9CF +829DB77BE22376CB5720938D5B16ACB959C52A2BFC6ED2DE07ED182F63C49562 +6CB2834F8ADD0B532B5E91F67F1A838CF979520485D605F684DF9D03FEF75721 +2DA53BA7EDDE557057D5B0EF4F476C8BEB7CB2CE930129EFB00DC86D101C0633 +B77585B6B42ECC2CB62758CF0833D9B941E9D46EE0CAF36F3503BCDCC7DFD183 +7D1372B9C53D56D98D1D04D85761E9DA026DA6F67A7821F9695C36185C577079 +2750DEF13CBC790A6CC6D26B20C3AB1ECFD15A376EC0388E2B21E9CF5EF4EDE8 +0637F7F0B069C910B7A8FB4A7A304791E9C7B235C3BEEC57C65DD6F0276AF51D +C7C4269504C7C176A361B468527DE2A3A705AF9697E16DD50ADBB0E84124E80D +67775545D05A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 @@ -1937,357 +1937,353 @@ 23DE9D803FD6E8D846B3F729BD36137E834E016242CD2F7BF048959DD45AD413 19B985D05E5D422F3D0968375EA6A90FBEBF8B42B15F15280469D69629C08A42 1C298CC027CC288B9C984239ABB96B6A891C1360D08F9ECC22202861E4CE9B39 -8BF32D2E5635B6583D04BC0AA187D10FE773067ACF3B528CD412ED96902B0056 -567103E3FD911A099ADDB9EAEB3C08F1B36A918FE865B7DAE1C49F21650E65F0 -C6845C15740631BCB7618A3266D83E54976BCDC707883E531F3F833AD0DE88A0 -CDB84D8384602B992263C3C223D1B5393DC98C75EFF9AD8D98A764228C70A303 -28D87B1A5510A579D01088C26D9667DB86F72FA302A3A8EEF7E05DD1835E72C0 -66A0728CB0DD8C34BA1D772886333BC78C79374026347FAC9CED39B7FBA84DEC -E70EABA29B80B4E813C0E6D5ECA5E9ECDF0413AF7556EA458C3C3B49A4B14A05 -3034C04E1F8665532D053F810683C957050FCF44C5D4040CF09893DBF641D68C -0969D67BEBBA6DA451D446DCF87B8243365E7158D89332FB33CA28F0A83A7A63 -D22A0948A46F0AB9B2CDECECDA40FA75B046CED41C017FF79FBD7380CF33D726 -B03304BF8EE1EE450C065BC8B83643AA74F8D45924181D1D0C52CE78C36DFE66 -99CFBD08406AB9FDCC61242472612AF009F8625C966AC9A7228B85912CA77A9C -832F9D14190A1DC798D4E99B5D067A020FAD7E13E2E5A155A94E46853CB93619 -39183DAAB590F1BE12C3C4B0209A93CB015E58EEA72C0F71E68EDF1CAD4CA776 -9320076D70BD2874A166F2CF735BD5154F9FBB219C868A568A7C176060F78092 -1E3661E66B7E0A8DCF294E09D487AD7F7D1ABEF83E7E0E5BDC60D672A4D8F5A2 -4C33479DB4FB7105158E19C62FB0E1B9749E6A9D4BFDF7884B1922C4C48265FB -7851C1116696C02337B64F1A0445396102B541EE1CA10D8311F79CC58F2106D0 -12FF6B1D274B810AF318BEF04467B5066889896BBF019F63DD5DAC53EDB1CD7F -AD10D90B2D3CE615546860B11AFD0D6B705DAC7545579DDD3ED867F31615CF4E -F3E4BBD8527C9C3CB4DEBE71F1AC965A69A1C6E244BD5A49FC81135A587EA904 -A863FF7D421C407EDE08825D78924635E6968CAC4399D231C785C9048FD8C916 -0B2676DB4D91487B862B25F68DBBD03B604BD875420565855CCBEF9AF0793964 -4FD45E490EFE697A470FA3C60192E660C45083E27B9E569DD1DBE07706975B9C -9AF2851279A7630999C92E9867F55D56CBBA0CA13A0F041CD0F3ADB318A0D298 -ED48F8288691BB2CE08B6A73E9FA89DAF661F201947BD64C1EB769EA3A0C6FC0 -3DC343AEF2379881E46627AD2F653B4C6BC37E8D8452C3A7E399C0B6B3D93671 -F51A92EEA7712A872D0BEBEBB071C83D9254A24C8799CCB5D2FF4DB31075483F -3743AE4BD1CEECE6B9432BB89399FE62B87DAB3B19FA924FCC1F6C3DCA1B0049 -51024011B8670DCE537387069A8732AC4ADDD77B2A0D5D97105810854595C4E8 -0663FD917B5B587B8ADA22351D79F5E5AD494FADE90336AFC27FF9FE8BC770D6 -0A8D6FBE6E45B3D4DB20E91A53D84C8B100813CEB9A81B03E142748475EEE77A -892B3458A3AAD744A20ACD28C7AA6C5A996C9A9900F2D6B3C1169DF3BF2B1A9A -56EF83195431EE89A89CCA5A0EB6A59D7D89179B6C127BA0981FE0122E4184A8 -FA9094D9C3D54BB7CBA31FD03C7048A09AE67C956A5363F5D51ABB19CA264D9D -5D515F61DBD9C35D259950530A95350A313CFA8CF06413ABEF844771BF99590E -F9A2F28975AFD00D700E83A59A3F0B7238CC74A8C1C9DB059C84DD91F1E07580 -C4C1311FF1C4AF2AFAA07CDCE72B0928663109CB31DE1548C72EA321F0EAFE9A -ACE0E0BBD840254E30D9A46162DACC79A07F21BA056BD90AD312A2D728CB94F5 -FDD65516843523741D2430C5338FDB4274162B8C0409ABF94581C1A3D8636BCB -78A98069466C0C869BA08047E9C154DC6FF00A1DDCC2C4AF4D5DA5437BD02616 -C0139731CAA7817984BE614D6D41E9C21AEA1CBC9E56C783F68364023CB95387 -C71A72D9DCD59222964D04650181988D140295091175DD985F5B53B070D20B89 -5E4B621C848C9370E0687B45EB1070A688A94BE949D242AA6266ED2D64C2518C -4A5E75442F030E137D2E3BD654C4E4EDAFF7B46EEDCC9090D537B6CE01DD6D0F -1872A47A04ECDED2421B511118B0628148D2289B74B79B3A68CA7A2547D644B5 -2ABB83CBBFFE319957FD2189E272DA2C2E35DACA8EE229F37EB4C94C920A65C7 -165A2ACFF7B92CE4338F3030E157CC75281E1F33AF00386FBE6003C4C8CDB57C -4EA70A31E2CD15FE6732F98BE47354C2F92AF632B5BA1C7ACCA3633ED13919BA -106E6ABCBDC11006BA4560AFB17C7091BC1A632E7870B65717656A89EE550576 -B5D3BD5DD829886BA59D186770871C3D293EBED70D66EE3AEA926F2AE6AC6CEE -30CE46B99DCEA2D15384C53D08C6F1A083A24C025D92832E16E816B893B3F2F6 -68BDF430788D1167B14633E0AD0FD74951C5826BE0F4B8CDD23CFAA88907C43D -1678FB2C4053E0E2056BC4B33F36A896D1BC212B0262B6CB59AB3A5ADCC027C9 -EA6A2C0F1EA2DC6B88517BF08AF54C9B1A4A7B0A4BB9A66ABECB539BB6BA1F9F -313F2A5619949D0FEF977DFB87ABB8B8DD420F3097B2B8BEC00EA5A3E8C207CF -508C7CA5133CA63B98A14E11FB57BB7C461D7C8C767DB10E68BCEA1D5A4B7F29 -7AE639BFD660B1CFC78DEF00CD1278833E48A65BE281C9438976BBB475AC6818 -C533FB4D2F4D3727B68F533D03554393D66FEFDAD1A3BE79FCEF05B98A5D9EF3 -71F4D16E531408B2D866286CB89B50DAAE9978B96C8BEA869F9E90B780F0C98C -1618C4F6FDDA21820BBA795B0AF3D00F96635FC5062544317A62A37060F965CF -3BF8A9C7B5C3D74914E0AF04AFFDA0FB1D1E644E2FB8125E94C480B4ED41FF6B -DE326A771B82A9C44B4DAA194D3C2A8855CA293787D7D5F466A2587860B64408 -6F14F78C085F63E6B63AC41FE7574E5E22C723202B7D42A1BE0D14A299231F75 -66FB900C2A030D0E09EF5107F9905A5C66E6A5648FBA2B8E80217160EB797496 -FE3D4904C8E3B6FDE528D1B931C369AE5115114B3701CD40B57457341D735576 -ABE1907500771C3EC5F562B63DCA85FAF5769ABF0F8F74A678E508A59802F1E1 -B11545E6C8697D1A7FBD4ED7A5DE57778DF66E04AD354E5A45E199615C6CBFC7 -7F6C232D710E8CD5F9953DDFE922B2CF50F02F65A96E1BEF0C1FE6B5C52415B9 -052B9C062B532A6B83260D13AB6D3B2A48D780E03B4519F4A2152B82D1A90359 -7CC62EBC5F26608232CDB89D2CD44F0E889AF80B1A9F8C0B9DE0EED9787D70AA -AFE3DEF464503D9E56674C9BCD0BC65876F2F455C83412E8FCAC08ADE7F8E2AE -CDA7A57425C7ACEF0D58CC85F71D8512B32D9C06AC001382A4095FEA02E2BF2B -A7EB6C298B10CD398780A7120CE9A31DE391C349AA273C890F620172CC434C23 -33265359372A5451C4DACF0C859BA6D37AAAADD08D2F85DCDA2399D894840D7D -AD9870DD307B9D602661D7ACA2F84FAFDFFABF5A89AFA9973161DC1CF3A3943D -CB84A9C241C8B6D6CBAFD2DDC75166C3C2D5994DF4D2C60739F34E7805582A15 -76191F4150309E55FA04EF8A59C4DF8EF1C95E57F0C255B63C82A7775D4CF3BD -A3C56600BB869D411A5ABE7EC6C67437B328DFF2F2BD6267A43D69B6788802B9 -249DAE42336C2A3DE75816951644C742C36C51F120943DE8B75052EE4405A346 -E157546DCB7D845D81AEB84E70B857B9152C3FA6D5F3BAEC8611C14F67B54DAC -F58BBDBAD4C473C0DA872330902A46610865EB0EF8F97078841AF74758F0E6E6 -3DBA2B1659FB937AADD1C8A612C61F0C1A9636F0624E64D6D92966D892F44F09 -48A4BDFC9A83C267ACEF143585C51ED45F59126AF7EBCEC2B9584B0FC6C1E670 -FC382E476B6C33071A9FD3FC2D0F943DBE055BAEDAD6702DC0F474F9B2DAFFFB -C0AF48B326EC447E31210586B7DCD517FB61F4D4870A5E467492F40CCEAA4F2D -B06BF4FD8B31D9650D032A0A28E1D413162C649352784A0414C474A82DC471FF -1FFBDAE7795DDB8BF3DF22C393E939F5634C540DFE2590D71BC1444BBD79A9D9 -7261CAC5207814AAA58D8B135A52A3D3174110FAE364257A6F79AB3B73B52A0A -EF08DC05593BD0327BEA4697339E45996E5D6812D166165790D8E4543C130DC5 -34725E44BB037555803390CAF9F94FD6BC08AFC3ACE747B9728D8CF0128D5B4E -1275C4BD7E50AB5F980DB3C3281E3FC4A500FC6DD0038D35F4F5589679647238 -FD7EE68BFA9AE20EB140B7277073E6F26C7EF556FD311D510C92E89B70762F42 -410ED318AFD46F66F605E98D1EF12F00727B3B3F21F695241B4B5863FB1C27E9 -6BBD4365B9AEEFE8A18AFE350731AAA0ED817498539433027D50C8D38284E888 -1E6A1E6CD54F851B264E2FC4597A6A4FE03C7CFFF7D1F75CEF43E97B22096A1B -D8BE2DC4A899E64492359B346D9C0051361B6AE9DF079BDF21FBD274597B3C02 -4D0FB1C66B8AE0AAFCE0C1CAC54BEFE069C0BE9505EB0B1AE60869B63C396698 -EF594E1C8E5995AD22DAD027BDBA4BF2FA9B570E8F0FA3CAEECEF6DB8C4819E4 -AEBD7165A655F1B7828527DCA9D01324FBFEEDD6797C8E3E9E17B760C70D7AF8 -8EC0AEBBB2C448DFDA6B6B4BEB43291772174F1C369DBD1C4183C8E00A4DB46F -208C324163E0BDE572A84B85393892545249DB26457AF5FB311CD5EAA11D7F9C -3E491B0D49C77898AD873381077DF84EF4498C012D7752B22F0660810B6EC0F8 -B66D447775AD659C51D3893CD2B4509E8B9D1413A99527F720571784E7B9302B -92175F1FCA726E8AD6D82B9B7E853FFA5739D0DE0A02BB115DABF83B1E4DE706 -C23532EE82BD57109F9A7A4E6A87DB4FF5C698B04003312F1BA23AEEE22162EF -F22F7D338554AB08625B26D74F7D23772532A371AEDA9CC2962B0B665393FF04 -0B032502628AC491E593D0D450757AB016B2C74C6AD44594E0FEC2F880B578CB -5C4D6A409FD6B64B9F1BD7CD8B69676814D169609D2ADB2F1E98F6C8F1A16D90 -63FEB3C8FC663DE0CCA1C5CFF03828FD1DF28678492DA710EA61B9096A173CA5 -FA8A85DCE00EA42ACCA03EF856F3F17FA32A69DF9F73C46944705C5DC20A7535 -34CCC3878E878A0BAC55B7D56CE2C43C102D0AB841BD4A3C5EA0379D321413C8 -6C2DF639D4EEA521E0A1C68D8B60319EB999707001795562E8AED4ABFAA486FD -C11D4F12ED45A04DC72264A882C97510C91F2DD77E3D5685DB2CE52C4746F613 -AD98EF16AA9773CB00735151B7D4B9315441BC3B8BDDA5ACF619F49B6052AFAB -0F19D9ACFC8D6E0CA79A25A8360F9749EF39FB60404E318BB1A98EEAD98FA0E8 -40DFD76BC3A84404F7D3904BFB2EE3597D8364EA556E4F7D18F32F1D86D10287 -8AE46984461ED91AE22B6EFE0CE5511921B539122DA3EB48707B8ABFCCF2E6F3 -9408D626EBD0C2A1A87827ABAAF02873B675AB54BC6CB5B40E697471320BB686 -9D845AD686DCA663AB31B4C2A1915C55A814FBA82E77736F7F258C1AE7B42449 -FD341CE08D65E648A3FB4DE280353F79FD70578A0C38C963461BE98100EE4084 -CC1DEF4E35B10BB81C632FF1AB4511B80C881A729EAB34C9E9D217E3A57EFC52 -6B73AAB4911830A00BA599013AD3BB83BD3DBC7445C316172B3B8A22B8148ADC -FF33379CBA195094D2C2CCAE0E260D8DFEC35153BB3533BE014F456A108C9D62 -5C21C1BCD3CB9D7AA0DB74AE571A88AF6BEDDB6DE3DAF92AE60187819E8EB8A6 -7CC1CCBB5F23E63A107EC8143F0F69B62CFC95605231FE605A989407218AE464 -C2B566EB86E1075B0D8FF788B726FDA5F5F2D8743C39224C2231A46426F3B6AC -747E69C46AC322733DC052641526E775F10924F0AF404C37BD47369986746AEE -ECC7CAAC1B2CF6E5D86A46F4F6AAA2BB7707BA4D89F1B46DA3024A84228E1A5C -BA5EDB68205AE6971A255381FC06BC03644D67B082FD503F502B28141D437C84 -E809F5C78BA5FBD5B8D51C012C3EFCA915505897C8099F0938EC15464FF4EAAD -2012A1239E0251BB126F4E400C170BD1C47656CC010235236733633CE22A43D6 -3E043B687B32BAC9EDB90DEA0D0B0015E8C1DE4EE0B0E0C10F2F50F4E35B31BC -915A1D984614AC0B10AF2FF1B28FC135D07072C0530C50FB6ABEBC1592CAB0C7 -2FF36245ECB609DD787852E5509AA57B3EC5F6186B16A4EF52ADF58D7ECD1D34 -B2BDC2BA556F7915F5293A8CB3F44E707A57F6CDBD91E90F9146874311F25B80 -A7348FA90D09459843F842FCCECFE4025D12B2BF2B61CA32E6F72B8618390560 -0157F80C82BC6A54B9F0289215D94C662CCFA55EFD0650B0ED761D98C65BD47C -F7CD595FEF1C7DA57F3B79FD55ABBCE8D30B1D0DE32994D52F8885A87F0C109B -D90052BCEF87DE36DB4A852E910C792C094D0D0228C53D20ADA83280C79E9100 -8AF8888CAB9835D6CE65D7FE36B18F365C4F6324DD5670157B37AF55B205F460 -D10A0D16CDCDA78539CF166ACECEF425A1740B7C8F02D13F2A86070416AD9AF7 -BD30314C6DC920E3CB78117564ABB1195397CD66FC92F54B5F1535C15E02F763 -C92A2F3F4CD1FEAD965306DF3614D0362B0191492905777B75D8D1C6F5064A1F -111B7EFE43756B4F0996030C00503EFC5351D388C150BEC0FDA5AB0E218423E5 -78F87F1B7684AFA6DC450EF115ACF8AC2C8DFF33AD39FEA1008A46EA9D6BABBF -B5F220B209770EF010154C87A4BC067315192ACEECE255BC6A5896C2F4963170 -576E250C3F8520E1E413A30A1C17F50F6E8D2DD87EC02320176F355709D75320 -D1747ABB9EA215793CAF3BDAC8F5C0812A630FE85D7FFC3AD199E5D83B068C44 -B757C8A127C3993C01E25FD94725415298FCFA762ED456DD7DBEDDA2F7AB71E6 -A289E0F59FAF62E3A2CB6A0995CC06838C8F9A6E19226B0E0953E2BA3764BBDC -257212FA3143D2B67D308AD49A0B245F0A97B09919C307B326D575F1F865ADBC -E292206795305174C193A4CABB0044936E51BF95D0B13E81F2C64248F1D9749E -CEC22448489B2AC1D766933B570E3471B4917ECB1D66E0A4779B084B1D22074D -108867FEC1329F5B30FA344C19FABB7C09A50F49A5B0A1C42413B3ED9FC39B36 -500AD32B07AEE4A5C0DFE29DAC2C6FEC431842A473EB710293F23774FB448E51 -3EB6B4A27D98078B2A4DF3A5F0F41308374765C86C0A879641FAD025EB77D7BC -9328E717E2EE4AEF31A3FD23573DDB8E81F20F6499FC2BB4C94D3F1054785E0E -6F3B8D6176EDA6E386FCBB034F6E82F6FE43CB83AA1147B05D51BBB03C477F54 -38FC98086DE0E04722C5F0CBF9270E0DFB928EC7387710118513A3C97C0D6A9C -D67BBC5AA5DA3A33BB0F534096582355E0B3BFF7E6536FBF496FE4E05F006F88 -C7C28672CC58838790821AA48534FCFB8DFD4EBA9C94E4F50E0B9E046651F779 -E11B8915503682E7FDD90F05DFFCC5A009CE64FBBD223E2634DC95803805F4D1 -C27B4D543FA3EF2B222DAAACF40C526B2A1563C0968E7F2FB22489810A530519 -100FB442B5F972F960FF6BD86A19A1F297F93DDFF83CE2347EA3F861596B961D -4FEDC423B8262ED0F0352DA19F07ED09117CA72EFF0CA7B666EA45493D1E1317 -559D4B5D278F107042D276C9AFA6A093ED696867BC1041E5F25B11C1687C8C1A -72DB2FCD4B632FC212D774785F2D3579BC0DBDDBC8CCFBCF7B686ED3BD92D4F5 -378CDE86406399B059198B66E88BB9EF7E572C6460C36B0F2FA3E19AC56F93EE -60F1F7BCE76F0AF284C3F41C8BB69F7D34B4644AECA4E9324CE2EE4E4044F4EE -7B9C28E8B454D894445AB47B05F7B4B94529808A007A5E3A7D323F661F9D9C0B -B5BF1C24FAE9D951AF26493C3C9302C4C040A33E94E6596246511185628C7A02 -15D33184493337E2543B1D82FD5ABF4F47E894E809C51DE0ABE163D378910FF1 -717FA82AD420E076611F5559AA027F1F82433B4B103CC1541D342330D9BE4592 -9B9112E1FAACB0FFD59326ABB3A352C54D097E0B79A91A0CB39B77AABC40D191 -C895ECDE7E9439DD2098E2D81E56F13F178CB8DFDCA5759C4580BF1DCF7AA3AE -83F2D998FF3B9789DDD4B2A3E1F5CEEEAB48CB410F5C07DD3FBB4C362BE0D32B -5BEA9A428692EC6585A20F11A5C73FA22D023131B1B416AC0B2F4A4C801863BB -D43B180F82391830064FBCC5A233E3ABC5B30C1FF8155C61E589604EC6C16E48 -F3C676C95C57B8E9D4305C1B1C7ECD75B3A5C7F8B8849AA1B46FDDD928D92B21 -D0B6FFBAD0B71D101EC153669E32324C497CD26093D0D2E4AA197F9D5E459C50 -709C64D20552A3B9DA9475D3658C302B5E7EAE0DAD3F9270A327A6644AF5C3FB -8338C062F33478E38E82C09510F27C2FD1FB2D304355F28B35C9EDFA0AAED925 -F2D1493BECA291483EB47FF0442C3692D29D10FA92ADF3C9AD85D5AC09D35949 -166DBEBAF7D425DBDF179F8BCF21912C5A2123E869DE9A9CEB4803F2C04414BE -45DF573DB40F5B9E42406F49862C7B23826CCCB05E76BA23BAA5A17CDA93D4EB -59569951158FC068E32ABDD8930D6C4C58A7DE1D39030E3B818E3382938F466E -47E8189A6B902AEE4798286CF0C032E0F2AD018380C904C2F4EC61ED98CCDF25 -9E2C691BE9812FD5E0CE01F2C94134C9F0C05F4B7F1260DEC20B9907E1B5D372 -8677FB4F0485ED87A3F6EA1A647072D635F7E2838649CFE37A4FF8182882BF7E -9474583F4E9D3548795E0A63D4859BD27B662D156DD893B3799371DB1BC75A38 -0F454EBF825D683CF2CBC8B308AEE9D8FF8EBB8A7DEA067AEFE8CC77331156CB -20210ADE2B5DD0A9F77BB6E98F3630800BF33915E73E515B34E58516D1AD87B5 -00A8969EE2595D2365AD69FA4F67CCAA7D243B8D03FB39CA136DC1E5FD434750 -8A329F7D11DC4D33F6A0BEC9A23E5EE1A18FD5C3640E3F30FC2D8CCE5630E618 -A273CACED00DA6F094148C5D6751DD983A2823418223E715DBE8ED167B2D1999 -650D0FD8685884BCF1D6147C162BDBBB6597DCEAED3B5CAA75F301D46F2F770A -CA1C8997E99D16CC0A58572FE1D68383D87335A38AF8C27556FF19CC421B8BE1 -8AF89CDBB98273BF4E43025A710B4ACB5D7F2C77249CF1756282B74CE43F037B -F62DEC52EA41330A2783B5E64F72392EE25FCE9A7E872F4A9AA7BB41E5368888 -6DC531A2E602696EDA1CD3DCF808F62176E9198AAE9CA8925038D41E17570FD2 -E976F627F7213AC8EE1B2BC240871B7CC1C61B81BAA031B8396536AA62A67DE7 -63FBDFCFD363DB5CE786230B302B786A859C48BBA8CC27EADB1FBC84F1059FA1 -3A02148B4CEF5DA6D90664E72DC6F3EA267E4102102F18D79FFBE4E2A642E94E -F3D9376838236476B1030A0C47D28F4E7EF6358D213AC0A95391659FE736010D -355826A83F7FBEDF3164FF177C16C41789E84F375C6FEFEA767DF654B0533E98 -A1430FEE50F41D39D41DC2ED6EA7EE1FCAB31FCE526D5556E89D36F3B402C5E1 -C0CCEAFA157772B77556AAC8F874A019EAE0A797BCF85655A7834D4DC32D388F -F3E48C0F7B338BBA1C9E949C5C0BC1A727A77FEBE57E1421FF81FE4AA81869FE -86EF313CAD75613726AB3F7508BC904A7E55F092A16D605802D36509525EE2E0 -18B8CE25A0BEC74D167F9E766E30C4EB0D7914F4DA044FD895F3A9C196E23256 -9033CF1E352E82193458B6CFD32238CC93CCBB0E05E8E6AED8CB27157BB148C5 -C644977C16D7F4FC50DA22A28CF8F945B5E0209C8D715E8E7D9D80F32FEACD13 -E6928F4BB60E9684C0F865C9D0C2EEA5EDB0A355FB16426A2405D124F3A01977 -1DE108F66E30EE01ECAA74FE0DEC9A6D485B084FA8A38EC3A59B23FD35B72F87 -ABC6B7D73EDA44DEAC4AA7285D15339EAC0B54B52FEC5B7EA723622704A3DE1C -AAD548509991E18B3AD4CAC7FCBA320ED3989A185CAFA4E22A42E1B5C209F774 -F5FDE4CF0FD23978F3C37BC3EB97A0AA9B9CBC66538FF705F8F7E2C3CD58A359 -40958DC811EBBD7F16902417BC1C97C3D409E4039E0569C6826D22923806BBCA -E601CFEB9B249597BF69BB74FA9607EA9CAC2DE0C8B958574B715D64D5E2AE19 -DF262825913DE26CB598B36E6F8168F7641A58018B9ADBF73237113B9FBB958F -1A3CF592672A51EE2463CD7F22F058597DB9C7316CCD49EFAEFB6A20646E0DDF -794C0A9DFB62A42FC95483D7F578BA3163317AEB14561F49F6E2A909B7C92370 -2592FF0614A1AAB9AC39E93A2DE2D38330AA56BD51D1FD225D0DDA8E91B94267 -127CADEC25E9769512EE28557E051F516329445C31D75E19711CEFDF77224F25 -8B590ABB3BCACF4C3620142B0401F7218BA00C67A748A2DA5F784EF53521F536 -7110D64B659B7BCD26E03F6D35A6EA3452A8F33B4A4E580AEDBC83E7D882BF65 -AACBDB77189BD88AD8A0CAB62EA74CD673A9B37AD1C40065C309BB399045594D -7BCACB882630E12489BD5E049F217C8498287D768B4D0BF904BF0BE1C6340D18 -C14229DE0AC87C1FB28EAF752A2C88FB5B80A4EA1066F11DD918A2FB2E18DBD8 -384E38D2B645EB843A019723C71FEA7C4D02621308D92FD72A10522EFB409D8B -9A5E51F4AA9D768ED428750A6F34FBFEF6FDBF163B13F6FF96450BC2DE22D65D -F7F0F5223CFD29524C61D0070228ED1113C58F48FA3154E53E67567B46F7040F -B03DAD476D4B4A2705ED9521BD22F48AE00AD101CD53BD79B7172ADBB6D4C4CD -951D9CB787F957A1177A7F967A3B867D48A74A0EFF9ACB491BAAB6C997896895 -2F3A1DCFFDC2D71659F916C1630ECE089BF7318201DAEE72972A8AFD0C69D5BE -B5DBBF85ACF39AEEEB8CD634A58D4AD84A49E75E39A5799D53DDAACB7CC08310 -23D44AEEC34D256B1C6C208CF20E986B5F52A866FBE4221FF02A77459AA91933 -4DDA62FD7070BBA306D113FFE2F96090AD748C09470FEB4FFD0CF8C72EA68FB9 -3F00F3F93A56DE5659A40ECAFEDF5E3CF327CBF8DAC7DF31F0F02EC416863D12 -2787C56399B9BE4AB5DEF7D7E185FF02521844F75C48D1ADEA4C0D8436B3A780 -8A55EB846C5CFFFC5D207B0F269DB3DAA7E06FFFAD34ED5A49BFFE73CAA09B6D -AF0C693F71CE69B77FC1378A3C4790CBE8B5546FFF134AE8CB103DD6376EF16E -03501532E3F725E58F36089E3718C635EF95FE9921EEDB08F0CFAEDDFBFB3336 -517AE8ECA540F6918563EAB9D1B5E5BFFAAADC83D0867125E2050A05EF871ED8 -CD0AAACE7D95D37065EA0C92E46115A732F468AA43FF12337839C206157A96BF -A8DFD01BFDF8E2D76E4D46C5B9AEF23193156FE4B535C6155F79149384737DB6 -BAFDB4DC69A64056EEE87A1186B137B6D9D394EB8811AADAE996D67EC403083A -86771A4CDF9AC65678A65DCF46CD1EA9CBE4C1D839CD7F166BA2CA8521F698FD -4CDEF798D360867ADC4C8FD100DC3AB3B62C5BF2527A688D3DB498AB5F407879 -970F2EF1EEBDBC4521CFCBC3E621F992F3EAD3E9737976CDB56596E661129545 -2EBE036A72F668E809D454DACA709F2C0531CCB26910652CCBF94EFC3A4B3852 -B144EB820877E7A55B33B3E9B2B1786729B0643517AD956A7A4779334D0A342A -3DD38F70100854C0B3032397BCDA640CD12C985BB2B5835AA83D442166613350 -BACB4CA9F706141A9E9EB3DFF314B1A82113CA28B74B6603D67AA2D15A36972B -1D8B0057D3D8EB92A1809023EB95762577BD753193DCAF7021366943AFF53A8B -A9ECCB74BF27EE70B1D0B73078CA5CB5AACC1BEE0A61A75981F8A0A3253035FA -1D5D6A1D47DF111693DD9A1D35D9B865C06BD05A688B0D9BC285C0EBB1DF7B2F -2CEA26CFF7583EFED470D4BF02CAE6E4CCFE5347F61F669BF8E82ECD2112E672 -86D10C529DDB600B5237C11BEE28BC3120A0E212E2ED4F52BDF6980675D7DE7C -89FBE11E19865B1C163EE5F4D410F95A434056202DB1BDD10B3A75FA3C091D5B -E3E2F888A6509E1755BFB39F9EE35AEACEDE970EAF42BBFB0D441BED621A8E20 -F504AAB0F511661754B03BFBDEE9E5D704B1FFC70E429E97B8C5651C90044269 -58BB39683838446D49507DCB70AB0DEDEFB73F05E621BC7371D21465AC659AA8 -90786F8CF2A0B0ECA4B40774D7143F92F2B0A95417C475DA5308B5BDCEC67A74 -A425CD76801FF2E115FA3A95818D088392C84FCBC00D3B3C7D683253414D4C5D -74446BBFD130AC89A0C9B68BB1CD772A1BFE8776D0772ED8C00C13C8D0412D7B -526A73A0E38885B79551DAC3E1060537C0EE8FFE574C4B9E8155E2CD83FD85BE -191BDD6ACAEE898A02717A9725196FA59E41FB45D2733CE77289FD178AF07D7A -FEF8D6BABC7DA5425A45AB8EF3C2E369432252E497B172A6FFD4D3DD957C0E26 -0D3D402EAD21FB3E404DB8082DF2ED2C300A0AEC0DA12B7FB571F415017D44E2 -57509A41CFC2284455635F50F06937D23699B43084728FCA9DD25A7264B9D1F4 -2E086976B56237887470653AC62DE323911A64507B40DBF281BB060AE635F37D -BB4F9EF7456EF62EAACAB52F0606DFA777D2965BF03D7CDA312AE654EBFA92C7 -580B7C2A2E604389152704BDF3008ED2F58200D825D0F60C7BF39AF14816B2DA -5738DE7338132B7E7E92424B7FDFB15D8E1EC176CBB7E15F3FA064CF04E357DC -72FDD1E8AF8079B1134EAE3E5CB6A7262994C71714691E8BD7CFF2676EA4D0C2 -A5FCD6C622B3B34469E3B2FCD810AE0252B2814EB02C544B0458CF12DAACAC5F -4A2E078844AC2AC74543F4763CDC6FC081073CD60E276AA6E7F1D948EFA02C23 -2FC1567CD952C837AA1ABD3E3077F5AA7F9986F01B0A9EE91C0EEA3895260CB6 -3B4EA5F58F8C8C23D42C81764E72399D2EDF40C8F18EFAF113AD16E753263943 -55EEC4F01AA885DCBCDB7C9E251210AB2B9382EE45050CC1184F592BBD65D6FD -44D9EA6BC7583CA725A1DCD28EA77A085B0A47CFCF5A847C5D29C4F64F2A17DB -BEAD7B3BA43BAF8548B65DFB4814135A2A789E7E76C978DEAE0138AF8A0AE4BD -B4D22A02C169BB0DA5215B2B91A10ED3A2A9797E5C5FBD11BB295B02C7498B13 -6D90D8CD79D4606007D408E8D336D75D42519BACFB7164C2797F0E9FCD98F178 -D82372F263BAF8B2D1F185E549BA63428E2B8DBCCDD243AD605DD10666F367C2 -3EB98C9157E068FCAB8D91AF9683EEE87A1158A562C911574136CFC172D50C4F -70BC388C728E821395579A081CC946F528CE6F3471B7615F67623F9138DF8FD0 -CAADC4E42AEBF892B36AC169C716DDA724300E9378B809DC6739929C3108A812 -F9C116118E9AE1B066E1928A4A442CE02B2D3BFE18D406AAAC1603E754224AEE -1B802E92CCDCDEF94BAA8955F389B7565AB67D73CED601FA7BFF438717EAD65B -449941F0C87F048B9186C9C78A3D43A3D4C372B5F8DA74DAE6DD2A2816E44303 -790F04C13F08E0815B43FCD837A67BF4A2A86FECB6ED6FFA56018961A0C528FB -472971A8E4C47C974DE12133616F3CBBFA20CE57B572F751649D9AE64A61F271 -0DDE783CF2509DFC2ED2CE7467574AAF79101D56D3D2664DDA30FC7DD5B5C6B7 -0BD084CA516A72E6D3F8B7FEDF0F11EF9CA594C2318EEA3CC266A2F4C2F2AC2C -AB1ABDC5F7419F46308865F1FA63CF2AF4AEBB8319372B3305AA052477ACD838 -7A35218A6CD4A7C0ADE0C3F8B005D6E30C8A208A3518C1134DC34D0E64F804A4 -258A995097F17642E97FE9CC38A34C250B8828B4FBA1840EECBD06D427FE7E10 -4EFAFEBBC934AA295E12F25D6FA3D277C7C88DA60D818A8A303364BD6B2C0288 -6E94BD8E474F28BFB951BE4ABC493AB0EA6EFF110193105DF8E9CEAE1CE549D0 -A907F7A7CF1AD20E121FA6547F93CC10D7957B36ACAF213EE436C92A00AB1A24 -540E535440938E748DAA6401133235D1CC74EC8FF80F9E297FB6C56C12B4E0A4 -D53AB28F11618F2C793F6EACB593E56B8370ED5CFF467B5FFF04AD11BC5A3AF0 -A6EF110B540CD2C87070FFCA3AA0776FF070C384BCDACB0FBD4921C06E24C8F0 -CE590D788FB8C1BCF9E083B4778818F92269C274B0CC6565E2D70FFFA2480381 -040C5CA012341D51427A59C3FC9B5121956B4323872E67BA499876052131B266 -C21F0B8B37902C7C3156FAEB668AE6A7851BC7AA62FE60D792B35B6A38183B23 -E5FB11DBBAF1E60B0D9DF0E84B9EA6F1EA6C37B84736FE657F4A29E92F7DD89D -3473C81FD7F595770BA69C91DAA3154425278D323C3E50A14FF72A02BF3820D6 -6621B91A96A1D2F76710143D41C8305E02810780D868D822DC6056DFA4690F24 -90BE5BB4F14902B97F5FB4CF31A6C8B346A76B95D82EEF610AAFF9F6B88E782C -F0E46DD18BD1CD53C92075AFEA0C1F0870DA52455847B22A638DABEA04C90ACF -0D89E8345F118E5E26A3934AC0C0C9F1269946E17F1AF5759123CE2359B60ED6 -3FB22A23380A34DF818CDA8570B36B92C4634A80AA4ABEFFFE36865AFB384DA8 -70E5CB4829052F8BEB962841C2030BBBF874EDEFE149EB8A38DE0ED59903FCBC -25788EFBB825265AFD7FF2F8D5F9A947EA94A368C52986E8640A6D6A11B14DFD -CF435B2F1F7C168D1E9C7B84B2C2D9E235DC59799B99971FE9E6D9780EAC653C -981FBDF083B949310FF20F7B383BD10737136E88B9D294677C7C63CC50A41AC1 -B4649631134034DB9FF76E0B19799396A232809A5BE397B63B528A0E860D38AD -A90BF0D4246F012E19CEABC74F21E2BD46FACF96D5F033B6023A98DA51653D59 -C306875AA02EDC3DB78060D72B0A00596BE36367A1681ECFEEFA447DB8DE6879 -18962C974B55038A8F67AA553ECD27C6C72D46CEADA75D68D7DACB40B063F9F7 -464401B0AE4CC61A1F55A7E40FBD0FEB890DD2FE36D9641E40BD2F6D20C54353 -C3B282E7F46D61EF3A41F8BCB31FA38EE2B99B671841DA2FAD644C11AE20B6F8 -C7D5D99806643412273F874273FBD04C65F048D76086EA1156F07A47CA0FE349 -391E906747C833320E84E18781C61DEA8FACB8D9DDF08D29E5983F2E1FDC8C72 -C200B63415529A45978010EA5C150BA9D70CF4F5799DA551A1CF7041A17DD5F4 -153A868BD4B81A25551784E2A6EE42996F4D6CFAED97725C940C0FE9FFE0AA31 -FB2A32941E6C555FCF33B4B8E802C40B423599C8E88C6DF1AEEC28938FCF3BAB -B6846C20D7EC7278A909073BD15BA75F470F82237BBFF6E7287A3771378A944C -8CA6215F95437DCC9EA67F7A8721FA63614CA7BC5054EF5E5716FD4B7DEFDE48 -FA8D2AF9F0B3BD92BF5F48A0DCC8406B0A940FBB5D35B56A49B7D4605A00F82D -495AEBF2B413F19FE37AECED8060D5C32E9FE0EE9C0FB14045AE87D04B92A734 -0A35DBFFE12CB1ED64C924E4ADEE0AD635BFC70CCEC92FB07B1DE13E3D14B09C -94590CE5F2F4B7D0C697F6F30E217ED09B35917714712B1182D687302770C205 -C3D17944AC1CC6AE2A023707E13DC1299256DB1211650F76A969D74F940CA580 -6B499C40B76BA77D12688A8CF75E90A19AA3E368D6C99FCF8163450CAD6EA028 -84D4E9A5279013354D9C8D7FB8BCF3FD31433C822F0A412A3115B0E5E71079F6 -60C6BBE10380872D5D75F1BE9BB6DE755103E4B376458B97E0B50BF8932940AE -F95D4002737966FF15A0B67C5B717AFF0E95B9F8F3498D7CCB538FF133A977EF -3471FCE3B83D5395F282D1982B2A6CDBD1C0DE44B3CA286E7E3F3E82B3561635 -6E462A4ABFAE8DE9331FEABA97AE7E7C93F0A30F4E3FDF4DFD66E5CBE234ADD8 -0AEFB354B80ADBDC128EAE328AF10FFDEF587B462A88F62F463D640C4F8898D4 -1AAECA8EAE36639F6CC17B68BC1F1202F462BF7CB20CBD42FF2DEC420B4A7001 -90A1F1499D49731DBC0C5DD4AADC4C32A7349219F25150117D733A0D51A7E51D -88712AF2AC91D73A906CCFFAEA98C68DB967D96DA69E38A0406F2DD149B3E771 -68D65EF65F99A4AD33BB5B15672E57433BC84C9023BA77997E82473C557D18A9 -60F7064934EDDA12E614186A092930690D2DF97E1955FA75CA3CA077EC39A561 -27FC8DCBF13DC183774AF61C2B1B65E5E4 +8BF32C1F1BE935F51A1E6A2B3EEC69C02A0BA8F2CB4A4F68FB7896DC43147822 +7617A156AA00BAB69F17AB7D05874335CE3C819E21DB0FEACF1E752980A202CA +BB393069D59FAAEA4B47BCC0FB9C4DAF2FA0710A8A3DF10E3300A162A988FD1B +D02BB074BC5A4AEB6F0F3F89B3D68E9392AE07E73D7B8D18FE83564C52823804 +979B6136D35154A701E9448881565857394B0D7405004459EE0C68EC17802041 +03FCE184AEDD76833090A32DAC65B34FB1BCDC136D12DA0D6F734F09A5F87BB2 +5407964AD8FBCA56F0CDF8AF907AD5352E4D93A6386BB2006E0FAF74AA8D548D +FFFC997F92F929B794A07CA8848DB5EBA8BA904DBE1AE6DB74FD125E11D39FD2 +293ED39ED1780FDB87D969679CD590297FD9939ACC30B4728227077FD6353E98 +9E62CB8E355522861928A6A4C4747D5794F4DAE08C94FF902D83E5C9FD260800 +FAF713E15B90131C1230A572514B78C4140A3BBE1C1A394F4C0FC8216C9A44B6 +56C67513A4D15B6FC3997D906F69BD022A380D1E6DEAC37434EEC14CB066C7A5 +3EDB6E01DEDF4D58FDAB5A263115D8DD8467F551283B349D0EDCD102A4CDC4DB +6133E4F3942264E0BC3D4FA9F42C3EA90B4FBC54DA6CF0339D0EB1B1BED4D7AB +86DFC6133D38627E2BF545E123B6B848938B4987D5C793EB031AAC98482B242A +B4F9662932E171F439CC1F75B38084F9460FAEFDBA8FAEC336348010BE72BF3C +B481A0F628CA6A15602A648DEFA045F796473FA9D1D1838128BE6AC22EE49445 +14C049A7DDF8CE32418992973BE5A03C61CB64088DD227CE312A802C34FDB144 +A48C3F4A2758D0A547693067D9FA6A36FF3F6349791133C440B1A9D3CCEC40FD +0449009528C4DA20FDB85B57F30B9941D61BD6C722E4E42C243BD21AB59CF8B2 +461F44EC175031BFC898F198D9453F580363DF0C4CC10245A23FEF9FBB5E7AE4 +7EDD08A647BDF27390BE255F3C5E9590CC56B68BF26F97463162A601F6FBDB73 +6B9C7E6B0C9944C91F24FB36F87C737E4A30F3782AA2237EDD48A259D283515C +030E4FD0F67BC97E1C2E1F82761D4AC4E0F19D5BCE52F69C4698376EFADA56E5 +A7540CCABDCD035DD158BF6EEB97E4E491AEFA346B5849E8841E1C512926219E +3D3F1C444D1CEFB2468DB2AA00708A6CACFCEAA65D922EDC5D64A9A66B17C938 +BC7CA14D2EC98A72C976F149DFA98DE557C4A52700856693C7AB5D80151B1C95 +663D913F0AE40F67F2648524E6B06B379D9E0E2EB8E4CCE6B026E7AB5C3DBB48 +B3F6963F58A66C267252AFF7CF2391D350A43377DF8C3E08E6E8DB5E0D26C996 +441A716B3DD2778E2067A37E6F1A9887855A539CC282609A42BE27F6F815B064 +A27B8CE2EF121386E670AA7442B14BE8B66530094EAA93E3FC6668A567F760D7 +D060D8605CDAC6440F2CD8F24493BAC8104211B03A4A115E78DEF16372A1EEA8 +840A5AD4E050CE415A938D1D9E9F0286A8E6345BF7EC8D096833B2BFC9E94C08 +D2927028B30C62D9F95E9FC78FE7D598799CF3D0D24912899DF0A387FA5EADD9 +F3D617D218F949AC82BDAA67D3D2863C5B7311E63CB1FA6C633254477A570DAA +E98E2E08BDC5F85AF690C3E71D958F9F63373D9D8AC9A52B4B89F3DB04B87131 +E3123D7D06FF0B20365F0FF541AB3440579A0F482E74ED7331CE040BF5ADA33E +5ACE0D28130EDF1683C60D79B25103C71AE56B87006BA19C8EC3CE08EFF66FDD +C6B4551ED82322C9089FF612381C320B3792B66B952062FA2971ED005A468FA9 +F9CA87E42DD3F8D610E10824986E9A83961009759E216532ED5BB5A8C27EACDD +A83660DEA812ACDB82271E1BF1B15D020FF800C8E80D0DB2A7793D85F124E4FC +C89268A6159F1734E97AE92022955D040362EDFC1A2F77954B35840B42996675 +00F6A0C6283059263244190DF799E158893572F2650A0A27AE03BBE64ECCE095 +BDCC8924567A84E89A7AE812ABBB82A4D0526054BDBD6A44C4A86DCDFC76397D +B49C98C5ACA66CB80CF32455348D9968E19898677D6AC6C22FAE5747D8C6D9ED +424A9D671130BA557F0BE38972CA0B6F7439F630FB07C409CAA8302212C426D1 +77859925DFF96F842FED263912E6AEC336B99FCDCAB61E8E3BC0C6D7F760FB74 +051321626865771FF83BB6DFE1A9035BB3ACD54836B901CEC6F3AF5B6603E31B +864BEB1C6DE0AD60BDB42508105EBA426E0396B19EE14B539BCE68853929A63D +8B27167E4D43F5502AF30B8111E42A0A593A0AA52F3EE42C23486B16BE004F8D +93BDA3EFB798A58D10F79E8EBAD6DCA69D8CA91C1D6ED75036066D153C6057CD +CCCCF40784B26F87F27345FBCF45435223490BCF6B84B4CFC5AB7B8B9FDC5F60 +EF9A3F0B60A6560C57E71BE1557C5466EFBE1AD76CD5D59681C6164FEBAD21D5 +D93E01DD9A881648CFD245E8F0791B361D64B0DD8BA93BC783B4F1403E002676 +9A4DB0B69E646F4D4497EC87CA672056CA7BF0B5AA0BB7CBC8A93919A1224757 +1DF0AFABB5F2013DD3FD67132BCD5D30247C329BB6B13BFC3E683DCC35026FC3 +515DD8A2D629818A9A9C9AD3263D781B86F52F352A3A0FD0A4F74E5BA65FE64B +162BBE0E843C31BDFE4AEBE3782F85C423DFF302D4F4BB3FAC7C6FAE7870626D +4C118C4885ACD643DFFD9DD232309AFE871E57CE81EE352EBD82A9769542E5BC +E3AE55CEFC790B1744D6B09535CB1A17AFEA289295A88F08A607F28E2D6D229F +6FBAB27397A3A3266B3FC952538A01E066EB51AB2AF4C13790BDF92977C3D4FD +8C76653BEBFB42BF5A93AB343CF71E006CCB1AA6DF07C3BE55DE82D86552ED2B +63A25D1B3D892EA7BFBA8401BE87F7D3C0F70BA06D0806D418DE025AD2A44BE9 +B0576406EF122471F4080B32FC8397C12BC550BBEFE63B119210CCF2856BDA5D +881DE21D34C7BF597ECBAF72DE16E2443932C864AFCDF2FB4C233D510176AF0E +E6B9C20EE11CE7A78BA76F19F2C81BD3F5ADE5A47C74D77B6E1BA858132FA09E +44D167069ECF433A3F5B74AAAC73E1E95EF7D983ED370B4C2287FE814154FF33 +6788130449F5536E305865CF8C513E9351A5103A3F338082E4F1D5F0C3D4F5B4 +E20EAC7BE2F363B012FFD806C5D2EE99F48B92B41019E794C7BF7A410776234F +26459D88A4D68494BC281E57C8C2CDD5DCBDF64E9E4B184AEB5C94D09305C0A8 +72835A6F6DF44F2A7B1848CE38EC6E938E0185988F39B9BC62D4BA3071E7FE54 +6DC79B49BF6A42756F398ADD8156F322CAE4AB583A9E47A1453F8410AFDD420E +5D32F0408E7BA999F52FAEA73DEB5035F083472D1C4EC6FDFC6E029534749597 +6037B0C4D49484DC804B14C87D708242AD05536AB037BCBDADBDDA4226E85F98 +A5BB63E8885348722C0938FB9EE57CA792B20F06280969D8C231AB8090BFD160 +0991D1DF5F89432045D3A0CC4E361A2AC466A402F89F09D7238900FD50AD0DE0 +46D8749949662F5FFA5A2258E5D35F4818E107EF5010A9720B63BA107387EE37 +A4448F122BD880D288CD50DD5033D06A2983F7F62D5A93CC12F9CCAB25654688 +50C5E7091FEBF634A1C2E5DA4C8CAEF51F9D9BFE236DA6958759B19CDD522947 +C4E74F63EF468B19ADCFFF7E6D44EC6406C4F70D11575793D9B783B24528C867 +2A4629BFCB1DDB087888C5625B4B552851BE71E5642FF42399B0A362ECBF34EA +EC45113E3A978EA6C403162C496B3BE73E5C67B9D0F8559B189ABEED9EE5B5BB +BA5D9F8EEC40035F176D7E445743979CB013ED191F3C1D4D7ACCD8BF0F2BD9EE +C34DEEC3F2A88547A7E7910C9586AFE4FD55E41422CD70AD0A55C27A2DBF267C +60FCD61946C94894CEADC4289799910A0E8FEFB941E9492610B6006E19748779 +5D3D455A46A6633EF137D10AE2797B14F9624CE9380ACBDB482F729EC8171913 +C24781311366642B79643C88AFC58457B8753B2842F16DEF21FC2FF03F0184CB +83DB0E89B74A13EC0DCFB29D435286FFD9B0B5BDF3B844E02EDDA76D3E0BD977 +A86F8F2BB836545B3D7D8793D5D327D32E5FF48FCCB7686104A851501D74955B +2C1CEFEF59B031487C246BDD6DB2299645286233B0885CCB51F1E600E6C90151 +CC1DABEBB50A7BE6F66B06D6340EE795C53CA2238E90281A26D09BF60E8FCBFE +A3A37C91DE4974908657F5805B1B1567294C155DA7FAE5E434A371BD9592A4D2 +CF57508CC3EDFBC11EB406E668B8F1204282E2A9EA9173D983A6CC7F2D3F578A +3904E5EB22C286B7930E5519F6A40A23DA7A3088E274284C1F640D2773D1028B +D299D969145FCC9B5F89DF1D5BE6F847F9F49326CBA4835EF03D1819045FAE5C +72895A3D0828BAC414291F042334B17EE49D849928E39BD9A464D31346BA4D6E +03DA880AA0C3C78F283ED687E2F70DC889A7B9D777845F1097F520704CE81333 +9B6EA93DF1A11ED41F821A831C0BEB917FABC8F68AF945E95B0BC9B883724BE2 +BCC7CF84650B0D5B43FCA10052093E832AB862B354EE89129CDE68C7364BFF6E +3B93F0CA5D19228F1F44E015B4B8E8DABE4229560E89589F11BB46E0F42BC64C +273CD536BAF00DF26FEEBF9EC4300DF01B221FAE541132674E6D16F43AB98040 +4CB4D0A72F272FC3320DB8B4B9BA8161B4895FF9EE2B18EC90FE9C5FD3F40622 +8E510CF33BF664475ECD70380164A55ABB43734650170D44B9B9BEF6FC727984 +975D5053360ECC7C0A375215AD4AB63DBB7B2E3F75AB136F6BC002D029A9AAE5 +05671CD18D26006CD662C47A4DA9E7FA08CD9C9EEA9ECD2B31FC65D7071F0B76 +BA692C320C49910F61B1152D71A36AD4B10D3C80AE250F50156ACDB218F59CA5 +028E43917181FBE4B062AD0CB441A0DB976C2F7D09C30D37B09C55C4F5C420E1 +887B196B4468A42AAFBB95F69C79EC97B378148A3DB04011C7F33D9662C89D6E +ACD69C757851AA44F830EFB11C1D259C041E9B56924F84CCEBBCE6AA0D10E45C +73E191726704188DC82FBA0AD70B98C7B183C9C529B145C2DD63E08393185543 +1894E2588815FA14DCE9EF5BABD58AD3D798F64F9418B62B2E02686F8B8D962A +CB20B6B04E581B9DF6C52F544BE97CDCD2F2740A92226D97211DD8168AC3D13C +17360807EE886289C78768D1116E3EBD682120FB6F90278CB3A70503A8B8CD28 +4E0F7E5A3BD6B7CF63B5B6ED9431D8E1434587EB4B74EA388FA301896F3E0FF5 +2CAC688D84B0B33C87AB1A7DF3D90792E9B7442AC5B1A450230A9DC514D3ABC4 +C6A7EFAC0B18488844946BDE5DDC18FCD3D832C1D6C62633D6E46F3D561D40EA +2A3B225E71717A2FF5E6DFB29FB611FA3122FC60364104458D9CFA6F5BC74117 +5582AFD3A15115290BD8F966176DE34A62173844D79EC73FE81EE77448AF1A35 +5F4AA813530949CFD5E53F5CED0323292DA6B28EC13C2B35A3B74165A2CE729F +F9C7EB1A728077725790A4F0FDA6AC9D9942D52CCD8652959E0BA58EFA5BE6CB +B07DCC2FD207F400F01F7D910ACB7CB87ED3FAC751A8DAF3516EA71AFF38EB27 +705217106FD0FCA158063E80FCF454444A5C16DC12FFD5EBCDF0F70C1E5CCBE2 +ED0A6270E1BA271989BCBAACF6085AD252AD2137644450360934D03D6A014150 +FD21949EB35C0F2104DC44643C56AD864CDD802D6BA57EDC7F8263A86DCFB0EA +439875AF0EFBAA5CA147B7CF6DBC691E32ECB2432328FD3B0C7AC5E3058FF419 +2F629075692FBAA974E2071E798EE81CE61545D6BCE7B40DF72416DD3161CCA8 +EE3F294DD3C7C61CCDF78F69C1AB0B63F4EEDBC01372D240268F2C60AA62E8DF +EE52909ADCC47044BA3BEE85D077986F179CDFF53AD8F9F22B1897C7C5D23B5B +A8C26584116FEC0E562E688EE078FC2D0082F92090A8585A8178102D22BED49C +62C9F7B589F105541DCDD6A157AB685699C580C282A5BA26126FB08FEEEB9CD7 +71781251823AFEB12F5B37DB4CFE59D5B23281D33911416D8EB55CF4DA0CCC88 +E380CB53BAFF81CEC5F29FB54DA3B66231E0A24BE4EA672A08F9E2046AEECF4C +B9AE458E76A3FDBB1A1BB37BA2F8E756D5E3D96A97750B0974D67EBAC26D6C17 +823A144AB04D93D93ABD0FA46E52D4FA04504542C6FB9ED028297D9B22F6C1BA +2FD3773F1E71E4BA936A4033351E12F48CACA9137BBA250D145D5A3E4B9BCF81 +F3EFFCD532FF2DD2085AA5F8259393B316EE9C9E3DC74C2B0015B018D1DDA120 +BACBEDA6E0BF7D91DD13E0D6AE3000E03E9FC0A2871C909476D2FA8B1E852E68 +2A20EF414950FE7D899F554245FB6E041723FFF36FBB0CDA14BC162C81884487 +A255D99BBA35BCBFED3369730FC89EFF68B64C5E84B007230368B32A7B2C3476 +6C1CC1F41A951D9D84B796EDFF484106F7479ACE356EB889453E138A98DE20F0 +F10EA068AF4B2C67F877AF2FC067669891F7EFE3EC3AD48A61CCB907C6573868 +0A47DD38ED7A60BFE77ECF4E6DF3DFA70E5217EDBF20DFC9F5B707665AD365E8 +F225B0708F9877CA0D27F6BF42250854129AB0F0096B03E653C83D65B03C4E4C +4B5B2B2FA881E58D94813A0C82B4BE017D7FE636544E7E698ED1F229372E856E +5A9D61BA773D85DB651D44FE34B770D37D6AA24B011C27A421E12FE0DAEEBDC7 +4EB72CCBDF1C68968DDA127416C7508FB39F3CC98DA18D3B00D083BBB9092413 +05582D08F7AEE5866B030F3000E08C4B18C3798B64511EC0B8C5F64625445609 +EB750668DCFC76A6CE41F18808D4D59CD8C4DCFEAE74E4AE9B5526774484C928 +3EDD497B94E12A6B8AA151BA9071A8A6F6B842C568C2FB1B9DA2668928966A71 +1FF06469F4EC05524A59683E4FF003D0C1D8501B35172985D3AE7B0104915E3C +1CDA23EFEA6702D67A2FE1C37EAB2AFEA5B23FFC3146C0AD143FD4B67E240A12 +A9FA5BB54B85B8B0DF788A9B6D70375D293BE862A648BA03620BE3D00F5DB2FC +2A5CB1CDDAC650FE19E4E67BE94F6D2C0CA491CF04736F001E8A440558D7630F +18B6F0C51A7A88D7DDF3B3E0B356CEDDA2DD90F1DEBBC2E0A00D356240D95D3D +8804DDB50C087DD7D743D37F787D519FF0E5331E40FEC71FC172B7B9FB4BFBDD +A9E4ADBDC72B68AE0B906EE04566DE98C2142137787C6FDC6959BCFD5DAFED7E +745ED34DF81F2BE2BA71FD29ABD9F9EA2EE83188B3530D0BF75A8524CB3B74B4 +8894B558118BF20CDF56AF809295491269D2103B8EB87B7B1E9FDC515E1BB263 +7BC9148A7EBFCE70188D0B1A17B7D658DA1C68718B5D877E766ADB4F9E1D2CAD +09F2D2A0BEC2AAAF29E2CE02D92AD9D69EA3B82725A81B66E6D7DFABEA83686B +43DDE5495E14ECDFF314283FEE34E12304720E21AD065ED65CC4927B2CF19F19 +7BFADECEB4AD2A72C922F275841A9A32B7F59F9CEC85993119EA5D84960A7E16 +A78AAC396EF0E30C9EA0F14FCFCF334B2784901240F83DA2D65116EAFC92AB25 +AC4E2BC6A2C67258CA0D0C97E5EDAF526293704A8F30231A677CAEA7CC36B6A5 +8BBE2CB635D030C8C189600BEB6F248862505AADFA5987F9B2FFD9E65C475FD4 +66181794F9F982943E3AE3FDFFF95E718499732568399B5E09D8D5C7452212BD +53421EBCBBDA4E61B97C6C85202EEF7891A2622566D4896702D004BF66CE8D79 +2EE381738D33D21B9EBC0B38CFBA58BAEC3A5195FFAFEFD39494FC304B540FE1 +079613FAC7D7CC0C1785640104E8A3AB50AE83168FCA02B4B26315EBAA7BC21B +CC30F1CE54F9947B32AADDBF8BC40A820A69B1508EC0C5E58E6453F95734094E +47089BC8E7491769E9C2D90AC2A35D9F4ADC88108863684DB8BDEEEF54BF923B +02AE114B153494AAD20A984AF198941C64A5A7DD2EC3EB037FA8BADACFC42754 +017BDCFD966710A88D82A1E9351543573607CCFCCCC3FFB85C40AF2F8EA5DD8F +C5261348F689AC3936833AA9F3A61C344444DBBD6635F920320D4E8A4A5DF1B6 +CD5FC3695819DE927A2974102499CC0145FFA6C52CB1F2B93C3C83249C780C94 +BD8D968A41F35B333DE07CDB261D0ACD1B2C95A2C87911B6C31C14196010ACC1 +CD88179FC58B95DBA799A38CB22DE08C4BE0B3FF4BC6B7BFC4E36F70C5E28C4D +791A6CFF8D40B32829C2D7083E25FCE1F58969353DDFF9FDB9290C530FC5E907 +2543ADEFC8D6675476C8ECE2D56E79F51FE9E0C5581D6F2AA7BB8AAE16563092 +7232722A00D49142B0421EFC1B648980ACFA873656615001E39EADB5C2BE4668 +66BDEF21952587EDF9C2B0087924EB9E312D59A1C918833AFE94ECEF30C2AEAB +AC5A38B2537D033F9B400FEAFC3DB5BD5DED92A10E74FA6BC97ED38E3F7F0755 +3C4319A7CCB2338580EF7E944FC98C621C049ED5E53CA6750E57AA903C05E3D1 +D5B5E1512D1AA6D7572192D6A395EB192A52499749858256BBDA1CE13DAB0E8C +67DE9632B8A19DE09A899596614DC6C509F1C851681DE8F1ABB93BC53B04DB7A +1E3120E0A2035141A410F18CD592CAF1C03EB8A6E642A560606B5CED064496C3 +055A97E4FB2211478ADE9DD8A53CC505B7ADD6411B343B0B09FF0F83B5BAA230 +39BEAEC22943DA553BA26E6DAFB61BB3377A2B3204A47097A5C3AD274C13436E +4C4E602F6899162FB5546E16C8D1FB5DF0AAB4178A95666BFA72BE46624C859A +ED91BA5035232461F7E513CA17C4E888097A00C9393A24E35B0B527E152ABF5A +D8791D481D237DDBBA411729DE4DC1A0466DC8F226569D941E88AD50722B32B0 +A368691B04E91C480F7DADD1D98739136FF55E3EA6284EE4A6481AD1E4C05362 +4550DBD19CC0D3443B88461EB9D686BD4E06E4E95585F88B54B7A49C60100EDC +39DEEC2C7C89668A546C3D3824C1A2E93A621D4E6ED4DD5D47151E240D00E30E +77CD08B5A15EF03311FAD97D4748CA80E03FB945B750E2A371EC67FF8ED0DA4B +45295D022E604D6BA9C9A2F82588375177D470D6D1221118DC147FFB77815771 +52C863DABA9F323FD85F0FA14E50AF8432AC0E490290F944A92951614606049C +C9EAF7132B9B96E79EB210A1EA3FE119F0417F99A69B319394357CED4ACB1CC5 +4D3FD5A27036E1AF8FBE81745BC66952F9B8327A80AFEDF31284CDA472A5D541 +5B0CCF34A0E0552037C297482C0424B08D4A865A3857E842B11E2CDF5D95955B +6603751890D83E8A9E37A04BE5C63C2DB06D6CDEBB6814E3BBCF77AC7BE65C84 +D6C0BC053FAEE8D3903D344FD6CC6929DE351B1382D334CE8FEDE5F0C489C948 +3123BE9C7385219A39B31BBF6E3D11BDE47FA99D56DD91D667613C87349DC66D +3687676D7CAFC723B694C106BB4D27FEB329B751A0EECB8A816D816010C073DA +F5BD48098375827561B1B7A9CD8A1BF6AD13CE823CE3CEAAE35C0B5F70CFBA7E +78922CDCF4BEDC0EE6C19260E9FF82310CAF25C609C811C685BEA557EC451E3F +65244B6424D6EF39A76758F934FB02C77FA4FA37F06D91B20711749962867B3B +5564EF4221E66F66D77ECA275F3E8BF7976DC2D0C1EA8CECFD50CCD12E183126 +A9418AD9D601865A5D168E2298E6B99F9C8C789477CCC8D607F0C3B86263BCFF +A42723F7F98152D8AB8BBBEDBAD28939A5F411D4B36ECF5068569B365F72A205 +8F763D8F968B1460A46344F77218A93FD44FFF5C747E9688E9DA572619CF0A9E +62E76C7EEC4A65349874F264B09A9E440F2F378F370E0337007C31F1DDCD5A8C +7D6BCDCC0734D316ED13ADCDDF39BF2DFBD6991C5B98027313DB8AEF1F3D5413 +D780EE5A3720B962FFA586966E75E4F064BF6F377CD1EC36A3D214D4F937F7BF +5D468B82993260D67878443F6D62F0E66BA31662DC26B77A9BFD958581C12158 +3D4490543A8EF43024BDD308DC03758DB8AFA6BD3735031D6543A93B03C07615 +7254F6E3985322D236C254B2170A5F058B27805DDDEDF15F322B6B83353BEEB6 +3953CC1EF2AD8BB529A0354CD6C6BC8DA275B2B5910AC60EDDAD63AFAB60B91E +FEF7CF4E1DE505F151DC34B361C8B28BE592C85F70CEC2A5D2E1212A185AFE8D +17E050A3386D95622ADA81CF1B49F441C45F6D3BAD328CA8B44FF892DFDA6BC0 +AF955998156294AFBF076489E21B33548DA4D48296545AB76C8EDF5A3CC623FF +022BE68E289615E6BFE4762B512E859F6C675AA6AB15C6EA447680BEA8623A17 +A7B75EBC69D9FF42B1441D61E57B563F152458E0224D1C0A05281A34BBE60B50 +2538A62D83DC2A5C3861330C2E9F6F645986B0429FE32D6BE27CCCFEC7AFC0E3 +E88634FB1B8E1043B4161D511AEFA2529EA0A334901D424518FEC1091501D35B +2C01F98DD44DBE964D669F975646D70F8871C6C6E357C4A368F32EEFFCA56B5D +95D40BF5E52A6FBEA4D1520DAB2241BBBBD19A517EDA5F2C5773D822CD8B8BF5 +36C1C62F3E23AF4AE255AB0AB66513984AB9F37F28EA9E11DAB0C59526637909 +BA89D0EDD0A3E62CF280D02F5A4FC8BD063E33669C4EC6F5FFE998CE424AB8CD +2224A23F41B3A2FF975C5C3CD8A2E179436BB62D5C228C7D02129621FB630A2E +477D64BD2360F28C1DDCFD43CD261008E5EE14AB3AE73387D76E0E7FBB49AE1C +3892FE09A397C35740E6E2EF2B783EB0CD2A2A8F01642CF988C8C2F01D3CB208 +368A37F2CD356AE129E4BD1DA5B4224DB4C2A3F6EF43ABD3127F119CE59AAA50 +7F3FFDE5EE4DA7B5DB7E2237C9C612E88F65D6AF84E91E3DA6044A6E4E685F4C +9B657AF9488E8F07DE024B6A2A111E33CD869D4EA16212970DD7B14502858F7B +4906040A2447BDA84B192D46B4B340DAAA674B9DA36A8301158C9745CA11A95D +3EA301E6BE26B103EAC473509DBD45A3405AF556DA77CC42E1A8F1C88C71B038 +E78FF38FD862615B27625561B4410FF6B00088E296F430A8A57C54D0C8E35C14 +561FC0471EFFD7D910D63F173BABD8984CB24B501E18548C54E89D7FDB9DFC65 +59B355C6AB5D412F8F91A82386CBA9AE283BC49058462580863A753C45C75C94 +1D889DAB030888A3A70167CCD945D35F396391724FA5B1637EE1CC8C24D53B93 +B95EBB6372F30CCF5A54305030936AC183BE80E5BB18995D6F1A1D9756C995AA +BA4272B4AB2F4D29A51F696FC75BBF78FA5524FFD2257701BE792D3D531515E3 +6801ADD6EF27D117C713AD79C7D9E6DC9BE752D2B731187834177BAD1E5F2710 +ABCF2A3FF1DE206119779C50BCAB175C0316D5FCF0156C344C10A7BF825A4470 +0E9B34EA7A0EBA52138D61D7FB0449B5E281929542138D2698E2C88AF1E0E247 +96FEBAF1172142B8103D3E28BE5CD34E0AE26F915A347E4F6ED3474EDE940522 +D58B3354246A05485B51DC53AAA7FF1EB279C1101402A240EB38621A8B8844EE +62D7FDF10E63353A904A834BD3CF1C84C235C42D636BF73A2832063B815E13EC +72EF0EC7EB877AE7A911CD28638F55186047AD33A536F54A8129AF42B8489D88 +EFB733B34695764CBF01E4C59C577687CD3F8A5F6A69397235EC71A85B30C5A0 +6D7B9E31DA11AC45D5FB9E133E124C95A7910C3D66CCDAE747EC6013F4D22DCC +A381E3EB9F359CE8644B13ABDC73F2CB6CD44F07F711F2E64861F948140EC6BB +4CF29D5532F62CDC98490A2A8F85A87F57E10F64E47C817E9FEFB2668C2D0010 +DF16161E7A8475F6BCA788A07A9EBC81B811A24A485FB532E382579329CCD64E +2C1FBBFB65E58223F1E33A18C4FCDE84B0C60A0B3F6F2E150570DA33EEE3FAEE +35DF52573E487223A23705176F5818C1E30F199EE005DBD1B0206F9CCF26C3F2 +C219BD50EC2E351D915096EA7B505CD5B7D3123C3E82F00E3313DA1D6128897E +5B2EAF7B8A48F75FB143E4E5AC63CE4740F30A0A8EC555986CF2A93016F4EF3E +C40DAF655E9CC9168F5A9A13729DB8F2FFF4086BC2FBFFE3E15F4077DBD07A3D +6337D47B8CFDCF2B2DC2E63A04C8E7E7DC9416DBE7081C27BFB67D33BA154B97 +8DAFD7F12C3F3E04F52B87B340B6EC8BFC2DFE2D176EAAF507C109FFB78C18DA +6703BB0301C804535E20734ACA8C1F5CB43A5648115175B63DDC626CEA6B4F52 +50BB6B0BD14ED98CA678B1451E549B73BDFC7256B5311909AA4744540E2F4AC4 +D6C42C010D47E5A526D39CD5FB80396954B7217B553E9843D525FFFBBDC9A2E2 +B39A877EA50449365A36A8C8D4D8EBDCFBE617C941AA71D8CC5B09E36734B014 +9645CAD85987BA89803C4ED19FCAD46000C9847D5618606574B41BF9EB9E64A6 +A2C313A9C25F72CBB1070E25DC10AA059A0910ADE3FB78AC91EFA287D4C77975 +1015B7F264C4496EBE54CAAE1A859E63B37006DDB51BB03641C0693CB91181D5 +0786709EB0A3C8EBFB1A6D2E0BA2C804B3A790B22E6C2C5C4CFA96BBB1C6BD4F +6BD98B17CE59D6506FCDF158B7E06283BE21E94041F97A14979358FA8D043AAE +6C61F6757F066EAA1DC9971307AAFD7D67F7B93F32F1AE6CD11E48A786BAC474 +B9465F52711DC08721FEEEFCF725CA4918A83922058BF7CAB2BF5720D2EFFAFC +0D7743CEE05135C1A172B74150B0A256A32BCA3F654B294DF0B29F777752EDE4 +A2F18B4D92F7CF38525E298E04299849CC535F405A61A20C5C50A1968B753CAE +07335CBD535D3C72449157ABCE83F8522EDA7236C089498F8C44C9D850775E97 +FD43E40726AA6AEADDE4379C38350D54893D238974FA31BD65DCC411F3E4F01C +AF47ADA23F44DEB5EE1D90B0129E35F6A141738B8E939DE99AAC5D94BE68802F +902BFD4FDA6EDDA70F1D4E979D9BA77E4427CEA58E42D87899DED7F3D5679E71 +F88C0366AAF9ED39D296132BC2891E97923C9FB8852E2F56914E1AB24F2A07FA +64C4CFA4B3207DD4990C1290379D5DF541A491A05114927BA77B20CA345A6F5F +865D18190DE6D6EB079F7CC6F56B2A082D7847C00B521563BC5006F96EB83F6A +DE78AC3F7034C1D434DC620A7EA95AB2EBD9BB94BDDBF0B5722B2148E7B4811E +C8CCE48DC8109BB83C8FDF41DDAFDF450B55A9C310C179427DAD501FBC1FE7DD +0349E94582C22F915664DD9C4963EF1792C258A138DC83F96333789684BA1181 +D58995ABBC3515628AD5BBD3F2979AE30D9B13E290137E54F21AC5408C5DC3CA +CBE34EA9E903180D81E9DF0ADDAF6E77E9E554EC557CDF93A65B87F2B2FC8C8E +EB7D90081F0218E41A869E2D5B2B0392D2F0FE721F050DC8683D75DE82E94C8C +1EFFD4CAB2698F65741E7BB37DD54D5599016B5C7D42950520C7ABC612442216 +9E90D84D0327D21D47C4EB5D10278ABF5D52C94021181299605576BD4EC39F58 +095B1062DA895DC8DF983862CD1CB24D8472970CB49BB77908CEB0C512A6AE51 +7A3F69A07DAC220975F73FBE94F82E29A672D5CF65C84AED4554650F815571CA +3A98619E103B215968EEDB12819AE6BC3F6BD6073F4C33931A9AA0D81134410F +46C6E5CDDEFFBB1BED5B924FE58502FE97DCC973C8BAA80F42546E3780436370 +637457C82494804B89E859164F404B67705C7D5E7EE5C8B72D454D85144C1BA5 +9B73B73014DD989761F1AB5015273B4EA9F7FFF87ADDD9929F8A5705F49BA3B9 +67BB0F491AB22AAFD699DD53093DA73FB1D2292059A31DA303D91C0AE99B4DF8 +20A669A9C8B307C723B4FF305CA08DAE05BCEEAB0EBAC5EAA2941AE37B5C1C6D +B906EFE67349DD3C808F1A58E468C47D7F9467D5B163E7807FD8934389307CFA +CD72F3C028F458658E0EBF3212CEF2DC57CC1569090E808F544A1F8C01268F9F +6CE1305CCA58376661553807CE98BD64180791B6053E5F5B8DB33CCE3A5474D6 +99A6269656E260E9E3CA51E549A5123C90FCAFB01DC0004322A149D1910027A1 +59E71BDFBF8DC2FCDF730747F89F1624BF608CEB937107AE0C0D4B92B13D1BE9 +7C77EC964D69EEEC02EE6EC06EF646B69A7269D49BAB698A8E7BAE9F61E875BB +1ED47150A53983FB314EFE6C345667701DFDBCC60566508C8264A929224E46ED +7D5091F7A563A97516E885F8702C9C693CBF361CE8503E86BBF983E826BB96EB +2AD5B07CDEE47E1F392D34CE14D44A167C3357FE6B7B760C63F78211F182854B +8D2BDFB4C910D6D36FF2415294AC84F7CC5DBAD89887CFF021B6C8DEC98271AE +386245779B38830FFDF6CFCC72F0271337E660BA96B6A9EED2CC85452DCE553B +21003D3890638C55EC3F372DCE3F78C8ADD68978656BF5D5ED1833EAC3156809 +3D779953B778336404BD7FBFDACD2B40169B30BF27F81ACE3F556B0E57232840 +9915285AD0A76E039E1B27A07536EEFA7554FB80E138D3E4288A554A775B98F4 +A3A97AE47F71FD60548FB927C3617D133F1AFCC01530EE36E284C5F60B319858 +9B79B63EDB1176DC1D3089661AFB824971F4EE6A7422C097A2A02C5B715D1D06 +F4AA09383337FD604D7EDB5060E70AF6BBE6F506FAA0EFCD79D3A4C12B4B3A20 +52152342C367691CDE79BA8CBA7C3EAC35AB75347A12C219BDFAAE94F5E51605 +D7D13A3EFD3F4526E705A3FABB1D1723FCB23FBDD72377BBF894FA19E9C6A52A +140AC6194B7DA07C4B99B67EE9A5AC5E179CDE082C086F1DC4D15A2B8CDA1CB0 +0A6D15FB974B17189BEFD09A4AA5D1B2D496318A739E7CCA40F711AF7D0A144D +F8AF19EAB4AC59AF5B3FF3315575869BE4E4846FF09D38CF28D4A72E9F64C3C8 +06BB5288EC2D86C5B1D775D2345476CADDB937BA6D510EEFF9E9A3BEF08872D0 +BE4AB08CCEEC207B26C215046D728E9D8F4332BF4CFFED2EA7685270AC0A65B8 +0005D013F1E7A5E180D595D5F0F622A8E25C6C65B0EB196B8B3194F49677AE27 +D3E64995EAA829AC57BB6378E2F0444E0CB4E3DBCCF25DAE6EAED6965FDDED94 +5384D050B567494E0E89F3F270F894CDD5E2231C4168D56A757F04D97FF4BB97 +FD46A8FE6ADB66047FEB3D034F1FEA4CE01653F31CA726ABE43109B01F143FE2 +CEDFDB6CC45FC0F63AE96C7D06FC3762F2BAE65942403D910F670ED2C1A34021 +E8461A5948DFEFC28F74BE4BABAB17BB515953CFE02C0DA932B7FF0449A8D99D +A6441306D001F676635E9251018F94556FE21A251F89882FF6ED05031786F1C7 +C056708BE36B512204106C2AF121A0FCD617A4410F9E2622C6DC6EF40FEA93A1 +875E53AC60C5B29A63DDEB693C3AA9DBBAB53A78D44F1896986D9ED77AE81819 +FC04C5E794FE678BCA5BD6F831AA362CB56CAE3FECFC661E5D8E672D8E6A9CF4 +337D177B73BBAFF89E0305B611952BA06488FC52782C1CE5C7CF2CD9ADC85888 +DC3F62DA0C90525E29935F3AD78B14A9D697EA0A4EAD9DF0D8B424D4D7EC3400 +0F1C4CE7BB586A75BF07A30729BE3C72E602C0628CAB7B1EE1C1EC928F7E2CDA +753BE0A5675C210C075654B58E9124E466B78A5935D6FC8C65C3417DB8504D00 +2255E63FE52069E2F15755764FF266D9F0C56D89743F2A8F349B1FFD8A91C5BE +F1F7933123CFAE944BDDFA98F4A8C702A12AF4777BCA487FF31060E8C58DC6B0 +4592DEF5D209518E88EF4783F0EF66E9DFD58D5AF8A56D7FFFF9BF611BA5EC33 +72A063A982793C163ECE15E824DE2D13E49C40529AAC183543DFBCAD1CEABCAB +CC31ED9C472D76616AF72705D42E7642F060EF3E4745CB3C8C6A75E8FBCFB7ED +18676984F53F4486CE489A4A66FB34D7437FF12B90B8A5EB7B04565FBD465DAD +E3CC75F67A7E774C96204A3E01E1F6DE238B90808B33B5F13ABD73EC4E594202 +768180D53CC11DFCC77B4C56BC06327F56991DD50777486BC4C2C3ADA85D2089 +DBFA423CE52A214E162FFD087244B16C9422A86B4508EB8FC692D507CB6C1625 +4B74A1617A2087327A369D894ACCA16797B210DA13C8C47B71E286C0FAC082FF + 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 @@ -2303,7 +2299,7 @@ 49.8132 /CMSY6 rf /Fb 134[32 1[43 32 34 24 24 24 1[34 30 34 50 18 32 1[18 34 30 19 27 34 27 34 30 13[34 44 1[41 47 1[54 3[22 1[47 39 2[43 1[45 6[18 4[30 1[30 30 -30 30 1[18 21 18 44[{ TeXf7b6d320Encoding ReEncodeFont }41 +1[30 1[18 21 18 44[{ TeXf7b6d320Encoding ReEncodeFont }40 49.8132 /CMR6 rf /Fc 135[33 3[24 29 4[40 58 18 2[22 36 2[33 36 33 33 36 50[22 46[{ TeX74afc74cEncoding ReEncodeFont }14 66.4176 /CMTI8 rf /Fd 134[43 43 59 43 45 32 32 34 1[45 @@ -2321,13 +2317,13 @@ 35 35 35 33[{ TeX09fbbfacEncoding ReEncodeFont }86 66.4176 /CMTT8 rf /Fh 134[60 60 2[64 45 45 47 1[64 57 64 95 32 60 1[32 1[57 1[53 64 51 64 56 10[87 88 80 64 86 2[86 -90 109 69 2[43 1[90 72 75 88 83 1[87 19[38 45[{ - TeXf7b6d320Encoding ReEncodeFont }36 99.6264 /CMBX10 +90 109 69 2[43 1[90 72 75 88 83 1[87 19[38 32 44[{ + TeXf7b6d320Encoding ReEncodeFont }37 99.6264 /CMBX10 rf /Fi 133[31 37 37 51 37 39 27 28 28 37 39 35 39 59 20 37 22 20 39 35 22 31 39 31 39 35 2[35 1[35 3[53 72 -53 53 51 39 52 1[48 55 53 65 44 55 1[25 53 55 46 48 54 -51 50 53 6[20 6[35 35 35 1[35 20 24 20 55 35 27 27 20 -2[35 59 35 20 19[39 39 41 11[{ TeXf7b6d320Encoding ReEncodeFont }70 +53 53 51 39 52 2[55 53 65 44 55 1[25 53 55 46 48 54 51 +50 53 6[20 6[35 35 35 1[35 20 24 20 55 35 27 27 20 2[35 +59 35 20 19[39 39 41 11[{ TeXf7b6d320Encoding ReEncodeFont }69 66.4176 /CMR8 rf /Fj 141[57 2[69 76 6[69 42 63 76 61 1[67 14[103 2[103 1[131 9[99 16[69 69 1[69 1[46 3[53 53 40[{ TeXf7b6d320Encoding ReEncodeFont }19 119.552 @@ -2342,148 +2338,144 @@ %%Page: 1 1 TeXDict begin @landscape 1 0 bop -169 -357 a Fj(Org-Mo)t(de)45 b(Reference)h(Card)g(\(1/2\))546 -242 y Fi(\(for)23 b(v)n(ersion)h -(3.21\))-150 -42 y Fh(Getting)37 b(Started)-150 125 y -Fi(Put)24 b(the)h(follo)n(wing)e(in)g(y)n(our)h Fg(~/.emacs)931 -102 y Ff(1)-150 199 y Fg(\(autoload)38 b('org-mode)g("org")e("Org)h -(mode")g(t\))-150 268 y(\(autoload)h('org-diary)g("org")f("Org)f(mode)h -(diary)f(entries"\))-150 338 y(\(autoload)i('org-agenda)g("org")f -("Agenda)g(from)g(Org)f(files")h(t\))-150 408 y(\(autoload)h -('org-store-link)h("org")e("Store)g(org)f(link")h(t\))-150 -478 y(\(autoload)h('orgtbl-mode)h("org")d("Orgtbl)i(minor)e(mode")h -(t\))-150 547 y(\(autoload)h('turn-on-orgtbl)h("org")e("Orgtbl)g(minor) -g(mode"\))-150 617 y(\(add-to-list)i('auto-mode-alist)h('\("\\\\.org$") -e(.)e(org-mode\)\))-150 699 y(\(define-key)i(global-map)h("\\C-cl")e -('org-store-link\))1504 676 y Ff(2)-150 782 y Fg(\(define-key)h -(global-map)h("\\C-ca")e('org-agenda\))1364 758 y Ff(2)-150 -879 y Fi(F)-6 b(or)23 b(the)i(man)n(y)f(customization)h(options)g(try) -68 b Fg(M-x)36 b(org-customize)-150 948 y Fi(T)-6 b(o)24 -b(read)g(the)g(on-line)g(do)r(cumen)n(tation)i(try)111 -b Fg(M-x)36 b(org-info)-150 1147 y Fh(Visibilit)m(y)h(Cycling)-150 -1297 y Fi(rotate)25 b(curren)n(t)f(subtree)g(b)r(et)n(w)n(een)i(states) -291 b Fg(TAB)-150 1367 y Fi(rotate)25 b(en)n(tire)f(bu\013er)g(b)r(et)n -(w)n(een)h(states)384 b Fg(S-TAB)-150 1436 y Fi(sho)n(w)24 -b(the)g(whole)g(\014le)854 b Fg(C-c)36 b(C-a)-150 1614 -y Fh(Motion)-150 1764 y Fi(next)25 b(heading)1043 b Fg(C-c)36 -b(C-n)-150 1834 y Fi(previous)24 b(heading)921 b Fg(C-c)36 -b(C-p)-150 1904 y Fi(next)25 b(heading,)f(same)g(lev)n(el)685 -b Fg(C-c)36 b(C-f)-150 1973 y Fi(previous)24 b(heading,)g(same)g(lev)n -(el)563 b Fg(C-c)36 b(C-b)-150 2043 y Fi(bac)n(kw)n(ard)25 +(3.22\))-150 -36 y Fh(Getting)37 b(Started)-150 96 y +Fg(\(add-to-list)i('auto-mode-alist)h('\("\\\\.org$")e(.)e +(org-mode\)\))-150 179 y(\(define-key)i(global-map)h("\\C-cl")e +('org-store-link\))1504 155 y Ff(2)-150 261 y Fg(\(define-key)h +(global-map)h("\\C-ca")e('org-agenda\))1364 237 y Ff(2)-150 +343 y Fg(\(define-key)h(global-map)h("\\C-ct")e('org-todo-list\))1469 +320 y Ff(2)-150 442 y Fi(F)-6 b(or)23 b(the)i(man)n(y)f(customization)h +(options)g(try)68 b Fg(M-x)36 b(org-customize)-150 511 +y Fi(T)-6 b(o)24 b(read)g(the)g(on-line)g(do)r(cumen)n(tation)i(try)111 +b Fg(M-x)36 b(org-info)-150 716 y Fh(Visibilit)m(y)h(Cycling)-150 +872 y Fi(rotate)25 b(curren)n(t)f(subtree)g(b)r(et)n(w)n(een)i(states) +291 b Fg(TAB)-150 942 y Fi(rotate)25 b(en)n(tire)f(bu\013er)g(b)r(et)n +(w)n(een)h(states)384 b Fg(S-TAB)-150 1011 y Fi(sho)n(w)24 +b(the)g(whole)g(\014le)854 b Fg(C-c)36 b(C-a)-150 1195 +y Fh(Motion)-150 1351 y Fi(next)25 b(heading)1043 b Fg(C-c)36 +b(C-n)-150 1421 y Fi(previous)24 b(heading)921 b Fg(C-c)36 +b(C-p)-150 1490 y Fi(next)25 b(heading,)f(same)g(lev)n(el)685 +b Fg(C-c)36 b(C-f)-150 1560 y Fi(previous)24 b(heading,)g(same)g(lev)n +(el)563 b Fg(C-c)36 b(C-b)-150 1630 y Fi(bac)n(kw)n(ard)25 b(to)f(higher)g(lev)n(el)f(heading)424 b Fg(C-c)36 b(C-u)-150 -2113 y Fi(jump)23 b(to)i(another)f(place)h(in)e(do)r(cumen)n(t)350 -b Fg(C-c)36 b(C-j)-150 2311 y Fh(Structure)g(Editing)-150 -2462 y Fi(insert)23 b(new)i(heading)f(at)g(same)g(lev)n(el)g(as)g -(curren)n(t)104 b Fg(M-RET)-150 2531 y Fi(insert)23 b(new)i(TODO)e(en)n -(try)700 b Fg(M-S-RET)-150 2628 y Fi(promote)24 b(curren)n(t)h(heading) -f(up)g(one)h(lev)n(el)285 b Fg(M-LEFT)-150 2698 y Fi(demote)25 +1700 y Fi(jump)23 b(to)i(another)f(place)h(in)e(do)r(cumen)n(t)350 +b Fg(C-c)36 b(C-j)-150 1905 y Fh(Structure)g(Editing)-150 +2060 y Fi(insert)23 b(new)i(heading)f(at)g(same)g(lev)n(el)g(as)g +(curren)n(t)104 b Fg(M-RET)-150 2130 y Fi(insert)23 b(new)i(TODO)e(en)n +(try)700 b Fg(M-S-RET)-150 2228 y Fi(promote)24 b(curren)n(t)h(heading) +f(up)g(one)h(lev)n(el)285 b Fg(M-LEFT)-150 2298 y Fi(demote)25 b(curren)n(t)f(heading)h(do)n(wn)f(one)g(lev)n(el)233 -b Fg(M-RIGHT)-150 2768 y Fi(promote)24 b(curren)n(t)h(subtree)f(up)g -(one)g(lev)n(el)301 b Fg(M-S-LEFT)-150 2838 y Fi(demote)25 +b Fg(M-RIGHT)-150 2368 y Fi(promote)24 b(curren)n(t)h(subtree)f(up)g +(one)g(lev)n(el)301 b Fg(M-S-LEFT)-150 2437 y Fi(demote)25 b(curren)n(t)f(subtree)h(do)n(wn)f(one)g(lev)n(el)248 -b Fg(M-S-RIGHT)-150 2935 y Fi(mo)n(v)n(e)24 b(subtree/list)h(item)e(up) -642 b Fg(M-S-UP)-150 3004 y Fi(mo)n(v)n(e)24 b(subtree/list)h(item)e -(do)n(wn)558 b Fg(M-S-DOWN)-150 3074 y Fi(kill)23 b(subtree)1097 -b Fg(C-c)36 b(C-x)g(C-w)-150 3144 y Fi(cop)n(y)25 b(subtree)1052 -b Fg(C-c)36 b(C-x)g(M-w)-150 3213 y Fi(y)n(ank)25 b(subtree)1046 -b Fg(C-c)36 b(C-x)g(C-y)-150 3310 y Fi(arc)n(hiv)n(e)24 -b(subtree)976 b Fg(C-c)36 b($)-150 3380 y Fi(T)-6 b(o)24 +b Fg(M-S-RIGHT)-150 2536 y Fi(mo)n(v)n(e)24 b(subtree/list)h(item)e(up) +642 b Fg(M-S-UP)-150 2605 y Fi(mo)n(v)n(e)24 b(subtree/list)h(item)e +(do)n(wn)558 b Fg(M-S-DOWN)-150 2675 y Fi(kill)23 b(subtree)1097 +b Fg(C-c)36 b(C-x)g(C-w)-150 2745 y Fi(cop)n(y)25 b(subtree)1052 +b Fg(C-c)36 b(C-x)g(M-w)-150 2815 y Fi(y)n(ank)25 b(subtree)1046 +b Fg(C-c)36 b(C-x)g(C-y)-150 2913 y Fi(arc)n(hiv)n(e)24 +b(subtree)976 b Fg(C-c)36 b($)-150 2983 y Fi(T)-6 b(o)24 b(set)g(arc)n(hiv)n(e)g(lo)r(cation)h(for)e(curren)n(t)h(\014le,)f(add) -h(a)g(line)f(lik)n(e)1495 3357 y Ff(3)1533 3380 y Fi(:)-150 -3454 y Fg(#+ARCHIVE:)38 b(archfile::*)h(Archived)e(Tasks)-150 -3631 y Fh(Filtering)g(and)g(Sparse)g(T)-10 b(rees)-150 -3781 y Fi(sho)n(w)24 b(sparse)f(tree)i(for)d(all)h(matc)n(hes)i(of)f(a) -g(regexp)92 b Fg(C-c)36 b(/)-150 3851 y Fi(view)24 b(TODO's)e(in)i -(sparse)f(tree)580 b Fg(C-c)36 b(C-v)-150 3921 y Fi(create)25 -b(sparse)e(tree)i(with)e(all)g(deadlines)i(due)204 b -Fg(C-c)36 b(C-w)-150 3991 y Fi(time)24 b(sorted)g(view)g(of)f(curren)n -(t)h(org)g(\014le)367 b Fg(C-c)36 b(C-r)-150 4060 y Fi(agenda)25 -b(for)e(the)i(w)n(eek)823 b Fg(C-c)36 b(a)p Fi(2)-150 -4130 y(agenda)25 b(for)e(date)i(at)f(cursor)661 b Fg(C-c)36 -b(C-o)2046 -364 y Fh(TODO)i(Items)2046 -215 y Fi(rotate)25 -b(the)f(state)h(of)f(the)g(curren)n(t)g(item)354 b Fg(C-c)36 -b(C-t)2046 -145 y Fi(view)24 b(TODO)f(items)g(in)h(a)g(sparse)f(tree) -380 b Fg(C-c)36 b(C-v)2046 -49 y Fi(set)24 b(the)h(priorit)n(y)e(of)g -(the)i(curren)n(t)f(item)369 b Fg(C-c)36 b(,)g([ABC])2046 -21 y Fi(remo)n(v)n(e)24 b(priorit)n(y)f(co)r(okie)i(from)d(curren)n(t)j -(item)179 b Fg(C-c)36 b(,)g(SPC)2046 102 y Fi(raise)23 -b(priorit)n(y)g(of)g(curren)n(t)i(item)557 b Fg(S-UP)3626 -78 y Ff(4)2046 182 y Fi(lo)n(w)n(er)23 b(priorit)n(y)g(of)h(curren)n(t) -g(item)538 b Fg(S-DOWN)3696 159 y Ff(4)2046 313 y Fi(p)r(er-\014le)23 +h(a)g(line)f(lik)n(e)1495 2959 y Ff(3)1533 2983 y Fi(:)-150 +3057 y Fg(#+ARCHIVE:)38 b(archfile::*)h(Archived)e(Tasks)-150 +3242 y Fh(Filtering)g(and)g(Sparse)g(T)-10 b(rees)-150 +3397 y Fi(sho)n(w)24 b(sparse)f(tree)i(for)d(all)h(matc)n(hes)i(of)f(a) +g(regexp)92 b Fg(C-c)36 b(/)-150 3467 y Fi(view)24 b(TODO's)e(in)i +(sparse)f(tree)580 b Fg(C-c)36 b(C-v)-150 3547 y Fi(global)24 +b(TODO)f(list)g(in)g(agenda)i(mo)r(de)389 b Fg(C-c)36 +b(t)1466 3524 y Ff(2)-150 3617 y Fi(create)25 b(sparse)e(tree)i(with)e +(all)g(deadlines)i(due)204 b Fg(C-c)36 b(C-w)-150 3687 +y Fi(time)24 b(sorted)g(view)g(of)f(curren)n(t)h(org)g(\014le)367 +b Fg(C-c)36 b(C-r)-150 3767 y Fi(agenda)25 b(for)e(the)i(w)n(eek)823 +b Fg(C-c)36 b(a)1466 3744 y Ff(2)-150 3837 y Fi(agenda)25 +b(for)e(date)i(at)f(cursor)661 b Fg(C-c)36 b(C-o)2046 +-364 y Fh(TODO)i(Items)2046 -215 y Fi(rotate)25 b(the)f(state)h(of)f +(the)g(curren)n(t)g(item)354 b Fg(C-c)36 b(C-t)2046 -145 +y Fi(view)24 b(TODO)f(items)g(in)h(a)g(sparse)f(tree)380 +b Fg(C-c)36 b(C-v)2046 -75 y Fi(view)24 b(3rd)f(TODO)g(k)n(eyw)n(ord's) +h(sparse)g(tree)258 b Fg(C-3)36 b(C-c)g(C-v)2046 22 y +Fi(set)24 b(the)h(priorit)n(y)e(of)g(the)i(curren)n(t)f(item)369 +b Fg(C-c)36 b(,)g([ABC])2046 91 y Fi(remo)n(v)n(e)24 +b(priorit)n(y)f(co)r(okie)i(from)d(curren)n(t)j(item)179 +b Fg(C-c)36 b(,)g(SPC)2046 172 y Fi(raise)23 b(priorit)n(y)g(of)g +(curren)n(t)i(item)557 b Fg(S-UP)3626 148 y Ff(4)2046 +252 y Fi(lo)n(w)n(er)23 b(priorit)n(y)g(of)h(curren)n(t)g(item)538 +b Fg(S-DOWN)3696 229 y Ff(4)2046 384 y Fi(p)r(er-\014le)23 b(TODO)g(w)n(ork\015o)n(w)h(states:)33 b(add)24 b(line\(s\))g(lik)n(e) -3505 290 y Ff(3)3542 313 y Fi(:)2046 386 y Fg(#+SEQ_TODO:)38 -b(TODO)f(PROCRASTINATE)i(BLUFF)e(DONE)2046 466 y Fi(p)r(er-\014le)23 +3505 360 y Ff(3)3542 384 y Fi(:)2046 457 y Fg(#+SEQ_TODO:)38 +b(TODO)f(PROCRASTINATE)i(BLUFF)e(DONE)2046 537 y Fi(p)r(er-\014le)23 b(TODO)g(k)n(eyw)n(ords:)32 b(add)24 b(line\(s\))g(lik)n(e)3314 -443 y Ff(3)3351 466 y Fi(:)2046 539 y Fg(#+TYP_TODO:)38 -b(Phil)f(home)f(work)h(DONE)2046 728 y Fh(Timestamps)2046 -877 y Fi(prompt)24 b(for)f(date)i(and)f(insert)f(timestamp)266 -b Fg(C-c)36 b(.)2046 946 y Fi(lik)n(e)23 b Fg(C-c)i Fi(.)31 -b(but)24 b(insert)g(date)g(and)h(time)e(format)144 b -Fg(C-u)36 b(C-c)g(.)2046 1016 y Fi(Lik)n(e)24 b Fg(C-c)36 +513 y Ff(3)3351 537 y Fi(:)2046 610 y Fg(#+TYP_TODO:)38 +b(Phil)f(home)f(work)h(DONE)2046 799 y Fh(Timestamps)2046 +949 y Fi(prompt)24 b(for)f(date)i(and)f(insert)f(timestamp)266 +b Fg(C-c)36 b(.)2046 1018 y Fi(lik)n(e)23 b Fg(C-c)i +Fi(.)31 b(but)24 b(insert)g(date)g(and)h(time)e(format)144 +b Fg(C-u)36 b(C-c)g(.)2046 1088 y Fi(Lik)n(e)24 b Fg(C-c)36 b(.)24 b Fi(but)g(mak)n(e)g(stamp)h(inactiv)n(e)322 b -Fg(C-c)36 b(!)2046 1086 y Fi(insert)23 b(DEADLINE)h(timestamp)516 -b Fg(C-c)36 b(C-d)2046 1156 y Fi(insert)23 b(SCHEDULED)h(timestamp)451 -b Fg(C-c)36 b(C-s)2046 1225 y Fi(create)25 b(sparse)e(tree)i(with)e -(all)g(deadlines)i(due)204 b Fg(C-c)36 b(C-w)2046 1295 +Fg(C-c)36 b(!)2046 1158 y Fi(insert)23 b(DEADLINE)h(timestamp)516 +b Fg(C-c)36 b(C-d)2046 1228 y Fi(insert)23 b(SCHEDULED)h(timestamp)451 +b Fg(C-c)36 b(C-s)2046 1297 y Fi(create)25 b(sparse)e(tree)i(with)e +(all)g(deadlines)i(due)204 b Fg(C-c)36 b(C-w)2046 1367 y Fi(the)25 b(time)e(b)r(et)n(w)n(een)j(2)e(dates)g(in)g(a)f(time)h -(range)172 b Fg(C-c)36 b(C-y)2046 1377 y Fi(c)n(hange)25 +(range)172 b Fg(C-c)36 b(C-y)2046 1449 y Fi(c)n(hange)25 b(timestamp)g(at)f(cursor)f(b)n(y)h Fe(\000)p Fi(1)g(da)n(y)238 -b Fg(S-LEFT)3696 1354 y Ff(4)2046 1458 y Fi(c)n(hange)25 +b Fg(S-LEFT)3696 1426 y Ff(4)2046 1530 y Fi(c)n(hange)25 b(timestamp)g(at)f(cursor)f(b)n(y)h(+1)g(da)n(y)238 b -Fg(S-RIGHT)3731 1434 y Ff(4)2046 1538 y Fi(c)n(hange)25 +Fg(S-RIGHT)3731 1506 y Ff(4)2046 1610 y Fi(c)n(hange)25 b(y)n(ear/mon)n(th/da)n(y)i(at)d(cursor)f(b)n(y)h Fe(\000)p -Fi(1)189 b Fg(S-DOWN)3696 1515 y Ff(4)2046 1622 y Fi(c)n(hange)25 +Fi(1)189 b Fg(S-DOWN)3696 1587 y Ff(4)2046 1694 y Fi(c)n(hange)25 b(y)n(ear/mon)n(th/da)n(y)i(at)d(cursor)f(b)n(y)h(+1)189 -b Fg(S-UP)3626 1599 y Ff(4)2046 1692 y Fi(access)25 b(the)f(calendar)g +b Fg(S-UP)3626 1671 y Ff(4)2046 1764 y Fi(access)25 b(the)f(calendar)g (for)f(the)i(curren)n(t)f(date)221 b Fg(C-c)36 b(>)2046 -1762 y Fi(insert)23 b(timestamp)i(matc)n(hing)g(date)f(in)g(calendar)89 -b Fg(C-c)36 b(<)2046 1832 y Fi(access)25 b(agenda)g(for)e(curren)n(t)h -(date)507 b Fg(C-c)36 b(C-o)2046 1901 y Fi(While)24 b(prompted)g(for)f -(a)h(date:)2046 1971 y(...)30 b(select)25 b(date)f(in)g(calendar)660 -b Fg(mouse-1/RET)2046 2041 y Fi(...)30 b(scroll)23 b(calendar)h(bac)n -(k/forw)n(ard)h(one)f(mon)n(th)121 b Fg(<)36 b(/)f(>)2046 -2111 y Fi(...)30 b(forw)n(ard/bac)n(kw)n(ard)24 b(one)h(da)n(y)525 -b Fg(S-LEFT/RIGHT)2046 2180 y Fi(...)30 b(forw)n(ard/bac)n(kw)n(ard)24 -b(one)h(w)n(eek)486 b Fg(S-UP/DOWN)2046 2250 y Fi(...)30 -b(forw)n(ard/bac)n(kw)n(ard)24 b(one)h(mon)n(th)437 b -Fg(M-S-LEFT/RIGT)2046 2449 y Fh(Links)2046 2598 y Fi(globally)24 -b(store)g(link)f(to)h(the)h(curren)n(t)f(lo)r(cation)166 -b Fg(C-c)36 b(l)3662 2574 y Ff(2)2046 2667 y Fi(insert)23 -b(a)h(link)f(\(T)-6 b(AB)24 b(completes)h(stored)f(links\))138 -b Fg(C-c)36 b(C-l)2046 2737 y Fi(insert)23 b(\014le)h(link)f(with)h -(\014le)g(name)g(completion)192 b Fg(C-u)36 b(C-c)g(C-l)2046 -2834 y Fi(op)r(en)25 b(link)e(at)h(p)r(oin)n(t)884 b -Fg(C-c)36 b(C-o)2046 2904 y Fi(op)r(en)25 b(\014le)e(links)g(in)h -(emacs)722 b Fg(C-u)36 b(C-c)g(C-o)2046 2973 y Fi(op)r(en)25 -b(link)e(at)h(p)r(oin)n(t)884 b Fg(mouse-2)2046 3043 -y Fi(op)r(en)25 b(\014le)e(links)g(in)h(emacs)722 b Fg(mouse-3)2046 -3140 y Fd(Link)27 b(t)n(yp)r(es)2046 3236 y Fg(<http://www.astro.uva.n) -q(l/~d)q(omi)q(nik>)247 b Fi(on)24 b(the)h(w)n(eb)2046 -3306 y Fg(<mailto:adent@galaxy.ne)q(t>)564 b Fi(EMail)23 -b(address)2046 3376 y Fg(<news:comp.emacs>)845 b Fi(Usenet)25 -b(group)2046 3446 y Fg(<file:/home/dominik/img)q(/mar)q(s.j)q(pg>)282 -b Fi(\014le,)23 b(absolute)2046 3515 y Fg(<file:papers/last.pdf>)670 -b Fi(\014le,)23 b(relativ)n(e)2046 3585 y Fg(<file:~/code/main.c:255)q -(>)599 b Fi(\014le)19 b(with)g(line)g(nr.)2046 3655 y -Fg(<bbdb:Richard)39 b(Stallman>)631 b Fi(BBDB)23 b(p)r(erson)2046 -3725 y Fg(<shell:ls)38 b(*.org>)877 b Fi(shell)23 b(command)2046 -3794 y Fg(<gnus:group>)1020 b Fi(GNUS)24 b(group)2046 -3864 y Fg(<gnus:group#id>)915 b Fi(GNUS)24 b(message)2046 -3934 y Fg(<vm:folder>)1055 b Fi(VM)23 b(folder)2046 4004 -y Fg(<vm:folder#id>)950 b Fi(VM)23 b(message)2046 4073 -y Fg(<vm://myself@some.where)q(.org)q(/fo)q(lder)q(#id)q(>)105 -b Fi(VM)23 b(remote)2046 4143 y(W)-6 b(anderlust)25 b -Fg(<wl:...>)h Fi(and)e(RMAIL)f Fg(<rmail:...>)k Fi(lik)n(e)c(VM)4242 --364 y Fh(T)-10 b(ables)4242 -263 y Fd(Creating)25 b(a)i(table)4242 --178 y Fi(insert)c(a)h(new)g(Org-mo)r(de)g(table)330 -b Fg(M-x)36 b(org-table-create)4242 -108 y Fi(...)30 -b(or)23 b(just)h(start)g(t)n(yping,)g(e.g.)173 b Fg(|Name|Phone|Age)39 -b(RET)d(|-)g(TAB)4242 -39 y Fi(con)n(v)n(ert)25 b(region)f(to)g(table) -741 b Fg(C-c)36 b(C-c)4242 31 y Fi(...)30 b(separator)24 -b(at)h(least)f(3)g(spaces)537 b Fg(C-3)36 b(C-c)g(C-c)4242 -116 y Fd(Commands)26 b(a)n(v)-5 b(ailable)25 b(inside)j(tables)4242 -201 y Fi(The)17 b(follo)n(wing)f(commands)i(w)n(ork)f(when)g(the)h -(cursor)e(is)g Fc(inside)k(a)f(table)p Fi(.)4242 270 -y(Outside)24 b(of)e(tables,)i(the)g(same)f(k)n(eys)h(ma)n(y)f(ha)n(v)n -(e)h(other)g(functionalit)n(y)-6 b(.)4242 355 y Fd(Re-aligning)25 +1834 y Fi(insert)23 b(timestamp)i(matc)n(hing)g(date)f(in)g(calendar)89 +b Fg(C-c)36 b(<)2046 1904 y Fi(access)25 b(agenda)g(for)e(curren)n(t)h +(date)507 b Fg(C-c)36 b(C-o)2046 1973 y Fi(Select)25 +b(date)g(while)e(prompted)598 b Fg(mouse-1/RET)2046 2169 +y Fh(Links)2046 2318 y Fi(globally)24 b(store)g(link)f(to)h(the)h +(curren)n(t)f(lo)r(cation)166 b Fg(C-c)36 b(l)3662 2295 +y Ff(2)2046 2388 y Fi(insert)23 b(a)h(link)f(\(T)-6 b(AB)24 +b(completes)h(stored)f(links\))138 b Fg(C-c)36 b(C-l)2046 +2458 y Fi(insert)23 b(\014le)h(link)f(with)h(\014le)g(name)g +(completion)192 b Fg(C-u)36 b(C-c)g(C-l)2046 2555 y Fi(op)r(en)25 +b(link)e(at)h(p)r(oin)n(t)884 b Fg(C-c)36 b(C-o)2046 +2624 y Fi(op)r(en)25 b(\014le)e(links)g(in)h(emacs)722 +b Fg(C-u)36 b(C-c)g(C-o)2046 2694 y Fi(op)r(en)25 b(link)e(at)h(p)r +(oin)n(t)884 b Fg(mouse-2)2046 2764 y Fi(op)r(en)25 b(\014le)e(links)g +(in)h(emacs)722 b Fg(mouse-3)2046 2861 y Fd(Link)27 b(t)n(yp)r(es)2046 +2957 y Fg(*CamelCaseWord)950 b Fi(searc)n(h)24 b(headline)2046 +3027 y Fg(CamelCaseWord)985 b Fi(searc)n(h)24 b(in)f(bu\013er)2046 +3097 y Fg(<file:/home/dominik/img)q(/mar)q(s.j)q(pg>)282 +b Fi(\014le,)23 b(absolute)2046 3167 y Fg(<file:papers/last.pdf>)670 +b Fi(\014le,)23 b(relativ)n(e)2046 3236 y Fg(<file:~/code/main.c:255)q +(>)599 b Fi(\014le)19 b(with)g(line)g(nr.)2046 3306 y +Fg(<file:projects.org::*Ca)q(melC)q(ase)q(Word)q(>)211 +b Fi(searc)n(h)24 b(headline)2046 3376 y Fg(<file:projects.org::fin)q +(d)41 b(me>)453 b Fi(searc)n(h)24 b(string)2046 3446 +y Fg(<file:projects.org::/re)q(gexp)q(/>)423 b Fi(searc)n(h)24 +b(regexp)2046 3515 y Fg(<http://www.astro.uva.n)q(l/~d)q(omi)q(nik>)247 +b Fi(on)24 b(the)h(w)n(eb)2046 3585 y Fg(<mailto:adent@galaxy.ne)q(t>) +564 b Fi(EMail)23 b(address)2046 3655 y Fg(<news:comp.emacs>)845 +b Fi(Usenet)25 b(group)2046 3725 y Fg(<bbdb:Richard)39 +b(Stallman>)631 b Fi(BBDB)23 b(p)r(erson)2046 3794 y +Fg(<shell:ls)38 b(*.org>)877 b Fi(shell)23 b(command)2046 +3864 y Fg(<gnus:group>)1020 b Fi(GNUS)24 b(group)2046 +3934 y Fg(<gnus:group#id>)915 b Fi(GNUS)24 b(message)2046 +4004 y Fg(<vm:folder>)1055 b Fi(VM)23 b(folder)2046 4073 +y Fg(<vm:folder#id>)950 b Fi(VM)23 b(message)2046 4143 +y(W)-6 b(anderlust)25 b Fg(<wl:...>)h Fi(and)e(RMAIL)f +Fg(<rmail:...>)k Fi(lik)n(e)c(VM)4242 -364 y Fh(T)-10 +b(ables)4242 -263 y Fd(Creating)25 b(a)i(table)4242 -178 +y Fi(insert)c(a)h(new)g(Org-mo)r(de)g(table)330 b Fg(M-x)36 +b(org-table-create)4242 -108 y Fi(...)30 b(or)23 b(just)h(start)g(t)n +(yping,)g(e.g.)173 b Fg(|Name|Phone|Age)39 b(RET)d(|-)g(TAB)4242 +-39 y Fi(con)n(v)n(ert)25 b(region)f(to)g(table)741 b +Fg(C-c)36 b(C-c)4242 31 y Fi(...)30 b(separator)24 b(at)h(least)f(3)g +(spaces)537 b Fg(C-3)36 b(C-c)g(C-c)4242 116 y Fd(Commands)26 +b(a)n(v)-5 b(ailable)25 b(inside)j(tables)4242 201 y +Fi(The)17 b(follo)n(wing)f(commands)i(w)n(ork)f(when)g(the)h(cursor)e +(is)g Fc(inside)k(a)f(table)p Fi(.)4242 270 y(Outside)24 +b(of)e(tables,)i(the)g(same)f(k)n(eys)h(ma)n(y)f(ha)n(v)n(e)h(other)g +(functionalit)n(y)-6 b(.)4242 355 y Fd(Re-aligning)25 b(and)i(\014eld)h(motion)4242 440 y Fi(re-align)22 b(the)i(table)g (without)g(mo)n(ving)g(the)g(cursor)70 b Fg(C-c)36 b(C-c)4242 510 y Fi(re-align)23 b(the)h(table,)g(mo)n(v)n(e)h(to)f(next)h(\014eld) @@ -2557,67 +2549,66 @@ %%Page: 2 2 TeXDict begin @landscape 2 1 bop -169 -357 a Fj(Org-Mo)t(de)45 b(Reference)h(Card)g(\(2/2\))546 -242 y Fi(\(for)23 b(v)n(ersion)h -(3.21\))-150 -46 y Fh(Timeline)37 b(and)g(Agenda)-150 -101 y Fi(sho)n(w)24 b(timeline)f(of)h(curren)n(t)g(org)f(\014le)458 -b Fg(C-c)36 b(C-r)-150 170 y Fi(...)30 b(include)24 b(past)h(dates)793 -b Fg(C-u)36 b(C-c)g(C-r)-150 267 y Fi(add/mo)n(v)n(e)25 -b(curren)n(t)f(\014le)g(to)g(fron)n(t)g(of)f(agenda)197 -b Fg(C-c)36 b([)-150 336 y Fi(remo)n(v)n(e)24 b(curren)n(t)g(\014le)g -(from)f(y)n(our)g(agenda)299 b Fg(C-c)36 b(])-150 406 -y Fi(cycle)24 b(through)h(agenda)g(\014le)f(list)551 -b Fg(C-,)-150 487 y Fi(compile)24 b(agenda)h(for)e(the)h(curren)n(t)g -(w)n(eek)320 b Fg(C-c)36 b(a)1466 463 y Ff(2)-150 556 -y Fi(agenda)25 b(for)e(date)i(at)f(cursor)661 b Fg(C-c)36 -b(C-o)-150 687 y Fi(T)-6 b(o)24 b(set)g(category)h(for)e(curren)n(t)h -(\014le,)g(add)g(line)1082 663 y Ff(3)1119 687 y Fi(:)-150 -759 y Fg(#+CATEGORY:)38 b(MyCateg)-150 856 y Fd(Commands)26 -b(a)n(v)-5 b(ailable)25 b(in)i(an)g(agenda)g(bu\013er)-150 -952 y Fi(The)g(agenda)h(bu\013er)f(is)f(electric:)38 -b(single)26 b(k)n(ey)i(presses)e(execute)j(com-)-150 -1022 y(mands.)-150 1118 y Fd(View)e(org)f(\014le)-150 -1214 y Fi(sho)n(w)e(original)f(lo)r(cation)h(of)g(item)524 -b Fg(SPC)-150 1284 y Fi(...)30 b(also)24 b(a)n(v)l(ailable)g(with)781 -b Fg(mouse-3)-150 1353 y Fi(sho)n(w)24 b(and)g(recen)n(ter)h(windo)n(w) -626 b Fg(l)-150 1423 y Fi(goto)25 b(original)e(lo)r(cation)h(in)g -(other)g(windo)n(w)260 b Fg(TAB)-150 1493 y Fi(...)30 +(3.22\))-150 -36 y Fh(Timeline,)36 b(Agenda,)h(Global)g(TODO)h(List) +-150 120 y Fi(sho)n(w)24 b(timeline)f(of)h(curren)n(t)g(org)f(\014le) +458 b Fg(C-c)36 b(C-r)-150 190 y Fi(...)30 b(include)24 +b(past)h(dates)793 b Fg(C-u)36 b(C-c)g(C-r)-150 288 y +Fi(add/mo)n(v)n(e)25 b(curren)n(t)f(\014le)g(to)g(fron)n(t)g(of)f +(agenda)197 b Fg(C-c)36 b([)-150 358 y Fi(remo)n(v)n(e)24 +b(curren)n(t)g(\014le)g(from)f(y)n(our)g(agenda)299 b +Fg(C-c)36 b(])-150 427 y Fi(cycle)24 b(through)h(agenda)g(\014le)f +(list)551 b Fg(C-,)-150 508 y Fi(compile)24 b(agenda)h(for)e(the)h +(curren)n(t)g(w)n(eek)320 b Fg(C-c)36 b(a)1466 485 y +Ff(2)-150 578 y Fi(agenda)25 b(for)e(date)i(at)f(cursor)661 +b Fg(C-c)36 b(C-o)-150 658 y Fi(global)24 b(TODO)f(list)899 +b Fg(C-c)36 b(t)1466 635 y Ff(2)-150 791 y Fi(T)-6 b(o)24 +b(set)g(category)h(for)e(curren)n(t)h(\014le,)g(add)g(line)1082 +767 y Ff(3)1119 791 y Fi(:)-150 866 y Fg(#+CATEGORY:)38 +b(MyCateg)-150 964 y Fd(Commands)26 b(a)n(v)-5 b(ailable)25 +b(in)i(an)g(agenda)g(bu\013er)-150 1062 y(View)g(org)f(\014le)-150 +1161 y Fi(sho)n(w)e(original)f(lo)r(cation)h(of)g(item)524 +b Fg(SPC)-150 1230 y Fi(...)30 b(also)24 b(a)n(v)l(ailable)g(with)781 +b Fg(mouse-3)-150 1300 y Fi(sho)n(w)24 b(and)g(recen)n(ter)h(windo)n(w) +626 b Fg(l)-150 1370 y Fi(goto)25 b(original)e(lo)r(cation)h(in)g +(other)g(windo)n(w)260 b Fg(TAB)-150 1439 y Fi(...)30 b(also)24 b(a)n(v)l(ailable)g(with)781 b Fg(mouse-2)-150 -1563 y Fi(goto)25 b(original)e(lo)r(cation,)h(delete)h(other)f(windo)n -(ws)91 b Fg(RET)-150 1632 y Fi(toggle)25 b(follo)n(w-mo)r(de)861 -b Fg(f)-150 1729 y Fd(Change)27 b(displa)n(y)-150 1825 -y Fi(delete)e(other)f(windo)n(ws)791 b Fg(o)-150 1895 +1509 y Fi(goto)25 b(original)e(lo)r(cation,)h(delete)h(other)f(windo)n +(ws)91 b Fg(RET)-150 1579 y Fi(toggle)25 b(follo)n(w-mo)r(de)861 +b Fg(f)-150 1677 y Fd(Change)27 b(displa)n(y)-150 1776 +y Fi(delete)e(other)f(windo)n(ws)791 b Fg(o)-150 1845 y Fi(switc)n(h)24 b(to)g(w)n(eekly)h(view)767 b Fg(w)-150 -1964 y Fi(switc)n(h)24 b(to)g(daily)g(view)822 b Fg(d)-150 -2034 y Fi(toggle)25 b(inclusion)e(of)h(diary)f(en)n(tries)473 -b Fg(D)-150 2104 y Fi(toggle)25 b(time)f(grid)f(for)g(daily)g(sc)n -(hedule)388 b Fg(g)-150 2174 y Fi(refresh)23 b(agenda)i(bu\013er)f -(with)g(an)n(y)g(c)n(hanges)239 b Fg(r)-150 2243 y Fi(displa)n(y)24 +1915 y Fi(switc)n(h)24 b(to)g(daily)g(view)822 b Fg(d)-150 +1985 y Fi(toggle)25 b(inclusion)e(of)h(diary)f(en)n(tries)473 +b Fg(D)-150 2055 y Fi(toggle)25 b(time)f(grid)f(for)g(daily)g(sc)n +(hedule)388 b Fg(g)-150 2124 y Fi(refresh)23 b(agenda)i(bu\013er)f +(with)g(an)n(y)g(c)n(hanges)239 b Fg(r)-150 2194 y Fi(displa)n(y)24 b(the)g(follo)n(wing)f Fg(org-agenda-ndays)221 b(RIGHT)-150 -2313 y Fi(displa)n(y)24 b(the)g(previous)g Fg(org-agenda-ndays)238 -b(LEFT)-150 2383 y Fi(goto)25 b(to)r(da)n(y)1110 b Fg(.)-150 -2479 y Fd(Remote)27 b(editing)-150 2575 y Fi(digit)d(argumen)n(t)984 -b Fg(0-9)-150 2671 y Fi(c)n(hange)25 b(state)g(of)f(curren)n(t)g(TODO)f -(item)333 b Fg(t)-150 2741 y Fi(set)24 b(priorit)n(y)f(of)g(curren)n(t) -i(item)612 b Fg(p)-150 2823 y Fi(raise)23 b(priorit)n(y)g(of)g(curren)n -(t)i(item)557 b Fg(S-UP)1430 2800 y Ff(4)-150 2904 y +2264 y Fi(displa)n(y)24 b(the)g(previous)g Fg(org-agenda-ndays)238 +b(LEFT)-150 2334 y Fi(goto)25 b(to)r(da)n(y)1110 b Fg(.)-150 +2432 y Fd(Remote)27 b(editing)-150 2530 y Fi(digit)d(argumen)n(t)984 +b Fg(0-9)-150 2629 y Fi(c)n(hange)25 b(state)g(of)f(curren)n(t)g(TODO)f +(item)333 b Fg(t)-150 2698 y Fi(set)24 b(priorit)n(y)f(of)g(curren)n(t) +i(item)612 b Fg(p)-150 2781 y Fi(raise)23 b(priorit)n(y)g(of)g(curren)n +(t)i(item)557 b Fg(S-UP)1430 2757 y Ff(4)-150 2861 y Fi(lo)n(w)n(er)23 b(priorit)n(y)g(of)h(curren)n(t)g(item)538 -b Fg(S-DOWN)1500 2880 y Ff(4)-150 2974 y Fi(displa)n(y)24 +b Fg(S-DOWN)1500 2838 y Ff(4)-150 2931 y Fi(displa)n(y)24 b(w)n(eigh)n(ted)h(priorit)n(y)e(of)g(curren)n(t)h(item)189 -b Fg(P)-150 3080 y Fi(c)n(hange)25 b(timestamp)g(to)f(one)g(da)n(y)h -(earlier)315 b Fg(S-LEFT)1500 3057 y Ff(4)-150 3161 y +b Fg(P)-150 3040 y Fi(c)n(hange)25 b(timestamp)g(to)f(one)g(da)n(y)h +(earlier)315 b Fg(S-LEFT)1500 3016 y Ff(4)-150 3120 y Fi(c)n(hange)25 b(timestamp)g(to)f(one)g(da)n(y)h(later)367 -b Fg(S-RIGHT)1535 3137 y Ff(4)-150 3231 y Fi(c)n(hange)25 -b(timestamp)g(to)f(to)r(da)n(y)598 b Fg(>)-150 3327 y +b Fg(S-RIGHT)1535 3097 y Ff(4)-150 3190 y Fi(c)n(hange)25 +b(timestamp)g(to)f(to)r(da)n(y)598 b Fg(>)-150 3288 y Fi(insert)23 b(new)i(en)n(try)f(in)n(to)g(diary)612 b -Fg(i)-150 3423 y Fd(Calendar)26 b(commands)-150 3519 +Fg(i)-150 3387 y Fd(Calendar)26 b(commands)-150 3485 y Fi(\014nd)e(agenda)h(cursor)f(date)g(in)g(calendar)350 -b Fg(c)-150 3589 y Fi(compute)25 b(agenda)g(for)e(calendar)i(cursor)e -(date)180 b Fg(c)-150 3659 y Fi(sho)n(w)24 b(phases)g(of)f(the)i(mo)r -(on)669 b Fg(M)-150 3728 y Fi(sho)n(w)24 b(sunrise/sunset)g(times)636 -b Fg(S)-150 3798 y Fi(sho)n(w)24 b(holida)n(ys)1014 b -Fg(H)-150 3868 y Fi(con)n(v)n(ert)25 b(date)g(to)f(other)g(calendars) -478 b Fg(C)-150 3964 y Fd(Quit)27 b(and)g(Exit)-150 4060 +b Fg(c)-150 3555 y Fi(compute)25 b(agenda)g(for)e(calendar)i(cursor)e +(date)180 b Fg(c)-150 3624 y Fi(sho)n(w)24 b(phases)g(of)f(the)i(mo)r +(on)669 b Fg(M)-150 3694 y Fi(sho)n(w)24 b(sunrise/sunset)g(times)636 +b Fg(S)-150 3764 y Fi(sho)n(w)24 b(holida)n(ys)1014 b +Fg(H)-150 3834 y Fi(con)n(v)n(ert)25 b(date)g(to)f(other)g(calendars) +478 b Fg(C)-150 3932 y Fd(Quit)27 b(and)g(Exit)-150 4030 y Fi(quit)d(agenda,)h(remo)n(v)n(e)f(agenda)h(bu\013er)376 -b Fg(q)-150 4130 y Fi(exit)24 b(agenda,)h(remo)n(v)n(e)f(all)f(agenda)i +b Fg(q)-150 4100 y Fi(exit)24 b(agenda,)h(remo)n(v)n(e)f(all)f(agenda)i (bu\013ers)258 b Fg(x)2046 -364 y Fh(Exp)s(orting)2046 -229 y Fi(Exp)r(orting)32 b(creates)g(\014les)g(with)f(extensions)i Fc(.txt)k Fi(and)32 b Fc(.html)38 b Fi(in)31 b(the)2046 @@ -2750,7 +2741,7 @@ Fg(org-CUA-compatibility)p Fi(.)4535 3770 y Fb(Cop)n(yrigh)n(t)4838 3768 y(c)4821 3770 y Fa(\015)d Fb(2005)i(F)-5 b(ree)21 b(Soft)n(w)n(are)i(F)-5 b(oundation,)20 b(Inc.)4795 3826 -y(v3.21)h(for)h(Org-Mo)r(de)e(3.21,)i(2005)4912 3882 +y(v3.22)h(for)h(Org-Mo)r(de)e(3.22,)i(2005)4912 3882 y(Author:)k(Philip)18 b(Ro)r(ok)n(e)4473 3937 y(based)j(on)g(refcard)g (design)g(and)f(format)i(b)n(y)f(Stephen)f(Gildea)4242 4022 y(P)n(ermission)28 b(is)f(gran)n(ted)i(to)f(mak)n(e)h(and)e
--- a/etc/orgcard.tex Sat Dec 10 21:12:12 2005 +0000 +++ b/etc/orgcard.tex Sat Dec 10 21:18:28 2005 +0000 @@ -1,4 +1,4 @@ -% Reference Card for Org Mode 3.21 +% Reference Card for Org Mode 3.22 % %**start of header \newcount\columnsperpage @@ -58,7 +58,7 @@ % Thanks to Paul Rubin, Bob Chassell, Len Tower, and Richard Mlynarik % for their many good ideas. -\def\orgversionnumber{3.21} +\def\orgversionnumber{3.22} \def\year{2005} \def\shortcopyrightnotice{\vskip 1ex plus 2 fill @@ -270,18 +270,20 @@ \section{Getting Started} % -Put the following in your \kbd{~/.emacs}$^1$ +%Put the following in your \kbd{~/.emacs}$^1$ \vskip -1mm \beginexample% -(autoload 'org-mode "org" "Org mode" t) -(autoload 'org-diary "org" "Org mode diary entries") -(autoload 'org-agenda "org" "Agenda from Org files" t) -(autoload 'org-store-link "org" "Store org link" t) -(autoload 'orgtbl-mode "org" "Orgtbl minor mode" t) -(autoload 'turn-on-orgtbl "org" "Orgtbl minor mode") +%(autoload 'org-mode "org" "Org mode" t) +%(autoload 'org-diary "org" "Org mode diary entries") +%(autoload 'org-agenda "org" "Agenda from Org files" t) +%(autoload 'org-todo-list "org" "Global TODO list" t) +%(autoload 'org-store-link "org" "Store org link" t) +%(autoload 'orgtbl-mode "org" "Orgtbl minor mode" t) +%(autoload 'turn-on-orgtbl "org" "Orgtbl minor mode") (add-to-list 'auto-mode-alist '("\\\\.org\$" . org-mode)) (define-key global-map "\\C-cl" 'org-store-link)$^2$ (define-key global-map "\\C-ca" 'org-agenda)$^2$ +(define-key global-map "\\C-ct" 'org-todo-list)$^2$ \endexample % \metax{For the many customization options try}{M-x org-customize} @@ -330,15 +332,17 @@ \key{show sparse tree for all matches of a regexp}{C-c /} \key{view TODO's in sparse tree}{C-c C-v} +\key{global TODO list in agenda mode}{C-c t$^2$} \key{create sparse tree with all deadlines due}{C-c C-w} \key{time sorted view of current org file}{C-c C-r} -\key{agenda for the week}{C-c a$2$} +\key{agenda for the week}{C-c a$^2$} \key{agenda for date at cursor}{C-c C-o} \section{TODO Items} \key{rotate the state of the current item}{C-c C-t} \key{view TODO items in a sparse tree}{C-c C-v} +\key{view 3rd TODO keyword's sparse tree}{C-3 C-c C-v} \key{set the priority of the current item}{C-c , [ABC]} \key{remove priority cookie from current item}{C-c , SPC} @@ -374,12 +378,12 @@ \key{access the calendar for the current date}{C-c >} \key{insert timestamp matching date in calendar}{C-c <} \key{access agenda for current date}{C-c C-o} -\key{While prompted for a date:}{} -\key{... select date in calendar}{mouse-1/RET} -\key{... scroll calendar back/forward one month}{< / >} -\key{... forward/backward one day}{S-LEFT/RIGHT} -\key{... forward/backward one week}{S-UP/DOWN} -\key{... forward/backward one month}{M-S-LEFT/RIGT} +\key{Select date while prompted}{mouse-1/RET} +%\key{... select date in calendar}{mouse-1/RET} +%\key{... scroll calendar back/forward one month}{< / >} +%\key{... forward/backward one day}{S-LEFT/RIGHT} +%\key{... forward/backward one week}{S-UP/DOWN} +%\key{... forward/backward one month}{M-S-LEFT/RIGT} \section{Links} @@ -394,19 +398,25 @@ {\bf Link types} +\key{\kbd{*CamelCaseWord}}{\rm search headline} +\key{\kbd{CamelCaseWord}}{\rm search in buffer} +\key{\kbd{<file:/home/dominik/img/mars.jpg>}}{\rm file, absolute} +\key{\kbd{<file:papers/last.pdf>}}{\rm file, relative} +\key{\kbd{<file:~/code/main.c:255>}}{\rm file with line nr.} +\key{\kbd{<file:projects.org::*CamelCaseWord>}}{\rm search headline} +\key{\kbd{<file:projects.org::find me>}}{\rm search string} +\key{\kbd{<file:projects.org::/regexp/>}}{\rm search regexp} \key{\kbd{<http://www.astro.uva.nl/~dominik>}}{\rm on the web} \key{\kbd{<mailto:adent@galaxy.net>}}{\rm EMail address} \key{\kbd{<news:comp.emacs>}}{\rm Usenet group} -\key{\kbd{<file:/home/dominik/img/mars.jpg>}}{\rm file, absolute} -\key{\kbd{<file:papers/last.pdf>}}{\rm file, relative} -\key{\kbd{<file:~/code/main.c:255>}}{\rm file with line nr.} \key{\kbd{<bbdb:Richard Stallman>}}{\rm BBDB person} \key{\kbd{<shell:ls *.org>}}{\rm shell command} \key{\kbd{<gnus:group>}}{\rm GNUS group} \key{\kbd{<gnus:group\#id>}}{\rm GNUS message} \key{\kbd{<vm:folder>}}{\rm VM folder} \key{\kbd{<vm:folder\#id>}}{\rm VM message} -\key{\kbd{<vm://myself@some.where.org/folder\#id>}}{\rm VM remote} +% FIXME: would like to get this back in. +%\key{\kbd{<vm://myself@some.where.org/folder\#id>}}{\rm VM remote} Wanderlust \kbd{<wl:...>} and RMAIL \kbd{<rmail:...>} like VM %\key{\kbd{<wl:folder>}}{\rm Wanderlust f.} %\key{\kbd{<wl:folder\#id>}}{\rm Wanderlust m.} @@ -506,7 +516,7 @@ \centerline{(for version \orgversionnumber)} -\section{Timeline and Agenda} +\section{Timeline, Agenda, Global TODO List} \key{show timeline of current org file}{C-c C-r} \key{... include past dates}{C-u C-c C-r} @@ -516,6 +526,7 @@ \key{cycle through agenda file list}{C-,} \key{compile agenda for the current week}{C-c a$^2$} \key{agenda for date at cursor}{C-c C-o} +\key{global TODO list}{C-c t$^2$} \vskip 1mm To set category for current file, add line$^3$: \vskip -1mm @@ -525,8 +536,6 @@ {\bf Commands available in an agenda buffer} -The agenda buffer is electric: single key presses execute commands. - {\bf View org file} \key{show original location of item}{SPC}
--- a/lisp/ChangeLog Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/ChangeLog Sat Dec 10 21:18:28 2005 +0000 @@ -1,3 +1,320 @@ +2005-12-08 Kenichi Handa <handa@m17n.org> + + * descr-text.el (describe-char): Use *Help-2* buffer if the + current buffer is *Help*. Call describe-text-properties while + setting the original buffer. + +2005-12-07 Bill Wohler <wohler@newt.com> + + * files.el (auto-mode-alist): Remove mh-letter-mode. Unnecessary, + and causes problems with non-MH users (such as Gnus users). + +2005-12-08 Nick Roberts <nickrob@snap.net.nz> + + * progmodes/gdb-ui.el (gdb-find-file-unhook): Delete variable. + (gdb-set-gud-minor-mode, gdb-set-gud-minor-mode): Delete functions. + (gdb-set-gud-minor-mode-existing-buffers, gdb-init-2): Use GDB + command "info sources". Move calls to GDB command "list". + (gdb-find-file-hook): Just use gdb-source-file-list. + (gdb-source-file-regexp): Use regexp for pre-GDB 6.4. + (gdb-source-file-regexp-1): New regexp for GDB 6.4+ only. + (gdb-set-gud-minor-mode-existing-buffers-1): Use it. + (gdb-data-list-register-values-handler): Use correct trigger name. + +2005-12-07 Kim F. Storm <storm@cua.dk> + + * ido.el (ido-completion-map): Renamed from ido-mode-map. + (ido-common-completion-map, ido-file-completion-map) + (ido-file-dir-completion-map, ido-buffer-completion-map): + Renamed from ido-mode-....-map. + (ido-init-completion-maps): Renamed from ido-init-mode-maps. + (ido-setup-completion-map): Renamed from ido-define-mode-map. + (ido-read-internal): Bind minibuffer-local-filename-completion-map + to ido-completion-map. + +2005-12-07 Kenichi Handa <handa@m17n.org> + + * international/mule-cmds.el + (set-display-table-and-terminal-coding-system): If the coding + system specified in `unibyte-display' property is different from + the arg coding-system, don't setup standard-display-table. + +2005-12-06 Stefan Monnier <monnier@iro.umontreal.ca> + + * emacs-lisp/edebug.el (edebug-skip-whitespace): read1:lread.c says + that comments end at \n, regardless of selective-display. + +2005-12-07 Nick Roberts <nickrob@snap.net.nz> + + * progmodes/gdb-ui.el (gdb-error-regexp, gdb-first-post-prompt) + (gdb-version): New variables. + (gdb-source-file-list, gdb-register-names) + (gdb-changed-registers): New variables for use with GDB 6.4+. + (gdb-ann3): Replace with... + (gdb-init-1, gdb-init-2): ...two new functions. + (gdba, gdb-prompt): Call gdb-init-1. + (gdb-get-version): New function. Call gdb-init-2 from here. + (gud-watch): Make it work with mouse events too. + (gdb-post-prompt): Don't add to queue until GDB version is known. + (gdb-speedbar-expand-node, gdb-post-prompt, gdb-registers-mode) + (gdb-locals-mode): Use gdb-version. + (gdb-memory-format-map, gdb-memory-unit-map) + (gdb-locals-watch-map): Rename from gdb-*-*-keymap. + (gdb-locals-font-lock-keywords-1) + (gdb-locals-font-lock-keywords-2): New variables. + (gdb-find-file-hook): fgfg. + (gdb-set-gud-minor-mode-existing-buffers-1) + (gdb-var-list-children-1, gdb-var-list-children-handler-1) + (gdb-var-update-1, gdb-var-update-handler-1) + (gdb-data-list-register-values-handler) + (gdb-data-list-register-values-custom) + (gdb-get-changed-registers, gdb-get-changed-registers-handler) + (gdb-stack-list-locals-handler, gdb-get-register-names): + New functions for use with GDB 6.4+. + (gdb-locals-watch-map-1): New variable for use with GDB 6.4+. + (gdb-source-file-regexp, gdb-var-list-children-regexp-1) + (gdb-var-update-regexp-1, gdb-data-list-register-values-regexp) + (gdb-stack-list-locals-regexp) + (gdb-data-list-register-names-regexp): New regexps for use with + GDB 6.4+. + +2005-12-06 Stefan Monnier <monnier@iro.umontreal.ca> + + * progmodes/cc-defs.el (c-emacs-features): Don't assume point-min==1. + +2005-12-06 Nozomu Ando <nand@mac.com> (tiny patch) + + * mail/smtpmail.el (smtpmail-try-auth-methods): Make password + prompts work for AUTH PLAIN. Also reported by Steve Allan + <seallan@verizon.net>. + +2005-12-06 L$,1 q(Brentey K,Aa(Broly <lorentey@elte.hu> + + * frame.el (set-frame-parameter): Add doc string. + +2005-12-06 Carsten Dominik <dominik@science.uva.nl> + + * textmodes/org.el: (org-occur-highlights): New variable. + (org-highlight-new-match, org-remove-occur-highlights): New functions. + (org-highlight-sparse-tree-matches): New option. + (org-do-occur): New function. + (org-get-heading): Make it work also at beginning of line. + (org-category-table): New variable. + (org-get-category-table, org-get-category) + (org-camel-to-words, org-link-search): New functions. + (org-select-this-todo-keyword): New variable. + (org-todo-list): New command. + (org-shiftright, org-shiftleft): New commands. + (org-agenda-todo): Add prefix argument. + (org-show-hierarchy-above): New option. + (org-show-todo-tree): Numerical prefix creates tree for specific + TODO keyword. + (org-outline-level): New function, to assign a level to plain + lists items. + (org-cycle-include-plain-lists): New option. + (org-mode): Use `org-outline-level' as value of `outline-level'. + (org-cycle): Temporarily switch `outline-regexp' if + `org-cycle-include-plain-lists' is non-nil. + (org-start-icalendar-file): Fix format bug. + (org-agenda-get-day-entries): Create category table. + (org-agenda-get-todos, org-agenda-get-timestamps) + (org-agenda-get-deadlines, org-agenda-get-scheduled) + (org-agenda-get-blocks): Use `org-get-category'. + (org-context-in-file-links): Rename from + `org-line-numbers-in-file-links' . + +2005-12-06 Romain Francoise <romain@orebokech.com> + + * window.el (balance-windows): Delete extraneous third arg in call + to `enlarge-window'. + +2005-12-06 Kenichi Handa <handa@m17n.org> + + * international/kinsoku.el (kinsoku-longer): Check eolp, not eobp. + +2005-12-06 Nick Roberts <nickrob@snap.net.nz> + + * progmodes/gdb-ui.el (gdb-var-create-handler) + (gdb-var-evaluate-expression-handler, gdb-frame-handler) + (gdb-var-list-children-handler, gdb-var-update-handler): + Current buffer is already gdb-partial-output-buffer, don't + make it current again. + +2005-12-05 Luc Teirlinck <teirllm@auburn.edu> + + * buff-menu.el (Buffer-menu-use-frame-buffer-list): New user option. + (list-buffers-noselect): Use it. + +2005-12-05 Stefan Monnier <monnier@iro.umontreal.ca> + + * mail/sendmail.el: Remove unnecessary leading-star in docstrings. + (mail-yank-ignored-headers): Use regexp-opt. + (mail-mode-map): Move initialization into declaration. + (mail-sent-via): Remove unused shadowed var `to-line'. + (mail-mailer-swallows-blank-line): Use with-temp-buffer. + (mail-bury, sendmail-send-it, mail-do-fcc): Use with-current-buffer. + (mail-do-fcc): Use dolist and push. + (mail-mode-fill-paragraph): Pass the arg to fill-region-as-paragraph. + (mail-yank-ignored-headers): Don't autoload. + +2005-12-05 Kenichi Handa <handa@m17n.org> + + * international/mule-cmds.el (set-language-info-internal): New fun. + (set-language-info): Call set-language-info-internal to update + language-info-alist. If LANG-ENV is the current one, call + set-language-environment to make INFO effective now. + (set-language-info-alist): Likewise. + (locale-language-names): With locale "en", use English + lang. env. but set the default codings to iso-8859-1. + +2005-12-04 Nick Roberts <nickrob@snap.net.nz> + + * progmodes/gdb-ui.el (gdb-use-inferior-io-buffer) + (gdb-speedbar-auto-raise): Echo new state in minibuffer. + (gdb-var-create-handler, gdb-assembler-custom): Use search-forward + for plain strings. + (gdb-frames-mode): Remove redundant call to font-lock-mode. + (gdb-all-registers): Rename from toggle-gdb-all-registers. + Create registers buffer if necessary. Echo new state in minibuffer. + (gdb-registers-mode-map, gdb-registers-mode): Use gdb-all-registers. + +2005-12-03 Chong Yidong <cyd@stupidchicken.com> + + * info.el (Info-fontify-node): Match external links using + non-directory part of filename. + +2005-12-04 Juri Linkov <juri@jurta.org> + + * font-core.el (global-font-lock-mode): Use define-global-minor-mode + instead of easy-mmode-define-global-mode. Add `:group font-lock'. + (font-lock-mode): Replace `:group font-lock' with `nil nil nil'. + + * font-lock.el (lisp-font-lock-keywords-1): + Add define-global-minor-mode. + + * emacs-lisp/autoload.el (make-autoload): Add define-global-minor-mode. + + * emacs-lisp/derived.el (define-derived-mode): Put `definition-name' + properties on the constructed variable names. + + * emacs-lisp/easy-mmode.el (easy-mmode-define-navigation): + Put `definition-name' properties on the constructed function names + next-sym and prev-sym. + + * emacs-lisp/find-func.el (find-function-regexp): + Add define-global-minor-mode. Replace `easy-mmode-define-global-mode' + with `easy-mmode-define-[a-z-]+'. Add easy-menu-define. + (find-variable-regexp): Add easy-mmode-defmap, easy-mmode-defsyntax + and easy-menu-define. + + * emacs-lisp/lisp-mode.el: Put `doc-string-elt' property on + easy-mmode-define-global-mode and define-global-minor-mode. + (lisp-imenu-generic-expression): Add define-global-minor-mode. + + * progmodes/cwarn.el (global-cwarn-mode): Use define-global-minor-mode + instead of easy-mmode-define-global-mode. + + * progmodes/idlw-shell.el (idlwave-shell-electric-debug-mode): + Use define-minor-mode instead of easy-mmode-define-minor-mode. + + * cus-edit.el (customize-group, customize-group-other-window): + Filter out autoloaded options from the group completion list by + using heuristics that autoloaded groups don't have `custom-autoload' + property on their symbols (they have only `custom-loads'). + + * simple.el (completion-setup-function): Put completions-common-part + face on full completion string too (i.e. completion string without + completions-first-difference face). + + * man.el (Man-section-regexp): Add 0-9 to support "3X11" sections. + +2005-12-03 Eli Zaretskii <eliz@gnu.org> + + * view.el (view-mode): Doc fix. + + * disp-table.el (standard-display-european): Add to the warning + message a reference to the doc string. + + * play/yow.el (apropos-zippy): Call print-help-return-message, + similar to other Help and Apropos commands. + + * help.el (print-help-return-message): If pop-up-frames is + non-nil, set up help-return-method to delete the help window and, + possibly, its frame as well, and don't display message about + scrolling the help window. Doc fix. + (help-return-method): Doc fix. + +2005-12-03 Martin Rudalics <rudalics@gmx.at> (tiny change) + + * emacs-lisp/lisp-mode.el (lisp-imenu-generic-expression): Fix bug + whereby names of length one or names starting with a + symbol-constituent character would not be returned. + +2005-12-03 Johan Bockg,Ae(Brd <bojohan@dd.chalmers.se> + + * subr.el (atomic-change-group): Add edebug and indentation spec. + +2005-12-02 Stefan Monnier <monnier@iro.umontreal.ca> + + * completion.el (save-completions-file-name): Fix typo in last change. + +2005-12-02 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> + + * info.el: Move back/forward history to the beginning of the tool bar. + +2005-12-02 Ken Manheimer <ken.manheimer@gmail.com> + + * allout.el:(eval-when-compile): Remove unnecessary load of 'cl. + Add fset of allout-real-isearch-abort during compile to fix + byte-compilation warnings. + (allout-mode-p): Move definition of this macro above all uses, or + byte compilation in barren emacs (eg, during emacs build) will + lack the definition. + (allout-mode): Move this variable above any uses, or byte + compilation will fail. + (allout-resolve-xref): Remove use of personal file-reference function. + (allout-toggle-current-subtree-encryption): Do the current (ie, + visible containing) topic, rather than nearest around point. Doc fix. + (allout-toggle-subtree-encryption): New function, workhorse that + works on nearest topic containing point. + (allout-encrypt-string): Signal requirement for newer version of pgg. + (allout-resumptions): Doc fix. + +2005-12-02 Eli Zaretskii <eliz@gnu.org> + + * international/latexenc.el (latex-inputenc-coding-alist): Doc fix. + +2005-12-02 Agustin Martin <agustin.martin@hispalinux.es> + + * textmodes/flyspell.el (flyspell-external-point-words): + Consider a misspelling as found in the string search if: (a) misspelling + and found string lengths match, or (b) misspelling is found as + element in a boundary-chars separated longer string, or (c) + ispell-program-name is really ispell and misspelling is found as + part of a TeX string. After successful match move beginning of + search region to end of match. Warn about not found misspellings + once the process is done. + (flyspell-large-region): Do not set ispell-parser to tex if in TeX mode. + +2005-12-02 Nick Roberts <nickrob@snap.net.nz> + + * progmodes/gud.el (gud-menu-map): Put gud-finish back on the + tool bar (removed inadvertently). + +2005-12-02 Juri Linkov <juri@jurta.org> + + * log-view.el (log-view-diff): Clarify doc string. + +2005-12-01 Bill Wohler <wohler@newt.com> + + * Makefile.in (mh-loaddefs.el): Reinsert Change Log as its absence + triggers lm-verify errors. + +2005-12-01 Luc Teirlinck <teirllm@auburn.edu> + + * simple.el (transient-mark-mode, line-number-mode) + (column-number-mode, size-indication-mode): Remove `:require nil'. + 2005-12-01 Nick Roberts <nickrob@snap.net.nz> * progmodes/gdb-ui.el (gdb-ann3): Bind mouse-2 to gdb-mouse-until @@ -18,7 +335,7 @@ (speedbar-frame-reposition-smartly): Use it. * dframe.el (dframe-reposition-frame-emacs): Fix position - computation for 'left location. + computation for `left' location. Update copyright year. 2005-11-30 Stefan Monnier <monnier@iro.umontreal.ca>
--- a/lisp/Makefile.in Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/Makefile.in Sat Dec 10 21:18:28 2005 +0000 @@ -235,6 +235,7 @@ echo ";; Author: Bill Wohler <wohler@newt.com>" >> $@ echo ";; Keywords: mail" >> $@ echo ";;; Commentary:" >> $@ + echo ";;; Change Log:" >> $@ echo ";;; Code:" >> $@ $(EMACS) $(EMACSOPT) \ -l autoload \
--- a/lisp/allout.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/allout.el Sat Dec 10 21:18:28 2005 +0000 @@ -80,9 +80,11 @@ (provide 'allout) ;;;_* Dependency autoloads -(eval-when-compile 'cl) ; otherwise, flet compilation fouls (eval-when-compile (progn (require 'pgg) - (require 'pgg-gpg))) + (require 'pgg-gpg) + (fset 'allout-real-isearch-abort + (symbol-function 'isearch-abort)) + )) (autoload 'pgg-gpg-symmetric-key-p "pgg-gpg" "True if decoded armor MESSAGE-KEYS has symmetric encryption indicator.") @@ -585,8 +587,7 @@ is nil. Operations potentially causing edits include allout encryption routines. -See the docstring for `allout-toggle-current-subtree-encryption' for -details." +For details, see `allout-toggle-current-subtree-encryption's docstring." :type 'boolean :group 'allout) (make-variable-buffer-local 'allout-enable-file-variable-adjustment) @@ -606,6 +607,10 @@ (if here (insert msg)) (message "%s" msg) msg)) +;;;_ : Mode activation (defined here because it's referenced early) +;;;_ = allout-mode +(defvar allout-mode nil "Allout outline mode minor-mode flag.") +(make-variable-buffer-local 'allout-mode) ;;;_ : Topic header format ;;;_ = allout-regexp (defvar allout-regexp "" @@ -898,7 +903,7 @@ First arg is NAME of variable affected. Optional second arg is list containing allout-mode-specific VALUE to be imposed on named -variable, and to be registered. (It's a list so you can specify +variable, and to be registered. \(It's a list so you can specify registrations of null values.) If no value is specified, the registered value is returned (encapsulated in the list, so the caller can distinguish nil vs no value), and the registration is popped @@ -1033,6 +1038,12 @@ This is used to decrypt the topic that was currently being edited, if it was encrypted automatically as part of a file write or autosave.") (make-variable-buffer-local 'allout-after-save-decrypt) +;;;_ > allout-mode-p () +;; Must define this macro above any uses, or byte compilation will lack +;; proper def, if file isn't loaded - eg, during emacs build! +(defmacro allout-mode-p () + "Return t if `allout-mode' is active in current buffer." + 'allout-mode) ;;;_ > allout-write-file-hook-handler () (defun allout-write-file-hook-handler () "Implement `allout-encrypt-unencrypted-on-saves' policy for file writes." @@ -1061,7 +1072,7 @@ nil) ;;;_ > allout-auto-save-hook-handler () (defun allout-auto-save-hook-handler () - "Implement `allout-encrypt-unencrypted-on-saves' policy for auto saves." + "Implement `allout-encrypt-unencrypted-on-saves' policy for auto save." (if (and (allout-mode-p) allout-encrypt-unencrypted-on-saves) ;; Always implement 'except-current policy when enabled. @@ -1082,7 +1093,7 @@ t (goto-char (car allout-after-save-decrypt)) (let ((was-modified (buffer-modified-p))) - (allout-toggle-current-subtree-encryption) + (allout-toggle-subtree-encryption) (if (not was-modified) (set-buffer-modified-p nil))) (goto-char (cadr allout-after-save-decrypt)) @@ -1090,13 +1101,6 @@ ) ;;;_ #2 Mode activation -;;;_ = allout-mode -(defvar allout-mode () "Allout outline mode minor-mode flag.") -(make-variable-buffer-local 'allout-mode) -;;;_ > allout-mode-p () -(defmacro allout-mode-p () - "Return t if `allout-mode' is active in current buffer." - 'allout-mode) ;;;_ = allout-explicitly-deactivated (defvar allout-explicitly-deactivated nil "If t, `allout-mode's last deactivation was deliberate. @@ -1297,7 +1301,7 @@ encryption, encryption with a mistaken passphrase, forgetting which passphrase was used, and other practical pitfalls. -See the `allout-toggle-current-subtree-encryption' function and +See `allout-toggle-current-subtree-encryption' function docstring and `allout-encrypt-unencrypted-on-saves' customization variable for details. HOT-SPOT Operation @@ -1404,12 +1408,10 @@ (or (and (listp toggle)(car toggle)) toggle))) ; Activation specifically demanded? - (explicit-activation (or - ;; - (and toggle + (explicit-activation (and toggle (or (symbolp toggle) - (and (natnump toggle) - (not (zerop toggle))))))) + (and (wholenump toggle) + (not (zerop toggle)))))) ;; allout-mode already called once during this complex command? (same-complex-command (eq allout-v18/19-file-var-hack (car command-history))) @@ -3714,14 +3716,7 @@ (setq file-name (if (re-search-forward "\\s-\\(\\S-*\\)" heading-end t) (buffer-substring (match-beginning 1) (match-end 1)))))) - (setq file-name - (if (not (= (aref file-name 0) ?:)) - (expand-file-name file-name) - ; A registry-files ref, strip the `:' - ; and try to follow it: - (let ((reg-ref (reference-registered-file - (substring file-name 1) nil t))) - (if reg-ref (car (cdr reg-ref)))))) + (setq file-name (expand-file-name file-name)) (if (or (file-exists-p file-name) (if (file-writable-p file-name) (y-or-n-p (format "%s not there, create one? " @@ -4851,13 +4846,13 @@ ;;;_ #8 Encryption ;;;_ > allout-toggle-current-subtree-encryption (&optional fetch-pass) (defun allout-toggle-current-subtree-encryption (&optional fetch-pass) - "Encrypt clear text or decrypt encoded topic contents \(body and subtopics.) + "Encrypt clear or decrypt encoded text of visibly-containing topic's contents. Optional FETCH-PASS universal argument provokes key-pair encryption with single universal argument. With doubled universal argument \(value = 16), it forces prompting for the passphrase regardless of availability from the passphrase cache. With no universal argument, the appropriate passphrase -for the is obtained from the cache, if available, else from the user. +is obtained from the cache, if available, else from the user. Currently only GnuPG encryption is supported. @@ -4915,6 +4910,28 @@ enabled \(see the `allout-passphrase-hint-handling' docstring for details), the hint string is stored in the local-variables section of the file, and solicited whenever the passphrase is changed." + (interactive "P") + (save-excursion + (allout-back-to-current-heading) + (allout-toggle-subtree-encryption) + ) + ) +;;;_ > allout-toggle-subtree-encryption (&optional fetch-pass) +(defun allout-toggle-subtree-encryption (&optional fetch-pass) + "Encrypt clear text or decrypt encoded topic contents \(body and subtopics.) + +Optional FETCH-PASS universal argument provokes key-pair encryption with +single universal argument. With doubled universal argument \(value = 16), +it forces prompting for the passphrase regardless of availability from the +passphrase cache. With no universal argument, the appropriate passphrase +is obtained from the cache, if available, else from the user. + +Currently only GnuPG encryption is supported. + +\**NOTE WELL** that the encrypted text must be ascii-armored. For gnupg +encryption, include the option ``armor'' in your ~/.gnupg/gpg.conf file. + +See `allout-toggle-current-subtree-encryption' for more details." (interactive "P") (save-excursion @@ -5022,6 +5039,9 @@ (require 'pgg) + (if (not (fboundp 'pgg-encrypt-symmetric)) + (error "Allout encryption depends on a newer version of pgg")) + (let* ((scheme (upcase (format "%s" (or pgg-scheme pgg-default-scheme "GPG")))) (for-key (and (equal key-type 'keypair) @@ -5498,7 +5518,7 @@ ;; we had to wait for this 'til now so prior topics are ;; encrypted, any relevant text shifts are in place: editing-point (marker-position current-mark))) - (allout-toggle-current-subtree-encryption) + (allout-toggle-subtree-encryption) (if (not was-modified) (set-buffer-modified-p nil)) )
--- a/lisp/buff-menu.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/buff-menu.el Sat Dec 10 21:18:28 2005 +0000 @@ -89,6 +89,16 @@ :type 'number :group 'Buffer-menu) +(defcustom Buffer-menu-use-frame-buffer-list t + "If non-nil, the Buffer Menu uses the selected frame's buffer list. +Buffers that were never selected in that frame are listed at the end. +If the value is nil, the Buffer Menu uses the global buffer list. +This variable matters if the Buffer Menu is sorted by visited order, +as it is by default." + :type 'boolean + :group 'Buffer-menu + :version "22.1") + ;; This should get updated & resorted when you click on a column heading (defvar Buffer-menu-sort-column nil "*2 for sorting by buffer names. 5 for sorting by file names. @@ -722,7 +732,10 @@ (if (memq c '(?\n ?\s)) c underline)) header))))) ;; Collect info for every buffer we're interested in. - (dolist (buffer (or buffer-list (buffer-list (selected-frame)))) + (dolist (buffer (or buffer-list + (buffer-list + (when Buffer-menu-use-frame-buffer-list + (selected-frame))))) (with-current-buffer buffer (let ((name (buffer-name)) (file buffer-file-name))
--- a/lisp/completion.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/completion.el Sat Dec 10 21:18:28 2005 +0000 @@ -302,7 +302,8 @@ (cond ((file-readable-p olddef) olddef) ((file-directory-p (convert-standard-filename "~/.emacs.d/")) - (convert-standard-filename (expand-file-name completions "~/.emacs.d/"))) + (convert-standard-filename + (expand-file-name "completions" "~/.emacs.d/"))) (t olddef))) "The filename to save completions to." :type 'file
--- a/lisp/cus-edit.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/cus-edit.el Sat Dec 10 21:18:28 2005 +0000 @@ -975,13 +975,15 @@ ;;;###autoload (defun customize-group (group) "Customize GROUP, which must be a customization group." - (interactive (list (let ((completion-ignore-case t)) - (completing-read "Customize group (default emacs): " - obarray - (lambda (symbol) - (or (get symbol 'custom-loads) - (get symbol 'custom-group))) - t)))) + (interactive + (list (let ((completion-ignore-case t)) + (completing-read "Customize group (default emacs): " + obarray + (lambda (symbol) + (or (and (get symbol 'custom-loads) + (not (get symbol 'custom-autoload))) + (get symbol 'custom-group))) + t)))) (when (stringp group) (if (string-equal "" group) (setq group 'emacs) @@ -998,13 +1000,15 @@ ;;;###autoload (defun customize-group-other-window (group) "Customize GROUP, which must be a customization group." - (interactive (list (let ((completion-ignore-case t)) - (completing-read "Customize group (default emacs): " - obarray - (lambda (symbol) - (or (get symbol 'custom-loads) - (get symbol 'custom-group))) - t)))) + (interactive + (list (let ((completion-ignore-case t)) + (completing-read "Customize group (default emacs): " + obarray + (lambda (symbol) + (or (and (get symbol 'custom-loads) + (not (get symbol 'custom-autoload))) + (get symbol 'custom-group))) + t)))) (when (stringp group) (if (string-equal "" group) (setq group 'emacs)
--- a/lisp/descr-text.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/descr-text.el Sat Dec 10 21:18:28 2005 +0000 @@ -464,6 +464,9 @@ (single-key-description char) (string-to-multibyte (char-to-string char))))) + (orig-buf (current-buffer)) + (help-buf (if (eq orig-buf (get-buffer "*Help*")) + "*Help-2*" "*Help*")) item-list max-width unicode) (if (or (< char 256) @@ -616,7 +619,7 @@ (setq max-width (apply #'max (mapcar #'(lambda (x) (if (cadr x) (length (car x)) 0)) item-list))) - (with-output-to-temp-buffer "*Help*" + (with-output-to-temp-buffer help-buf (with-current-buffer standard-output (set-buffer-multibyte multibyte-p) (let ((formatter (format "%%%ds:" max-width))) @@ -636,18 +639,17 @@ (insert " " clm))) (insert "\n")))) - (save-excursion - (goto-char (point-min)) - (re-search-forward "character:[ \t\n]+") - (setq pos (point))) - (let ((end (+ pos (length char-description)))) - (if overlays + (when overlays + (save-excursion + (goto-char (point-min)) + (re-search-forward "character:[ \t\n]+") + (let* ((end (+ (point) (length char-description)))) (mapc #'(lambda (props) - (let ((o (make-overlay pos end))) + (let ((o (make-overlay (point) end))) (while props (overlay-put o (car props) (nth 1 props)) (setq props (cddr props))))) - overlays))) + overlays)))) (when disp-vector (insert @@ -720,7 +722,9 @@ (insert "\nSee the variable `reference-point-alist' for " "the meaning of the rule.\n")) - (describe-text-properties pos (current-buffer)) + (save-excursion + (set-buffer orig-buf) + (describe-text-properties pos help-buf)) (describe-text-mode))))) (defalias 'describe-char-after 'describe-char)
--- a/lisp/disp-table.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/disp-table.el Sat Dec 10 21:18:28 2005 +0000 @@ -222,7 +222,7 @@ (set-terminal-coding-system nil)))) (display-warning 'i18n - "`standard-display-european' is semi-obsolete" + "`standard-display-european' is semi-obsolete; see its doc string for details" :warning) ;; Switch to Latin-1 language environment
--- a/lisp/emacs-lisp/autoload.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/emacs-lisp/autoload.el Sat Dec 10 21:18:28 2005 +0000 @@ -86,10 +86,10 @@ ;; For special function-like operators, use the `autoload' function. ((memq car '(defun define-skeleton defmacro define-derived-mode - define-compilation-mode - define-generic-mode easy-mmode-define-minor-mode - easy-mmode-define-global-mode - define-minor-mode defun* defmacro*)) + define-compilation-mode define-generic-mode + easy-mmode-define-global-mode define-global-minor-mode + easy-mmode-define-minor-mode define-minor-mode + defun* defmacro*)) (let* ((macrop (memq car '(defmacro defmacro*))) (name (nth 1 form)) (args (case car @@ -109,6 +109,7 @@ (or (and (memq car '(define-skeleton define-derived-mode define-generic-mode easy-mmode-define-global-mode + define-global-minor-mode easy-mmode-define-minor-mode define-minor-mode)) t) (eq (car-safe (car body)) 'interactive))
--- a/lisp/emacs-lisp/derived.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/emacs-lisp/derived.el Sat Dec 10 21:18:28 2005 +0000 @@ -200,12 +200,19 @@ No problems result if this variable is not bound. `add-hook' automatically binds it. (This is true for all hook variables.)" name))) + (unless (boundp ',map) + (put ',map 'definition-name ',child)) (defvar ,map (make-sparse-keymap)) ,(if declare-syntax - `(defvar ,syntax (make-syntax-table))) + `(progn + (unless (boundp ',syntax) + (put ',syntax 'definition-name ',child)) + (defvar ,syntax (make-syntax-table)))) ,(if declare-abbrev - `(defvar ,abbrev - (progn (define-abbrev-table ',abbrev nil) ,abbrev))) + `(progn + (put ',abbrev 'definition-name ',child) + (defvar ,abbrev + (progn (define-abbrev-table ',abbrev nil) ,abbrev)))) (put ',child 'derived-mode-parent ',parent) ,(if group `(put ',child 'custom-mode-group ,group))
--- a/lisp/emacs-lisp/easy-mmode.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/emacs-lisp/easy-mmode.el Sat Dec 10 21:18:28 2005 +0000 @@ -515,6 +515,7 @@ (unless (pos-visible-in-window-p endpt nil t) (recenter '(0)))))) ,re-narrow-maybe))) + (put ',next-sym 'definition-name ',base) (defun ,prev-sym (&optional count) ,(format "Go to the previous COUNT'th %s" (or name base-name)) (interactive) @@ -524,7 +525,8 @@ ,check-narrow-maybe (unless (re-search-backward ,re nil t count) (error "No previous %s" ,name)) - ,re-narrow-maybe)))))) + ,re-narrow-maybe))) + (put ',prev-sym 'definition-name ',base)))) (provide 'easy-mmode)
--- a/lisp/emacs-lisp/edebug.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/emacs-lisp/edebug.el Sat Dec 10 21:18:28 2005 +0000 @@ -733,8 +733,7 @@ ;; Leave point before the next token, skipping white space and comments. (skip-chars-forward " \t\r\n\f") (while (= (following-char) ?\;) - ;; \r is counted as a comment terminator to support selective display. - (skip-chars-forward "^\n\r") ; skip the comment + (skip-chars-forward "^\n") ; skip the comment (skip-chars-forward " \t\r\n\f")))
--- a/lisp/emacs-lisp/find-func.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/emacs-lisp/find-func.el Sat Dec 10 21:18:28 2005 +0000 @@ -63,8 +63,9 @@ ;; (define-derived-mode foo ...), (define-minor-mode foo) (concat "^\\s-*(\\(def\\(ine-skeleton\\|ine-generic-mode\\|ine-derived-mode\\|\ -ine-minor-mode\\|ine-compilation-mode\\|un-cvs-mode\\|foo\\|[^cfgv]\\w+\\*?\\)\ -\\|easy-mmode-define-global-mode\\|menu-bar-make-toggle\\)" +ine\\(?:-global\\)?-minor-mode\\|ine-compilation-mode\\|un-cvs-mode\\|\ +foo\\|[^cfgv]\\w+\\*?\\)\\|easy-mmode-define-[a-z-]+\\|easy-menu-define\\|\ +menu-bar-make-toggle\\)" find-function-space-re "\\('\\|\(quote \\)?%s\\(\\s-\\|$\\|\(\\|\)\\)") "The regexp used by `find-function' to search for a function definition. @@ -78,7 +79,11 @@ :version "21.1") (defcustom find-variable-regexp - (concat"^\\s-*(def[^fumag]\\(\\w\\|\\s_\\)+\\*?" find-function-space-re "%s\\(\\s-\\|$\\)") + (concat + "^\\s-*(\\(def[^fumag]\\(\\w\\|\\s_\\)+\\*?\\|\ +easy-mmode-def\\(map\\|syntax\\)\\|easy-menu-define\\)" + find-function-space-re + "%s\\(\\s-\\|$\\)") "The regexp used by `find-variable' to search for a variable definition. Note it must contain a `%s' at the place where `format' should insert the variable name. The default value
--- a/lisp/emacs-lisp/lisp-mode.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/emacs-lisp/lisp-mode.el Sat Dec 10 21:18:28 2005 +0000 @@ -96,13 +96,13 @@ (regexp-opt '("defun" "defun*" "defsubst" "defmacro" "defadvice" "define-skeleton" - "define-minor-mode" "define-derived-mode" - "define-generic-mode" + "define-minor-mode" "define-global-minor-mode" + "define-derived-mode" "define-generic-mode" "define-compiler-macro" "define-modify-macro" "defsetf" "define-setf-expander" "define-method-combination" "defgeneric" "defmethod") t)) - "\\s-+\\(\\sw\\(\\sw\\|\\s_\\)+\\)")) + "\\s-+\\(\\(\\sw\\|\\s_\\)+\\)")) 2) (list (purecopy "Variables") (purecopy (concat "^\\s-*(" @@ -110,7 +110,7 @@ (regexp-opt '("defvar" "defconst" "defconstant" "defcustom" "defparameter" "define-symbol-macro") t)) - "\\s-+\\(\\sw\\(\\sw\\|\\s_\\)+\\)")) + "\\s-+\\(\\(\\sw\\|\\s_\\)+\\)")) 2) (list (purecopy "Types") (purecopy (concat "^\\s-*(" @@ -119,7 +119,7 @@ '("defgroup" "deftheme" "deftype" "defstruct" "defclass" "define-condition" "define-widget" "defface" "defpackage") t)) - "\\s-+'?\\(\\sw\\(\\sw\\|\\s_\\)+\\)")) + "\\s-+'?\\(\\(\\sw\\|\\s_\\)+\\)")) 2)) "Imenu generic expression for Lisp mode. See `imenu-generic-expression'.") @@ -141,6 +141,8 @@ (put 'define-compilation-mode 'doc-string-elt 3) (put 'easy-mmode-define-minor-mode 'doc-string-elt 2) (put 'define-minor-mode 'doc-string-elt 2) +(put 'easy-mmode-define-global-mode 'doc-string-elt 2) +(put 'define-global-minor-mode 'doc-string-elt 2) (put 'define-generic-mode 'doc-string-elt 7) (put 'define-ibuffer-filter 'doc-string-elt 2) (put 'define-ibuffer-op 'doc-string-elt 3)
--- a/lisp/files.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/files.el Sat Dec 10 21:18:28 2005 +0000 @@ -1869,7 +1869,6 @@ ;; /tmp/Re.... or Message ("\\`/tmp/Re" . text-mode) ("/Message[0-9]*\\'" . text-mode) - ("/drafts/[0-9]+\\'" . mh-letter-mode) ("\\.zone\\'" . zone-mode) ;; some news reader is reported to use this ("\\`/tmp/fol/" . text-mode)
--- a/lisp/font-core.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/font-core.el Sat Dec 10 21:18:28 2005 +0000 @@ -146,7 +146,7 @@ The above is the default behavior of `font-lock-mode'; you may specify your own function which is called when `font-lock-mode' is toggled via `font-lock-function'. " - :group 'font-lock + nil nil nil ;; Don't turn on Font Lock mode if we don't have a display (we're running a ;; batch job) or if the buffer is invisible (the name starts with a space). (when (or noninteractive (eq (aref (buffer-name) 0) ?\ )) @@ -291,12 +291,13 @@ (let (inhibit-quit) (turn-on-font-lock)))) -(easy-mmode-define-global-mode - global-font-lock-mode font-lock-mode turn-on-font-lock-if-enabled - :extra-args (dummy) - :initialize 'custom-initialize-safe-default - :init-value (not (or noninteractive emacs-basic-display)) - :version "22.1") +(define-global-minor-mode global-font-lock-mode + font-lock-mode turn-on-font-lock-if-enabled + :extra-args (dummy) + :initialize 'custom-initialize-safe-default + :init-value (not (or noninteractive emacs-basic-display)) + :group 'font-lock + :version "22.1") ;;; End of Global Font Lock mode.
--- a/lisp/font-lock.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/font-lock.el Sat Dec 10 21:18:28 2005 +0000 @@ -1967,7 +1967,8 @@ ;; Function declarations. "\\(advice\\|varalias\\|alias\\|generic\\|macro\\*?\\|method\\|" "setf\\|subst\\*?\\|un\\*?\\|" - "ine-\\(condition\\|\\(?:derived\\|minor\\|generic\\)-mode\\|" + "ine-\\(condition\\|" + "\\(?:derived\\|\\(?:global-\\)?minor\\|generic\\)-mode\\|" "method-combination\\|setf-expander\\|skeleton\\|widget\\|" "function\\|\\(compiler\\|modify\\|symbol\\)-macro\\)\\)\\|" ;; Variable declarations.
--- a/lisp/frame.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/frame.el Sat Dec 10 21:18:28 2005 +0000 @@ -953,6 +953,9 @@ (run-hooks 'after-setting-font-hook 'after-setting-font-hooks)) (defun set-frame-parameter (frame parameter value) + "Set frame parameter PARAMETER to VALUE on FRAME. +If FRAME is nil, it defaults to the selected frame. +See `modify-frame-parameters.'" (modify-frame-parameters frame (list (cons parameter value)))) (defun set-background-color (color-name)
--- a/lisp/help.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/help.el Sat Dec 10 21:18:28 2005 +0000 @@ -111,7 +111,8 @@ (defvar help-return-method nil "What to do to \"exit\" the help buffer. This is a list - (WINDOW . t) delete the selected window, go to WINDOW. + (WINDOW . t) delete the selected window (and possibly its frame, + see `quit-window' and `View-quit'), go to WINDOW. (WINDOW . quit-window) do quit-window, then select WINDOW. (WINDOW BUF START POINT) display BUF at START, POINT, then select WINDOW.") @@ -119,10 +120,14 @@ "Display or return message saying how to restore windows after help command. This function assumes that `standard-output' is the help buffer. It computes a message, and applies the optional argument FUNCTION to it. -If FUNCTION is nil, it applies `message', thus displaying the message." +If FUNCTION is nil, it applies `message', thus displaying the message. +In addition, this function sets up `help-return-method', which see, that +specifies what to do when the user exits the help buffer." (and (not (get-buffer-window standard-output)) (let ((first-message - (cond ((special-display-p (buffer-name standard-output)) + (cond ((or + pop-up-frames + (special-display-p (buffer-name standard-output))) (setq help-return-method (cons (selected-window) t)) ;; If the help output buffer is a special display buffer, ;; don't say anything about how to get rid of it. @@ -154,7 +159,8 @@ (if first-message " ") ;; If the help buffer will go in a separate frame, ;; it's no use mentioning a command to scroll, so don't. - (if (special-display-p (buffer-name standard-output)) + (if (or pop-up-windows + (special-display-p (buffer-name standard-output))) nil (if (same-window-p (buffer-name standard-output)) ;; Say how to scroll this window.
--- a/lisp/ido.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/ido.el Sat Dec 10 21:18:28 2005 +0000 @@ -252,7 +252,7 @@ ;; ;;(defun ido-my-keys () ;; "Add my keybindings for ido." -;; (define-key ido-mode-map " " 'ido-next-match) +;; (define-key ido-completion-map " " 'ido-next-match) ;; ) ;; Seeing all the matching buffers or files @@ -716,7 +716,7 @@ "*Hook run after the ido variables and keymap have been setup. The dynamic variable `ido-cur-item' contains the current type of item that is read by ido, possible values are file, dir, buffer, and list. -Additional keys can be defined in `ido-mode-map'." +Additional keys can be defined in `ido-completion-map'." :type 'hook :group 'ido) @@ -898,19 +898,19 @@ ;; Persistent variables -(defvar ido-mode-map nil +(defvar ido-completion-map nil "Currently active keymap for ido commands.") -(defvar ido-mode-common-map nil +(defvar ido-common-completion-map nil "Keymap for all ido commands.") -(defvar ido-mode-file-map nil +(defvar ido-file-completion-map nil "Keymap for ido file commands.") -(defvar ido-mode-file-dir-map nil +(defvar ido-file-dir-completion-map nil "Keymap for ido file and directory commands.") -(defvar ido-mode-buffer-map nil +(defvar ido-buffer-completion-map nil "Keymap for ido buffer commands.") (defvar ido-file-history nil @@ -1345,7 +1345,7 @@ (ido-everywhere (if ido-everywhere 1 -1)) (when ido-mode - (ido-init-mode-maps)) + (ido-init-completion-maps)) (when ido-mode (add-hook 'minibuffer-setup-hook 'ido-minibuffer-setup) @@ -1354,12 +1354,7 @@ (add-hook 'kill-emacs-hook 'ido-kill-emacs-hook) - (if ido-minor-mode-map-entry - (setcdr ido-minor-mode-map-entry (make-sparse-keymap)) - (setq ido-minor-mode-map-entry (cons 'ido-mode (make-sparse-keymap))) - (add-to-list 'minor-mode-map-alist ido-minor-mode-map-entry)) - - (let ((map (cdr ido-minor-mode-map-entry))) + (let ((map (make-sparse-keymap))) (when (memq ido-mode '(file both)) (define-key map [remap find-file] 'ido-find-file) (define-key map [remap find-file-read-only] 'ido-find-file-read-only) @@ -1379,7 +1374,13 @@ (define-key map [remap switch-to-buffer-other-frame] 'ido-switch-buffer-other-frame) (define-key map [remap insert-buffer] 'ido-insert-buffer) (define-key map [remap kill-buffer] 'ido-kill-buffer) - (define-key map [remap display-buffer] 'ido-display-buffer))))) + (define-key map [remap display-buffer] 'ido-display-buffer)) + + (if ido-minor-mode-map-entry + (setcdr ido-minor-mode-map-entry map) + (setq ido-minor-mode-map-entry (cons 'ido-mode map)) + (add-to-list 'minor-mode-map-alist ido-minor-mode-map-entry))))) + (defun ido-everywhere (arg) "Toggle using ido speed-ups everywhere file and directory names are read. @@ -1404,8 +1405,8 @@ ;;; IDO KEYMAP -(defun ido-init-mode-maps () - "Set up the keymaps used by `ido'." +(defun ido-init-completion-maps () + "Set up the completion keymaps used by `ido'." ;; Common map (let ((map (make-sparse-keymap))) @@ -1431,7 +1432,7 @@ (define-key map "\C-f" 'ido-magic-forward-char) (define-key map "\C-d" 'ido-magic-delete-char) (set-keymap-parent map minibuffer-local-map) - (setq ido-mode-common-map map)) + (setq ido-common-completion-map map)) ;; File and directory map (let ((map (make-sparse-keymap))) @@ -1457,8 +1458,8 @@ (define-key map [(meta control ?o)] 'ido-next-work-file) (define-key map [(meta ?p)] 'ido-prev-work-directory) (define-key map [(meta ?s)] 'ido-merge-work-directories) - (set-keymap-parent map ido-mode-common-map) - (setq ido-mode-file-dir-map map)) + (set-keymap-parent map ido-common-completion-map) + (setq ido-file-dir-completion-map map)) ;; File only map (let ((map (make-sparse-keymap))) @@ -1467,19 +1468,19 @@ (define-key map "\C-w" 'ido-copy-current-file-name) (define-key map [(meta ?l)] 'ido-toggle-literal) (define-key map "\C-v" 'ido-toggle-vc) - (set-keymap-parent map ido-mode-file-dir-map) - (setq ido-mode-file-map map)) + (set-keymap-parent map ido-file-dir-completion-map) + (setq ido-file-completion-map map)) ;; Buffer map (let ((map (make-sparse-keymap))) (define-key map "\C-x\C-f" 'ido-enter-find-file) (define-key map "\C-x\C-b" 'ido-fallback-command) (define-key map "\C-k" 'ido-kill-buffer-at-head) - (set-keymap-parent map ido-mode-common-map) - (setq ido-mode-buffer-map map))) - - -(defun ido-define-mode-map () + (set-keymap-parent map ido-common-completion-map) + (setq ido-buffer-completion-map map))) + + +(defun ido-setup-completion-map () "Set up the keymap for `ido'." ;; generated every time so that it can inherit new functions. @@ -1500,18 +1501,18 @@ (define-key map [remap viper-delete-backward-word] 'ido-delete-backward-word-updir)) (set-keymap-parent map (if (eq ido-cur-item 'file) - ido-mode-file-map - ido-mode-file-dir-map))) + ido-file-completion-map + ido-file-dir-completion-map))) ((eq ido-cur-item 'buffer) (when ido-context-switch-command (define-key map "\C-x\C-f" ido-context-switch-command)) - (set-keymap-parent map ido-mode-buffer-map)) + (set-keymap-parent map ido-buffer-completion-map)) (t - (set-keymap-parent map ido-mode-common-map))) - - (setq ido-mode-map map))) + (set-keymap-parent map ido-common-completion-map))) + + (setq ido-completion-map map))) (defun ido-final-slash (dir &optional fix-it) ;; return DIR if DIR has final slash. @@ -1683,7 +1684,7 @@ (ido-enable-regexp ido-enable-regexp) ) - (ido-define-mode-map) + (ido-setup-completion-map) (setq ido-text-init initial) (setq ido-input-stack nil) @@ -1788,7 +1789,8 @@ (if (and ido-matches (eq ido-try-merged-list 'auto)) (setq ido-try-merged-list t)) (let - ((minibuffer-local-completion-map ido-mode-map) + ((minibuffer-local-completion-map ido-completion-map) + (minibuffer-local-filename-completion-map ido-completion-map) (max-mini-window-height (or ido-max-window-height (and (boundp 'max-mini-window-height) max-mini-window-height))) (ido-completing-read t) @@ -3670,7 +3672,7 @@ displayed if substring-matching is used \(default). Look at `ido-enable-prefix' and `ido-toggle-prefix'. When you have found the buffer you want, it can then be selected. As you type, most keys have -their normal keybindings, except for the following: \\<ido-mode-buffer-map> +their normal keybindings, except for the following: \\<ido-buffer-completion-map> RET Select the buffer at the front of the list of matches. If the list is empty, possibly prompt to create new buffer. @@ -3758,7 +3760,7 @@ if substring-matching is used \(default). Look at `ido-enable-prefix' and `ido-toggle-prefix'. When you have found the filename you want, it can then be selected. As you type, most keys have their normal keybindings, -except for the following: \\<ido-mode-file-map> +except for the following: \\<ido-file-completion-map> RET Select the file at the front of the list of matches. If the list is empty, possibly prompt to create new file.
--- a/lisp/info.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/info.el Sat Dec 10 21:18:28 2005 +0000 @@ -3181,11 +3181,11 @@ (if (display-graphic-p) (let ((map (make-sparse-keymap))) (tool-bar-local-item-from-menu 'Info-exit "close" map Info-mode-map) + (tool-bar-local-item-from-menu 'Info-history-back "left-arrow" map Info-mode-map) + (tool-bar-local-item-from-menu 'Info-history-forward "right-arrow" map Info-mode-map) (tool-bar-local-item-from-menu 'Info-prev "prev-node" map Info-mode-map) (tool-bar-local-item-from-menu 'Info-next "next-node" map Info-mode-map) (tool-bar-local-item-from-menu 'Info-up "up-node" map Info-mode-map) - (tool-bar-local-item-from-menu 'Info-history-back "left-arrow" map Info-mode-map) - (tool-bar-local-item-from-menu 'Info-history-forward "right-arrow" map Info-mode-map) (tool-bar-local-item-from-menu 'Info-top-node "home" map Info-mode-map) (tool-bar-local-item-from-menu 'Info-index "index" map Info-mode-map) (tool-bar-local-item-from-menu 'Info-goto-node "jump-to" map Info-mode-map) @@ -3800,17 +3800,25 @@ (and (not (equal (match-string 4) "")) (match-string 4)) (match-string 2))))) - (file Info-current-file) + (external-link-p + (string-match "(\\([^)]+\\))\\([^)]*\\)" node)) + (file (if external-link-p + (file-name-nondirectory + (match-string 1 node)) + Info-current-file)) (hl Info-history-list) res) - (if (string-match "(\\([^)]+\\))\\([^)]*\\)" node) - (setq file (Info-find-file (match-string 1 node) t) - node (if (equal (match-string 2 node) "") + (if external-link-p + (setq node (if (equal (match-string 2 node) "") "Top" (match-string 2 node)))) (while hl (if (and (string-equal node (nth 1 (car hl))) - (string-equal file (nth 0 (car hl)))) + (string-equal + file (if external-link-p + (file-name-nondirectory + (caar hl)) + (caar hl)))) (setq res (car hl) hl nil) (setq hl (cdr hl)))) res))) 'info-xref-visited 'info-xref)) @@ -3902,20 +3910,27 @@ ;; Display visited menu items in a different face (if (and Info-fontify-visited-nodes (save-match-data - (let ((node (if (equal (match-string 3) "") - (match-string 1) - (match-string 3))) - (file Info-current-file) - (hl Info-history-list) - res) - (if (string-match "(\\([^)]+\\))\\([^)]*\\)" node) - (setq file (Info-find-file (match-string 1 node) t) - node (if (equal (match-string 2 node) "") + (let* ((node (if (equal (match-string 3) "") + (match-string 1) + (match-string 3))) + (external-link-p + (string-match "(\\([^)]+\\))\\([^)]*\\)" node)) + (file (if external-link-p + (file-name-nondirectory + (match-string 1 node)) + Info-current-file)) + (hl Info-history-list) + res) + (if external-link-p + (setq node (if (equal (match-string 2 node) "") "Top" (match-string 2 node)))) (while hl (if (and (string-equal node (nth 1 (car hl))) - (string-equal file (nth 0 (car hl)))) + (string-equal + file (if external-link-p + (file-name-nondirectory (caar hl)) + (caar hl)))) (setq res (car hl) hl nil) (setq hl (cdr hl)))) res))) 'info-xref-visited 'info-xref)))
--- a/lisp/international/kinsoku.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/international/kinsoku.el Sat Dec 10 21:18:28 2005 +0000 @@ -109,7 +109,7 @@ $A!.!0#"#(!2!4!6!8!:!<!>!c!d!e#@!f!l(B" ;; Chinese GB2312 "$A(E(F(G(H(I(J(K(L(M(N(O(P(Q(R(S(T(U(V(W(X(Y(h(B\ -$(0!>!@!B!D!F!H!J!L!N!P!R!T!V!X!Z!\!^!`!b(B" +\$(0!>!@!B!D!F!H!J!L!N!P!R!T!V!X!Z!\!^!`!b(B" ;; Chinese BIG5 "$(0!d!f!h!j!k!q!p"i"j"k"n"x$u$v$w$x$y$z${(B\ $(0$|$}$~%!%"%#%$%%%&%'%(%)%*%+%:(B")) @@ -126,7 +126,7 @@ (let ((pos-and-column (save-excursion (forward-char 1) - (while (and (not (eobp)) + (while (and (not (eolp)) (or (aref (char-category-set (following-char)) ?>) ;; protect non-kinsoku words (not (or (eq (preceding-char) ? )
--- a/lisp/international/latexenc.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/international/latexenc.el Sat Dec 10 21:18:28 2005 +0000 @@ -78,7 +78,7 @@ ("next" . next) ; The Next encoding ("utf8" . utf-8) ("utf8x" . utf-8)) ; used by the Unicode LaTeX package - "Mapping from LaTeX encodings to Emacs coding systems. + "Mapping from LaTeX encodings in \"inputenc.sty\" to Emacs coding systems. LaTeX encodings are specified with \"\\usepackage[encoding]{inputenc}\". Used by the function `latexenc-find-file-coding-system'." :group 'files
--- a/lisp/international/mule-cmds.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/international/mule-cmds.el Sat Dec 10 21:18:28 2005 +0000 @@ -1126,6 +1126,13 @@ see `language-info-alist'." (if (symbolp lang-env) (setq lang-env (symbol-name lang-env))) + (set-language-info-internal lang-env key info) + (if (equal lang-env current-language-environment) + (set-language-environment lang-env))) + +(defun set-language-info-internal (lang-env key info) + "Internal use only. +Arguments are the same as `set-language-info'." (let (lang-slot key-slot) (setq lang-slot (assoc lang-env language-info-alist)) (if (null lang-slot) ; If no slot for the language, add it. @@ -1196,9 +1203,11 @@ (define-key-after setup-map (vector (intern lang-env)) (cons lang-env 'setup-specified-language-environment) t) - (while alist - (set-language-info lang-env (car (car alist)) (cdr (car alist))) - (setq alist (cdr alist))))) + (dolist (elt alist) + (set-language-info-internal lang-env (car elt) (cdr elt))) + + (if (equal lang-env current-language-environment) + (set-language-environment lang-env)))) (defun read-language-name (key prompt &optional default) "Read a language environment name which has information for KEY. @@ -1789,7 +1798,9 @@ (defun set-display-table-and-terminal-coding-system (language-name &optional coding-system display) "Set up the display table and terminal coding system for LANGUAGE-NAME." (let ((coding (get-language-info language-name 'unibyte-display))) - (if coding + (if (and coding + (or (not coding-system) + (coding-system-equal coding coding-system))) (standard-display-european-internal) ;; The following 2 lines undo the 8-bit display that we set up ;; in standard-display-european-internal, which see. This is in @@ -2129,7 +2140,7 @@ ;; That's actually what the GNU locales define, modulo things like ;; en_IN -- fx. ("en_IN" "English" utf-8) ; glibc uses utf-8 for English in India - ("en" . "Latin-1") ; English + ("en" "English" iso-8859-1) ; English ("eo" . "Latin-3") ; Esperanto ("es" "Spanish" iso-8859-1) ("et" . "Latin-1") ; Estonian
--- a/lisp/log-view.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/log-view.el Sat Dec 10 21:18:28 2005 +0000 @@ -196,9 +196,9 @@ (defun log-view-diff (beg end) "Get the diff for several revisions. -If the point is the same as the mark, get the diff for this revision. -Otherwise, get the diff between the revisions -were the region starts and ends." +If the point is the same as the mark or the mark is not active, +get the diff for this revision. Otherwise, get the diff between +the revisions where the region starts and ends." (interactive (list (if mark-active (region-beginning) (point)) (if mark-active (region-end) (point))))
--- a/lisp/mail/sendmail.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/mail/sendmail.el Sat Dec 10 21:18:28 2005 +0000 @@ -49,8 +49,8 @@ :version "22.1") ;;;###autoload -(defcustom mail-from-style 'angles "\ -*Specifies how \"From:\" fields look. +(defcustom mail-from-style 'angles + "Specifies how \"From:\" fields look. If `nil', they contain just the return address like: king@grassland.com @@ -72,7 +72,7 @@ ;;;###autoload (defcustom mail-specify-envelope-from nil - "*If non-nil, specify the envelope-from address when sending mail. + "If non-nil, specify the envelope-from address when sending mail. The value used to specify it is whatever is found in the variable `mail-envelope-from', with `user-mail-address' as fallback. @@ -85,7 +85,7 @@ :group 'sendmail) (defcustom mail-envelope-from nil - "*If non-nil, designate the envelope-from address when sending mail. + "If non-nil, designate the envelope-from address when sending mail. This only has an effect if `mail-specify-envelope-from' is non-nil. The value should be either a string, or the symbol `header' (in which case the contents of the \"From\" header of the message @@ -98,29 +98,34 @@ :group 'sendmail) ;;;###autoload -(defcustom mail-self-blind nil "\ -*Non-nil means insert BCC to self in messages to be sent. +(defcustom mail-self-blind nil + "Non-nil means insert BCC to self in messages to be sent. This is done when the message is initialized, so you can remove or alter the BCC field to override the default." :type 'boolean :group 'sendmail) ;;;###autoload -(defcustom mail-interactive nil "\ -*Non-nil means when sending a message wait for and display errors. +(defcustom mail-interactive nil + "Non-nil means when sending a message wait for and display errors. nil means let mailer mail back a message to report errors." :type 'boolean :group 'sendmail) -;;;###autoload -(defcustom mail-yank-ignored-headers "^via:\\|^mail-from:\\|^origin:\\|^status:\\|^remailed\\|^received:\\|^message-id:\\|^summary-line:\\|^to:\\|^subject:\\|^in-reply-to:\\|^return-path:\\|^mail-reply-to:\\|^mail-followup-to:" "\ -*Delete these headers from old message when it's inserted in a reply." +(defcustom mail-yank-ignored-headers + (concat "^" + (regexp-opt '("via" "mail-from" "origin" "status" "remailed" + "received" "message-id" "summary-line" "to" "subject" + "in-reply-to" "return-path" "mail-reply-to" + "mail-followup-to") "\\(?:") + ":") + "Delete these headers from old message when it's inserted in a reply." :type 'regexp :group 'sendmail) ;; Useful to set in site-init.el ;;;###autoload -(defcustom send-mail-function +(defcustom send-mail-function (if (and window-system (memq system-type '(darwin windows-nt))) 'mailclient-send-it 'sendmail-send-it) @@ -138,30 +143,30 @@ :group 'sendmail) ;;;###autoload -(defcustom mail-header-separator "--text follows this line--" "\ -*Line used to separate headers from text in messages being composed." +(defcustom mail-header-separator "--text follows this line--" + "Line used to separate headers from text in messages being composed." :type 'string :group 'sendmail) ;; Set up mail-header-separator for use as a category text property. (put 'mail-header-separator 'rear-nonsticky '(category)) -;;; This was a nice idea, for preventing accidental modification of -;;; the separator. But I found it also prevented or obstructed -;;; certain deliberate operations, such as copying the separator line -;;; up to the top to send myself a copy of an already sent outgoing message -;;; and other things. So I turned it off. --rms. -;;;(put 'mail-header-separator 'read-only t) +;; This was a nice idea, for preventing accidental modification of +;; the separator. But I found it also prevented or obstructed +;; certain deliberate operations, such as copying the separator line +;; up to the top to send myself a copy of an already sent outgoing message +;; and other things. So I turned it off. --rms. +;;(put 'mail-header-separator 'read-only t) ;;;###autoload -(defcustom mail-archive-file-name nil "\ -*Name of file to write all outgoing messages in, or nil for none. +(defcustom mail-archive-file-name nil + "Name of file to write all outgoing messages in, or nil for none. This can be an inbox file or an Rmail file." :type '(choice file (const nil)) :group 'sendmail) ;;;###autoload (defcustom mail-default-reply-to nil - "*Address to insert as default Reply-to field of outgoing messages. + "Address to insert as default Reply-to field of outgoing messages. If nil, it will be initialized from the REPLYTO environment variable when you first send mail." :type '(choice (const nil) string) @@ -169,7 +174,7 @@ ;;;###autoload (defcustom mail-alias-file nil - "*If non-nil, the name of a file to use instead of `/usr/lib/aliases'. + "If non-nil, the name of a file to use instead of `/usr/lib/aliases'. This file defines aliases to be expanded by the mailer; this is a different feature from that of defining aliases in `.mailrc' to be expanded in Emacs. This variable has no effect unless your system uses sendmail as its mailer." @@ -178,7 +183,7 @@ ;;;###autoload (defcustom mail-personal-alias-file "~/.mailrc" - "*If non-nil, the name of the user's personal mail alias file. + "If non-nil, the name of the user's personal mail alias file. This file typically should be in same format as the `.mailrc' file used by the `Mail' or `mailx' program. This file need not actually exist." @@ -207,14 +212,14 @@ ;;;###autoload (defcustom mail-yank-prefix nil - "*Prefix insert on lines of yanked message being replied to. + "Prefix insert on lines of yanked message being replied to. nil means use indentation." :type '(choice (const nil) string) :group 'sendmail) ;;;###autoload (defcustom mail-indentation-spaces 3 - "*Number of spaces to insert at the beginning of each cited line. + "Number of spaces to insert at the beginning of each cited line. Used by `mail-yank-original' via `mail-indent-citation'." :type 'integer :group 'sendmail) @@ -230,7 +235,7 @@ ;;;###autoload (defcustom mail-citation-hook nil - "*Hook for modifying a citation just inserted in the mail buffer. + "Hook for modifying a citation just inserted in the mail buffer. Each hook function can find the citation between (point) and (mark t), and should leave point and mark around the citation text as modified. The hook functions can find the header of the cited message @@ -249,7 +254,7 @@ ;;;###autoload (defcustom mail-citation-prefix-regexp "[ \t]*[-a-z0-9A-Z]*>+[ \t]*\\|[ \t]*" - "*Regular expression to match a citation prefix plus whitespace. + "Regular expression to match a citation prefix plus whitespace. It should match whatever sort of citation prefixes you want to handle, with whitespace before and after; it should also match just whitespace. The default value matches citations like `foo-bar>' plus whitespace." @@ -258,7 +263,90 @@ :version "20.3") (defvar mail-abbrevs-loaded nil) -(defvar mail-mode-map nil) +(defvar mail-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "\M-\t" 'mail-complete) + (define-key map "\C-c?" 'describe-mode) + (define-key map "\C-c\C-f\C-t" 'mail-to) + (define-key map "\C-c\C-f\C-b" 'mail-bcc) + (define-key map "\C-c\C-f\C-f" 'mail-fcc) + (define-key map "\C-c\C-f\C-c" 'mail-cc) + (define-key map "\C-c\C-f\C-s" 'mail-subject) + (define-key map "\C-c\C-f\C-r" 'mail-reply-to) + (define-key map "\C-c\C-f\C-a" 'mail-mail-reply-to) ; author + (define-key map "\C-c\C-f\C-l" 'mail-mail-followup-to) ; list + (define-key map "\C-c\C-t" 'mail-text) + (define-key map "\C-c\C-y" 'mail-yank-original) + (define-key map "\C-c\C-r" 'mail-yank-region) + (define-key map [remap split-line] 'mail-split-line) + (define-key map "\C-c\C-q" 'mail-fill-yanked-message) + (define-key map "\C-c\C-w" 'mail-signature) + (define-key map "\C-c\C-v" 'mail-sent-via) + (define-key map "\C-c\C-c" 'mail-send-and-exit) + (define-key map "\C-c\C-s" 'mail-send) + (define-key map "\C-c\C-i" 'mail-attach-file) + + (define-key map [menu-bar mail] + (cons "Mail" (make-sparse-keymap "Mail"))) + + (define-key map [menu-bar mail fill] + '("Fill Citation" . mail-fill-yanked-message)) + + (define-key map [menu-bar mail yank] + '("Cite Original" . mail-yank-original)) + + (define-key map [menu-bar mail signature] + '("Insert Signature" . mail-signature)) + + (define-key map [menu-bar mail mail-sep] + '("--")) + + (define-key map [menu-bar mail cancel] + '("Cancel" . mail-dont-send)) + + (define-key map [menu-bar mail send-stay] + '("Send, Keep Editing" . mail-send)) + + (define-key map [menu-bar mail send] + '("Send Message" . mail-send-and-exit)) + + (define-key map [menu-bar headers] + (cons "Headers" (make-sparse-keymap "Move to Header"))) + + (define-key map [menu-bar headers text] + '("Text" . mail-text)) + + (define-key map [menu-bar headers expand-aliases] + '("Expand Aliases" . expand-mail-aliases)) + + (define-key map [menu-bar headers sent-via] + '("Sent Via" . mail-sent-via)) + + (define-key map [menu-bar headers mail-reply-to] + '("Mail Reply To" . mail-mail-reply-to)) + + (define-key map [menu-bar headers mail-followup-to] + '("Mail Followup To" . mail-mail-followup-to)) + + (define-key map [menu-bar headers reply-to] + '("Reply-To" . mail-reply-to)) + + (define-key map [menu-bar headers bcc] + '("Bcc" . mail-bcc)) + + (define-key map [menu-bar headers fcc] + '("Fcc" . mail-fcc)) + + (define-key map [menu-bar headers cc] + '("Cc" . mail-cc)) + + (define-key map [menu-bar headers subject] + '("Subject" . mail-subject)) + + (define-key map [menu-bar headers to] + '("To" . mail-to)) + + map)) (autoload 'build-mail-aliases "mailalias" "Read mail aliases from user's personal aliases file and set `mail-aliases'." @@ -273,7 +361,7 @@ ;;;###autoload (defcustom mail-signature nil - "*Text inserted at end of mail buffer when a message is initialized. + "Text inserted at end of mail buffer when a message is initialized. If t, it means to insert the contents of the file `mail-signature-file'. If a string, that string is inserted. (To make a proper signature, the string should begin with \\n\\n-- \\n, @@ -289,13 +377,13 @@ ;;;###autoload (defcustom mail-signature-file "~/.signature" - "*File containing the text inserted at end of mail buffer." + "File containing the text inserted at end of mail buffer." :type 'file :group 'sendmail) ;;;###autoload (defcustom mail-default-directory "~/" - "*Directory for mail buffers. + "Directory for mail buffers. Value of `default-directory' for mail buffers. This directory is used for auto-save files of mail buffers." :type '(directory :tag "Directory") @@ -310,7 +398,7 @@ ;;;###autoload (defcustom mail-default-headers nil - "*A string containing header lines, to be inserted in outgoing messages. + "A string containing header lines, to be inserted in outgoing messages. It is inserted before you edit the message, so you can edit or delete these lines." :type '(choice (const nil) string) @@ -318,7 +406,7 @@ ;;;###autoload (defcustom mail-bury-selects-summary t - "*If non-nil, try to show RMAIL summary buffer after returning from mail. + "If non-nil, try to show RMAIL summary buffer after returning from mail. The functions \\[mail-send-on-exit] or \\[mail-dont-send] select the RMAIL summary buffer before returning, if it exists and this variable is non-nil." @@ -327,7 +415,7 @@ ;;;###autoload (defcustom mail-send-nonascii 'mime - "*Specify whether to allow sending non-ASCII characters in mail. + "Specify whether to allow sending non-ASCII characters in mail. If t, that means do allow it. nil means don't allow it. `query' means ask the user each time. `mime' means add an appropriate MIME header if none already present. @@ -338,7 +426,7 @@ :group 'sendmail) (defcustom mail-use-dsn nil - "*Ask MTA for notification of failed, delayed or successful delivery. + "Ask MTA for notification of failed, delayed or successful delivery. Note that only some MTAs (currently only recent versions of Sendmail) support Delivery Status Notification." :group 'sendmail @@ -352,15 +440,11 @@ (defvar mail-mailer-swallows-blank-line (if (and (string-match "sparc-sun-sunos\\(\\'\\|[^5]\\)" system-configuration) (file-readable-p "/etc/sendmail.cf") - (let ((buffer (get-buffer-create " *temp*"))) - (unwind-protect - (save-excursion - (set-buffer buffer) - (insert-file-contents "/etc/sendmail.cf") - (goto-char (point-min)) - (let ((case-fold-search nil)) - (re-search-forward "^OR\\>" nil t))) - (kill-buffer buffer)))) + (with-temp-buffer + (insert-file-contents "/etc/sendmail.cf") + (goto-char (point-min)) + (let ((case-fold-search nil)) + (re-search-forward "^OR\\>" nil t)))) ;; According to RFC822, "The field-name must be composed of printable ;; ASCII characters (i.e. characters that have decimal values between ;; 33 and 126, except colon)", i.e. any chars except ctl chars, @@ -632,7 +716,7 @@ (while (search-forward "," end t) (or (looking-at "[ \t]") (insert " ")))) - (fill-region-as-paragraph beg end) + (fill-region-as-paragraph beg end arg) ;; Mark all lines except the first as continuations. (goto-char beg) (forward-line 1) @@ -642,92 +726,6 @@ (move-marker end nil) t))) -;;; Set up keymap. - -(if mail-mode-map - nil - (setq mail-mode-map (make-sparse-keymap)) - (define-key mail-mode-map "\M-\t" 'mail-complete) - (define-key mail-mode-map "\C-c?" 'describe-mode) - (define-key mail-mode-map "\C-c\C-f\C-t" 'mail-to) - (define-key mail-mode-map "\C-c\C-f\C-b" 'mail-bcc) - (define-key mail-mode-map "\C-c\C-f\C-f" 'mail-fcc) - (define-key mail-mode-map "\C-c\C-f\C-c" 'mail-cc) - (define-key mail-mode-map "\C-c\C-f\C-s" 'mail-subject) - (define-key mail-mode-map "\C-c\C-f\C-r" 'mail-reply-to) - (define-key mail-mode-map "\C-c\C-f\C-a" 'mail-mail-reply-to) ; author - (define-key mail-mode-map "\C-c\C-f\C-l" 'mail-mail-followup-to) ; list - (define-key mail-mode-map "\C-c\C-t" 'mail-text) - (define-key mail-mode-map "\C-c\C-y" 'mail-yank-original) - (define-key mail-mode-map "\C-c\C-r" 'mail-yank-region) - (define-key mail-mode-map [remap split-line] 'mail-split-line) - (define-key mail-mode-map "\C-c\C-q" 'mail-fill-yanked-message) - (define-key mail-mode-map "\C-c\C-w" 'mail-signature) - (define-key mail-mode-map "\C-c\C-v" 'mail-sent-via) - (define-key mail-mode-map "\C-c\C-c" 'mail-send-and-exit) - (define-key mail-mode-map "\C-c\C-s" 'mail-send) - (define-key mail-mode-map "\C-c\C-i" 'mail-attach-file)) - -(define-key mail-mode-map [menu-bar mail] - (cons "Mail" (make-sparse-keymap "Mail"))) - -(define-key mail-mode-map [menu-bar mail fill] - '("Fill Citation" . mail-fill-yanked-message)) - -(define-key mail-mode-map [menu-bar mail yank] - '("Cite Original" . mail-yank-original)) - -(define-key mail-mode-map [menu-bar mail signature] - '("Insert Signature" . mail-signature)) - -(define-key mail-mode-map [menu-bar mail mail-sep] - '("--")) - -(define-key mail-mode-map [menu-bar mail cancel] - '("Cancel" . mail-dont-send)) - -(define-key mail-mode-map [menu-bar mail send-stay] - '("Send, Keep Editing" . mail-send)) - -(define-key mail-mode-map [menu-bar mail send] - '("Send Message" . mail-send-and-exit)) - -(define-key mail-mode-map [menu-bar headers] - (cons "Headers" (make-sparse-keymap "Move to Header"))) - -(define-key mail-mode-map [menu-bar headers text] - '("Text" . mail-text)) - -(define-key mail-mode-map [menu-bar headers expand-aliases] - '("Expand Aliases" . expand-mail-aliases)) - -(define-key mail-mode-map [menu-bar headers sent-via] - '("Sent Via" . mail-sent-via)) - -(define-key mail-mode-map [menu-bar headers mail-reply-to] - '("Mail Reply To" . mail-mail-reply-to)) - -(define-key mail-mode-map [menu-bar headers mail-followup-to] - '("Mail Followup To" . mail-mail-followup-to)) - -(define-key mail-mode-map [menu-bar headers reply-to] - '("Reply-To" . mail-reply-to)) - -(define-key mail-mode-map [menu-bar headers bcc] - '("Bcc" . mail-bcc)) - -(define-key mail-mode-map [menu-bar headers fcc] - '("Fcc" . mail-fcc)) - -(define-key mail-mode-map [menu-bar headers cc] - '("Cc" . mail-cc)) - -(define-key mail-mode-map [menu-bar headers subject] - '("Subject" . mail-subject)) - -(define-key mail-mode-map [menu-bar headers to] - '("To" . mail-to)) - ;; User-level commands for sending. (defun mail-send-and-exit (&optional arg) @@ -759,8 +757,8 @@ (let (rmail-flag summary-buffer) (and (not arg) (not (one-window-p)) - (save-excursion - (set-buffer (window-buffer (next-window (selected-window) 'not))) + (with-current-buffer + (window-buffer (next-window (selected-window) 'not)) (setq rmail-flag (eq major-mode 'rmail-mode)) (setq summary-buffer (and mail-bury-selects-summary @@ -987,8 +985,7 @@ (and mail-specify-envelope-from (or (mail-envelope-from) user-mail-address)))) (unwind-protect - (save-excursion - (set-buffer tembuf) + (with-current-buffer tembuf (erase-buffer) (unless multibyte (set-buffer-multibyte nil)) @@ -1086,8 +1083,7 @@ (setq fcc-was-found t) (mail-do-fcc delimline))) (if mail-interactive - (save-excursion - (set-buffer errbuf) + (with-current-buffer errbuf (erase-buffer)))) (goto-char (point-min)) (if (let ((case-fold-search t)) @@ -1133,8 +1129,7 @@ (or fcc-was-found (error "No recipients"))) (if mail-interactive - (save-excursion - (set-buffer errbuf) + (with-current-buffer errbuf (goto-char (point-min)) (while (re-search-forward "\n\n* *" nil t) (replace-match "; ")) @@ -1146,22 +1141,22 @@ (kill-buffer errbuf))))) (defun mail-do-fcc (header-end) + (unless (markerp header-end) + (error "Value of `header-end' must be a marker")) (let (fcc-list (rmailbuf (current-buffer)) (time (current-time)) (tembuf (generate-new-buffer " rmail output")) (case-fold-search t)) - (unless (markerp header-end) - (error "Value of `header-end' must be a marker")) (save-excursion (goto-char (point-min)) (while (re-search-forward "^FCC:[ \t]*" header-end t) - (setq fcc-list (cons (buffer-substring (point) - (progn - (end-of-line) - (skip-chars-backward " \t") - (point))) - fcc-list)) + (push (buffer-substring (point) + (progn + (end-of-line) + (skip-chars-backward " \t") + (point))) + fcc-list) (delete-region (match-beginning 0) (progn (forward-line 1) (point)))) (set-buffer tembuf) @@ -1187,8 +1182,8 @@ (while (search-forward "\nFrom " nil t) (forward-char -5) (insert ?>))) - (while fcc-list - (let* ((buffer (find-buffer-visiting (car fcc-list))) + (dolist (fcc fcc-list) + (let* ((buffer (find-buffer-visiting fcc)) (curbuf (current-buffer)) dont-write-the-file buffer-matches-file @@ -1197,8 +1192,7 @@ (forward-line 2) (point)))) (if buffer ;; File is present in a buffer => append to that buffer. - (save-excursion - (set-buffer buffer) + (with-current-buffer buffer (setq buffer-matches-file (and (not (buffer-modified-p)) (verify-visited-file-modtime buffer))) @@ -1239,40 +1233,38 @@ (or buffer-matches-file (progn (if (y-or-n-p (format "Save file %s? " - (car fcc-list))) + fcc)) (save-buffer)) (setq dont-write-the-file t)))) (if max (narrow-to-region (point-min) max)))))) ;; Append to the file directly, ;; unless we've already taken care of it. (unless dont-write-the-file - (if (and (file-exists-p (car fcc-list)) + (if (and (file-exists-p fcc) ;; Check that the file isn't empty. We don't ;; want to insert a newline at the start of an ;; empty file. - (not (zerop (nth 7 (file-attributes (car fcc-list))))) - (mail-file-babyl-p (car fcc-list))) + (not (zerop (nth 7 (file-attributes fcc)))) + (mail-file-babyl-p fcc)) ;; If the file is a Babyl file, ;; convert the message to Babyl format. (let ((coding-system-for-write (or rmail-file-coding-system 'emacs-mule))) - (save-excursion - (set-buffer (get-buffer-create " mail-temp")) + (with-current-buffer (get-buffer-create " mail-temp") (setq buffer-read-only nil) (erase-buffer) (insert "\C-l\n0, unseen,,\n*** EOOH ***\nDate: " (mail-rfc822-date) "\n") (insert-buffer-substring curbuf beg2 end) (insert "\n\C-_") - (write-region (point-min) (point-max) (car fcc-list) t) + (write-region (point-min) (point-max) fcc t) (erase-buffer))) (write-region - (1+ (point-min)) (point-max) (car fcc-list) t))) + (1+ (point-min)) (point-max) fcc t))) (and buffer (not dont-write-the-file) (with-current-buffer buffer - (set-visited-file-modtime)))) - (setq fcc-list (cdr fcc-list)))) + (set-visited-file-modtime)))))) (kill-buffer tembuf))) (defun mail-sent-via () @@ -1281,8 +1273,7 @@ (save-excursion ;; put a marker at the end of the header (let ((end (copy-marker (mail-header-end))) - (case-fold-search t) - to-line) + (case-fold-search t)) (goto-char (point-min)) ;; search for the To: lines and make Sent-via: lines from them ;; search for the next To: line @@ -1625,10 +1616,10 @@ when the message is sent, we apply FUNCTION to ARGS. This is how Rmail arranges to mark messages `answered'." (interactive "P") -;;; This is commented out because I found it was confusing in practice. -;;; It is easy enough to rename *mail* by hand with rename-buffer -;;; if you want to have multiple mail buffers. -;;; And then you can control which messages to save. --rms. +;;; This is commented out because I found it was confusing in practice. +;;; It is easy enough to rename *mail* by hand with rename-buffer +;;; if you want to have multiple mail buffers. +;;; And then you can control which messages to save. --rms. ;;; (let ((index 1) ;;; buffer) ;;; ;; If requested, look for a mail buffer that is modified and go to it. @@ -1687,7 +1678,7 @@ (mail-mode) ;; Disconnect the buffer from its visited file ;; (in case the user has actually visited a file *mail*). -; (set-visited-file-name nil) +;;; (set-visited-file-name nil) (let (initialized) (and (not (and noerase (not (eq noerase 'new)))) @@ -1855,9 +1846,9 @@ (pop-to-buffer "*mail*")) (mail noerase to subject in-reply-to cc replybuffer sendactions)) -;;; Do not add anything but external entries on this page. +;; Do not add anything but external entries on this page. (provide 'sendmail) -;;; arch-tag: 48bc1025-d993-4d31-8d81-2a29491f0626 +;; arch-tag: 48bc1025-d993-4d31-8d81-2a29491f0626 ;;; sendmail.el ends here
--- a/lisp/mail/smtpmail.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/mail/smtpmail.el Sat Dec 10 21:18:28 2005 +0000 @@ -569,7 +569,7 @@ (concat "\0" (smtpmail-cred-user cred) "\0" - (smtpmail-cred-passwd cred)))) + passwd))) (if (or (null (car (setq ret (smtpmail-read-response process)))) (not (integerp (car ret))) (not (equal (car ret) 235)))
--- a/lisp/man.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/man.el Sat Dec 10 21:18:28 2005 +0000 @@ -262,7 +262,7 @@ (defvar Man-name-regexp "[-a-zA-Z0-9_+][-a-zA-Z0-9_.:+]*" "Regular expression describing the name of a manpage (without section).") -(defvar Man-section-regexp "[0-9][a-zA-Z+]*\\|[LNln]" +(defvar Man-section-regexp "[0-9][a-zA-Z0-9+]*\\|[LNln]" "Regular expression describing a manpage section within parentheses.") (defvar Man-page-header-regexp
--- a/lisp/mh-e/ChangeLog Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/mh-e/ChangeLog Sat Dec 10 21:18:28 2005 +0000 @@ -1,3 +1,190 @@ +2005-12-04 Bill Wohler <wohler@newt.com> + + * mh-customize.el (mh-sortm-args): Sync docstrings with manual. + (mh-invisible-header-fields-internal): Add X-Bugzilla-* and + X-Virus-Scanned. + + * mh-customize.el (mh-insert-signature-hook): Rename + mh-letter-insert-signature-hook to mh-insert-signature-hook. + + * mh-comp.el (mh-insert-signature): Ditto. + + * mh-customize.el (mh-fetch-x-image-url): Change default from 'ask + to nil. Remove t option. Sync docstring with manual (closes SF + #831278). + (mh-invisible-header-fields-internal): Remove X-Image-URL so that + users can see it, look it up in the manual's index, and discover + mh-fetch-x-image-url (closes SF #831278). + + * mh-customize.el (mh-new-messages-folders): Rename from + mh-index-new-messages-folders. + (mh-ticked-messages-folders): Rename from + mh-index-ticked-messages-folders. + + * mh-index.el (mh-index-sequenced-messages) + (mh-index-new-messages): Ditto. + + * mh-comp.el (mh-forward): Went over all uses of the word "RANGE" + in the docstrings and made usage consistent. Generally speaking, + "messages in range" and "range of messages" is redundant and just + "range" can be used in most circumstances. Also ensured that + mh-interactive-range was mentioned in all interactive functions + that use a range which describes the range argument for both users + and programmers. + + * mh-e.el (mh-delete-msg-no-motion, mh-refile-msg) + (mh-refile-or-write-again, mh-rescan-folder, mh-undo) + (mh-visit-folder, mh-scan-folder, mh-regenerate-headers) + (mh-notate-user-sequences, mh-delete-msg-from-seq, mh-catchup): + Ditto. + + * mh-funcs.el (mh-copy-msg, mh-pack-folder, mh-pack-folder-1): + Ditto. + + * mh-junk.el (mh-junk-blacklist, mh-junk-whitelist): Ditto. + + * mh-print.el (mh-ps-print-range, mh-ps-print-msg) + (mh-ps-print-msg-file, mh-print-msg): Ditto. + + * mh-seq.el (mh-put-msg-in-seq, mh-range-to-msg-list) + (mh-narrow-to-range, mh-toggle-tick): Ditto. + + +2005-12-01 Bill Wohler <wohler@newt.com> + + Rewrote Reading Mail chapter in manual which affected mh-show + customization group and related functions. + + * mh-comp.el (mh-letter-mode): Use mh-highlight-citation-style + instead of mh-highlight-citation-p. + (mh-letter-toggle-header-field-display): "Ellipsed" isn't a word, + I think, so use "truncated". + + * mh-customize.el (mh-folder, mh-folder-faces): Group's manual + section is Folders, not Organizing. Parent of mh-folder-faces is + mh-folder, not mh-show. + (mh-speed): Rename to mh-speedbar for consistency with mh-toolbar. + (mh-thread): New group that corresponds with manual's Threading + chapter. + (mh-letter-faces): Group's manual section is Editing Drafts, not + Sending Mail. + (mh-sortm-args): New customization variable that used to be a + defvar. + (mh-index-new-messages-folders, mh-index-ticked-messages-folders): + Move from mh-index group to mh-folders group. + (mh-alias-local-users-prefix, mh-large-folder) + (mh-recursive-folders-flag, mh-before-quit-hook) + (mh-folder-mode-hook, mh-kill-folder-suppress-prompt-hook) + (mh-quit-hook, mh-refile-msg-hook): Move from mh-show group to + mh-folder group. + (mh-highlight-citation-style): Rename from + mh-highlight-citation-p. Sync docstrings with manual. + (mh-mhl-format-file): Rename from mhl-formfile. Sync docstrings + with manual. + (mh-show-threads-flag): Move from mh-show group to mh-thread + group. + (mh-find-path-hook): Move from mh-show group to mh-e group. + (mh-folder-updated-hook): Add to mh-folder group. + (mh-forward-hook): Move from mh-folder to mh-sending-mail group. + (mh-unseen-updated-hook): Move from mh-show to mh-sequences group. + (mh-bury-show-buffer-flag, mh-clean-message-header-flag) + (mh-decode-mime-flag, mh-display-buttons-for-alternatives-flag) + (mh-display-buttons-for-inline-parts-flag) + (mh-do-not-confirm-flag, mh-fetch-x-image-url) + (mh-graphical-smileys-flag, mh-graphical-emphasis-flag) + (mh-invisible-header-fields-default, mh-invisible-header-fields) + (mh-lpr-command-format, mh-max-inline-image-height) + (mh-max-inline-image-width) + (mh-mime-save-parts-default-directory, mh-print-background-flag) + (mh-show-maximum-size, mh-show-use-goto-addr-flag) + (mh-show-use-xface-flag, mh-store-default-directory) + (mh-summary-height, mh-delete-msg-hook + (mh-show-hook, mh-show-mode-hook): Sync docstrings with manual. + + * mh-e.el + (mh-scan-format-mh, mh-scan-good-msg-regexp) + (mh-scan-deleted-msg-regexp, mh-scan-refiled-msg-regexp) + (mh-scan-cur-msg-number-regexp, mh-scan-subject-regexp): Use + non-fontification instead of non-fontifying. + (mh-header-display): Use mh-mhl-format-file instead of + mhl-formfile. Sync docstrings with manual. + (mh-next-undeleted-msg, mh-previous-undeleted-msg): Rename arg to + count. Sync docstrings with manual. + (mh-refile-or-write-again): Use output from mh-write-msg-to-file + so that message doesn't change when using this command. Sync + docstrings with manual. + (mh-page-msg, mh-previous-page): Rename arg to lines. Sync + docstrings with manual. + (mh-write-msg-to-file): Rename msg to message. Rename no-headers + to no-header. Sync docstrings with manual. + (mh-ps-print-map): Delete keybindings for deleted commands + mh-ps-print-toggle-mime and mh-ps-print-msg-show. + (mh-help-messages): Updated printing help. + (mh-delete-msg, mh-delete-msg-no-motion, mh-first-msg) + (mh-last-msg, mh-previous-unread-msg, mh-next-button) + (mh-prev-button, mh-folder-toggle-mime-part) + (mh-folder-inline-mime-part, mh-folder-save-mime-part) + (mh-next-unread-msg, mh-toggle-mime-buttons): Sync docstrings with + manual. + + * mh-funcs.el (mh-sortm-args): Now a customization option and + in mh-customize.el. + (mh-pipe-msg): Rename include-headers to include-header. Sync + docstrings with manual. + (mh-burst-digest, mh-page-digest, mh-page-digest-backwards) + (mh-store-msg): Sync docstrings with manual. + + * mh-mime.el (mh-mime-save-parts): Rename arg to prompt. Sync + docstrings with manual. + (mh-toggle-mh-decode-mime-flag): Use English in message, not Lisp. + Sync docstrings with manual. + (mh-mm-display-part, mh-mm-inline-message): Use + mh-highlight-citation-style instead of mh-highlight-citation-p. + (mh-press-button): Sync docstrings with manual. + (mh-display-with-external-viewer): Fix default output in + minibuffer. Sync docstrings with manual. + + * mh-print.el: (mh-ps-print-mime, mh-ps-print-toggle-mime): + Deleted. + (mh-ps-print-color-option): Incorporate docstring from + ps-print-color-p. + (mh-ps-spool-buffer): Remove unused code. Fix indent. Slimline + docstring. + (mh-ps-spool-msg): Slimline docstring. Rename from + mh-ps-spool-a-msg. Rewrote to use existing show buffer when + available. + (mh-ps-print-range): Extract method from common code in + mh-ps-print-msg and mh-ps-print-msg-file. + (mh-ps-print-preprint): Clean docstring. Use filename "mh-%s". + (mh-ps-print-msg-show): Delete. Can use either + mh-ps-print-msg-show or mh-ps-print-msg-show to same effect with + new code in mh-ps-spool-msg. + (mh-print-msg): Use mh-mhl-format-file instead of mhl-formfile. + Sync docstrings with manual. + (mh-ps-print-msg, mh-ps-print-msg-file) + (mh-ps-print-toggle-faces, mh-ps-print-toggle-color): Sync + docstrings with manual. + + * mh-utils.el (mh-show-ps-print-msg-show, + mh-show-ps-print-toggle-mime): Delete. + (mh-show-ps-print-map): Updated accordingly. + (mh-show-mode): Use mh-highlight-citation-style instead of + mh-highlight-citation-p. + (mh-show-xface, mh-display-msg): Use mh-mhl-format-file instead of + mhl-formfile. + (mh-show): Use mh-mhl-format-file instead of mhl-formfile. Sync + docstrings with manual. + (mh-show-font-lock-fontify-region, mh-modify, mh-goto-msg): Sync + docstrings with manual. + +2005-12-01 Bill Wohler <wohler@newt.com> + + * mh-init.el (mh-defface-compat): Checkdoc fix. + + * mh-junk.el (mh-bogofilter-blacklist, mh-bogofilter-whitelist): + Bogofilter is lowercase except at beginning of sentence and in + titles. + 2005-11-04 Bill Wohler <wohler@newt.com> * mh-customize.el (mh-min-colors-defined-flag, mh-defface-compat):
--- a/lisp/mh-e/mh-comp.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/mh-e/mh-comp.el Sat Dec 10 21:18:28 2005 +0000 @@ -327,18 +327,15 @@ ;;;###mh-autoload (defun mh-forward (to cc &optional range) - "Forward message(s). + "Forward message. You are prompted for the TO and CC recipients. You are given a draft to edit that looks like it would if you had run the MH command \"forw\". You are given a chance to add some text. -You can forward several messages by using a RANGE. All of the messages in the -range are inserted into your draft. Check the documentation of +You can forward several messages by using a RANGE. Check the documentation of `mh-interactive-range' to see how RANGE is read in interactive use. -The default message is the current message. - See also `mh-compose-forward-as-mime-flag', `mh-forward-subject-format', and `mh-send'." (interactive (list (mh-interactive-read-address "To: ") @@ -1000,8 +997,8 @@ (mh-funcall-if-exists mh-toolbar-init :letter) (make-local-variable 'font-lock-defaults) (cond - ((or (equal mh-highlight-citation-p 'font-lock) - (equal mh-highlight-citation-p 'gnus)) + ((or (equal mh-highlight-citation-style 'font-lock) + (equal mh-highlight-citation-style 'gnus)) ;; Let's use font-lock even if gnus is used in show-mode. The reason ;; is that gnus uses static text properties which are not appropriate ;; for a buffer that will be edited. So the choice here is either fontify @@ -1146,7 +1143,7 @@ A signature separator (\"-- \") will be added if the signature block does not contain one and `mh-signature-separator-flag' is on. -The value of `mh-letter-insert-signature-hook' is a list of functions to be +The value of `mh-insert-signature-hook' is a list of functions to be called, with no arguments, after the signature is inserted. These functions may access the actual name of the file or the function used to insert the signature with `mh-signature-file-name'. @@ -1184,7 +1181,7 @@ (funcall mh-signature-file-name))))) (save-restriction (widen) - (run-hooks 'mh-letter-insert-signature-hook)) + (run-hooks 'mh-insert-signature-hook)) (goto-char (point-min)) (when (and (not (mh-file-is-vcard-p mh-signature-file-name)) mh-signature-separator-flag @@ -1950,7 +1947,7 @@ (defun mh-letter-toggle-header-field-display (arg) "Toggle display of header field at point. -Use this command to display ellipsed header fields. This command is a toggle +Use this command to display truncated header fields. This command is a toggle so entering it again will hide the field. This command takes a prefix argument ARG: if negative then the field is hidden, if positive then the field is displayed."
--- a/lisp/mh-e/mh-customize.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/mh-e/mh-customize.el Sat Dec 10 21:18:28 2005 +0000 @@ -117,7 +117,7 @@ (defgroup mh-folder nil "Organizing your mail with folders." :prefix "mh-" - :link '(custom-manual "(mh-e)Organizing") + :link '(custom-manual "(mh-e)Folders") :group 'mh-e) (defgroup mh-folder-selection nil @@ -186,12 +186,18 @@ :link '(custom-manual "(mh-e)Reading Mail") :group 'mh-e) -(defgroup mh-speed nil +(defgroup mh-speedbar nil "The speedbar." :prefix "mh-speed-" :link '(custom-manual "(mh-e)Speedbar") :group 'mh-e) +(defgroup mh-thread nil + "Threading." + :prefix "mh-thread-" + :link '(custom-manual "(mh-e)Threading") + :group 'mh-e) + (defgroup mh-toolbar nil "The toolbar" :link '(custom-manual "(mh-e)Toolbar") @@ -215,10 +221,10 @@ (defgroup mh-folder-faces nil "Faces used in scan listing." - :link '(custom-manual "(mh-e)Organizing") + :link '(custom-manual "(mh-e)Folders") :prefix "mh-" :group 'mh-faces - :group 'mh-show) + :group 'mh-folder) (defgroup mh-index-faces nil "Faces used in searching." @@ -229,7 +235,7 @@ (defgroup mh-letter-faces nil "Faces used in message drafts." - :link '(custom-manual "(mh-e)Sending Mail") + :link '(custom-manual "(mh-e)Editing Drafts") :prefix "mh-" :group 'mh-faces :group 'mh-letter) @@ -250,7 +256,7 @@ -;;; Emacs interface to the MH mail system (:group mh) +;;; Emacs interface to the MH mail system (:group mh-e) (eval-when (compile) (setq mh-variant 'none)) @@ -346,7 +352,7 @@ :group 'mh-alias) (defcustom mh-alias-local-users-prefix "local." - "*String prepended to the real names of users from the password file. + "*String prefixed to the real names of users from the password file. This option can also be set to `Use Login'. For example, consider the following password file entry: @@ -378,6 +384,41 @@ ;;; Organizing Your Mail with Folders (:group 'mh-folder) +(defcustom mh-new-messages-folders t + "Folders searched for the \"unseen\" sequence. + +Set this option to \"Inbox\" to search the \"+inbox\" folder or \"All\" to +search all of the top level folders. Otherwise, list the folders that should +be searched with the \"Choose Folders\" menu item. + +See also `mh-recursive-folders-flag'." + :type '(choice (const :tag "Inbox" t) + (const :tag "All" nil) + (repeat :tag "Choose Folders" (string :tag "Folder"))) + :group 'mh-folder) + +(defcustom mh-ticked-messages-folders t + "Folders searched for `mh-tick-seq'. + +Set this option to \"Inbox\" to search the \"+inbox\" folder or \"All\" to +search all of the top level folders. Otherwise, list the folders that should +be searched with the \"Choose Folders\" menu item. + +See also `mh-recursive-folders-flag'." + :type '(choice (const :tag "Inbox" t) + (const :tag "All" nil) + (repeat :tag "Choose Folders" (string :tag "Folder"))) + :group 'mh-folder) + +(defcustom mh-large-folder 200 + "The number of messages that indicates a large folder. +If a folder is deemed to be large, that is the number of messages in it exceed +this value, then confirmation is needed when it is visited. Even when +`mh-show-threads-flag' is non-nil, the folder is not automatically threaded, if +it is large. If set to nil all folders are treated as if they are small." + :type '(choice (const :tag "No Limit") integer) + :group 'mh-folder) + (defcustom mh-recenter-summary-flag nil "*Non-nil means to recenter the summary window. If this option is turned on, recenter the summary window when the show window @@ -385,6 +426,21 @@ :type 'boolean :group 'mh-folder) +(defcustom mh-recursive-folders-flag nil + "*Non-nil means that commands which operate on folders do so recursively." + :type 'boolean + :group 'mh-folder) + +(defcustom mh-sortm-args nil + "*Additional arguments for \"sortm\"\\<mh-folder-mode-map>. + +This option is consulted when a prefix argument is used with +\\[mh-sort-folder]. Normally default arguments to \"sortm\" are specified in +the MH profile. This option may be used to provide an alternate view. For +example, \"'(\"-nolimit\" \"-textfield\" \"subject\")\" is a useful setting." + :type 'string + :group 'mh-folder) + ;;; Folder Selection (:group 'mh-folder-selection) @@ -657,18 +713,6 @@ ;;; Searching (:group 'mh-index) -(defcustom mh-index-new-messages-folders t - "Folders searched for the \"unseen\" sequence. -Set this option to \"Inbox\" to search the \"+inbox\" folder or \"All\" to -search all of the top level folders. Otherwise, list the folders that should -be searched with the \"Choose Folders\" menu item. - -See also `mh-recursive-folders-flag'." - :group 'mh-index - :type '(choice (const :tag "Inbox" t) - (const :tag "All" nil) - (repeat :tag "Choose Folders" (string :tag "Folder")))) - (defcustom mh-index-program nil "Indexing program that MH-E shall use. The default setting of this option is `Auto-detect' which means that MH-E will @@ -687,18 +731,6 @@ (const :tag "grep" grep)) :group 'mh-index) -(defcustom mh-index-ticked-messages-folders t - "Folders searched for `mh-tick-seq'. -Set this option to \"Inbox\" to search the \"+inbox\" folder or \"All\" to -search all of the top level folders. Otherwise, list the folders that should -be searched with the \"Choose Folders\" menu item. - -See also `mh-recursive-folders-flag'." - :group 'mh-index - :type '(choice (const :tag "Inbox" t) - (const :tag "All" nil) - (repeat :tag "Choose Folders" (string :tag "Folder")))) - ;;; Dealing with Junk Mail (:group 'mh-junk) @@ -747,9 +779,9 @@ "Spam program that MH-E should use. The default setting of this option is \"Auto-detect\" which means that MH-E -will automatically choose one of SpamAssassin, Bogofilter, or SpamProbe in -that order. If, for example, you have both SpamAssassin and Bogofilter -installed and you want to use BogoFilter, then you can set this option to +will automatically choose one of SpamAssassin, bogofilter, or SpamProbe in +that order. If, for example, you have both SpamAssassin and bogofilter +installed and you want to use bogofilter, then you can set this option to \"Bogofilter\"." :type '(choice (const :tag "Auto-detect" nil) (const :tag "SpamAssassin" spamassassin) @@ -1167,98 +1199,153 @@ ;;; Reading Your Mail (:group 'mh-show) (defcustom mh-bury-show-buffer-flag t - "*Non-nil means that the displayed show buffer for a folder is buried." + "*Non-nil means show buffer is buried. + +One advantage of not burying the show buffer is that one can delete the show +buffer more easily in an electric buffer list because of its proximity to its +associated MH-Folder buffer. Try running \\[electric-buffer-list] to see what +I mean." :type 'boolean :group 'mh-show) (defcustom mh-clean-message-header-flag t "*Non-nil means remove extraneous header fields. -The header fields listed in the `mh-invisible-header-fields-default' option -are hidden, although you can check off any field that you would like to see. -Header fields that you would like to hide that aren't listed can be added to -the `mh-invisible-header-fields' option." + +See also `mh-invisible-header-fields-default' and +`mh-invisible-header-fields'." :type 'boolean :group 'mh-show) (defcustom mh-decode-mime-flag (not (not (locate-library "mm-decode"))) - "*Non-nil means that Gnus is used to show MIME attachments with Gnus." + "*Non-nil means attachments are handled\\<mh-folder-mode-map>. + +MH-E can handle attachments as well if the Gnus `mm-decode' library is +present. If so, this option will be on. Otherwise, you'll see the MIME body +parts rather than text or attachments. There isn't much point in turning off +this option; however, you can inspect it if it appears that the body parts are +not being interpreted correctly or toggle it with the command +\\[mh-toggle-mh-decode-mime-flag] to view the raw message. + +This option also controls the display of quoted-printable messages and other +graphical widgets. See the options `mh-graphical-smileys-flag' and +`mh-graphical-emphasis-flag'." :type 'boolean :group 'mh-show) (defcustom mh-display-buttons-for-alternatives-flag nil - "*Non-nil means display buttons for all MIME alternatives. -Default behavior is to display only the preferred alternative. If this -variable is non-nil, then the preferred part is shown inline and buttons -are shown for each of the other alternatives." + "*Non-nil means display buttons for all alternative attachments. + +Sometimes, a mail program will produce multiple alternatives of the attachment +in increasing degree of faithfulness to the original content. By default, only +the preferred alternative is displayed. If this option is on, then the +preferred part is shown inline and buttons are shown for each of the other +alternatives." :type 'boolean :group 'mh-show) (defcustom mh-display-buttons-for-inline-parts-flag nil - "*Non-nil means display buttons for all inline MIME parts. -If non-nil, buttons are displayed for all MIME parts. Inline parts start off -in displayed state but they can be hidden by clicking the button. If nil no -buttons are shown for inline parts." + "*Non-nil means display buttons for all inline attachments\\<mh-folder-mode-map>. + +The sender can request that attachments should be viewed inline so that they +do not really appear like an attachment at all to the reader. Most of the +time, this is desirable, so by default MH-E suppresses the buttons for inline +attachments. On the other hand, you may receive code or HTML which the sender +has added to his message as inline attachments so that you can read them in +MH-E. In this case, it is useful to see the buttons so that you know you don't +have to cut and paste the code into a file; you can simply save the +attachment. + +If you want to make the buttons visible for inline attachments, you can use +the command \\[mh-toggle-mime-buttons] to toggle the visibility of these +buttons. You can turn on these buttons permanently by turning on this option. + +MH-E cannot display all attachments inline however. It can display +text (including HTML) and images." :type 'boolean :group 'mh-show) (defcustom mh-do-not-confirm-flag nil - "*Non-nil means do not prompt for confirmation. + "*Non-nil means non-reversible commands do not prompt for confirmation. + Commands such as `mh-pack-folder' prompt to confirm whether to process -outstanding moves and deletes or not before continuing. A non-nil setting will -perform the action--which is usually desired but cannot be retracted--without -question." +outstanding moves and deletes or not before continuing. Turning on this option +means that these actions will be performed--which is usually desired but +cannot be retracted--without question." :type 'boolean :group 'mh-show) -(defcustom mh-fetch-x-image-url 'ask - "*Control fetching of `X-Image-URL:' header field image. -If set to \"Always fetch\" (t), the image is always fetched. You probably want -to avoid this setting for privacy and DOS (denial of service) reasons. For -example, fetching a URL can tip off a spammer that you've read his email. -Someone may also flood your network and fill your disk drive by sending a -torrent of messages, each specifying a unique URL to a very large file. - -If set to \"Ask before fetching\" ('ask), you are prompted before the image is -fetched. MH-E will remember your reply and will either use the already fetched -image the next time the same URL is encountered or silently skip it if you -didn't fetch it the first time. This is the default. - -If set to \"Never fetch\" (nil), images are never fetched and only displayed -if they are already present in the cache. - -The cache of images is found in the directory `.mhe-x-image-cache' within your -MH directory. To see how you can add your own face to the `From:' field, see -`mh-x-face-file'. - -This setting only has effect if `mh-show-use-xface-flag' is non-nil." - - :type '(choice (const :tag "Always fetch" t) - (const :tag "Ask before fetching" ask) - (const :tag "Never fetch" nil)) +(defcustom mh-fetch-x-image-url nil + "*Control fetching of \"X-Image-URL:\" header field image. + +Ths option controls the fetching of the \"X-Image-URL:\" header field image +with the following values: + +Ask Before Fetching + You are prompted before the image is fetched. MH-E will remember + your reply and will either use the already fetched image the next + time the same URL is encountered or silently skip it if you didn't + fetch it the first time. This is a good setting. + +Never Fetch + Images are never fetched and only displayed if they are already + present in the cache. This is the default. + +There isn't a value of \"Always Fetch\" for privacy and DOS (denial of +service) reasons. For example, fetching a URL can tip off a spammer that +you've read his email (which is why you shouldn't blindly answer yes if you've +set this option to \"Ask Before Fetching\"). Someone may also flood your +network and fill your disk drive by sending a torrent of messages, each +specifying a unique URL to a very large file. + +The cache of images is found in the directory \".mhe-x-image-cache\" within +your MH directory. You can add your own face to the \"From:\" field too. See +Info node `(mh-e)Picture'. + +This setting only has effect if the option `mh-show-use-xface-flag' is turned +on." + + :type '(choice (const :tag "Ask Before Fetching" ask) + (const :tag "Never Fetch" nil)) :group 'mh-show) (defcustom mh-graphical-smileys-flag t "*Non-nil means graphical smileys are displayed. -Non-nil means that small graphics will be used in the show buffer instead of -patterns like :-), ;-) etc. The setting only has effect if -`mh-decode-mime-flag' is non-nil." + +It is a long standing custom to inject body language using a cornucopia of +punctuation, also known as the \"smileys\". MH-E can render these as graphical +widgets if this option is turned on, which it is by default. Smileys include +patterns such as :-) and ;-). + +This option is disabled if the option `mh-decode-mime-flag' is turned off." :type 'boolean :group 'mh-show) (defcustom mh-graphical-emphasis-flag t "*Non-nil means graphical emphasis is displayed. -Non-nil means that _underline_ will be underlined, *bold* will appear in bold, -/italic/ will appear in italic etc. See `gnus-emphasis-alist' for the whole -list. The setting only has effect if `mh-decode-mime-flag' is non-nil." + +A few typesetting features are indicated in ASCII text with certain +characters. If your terminal supports it, MH-E can render these typesetting +directives naturally if this option is turned on, which it is by default. For +example, _underline_ will be underlined, *bold* will appear in bold, /italics/ +will appear in italics, and so on. See the option `gnus-emphasis-alist' for +the whole list. + +This option is disabled if the option `mh-decode-mime-flag' is turned off." :type 'boolean :group 'mh-show) -(defcustom mh-highlight-citation-p 'gnus - "How to highlight citations in show buffers. -The gnus method uses a different color for each indentation." - :type '(choice (const :tag "Use Gnus" gnus) - (const :tag "Use font-lock" font-lock) - (const :tag "Don't fontify" nil)) +(defcustom mh-highlight-citation-style 'gnus + "Style for highlighting citations. + +If the sender of the message has cited other messages in his message, then +MH-E will highlight these citations to emphasize the sender's actual response. +This option can be customized to change the highlighting style. The +\"Multicolor\" method uses a different color for each indentation while the +\"Monochrome\" method highlights all citations in red. To disable highlighting +of citations entirely, choose \"None\"." + :type '(choice (const :tag "Multicolor" gnus) + (const :tag "Monochrome" font-lock) + (const :tag "None" nil)) :group 'mh-show) ;; Keep fields alphabetized. Mention source, if known. @@ -1332,6 +1419,7 @@ "X-Authentication-Warning:" ; sendmail "X-Beenthere:" ; Mailman mailing list manager "X-Bogosity:" ; bogofilter + "X-Bugzilla-*" ; Bugzilla "X-Complaints-To:" "X-Cron-Env:" "X-DMCA" @@ -1357,7 +1445,6 @@ "X-Habeas-SWE-7:" ; Spam "X-Habeas-SWE-8:" ; Spam "X-Habeas-SWE-9:" ; Spam - "X-Image-URL:" ; URL equivalent of X-Face and Face "X-Info:" ; NTMail "X-Juno-" ; Juno "X-List-Host:" ; Unknown mailing list managers @@ -1421,6 +1508,7 @@ "X-UIDL:" "X-USANET-" ; usa.net "X-UserInfo1:" + "X-Virus-Scanned" ; amavisd-new "X-VSMLoop:" ; NTMail "X-Vms-To:" "X-WebTV-Signature:" @@ -1470,10 +1558,12 @@ (defcustom mh-invisible-header-fields-default nil "*List of hidden header fields. + The header fields listed in this option are hidden, although you can check off -any field that you would like to see. Header fields that you would like to -hide that aren't listed can be added to the `mh-invisible-header-fields' -option. +any field that you would like to see. + +Header fields that you would like to hide that aren't listed can be added to +the option `mh-invisible-header-fields'. See also `mh-clean-message-header-flag'." :type `(set ,@(mapcar (lambda (x) `(const ,x)) @@ -1485,11 +1575,14 @@ (defcustom mh-invisible-header-fields nil "*Additional header fields to hide. + Header fields that you would like to hide that aren't listed in `mh-invisible-header-fields-default' can be added to this option with a couple of caveats. Regular expressions are not allowed. Unique fields should have a `:' suffix; otherwise, the element can be used to render invisible an entire -class of fields that start with the same prefix. +class of fields that start with the same prefix. If you think a header field +should be generally ignored, report a bug (see URL +`https://sourceforge.net/tracker/?group_id=13357&atid=113357'). See also `mh-clean-message-header-flag'." @@ -1500,146 +1593,184 @@ :group 'mh-show) (defcustom mh-lpr-command-format "lpr -J '%s'" - "*Format for Unix command that prints a message. -The string should be a Unix command line, with the string '%s' where -the job's name (folder and message number) should appear. The formatted -message text is piped to this command when you type \\<mh-folder-mode-map>`\\[mh-print-msg]'." + "*Command used to print\\<mh-folder-mode-map>. + +This option contains the Unix command line which performs the actual printing +for the \\[mh-print-msg] command. The string can contain one escape, \"%s\", +which is replaced by the name of the folder and the message number and is +useful for print job names. I use \"mpage -h'%s' -b Letter -H1of -mlrtb -P\" +which produces a nice header and adds a bit of margin so the text fits within +my printer's margins. + +This options is not used by the commands \\[mh-ps-print-msg] or +\\[mh-ps-print-msg-file]." :type 'string :group 'mh-show) (defcustom mh-max-inline-image-height nil - "*Maximum inline image height if Content-Disposition is not present. -If nil, image will be displayed if its height is smaller than the height of -the window." + "*Maximum inline image height if \"Content-Disposition:\" is not present. + +Some older mail programs do not insert this needed plumbing to tell +MH-E whether to display the attachments inline or not. If this is the +case, MH-E will display these images inline if they are smaller than +the window. However, you might want to allow larger images to be +displayed inline. To do this, you can change the options +`mh-max-inline-image-width' and `mh-max-inline-image-height' from their +default value of zero to a large number. The size of your screen is a +good choice for these numbers." :type '(choice (const nil) integer) :group 'mh-show) (defcustom mh-max-inline-image-width nil - "*Maximum inline image width if Content-Disposition is not present. -If nil, image will be displayed if its width is smaller than the width of the -window." + "*Maximum inline image width if \"Content-Disposition:\" is not present. + +Some older mail programs do not insert this needed plumbing to tell +MH-E whether to display the attachments inline or not. If this is the +case, MH-E will display these images inline if they are smaller than +the window. However, you might want to allow larger images to be +displayed inline. To do this, you can change the options +`mh-max-inline-image-width' and `mh-max-inline-image-height' from their +default value of zero to a large number. The size of your screen is a +good choice for these numbers." :type '(choice (const nil) integer) :group 'mh-show) +(defcustom mh-mhl-format-file nil + "*Specifies the format file to pass to the \"mhl\" program. + +Normally MH-E takes care of displaying messages itself (rather than calling an +MH program to do the work). If you'd rather have \"mhl\" display the +message (within MH-E), change this option from its default value of \"Use +Default mhl Format (Printing Only)\". + +You can set this option to \"Use Default mhl Format\" to get the same output +as you would get if you ran \"mhl\" from the shell. + +If you have a format file that you want MH-E to use, you can set this option +to \"Specify an mhl Format File\" and enter the name of your format file. Your +format file should specify a non-zero value for \"overflowoffset\" to allow +MH-E to parse the header. Note that \"mhl\" is always used for printing and +forwarding; in this case, the value of this option is consulted if you have +specified a format file." + :type '(choice (const :tag "Use Default mhl Format (Printing Only)" nil) + (const :tag "Use Default mhl Format" t) + (file :tag "Specify an mhl Format File")) + :group 'mh-show) + (defcustom mh-mime-save-parts-default-directory t - "Default directory to use for `mh-mime-save-parts'. -If nil, prompt and set for next time the command is used during same session. -If t, prompt always" - :type '(choice (const :tag "Prompt the first time" nil) - (const :tag "Prompt always" t) + "Default directory to use for \\<mh-folder-mode-map>\\[mh-mime-save-parts]. + +The default value for this option is \"Prompt Always\" so that you are always +prompted for the directory in which to save the attachments. However, if you +usually use the same directory within a session, then you can set this option +to \"Prompt the First Time\" to avoid the prompt each time. you can make this +directory permanent by choosing \"Directory\" and entering the directory's +name." + :type '(choice (const :tag "Prompt the First Time" nil) + (const :tag "Prompt Always" t) directory) :group 'mh-show) (defcustom mh-print-background-flag nil - "*Non-nil means messages should be printed in the background. -WARNING: do not delete the messages until printing is finished; -otherwise, your output may be truncated." - :type 'boolean - :group 'mh-show) - -(defcustom mh-recursive-folders-flag nil - "*Non-nil means that commands which operate on folders do so recursively." + "*Non-nil means messages should be printed in the background\\<mh-folder-mode-map>. + +Normally messages are printed in the foreground. If this is slow on your +system, you may elect to turn off this option to print in the background. + +WARNING: If you do this, do not delete the message until it is printed or else +the output may be truncated. + +This option is not used by the commands \\[mh-ps-print-msg] or +\\[mh-ps-print-msg-file]." :type 'boolean :group 'mh-show) (defcustom mh-show-maximum-size 0 "*Maximum size of message (in bytes) to display automatically. -Provides an opportunity to skip over large messages which may be slow to load. -Use a value of 0 to display all messages automatically regardless of size." + +This option provides an opportunity to skip over large messages which may be +slow to load. The default value of 0 means that all message are shown +regardless of size." :type 'integer :group 'mh-show) -(defcustom mh-show-threads-flag nil - "Non-nil means new folders start in threaded mode. -Threading large number of messages can be time consuming. So if the flag is -non-nil then threading will be done only if the number of messages being -threaded is less than `mh-large-folder'." - :type 'boolean - :group 'mh-show) - -;; Use goto-addr if it was already loaded (which probably sets this -;; variable to t), or if this variable is otherwise set to t. (defcustom mh-show-use-goto-addr-flag (and (boundp 'goto-address-highlight-p) goto-address-highlight-p) - "*Non-nil means highlight URLs and email addresses. -The `goto-addr' module is used." + "*Non-nil means highlight URLs and email addresses\\<goto-address-highlight-keymap>. + +To send a message using the highlighted email address or to view the web page +for the highlighted URL, use the middle mouse button or +\\[goto-address-at-point]. + +See Info node `(mh-e)Sending Mail' to see how to configure Emacs to send the +message using MH-E. + +The default value of this option comes from the value of +`goto-address-highlight-p'." :type 'boolean :group 'mh-show) (defcustom mh-show-use-xface-flag (>= emacs-major-version 21) - "*Non-nil means display face images in `mh-show-mode'. - -MH-E can display the content of `Face:', `X-Face:', and `X-Image-URL:' header -fields. If any of these fields occur in the header of your message, the -sender's face will appear in the `From:' header field. If more than one of -these fields appear, then the first field found in the order `Face:', -`X-Face:', and `X-Image-URL:' will be used. Note that versions of GNU Emacs -prior to 21.1 don't support the display of inline images, so face images are -not displayed in these versions. + "*Non-nil means display face images in MH-show buffers. + +MH-E can display the content of \"Face:\", \"X-Face:\", and \"X-Image-URL:\" +header fields. If any of these fields occur in the header of your message, the +sender's face will appear in the \"From:\" header field. If more than one of +these fields appear, then the first field found in the order \"Face:\", +\"X-Face:\", and \"X-Image-URL:\" will be used. The option `mh-show-use-xface-flag' is used to turn this feature on and off. This feature will be turned on by default if your system supports it. -The first header field used, if present, is the Gnus-specific `Face:' field. -The `Face:' field appeared in GNU Emacs 21 and XEmacs. For more information, +The first header field used, if present, is the Gnus-specific \"Face:\" field. +The \"Face:\" field appeared in GNU Emacs 21 and XEmacs. For more information, see URL `http://quimby.gnus.org/circus/face/'. Next is the traditional -`X-Face:' header field. The display of this field requires the `uncompface' -program (see URL `ftp://ftp.cs.indiana.edu/pub/faces/compface/compface.tar.Z'). -Recent versions of XEmacs have internal support for `X-Face:' images. If your -version of XEmacs does not, then you'll need both `uncompface' and the x-face +\"X-Face:\" header field. The display of this field requires the +\"uncompface\" program (see URL +`ftp://ftp.cs.indiana.edu/pub/faces/compface/compface.tar.z'). Recent versions +of XEmacs have internal support for \"X-Face:\" images. If your version of +XEmacs does not, then you'll need both \"uncompface\" and the x-face package (see URL `ftp://ftp.jpl.org/pub/elisp/'). -Finally, MH-E will display images referenced by the `X-Image-URL:' header -field if neither the `Face:' nor the `X-Face:' fields are present. The display -of the images requires `wget' (see URL -`http://www.gnu.org/software/wget/wget.html'), `fetch', or `curl' to fetch the -image and the `convert' program from the ImageMagick suite (see URL +Finally, MH-E will display images referenced by the \"X-Image-URL:\" header +field if neither the \"Face:\" nor the \"X-Face:\" fields are present. The +display of the images requires \"wget\" (see URL +`http://www.gnu.org/software/wget/wget.html'), \"fetch\", or \"curl\" to fetch +the image and the \"convert\" program from the ImageMagick suite (see URL `http://www.imagemagick.org/'). Of the three header fields this is the most efficient in terms of network usage since the image doesn't need to be transmitted with every single mail. -The option `mh-fetch-x-image-url' controls the fetching of the `X-Image-URL:' -header field image." +The option `mh-fetch-x-image-url' controls the fetching of the +\"X-Image-URL:\" header field image." :type 'boolean :group 'mh-show) (defcustom mh-store-default-directory nil - "*Last directory used by \\[mh-store-msg]; default for next store. -A directory name string, or nil to use current directory." + "*Default directory for \\<mh-folder-mode-map>\\[mh-store-msg]. + +If you would like to change the initial default directory, customize this +option, change the value from `Current' to `Directory', and then enter the +name of the directory for storing the content of these messages." :type '(choice (const :tag "Current" nil) directory) :group 'mh-show) (defcustom mh-summary-height nil - "*Number of lines in MH-Folder window (including the mode line)." + "*Number of lines in MH-Folder buffer (including the mode line). + +The default value of this option is \"Automatic\" which means that the +MH-Folder buffer will maintain the same proportional size if the frame is +resized. If you'd prefer a fixed height, then choose the \"Fixed Size\" option +and enter the number of lines you'd like to see." :type '(choice (const :tag "Automatic" nil) - (integer :tag "Fixed sized")) + (integer :tag "Fixed Size")) :group 'mh-show) -(defcustom mhl-formfile nil - "*Name of format file to be used by mhl to show and print messages. -A value of t means use the default format file. -nil means don't use mhl to format messages when showing; mhl is still used, -with the default format file, to format messages when printing them. -The format used should specify a non-zero value for overflowoffset so -the message continues to conform to RFC 822 and MH-E can parse the headers." - :type '(choice (const nil) (const t) string) - :group 'mh-show) -(put 'mhl-formfile 'info-file "mh-e") - ;;; The Speedbar (:group 'mh-speed) -(defcustom mh-large-folder 200 - "The number of messages that indicates a large folder. -If a folder is deemed to be large, that is the number of messages in it exceed -this value, then confirmation is needed when it is visited. Even when -`mh-show-threads-flag' is non-nil, the folder is not automatically threaded, if -it is large. If set to nil all folders are treated as if they are small." - :type '(choice (const :tag "No limit") integer) - :group 'mh-speed) - (defcustom mh-speed-flists-interval 60 "Time between calls to flists in seconds. If 0, flists is not called repeatedly." @@ -1657,6 +1788,19 @@ +;;; Threading (:group 'mh-thread) + +(defcustom mh-show-threads-flag nil + "*Non-nil means new folders start in threaded mode. + +Threading large number of messages can be time consuming so this option is +turned off by default. If you turn this option on, then threading will be done +only if the number of messages being threaded is less than `mh-large-folder'." + :type 'boolean + :group 'mh-thread) + + + ;;; The Toolbar (:group 'mh-toolbar) (defcustom mh-tool-bar-search-function 'mh-search-folder @@ -2119,7 +2263,7 @@ See also `mh-quit-hook'." :type 'hook :group 'mh-hooks - :group 'mh-show) + :group 'mh-folder) (defcustom mh-before-send-letter-hook nil "Invoked at the beginning of the \\<mh-letter-mode-map>\\[mh-send-letter] command. @@ -2131,7 +2275,10 @@ :group 'mh-letter) (defcustom mh-delete-msg-hook nil - "Invoked after marking each message for deletion." + "Invoked after marking each message for deletion. + +For example, a past maintainer of MH-E used this once when he kept statistics +on his mail usage." :type 'hook :group 'mh-hooks :group 'mh-show) @@ -2146,13 +2293,13 @@ "Invoked by `mh-find-path' after reading the user's MH profile." :type 'hook :group 'mh-hooks - :group 'mh-show) + :group 'mh-e) (defcustom mh-folder-mode-hook nil "Invoked in `mh-folder-mode' on a new folder." :type 'hook :group 'mh-hooks - :group 'mh-show) + :group 'mh-folder) (defcustom mh-folder-updated-hook nil "Invoked when the folder actions (such as moves and deletes) are performed. @@ -2160,13 +2307,14 @@ `mh-refile-list' which can be used to see which changes are being made to current folder, `mh-current-folder'." :type 'hook - :group 'mh-hooks) + :group 'mh-hooks + :group 'mh-folder) (defcustom mh-forward-hook nil "Invoked on the forwarded letter by \\<mh-folder-mode-map>\\[mh-forward]." :type 'hook :group 'mh-hooks - :group 'mh-folder) + :group 'mh-sending-mail) (defcustom mh-inc-folder-hook nil "Invoked by \\<mh-folder-mode-map>`\\[mh-inc-folder]' after incorporating mail into a folder." @@ -2174,6 +2322,15 @@ :group 'mh-hooks :group 'mh-inc) +(defcustom mh-insert-signature-hook nil + "Invoked after signature has been inserted. + +These functions may access the actual name of the file or the function used to +insert the signature with `mh-signature-file-name'." + :type 'hook + :group 'mh-hooks + :group 'mh-letter) + (defcustom mh-kill-folder-suppress-prompt-hook '(mh-index-p) "Invoked at the beginning of the \\<mh-folder-mode-map>`\\[mh-kill-folder]' command. This hook is a list of functions to be called, with no arguments, which should @@ -2189,15 +2346,7 @@ in the +inbox buffer, you will not be happy." :type 'hook :group 'mh-hooks - :group 'mh-show) - -(defcustom mh-letter-insert-signature-hook nil - "Invoked after signature has been inserted. -This hook may access the actual name of the file or the function used to -insert the signature with `mh-signature-file-name'." - :type 'hook - :group 'mh-hooks - :group 'mh-letter) + :group 'mh-folder) (defcustom mh-letter-mode-hook nil "Invoked by `mh-letter-mode' on a new letter." @@ -2216,22 +2365,28 @@ See also `mh-before-quit-hook'." :type 'hook :group 'mh-hooks - :group 'mh-show) + :group 'mh-folder) (defcustom mh-refile-msg-hook nil "Invoked after marking each message for refiling." :type 'hook :group 'mh-hooks - :group 'mh-show) + :group 'mh-folder) (defcustom mh-show-hook nil - "Invoked after \\<mh-folder-mode-map>`\\[mh-show]' shows a message." + "Invoked after \\<mh-folder-mode-map>\\[mh-show] shows a message. + +It is the last thing called after messages are displayed. It's used to affect +the behavior of MH-E in general or when `mh-show-mode-hook' is too early." :type 'hook :group 'mh-hooks :group 'mh-show) (defcustom mh-show-mode-hook nil - "Invoked upon entry to `mh-show-mode'." + "Invoked upon entry to `mh-show-mode'. + +This hook is called early on in the process of the message display. It is +usually used to perform some action on the message's content." :type 'hook :group 'mh-hooks :group 'mh-show) @@ -2242,7 +2397,7 @@ will be removed from the unseen sequence." :type 'hook :group 'mh-hooks - :group 'mh-show) + :group 'mh-sequences)
--- a/lisp/mh-e/mh-e.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/mh-e/mh-e.el Sat Dec 10 21:18:28 2005 +0000 @@ -132,7 +132,7 @@ "%<(zero)%17(friendly{from})%> " "%{subject}%<{body}<<%{body}%>") "*Scan format string for MH. -This string is passed to the scan program via the -format arg. +This string is passed to the scan program via the -format argument. This format is identical to the default except that additional hints for fontification have been added to the fifth column (remember that in Emacs, the first column is 0). @@ -186,7 +186,7 @@ parenthesized expression which matches the message number as in the default of \"^\\\\( *[0-9]+\\\\)[^D^0-9]\". This expression includes the leading space within the parenthesis since it looks better to highlight it as well. This -regular expression should be correct as it is needed by non-fontifying +regular expression should be correct as it is needed by non-fontification functions.") (defvar mh-scan-deleted-msg-regexp "^\\( *[0-9]+\\)D" @@ -196,8 +196,8 @@ parenthesized expression which matches the message number as in the default of \"^\\\\( *[0-9]+\\\\)D\". This expression includes the leading space within the parenthesis since it looks better to highlight it as well. This regular -expression should be correct as it is needed by non-fontifying functions. See -also `mh-note-deleted'.") +expression should be correct as it is needed by non-fontification functions. +See also `mh-note-deleted'.") (defvar mh-scan-refiled-msg-regexp "^\\( *[0-9]+\\)\\^" "This regular expression matches refiled messages. @@ -206,7 +206,7 @@ parenthesized expression which matches the message number as in the default of \"^\\\\( *[0-9]+\\\\)\\\\^\". This expression includes the leading space within the parenthesis since it looks better to highlight it as well. This -regular expression should be correct as it is needed by non-fontifying +regular expression should be correct as it is needed by non-fontification functions. See also `mh-note-refiled'.") (defvar mh-scan-valid-regexp "^ *[0-9]" @@ -222,7 +222,7 @@ \"^\\\\( *[0-9]+\\\\+\\\\).*\". This expression includes the leading space and current message marker \"+\" within the parenthesis since it looks better to highlight these items as well. This regular expression should be correct as it -is needed by non-fontifying functions. See also `mh-note-cur'.") +is needed by non-fontification functions. See also `mh-note-cur'.") (defvar mh-scan-date-regexp "\\([0-9][0-9]/[0-9][0-9]\\)" "This regular expression matches a valid date. @@ -262,7 +262,7 @@ ^ *[0-9]+........[ ]*................... \\\\([Rr][Ee]\\\\(\\\\\\=[[0-9]+\\\\]\\\\)?:\\\\s-*\\\\)* \\\\([^<\\n]*\\\\) -This regular expression should be correct as it is needed by non-fontifying +This regular expression should be correct as it is needed by non-fontification functions.") (defvar mh-scan-format-regexp @@ -535,8 +535,15 @@ ;;; User executable MH-E commands: (defun mh-delete-msg (range) - "Mark the specified RANGE for subsequent deletion and move to the next. -Default is the displayed message. + "Delete message\\<mh-folder-mode-map>. + +To mark a message for deletion, use this command. A \"D\" is placed by the +message in the scan window, and the next undeleted message is displayed. If +the previous command had been \\[mh-previous-undeleted-msg], then the next +message displayed is the first undeleted message previous to the message just +deleted. Use \\[mh-next-undeleted-msg] to force subsequent \\[mh-delete-msg] +commands to move forward to the next undeleted message after deleting the +message under the cursor. Check the documentation of `mh-interactive-range' to see how RANGE is read in interactive use." @@ -545,7 +552,10 @@ (if (looking-at mh-scan-deleted-msg-regexp) (mh-next-msg))) (defun mh-delete-msg-no-motion (range) - "Mark the specified RANGE for subsequent deletion. + "Delete RANGE, don't move to next message. + +This command marks the RANGE for deletion but leaves the cursor at the current +message in case you wish to perform other operations on the message. Check the documentation of `mh-interactive-range' to see how RANGE is read in interactive use." @@ -564,24 +574,22 @@ t) ; return t for write-file-functions (defun mh-first-msg () - "Move to the first message." + "Display first message." (interactive) (goto-char (point-min)) (while (and (not (eobp)) (not (looking-at mh-scan-valid-regexp))) (forward-line 1))) (defun mh-header-display () - "Show the current message with all its headers. -Displays headers that might have been suppressed by setting the -variables `mh-clean-message-header-flag' or `mhl-formfile', or by the fallback -behavior of scrolling uninteresting headers off the top of the window. -Type \"\\[mh-show]\" to show the message normally again." + "Display message with all header fields\\<mh-folder-mode-map>. + +Use the command \\[mh-show] to show the message normally again." (interactive) (and (not mh-showing-with-headers) - (or mhl-formfile mh-clean-message-header-flag) + (or mh-mhl-format-file mh-clean-message-header-flag) (mh-invalidate-show-buffer)) (let ((mh-decode-mime-flag nil) - (mhl-formfile nil) + (mh-mhl-format-file nil) (mh-clean-message-header-flag nil)) (mh-show-msg nil) (mh-in-show-buffer (mh-show-buffer) @@ -630,21 +638,26 @@ (run-hooks 'mh-inc-folder-hook))) (defun mh-last-msg () - "Move to the last message." + "Display last message." (interactive) (goto-char (point-max)) (while (and (not (bobp)) (not (looking-at mh-scan-valid-regexp))) (forward-line -1)) (mh-recenter nil)) -(defun mh-next-undeleted-msg (&optional arg wait-after-complaining-flag) - "Move to the next undeleted message ARG in window. -If optional argument WAIT-AFTER-COMPLAINING-FLAG is non-nil and we are at the -last undeleted message then pause for a second after printing message." +(defun mh-next-undeleted-msg (&optional count wait-after-complaining-flag) + "Display next message. + +This command can be given a prefix argument COUNT to specify how many unread +messages to skip. + +In a program, pause for a second after printing message if we are at the last +undeleted message and optional argument WAIT-AFTER-COMPLAINING-FLAG is +non-nil." (interactive "p") (setq mh-next-direction 'forward) (forward-line 1) - (cond ((re-search-forward mh-scan-good-msg-regexp nil t arg) + (cond ((re-search-forward mh-scan-good-msg-regexp nil t count) (beginning-of-line) (mh-maybe-show)) (t (forward-line -1) @@ -730,14 +743,20 @@ t)) (defun mh-refile-msg (range folder &optional dont-update-last-destination-flag) - "Refile RANGE into FOLDER. + "Refile (output) RANGE into FOLDER. + +You are prompted for the folder name. Note that this command can also be used +to create folders. If you specify a folder that does not exist, you will be +prompted to create it. + +The hook `mh-refile-msg-hook' is called after a message is marked to be +refiled. Check the documentation of `mh-interactive-range' to see how RANGE is read in interactive use. -If optional argument DONT-UPDATE-LAST-DESTINATION-FLAG is non-nil then the -variables `mh-last-destination' and `mh-last-destination-folder' are not -updated." +If DONT-UPDATE-LAST-DESTINATION-FLAG is non-nil, then the variables +`mh-last-destination' and `mh-last-destination-folder' are not updated." (interactive (list (mh-interactive-range "Refile") (intern (mh-prompt-for-refile-folder)))) (unless dont-update-last-destination-flag @@ -748,24 +767,27 @@ (when (looking-at mh-scan-refiled-msg-regexp) (mh-next-msg))) (defun mh-refile-or-write-again (range &optional interactive-flag) - "Re-execute the last refile or write command on the given RANGE. -Default is the displayed message. Use the same folder or file as the previous -refile or write command. -If INTERACTIVE-FLAG is non-nil then the function was called interactively." + "Repeat last output command. + +If you are refiling several messages into the same folder, you can use this +command to repeat the last refile or write. You can use a range. + +Check the documentation of `mh-interactive-range' to see how RANGE is read in +interactive use. + +In a program, a non-nil INTERACTIVE-FLAG means that the function was called +interactively." (interactive (list (mh-interactive-range "Redo") t)) (if (null mh-last-destination) (error "No previous refile or write")) - (let (output) - (setq output - (cond ((eq (car mh-last-destination) 'refile) - (mh-refile-msg range (cdr mh-last-destination)) - (format "Destination folder: %s" (cdr mh-last-destination))) - (t - (mh-iterate-on-range msg range - (apply 'mh-write-msg-to-file msg (cdr mh-last-destination))) - (mh-next-msg interactive-flag) - (format "Destination: %s" (cdr mh-last-destination))))) - (message "%s" output))) + (cond ((eq (car mh-last-destination) 'refile) + (mh-refile-msg range (cdr mh-last-destination)) + (message "%s" (format "Destination folder: %s" + (cdr mh-last-destination)))) + (t + (mh-iterate-on-range msg range + (apply 'mh-write-msg-to-file msg (cdr mh-last-destination))) + (mh-next-msg interactive-flag)))) (defun mh-quit () "Quit the current MH-E folder. @@ -795,11 +817,12 @@ (set-window-configuration mh-previous-window-config)) (run-hooks 'mh-quit-hook)) -(defun mh-page-msg (&optional arg) - "Page the displayed message forwards. -Scrolls ARG lines or a full screen if no argument is supplied. Show buffer -first if not displayed. Show the next undeleted message if looking at the -bottom of the current message." +(defun mh-page-msg (&optional lines) + "Display next page in message. + +You can give this command a prefix argument that specifies the number of LINES +to scroll. This command will also show the next undeleted message if it is +used at the bottom of a message." (interactive "P") (if mh-showing-mode (if mh-page-to-next-msg-flag @@ -816,32 +839,40 @@ "previous" "next")) (setq mh-page-to-next-msg-flag t)) - (scroll-other-window arg))) + (scroll-other-window lines))) (mh-show))) -(defun mh-previous-page (&optional arg) - "Page the displayed message backwards. -Scrolls ARG lines or a full screen if no argument is supplied." +(defun mh-previous-page (&optional lines) + "Display next page in message. + +You can give this command a prefix argument that specifies the number of LINES +to scroll." (interactive "P") (mh-in-show-buffer (mh-show-buffer) - (scroll-down arg))) + (scroll-down lines))) + +(defun mh-previous-undeleted-msg (&optional count wait-after-complaining-flag) + "Display previous message. -(defun mh-previous-undeleted-msg (&optional arg wait-after-complaining-flag) - "Move to the previous undeleted message ARG in window. -If optional argument WAIT-AFTER-COMPLAINING-FLAG is non-nil and we are at the -first undeleted message then pause for a second after printing message." +This command can be given a prefix argument COUNT to specify how many unread +messages to skip. + +In a program, pause for a second after printing message if we are at the last +undeleted message and optional argument WAIT-AFTER-COMPLAINING-FLAG is +non-nil." (interactive "p") (setq mh-next-direction 'backward) (beginning-of-line) - (cond ((re-search-backward mh-scan-good-msg-regexp nil t arg) + (cond ((re-search-backward mh-scan-good-msg-regexp nil t count) (mh-maybe-show)) (t (message "No previous undeleted message") (if wait-after-complaining-flag (sit-for 1))))) (defun mh-previous-unread-msg (&optional count) - "Move to previous unread message. -With optional argument COUNT, COUNT-1 unread messages before current message -are skipped." + "Display previous unread message. + +This command can be given a prefix argument COUNT to specify how many unread +messages to skip." (interactive "p") (unless (> count 0) (error "The function mh-previous-unread-msg expects positive argument")) @@ -916,11 +947,13 @@ (point)))) (defun mh-next-button (&optional backward-flag) - "Go to the next MIME button. -Advance point to the next MIME button in the show buffer. If the end -of buffer is reached then the search wraps over to the start of the -buffer. With prefix argument, BACKWARD-FLAG the point will move to the -previous MIME button." + "Go to the next button. + +If the end of the buffer is reached then the search wraps over to the start of +the buffer. + +If an optional prefix argument BACKWARD-FLAG is given, the cursor will move to +the previous button." (interactive (list current-prefix-arg)) (unless mh-showing-mode (mh-show)) @@ -928,10 +961,10 @@ (mh-goto-next-button backward-flag))) (defun mh-prev-button () - "Go to the prev MIME button. -Move point to the previous MIME button in the show buffer. If the beginning -of the buffer is reached then the search wraps over to the end of the -buffer." + "Go to the previous button. + +If the beginning of the buffer is reached then the search wraps over to the +end of the buffer." (interactive) (mh-next-button t)) @@ -969,31 +1002,48 @@ (funcall action))))))) (defun mh-folder-toggle-mime-part (part-index) - "Toggle display of button. -If point in show buffer is at a button then that part is toggled. -If not at a button and PART-INDEX is non-nil point is moved to that part. -With nil PART-INDEX find the first button after point (search wraps around if -end of buffer is reached) and toggle it." + "View attachment. + +This command displays (or hides) the attachment associated with the button +under the cursor. If the cursor is not located over a button, then the cursor +first moves to the next button, wrapping to the beginning of the message if +necessary. This command has the advantage over related commands of working +from the MH-Folder buffer. + +You can also provide a numeric prefix argument PART-INDEX to view the +attachment labeled with that number. If Emacs does not know how to display the +attachment, then Emacs offers to save the attachment in a file." (interactive "P") (when (consp part-index) (setq part-index (car part-index))) (mh-folder-mime-action part-index #'mh-press-button t)) (defun mh-folder-inline-mime-part (part-index) - "Show the raw bytes of MIME part inline. -If point in show buffer is at a mime part then that part is inlined. -If not at a mime-part and PART-INDEX is non-nil point is moved to that part. -With nil PART-INDEX find the first button after point (search wraps around if -end of buffer is reached) and inline it." + "Show attachment verbatim. + +You can view the raw contents of an attachment with this command. This command +displays (or hides) the contents of the attachment associated with the button +under the cursor verbatim. If the cursor is not located over a button, then +the cursor first moves to the next button, wrapping to the beginning of the +message if necessary. + +You can also provide a numeric prefix argument PART-INDEX to view the +attachment labeled with that number." (interactive "P") (when (consp part-index) (setq part-index (car part-index))) (mh-folder-mime-action part-index #'mh-mime-inline-part nil)) (defun mh-folder-save-mime-part (part-index) - "Save MIME part. -If point in show buffer is at a mime part then that part is saved. -If not at a mime-part and PART-INDEX is non-nil point is moved to that part. -With nil PART-INDEX find the first button after point (search wraps around if -end of buffer is reached) and save it." + "Save (output) attachment. + +This command saves the attachment associated with the button under the cursor. +If the cursor is not located over a button, then the cursor first moves to the +next button, wrapping to the beginning of the message if necessary. + +You can also provide a numeric prefix argument PART-INDEX to save the +attachment labeled with that number. + +This command prompts you for a filename and suggests a specific name if it is +available." (interactive "P") (when (consp part-index) (setq part-index (car part-index))) (mh-folder-mime-action part-index #'mh-mime-save-part nil)) @@ -1009,11 +1059,19 @@ (let ((buffer-read-only nil)) (erase-buffer))) (defun mh-rescan-folder (&optional range dont-exec-pending) - "Rescan a folder after optionally processing the outstanding commands. -If optional prefix argument RANGE is provided, prompt for the range of -messages to display. Otherwise show the entire folder. -If optional argument DONT-EXEC-PENDING is non-nil then pending deletes and -refiles aren't carried out." + "Rescan folder\\<mh-folder-mode-map>. + +This command is useful to grab all messages in your \"+inbox\" after +processing your new mail for the first time. If you don't want to rescan the +entire folder, this command will accept a RANGE. Check the documentation of +`mh-interactive-range' to see how RANGE is read in interactive use. + +This command will ask if you want to process refiles or deletes first and then +either run \\[mh-execute-commands] for you or undo the pending refiles and +deletes, which are lost. + +In a program, the processing of outstanding commands is not performed if +DONT-EXEC-PENDING is non-nil." (interactive (list (if current-prefix-arg (mh-read-range "Rescan" mh-current-folder t nil t mh-interpret-number-as-range-flag) @@ -1024,10 +1082,13 @@ (cond (threaded-flag (mh-toggle-threads)) (mh-index-data (mh-index-insert-folder-headers))))) -(defun mh-write-msg-to-file (msg file no-headers) - "Append MSG to the end of a FILE. -If prefix argument NO-HEADERS is provided, write only the message body. -Otherwise send the entire message including the headers." +(defun mh-write-msg-to-file (message file no-header) + "Append MESSAGE to end of FILE\\<mh-folder-mode-map>. + +You are prompted for the filename. If the file already exists, the message is +appended to it. You can also write the message to the file without the header +by specifying a prefix argument NO-HEADER. Subsequent writes to the same file +can be made with the command \\[mh-refile-or-write-again]." (interactive (list (mh-get-msg-num t) (let ((default-dir (if (eq 'write (car mh-last-destination-write)) @@ -1041,16 +1102,16 @@ (car (cdr mh-last-destination-write)) (expand-file-name "mail.out" default-dir)))) current-prefix-arg)) - (let ((msg-file-to-output (mh-msg-filename msg)) + (let ((msg-file-to-output (mh-msg-filename message)) (output-file (mh-expand-file-name file))) - (setq mh-last-destination (list 'write file (if no-headers 'no-headers)) + (setq mh-last-destination (list 'write file (if no-header 'no-header)) mh-last-destination-write mh-last-destination) (save-excursion (set-buffer (get-buffer-create mh-temp-buffer)) (erase-buffer) (insert-file-contents msg-file-to-output) (goto-char (point-min)) - (if no-headers (search-forward "\n\n")) + (if no-header (search-forward "\n\n")) (append-to-file (point) (point-max) output-file)))) (defun mh-toggle-showing () @@ -1061,7 +1122,12 @@ (mh-show))) (defun mh-undo (range) - "Undo the pending deletion or refile of the specified RANGE. + "Undo pending deletes or refiles in RANGE. + +If you've deleted a message or refiled it, but changed your mind, you can +cancel the action before you've executed it. Use this command to undo a refile +on or deletion of a single message. You can also undo refiles and deletes for +messages that are found in a given RANGE. Check the documentation of `mh-interactive-range' to see how RANGE is read in interactive use." @@ -1206,17 +1272,29 @@ (mh-folder-size-folder folder))) (defun mh-visit-folder (folder &optional range index-data) - "Visit FOLDER and display RANGE of messages. -Do not call this function from outside MH-E; see \\[mh-rmail] instead. + "Visit FOLDER. + +When you want to read the messages that you have refiled into folders, use +this command to visit the folder. You are prompted for the folder name. -If RANGE is nil (the default if it is omitted when called non-interactively), -then all messages in FOLDER are displayed. +The folder buffer will show just unseen messages if there are any; otherwise, +it will show all the messages in the buffer as long there are fewer than +`mh-large-folder' messages. If there are more, then you are prompted for a +range of messages to scan. -If an index buffer is being created then INDEX-DATA is used to initialize the -index buffer specific data structures. +You can provide a prefix argument in order to specify a RANGE of messages to +show when you visit the folder. In this case, regions are not used to specify +the range and `mh-large-folder' is ignored. Check the documentation of +`mh-interactive-range' to see how RANGE is read in interactive use. -A prefix argument will cause a prompt for the RANGE of messages -regardless of the size of the `mh-large-folder' variable." +Note that this command can also be used to create folders. If you specify a +folder that does not exist, you will be prompted to create it. + +Do not call this function from outside MH-E; use \\[mh-rmail] instead. + +If, in a program, RANGE is nil (the default), then all messages in FOLDER are +displayed. If an index buffer is being created then INDEX-DATA is used to +initialize the index buffer specific data structures." (interactive (let ((folder-name (mh-prompt-for-folder "Visit" mh-inbox t))) (list folder-name (mh-read-range "Scan" folder-name t nil @@ -1346,8 +1424,10 @@ (mh-previous-undeleted-msg 1 wait-after-complaining-flag))) (defun mh-next-unread-msg (&optional count) - "Move to next unread message. -With optional argument COUNT, COUNT-1 unread messages are skipped." + "Display next unread message. + +This command can be given a prefix argument COUNT to specify how many unread +messages to skip." (interactive "p") (unless (> count 0) (error "The function mh-next-unread-msg expects positive argument")) @@ -1577,7 +1657,7 @@ `<num>:+N' `<num>:-N' Up to N messages beginning with (or ending with) message num. Num may be - any of the pre-defined symbols: first, prev, cur, next or last. + any of the predefined symbols: first, prev, cur, next or last. `first:N' `prev:N' @@ -1668,7 +1748,7 @@ (turn-on-font-lock))) ; Force font-lock in XEmacs. (defun mh-toggle-mime-buttons () - "Toggle display of buttons for inline MIME parts." + "Toggle option `mh-display-buttons-for-inline-parts-flag'." (interactive) (setq mh-display-buttons-for-inline-parts-flag (not mh-display-buttons-for-inline-parts-flag)) @@ -1712,10 +1792,15 @@ '(mh-folder-mode . mh-restore-desktop-buffer))) (defun mh-scan-folder (folder range &optional dont-exec-pending) - "Scan the FOLDER over the RANGE. -If the optional argument DONT-EXEC-PENDING is non-nil then pending deletes and -refiles aren't carried out. -Return in the folder's buffer." + "Scan FOLDER over RANGE. + +After the scan is performed, switch to the buffer associated with FOLDER. + +Check the documentation of `mh-interactive-range' to see how RANGE is read in +interactive use. + +The processing of outstanding commands is not performed if DONT-EXEC-PENDING +is non-nil." (when (stringp range) (setq range (delete "" (split-string range "[ \t\n]")))) (cond ((null (get-buffer folder)) @@ -1754,7 +1839,7 @@ (setq mh-cmd-note column)) (defun mh-regenerate-headers (range &optional update) - "Scan folder over range RANGE. + "Scan folder over RANGE. If UPDATE, append the scan lines, otherwise replace." (let ((folder mh-current-folder) (range (if (and range (atom range)) (list range) range)) @@ -2281,9 +2366,10 @@ msgs)) (defun mh-notate-user-sequences (&optional range) - "Mark user-defined sequences in the messages specified by RANGE. -The optional argument RANGE can be a message number, a list of message -numbers, a sequence, a region in a cons cell. If nil all messages are notated." + "Mark user-defined sequences in RANGE. + +Check the documentation of `mh-interactive-range' to see how RANGE is read in +interactive use; if nil all messages are notated." (unless range (setq range (cons (point-min) (point-max)))) (let ((seqs mh-seq-list) @@ -2316,8 +2402,7 @@ Check the documentation of `mh-interactive-range' to see how RANGE is read in interactive use. -Optional third arg INTERNAL-FLAG non-nil means do not inform MH of the -change." +In a program, non-nil INTERNAL-FLAG means do not inform MH of the change." (interactive (list (mh-interactive-range "Delete") (mh-read-seq-default "Delete from" t) nil)) @@ -2343,9 +2428,9 @@ (apply #'mh-speed-flists t folders-changed))))) (defun mh-catchup (range) - "Delete RANGE from the `mh-unseen-seq' sequence. + "Delete RANGE from the \"unseen\" sequence. -Check the document of `mh-interactive-range' to see how RANGE is read in +Check the documentation of `mh-interactive-range' to see how RANGE is read in interactive use." (interactive (list (mh-interactive-range "Catchup" (cons (point-min) (point-max))))) @@ -2475,14 +2560,11 @@ (gnus-define-keys (mh-ps-print-map "P" mh-folder-mode-map) "?" mh-prefix-help - "A" mh-ps-print-toggle-mime "C" mh-ps-print-toggle-color "F" mh-ps-print-toggle-faces - "M" mh-ps-print-toggle-mime "f" mh-ps-print-msg-file "l" mh-print-msg - "p" mh-ps-print-msg - "s" mh-ps-print-msg-show) + "p" mh-ps-print-msg) (gnus-define-keys (mh-sequence-map "S" mh-folder-mode-map) "'" mh-narrow-to-tick @@ -2569,9 +2651,8 @@ (?F "[l]ist; [v]isit folder;\n" "[n]ew messages; [']ticked messages; [s]earch; [i]ndexed search;\n" "[p]ack; [S]ort; [r]escan; [k]ill") - (?P "PS [p]rint message; [l]non-PS print;\n" - "PS Print [s]how window, message to [f]ile;\n" - "Toggle printing of [M]IME parts, [C]olor, [F]aces") + (?P "[p]rint message to [f]ile; old-style [l]pr printing;\n" + "Toggle printing of [C]olors, [F]aces") (?S "[p]ut message in sequence, [n]arrow, [']narrow to ticked, [w]iden,\n" "[s]equences, [l]ist,\n" "[d]elete message from sequence, [k]ill sequence")
--- a/lisp/mh-e/mh-funcs.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/mh-e/mh-funcs.el Sat Dec 10 21:18:28 2005 +0000 @@ -1,7 +1,7 @@ ;;; mh-funcs.el --- MH-E functions not everyone will use right away ;; Copyright (C) 1993, 1995, -;; 2001, 2002, 2003, 2004 Free Software Foundation, Inc. +;; 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. ;; Author: Bill Wohler <wohler@newt.com> ;; Maintainer: Bill Wohler <wohler@newt.com> @@ -39,15 +39,6 @@ (mh-require-cl) (require 'mh-e) -;;; Customization - -(defvar mh-sortm-args nil - "Extra arguments to have \\[mh-sort-folder] pass to the \"sortm\" command. -The arguments are passed to sortm if \\[mh-sort-folder] is given a -prefix argument. Normally default arguments to sortm are specified in the -MH profile. -For example, '(\"-nolimit\" \"-textfield\" \"subject\") is a useful setting.") - ;;; Scan Line Formats (defvar mh-note-copied "C" @@ -60,9 +51,19 @@ ;;;###mh-autoload (defun mh-burst-digest () - "Burst apart the current message, which should be a digest. -The message is replaced by its table of contents and the messages from the -digest are inserted into the folder after that message." + "Break up digest into separate messages\\<mh-folder-mode-map>. + +This command uses the MH command \"burst\" to break out each message in the +digest into its own message. Using this command, you can quickly delete +unwanted messages, like this: Once the digest is split up, toggle out of +MH-Folder Show mode with \\[mh-toggle-showing] so that the scan lines fill the +screen and messages aren't displayed. Then use \\[mh-delete-msg] to quickly +delete messages that you don't want to read (based on the \"Subject:\" header +field). You can also burst the digest to reply directly to the people who +posted the messages in the digest. One problem you may encounter is that the +\"From:\" header fields are preceded with a \">\" so that your reply can't +create the \"To:\" field correctly. In this case, you must correct the \"To:\" +field yourself." (interactive) (let ((digest (mh-get-msg-num t))) (mh-process-or-undo-commands mh-current-folder) @@ -78,7 +79,14 @@ ;;;###mh-autoload (defun mh-copy-msg (range folder) - "Copy the specified RANGE to another FOLDER without deleting them. + "Copy RANGE to FOLDER\\<mh-folder-mode-map>. + +If you wish to copy a message to another folder, you can use this command +\(see the \"-link\" argument to \"refile\"). Like the command +\\[mh-refile-msg], this command prompts you for the name of the target folder +and you can specify a range. Note that unlike the command \\[mh-refile-msg], +the copy takes place immediately. The original copy remains in the current +folder. Check the documentation of `mh-interactive-range' to see how RANGE is read in interactive use." @@ -155,10 +163,16 @@ ;;;###mh-autoload (defun mh-pack-folder (range) - "Renumber the messages of a folder to be 1..n. -First, offer to execute any outstanding commands for the current folder. If -optional prefix argument provided, prompt for the RANGE of messages to display -after packing. Otherwise, show the entire folder." + "Pack folder\\<mh-folder-mode-map>. + +This command packs the folder, removing gaps from the numbering sequence. If +you don't want to rescan the entire folder afterward, this command will accept +a RANGE. Check the documentation of `mh-interactive-range' to see how RANGE is +read in interactive use. + +This command will ask if you want to process refiles or deletes first and then +either run \\[mh-execute-commands] for you or undo the pending refiles and +deletes, which are lost." (interactive (list (if current-prefix-arg (mh-read-range "Scan" mh-current-folder t nil t mh-interpret-number-as-range-flag) @@ -174,8 +188,8 @@ (defun mh-pack-folder-1 (range) "Close and pack the current folder. -Display the given RANGE of messages after packing. If RANGE is nil, show the -entire folder." + +Display RANGE after packing, or the entire folder if RANGE is nil." (mh-process-or-undo-commands mh-current-folder) (message "Packing folder...") (mh-set-folder-modified-p t) ; lock folder while packing @@ -186,10 +200,12 @@ (mh-regenerate-headers range)) ;;;###mh-autoload -(defun mh-pipe-msg (command include-headers) - "Pipe the current message through the given shell COMMAND. -If INCLUDE-HEADERS (prefix argument) is provided, send the entire message. -Otherwise just send the message's body without the headers." +(defun mh-pipe-msg (command include-header) + "Pipe message through shell command COMMAND. + +You are prompted for the Unix command through which you wish to run your +message. If you give an argument INCLUDE-HEADER to this command, the message +header is included in the text passed to the command." (interactive (list (read-string "Shell command on message: ") current-prefix-arg)) (let ((msg-file-to-pipe (mh-msg-filename (mh-get-msg-num t))) @@ -199,13 +215,13 @@ (erase-buffer) (insert-file-contents msg-file-to-pipe) (goto-char (point-min)) - (if (not include-headers) (search-forward "\n\n")) + (if (not include-header) (search-forward "\n\n")) (let ((default-directory message-directory)) (shell-command-on-region (point) (point-max) command nil))))) ;;;###mh-autoload (defun mh-page-digest () - "Advance displayed message to next digested message." + "Display next message in digest." (interactive) (mh-in-show-buffer (mh-show-buffer) ;; Go to top of screen (in case user moved point). @@ -222,7 +238,7 @@ ;;;###mh-autoload (defun mh-page-digest-backwards () - "Back up displayed message to previous digested message." + "Display previous message in digest." (interactive) (mh-in-show-buffer (mh-show-buffer) ;; Go to top of screen (in case user moved point). @@ -274,10 +290,13 @@ ;;;###mh-autoload (defun mh-store-msg (directory) - "Store the file(s) contained in the current message into DIRECTORY. -The message can contain a shar file or uuencoded file. -Default directory is the last directory used, or initially the value of -`mh-store-default-directory' or the current directory." + "Unpack message created with `uudecode' or `shar'. + +The default DIRECTORY for extraction is the current directory; however, you +have a chance to specify a different extraction directory. The next time you +use this command, the default directory is the last directory you used. If you +would like to change the initial default directory, customize the option +`mh-store-default-directory'." (interactive (list (let ((udir (or mh-store-default-directory default-directory))) (read-file-name "Store message in directory: "
--- a/lisp/mh-e/mh-index.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/mh-e/mh-index.el Sat Dec 10 21:18:28 2005 +0000 @@ -1287,12 +1287,12 @@ (defun mh-index-sequenced-messages (folders sequence) "Display messages from FOLDERS in SEQUENCE. All messages in the sequence you provide from the folders in -`mh-index-new-messages-folders' are listed. With a prefix argument, enter a +`mh-new-messages-folders' are listed. With a prefix argument, enter a space-separated list of folders, or nothing to search all folders." (interactive (list (if current-prefix-arg - (split-string (read-string "Search folder(s): [all] ")) - mh-index-new-messages-folders) + (split-string (read-string "Search folder(s) (default all): ")) + mh-new-messages-folders) (mh-read-seq-default "Search" nil))) (unless sequence (setq sequence mh-unseen-seq)) (let* ((mh-flists-search-folders folders) @@ -1330,27 +1330,33 @@ ;;;###mh-autoload (defun mh-index-new-messages (folders) "Display unseen messages. + If you use a program such as `procmail' to use `rcvstore' to file your incoming mail automatically, you can display new, unseen, messages using this command. All messages in the `unseen' sequence from the folders in -`mh-index-new-messages-folders' are listed. With a prefix argument, enter a -space-separated list of FOLDERS, or nothing to search all folders." +`mh-new-messages-folders' are listed. + +With a prefix argument, enter a space-separated list of FOLDERS, or nothing to +search all folders." (interactive (list (if current-prefix-arg - (split-string (read-string "Search folder(s): [all] ")) - mh-index-new-messages-folders))) + (split-string (read-string "Search folder(s) (default all): ")) + mh-new-messages-folders))) (mh-index-sequenced-messages folders mh-unseen-seq)) ;;;###mh-autoload (defun mh-index-ticked-messages (folders) "Display ticked messages. -All messages in `mh-tick-seq' from the folders in -`mh-index-ticked-messages-folders' are listed. With a prefix argument, enter a -space-separated list of FOLDERS, or nothing to search all folders." + +All messages in `mh-tick-seq' from the folders in `mh-ticked-messages-folders' +are listed. + +With a prefix argument, enter a space-separated list of FOLDERS, or nothing to +search all folders." (interactive (list (if current-prefix-arg - (split-string (read-string "Search folder(s): [all] ")) - mh-index-ticked-messages-folders))) + (split-string (read-string "Search folder(s) (default all): ")) + mh-ticked-messages-folders))) (mh-index-sequenced-messages folders mh-tick-seq))
--- a/lisp/mh-e/mh-init.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/mh-e/mh-init.el Sat Dec 10 21:18:28 2005 +0000 @@ -1,6 +1,6 @@ ;;; mh-init.el --- MH-E initialization. -;; Copyright (C) 2003, 2004 Free Software Foundation, Inc. +;; Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. ;; Author: Peter S. Galbraith <psg@debian.org> ;; Maintainer: Bill Wohler <wohler@newt.com> @@ -336,7 +336,7 @@ "Non-nil means defface supports min-colors display requirement.") (defun mh-defface-compat (spec) - "Converts SPEC for defface if necessary to run on older platforms. + "Convert SPEC for defface if necessary to run on older platforms. See `defface' for the spec definition. When `mh-min-colors-defined-flag' is nil, this function finds a display with a @@ -354,7 +354,7 @@ (when (not (eq (car entry) t)) (if (assoc 'min-colors (car entry)) (delq (assoc 'min-colors (car entry)) (car entry))))))) - + (provide 'mh-init) ;;; Local Variables:
--- a/lisp/mh-e/mh-junk.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/mh-e/mh-junk.el Sat Dec 10 21:18:28 2005 +0000 @@ -41,9 +41,12 @@ (defun mh-junk-blacklist (range) "Blacklist RANGE as spam. -This command trains the spam program in use (see the `mh-junk-program' option) -with the content of the range (see `mh-interactive-range') and then handles -the message(s) as specified by the `mh-junk-disposition' option. +This command trains the spam program in use (see the option `mh-junk-program') +with the content of RANGE and then handles the message(s) as specified by the +option `mh-junk-disposition'. + +Check the documentation of `mh-interactive-range' to see how RANGE is read in +interactive use. For more information about using your particular spam fighting program, see: @@ -77,11 +80,12 @@ (defun mh-junk-whitelist (range) "Whitelist RANGE as ham. -This command reclassifies a range of messages (see `mh-interactive-range') as -ham if it were incorrectly classified as spam. It then refiles the message -into the `+inbox' folder. +This command reclassifies the RANGE as ham if it were incorrectly classified +as spam (see the option `mh-junk-program'). It then refiles the message into +the \"+inbox\" folder. -The `mh-junk-program' option specifies the spam program in use." +Check the documentation of `mh-interactive-range' to see how RANGE is read in +interactive use." (interactive (list (mh-interactive-range "Whitelist"))) (let ((whitelist-func (nth 2 (assoc mh-junk-choice mh-junk-function-alist)))) (unless whitelist-func @@ -306,7 +310,7 @@ (defvar mh-bogofilter-executable (executable-find "bogofilter")) (defun mh-bogofilter-blacklist (msg) - "Blacklist MSG with Bogofilter. + "Blacklist MSG with bogofilter. Bogofilter is a Bayesian spam filtering program. Get it from your local distribution or from http://bogofilter.sourceforge.net/. @@ -324,11 +328,11 @@ Note that most Bayesian filters need 1000 to 5000 of each type of message to start doing a good job. -To use Bogofilter, add the following recipes to `.procmailrc': +To use bogofilter, add the following recipes to `.procmailrc': MAILDIR=$HOME/`mhparam Path` - # Fight spam with Bogofilter. + # Fight spam with bogofilter. :0fw | bogofilter -3 -e -p @@ -340,9 +344,9 @@ * ^X-Bogosity: Unsure, tests=bogofilter spam/unsure/. -If Bogofilter classifies a message incorrectly, or is unsure, you can use the +If bogofilter classifies a message incorrectly, or is unsure, you can use the MH-E commands \\[mh-junk-blacklist] and \\[mh-junk-whitelist] to update -Bogofilter's training. +bogofilter's training. The \"Bogofilter FAQ\" suggests that you run the following occasionally to shrink the database: @@ -359,7 +363,7 @@ nil "-s"))) (defun mh-bogofilter-whitelist (msg) - "Whitelist MSG with Bogofilter. + "Whitelist MSG with bogofilter. See `mh-bogofilter-blacklist' for more information." (unless mh-bogofilter-executable
--- a/lisp/mh-e/mh-mime.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/mh-e/mh-mime.el Sat Dec 10 21:18:28 2005 +0000 @@ -799,11 +799,15 @@ Set from last use.") ;;;###mh-autoload -(defun mh-mime-save-parts (arg) - "Store the MIME parts of the current message. -If ARG, prompt for directory, else use that specified by the variable -`mh-mime-save-parts-default-directory'. These directories may be superseded by -MH profile components, since this function calls on mhstore to do the work." +(defun mh-mime-save-parts (prompt) + "Save attachments. + +You can save all of the attachments at once with this command. The attachments +are saved in the directory specified by the option +`mh-mime-save-parts-default-directory' unless you use a prefix argument PROMPT +in which case you are prompted for the directory. These directories may be +superseded by MH profile components, since this function calls on +\"mhstore\" (\"mhn\") to do the work." (interactive "P") (let ((msg (if (eq major-mode 'mh-show-mode) (mh-show-buffer-message-number) @@ -814,12 +818,12 @@ (command (if (mh-variant-p 'nmh) "mhstore" "mhn")) (directory (cond - ((and (or arg + ((and (or prompt (equal nil mh-mime-save-parts-default-directory) (equal t mh-mime-save-parts-default-directory)) (not mh-mime-save-parts-directory)) (read-file-name "Store in directory: " nil nil t nil)) - ((and (or arg + ((and (or prompt (equal t mh-mime-save-parts-default-directory)) mh-mime-save-parts-directory) (read-file-name (format @@ -877,11 +881,13 @@ ;;;###mh-autoload (defun mh-toggle-mh-decode-mime-flag () - "Toggle whether MH-E should decode MIME or not." + "Toggle the value of `mh-decode-mime-flag'." (interactive) (setq mh-decode-mime-flag (not mh-decode-mime-flag)) (mh-show nil t) - (message "(setq mh-decode-mime-flag %s)" mh-decode-mime-flag)) + (message "%s" (if mh-decode-mime-flag + "Processing attachments normally" + "Displaying raw message"))) ;;;###mh-autoload (defun mh-decode-message-header () @@ -1184,7 +1190,7 @@ (goto-char (point-min)) (delete-char 1)) (when (equal (mm-handle-media-supertype handle) "text") - (when (eq mh-highlight-citation-p 'gnus) + (when (eq mh-highlight-citation-style 'gnus) (mh-gnus-article-highlight-citation)) (mh-display-smileys) (mh-display-emphasis) @@ -1205,9 +1211,10 @@ ;;;###mh-autoload (defun mh-press-button () - "Press MIME button. -If the MIME part is visible then it is removed. Otherwise the part is -displayed." + "View contents of button. + +This command is a toggle so if you use it again on the same attachment, the +attachment is hidden." (interactive) (let ((mm-inline-media-tests mh-mm-inline-media-tests) (data (get-text-property (point) 'mh-data)) @@ -1279,7 +1286,23 @@ ;;;###mh-autoload (defun mh-display-with-external-viewer (part-index) - "View MIME PART-INDEX externally." + "View attachment externally. + +If Emacs does not know how to view an attachment, you could save it into a +file and then run some program to open it. It is easier, however, to launch +the program directly from MH-E with this command. While you'll most likely use +this to view spreadsheets and documents, it is also useful to use your browser +to view HTML attachments with higher fidelity than what Emacs can provide. + +This command displays the attachment associated with the button under the +cursor. If the cursor is not located over a button, then the cursor first +moves to the next button, wrapping to the beginning of the message if +necessary. You can provide a numeric prefix argument PART-INDEX to view the +attachment labeled with that number. + +This command tries to provide a reasonable default for the viewer by calling +the Emacs function `mailcap-mime-info'. This function usually reads the file +\"/etc/mailcap\"." (interactive "P") (when (consp part-index) (setq part-index (car part-index))) (mh-folder-mime-action @@ -1290,7 +1313,9 @@ (methods (mapcar (lambda (x) (list (cdr (assoc 'viewer x)))) (mailcap-mime-info type 'all))) (def (caar methods)) - (prompt (format "Viewer: %s" (if def (format "[%s] " def) ""))) + (prompt (format "Viewer%s: " (if def + (format " (default %s)" def) + ""))) (method (completing-read prompt methods nil nil nil nil def)) (folder mh-show-folder-buffer) (buffer-read-only nil)) @@ -1464,7 +1489,7 @@ (mh-decode-message-header) (mh-show-addr) ;; The other highlighting types don't need anything special - (when (eq mh-highlight-citation-p 'gnus) + (when (eq mh-highlight-citation-style 'gnus) (mh-gnus-article-highlight-citation)) (goto-char (point-min)) (insert "\n------- Forwarded Message\n\n")
--- a/lisp/mh-e/mh-print.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/mh-e/mh-print.el Sat Dec 10 21:18:28 2005 +0000 @@ -25,13 +25,6 @@ ;; Boston, MA 02110-1301, USA. ;;; Commentary: -;; Pp Print to lpr | Default inline settings -;; Pf Print to file | Generate a postscript file -;; Ps Print show buffer | Fails if no show buffer -;; -;; PA Toggle inline/attachments -;; PC Toggle color -;; PF Toggle faces ;;; Change Log: @@ -44,125 +37,121 @@ (require 'mh-funcs) (eval-when-compile (require 'mh-seq)) -(defvar mh-ps-print-mime nil - "Control printing of MIME parts. -The three possible states are: - 1. nil to not print inline parts - 2. t to print inline parts - 3. non-zero to print inline parts and attachments") +(defvar mh-ps-print-color-option ps-print-color-p + "Specify how buffer's text color is printed. + +Valid values are: -(defvar mh-ps-print-color-option ps-print-color-p - "MH-E's version of `\\[ps-print-color-p]'.") + nil - Do not print colors. + t - Print colors. + black-white - Print colors on black/white printer. + See also `ps-black-white-faces'. + +Any other value is treated as t. This variable is initialized from +`ps-print-color-p'.") (defvar mh-ps-print-func 'ps-spool-buffer-with-faces "Function to use to spool a buffer. + Sensible choices are the functions `ps-spool-buffer' and `ps-spool-buffer-with-faces'.") -;; XXX - If buffer is already being displayed, use that buffer -;; XXX - What about showing MIME content? -;; XXX - Default print buffer is bogus (defun mh-ps-spool-buffer (buffer) - "Send BUFFER to printer queue." + "Spool BUFFER." (save-excursion (set-buffer buffer) (let ((ps-print-color-p mh-ps-print-color-option) - (ps-left-header - (list - (concat "(" - (mh-get-header-field "Subject:") ")") - (concat "(" - (mh-get-header-field "From:") ")"))) - (ps-right-header - (list - "/pagenumberstring load" - (concat "(" - (mh-get-header-field "Date:") ")")))) - (funcall mh-ps-print-func)))) + (ps-left-header + (list + (concat "(" (mh-get-header-field "Subject:") ")") + (concat "(" (mh-get-header-field "From:") ")"))) + (ps-right-header + (list + "/pagenumberstring load" + (concat "(" (mh-get-header-field "Date:") ")")))) + (funcall mh-ps-print-func)))) -(defun mh-ps-spool-a-msg (msg buffer) - "Print MSG. -First the message is decoded in BUFFER before the results are sent to the -printer." - (let ((mh-show-buffer mh-show-buffer) - (folder mh-current-folder) - ;; The following is commented out because - ;; `clean-message-header-flag' isn't used anywhere. I - ;; commented rather than deleted in case somebody had some - ;; future plans for it. --SY. - ;(clean-message-header-flag mh-clean-message-header-flag) - ) +(defun mh-ps-spool-msg (msg) + "Spool MSG." + (let* ((folder mh-current-folder) + (buffer (mh-in-show-buffer (mh-show-buffer) + (if (not (equal (mh-msg-filename msg folder) + buffer-file-name)) + (get-buffer-create mh-temp-buffer))))) (unwind-protect - (progn - (setq mh-show-buffer buffer) - (save-excursion - ;; - ;; XXX - Use setting of mh-ps-print-mime - ;; - (mh-display-msg msg folder) - (mh-ps-spool-buffer mh-show-buffer) - (kill-buffer mh-show-buffer)))))) + (save-excursion + (if buffer + (let ((mh-show-buffer buffer)) + (mh-display-msg msg folder))) + (mh-ps-spool-buffer (if buffer buffer mh-show-buffer))) + (if buffer + (kill-buffer buffer))))) + +(defun mh-ps-print-range (range file) + "Print RANGE to FILE. + +This is the function that actually does the work. +If FILE is nil, then the messages are spooled to the printer." + (mh-iterate-on-range msg range + (unwind-protect + (mh-ps-spool-msg msg)) + (mh-notate msg mh-note-printed mh-cmd-note)) + (ps-despool file)) + +(defun mh-ps-print-preprint (prefix-arg) + "Provide a better default file name for `ps-print-preprint'. +Pass along the PREFIX-ARG to it." + (let ((buffer-file-name (format "mh-%s" (substring (buffer-name) 1)))) + (ps-print-preprint prefix-arg))) ;;;###mh-autoload (defun mh-ps-print-msg (range) - "Print the messages in RANGE. - -Check the documentation of `mh-interactive-range' to see how RANGE is read in -interactive use." - (interactive (list (mh-interactive-range "Print"))) - (mh-iterate-on-range msg range - (let ((buffer (get-buffer-create mh-temp-buffer))) - (unwind-protect - (mh-ps-spool-a-msg msg buffer) - (kill-buffer buffer))) - (mh-notate nil mh-note-printed mh-cmd-note)) - (ps-despool nil)) - -(defun mh-ps-print-preprint (prefix-arg) - "Replacement for `ps-print-preprint'. -The original function does not handle the fact that MH folders are directories -nicely, when generating the default file name. This function works around -that. The function is passed the interactive PREFIX-ARG." - (let ((buffer-file-name (format "/tmp/%s" (substring (buffer-name) 1)))) - (ps-print-preprint prefix-arg))) - -;;;###mh-autoload -(defun mh-ps-print-msg-file (file range) - "Print to FILE the messages in RANGE. + "Print RANGE\\<mh-folder-mode-map>. Check the documentation of `mh-interactive-range' to see how RANGE is read in -interactive use." - (interactive (list - (mh-ps-print-preprint 1) - (mh-interactive-range "Print"))) - (mh-iterate-on-range msg range - (let ((buffer (get-buffer-create mh-temp-buffer))) - (unwind-protect - (mh-ps-spool-a-msg msg buffer) - (kill-buffer buffer))) - (mh-notate nil mh-note-printed mh-cmd-note)) - (ps-despool file)) +interactive use. + +This command will print inline text attachments but will not decrypt messages. +However, when a message is displayed in an MH-Show buffer, then that buffer is +used verbatim for printing with the caveat that only text attachments, if +opened inline, are printed. Therefore, encrypted messages can be printed by +showing and decrypting them first. + +MH-E uses the \"ps-print\" package to do the printing, so you can customize +the printing further by going to the `ps-print' customization group. This +command does not use the options `mh-lpr-command-format' or +`mh-print-background-flag'. See also the commands \\[mh-ps-print-toggle-color] +and \\[mh-ps-print-toggle-faces]." + (interactive (list (mh-interactive-range "Print"))) + (mh-ps-print-range range nil)) ;;;###mh-autoload -(defun mh-ps-print-msg-show (file) - "Print current show buffer to FILE." - (interactive (list (mh-ps-print-preprint current-prefix-arg))) - (let ((msg (mh-get-msg-num t)) - (folder mh-current-folder) - (show-buffer mh-show-buffer) - (show-window (get-buffer-window mh-show-buffer))) - (if (and show-buffer show-window) - (mh-in-show-buffer (show-buffer) - (if (equal (mh-msg-filename msg folder) buffer-file-name) - (progn - (mh-ps-spool-buffer show-buffer) - (ps-despool file)) - (message "Current message is not being shown(1)"))) - (message "Current message is not being shown(2)")))) +(defun mh-ps-print-msg-file (range file) + "Print RANGE to FILE\\<mh-folder-mode-map>. + +Check the documentation of `mh-interactive-range' to see how RANGE is read in +interactive use. + +This command will print inline text attachments but will not decrypt messages. +However, when a message is displayed in an MH-Show buffer, then that buffer is +used verbatim for printing with the caveat that only text attachments, if +opened inline, are printed. Therefore, encrypted messages can be printed by +showing and decrypting them first. + +MH-E uses the \"ps-print\" package to do the printing, so you can customize +the printing further by going to the `ps-print' customization group. This +command does not use the options `mh-lpr-command-format' or +`mh-print-background-flag'. See also the commands \\[mh-ps-print-toggle-color] +and \\[mh-ps-print-toggle-faces]." + (interactive (list (mh-interactive-range "Print") (mh-ps-print-preprint 1))) + (mh-ps-print-range range file)) ;;;###mh-autoload (defun mh-ps-print-toggle-faces () - "Toggle whether printing is done with faces or not." + "Toggle whether printing is done with faces or not. + +When faces are enabled, the printed message will look very similar to the +message in the MH-Show buffer." (interactive) (if (eq mh-ps-print-func 'ps-spool-buffer-with-faces) (progn @@ -173,7 +162,15 @@ ;;;###mh-autoload (defun mh-ps-print-toggle-color () - "Toggle whether color is used in printing messages." + "Toggle whether color is used in printing messages. + +Colors are emulated on black-and-white printers with shades of gray. This +might produce illegible output, even if your screen colors only use shades of +gray. If this is the case, try using this command to toggle between color, no +color, and a black and white representation of the colors and see which works +best. You change this setting permanently by customizing the option +`ps-print-color-p'." + (interactive) (if (eq mh-ps-print-color-option nil) (progn @@ -186,36 +183,18 @@ (setq mh-ps-print-color-option nil) (message "Colors will not be printed")))) -;;; XXX: Check option 3. Documentation doesn't sound right. -;;;###mh-autoload -(defun mh-ps-print-toggle-mime () - "Cycle through available choices on how MIME parts should be printed. -The available settings are: - 1. Print only inline MIME parts. - 2. Print all MIME parts. - 3. Print no MIME parts." - (interactive) - (if (eq mh-ps-print-mime nil) - (progn - (setq mh-ps-print-mime t) - (message "Inline parts will be printed, attachments will not be printed")) - (if (eq mh-ps-print-mime t) - (progn - (setq mh-ps-print-mime 1) - (message "Both Inline parts and attachments will be printed")) - (setq mh-ps-print-mime nil) - (message "Neither inline parts nor attachments will be printed")))) - ;;; Old non-PS based printing ;;;###mh-autoload (defun mh-print-msg (range) - "Print RANGE on printer. + "Print RANGE the old fashioned way\\<mh-folder-mode-map>. + +The message is formatted with \"mhl\" (see option `mh-mhl-format-file') and +printed with the \"lpr\" command (see option `mh-lpr-command-format'). Check the documentation of `mh-interactive-range' to see how RANGE is read in interactive use. -The variable `mh-lpr-command-format' is used to generate the print command. -The messages are formatted by mhl. See the variable `mhl-formfile'." +Consider using \\[mh-ps-print-msg] instead." (interactive (list (mh-interactive-range "Print"))) (message "Printing...") (let (msgs) @@ -247,8 +226,8 @@ (dolist (msg msgs) (let* ((mhl-command (format "%s %s %s" (expand-file-name "mhl" mh-lib-progs) - (if mhl-formfile - (format " -form %s" mhl-formfile) + (if mh-mhl-format-file + (format " -form %s" mh-mhl-format-file) "") (mh-msg-filename msg))) (lpr-command
--- a/lisp/mh-e/mh-seq.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/mh-e/mh-seq.el Sat Dec 10 21:18:28 2005 +0000 @@ -273,10 +273,16 @@ ;;;###mh-autoload (defun mh-put-msg-in-seq (range sequence) - "Add RANGE to SEQUENCE. + "Add RANGE to SEQUENCE\\<mh-folder-mode-map>. -Check the documentation of `mh-interactive-range' to see how RANGE is read in -interactive use." +To place a message in a sequence, use this command to do it manually, or use +the MH command \"pick\" or the MH-E version of \"pick\", \\[mh-search-folder], +which create a sequence automatically. + +Give this command a RANGE and you can add all the messages in a sequence to +another sequence (for example, \"\\[universal-argument] \\[mh-put-msg-in-seq] +SourceSequence RET DestSequence RET\"). Check the documentation of +`mh-interactive-range' to see how RANGE is read in interactive use." (interactive (list (mh-interactive-range "Add messages from") (mh-read-seq-default "Add to" nil))) (unless (mh-valid-seq-p sequence) @@ -661,8 +667,9 @@ ;;;###mh-autoload (defun mh-range-to-msg-list (range) "Return a list of messages for RANGE. -RANGE can be a message number, a list of message numbers, a sequence, or -a region in a cons cell." + +Check the documentation of `mh-interactive-range' to see how RANGE is read in +interactive use." (let (msg-list) (mh-iterate-on-range msg range (push msg msg-list)) @@ -915,7 +922,7 @@ ;;;###mh-autoload (defun mh-narrow-to-range (range) - "Limit to messages in RANGE. + "Limit to RANGE. Check the documentation of `mh-interactive-range' to see how RANGE is read in interactive use. @@ -1679,7 +1686,7 @@ ;;;###mh-autoload (defun mh-toggle-tick (range) - "Toggle tick mark of all messages in RANGE. + "Toggle tick mark of RANGE. This command adds messages to the \"tick\" sequence (which you can customize via the option `mh-tick-seq'). This sequence can be viewed later with the
--- a/lisp/mh-e/mh-utils.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/mh-e/mh-utils.el Sat Dec 10 21:18:28 2005 +0000 @@ -414,10 +414,11 @@ (defun mh-show-font-lock-fontify-region (beg end loudly) "Limit font-lock in `mh-show-mode' to the header. -Used when `mh-highlight-citation-p' is set to \"'gnus\", leaving the body to -be dealt with by gnus highlighting. The region between BEG and END is given -over to be fontified and LOUDLY controls if a user sees a message about the -fontification operation." + +Used when the option `mh-highlight-citation-style' is set to \"Gnus\", leaving +the body to be dealt with by Gnus highlighting. The region between BEG and END +is given over to be fontified and LOUDLY controls if a user sees a message +about the fontification operation." (let ((header-end (mh-mail-header-end))) (cond ((and (< beg header-end)(< end header-end)) @@ -874,12 +875,10 @@ (mh-defun-show-buffer mh-show-index-sequenced-messages mh-index-sequenced-messages) (mh-defun-show-buffer mh-show-catchup mh-catchup) -(mh-defun-show-buffer mh-show-ps-print-toggle-mime mh-ps-print-toggle-mime) (mh-defun-show-buffer mh-show-ps-print-toggle-color mh-ps-print-toggle-color) (mh-defun-show-buffer mh-show-ps-print-toggle-faces mh-ps-print-toggle-faces) (mh-defun-show-buffer mh-show-ps-print-msg-file mh-ps-print-msg-file) (mh-defun-show-buffer mh-show-ps-print-msg mh-ps-print-msg) -(mh-defun-show-buffer mh-show-ps-print-msg-show mh-ps-print-msg-show) (mh-defun-show-buffer mh-show-toggle-mime-buttons mh-toggle-mime-buttons) (mh-defun-show-buffer mh-show-display-with-external-viewer mh-display-with-external-viewer) @@ -962,14 +961,11 @@ (gnus-define-keys (mh-show-ps-print-map "P" mh-show-mode-map) "?" mh-prefix-help - "A" mh-show-ps-print-toggle-mime "C" mh-show-ps-print-toggle-color "F" mh-show-ps-print-toggle-faces - "M" mh-show-ps-print-toggle-mime "f" mh-show-ps-print-msg-file "l" mh-show-print-msg - "p" mh-show-ps-print-msg - "s" mh-show-ps-print-msg-show) + "p" mh-show-ps-print-msg) (gnus-define-keys (mh-show-thread-map "T" mh-show-mode-map) "?" mh-prefix-help @@ -1110,9 +1106,9 @@ (make-local-variable 'font-lock-defaults) ;;(set (make-local-variable 'font-lock-support-mode) nil) (cond - ((equal mh-highlight-citation-p 'font-lock) + ((equal mh-highlight-citation-style 'font-lock) (setq font-lock-defaults '(mh-show-font-lock-keywords-with-cite t))) - ((equal mh-highlight-citation-p 'gnus) + ((equal mh-highlight-citation-style 'gnus) (setq font-lock-defaults '((mh-show-font-lock-keywords) t nil nil nil (font-lock-fontify-region-function @@ -1258,7 +1254,7 @@ (defun mh-show-xface () "Display X-Face." (when (and window-system mh-show-use-xface-flag - (or mh-decode-mime-flag mhl-formfile + (or mh-decode-mime-flag mh-mhl-format-file mh-clean-message-header-flag)) (funcall mh-show-xface-function))) @@ -1560,24 +1556,24 @@ (if mh-showing-mode (mh-show msg))) (defun mh-show (&optional message redisplay-flag) - "Show message at cursor. -If optional argument MESSAGE is non-nil, display that message instead. -Force a two-window display with the folder window on top (size given by the -variable `mh-summary-height') and the show buffer below it. -If the message is already visible, display the start of the message. + "Display message\\<mh-folder-mode-map>. + +If the message under the cursor is already displayed, this command scrolls to +the beginning of the message. MH-E normally hides a lot of the superfluous +header fields that mailers add to a message, but if you wish to see all of +them, use the command \\[mh-header-display]. -If REDISPLAY-FLAG is non-nil, the default when called interactively, the -message is redisplayed even if the show buffer was already displaying the -correct message. +From a program, optional argument MESSAGE can be used to display an +alternative message. The optional argument REDISPLAY-FLAG forces the redisplay +of the message even if the show buffer was already displaying the correct +message. -Display of the message is controlled by setting the variables -`mh-clean-message-header-flag' and `mhl-formfile'. The default behavior is -to scroll uninteresting headers off the top of the window. -Type \"\\[mh-header-display]\" to see the message with all its headers." +See the \"mh-show\" customization group for a litany of options that control +what displayed messages look like." (interactive (list nil t)) (when (or redisplay-flag (and mh-showing-with-headers - (or mhl-formfile mh-clean-message-header-flag))) + (or mh-mhl-format-file mh-clean-message-header-flag))) (mh-invalidate-show-buffer)) (mh-show-msg message)) @@ -1639,13 +1635,14 @@ (run-hooks 'mh-show-hook))) (defun mh-modify (&optional message) - "Edit message at cursor. -If optional argument MESSAGE is non-nil, edit that message instead. -Force a two-window display with the folder window on top (size given by the -value of the variable `mh-summary-height') and the message editing buffer below -it. + "Edit message. -The message is displayed in raw form." +There are times when you need to edit a message. For example, you may need to +fix a broken Content-Type header field. You can do this with this command. It +displays the raw message in an editable buffer. When you are done editing, +save and kill the buffer as you would any other. + +From a program, edit MESSAGE instead if it is non-nil." (interactive) (let* ((message (or message (mh-get-msg-num t))) (msg-filename (mh-msg-filename message)) @@ -1700,7 +1697,7 @@ (unless (mh-buffer-data) (setf (mh-buffer-data) (mh-make-buffer-data))) ;; Bind variables in folder buffer in case they are local - (let ((formfile mhl-formfile) + (let ((formfile mh-mhl-format-file) (clean-message-header mh-clean-message-header-flag) (invisible-headers mh-invisible-header-fields-compiled) (visible-headers nil) @@ -1849,11 +1846,15 @@ (mh-thread-update-scan-line-map msg notation offset))))))) (defun mh-goto-msg (number &optional no-error-if-no-message dont-show) - "Position the cursor at message NUMBER. -Optional non-nil second argument NO-ERROR-IF-NO-MESSAGE means return nil -instead of signaling an error if message does not exist; in this case, the -cursor is positioned near where the message would have been. -Non-nil third argument DONT-SHOW means not to show the message." + "Go to a message\\<mh-folder-mode-map>. + +You can enter the message NUMBER either before or after typing +\\[mh-goto-msg]. In the latter case, Emacs prompts you. + +In a program, optional non-nil second argument NO-ERROR-IF-NO-MESSAGE means +return nil instead of signaling an error if message does not exist\; in this +case, the cursor is positioned near where the message would have been. Non-nil +third argument DONT-SHOW means not to show the message." (interactive "NGo to message: ") (setq number (prefix-numeric-value number)) (let ((point (point))
--- a/lisp/play/yow.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/play/yow.el Sat Dec 10 21:18:28 2005 +0000 @@ -102,7 +102,8 @@ (while l (princ (car l)) (setq l (cdr l)) - (and l (princ "\n\n")))))))) + (and l (princ "\n\n"))) + (print-help-return-message)))))) matches))
--- a/lisp/progmodes/cc-align.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/progmodes/cc-align.el Sat Dec 10 21:18:28 2005 +0000 @@ -45,19 +45,10 @@ (cc-require 'cc-engine) -;; Standard indentation line-ups - -;; Calling convention: +;; Standard line-up functions ;; -;; The single argument is a cons cell containing the syntactic symbol -;; in the car, and the relpos (a.k.a. anchor position) in the cdr. -;; The cdr may be nil for syntactic symbols which doesn't have an -;; associated relpos. -;; -;; Some syntactic symbols provide more information, usually more -;; interesting positions. The complete list for the syntactic element -;; (beginning with the symbol itself) is available in -;; `c-syntactic-element'. +;; See the section "Custom Indentation Functions" in the manual for +;; details on the calling convention. (defun c-lineup-topmost-intro-cont (langelem) "Line up declaration continuation lines zero or one indentation step. @@ -91,17 +82,67 @@ Works with: topmost-intro-cont." (save-excursion (beginning-of-line) - (c-backward-syntactic-ws (cdr langelem)) - (if (memq (char-before) '(?} ?,)) + (c-backward-syntactic-ws (c-langelem-pos langelem)) + (if (and (memq (char-before) '(?} ?,)) + (not (and c-overloadable-operators-regexp + (c-after-special-operator-id)))) c-basic-offset))) +(defun c-block-in-arglist-dwim (arglist-start) + ;; This function implements the DWIM to avoid far indentation of + ;; brace block constructs in arguments in `c-lineup-arglist' etc. + ;; Return non-nil if a brace block construct is detected within the + ;; arglist starting at ARGLIST-START. + + (or + ;; Check if the syntactic context contains any of the symbols for + ;; in-expression constructs. This can both save the work that we + ;; have to do below, and it also detect the brace list constructs + ;; that `c-looking-at-inexpr-block' currently misses (they are + ;; recognized by `c-inside-bracelist-p' instead). + (assq 'inexpr-class c-syntactic-context) + (assq 'inexpr-statement c-syntactic-context) + (assq 'inlambda c-syntactic-context) + + (save-restriction + ;; Search for open braces from the arglist start to the end of the + ;; line. + (narrow-to-region arglist-start (c-point 'eol arglist-start)) + + (goto-char arglist-start) + (while (and (c-syntactic-re-search-forward "{" nil t) + (progn + (backward-char) + (or + ;; Ignore starts of special brace lists. + (and c-special-brace-lists + (save-restriction + (widen) + (c-looking-at-special-brace-list))) + ;; Ignore complete blocks. + (c-safe (c-forward-sexp) t)))) + (forward-char)) + + (looking-at "{")) + + (let (containing-sexp) + (goto-char arglist-start) + ;; `c-syntactic-eol' always matches somewhere on the line. + (re-search-forward c-syntactic-eol) + (goto-char (match-beginning 0)) + (c-forward-syntactic-ws) + (setq containing-sexp (c-most-enclosing-brace (c-parse-state))) + (c-looking-at-inexpr-block + (c-safe-position (or containing-sexp (point)) c-state-cache) + containing-sexp)))) + (defun c-lineup-arglist (langelem) "Line up the current argument line under the first argument. -As a special case, if an argument on the same line as the open -parenthesis starts with a brace block opener, the indentation is -`c-basic-offset' only. This is intended as a \"DWIM\" measure in -cases like macros that contains statement blocks, e.g: +As a special case, if the indented line is inside a brace block +construct, the indentation is `c-basic-offset' only. This is intended +as a \"DWIM\" measure in cases like macros that contains statement +blocks, e.g: A_VERY_LONG_MACRO_NAME ({ some (code, with + long, lines * in[it]); @@ -115,38 +156,25 @@ Works with: arglist-cont-nonempty, arglist-close." (save-excursion - (goto-char (1+ (elt c-syntactic-element 2))) - - ;; Don't stop in the middle of a special brace list opener - ;; like "({". - (when c-special-brace-lists - (let ((special-list (c-looking-at-special-brace-list))) - (when (and special-list (< (car (car special-list)) (point))) - (goto-char (+ (car (car special-list)) 2))))) - - (let ((savepos (point)) - (eol (c-point 'eol))) + (let ((indent-pos (point))) - ;; Find out if an argument on the same line starts with an - ;; unclosed open brace paren. Note similar code in - ;; `c-lineup-close-paren' and - ;; `c-lineup-arglist-close-under-paren'. - (if (and (c-syntactic-re-search-forward "{" eol t t) - (looking-at c-syntactic-eol) - (progn (backward-char) - (not (c-looking-at-special-brace-list))) - (progn (c-backward-syntactic-ws) - (or (= (point) savepos) - (eq (char-before) ?,)))) - c-basic-offset + (if (c-block-in-arglist-dwim (c-langelem-2nd-pos c-syntactic-element)) + c-basic-offset ; DWIM case. ;; Normal case. Indent to the token after the arglist open paren. - (goto-char savepos) - (c-forward-syntactic-ws) - (when (< (point) eol) - (goto-char savepos) - (skip-chars-forward " \t")) - (vector (current-column)))))) + (goto-char (c-langelem-2nd-pos c-syntactic-element)) + (if (and c-special-brace-lists + (c-looking-at-special-brace-list)) + ;; Skip a special brace list opener like "({". + (progn (c-forward-token-2) + (forward-char)) + (forward-char)) + (let ((arglist-content-start (point))) + (c-forward-syntactic-ws) + (when (< (point) indent-pos) + (goto-char arglist-content-start) + (skip-chars-forward " \t")) + (vector (current-column))))))) ;; Contributed by Kevin Ryde <user42@zip.com.au>. (defun c-lineup-argcont (elem) @@ -172,7 +200,7 @@ ;; isn't, go back to the last position in it. We do this by ;; stepping back over open parens until we get to the open paren ;; of our argument list. - (let ((open-paren (elt c-syntactic-element 2)) + (let ((open-paren (c-langelem-2nd-pos c-syntactic-element)) (paren-state (c-parse-state))) (while (not (eq (car paren-state) open-paren)) (unless (consp (car paren-state)) ;; ignore matched braces @@ -233,51 +261,36 @@ arglist-cont-nonempty to line up all lines inside a parenthesis under the open paren. -As a special case, if a brace block is opened at the same line as the -open parenthesis of the argument list, the indentation is +As a special case, if a brace block construct starts at the same line +as the open parenthesis of the argument list, the indentation is `c-basic-offset' only. See `c-lineup-arglist' for further discussion of this \"DWIM\" measure. Works with: Almost all symbols, but are typically most useful on arglist-close, brace-list-close, arglist-cont and arglist-cont-nonempty." (save-excursion - (let (special-list paren-start savepos) - (if (memq (car langelem) '(arglist-cont-nonempty arglist-close)) - (goto-char (elt c-syntactic-element 2)) - (beginning-of-line) - (c-go-up-list-backward)) - - (if (and c-special-brace-lists - (setq special-list (c-looking-at-special-brace-list))) - ;; Don't stop in the middle of a special brace list opener - ;; like "({". - (progn - (setq paren-start (car (car special-list))) - (goto-char (+ paren-start 2))) - (setq paren-start (point)) - (forward-char 1)) + (if (memq (c-langelem-sym langelem) + '(arglist-cont-nonempty arglist-close)) + (goto-char (c-langelem-2nd-pos c-syntactic-element)) + (beginning-of-line) + (c-go-up-list-backward)) - (setq savepos (point)) - ;; Find out if an argument on the same line starts with an - ;; unclosed open brace paren. Note similar code in - ;; `c-lineup-arglist' and `c-lineup-close-paren'. - (if (and (c-syntactic-re-search-forward "{" (c-point 'eol) t t) - (looking-at c-syntactic-eol) - (progn (backward-char) - (not (c-looking-at-special-brace-list))) - (progn (c-backward-syntactic-ws) - (or (= (point) savepos) - (eq (char-before) ?,)))) - c-basic-offset + (if (save-excursion (c-block-in-arglist-dwim (point))) + c-basic-offset ; DWIM case. - ;; Normal case. Indent to the arglist open paren. - (goto-char paren-start) + ;; Normal case. Indent to the arglist open paren. + (let (special-list) + (if (and c-special-brace-lists + (setq special-list (c-looking-at-special-brace-list))) + ;; Cope if we're in the middle of a special brace list + ;; opener like "({". + (goto-char (car (car special-list)))) (vector (current-column)))))) (defun c-lineup-arglist-operators (langelem) "Line up lines starting with an infix operator under the open paren. Return nil on lines that don't start with an operator, to leave those -cases to other lineup functions. Example: +cases to other line-up functions. Example: if ( x < 10 || at_limit (x, <- c-lineup-arglist-operators @@ -285,7 +298,7 @@ ) Since this function doesn't do anything for lines without an infix -operator you typically want to use it together with some other lineup +operator you typically want to use it together with some other line-up settings, e.g. as follows \(the arglist-close setting is just a suggestion to get a consistent style): @@ -310,52 +323,48 @@ char ** int, char ** ) <-> ) <- c-lineup-close-paren -As a special case, if a brace block is opened at the same line as the -open parenthesis of the argument list, the indentation is +As a special case, if a brace block construct starts at the same line +as the open parenthesis of the argument list, the indentation is `c-basic-offset' instead of the open paren column. See `c-lineup-arglist' for further discussion of this \"DWIM\" measure. Works with: All *-close symbols." (save-excursion - (beginning-of-line) - (c-go-up-list-backward) - - (let ((spec (c-looking-at-special-brace-list)) savepos argstart) - (if spec (goto-char (car (car spec)))) - (setq savepos (point)) - (forward-char 1) - (when spec - (c-forward-syntactic-ws) - (forward-char 1)) - - (if (looking-at c-syntactic-eol) - ;; The arglist is "empty". - 0 + (if (memq (c-langelem-sym langelem) + '(arglist-cont-nonempty arglist-close)) + (goto-char (c-langelem-2nd-pos c-syntactic-element)) + (beginning-of-line) + (c-go-up-list-backward)) - ;; Find out if an argument on the same line starts with an - ;; unclosed open brace paren. Note similar code in - ;; `c-lineup-arglist' and - ;; `c-lineup-arglist-close-under-paren'. - (setq argstart (point)) - (if (and (c-syntactic-re-search-forward "{" (c-point 'eol) t t) - (looking-at c-syntactic-eol) - (progn (backward-char) - (not (c-looking-at-special-brace-list))) - (progn (c-backward-syntactic-ws) - (or (= (point) argstart) - (eq (char-before) ?,)))) - c-basic-offset + (let (special-list arglist-start) + (if (and c-special-brace-lists + (setq special-list (c-looking-at-special-brace-list))) + ;; Cope if we're in the middle of a special brace list + ;; opener like "({". + (progn + (goto-char (setq arglist-start (car (car special-list)))) + (c-forward-token-2) + (forward-char)) + (setq arglist-start (point)) + (forward-char)) - ;; Normal case. Indent to the arglist open paren. - (goto-char savepos) - (vector (current-column))))))) + (cond ((looking-at c-syntactic-eol) + 0) ; The arglist is "empty". + + ((c-block-in-arglist-dwim (point)) + c-basic-offset) ; DWIM case. + + (t + ;; Normal case. Indent to the arglist open paren. + (goto-char arglist-start) + (vector (current-column))))))) (defun c-lineup-streamop (langelem) "Line up C++ stream operators under each other. Works with: stream-op." (save-excursion - (goto-char (cdr langelem)) + (goto-char (c-langelem-pos langelem)) (re-search-forward "<<\\|>>" (c-point 'eol) 'move) (goto-char (match-beginning 0)) (vector (current-column)))) @@ -382,7 +391,8 @@ (let* ((eol (c-point 'eol)) (here (point)) (char-after-ip (char-after))) - (if (cdr langelem) (goto-char (cdr langelem))) + (if (c-langelem-pos langelem) + (goto-char (c-langelem-pos langelem))) ;; This kludge is necessary to support both inher-cont and ;; member-init-cont, since they have different anchor positions. @@ -415,7 +425,7 @@ Works with: inher-cont." (save-excursion - (goto-char (cdr langelem)) + (goto-char (c-langelem-pos langelem)) (forward-word 1) (if (looking-at "[ \t]*$") c-basic-offset @@ -439,7 +449,7 @@ (save-excursion (let* ((lim (1- (c-point 'bol))) (throws (catch 'done - (goto-char (cdr langelem)) + (goto-char (c-langelem-pos langelem)) (while (zerop (c-forward-token-2 1 t lim)) (if (looking-at "throws\\>[^_]") (throw 'done t)))))) @@ -537,13 +547,13 @@ ;; matches comment-start-skip, and choose whichever is ;; longest. (max (save-excursion - (goto-char (1+ (cdr langelem))) + (goto-char (1+ (c-langelem-pos langelem))) (if (and (match-string 0) (looking-at (regexp-quote (match-string 0)))) (- (match-end 0) (match-beginning 0)) 0)) (save-excursion - (goto-char (cdr langelem)) + (goto-char (c-langelem-pos langelem)) (looking-at comment-start-skip) (- (or (match-end 1) (save-excursion @@ -557,14 +567,20 @@ ;; a nonempty comment prefix. Treat it as free form text ;; and don't change the indentation. (vector (current-column)) - (forward-line -1) - (back-to-indentation) - (if (>= (cdr langelem) (point)) - ;; On the second line in the comment. + ;; Go back to the previous non-blank line, if any. + (while + (progn + (forward-line -1) + (back-to-indentation) + (and (> (point) (c-langelem-pos langelem)) + (looking-at "[ \t]*$")))) + ;; Is the starting line the first continuation line with content? + (if (>= (c-langelem-pos langelem) (point)) (if (zerop prefixlen) ;; No nonempty comment prefix. Align after comment ;; starter. (progn + (looking-at comment-start-skip) (goto-char (match-end 0)) ;; The following should not be necessary, since ;; comment-start-skip should match everything (i.e. @@ -580,27 +596,27 @@ ;; Javadoc style comments. (if (> starterlen prefixlen) (progn - (goto-char (cdr langelem)) + (goto-char (c-langelem-pos langelem)) (vector (1+ (current-column)))) - (goto-char (+ (cdr langelem) starterlen 1)) + (goto-char (+ (c-langelem-pos langelem) starterlen 1)) (vector (- (current-column) prefixlen)))) - ;; Not on the second line in the comment. If the previous - ;; line has a nonempty comment prefix, align with it. - ;; Otherwise, align with the previous nonempty line, but - ;; align the comment ender with the starter. + ;; We didn't start on the first non-blank continuation line. If the + ;; previous line has a nonempty comment prefix, align with it. + ;; Otherwise, align with the previous nonempty line, but align the + ;; comment ender with the starter. (when (or (not (looking-at c-current-comment-prefix)) (eq (match-beginning 0) (match-end 0))) (goto-char here) (back-to-indentation) (if (looking-at (concat "\\(" c-current-comment-prefix "\\)\\*/")) - (goto-char (cdr langelem)) + (goto-char (c-langelem-pos langelem)) (while (and (zerop (forward-line -1)) (looking-at "^[ \t]*$"))) (back-to-indentation) - (if (< (point) (cdr langelem)) + (if (< (point) (c-langelem-pos langelem)) ;; Align with the comment starter rather than ;; with the code before it. - (goto-char (cdr langelem))))) + (goto-char (c-langelem-pos langelem))))) (vector (current-column))))))) (defun c-lineup-comment (langelem) @@ -665,38 +681,39 @@ returned. This makes the function usable in list expressions. Works with: The `statement' syntactic symbol." - (if (eq (char-after (cdr langelem)) ?{) + (if (eq (char-after (c-langelem-pos langelem)) ?{) (save-excursion - (if (cdr langelem) (goto-char (cdr langelem))) + (if (c-langelem-pos langelem) + (goto-char (c-langelem-pos langelem))) (forward-char 1) (skip-chars-forward " \t") (unless (eolp) (vector (current-column)))))) -(defun c-lineup-math (langelem) - "Line up the current line after the equal sign on the first line in -the statement. If there isn't any, indent with `c-basic-offset'. If -the current line contains an equal sign too, try to align it with the -first one. +(defun c-lineup-assignments (langelem) + "Line up the current line after the assignment operator on the first +line in the statement. If there isn't any, return nil to allow +stacking with other line-up functions. If the current line contains +an assignment operator too, try to align it with the first one. Works with: topmost-intro-cont, statement-cont, arglist-cont, arglist-cont-nonempty." (let (startpos endpos equalp) - (if (eq (car langelem) 'arglist-cont-nonempty) + (if (eq (c-langelem-sym langelem) 'arglist-cont-nonempty) ;; If it's an arglist-cont-nonempty then we're only interested ;; in equal signs outside it. We don't search for a "=" on ;; the current line since that'd have a different nesting ;; compared to the one we should align with. (save-excursion (save-restriction - (setq endpos (nth 2 c-syntactic-element)) - (narrow-to-region (cdr langelem) endpos) + (setq endpos (c-langelem-2nd-pos c-syntactic-element)) + (narrow-to-region (c-langelem-pos langelem) endpos) (if (setq startpos (c-up-list-backward endpos)) (setq startpos (1+ startpos)) - (setq startpos (cdr langelem))))) + (setq startpos (c-langelem-pos langelem))))) - (setq startpos (cdr langelem) + (setq startpos (c-langelem-pos langelem) endpos (point)) ;; Find a syntactically relevant and unnested "=" token on the @@ -727,7 +744,7 @@ (eolp))) ;; There's no equal sign on the line, or there is one but ;; nothing follows it. - c-basic-offset + nil ;; calculate indentation column after equals and ws, unless ;; our line contains an equals sign @@ -739,6 +756,17 @@ (vector (- (current-column) equalp))) ))) +(defun c-lineup-math (langelem) + "Like `c-lineup-assignments' but indent with `c-basic-offset' if no +assignment operator was found on the first line. I.e. this function +is the same as specifying a list (c-lineup-assignments +). It's +provided for compatibility with old configurations. + +Works with: topmost-intro-cont, statement-cont, arglist-cont, +arglist-cont-nonempty." + (or (c-lineup-assignments langelem) + c-basic-offset)) + (defun c-lineup-cascaded-calls (langelem) "Line up \"cascaded calls\" under each other. If the line begins with \"->\" or \".\" and the preceding line ends @@ -755,8 +783,8 @@ Works with: topmost-intro-cont, statement-cont, arglist-cont, arglist-cont-nonempty." - (if (and (eq (car langelem) 'arglist-cont-nonempty) - (not (eq (nth 2 c-syntactic-element) + (if (and (eq (c-langelem-sym langelem) 'arglist-cont-nonempty) + (not (eq (c-langelem-2nd-pos c-syntactic-element) (c-most-enclosing-brace (c-parse-state))))) ;; The innermost open paren is not our one, so don't do ;; anything. This can occur for arglist-cont-nonempty with @@ -767,7 +795,7 @@ (back-to-indentation) (let ((operator (and (looking-at "->\\|\\.") (regexp-quote (match-string 0)))) - (stmt-start (cdr langelem)) col) + (stmt-start (c-langelem-pos langelem)) col) (when (and operator (looking-at operator) @@ -794,7 +822,7 @@ \"string.\"; <- c-lineup-string-cont Nil is returned in other situations, to allow stacking with other -lineup functions. +line-up functions. Works with: topmost-intro-cont, statement-cont, arglist-cont, arglist-cont-nonempty." @@ -829,18 +857,18 @@ Go to the position right after the message receiver, and if you are at the end of the line, indent the current line c-basic-offset columns from the opening bracket; otherwise you are looking at the first -character of the first method call argument, so lineup the current +character of the first method call argument, so line up the current line with it. Works with: objc-method-call-cont." (save-excursion (let* ((extra (save-excursion (back-to-indentation) - (c-backward-syntactic-ws (cdr langelem)) + (c-backward-syntactic-ws (c-langelem-pos langelem)) (if (eq (char-before) ?:) (- c-basic-offset) 0))) - (open-bracket-pos (cdr langelem)) + (open-bracket-pos (c-langelem-pos langelem)) (open-bracket-col (progn (goto-char open-bracket-pos) (current-column))) @@ -864,7 +892,7 @@ (let* ((here (c-point 'boi)) (curcol (progn (goto-char here) (current-column))) (eol (c-point 'eol)) - (relpos (cdr langelem)) + (relpos (c-langelem-pos langelem)) (first-col-column (progn (goto-char relpos) (skip-chars-forward "^:" eol) @@ -888,7 +916,7 @@ (let* ((here (c-point 'boi)) (curcol (progn (goto-char here) (current-column))) (eol (c-point 'eol)) - (relpos (cdr langelem)) + (relpos (c-langelem-pos langelem)) (prev-col-column (progn (skip-chars-backward "^:" relpos) (and (eq (char-before) ?:) @@ -927,13 +955,10 @@ containing-sexp)))))) (when res (goto-char (cdr res)) - (- (current-column) - (progn - (back-to-indentation) - (current-column))))))) + (vector (current-column)))))) (defun c-lineup-whitesmith-in-block (langelem) - "Line up lines inside a block in whitesmith style. + "Line up lines inside a block in Whitesmith style. It's done in a way that works both when the opening brace hangs and when it doesn't. E.g: @@ -946,21 +971,54 @@ In the first case the indentation is kept unchanged, in the second `c-basic-offset' is added. -Works with: defun-close, defun-block-intro, block-close, -brace-list-close, brace-list-intro, statement-block-intro and all in* +Works with: defun-close, defun-block-intro, inline-close, block-close, +brace-list-close, brace-list-intro, statement-block-intro, +arglist-intro, arglist-cont-nonempty, arglist-close, and all in* symbols, e.g. inclass and inextern-lang." (save-excursion - (+ (progn - (back-to-indentation) - (if (eq (char-syntax (char-after)) ?\() - c-basic-offset - 0)) - (progn - (goto-char (cdr langelem)) - (back-to-indentation) - (if (eq (char-syntax (char-after)) ?\() - 0 - c-basic-offset))))) + (if (and (c-go-up-list-backward) + (= (point) (c-point 'boi))) + nil + c-basic-offset))) + +(defun c-lineup-after-whitesmith-blocks (langelem) + "Compensate for Whitesmith style indentation of blocks. +Due to the way CC Mode calculates anchor positions for normal lines +inside blocks, this function is necessary for those lines to get +correct Whitesmith style indentation. Consider the following +examples: + + int foo() + { +int foo() { + { a; + a; } + x; <-> x; <- c-lineup-after-whitesmith-blocks + +The fact that the line with \"x\" is preceded by a Whitesmith style +indented block in one case and not the other should not affect its +indentation. But since CC Mode in cases like this uses the +indentation of the preceding statement as anchor position, the \"x\" +would in the rightmost case be indented too much if the offset for +`statement' was set simply to zero. + +This lineup function corrects for this situation by detecting if the +anchor position is at an open paren character. In that case, it +instead indents relative to the surrounding block just like +`c-lineup-whitesmith-in-block'. + +Works with: brace-list-entry, brace-entry-open, statement, +arglist-cont." + (save-excursion + (goto-char (c-langelem-pos langelem)) + (when (looking-at "\\s\(") + (if (c-go-up-list-backward) + (let ((pos (point))) + (back-to-indentation) + (if (= pos (point)) + (vector (current-column)) + (vector (+ (current-column) c-basic-offset)))) + (vector 0))))) (defun c-lineup-cpp-define (langelem) "Line up macro continuation lines according to the indentation of @@ -1058,9 +1116,10 @@ The \"x\" line is aligned to the text after the \":\" on the \"w\" line, and similarly \"z\" under \"y\". -This is done only in an \"asm\" or \"__asm__\" block, and only to those -lines mentioned. Anywhere else nil is returned. The usual arrangement is -to have this routine as an extra feature at the start of arglist lineups, e.g. +This is done only in an \"asm\" or \"__asm__\" block, and only to +those lines mentioned. Anywhere else nil is returned. The usual +arrangement is to have this routine as an extra feature at the start +of arglist line-ups, e.g. (c-lineup-gcc-asm-reg c-lineup-arglist) @@ -1076,7 +1135,7 @@ ;; This can occur for arglist-cont-nonempty with nested arglist ;; starts on the same line. (or (not (eq (car elem) 'arglist-cont-nonempty)) - (eq (elt c-syntactic-element 2) + (eq (c-langelem-2nd-pos c-syntactic-element) (c-most-enclosing-brace (c-parse-state)))) ;; Find the ":" to align to. Look for this first so as to quickly @@ -1117,13 +1176,24 @@ (let (langelem) (if (and (eq syntax 'block-close) (setq langelem (assq 'block-close c-syntactic-context)) - (progn (goto-char (elt langelem 1)) + (progn (goto-char (c-langelem-pos langelem)) (if (eq (char-after) ?{) (c-safe (c-forward-sexp -1))) (looking-at "\\<do\\>[^_]"))) '(before) '(before after))))) +(defun c-snug-1line-defun-close (syntax pos) + "Determine the brace hanginess for an AWK defun-close. +If the action/function being closed is a one-liner, keep it so. Otherwise put +the closing brace on its own line." + (save-excursion + (goto-char pos) + (if (> (c-point 'bol) + (progn (up-list -1) (point))) + '(before after) + '(after)))) + (defun c-gnu-impose-minimum () "Imposes a minimum indentation for lines inside code blocks. The variable `c-label-minimum-indentation' specifies the minimum
--- a/lisp/progmodes/cc-awk.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/progmodes/cc-awk.el Sat Dec 10 21:18:28 2005 +0000 @@ -1,7 +1,7 @@ ;;; cc-awk.el --- AWK specific code within cc-mode. -;; Copyright (C) 1988, 94, 96, 2000, 2001, 2002, 2003, 2004, 2005 -;; Free Software Foundation, Inc. +;; Copyright (C) 1988,94,96,2000, 2001, 2002, 2003, 2004, 2005 Free +;; Software Foundation, Inc. ;; Author: Alan Mackenzie <acm@muc.de> (originally based on awk-mode.el) ;; Maintainer: FSF @@ -20,7 +20,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the +;; along with this program; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. @@ -28,13 +28,14 @@ ;; This file contains (most of) the adaptations to cc-mode required for the ;; integration of AWK Mode. -;; It is organised thusly: +;; It is organised thusly, the sections being separated by page breaks: ;; 1. The AWK Mode syntax table. -;; 2. Indentation calculation stuff ("c-awk-NL-prop text-property"). -;; 3. Syntax-table property/font-locking stuff, but not including the +;; 2. Regular expressions for analysing AWK code. +;; 3. Indentation calculation stuff ("c-awk-NL-prop text-property"). +;; 4. Syntax-table property/font-locking stuff, but not including the ;; font-lock-keywords setting. -;; 4. The AWK Mode before/after-change-functions. -;; 5. AWK Mode specific versions of commands like beginning-of-defun. +;; 5. The AWK Mode before/after-change-functions. +;; 6. AWK Mode specific versions of commands like beginning-of-defun. ;; The AWK Mode keymap, abbreviation table, and the mode function itself are ;; in cc-mode.el. @@ -70,7 +71,7 @@ ;; / can delimit regexes or be a division operator. By default we assume ;; that it is a division sign, and fix the regexp operator cases with ;; `font-lock-syntactic-keywords'. - (modify-syntax-entry ?/ "." st) ; ACM 2002/4/27. + (modify-syntax-entry ?/ "." st) ; ACM 2002/4/27. (modify-syntax-entry ?* "." st) (modify-syntax-entry ?+ "." st) (modify-syntax-entry ?- "." st) @@ -85,378 +86,8 @@ st) "Syntax table in use in AWK Mode buffers.") -;; ACM, 2002/5/29: -;; -;; The next section of code is about determining whether or not an AWK -;; statement is complete or not. We use this to indent the following line. -;; The determination is pretty straightforward in C, where a statement ends -;; with either a ; or a }. Only "while" really gives any trouble there, since -;; it might be the end of a do-while. In AWK, on the other hand, semicolons -;; are rarely used, and EOLs _usually_ act as "virtual semicolons". In -;; addition, we have the complexity of escaped EOLs. The core of this -;; analysis is in the middle of the function -;; c-awk-calculate-NL-prop-prev-line, about 130 lines lower down. -;; -;; To avoid continually repeating this expensive analysis, we "cache" its -;; result in a text-property, c-awk-NL-prop, whose value for a line is set on -;; the EOL (if any) which terminates that line. Should the property be -;; required for the very last line (which has no EOL), it is calculated as -;; required but not cached. The c-awk-NL-prop property should be thought of -;; as only really valid immediately after a buffer change, not a permanently -;; set property. (By contrast, the syntax-table text properties (set by an -;; after-change function) must be constantly updated for the mode to work -;; properly). -;; -;; The valid values for c-awk-NL-prop are: -;; -;; nil The property is not currently set for this line. -;; '#' There is NO statement on this line (at most a comment), and no open -;; statement from a previous line which could have been completed on this -;; line. -;; '{' There is an unfinished statement on this (or a previous) line which -;; doesn't require \s to continue onto another line, e.g. the line ends -;; with {, or the && operator, or "if (condition)". Note that even if the -;; newline is redundantly escaped, it remains a '{' line. -;; '\' There is an escaped newline at the end of this line and this '\' is -;; essential to the syntax of the program. (i.e. if it had been a -;; frivolous \, it would have been ignored and the line been given one of -;; the other property values.) -;; ';' A statement is completed as the last thing (aside from ws) on the line - -;; i.e. there is (at least part of) a statement on this line, and the last -;; statement on the line is complete, OR (2002/10/25) the line is -;; content-free but terminates a statement from the preceding (continued) -;; line (which has property \). -;; -;; This set of values has been chosen so that the property's value on a line -;; is completely determined by the contents of the line and the property on -;; the previous line, EXCEPT for where a "while" might be the closing -;; statement of a do-while. - -(defun c-awk-after-if-for-while-condition-p (&optional do-lim) - ;; Are we just after the ) in "if/for/while (<condition>)"? - ;; - ;; Note that the end of the ) in a do .... while (<condition>) doesn't - ;; count, since the purpose of this routine is essentially to decide - ;; whether to indent the next line. - ;; - ;; DO-LIM sets a limit on how far back we search for the "do" of a possible - ;; do-while. - (and - (eq (char-before) ?\)) - (save-excursion - (let ((par-pos (c-safe (scan-lists (point) -1 0)))) - (when par-pos - (goto-char par-pos) ; back over "(...)" - (c-backward-token-1) ; BOB isn't a problem. - (or (looking-at "\\(if\\|for\\)\\>\\([^_]\\|$\\)") - (and (looking-at "while\\>\\([^_]\\|$\\)") ; Ensure this isn't a do-while. - (not (eq (c-beginning-of-statement-1 do-lim) - 'beginning))))))))) - -(defun c-awk-after-function-decl-param-list () - ;; Are we just after the ) in "function foo (bar)" ? - (and (eq (char-before) ?\)) - (save-excursion - (let ((par-pos (c-safe (scan-lists (point) -1 0)))) - (when par-pos - (goto-char par-pos) ; back over "(...)" - (c-backward-token-1) ; BOB isn't a problem - (and (looking-at "[_a-zA-Z][_a-zA-Z0-9]*\\>") - (progn (c-backward-token-1) - (looking-at "func\\(tion\\)?\\>")))))))) - -;; 2002/11/8: FIXME! Check c-backward-token-1/2 for success (0 return code). -(defun c-awk-after-continue-token () -;; Are we just after a token which can be continued onto the next line without -;; a backslash? - (save-excursion - (c-backward-token-1) ; FIXME 2002/10/27. What if this fails? - (if (and (looking-at "[&|]") (not (bobp))) - (backward-char)) ; c-backward-token-1 doesn't do this :-( - (looking-at "[,{?:]\\|&&\\|||\\|do\\>\\|else\\>"))) - -(defun c-awk-after-rbrace-or-statement-semicolon () - ;; Are we just after a } or a ; which closes a statement? - ;; Be careful about ;s in for loop control bits. They don't count! - (or (eq (char-before) ?\}) - (and - (eq (char-before) ?\;) - (save-excursion - (let ((par-pos (c-safe (scan-lists (point) -1 1)))) - (when par-pos - (goto-char par-pos) ; go back to containing ( - (not (and (looking-at "(") - (c-backward-token-1) ; BOB isn't a problem - (looking-at "for\\>"))))))))) - -(defun c-awk-back-to-contentful-text-or-NL-prop () - ;; Move back to just after the first found of either (i) an EOL which has - ;; the c-awk-NL-prop text-property set; or (ii) non-ws text; or (iii) BOB. - ;; We return either the value of c-awk-NL-prop (in case (i)) or nil. - ;; Calling function can best distinguish cases (ii) and (iii) with (bolp). - ;; - ;; Note that an escaped eol counts as whitespace here. - ;; - ;; Kludge: If c-backward-syntactic-ws gets stuck at a BOL, it is likely - ;; that the previous line contains an unterminated string (without \). In - ;; this case, assume that the previous line's c-awk-NL-prop is a ;. - ;; - ;; POINT MUST BE AT THE START OF A LINE when calling this function. This - ;; is to ensure that the various backward-comment functions will work - ;; properly. - (let ((nl-prop nil) - bol-pos bsws-pos) ; starting pos for a backward-syntactic-ws call. - (while ;; We are at a BOL here. Go back one line each iteration. - (and - (not (bobp)) - (not (setq nl-prop (c-get-char-property (1- (point)) 'c-awk-NL-prop))) - (progn (setq bol-pos (c-point 'bopl)) - (setq bsws-pos (point)) - ;; N.B. the following function will not go back past an EOL if - ;; there is an open string (without \) on the previous line. - (c-backward-syntactic-ws bol-pos) - (or (/= (point) bsws-pos) - (progn (setq nl-prop ?\;) - nil))) - ;; If we had a backslash at EOL, c-backward-syntactic-ws will - ;; have gone backwards over it. Check the backslash was "real". - (progn - (if (looking-at "[ \t]*\\\\+$") - (if (progn - (end-of-line) - (search-backward-regexp - "\\(^\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\$" ; ODD number of \s at EOL :-) - bol-pos t)) - (progn (end-of-line) ; escaped EOL. - (backward-char) - (c-backward-syntactic-ws bol-pos)) - (end-of-line))) ; The \ at eol is a fake. - (bolp)))) - nl-prop)) - -(defun c-awk-calculate-NL-prop-prev-line (&optional do-lim) - ;; Calculate and set the value of the c-awk-NL-prop on the immediately - ;; preceding EOL. This may also involve doing the same for several - ;; preceding EOLs. - ;; - ;; NOTE that if the property was already set, we return it without - ;; recalculation. (This is by accident rather than design.) - ;; - ;; Return the property which got set (or was already set) on the previous - ;; line. Return nil if we hit BOB. - ;; - ;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM. - (save-excursion - (save-match-data - (beginning-of-line) - (let* ((pos (point)) - (nl-prop (c-awk-back-to-contentful-text-or-NL-prop))) - ;; We are either (1) at a BOL (with nl-prop containing the previous - ;; line's c-awk-NL-prop) or (2) after contentful text on a line. At - ;; the BOB counts as case (1), so we test next for bolp rather than - ;; non-nil nl-prop. - (when (not (bolp)) - (setq nl-prop - (cond - ;; Incomplete statement which doesn't require escaped EOL? - ((or (c-awk-after-if-for-while-condition-p do-lim) - (c-awk-after-function-decl-param-list) - (c-awk-after-continue-token)) - ?\{) - ;; Escaped EOL (where there's also something to continue)? - ((and (looking-at "[ \t]*\\\\$") - (not (c-awk-after-rbrace-or-statement-semicolon))) - ?\\) - (t ?\;))) ; A statement was completed on this line - (end-of-line) - (c-put-char-property (point) 'c-awk-NL-prop nl-prop) - (forward-line)) - - ;; We are now at a (possibly empty) sequence of content-free lines. - ;; Set c-awk-NL-prop on each of these lines's EOL. - (while (< (point) pos) ; one content-free line each iteration. - (cond ; recalculate nl-prop from previous line's value. - ((memq nl-prop '(?\; nil)) (setq nl-prop ?\#)) - ((eq nl-prop ?\\) - (if (not (looking-at "[ \t]*\\\\$")) (setq nl-prop ?\;))) ; was ?\# 2002/10/25 - ;; ?\# (empty line) and ?\{ (open stmt) don't change. - ) - (forward-line) - (c-put-char-property (1- (point)) 'c-awk-NL-prop nl-prop)) - nl-prop)))) - -(defun c-awk-get-NL-prop-prev-line (&optional do-lim) - ;; Get the c-awk-NL-prop text-property from the previous line, calculating - ;; it if necessary. Return nil iff we're already at BOB. - ;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM. - (if (bobp) - nil - (or (c-get-char-property (c-point 'eopl) 'c-awk-NL-prop) - (c-awk-calculate-NL-prop-prev-line do-lim)))) - -(defun c-awk-get-NL-prop-cur-line (&optional do-lim) - ;; Get the c-awk-NL-prop text-property from the current line, calculating it - ;; if necessary. (As a special case, the property doesn't get set on an - ;; empty line at EOB (there's no position to set the property on), but the - ;; function returns the property value an EOL would have got.) - ;; - ;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM. - (save-excursion - (let ((extra-nl nil)) - (end-of-line) ; Necessary for the following test to work. - (when (= (forward-line) 1) ; if we were on the last line.... - (insert-char ?\n 1) ; ...artificial eol is needed for comment detection. - (setq extra-nl t)) - (prog1 (c-awk-get-NL-prop-prev-line do-lim) - (if extra-nl (delete-backward-char 1)))))) - -(defun c-awk-prev-line-incomplete-p (&optional do-lim) - ;; Is there an incomplete statement at the end of the previous line? - ;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM. - (memq (c-awk-get-NL-prop-prev-line do-lim) '(?\\ ?\{))) - -(defun c-awk-cur-line-incomplete-p (&optional do-lim) - ;; Is there an incomplete statement at the end of the current line? - ;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM. - (memq (c-awk-get-NL-prop-cur-line do-lim) '(?\\ ?\{))) - -(defun c-awk-completed-stmt-ws-ends-prev-line-p (&optional do-lim) - ;; Is there a termination of a statement as the last thing (apart from an - ;; optional comment) on the previous line? - ;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM. - (eq (c-awk-get-NL-prop-prev-line do-lim) ?\;)) - -(defun c-awk-completed-stmt-ws-ends-line-p (&optional pos do-lim) - ;; Same as previous function, but for the line containing position POS (or - ;; the current line if POS is omitted). - ;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM. - (save-excursion - (if pos (goto-char pos)) - (eq (c-awk-get-NL-prop-cur-line do-lim) ?\;))) - -(defun c-awk-after-logical-semicolon (&optional do-lim) -;; Are we at BOL, the preceding EOL being a "logical semicolon"? -;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM. - (and (bolp) - (eq (c-awk-get-NL-prop-prev-line do-lim) ?\;))) - -(defun c-awk-backward-syntactic-ws (&optional lim) -;; Skip backwards over awk-syntactic whitespace. This is whitespace -;; characters, comments, and NEWLINES WHICH AREN'T "VIRTUAL SEMICOLONS". For -;; this function, a newline isn't a "virtual semicolon" if that line ends with -;; a real semicolon (or closing brace). -;; However if point starts inside a comment or preprocessor directive, the -;; content of it is not treated as whitespace. LIM (optional) sets a limit on -;; the backward movement. - (let ((lim (or lim (point-min))) - after-real-br) - (c-backward-syntactic-ws (max lim (c-point 'bol))) - (while ; go back one WS line each time round this loop. - (and (bolp) - (> (point) lim) - (/= (c-awk-get-NL-prop-prev-line) ?\;) - (/= (point) - ;; The following function requires point at BONL [not EOL] to - ;; recognise a preceding comment,. - (progn (c-backward-syntactic-ws (max lim (c-point 'bopl))) - (point))))) - ;; Does the previous line end with a real ; or }? If so, go back to it. - (if (and (bolp) - (eq (c-awk-get-NL-prop-prev-line) ?\;) - (save-excursion - (c-backward-syntactic-ws (max lim (c-point 'bopl))) - (setq after-real-br (point)) - (c-awk-after-rbrace-or-statement-semicolon))) - (goto-char after-real-br)))) - -(defun c-awk-NL-prop-not-set () - ;; Is the NL-prop on the current line either nil or unset? - (not (c-get-char-property (c-point 'eol) 'c-awk-NL-prop))) - -(defun c-awk-clear-NL-props (beg end) - ;; This function is run from before-change-hooks. It clears the - ;; c-awk-NL-prop text property from beg to the end of the buffer (The END - ;; parameter is ignored). This ensures that the indentation engine will - ;; never use stale values for this property. - (save-restriction - (widen) - (c-clear-char-properties beg (point-max) 'c-awk-NL-prop))) - -(defun c-awk-unstick-NL-prop () - ;; Ensure that the text property c-awk-NL-prop is "non-sticky". Without - ;; this, a new newline inserted after an old newline (e.g. by C-j) would - ;; inherit any c-awk-NL-prop from the old newline. This would be a Bad - ;; Thing. This function's action is required by c-put-char-property. - (if (and (boundp 'text-property-default-nonsticky) ; doesn't exist in Xemacs - (not (assoc 'c-awk-NL-prop text-property-default-nonsticky))) - (setq text-property-default-nonsticky - (cons '(c-awk-NL-prop . t) text-property-default-nonsticky)))) - -;; The following is purely a diagnostic command, to be commented out of the -;; final release. ACM, 2002/6/1 -;; (defun NL-props () -;; (interactive) -;; (let (pl-prop cl-prop) -;; (message "Prev-line: %s Cur-line: %s" -;; (if (setq pl-prop (c-get-char-property (c-point 'eopl) 'c-awk-NL-prop)) -;; (char-to-string pl-prop) -;; "nil") -;; (if (setq cl-prop (c-get-char-property (c-point 'eol) 'c-awk-NL-prop)) -;; (char-to-string cl-prop) -;; "nil")))) -;(define-key awk-mode-map [?\C-c ?\r] 'NL-props) ; commented out, 2002/8/31 -;for now. In the byte compiled version, this causes things to crash because -;awk-mode-map isn't yet defined. :-( - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; The following section of the code is to do with font-locking. The biggest -;; problem for font-locking is deciding whether a / is a regular expression -;; delimiter or a division sign - determining precisely where strings and -;; regular expressions start and stop is also troublesome. This is the -;; purpose of the function c-awk-set-syntax-table-properties and the myriad -;; elisp regular expressions it uses. -;; -;; Because AWK is a line oriented language, I felt the normal cc-mode strategy -;; for font-locking unterminated strings (i.e. font-locking the buffer up to -;; the next string delimiter as a string) was inappropriate. Instead, -;; unbalanced string/regexp delimiters are given the warning font, being -;; refonted with the string font as soon as the matching delimiter is entered. -;; -;; This requires the region processed by the current font-lock after-change -;; function to have access to the start of the string/regexp, which may be -;; several lines back. The elisp "advice" feature is used on these functions -;; to allow this. - -(defun c-awk-beginning-of-logical-line (&optional pos) -;; Go back to the start of the (apparent) current line (or the start of the -;; line containing POS), returning the buffer position of that point. I.e., -;; go back to the last line which doesn't have an escaped EOL before it. -;; -;; This is guaranteed to be "safe" for syntactic analysis, i.e. outwith any -;; comment, string or regexp. IT MAY WELL BE that this function should not be -;; executed on a narrowed buffer. - (if pos (goto-char pos)) - (forward-line 0) - (while (and (> (point) (point-min)) - (eq (char-before (1- (point))) ?\\)) - (forward-line -1)) - (point)) - -(defun c-awk-end-of-logical-line (&optional pos) -;; Go forward to the end of the (apparent) current logical line (or the end of -;; the line containing POS), returning the buffer position of that point. I.e., -;; go to the end of the next line which doesn't have an escaped EOL. -;; -;; This is guaranteed to be "safe" for syntactic analysis, i.e. outwith any -;; comment, string or regexp. IT MAY WELL BE that this function should not be -;; executed on a narrowed buffer. - (if pos (goto-char pos)) - (end-of-line) - (while (and (< (point) (point-max)) - (eq (char-before) ?\\)) - (end-of-line 2)) - (point)) + +;; This section defines regular expressions used in the analysis of AWK code. ;; N.B. In the following regexps, an EOL is either \n OR \r. This is because ;; Emacs has in the past used \r to mark hidden lines in some fashion (and @@ -464,6 +95,8 @@ (defconst c-awk-esc-pair-re "\\\\\\(.\\|\n\\|\r\\|\\'\\)") ;; Matches any escaped (with \) character-pair, including an escaped newline. +(defconst c-awk-non-eol-esc-pair-re "\\\\\\(.\\|\\'\\)") +;; Matches any escaped (with \) character-pair, apart from an escaped newline. (defconst c-awk-comment-without-nl "#.*") ;; Matches an AWK comment, not including the terminating NL (if any). Note ;; that the "enclosing" (elisp) regexp must ensure the # is real. @@ -471,7 +104,8 @@ ;; Matches a newline, or the end of buffer. ;; "Space" regular expressions. -(defconst c-awk-escaped-nl "\\\\[\n\r]") +(eval-and-compile + (defconst c-awk-escaped-nl "\\\\[\n\r]")) ;; Matches an escaped newline. (defconst c-awk-escaped-nls* (concat "\\(" c-awk-escaped-nl "\\)*")) ;; Matches a possibly empty sequence of escaped newlines. Used in @@ -480,10 +114,15 @@ ;; (concat "\\(" c-awk-escaped-nls* "\\|" "[ \t]+" "\\)*")) ;; The above RE was very slow. It's runtime was doubling with each additional ;; space :-( Reformulate it as below: -(defconst c-awk-escaped-nls*-with-space* - (concat "\\(" c-awk-escaped-nl "\\|" "[ \t]" "\\)*")) +(eval-and-compile + (defconst c-awk-escaped-nls*-with-space* + (concat "\\(" c-awk-escaped-nl "\\|" "[ \t]" "\\)*"))) ;; Matches a possibly empty sequence of escaped newlines with optional ;; interspersed spaces and tabs. Used in awk-font-lock-keywords. +(defconst c-awk-blank-or-comment-line-re + (concat "[ \t]*\\(#\\|\\\\?$\\)")) +;; Matche (the tail of) a line containing at most either a comment or an +;; escaped EOL. ;; REGEXPS FOR "HARMLESS" STRINGS/LINES. (defconst c-awk-harmless-char-re "[^_#/\"\\\\\n\r]") @@ -521,6 +160,9 @@ (concat "\\=_?\"" c-awk-string-innards-re)) ;; Matches an AWK string at point up to, but not including, any terminator. ;; A gawk 3.1+ string may look like _"localisable string". +(defconst c-awk-one-line-possibly-open-string-re + (concat "\"\\(" c-awk-string-ch-re "\\|" c-awk-non-eol-esc-pair-re "\\)*" + "\\(\"\\|\\\\?$\\|\\'\\)")) ;; REGEXPS FOR AWK REGEXPS. (defconst c-awk-regexp-normal-re "[^[/\\\n\r]") @@ -541,13 +183,25 @@ "\\|" "[^]\n\r]" "\\)*" "\\(]\\|$\\)")) ;; Matches a regexp char list, up to (but not including) EOL if the ] is ;; missing. +(defconst c-awk-regexp-one-line-possibly-open-char-list-re + (concat "\\[\\]?\\(" c-awk-non-eol-esc-pair-re "\\|" "[^]\n\r]" "\\)*" + "\\(]\\|\\\\?$\\|\\'\\)")) +;; Matches the head (or all) of a regexp char class, up to (but not +;; including) the first EOL. (defconst c-awk-regexp-innards-re (concat "\\(" c-awk-esc-pair-re "\\|" c-awk-regexp-char-list-re "\\|" c-awk-regexp-normal-re "\\)*")) ;; Matches the inside of an AWK regexp (i.e. without the enclosing /s) (defconst c-awk-regexp-without-end-re (concat "/" c-awk-regexp-innards-re)) -;; Matches an AWK regexp up to, but not including, any terminating /. +;; Matches an AWK regexp up to, but not including, any terminating /. +(defconst c-awk-one-line-possibly-open-regexp-re + (concat "/\\(" c-awk-non-eol-esc-pair-re + "\\|" c-awk-regexp-one-line-possibly-open-char-list-re + "\\|" c-awk-regexp-normal-re "\\)*" + "\\(/\\|\\\\?$\\|\\'\\)")) +;; Matches as much of the head of an AWK regexp which fits on one line, +;; possibly all of it. ;; REGEXPS used for scanning an AWK buffer in order to decide IF A '/' IS A ;; REGEXP OPENER OR A DIVISION SIGN. By "state" in the following is meant @@ -587,6 +241,405 @@ ;; will only work when there won't be a preceding " or / before the sought / ;; to foul things up. +;; REGEXPS USED FOR FINDING THE POSITION OF A "virtual semicolon" +(defconst c-awk-_-harmless-nonws-char-re "[^#/\"\\\\\n\r \t]") +;;;; NEW VERSION! (which will be restricted to the current line) +(defconst c-awk-one-line-non-syn-ws*-re + (concat "\\([ \t]*" + "\\(" c-awk-_-harmless-nonws-char-re "\\|" + c-awk-non-eol-esc-pair-re "\\|" + c-awk-one-line-possibly-open-string-re "\\|" + c-awk-one-line-possibly-open-regexp-re + "\\)" + "\\)*")) + + +;; ACM, 2002/5/29: +;; +;; The next section of code is about determining whether or not an AWK +;; statement is complete or not. We use this to indent the following line. +;; The determination is pretty straightforward in C, where a statement ends +;; with either a ; or a }. Only "while" really gives any trouble there, since +;; it might be the end of a do-while. In AWK, on the other hand, semicolons +;; are rarely used, and EOLs _usually_ act as "virtual semicolons". In +;; addition, we have the complexity of escaped EOLs. The core of this +;; analysis is in the middle of the function +;; c-awk-calculate-NL-prop-prev-line, about 130 lines lower down. +;; +;; To avoid continually repeating this expensive analysis, we "cache" its +;; result in a text-property, c-awk-NL-prop, whose value for a line is set on +;; the EOL (if any) which terminates that line. Should the property be +;; required for the very last line (which has no EOL), it is calculated as +;; required but not cached. The c-awk-NL-prop property should be thought of +;; as only really valid immediately after a buffer change, not a permanently +;; set property. (By contrast, the syntax-table text properties (set by an +;; after-change function) must be constantly updated for the mode to work +;; properly). +;; +;; This text property is also used for "syntactic whitespace" movement, this +;; being where the distinction between the values '$' and '}' is significant. +;; +;; The valid values for c-awk-NL-prop are: +;; +;; nil The property is not currently set for this line. +;; '#' There is NO statement on this line (at most a comment), and no open +;; statement from a previous line which could have been completed on this +;; line. +;; '{' There is an unfinished statement on this (or a previous) line which +;; doesn't require \s to continue onto another line, e.g. the line ends +;; with {, or the && operator, or "if (condition)". Note that even if the +;; newline is redundantly escaped, it remains a '{' line. +;; '\' There is an escaped newline at the end of this line and this '\' is +;; essential to the syntax of the program. (i.e. if it had been a +;; frivolous \, it would have been ignored and the line been given one of +;; the other property values.) +;; '$' A non-empty statement is terminated on the line by an EOL (a "virtual +;; semicolon"). This might be a content-free line terminating a statement +;; from the preceding (continued) line (which has property \). +;; '}' A statement, being the last thing (aside from ws/comments) is +;; explicitly terminated on this line by a closing brace (or sometimes a +;; semicolon). +;; +;; This set of values has been chosen so that the property's value on a line +;; is completely determined by the contents of the line and the property on +;; the previous line, EXCEPT for where a "while" might be the closing +;; statement of a do-while. + +(defun c-awk-after-if-for-while-condition-p (&optional do-lim) + ;; Are we just after the ) in "if/for/while (<condition>)"? + ;; + ;; Note that the end of the ) in a do .... while (<condition>) doesn't + ;; count, since the purpose of this routine is essentially to decide + ;; whether to indent the next line. + ;; + ;; DO-LIM sets a limit on how far back we search for the "do" of a possible + ;; do-while. + ;; + ;; This function might do hidden buffer changes. + (and + (eq (char-before) ?\)) + (save-excursion + (let ((par-pos (c-safe (scan-lists (point) -1 0)))) + (when par-pos + (goto-char par-pos) ; back over "(...)" + (c-backward-token-1) ; BOB isn't a problem. + (or (looking-at "\\(if\\|for\\)\\>\\([^_]\\|$\\)") + (and (looking-at "while\\>\\([^_]\\|$\\)") ; Ensure this isn't a do-while. + (not (eq (c-beginning-of-statement-1 do-lim) + 'beginning))))))))) + +(defun c-awk-after-function-decl-param-list () + ;; Are we just after the ) in "function foo (bar)" ? + ;; + ;; This function might do hidden buffer changes. + (and (eq (char-before) ?\)) + (save-excursion + (let ((par-pos (c-safe (scan-lists (point) -1 0)))) + (when par-pos + (goto-char par-pos) ; back over "(...)" + (c-backward-token-1) ; BOB isn't a problem + (and (looking-at "[_a-zA-Z][_a-zA-Z0-9]*\\>") + (progn (c-backward-token-1) + (looking-at "func\\(tion\\)?\\>")))))))) + +;; 2002/11/8: FIXME! Check c-backward-token-1/2 for success (0 return code). +(defun c-awk-after-continue-token () +;; Are we just after a token which can be continued onto the next line without +;; a backslash? +;; +;; This function might do hidden buffer changes. + (save-excursion + (c-backward-token-1) ; FIXME 2002/10/27. What if this fails? + (if (and (looking-at "[&|]") (not (bobp))) + (backward-char)) ; c-backward-token-1 doesn't do this :-( + (looking-at "[,{?:]\\|&&\\|||\\|do\\>\\|else\\>"))) + +(defun c-awk-after-rbrace-or-statement-semicolon () + ;; Are we just after a } or a ; which closes a statement? + ;; Be careful about ;s in for loop control bits. They don't count! + ;; + ;; This function might do hidden buffer changes. + (or (eq (char-before) ?\}) + (and + (eq (char-before) ?\;) + (save-excursion + (let ((par-pos (c-safe (scan-lists (point) -1 1)))) + (when par-pos + (goto-char par-pos) ; go back to containing ( + (not (and (looking-at "(") + (c-backward-token-1) ; BOB isn't a problem + (looking-at "for\\>"))))))))) + +(defun c-awk-back-to-contentful-text-or-NL-prop () + ;; Move back to just after the first found of either (i) an EOL which has + ;; the c-awk-NL-prop text-property set; or (ii) non-ws text; or (iii) BOB. + ;; We return either the value of c-awk-NL-prop (in case (i)) or nil. + ;; Calling functions can best distinguish cases (ii) and (iii) with (bolp). + ;; + ;; Note that an escaped eol counts as whitespace here. + ;; + ;; Kludge: If c-backward-syntactic-ws gets stuck at a BOL, it is likely + ;; that the previous line contains an unterminated string (without \). In + ;; this case, assume that the previous line's c-awk-NL-prop is a $. + ;; + ;; POINT MUST BE AT THE START OF A LINE when calling this function. This + ;; is to ensure that the various backward-comment functions will work + ;; properly. + ;; + ;; This function might do hidden buffer changes. + (let ((nl-prop nil) + bol-pos bsws-pos) ; starting pos for a backward-syntactic-ws call. + (while ;; We are at a BOL here. Go back one line each iteration. + (and + (not (bobp)) + (not (setq nl-prop (c-get-char-property (1- (point)) 'c-awk-NL-prop))) + (progn (setq bol-pos (c-point 'bopl)) + (setq bsws-pos (point)) + ;; N.B. the following function will not go back past an EOL if + ;; there is an open string (without \) on the previous line. + ;; If we find such, set the c-awk-NL-prop on it, too + ;; (2004/3/29). + (c-backward-syntactic-ws bol-pos) + (or (/= (point) bsws-pos) + (progn (setq nl-prop ?\$) + (c-put-char-property (1- (point)) 'c-awk-NL-prop nl-prop) + nil))) + ;; If we had a backslash at EOL, c-backward-syntactic-ws will + ;; have gone backwards over it. Check the backslash was "real". + (progn + (if (looking-at "[ \t]*\\\\+$") + (if (progn + (end-of-line) + (search-backward-regexp + "\\(^\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\$" ; ODD number of \s at EOL :-) + bol-pos t)) + (progn (end-of-line) ; escaped EOL. + (backward-char) + (c-backward-syntactic-ws bol-pos)) + (end-of-line))) ; The \ at eol is a fake. + (bolp)))) + nl-prop)) + +(defun c-awk-calculate-NL-prop-prev-line (&optional do-lim) + ;; Calculate and set the value of the c-awk-NL-prop on the immediately + ;; preceding EOL. This may also involve doing the same for several + ;; preceding EOLs. + ;; + ;; NOTE that if the property was already set, we return it without + ;; recalculation. (This is by accident rather than design.) + ;; + ;; Return the property which got set (or was already set) on the previous + ;; line. Return nil if we hit BOB. + ;; + ;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM. + ;; + ;; This function might do hidden buffer changes. + (save-excursion + (save-match-data + (beginning-of-line) + (let* ((pos (point)) + (nl-prop (c-awk-back-to-contentful-text-or-NL-prop))) + ;; We are either (1) at a BOL (with nl-prop containing the previous + ;; line's c-awk-NL-prop) or (2) after contentful text on a line. At + ;; the BOB counts as case (1), so we test next for bolp rather than + ;; non-nil nl-prop. + (when (not (bolp)) + (setq nl-prop + (cond + ;; Incomplete statement which doesn't require escaped EOL? + ((or (c-awk-after-if-for-while-condition-p do-lim) + (c-awk-after-function-decl-param-list) + (c-awk-after-continue-token)) + ?\{) + ;; Escaped EOL (where there's also something to continue)? + ((and (looking-at "[ \t]*\\\\$") + (not (c-awk-after-rbrace-or-statement-semicolon))) + ?\\) + ;; A statement was completed on this line. How? + ((memq (char-before) '(?\; ?\})) ?\}) ; Real ; or } + (t ?\$))) ; A virtual semicolon. + (end-of-line) + (c-put-char-property (point) 'c-awk-NL-prop nl-prop) + (forward-line)) + + ;; We are now at a (possibly empty) sequence of content-free lines. + ;; Set c-awk-NL-prop on each of these lines's EOL. + (while (< (point) pos) ; one content-free line each iteration. + (cond ; recalculate nl-prop from previous line's value. + ((memq nl-prop '(?\} ?\$ nil)) (setq nl-prop ?\#)) + ((eq nl-prop ?\\) + (if (not (looking-at "[ \t]*\\\\$")) (setq nl-prop ?\$))) + ;; ?\# (empty line) and ?\{ (open stmt) don't change. + ) + (forward-line) + (c-put-char-property (1- (point)) 'c-awk-NL-prop nl-prop)) + nl-prop)))) + +(defun c-awk-get-NL-prop-prev-line (&optional do-lim) + ;; Get the c-awk-NL-prop text-property from the previous line, calculating + ;; it if necessary. Return nil iff we're already at BOB. + ;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM. + ;; + ;; This function might do hidden buffer changes. + (if (bobp) + nil + (or (c-get-char-property (c-point 'eopl) 'c-awk-NL-prop) + (c-awk-calculate-NL-prop-prev-line do-lim)))) + +(defun c-awk-get-NL-prop-cur-line (&optional do-lim) + ;; Get the c-awk-NL-prop text-property from the current line, calculating it + ;; if necessary. (As a special case, the property doesn't get set on an + ;; empty line at EOB (there's no position to set the property on), but the + ;; function returns the property value an EOL would have got.) + ;; + ;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM. + ;; + ;; This function might do hidden buffer changes. + (save-excursion + (let ((extra-nl nil)) + (end-of-line) ; Necessary for the following test to work. + (when (= (forward-line) 1) ; if we were on the last line.... + (insert-char ?\n 1) ; ...artificial eol is needed for comment detection. + (setq extra-nl t)) + (prog1 (c-awk-get-NL-prop-prev-line do-lim) + (if extra-nl (delete-backward-char 1)))))) + +(defsubst c-awk-prev-line-incomplete-p (&optional do-lim) + ;; Is there an incomplete statement at the end of the previous line? + ;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM. + ;; + ;; This function might do hidden buffer changes. + (memq (c-awk-get-NL-prop-prev-line do-lim) '(?\\ ?\{))) + +(defsubst c-awk-cur-line-incomplete-p (&optional do-lim) + ;; Is there an incomplete statement at the end of the current line? + ;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM. + ;; + ;; This function might do hidden buffer changes. + (memq (c-awk-get-NL-prop-cur-line do-lim) '(?\\ ?\{))) + +;;;; NOTES ON "VIRTUAL SEMICOLONS" +;;;; +;;;; A "virtual semicolon" is what terminates a statement when there is no ; +;;;; or } to do the job. Like point, it is considered to lie _between_ two +;;;; characters. As from mid-March 2004, it is considered to lie just after +;;;; the last non-syntactic-whitespace character on the line; (previously, it +;;;; was considered an attribute of the EOL on the line). A real semicolon +;;;; never counts as a virtual one. + +(defun c-awk-at-vsemi-p (&optional pos) + ;; Is there a virtual semicolon at POS (or POINT)? + (save-excursion + (let (nl-prop + (pos-or-point (progn (if pos (goto-char pos)) (point)))) + (forward-line 0) + (search-forward-regexp c-awk-one-line-non-syn-ws*-re) + (and (eq (point) pos-or-point) + (progn + (while (and (eq (setq nl-prop (c-awk-get-NL-prop-cur-line)) ?\\) + (eq (forward-line) 0) + (looking-at c-awk-blank-or-comment-line-re))) + (eq nl-prop ?\$)))))) + +(defun c-awk-vsemi-status-unknown-p () + ;; Are we unsure whether there is a virtual semicolon on the current line? + ;; DO NOT under any circumstances attempt to calculate this; that would + ;; defeat the (admittedly kludgey) purpose of this function, which is to + ;; prevent an infinite recursion in c-beginning-of-statement-1 when point + ;; starts at a `while' token. + (not (c-get-char-property (c-point 'eol) 'c-awk-NL-prop))) + +(defun c-awk-clear-NL-props (beg end) + ;; This function is run from before-change-hooks. It clears the + ;; c-awk-NL-prop text property from beg to the end of the buffer (The END + ;; parameter is ignored). This ensures that the indentation engine will + ;; never use stale values for this property. + ;; + ;; This function might do hidden buffer changes. + (save-restriction + (widen) + (c-clear-char-properties beg (point-max) 'c-awk-NL-prop))) + +(defun c-awk-unstick-NL-prop () + ;; Ensure that the text property c-awk-NL-prop is "non-sticky". Without + ;; this, a new newline inserted after an old newline (e.g. by C-j) would + ;; inherit any c-awk-NL-prop from the old newline. This would be a Bad + ;; Thing. This function's action is required by c-put-char-property. + (if (and (boundp 'text-property-default-nonsticky) ; doesn't exist in Xemacs + (not (assoc 'c-awk-NL-prop text-property-default-nonsticky))) + (setq text-property-default-nonsticky + (cons '(c-awk-NL-prop . t) text-property-default-nonsticky)))) + +;; The following is purely a diagnostic command, to be commented out of the +;; final release. ACM, 2002/6/1 +;; (defun NL-props () +;; (interactive) +;; (let (pl-prop cl-prop) +;; (message "Prev-line: %s Cur-line: %s" +;; (if (setq pl-prop (c-get-char-property (c-point 'eopl) 'c-awk-NL-prop)) +;; (char-to-string pl-prop) +;; "nil") +;; (if (setq cl-prop (c-get-char-property (c-point 'eol) 'c-awk-NL-prop)) +;; (char-to-string cl-prop) +;; "nil")))) +;(define-key awk-mode-map [?\C-c ?\r] 'NL-props) ; commented out, 2002/8/31 +;for now. In the byte compiled version, this causes things to crash because +;awk-mode-map isn't yet defined. :-( + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; The following section of the code is to do with font-locking. The biggest +;; problem for font-locking is deciding whether a / is a regular expression +;; delimiter or a division sign - determining precisely where strings and +;; regular expressions start and stop is also troublesome. This is the +;; purpose of the function c-awk-set-syntax-table-properties and the myriad +;; elisp regular expressions it uses. +;; +;; Because AWK is a line oriented language, I felt the normal cc-mode strategy +;; for font-locking unterminated strings (i.e. font-locking the buffer up to +;; the next string delimiter as a string) was inappropriate. Instead, +;; unbalanced string/regexp delimiters are given the warning font, being +;; refonted with the string font as soon as the matching delimiter is entered. +;; +;; This requires the region processed by the current font-lock after-change +;; function to have access to the start of the string/regexp, which may be +;; several lines back. The elisp "advice" feature is used on these functions +;; to allow this. + +(defun c-awk-beginning-of-logical-line (&optional pos) +;; Go back to the start of the (apparent) current line (or the start of the +;; line containing POS), returning the buffer position of that point. I.e., +;; go back to the last line which doesn't have an escaped EOL before it. +;; +;; This is guaranteed to be "safe" for syntactic analysis, i.e. outwith any +;; comment, string or regexp. IT MAY WELL BE that this function should not be +;; executed on a narrowed buffer. +;; +;; This function might do hidden buffer changes. + (if pos (goto-char pos)) + (forward-line 0) + (while (and (> (point) (point-min)) + (eq (char-before (1- (point))) ?\\)) + (forward-line -1)) + (point)) + +(defun c-awk-end-of-logical-line (&optional pos) +;; Go forward to the end of the (apparent) current logical line (or the end of +;; the line containing POS), returning the buffer position of that point. I.e., +;; go to the end of the next line which doesn't have an escaped EOL. +;; +;; This is guaranteed to be "safe" for syntactic analysis, i.e. outwith any +;; comment, string or regexp. IT MAY WELL BE that this function should not be +;; executed on a narrowed buffer. +;; +;; This function might do hidden buffer changes. + (if pos (goto-char pos)) + (end-of-line) + (while (and (< (point) (point-max)) + (eq (char-before) ?\\)) + (end-of-line 2)) + (point)) + ;; ACM, 2002/02/15: The idea of the next function is to put the "Error font" ;; on strings/regexps which are missing their closing delimiter. ;; 2002/4/28. The default syntax for / has been changed from "string" to @@ -605,24 +658,26 @@ ;; ;; If the closing delimiter is missing (i.e., there is an EOL there) set the ;; STRING-FENCE property on the opening " or / and closing EOL. +;; +;; This function does hidden buffer changes. (if (eq (char-after beg) ?_) (setq beg (1+ beg))) ;; First put the properties on the delimiters. (cond ((eq end (point-max)) ; string/regexp terminated by EOB - (put-text-property beg (1+ beg) 'syntax-table '(15))) ; (15) = "string fence" + (c-put-char-property beg 'syntax-table '(15))) ; (15) = "string fence" ((/= (char-after beg) (char-after end)) ; missing end delimiter - (put-text-property beg (1+ beg) 'syntax-table '(15)) - (put-text-property end (1+ end) 'syntax-table '(15))) + (c-put-char-property beg 'syntax-table '(15)) + (c-put-char-property end 'syntax-table '(15))) ((eq (char-after beg) ?/) ; Properly bracketed regexp - (put-text-property beg (1+ beg) 'syntax-table '(7)) ; (7) = "string" - (put-text-property end (1+ end) 'syntax-table '(7))) + (c-put-char-property beg 'syntax-table '(7)) ; (7) = "string" + (c-put-char-property end 'syntax-table '(7))) (t)) ; Properly bracketed string: Nothing to do. ;; Now change the properties of any escaped "s in the string to punctuation. (save-excursion (goto-char (1+ beg)) (or (eobp) (while (search-forward "\"" end t) - (put-text-property (1- (point)) (point) 'syntax-table '(1)))))) + (c-put-char-property (1- (point)) 'syntax-table '(1)))))) (defun c-awk-syntax-tablify-string () ;; Point is at the opening " or _" of a string. Set the syntax-table @@ -630,6 +685,8 @@ ;; ;; The result is nil if a / immediately after the string would be a regexp ;; opener, t if it would be a division sign. + ;; + ;; This function does hidden buffer changes. (search-forward-regexp c-awk-string-without-end-here-re nil t) ; a (possibly unterminated) string (c-awk-set-string-regexp-syntax-table-properties (match-beginning 0) (match-end 0)) @@ -653,6 +710,8 @@ ;; point is. ;; ;; The result is what ANCHOR-STATE-/DIV (see above) is where point is left. + ;; + ;; This function might do hidden buffer changes. (let ((/point (point))) (goto-char anchor) ;; Analyse the line to find out what the / is. @@ -698,14 +757,18 @@ ;; given the property "punctuation". This will later allow other routines ;; to use the regexp "\\S\"*" to skip over the string innards. ;; (iv) Inside a comment, all syntax-table properties are cleared. +;; +;; This function does hidden buffer changes. (let (anchor (anchor-state-/div nil)) ; t means a following / would be a div sign. (c-awk-beginning-of-logical-line) ; ACM 2002/7/21. This is probably redundant. - (put-text-property (point) lim 'syntax-table nil) - (search-forward-regexp c-awk-harmless-lines+-here-re nil t) ; skip harmless lines. - + (c-clear-char-properties (point) lim 'syntax-table) ;; Once round the next loop for each string, regexp, or div sign - (while (< (point) lim) + (while (progn + ;; Skip any "harmless" lines before the next tricky one. + (if (search-forward-regexp c-awk-harmless-lines+-here-re nil t) + (setq anchor-state-/div nil)) + (< (point) lim)) (setq anchor (point)) (search-forward-regexp c-awk-harmless-string*-here-re nil t) ;; We are now looking at either a " or a /. @@ -713,11 +776,7 @@ (setq anchor-state-/div (if (looking-at "_?\"") (c-awk-syntax-tablify-string) - (c-awk-syntax-tablify-/ anchor anchor-state-/div))) - - ;; Skip any further "harmless" lines before the next tricky one. - (if (search-forward-regexp c-awk-harmless-lines+-here-re nil t) - (setq anchor-state-/div nil))) + (c-awk-syntax-tablify-/ anchor anchor-state-/div)))) nil)) @@ -734,6 +793,8 @@ ;; This function is called exclusively from the before-change-functions hook. ;; It does two things: Finds the end of the (logical) line on which END lies, ;; and clears c-awk-NL-prop text properties from this point onwards. +;; +;; This function might do hidden buffer changes. (save-restriction (save-excursion (setq c-awk-old-EOLL (c-awk-end-of-logical-line end)) @@ -745,6 +806,8 @@ ;; This is the end of the logical line on which the change happened, either ;; as it was before the change, or as it is now, which ever is later. ;; N.B. point is left undefined. + ;; + ;; This function might do hidden buffer changes. (max (+ (- c-awk-old-EOLL old-len) (- end beg)) (c-awk-end-of-logical-line end))) @@ -754,6 +817,8 @@ ;; changed region. However, if font-lock is enabled, this function does ;; nothing, since an enabled font-lock after-change function will always do ;; this. +;; +;; This function might do hidden buffer changes. (unless (and (boundp 'font-lock-mode) font-lock-mode) (save-restriction (save-excursion @@ -786,10 +851,14 @@ (c-awk-advise-fl-for-awk-region lazy-lock-defer-rest-after-change) (c-awk-advise-fl-for-awk-region lazy-lock-defer-line-after-change) -;; ACM 2002/9/29. Functions for C-M-a and C-M-e + +;; ACM 2002/9/29. Movement functions, e.g. for C-M-a and C-M-e +;; The following three regexps differ from those earlier on in cc-awk.el in +;; that they assume the syntax-table properties have been set. They are thus +;; not useful for code which sets these properties. (defconst c-awk-terminated-regexp-or-string-here-re "\\=\\s\"\\S\"*\\s\"") -;; Matches a terminated string/regexp (utilising syntax-table properties). +;; Matches a terminated string/regexp. (defconst c-awk-unterminated-regexp-or-string-here-re "\\=\\s|\\S|*$") ;; Matches an unterminated string/regexp, NOT including the eol at the end. @@ -798,6 +867,21 @@ (concat "\\([^{;#/\"\\\\\n\r]\\|" c-awk-esc-pair-re "\\)*")) ;; Matches any "harmless" character in a pattern or an escaped character pair. +(defun c-awk-at-statement-end-p () + ;; Point is not inside a comment or string. Is it AT the end of a + ;; statement? This means immediately after the last non-ws character of the + ;; statement. The caller is responsible for widening the buffer, if + ;; appropriate. + (and (not (bobp)) + (save-excursion + (backward-char) + (or (looking-at "[};]") + (and (memq (c-awk-get-NL-prop-cur-line) '(?\$ ?\\)) + (looking-at + (eval-when-compile + (concat "[^ \t\n\r\\]" c-awk-escaped-nls*-with-space* + "[#\n\r]")))))))) + (defun c-awk-beginning-of-defun (&optional arg) "Move backward to the beginning of an AWK \"defun\". With ARG, do it that many times. Negative arg -N means move forward to Nth following beginning of @@ -807,7 +891,10 @@ of a defun is recognized as code starting at column zero which is neither a closing brace nor a comment nor a continuation of the previous line. Unlike in some other modes, having an opening brace at column 0 is neither necessary -nor helpful." +nor helpful. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." (interactive "p") (save-match-data (c-save-buffer-state ; ensures the buffer is writable. @@ -820,14 +907,14 @@ ;; is genuinely a beginning-of-defun. (while (and (setq found (search-backward-regexp "^[^#} \t\n\r]" (point-min) 'stop-at-limit)) - (not (memq (c-awk-get-NL-prop-prev-line) '(?\; ?\#))))) + (not (memq (c-awk-get-NL-prop-prev-line) '(?\$ ?\} ?\#))))) (setq arg (1- arg))) ;; The same for a -ve arg. (if (not (eq (point) (point-max))) (forward-char 1)) (while (and found (< arg 0) (not (eq (point) (point-max)))) ; The same for -ve arg. (while (and (setq found (search-forward-regexp "^[^#} \t\n\r]" (point-max) 'stop-at-limit)) - (not (memq (c-awk-get-NL-prop-prev-line) '(?\; ?\#))))) + (not (memq (c-awk-get-NL-prop-prev-line) '(?\$ ?\} ?\#))))) (setq arg (1+ arg))) (if found (goto-char (match-beginning 0)))) (eq arg 0))))) @@ -838,6 +925,8 @@ ;; comment. Typically, we stop at the { which denotes the corresponding AWK ;; action/function body. Otherwise we stop at the EOL (or ;) marking the ;; absence of an explicit action. + ;; + ;; This function might do hidden buffer changes. (while (progn (search-forward-regexp c-awk-harmless-pattern-characters*) @@ -855,6 +944,8 @@ (defun c-awk-end-of-defun1 () ;; point is at the start of a "defun". Move to its end. Return end position. + ;; + ;; This function might do hidden buffer changes. (c-awk-forward-awk-pattern) (cond ((looking-at "{") (goto-char (scan-sexps (point) 1))) @@ -866,6 +957,8 @@ (defun c-awk-beginning-of-defun-p () ;; Are we already at the beginning of a defun? (i.e. at code in column 0 ;; which isn't a }, and isn't a continuation line of any sort. + ;; + ;; This function might do hidden buffer changes. (and (looking-at "^[^#} \t\n\r]") (not (c-awk-prev-line-incomplete-p)))) @@ -875,7 +968,10 @@ An end of a defun occurs right after the closing brace that matches the opening brace at its start, or immediately after the AWK pattern when there is -no explicit action; see function `c-awk-beginning-of-defun'." +no explicit action; see function `c-awk-beginning-of-defun'. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." (interactive "p") (or arg (setq arg 1)) (save-match-data @@ -911,6 +1007,7 @@ (< arg 0))) (goto-char (min start-point end-point))))))) + (cc-provide 'cc-awk) ; Changed from 'awk-mode, ACM 2002/5/21 ;;; arch-tag: c4836289-3aa4-4a59-9934-9ccc2bacccf3
--- a/lisp/progmodes/cc-bytecomp.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/progmodes/cc-bytecomp.el Sat Dec 10 21:18:28 2005 +0000 @@ -1,7 +1,7 @@ ;;; cc-bytecomp.el --- compile time setup for proper compilation -;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 -;; Free Software Foundation, Inc. +;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, +;; Inc. ;; Author: Martin Stjernholm ;; Maintainer: bug-cc-mode@gnu.org @@ -22,7 +22,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to +;; along with this program; see the file COPYING. If not, write to ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA.
--- a/lisp/progmodes/cc-cmds.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/progmodes/cc-cmds.el Sat Dec 10 21:18:28 2005 +0000 @@ -1,6 +1,7 @@ ;;; cc-cmds.el --- user level commands for CC Mode -;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, Inc. +;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, +;; Inc. ;; Authors: 1998- Martin Stjernholm ;; 1992-1999 Barry A. Warsaw @@ -24,7 +25,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to +;; along with this program; see the file COPYING. If not, write to ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. @@ -45,12 +46,11 @@ (cc-require 'cc-engine) ;; Silence the compiler. -(cc-bytecomp-defvar delete-key-deletes-forward) ; XEmacs 20+ -(cc-bytecomp-defun delete-forward-p) ; XEmacs 21+ -(cc-bytecomp-obsolete-fun insert-and-inherit) ; Marked obsolete in XEmacs 19 +(cc-bytecomp-defun delete-forward-p) ; XEmacs (cc-bytecomp-defvar filladapt-mode) ; c-fill-paragraph contains a kludge ; which looks at this. - +(cc-bytecomp-defun c-forward-subword) +(cc-bytecomp-defun c-backward-subword) (defvar c-fix-backslashes t) @@ -64,8 +64,6 @@ is otherwise empty \(ignoring any line continuation backslash), but that's not done if IGNORE-POINT-POS is non-nil. Returns the amount of indentation change \(in columns)." - ;; - ;; This function does not do any hidden buffer changes. (let ((line-cont-backslash (save-excursion (end-of-line) @@ -134,13 +132,11 @@ shift-amt)) (defun c-newline-and-indent (&optional newline-arg) - "Inserts a newline and indents the new line. + "Insert a newline and indent the new line. This function fixes line continuation backslashes if inside a macro, and takes care to set the indentation before calling `indent-according-to-mode', so that lineup functions like `c-lineup-dont-change' works better." - ;; - ;; This function does not do any hidden buffer changes. ;; TODO: Backslashes before eol in comments and literals aren't ;; kept intact. @@ -221,14 +217,30 @@ (c-save-buffer-state nil (c-guess-basic-syntax))))) (if (not (consp arg)) - (message "syntactic analysis: %s" syntax) + (let (elem pos ols) + (message "Syntactic analysis: %s" syntax) + (unwind-protect + (progn + (while syntax + (setq elem (pop syntax)) + (when (setq pos (c-langelem-pos elem)) + (push (c-put-overlay pos (1+ pos) + 'face 'highlight) + ols)) + (when (setq pos (c-langelem-2nd-pos elem)) + (push (c-put-overlay pos (1+ pos) + 'face 'secondary-selection) + ols))) + (sit-for 10)) + (while ols + (c-delete-overlay (pop ols))))) (indent-for-comment) (insert-and-inherit (format "%s" syntax)) )) (c-keep-region-active)) (defun c-syntactic-information-on-region (from to) - "Inserts a comment with the syntactic analysis on every line in the region." + "Insert a comment with the syntactic analysis on every line in the region." (interactive "*r") (save-excursion (save-restriction @@ -239,6 +251,23 @@ (forward-line))))) +(defun c-update-modeline () + (let ((fmt (format "/%s%s%s%s" + (if c-electric-flag "l" "") + (if (and c-electric-flag c-auto-newline) + "a" "") + (if c-hungry-delete-key "h" "") + (if (and + ;; cc-subword might not be loaded. + (boundp 'c-subword-mode) + (symbol-value 'c-subword-mode)) + "w" + "")))) + (setq c-submode-indicators + (if (> (length fmt) 1) + fmt)) + (force-mode-line-update))) + (defun c-toggle-syntactic-indentation (&optional arg) "Toggle syntactic indentation. Optional numeric ARG, if supplied, turns on syntactic indentation when @@ -249,12 +278,12 @@ functions and the electric keys indent according to the syntactic context keys, when applicable. -When it's turned off, the electric keys does no reindentation, the -indentation functions indents every new line to the same level as the -previous nonempty line, and \\[c-indent-command] adjusts the -indentation in seps specified `c-basic-offset'. The indentation style -has no effect in this mode, nor any of the indentation associated -variables, e.g. `c-special-indent-hook'. +When it's turned off, the electric keys don't reindent, the indentation +functions indents every new line to the same level as the previous +nonempty line, and \\[c-indent-command] adjusts the indentation in steps +specified by `c-basic-offset'. The indentation style has no effect in +this mode, nor any of the indentation associated variables, +e.g. `c-special-indent-hook'. This command sets the variable `c-syntactic-indentation'." (interactive "P") @@ -262,30 +291,36 @@ (c-calculate-state arg c-syntactic-indentation)) (c-keep-region-active)) -(defun c-toggle-auto-state (&optional arg) +(defun c-toggle-auto-newline (&optional arg) "Toggle auto-newline feature. Optional numeric ARG, if supplied, turns on auto-newline when positive, turns it off when negative, and just toggles it when zero or left out. -When the auto-newline feature is enabled (as evidenced by the `/a' or -`/ah' on the modeline after the mode name) newlines are automatically -inserted after special characters such as brace, comma, semi-colon, -and colon." +Turning on auto-newline automatically enables electric indentation. + +When the auto-newline feature is enabled (indicated by \"/la\" on the +modeline after the mode name) newlines are automatically inserted +after special characters such as brace, comma, semi-colon, and colon." (interactive "P") - (setq c-auto-newline (c-calculate-state arg c-auto-newline)) + (setq c-auto-newline + (c-calculate-state arg (and c-auto-newline c-electric-flag))) + (if c-auto-newline (setq c-electric-flag t)) (c-update-modeline) (c-keep-region-active)) +(defalias 'c-toggle-auto-state 'c-toggle-auto-newline) +(make-obsolete 'c-toggle-auto-state 'c-toggle-auto-newline) + (defun c-toggle-hungry-state (&optional arg) "Toggle hungry-delete-key feature. Optional numeric ARG, if supplied, turns on hungry-delete when positive, turns it off when negative, and just toggles it when zero or left out. -When the hungry-delete-key feature is enabled (as evidenced by the -`/h' or `/ah' on the modeline after the mode name) the delete key -gobbles all preceding whitespace in one fell swoop." +When the hungry-delete-key feature is enabled (indicated by \"/h\" on +the modeline after the mode name) the delete key gobbles all preceding +whitespace in one fell swoop." (interactive "P") (setq c-hungry-delete-key (c-calculate-state arg c-hungry-delete-key)) (c-update-modeline) @@ -297,27 +332,38 @@ hungry-delete when positive, turns them off when negative, and just toggles them when zero or left out. -See `c-toggle-auto-state' and `c-toggle-hungry-state' for details." +See `c-toggle-auto-newline' and `c-toggle-hungry-state' for details." (interactive "P") (setq c-auto-newline (c-calculate-state arg c-auto-newline)) (setq c-hungry-delete-key (c-calculate-state arg c-hungry-delete-key)) (c-update-modeline) (c-keep-region-active)) +(defun c-toggle-electric-state (&optional arg) + "Toggle the electric indentation feature. +Optional numeric ARG, if supplied, turns on electric indentation when +positive, turns it off when negative, and just toggles it when zero or +left out." + (interactive "P") + (setq c-electric-flag (c-calculate-state arg c-electric-flag)) + (c-update-modeline) + (c-keep-region-active)) + ;; Electric keys (defun c-electric-backspace (arg) "Delete the preceding character or whitespace. -If `c-hungry-delete-key' is non-nil, as evidenced by the \"/h\" or -\"/ah\" string on the mode line, then all preceding whitespace is -consumed. If however a prefix argument is supplied, or -`c-hungry-delete-key' is nil, or point is inside a literal then the -function in the variable `c-backspace-function' is called." +If `c-hungry-delete-key' is non-nil (indicated by \"/h\" on the mode +line) then all preceding whitespace is consumed. If however a prefix +argument is supplied, or `c-hungry-delete-key' is nil, or point is +inside a literal then the function in the variable +`c-backspace-function' is called." (interactive "*P") - (if (or (not c-hungry-delete-key) - arg - (c-in-literal)) + (if (c-save-buffer-state () + (or (not c-hungry-delete-key) + arg + (c-in-literal))) (funcall c-backspace-function (prefix-numeric-value arg)) (c-hungry-backspace))) @@ -334,15 +380,16 @@ (defun c-electric-delete-forward (arg) "Delete the following character or whitespace. -If `c-hungry-delete-key' is non-nil, as evidenced by the \"/h\" or -\"/ah\" string on the mode line, then all following whitespace is -consumed. If however a prefix argument is supplied, or -`c-hungry-delete-key' is nil, or point is inside a literal then the -function in the variable `c-delete-function' is called." +If `c-hungry-delete-key' is non-nil (indicated by \"/h\" on the mode +line) then all following whitespace is consumed. If however a prefix +argument is supplied, or `c-hungry-delete-key' is nil, or point is +inside a literal then the function in the variable `c-delete-function' +is called." (interactive "*P") - (if (or (not c-hungry-delete-key) - arg - (c-in-literal)) + (if (c-save-buffer-state () + (or (not c-hungry-delete-key) + arg + (c-in-literal))) (funcall c-delete-function (prefix-numeric-value arg)) (c-hungry-delete-forward))) @@ -361,43 +408,54 @@ (defun c-electric-delete (arg) "Deletes preceding or following character or whitespace. This function either deletes forward as `c-electric-delete-forward' or -backward as `c-electric-backspace', depending on the configuration: - -If the function `delete-forward-p' is defined (XEmacs 21) and returns -non-nil, it deletes forward. Else, if the variable -`delete-key-deletes-forward' is defined (XEmacs 20) and is set to -non-nil, it deletes forward. Otherwise it deletes backward. - -Note: This is the way in XEmacs 20 and later to choose the correct -action for the [delete] key, whichever key that means. In other -flavors this function isn't used, instead it's left to the user to -bind [delete] to either \\[c-electric-delete-forward] or \\[c-electric-backspace] as appropriate -\(the keymap `function-key-map' is useful for that). Emacs 21 handles -that automatically, though." +backward as `c-electric-backspace', depending on the configuration: If +the function `delete-forward-p' is defined and returns non-nil, it +deletes forward. Otherwise it deletes backward. + +Note: This is the way in XEmacs to choose the correct action for the +\[delete] key, whichever key that means. Other flavors don't use this +function to control that." (interactive "*P") - (if (or (and (fboundp 'delete-forward-p) ;XEmacs 21 - (delete-forward-p)) - (and (boundp 'delete-key-deletes-forward) ;XEmacs 20 - delete-key-deletes-forward)) + (if (and (fboundp 'delete-forward-p) + (delete-forward-p)) (c-electric-delete-forward arg) (c-electric-backspace arg))) +;; This function is only used in XEmacs. +(defun c-hungry-delete () + "Delete a non-whitespace char, or all whitespace up to the next non-whitespace char. +The direction of deletion depends on the configuration: If the +function `delete-forward-p' is defined and returns non-nil, it deletes +forward using `c-hungry-delete-forward'. Otherwise it deletes +backward using `c-hungry-backspace'. + +Note: This is the way in XEmacs to choose the correct action for the +\[delete] key, whichever key that means. Other flavors don't use this +function to control that." + (interactive) + (if (and (fboundp 'delete-forward-p) + (delete-forward-p)) + (c-hungry-delete-forward) + (c-hungry-backspace))) + (defun c-electric-pound (arg) - "Electric pound (`#') insertion. -Inserts a `#' character specially depending on the variable -`c-electric-pound-behavior'. If a numeric ARG is supplied, or if -point is inside a literal or a macro, nothing special happens." + "Insert a \"#\". +If `c-electric-flag' is set, handle it specially according to the variable +`c-electric-pound-behavior'. If a numeric ARG is supplied, or if point is +inside a literal or a macro, nothing special happens." (interactive "*P") - (if (or arg - (not (memq 'alignleft c-electric-pound-behavior)) - (save-excursion - (skip-chars-backward " \t") - (not (bolp))) - (save-excursion - (and (= (forward-line -1) 0) - (progn (end-of-line) - (eq (char-before) ?\\)))) - (c-in-literal)) + (if (c-save-buffer-state () + (or arg + (not c-electric-flag) + (not (memq 'alignleft c-electric-pound-behavior)) + (save-excursion + (skip-chars-backward " \t") + (not (bolp))) + (save-excursion + (and (= (forward-line -1) 0) + (progn (end-of-line) + (eq (char-before) ?\\)))) + (c-in-literal))) ;; do nothing special (self-insert-command (prefix-numeric-value arg)) ;; place the pound character at the left edge @@ -410,243 +468,332 @@ (goto-char (- (point-max) pos))) ))) +(defun c-point-syntax () + ;; Return the syntactic context of the construct at point. (This is NOT + ;; nec. the same as the s.c. of the line point is on). N.B. This won't work + ;; between the `#' of a cpp thing and what follows (see c-opt-cpp-prefix). + (c-save-buffer-state (;; shut this up too + (c-echo-syntactic-information-p nil) + syntax) + (c-tentative-buffer-changes + ;; insert a newline to isolate the construct at point for syntactic + ;; analysis. + (insert-char ?\n 1) + ;; In AWK (etc.) or in a macro, make sure this CR hasn't changed + ;; the syntax. (There might already be an escaped NL there.) + (when (or (c-at-vsemi-p (1- (point))) + (let ((pt (point))) + (save-excursion + (backward-char) + (and (c-beginning-of-macro) + (progn (c-end-of-macro) + (< (point) pt)))))) + (backward-char) + (insert-char ?\\ 1) + (forward-char)) + (let ((c-syntactic-indentation-in-macros t) + (c-auto-newline-analysis t)) + ;; Turn on syntactic macro analysis to help with auto + ;; newlines only. + (setq syntax (c-guess-basic-syntax)) + nil)) + syntax)) + +(defun c-brace-newlines (syntax) + ;; A brace stands at point. SYNTAX is the syntactic context of this brace + ;; (not necessarily the same as the S.C. of the line it is on). Return + ;; NEWLINES, the list containing some combination of the symbols `before' + ;; and `after' saying where newlines should be inserted. + (c-save-buffer-state + ((syms + ;; This is the list of brace syntactic symbols that can hang. + ;; If any new ones are added to c-offsets-alist, they should be + ;; added here as well. + '(class-open class-close defun-open defun-close + inline-open inline-close + brace-list-open brace-list-close + brace-list-intro brace-entry-open + block-open block-close + substatement-open statement-case-open + extern-lang-open extern-lang-close + namespace-open namespace-close + module-open module-close + composition-open composition-close + inexpr-class-open inexpr-class-close + ;; `statement-cont' is here for the case with a brace + ;; list opener inside a statement. C.f. CASE B.2 in + ;; `c-guess-continued-construct'. + statement-cont)) + ;; shut this up too + (c-echo-syntactic-information-p nil) + symb-newlines) ; e.g. (substatement-open . (after)) + + (setq symb-newlines + ;; Do not try to insert newlines around a special + ;; (Pike-style) brace list. + (if (and c-special-brace-lists + (save-excursion + (c-safe (if (= (char-before) ?{) + (forward-char -1) + (c-forward-sexp -1)) + (c-looking-at-special-brace-list)))) + nil + ;; Seek the matching entry in c-hanging-braces-alist. + (or (c-lookup-lists + syms + ;; Substitute inexpr-class and class-open or + ;; class-close with inexpr-class-open or + ;; inexpr-class-close. + (if (assq 'inexpr-class syntax) + (cond ((assq 'class-open syntax) + '((inexpr-class-open))) + ((assq 'class-close syntax) + '((inexpr-class-close))) + (t syntax)) + syntax) + c-hanging-braces-alist) + '(ignore before after)))) ; Default, when not in c-h-b-l. + + ;; If syntax is a function symbol, then call it using the + ;; defined semantics. + (if (and (not (consp (cdr symb-newlines))) + (functionp (cdr symb-newlines))) + (let ((c-syntactic-context syntax)) + (funcall (cdr symb-newlines) + (car symb-newlines) + (point))) + (cdr symb-newlines)))) + +(defun c-try-one-liner () + ;; Point is just after a newly inserted }. If the non-whitespace + ;; content of the braces is a single line of code, compact the whole + ;; construct to a single line, if this line isn't too long. The Right + ;; Thing is done with comments. + ;; + ;; Point will be left after the }, regardless of whether the clean-up is + ;; done. Return NON-NIL if the clean-up happened, NIL if it didn't. + + (let ((here (point)) + (pos (- (point-max) (point))) + mbeg1 mend1 mbeg4 mend4 + eol-col cmnt-pos cmnt-col cmnt-gap) + + (when + (save-excursion + (save-restriction + ;; Avoid backtracking over a very large block. The one we + ;; deal with here can never be more than three lines. + (narrow-to-region (save-excursion + (forward-line -2) + (point)) + (point)) + (and (c-safe (c-backward-sexp)) + (progn + (forward-char) + (narrow-to-region (point) (1- here)) ; innards of {.} + (looking-at + (cc-eval-when-compile + (concat + "\\(" ; (match-beginning 1) + "[ \t]*\\([\r\n][ \t]*\\)?" ; WS with opt. NL + "\\)" ; (match-end 1) + "[^ \t\r\n]+\\([ \t]+[^ \t\r\n]+\\)*" ; non-WS + "\\(" ; (match-beginning 4) + "[ \t]*\\([\r\n][ \t]*\\)?" ; WS with opt. NL + "\\)\\'"))))))) ; (match-end 4) at EOB. + + (if (c-tentative-buffer-changes + (setq mbeg1 (match-beginning 1) mend1 (match-end 1) + mbeg4 (match-beginning 4) mend4 (match-end 4)) + (backward-char) ; back over the `}' + (save-excursion + (setq cmnt-pos (and (c-backward-single-comment) + (- (point) (- mend1 mbeg1))))) + (delete-region mbeg4 mend4) + (delete-region mbeg1 mend1) + (setq eol-col (save-excursion (end-of-line) (current-column))) + + ;; Necessary to put the closing brace before any line + ;; oriented comment to keep it syntactically significant. + ;; This isn't necessary for block comments, but the result + ;; looks nicer anyway. + (when cmnt-pos + (delete-char 1) ; the `}' has blundered into a comment + (goto-char cmnt-pos) + (setq cmnt-col (1+ (current-column))) + (setq cmnt-pos (1+ cmnt-pos)) ; we're inserting a `}' + (c-skip-ws-backward) + (insert-char ?\} 1) ; reinsert the `}' before the comment. + (setq cmnt-gap (- cmnt-col (current-column))) + (when (zerop cmnt-gap) + (insert-char ?\ 1) ; Put a space before a bare comment. + (setq cmnt-gap 1))) + + (or (null c-max-one-liner-length) + (zerop c-max-one-liner-length) + (<= eol-col c-max-one-liner-length) + ;; Can we trim space before comment to make the line fit? + (and cmnt-gap + (< (- eol-col cmnt-gap) c-max-one-liner-length) + (progn (goto-char cmnt-pos) + (backward-delete-char-untabify + (- eol-col c-max-one-liner-length)) + t)))) + (goto-char (- (point-max) pos)))))) + (defun c-electric-brace (arg) "Insert a brace. -If the auto-newline feature is turned on, as evidenced by the \"/a\" -or \"/ah\" string on the mode line, newlines are inserted before and -after braces based on the value of `c-hanging-braces-alist'. - -Also, the line is re-indented unless a numeric ARG is supplied, the -brace is inserted inside a literal, or `c-syntactic-indentation' is -nil. - -This function does various newline cleanups based on the value of -`c-cleanup-list'." +If `c-electric-flag' is non-nil, the brace is not inside a literal and a +numeric ARG hasn't been supplied, the command performs several electric +actions: + +\(a) If the auto-newline feature is turned on (indicated by \"/ln\" on +the mode line) newlines are inserted before and after the brace as +directed by the settings in `c-hanging-braces-alist'. + +\(b) Any auto-newlines are indented. The original line is also +reindented unless `c-syntactic-indentation' is nil. + +\(c) If auto-newline is turned on, various newline cleanups based on the +settings of `c-cleanup-list' are done." + (interactive "*P") - (let* ((safepos (c-safe-position (point) (c-parse-state))) - (literal (c-in-literal safepos)) - ;; We want to inhibit blinking the paren since this will be - ;; most disruptive. We'll blink it ourselves later on. - (old-blink-paren blink-paren-function) - blink-paren-function) - (cond - ((or literal arg) - (self-insert-command (prefix-numeric-value arg))) - ((not (looking-at "[ \t]*\\\\?$")) - (self-insert-command (prefix-numeric-value arg)) - (if c-syntactic-indentation - (indent-according-to-mode))) - (t - (let* ((syms - ;; This is the list of brace syntactic symbols that can - ;; hang. If any new ones are added to c-offsets-alist, - ;; they should be added here as well. - '(class-open class-close defun-open defun-close - inline-open inline-close - brace-list-open brace-list-close - brace-list-intro brace-entry-open - block-open block-close - substatement-open statement-case-open - extern-lang-open extern-lang-close - namespace-open namespace-close - module-open module-close - composition-open composition-close - inexpr-class-open inexpr-class-close - ;; `statement-cont' is here for the case with a brace - ;; list opener inside a statement. C.f. CASE B.2 in - ;; `c-guess-continued-construct'. - statement-cont)) - (insertion-point (point)) - (preserve-p (and (not (bobp)) - (eq ?\ (char-syntax (char-before))))) - ;; shut this up too - (c-echo-syntactic-information-p nil) - delete-temp-newline syntax newlines) - ;; only insert a newline if there is non-whitespace behind us - (when (save-excursion - (skip-chars-backward " \t") - (not (bolp))) - (c-newline-and-indent) - ;; Set markers around the newline and indention inserted - ;; above. We insert the start marker here and not before - ;; the call to kludge around a misfeature in expand-abbrev: - ;; If the line contains e.g. "else" then expand-abbrev will - ;; be called when c-newline-and-indent inserts the newline. - ;; That function first removes the abbrev "else" and then - ;; inserts the expansion, which is an identical "else" in - ;; this case. So the marker that we put after "else" would - ;; end up before it. - (setq delete-temp-newline - (cons (save-excursion - (end-of-line 0) - (if (eq (char-before) ?\\) - ;; Ignore a line continuation. - (backward-char)) - (skip-chars-backward " \t") - (copy-marker (point) t)) - (point-marker)))) - (unwind-protect - (progn - (if (eq last-command-char ?{) - (setq c-state-cache (cons (point) c-state-cache))) - (self-insert-command (prefix-numeric-value arg)) - (c-save-buffer-state ((c-syntactic-indentation-in-macros t) - (c-auto-newline-analysis t)) - ;; Turn on syntactic macro analysis to help with auto - ;; newlines only. - (setq syntax (c-guess-basic-syntax))) - (setq newlines - (and - c-auto-newline - (or (c-lookup-lists - syms - ;; Substitute inexpr-class and class-open or - ;; class-close with inexpr-class-open or - ;; inexpr-class-close. - (if (assq 'inexpr-class syntax) - (cond ((assq 'class-open syntax) - '((inexpr-class-open))) - ((assq 'class-close syntax) - '((inexpr-class-close))) - (t syntax)) - syntax) - c-hanging-braces-alist) - '(ignore before after)))) - ;; Do not try to insert newlines around a special - ;; (Pike-style) brace list. - (if (and c-special-brace-lists - (save-excursion - (c-save-buffer-state nil - (c-safe (if (= (char-before) ?{) - (forward-char -1) - (c-forward-sexp -1)) - (c-looking-at-special-brace-list))))) - (setq newlines nil)) - ;; If syntax is a function symbol, then call it using the - ;; defined semantics. - (if (and (not (consp (cdr newlines))) - (functionp (cdr newlines))) - (let ((c-syntactic-context syntax)) - (setq newlines - (funcall (cdr newlines) - (car newlines) - insertion-point)))) - ;; does a newline go before the open brace? - (when (memq 'before newlines) - ;; we leave the newline we've put in there before, - ;; but we need to re-indent the line above - (when delete-temp-newline - (set-marker (car delete-temp-newline) nil) - (set-marker (cdr delete-temp-newline) nil) - (setq delete-temp-newline nil)) - (when c-syntactic-indentation - (let ((pos (- (point-max) (point))) - (here (point))) - (forward-line -1) - (indent-according-to-mode) - (goto-char (- (point-max) pos)) - ;; if the buffer has changed due to the - ;; indentation, we need to recalculate syntax for - ;; the current line. - (if (/= (point) here) - (c-save-buffer-state - ((c-syntactic-indentation-in-macros t) - (c-auto-newline-analysis t)) - ;; Turn on syntactic macro analysis to help - ;; with auto newlines only. - (setq syntax (c-guess-basic-syntax)))))))) - ;; must remove the newline we just stuck in (if we really did it) - (when delete-temp-newline - (save-excursion - (delete-region (car delete-temp-newline) - (cdr delete-temp-newline)) - (goto-char (car delete-temp-newline)) - (set-marker (car delete-temp-newline) nil) - (set-marker (cdr delete-temp-newline) nil) - ;; if there is whitespace before point, then preserve - ;; at least one space. - (just-one-space) - (if (not preserve-p) - (delete-char -1))))) - (if (not (memq 'before newlines)) - ;; since we're hanging the brace, we need to recalculate - ;; syntax. - (c-save-buffer-state ((c-syntactic-indentation-in-macros t) - (c-auto-newline-analysis t)) - ;; Turn on syntactic macro analysis to help with auto - ;; newlines only. - (setq syntax (c-guess-basic-syntax)))) - (when c-syntactic-indentation - ;; Now adjust the line's indentation. Don't update the state - ;; cache since c-guess-basic-syntax isn't called when - ;; c-syntactic-context is set. - (let* ((c-syntactic-context syntax)) - (indent-according-to-mode))) - ;; Do all appropriate clean ups - (let ((here (point)) - (pos (- (point-max) (point))) - mbeg mend tmp) - ;; clean up empty defun braces - (if (and c-auto-newline - (memq 'empty-defun-braces c-cleanup-list) - (eq last-command-char ?\}) - (c-intersect-lists '(defun-close class-close inline-close) - syntax) - (progn - (forward-char -1) - (c-skip-ws-backward) - (eq (char-before) ?\{)) - ;; make sure matching open brace isn't in a comment - (not (c-in-literal))) - (delete-region (point) (1- here))) - ;; clean up brace-else-brace and brace-elseif-brace - (when (and c-auto-newline - (eq last-command-char ?\{)) - (cond - ((and (memq 'brace-else-brace c-cleanup-list) - (re-search-backward - (concat "}" - "\\([ \t\n]\\|\\\\\n\\)*" - "else" - "\\([ \t\n]\\|\\\\\n\\)*" - "{") - nil t) - (progn - (setq mbeg (match-beginning 0) - mend (match-end 0)) - (eq (match-end 0) here))) - (delete-region mbeg mend) - (insert-and-inherit "} else {")) - ((and (memq 'brace-elseif-brace c-cleanup-list) - (progn - (goto-char (1- here)) - (setq mend (point)) - (c-skip-ws-backward) - (setq mbeg (point)) - (eq (char-before) ?\))) - (zerop (c-save-buffer-state nil (c-backward-token-2 1 t))) - (eq (char-after) ?\() - (progn - (setq tmp (point)) - (re-search-backward - (concat "}" - "\\([ \t\n]\\|\\\\\n\\)*" - "else" - "\\([ \t\n]\\|\\\\\n\\)+" - "if" - "\\([ \t\n]\\|\\\\\n\\)*") - nil t)) - (eq (match-end 0) tmp)) - (delete-region mbeg mend) - (goto-char mbeg) - (insert ?\ )))) - (goto-char (- (point-max) pos)) - ) - ;; does a newline go after the brace? - (if (memq 'after newlines) - (c-newline-and-indent)) - ))) + (let (safepos literal + ;; We want to inhibit blinking the paren since this would be + ;; most disruptive. We'll blink it ourselves later on. + (old-blink-paren blink-paren-function) + blink-paren-function) + + (c-save-buffer-state () + (setq safepos (c-safe-position (point) (c-parse-state)) + literal (c-in-literal safepos))) + + ;; Insert the brace. Note that expand-abbrev might reindent + ;; the line here if there's a preceding "else" or something. + (self-insert-command (prefix-numeric-value arg)) + + (when (and c-electric-flag (not literal) (not arg)) + (if (not (looking-at "[ \t]*\\\\?$")) + (if c-syntactic-indentation + (indent-according-to-mode)) + + (let ( ;; shut this up too + (c-echo-syntactic-information-p nil) + newlines + ln-syntax br-syntax syntax) ; Syntactic context of the original line, + ; of the brace itself, of the line the brace ends up on. + (c-save-buffer-state ((c-syntactic-indentation-in-macros t) + (c-auto-newline-analysis t)) + (setq ln-syntax (c-guess-basic-syntax))) + (if c-syntactic-indentation + (c-indent-line ln-syntax)) + + (when c-auto-newline + (backward-char) + (setq br-syntax (c-point-syntax) + newlines (c-brace-newlines br-syntax)) + + ;; Insert the BEFORE newline, if wanted, and reindent the newline. + (if (and (memq 'before newlines) + (> (current-column) (current-indentation))) + (if c-syntactic-indentation + ;; Only a plain newline for now - it's indented + ;; after the cleanups when the line has its final + ;; appearance. + (newline) + (c-newline-and-indent))) + (forward-char) + + ;; `syntax' is the syntactic context of the line which ends up + ;; with the brace on it. + (setq syntax (if (memq 'before newlines) br-syntax ln-syntax)) + + ;; Do all appropriate clean ups + (let ((here (point)) + (pos (- (point-max) (point))) + mbeg mend + ) + + ;; `}': clean up empty defun braces + (when (c-save-buffer-state () + (and (memq 'empty-defun-braces c-cleanup-list) + (eq last-command-char ?\}) + (c-intersect-lists '(defun-close class-close inline-close) + syntax) + (progn + (forward-char -1) + (c-skip-ws-backward) + (eq (char-before) ?\{)) + ;; make sure matching open brace isn't in a comment + (not (c-in-literal)))) + (delete-region (point) (1- here)) + (setq here (- (point-max) pos))) + (goto-char here) + + ;; `}': compact to a one-liner defun? + (save-match-data + (when + (and (eq last-command-char ?\}) + (memq 'one-liner-defun c-cleanup-list) + (c-intersect-lists '(defun-close) syntax) + (c-try-one-liner)) + (setq here (- (point-max) pos)))) + + ;; `{': clean up brace-else-brace and brace-elseif-brace + (when (eq last-command-char ?\{) + (cond + ((and (memq 'brace-else-brace c-cleanup-list) + (re-search-backward + (concat "}" + "\\([ \t\n]\\|\\\\\n\\)*" + "else" + "\\([ \t\n]\\|\\\\\n\\)*" + "{" + "\\=") + nil t)) + (delete-region mbeg mend) + (insert-and-inherit "} else {")) + ((and (memq 'brace-elseif-brace c-cleanup-list) + (progn + (goto-char (1- here)) + (setq mend (point)) + (c-skip-ws-backward) + (setq mbeg (point)) + (eq (char-before) ?\))) + (zerop (c-save-buffer-state nil (c-backward-token-2 1 t))) + (eq (char-after) ?\() + ; (progn + ; (setq tmp (point)) + (re-search-backward + (concat "}" + "\\([ \t\n]\\|\\\\\n\\)*" + "else" + "\\([ \t\n]\\|\\\\\n\\)+" + "if" + "\\([ \t\n]\\|\\\\\n\\)*" + "\\=") + nil t);) + ;(eq (match-end 0) tmp); + ) + (delete-region mbeg mend) + (goto-char mbeg) + (insert ?\ )))) + + (goto-char (- (point-max) pos)) + + ;; Indent the line after the cleanups since it might + ;; very well indent differently due to them, e.g. if + ;; c-indent-one-line-block is used together with the + ;; one-liner-defun cleanup. + (when c-syntactic-indentation + (c-indent-line))) + + ;; does a newline go after the brace? + (if (memq 'after newlines) + (c-newline-and-indent)) + )))) + ;; blink the paren (and (eq last-command-char ?\}) (not executing-kbd-macro) @@ -659,332 +806,465 @@ (defun c-electric-slash (arg) "Insert a slash character. +If the slash is inserted immediately after the comment prefix in a c-style +comment, the comment might get closed by removing whitespace and possibly +inserting a \"*\". See the variable `c-cleanup-list'. + Indent the line as a comment, if: - 1. The slash is second of a `//' line oriented comment introducing + 1. The slash is second of a \"//\" line oriented comment introducing token and we are on a comment-only-line, or - 2. The slash is part of a `*/' token that closes a block oriented + 2. The slash is part of a \"*/\" token that closes a block oriented comment. If a numeric ARG is supplied, point is inside a literal, or -`c-syntactic-indentation' is nil, indentation is inhibited." +`c-syntactic-indentation' is nil or `c-electric-flag' is nil, indentation +is inhibited." (interactive "*P") - (let* ((ch (char-before)) - (literal (c-in-literal)) - (indentp (and c-syntactic-indentation - (not arg) + (let ((literal (c-save-buffer-state () (c-in-literal))) + indentp + ;; shut this up + (c-echo-syntactic-information-p nil)) + + ;; comment-close-slash cleanup? This DOESN'T need `c-electric-flag' or + ;; `c-syntactic-indentation' set. + (when (and (not arg) + (eq literal 'c) + (memq 'comment-close-slash c-cleanup-list) + (eq last-command-char ?/) + ; (eq c-block-comment-ender "*/") ; C-style comments ALWAYS end in */ + (save-excursion + (back-to-indentation) + (looking-at (concat c-current-comment-prefix "[ \t]*$")))) + (end-of-line) + (delete-horizontal-space) + (or (eq (char-before) ?*) (insert-char ?* 1))) ; Do I need a t (retain sticky properties) here? + + (setq indentp (and (not arg) + c-syntactic-indentation + c-electric-flag (eq last-command-char ?/) - (or (and (eq ch ?/) - (not literal)) - (and (eq ch ?*) - literal)) - )) - ;; shut this up - (c-echo-syntactic-information-p nil)) + (eq (char-before) (if literal ?* ?/)))) (self-insert-command (prefix-numeric-value arg)) (if indentp (indent-according-to-mode)))) (defun c-electric-star (arg) "Insert a star character. -If the star is the second character of a C style comment introducing -construct, and we are on a comment-only-line, indent line as comment. -If a numeric ARG is supplied, point is inside a literal, or -`c-syntactic-indentation' is nil, indentation is inhibited." +If `c-electric-flag' and `c-syntactic-indentation' are both non-nil, and +the star is the second character of a C style comment starter on a +comment-only-line, indent the line as a comment. If a numeric ARG is +supplied, point is inside a literal, or `c-syntactic-indentation' is nil, +this indentation is inhibited." + (interactive "*P") (self-insert-command (prefix-numeric-value arg)) - ;; if we are in a literal, or if arg is given do not re-indent the + ;; if we are in a literal, or if arg is given do not reindent the ;; current line, unless this star introduces a comment-only line. - (if (and c-syntactic-indentation - (not arg) - (eq (c-in-literal) 'c) - (eq (char-before) ?*) - (save-excursion - (forward-char -1) - (skip-chars-backward "*") - (if (eq (char-before) ?/) - (forward-char -1)) - (skip-chars-backward " \t") - (bolp))) + (if (c-save-buffer-state () + (and c-syntactic-indentation + c-electric-flag + (not arg) + (eq (c-in-literal) 'c) + (eq (char-before) ?*) + (save-excursion + (forward-char -1) + (skip-chars-backward "*") + (if (eq (char-before) ?/) + (forward-char -1)) + (skip-chars-backward " \t") + (bolp)))) (let (c-echo-syntactic-information-p) ; shut this up (indent-according-to-mode)) )) (defun c-electric-semi&comma (arg) "Insert a comma or semicolon. -When the auto-newline feature is turned on, as evidenced by the \"/a\" -or \"/ah\" string on the mode line, a newline might be inserted. See -the variable `c-hanging-semi&comma-criteria' for how newline insertion -is determined. - -When a semicolon is inserted, the line is re-indented unless a numeric -arg is supplied, point is inside a literal, or -`c-syntactic-indentation' is nil. - -Based on the value of `c-cleanup-list', this function cleans up commas -following brace lists and semicolons following defuns." + +If `c-electric-flag' is non-nil, point isn't inside a literal and a +numeric ARG hasn't been supplied, the command performs several electric +actions: + +\(a) When the auto-newline feature is turned on (indicated by \"/ln\" on +the mode line) a newline might be inserted. See the variable +`c-hanging-semi&comma-criteria' for how newline insertion is determined. + +\(b) Any auto-newlines are indented. The original line is also +reindented unless `c-syntactic-indentation' is nil. + +\(c) If auto-newline is turned on, a comma following a brace list or a +semicolon following a defun might be cleaned up, depending on the +settings of `c-cleanup-list'." (interactive "*P") - (let* ((lim (c-most-enclosing-brace (c-parse-state))) - (literal (c-in-literal lim)) + (let* (lim literal c-syntactic-context (here (point)) ;; shut this up (c-echo-syntactic-information-p nil)) - (if (or literal arg) - (self-insert-command (prefix-numeric-value arg)) - ;; do some special stuff with the character - (self-insert-command (prefix-numeric-value arg)) - ;; do all cleanups and newline insertions if c-auto-newline is - ;; turned on - (if (or (not c-auto-newline) - (not (looking-at "[ \t]*\\\\?$"))) - (if c-syntactic-indentation - (indent-according-to-mode)) - ;; clean ups - (let ((pos (- (point-max) (point)))) - (if (and (or (and - (eq last-command-char ?,) - (memq 'list-close-comma c-cleanup-list)) - (and - (eq last-command-char ?\;) - (memq 'defun-close-semi c-cleanup-list))) - (progn - (forward-char -1) - (c-skip-ws-backward) - (eq (char-before) ?})) - ;; make sure matching open brace isn't in a comment - (not (c-in-literal lim))) - (delete-region (point) here)) - (goto-char (- (point-max) pos))) - ;; re-indent line - (if c-syntactic-indentation - (indent-according-to-mode)) - ;; check to see if a newline should be added - (let ((criteria c-hanging-semi&comma-criteria) - answer add-newline-p) - (while criteria - (setq answer (funcall (car criteria))) - ;; only nil value means continue checking - (if (not answer) - (setq criteria (cdr criteria)) - (setq criteria nil) - ;; only 'stop specifically says do not add a newline - (setq add-newline-p (not (eq answer 'stop))) - )) - (if add-newline-p - (c-newline-and-indent)) - ))))) + + (c-save-buffer-state () + (setq lim (c-most-enclosing-brace (c-parse-state)) + literal (c-in-literal lim))) + + (self-insert-command (prefix-numeric-value arg)) + + (if (and c-electric-flag (not literal) (not arg)) + ;; do all cleanups and newline insertions if c-auto-newline is on. + (if (or (not c-auto-newline) + (not (looking-at "[ \t]*\\\\?$"))) + (if c-syntactic-indentation + (c-indent-line)) + ;; clean ups: list-close-comma or defun-close-semi + (let ((pos (- (point-max) (point)))) + (if (c-save-buffer-state () + (and (or (and + (eq last-command-char ?,) + (memq 'list-close-comma c-cleanup-list)) + (and + (eq last-command-char ?\;) + (memq 'defun-close-semi c-cleanup-list))) + (progn + (forward-char -1) + (c-skip-ws-backward) + (eq (char-before) ?})) + ;; make sure matching open brace isn't in a comment + (not (c-in-literal lim)))) + (delete-region (point) here)) + (goto-char (- (point-max) pos))) + ;; reindent line + (when c-syntactic-indentation + (setq c-syntactic-context (c-guess-basic-syntax)) + (c-indent-line c-syntactic-context)) + ;; check to see if a newline should be added + (let ((criteria c-hanging-semi&comma-criteria) + answer add-newline-p) + (while criteria + (setq answer (funcall (car criteria))) + ;; only nil value means continue checking + (if (not answer) + (setq criteria (cdr criteria)) + (setq criteria nil) + ;; only 'stop specifically says do not add a newline + (setq add-newline-p (not (eq answer 'stop))) + )) + (if add-newline-p + (c-newline-and-indent)) + ))))) (defun c-electric-colon (arg) "Insert a colon. -If the auto-newline feature is turned on, as evidenced by the \"/a\" -or \"/ah\" string on the mode line, newlines are inserted before and -after colons based on the value of `c-hanging-colons-alist'. - -Also, the line is re-indented unless a numeric ARG is supplied, the -colon is inserted inside a literal, or `c-syntactic-indentation' is -nil. - -This function cleans up double colon scope operators based on the -value of `c-cleanup-list'." +If `c-electric-flag' is non-nil, the colon is not inside a literal and a +numeric ARG hasn't been supplied, the command performs several electric +actions: + +\(a) If the auto-newline feature is turned on (indicated by \"/ln\" on +the mode line) newlines are inserted before and after the colon based on +the settings in `c-hanging-colons-alist'. + +\(b) Any auto-newlines are indented. The original line is also +reindented unless `c-syntactic-indentation' is nil. + +\(c) If auto-newline is turned on, whitespace between two colons will be +\"cleaned up\" leaving a scope operator, if this action is set in +`c-cleanup-list'." + (interactive "*P") (let* ((bod (c-point 'bod)) - (literal (c-in-literal bod)) + (literal (c-save-buffer-state () (c-in-literal bod))) newlines is-scope-op ;; shut this up (c-echo-syntactic-information-p nil)) - (cond - ((or literal arg) - (self-insert-command (prefix-numeric-value arg))) - ((not (looking-at "[ \t]*\\\\?$")) - (self-insert-command (prefix-numeric-value arg)) - (if c-syntactic-indentation - (indent-according-to-mode))) - (t - ;; insert the colon, then do any specified cleanups - (self-insert-command (prefix-numeric-value arg)) - (let ((pos (- (point-max) (point))) - (here (point))) - (if (and c-auto-newline - (memq 'scope-operator c-cleanup-list) - (eq (char-before) ?:) - (progn - (forward-char -1) - (c-skip-ws-backward) - (eq (char-before) ?:)) - (not (c-in-literal)) - (not (eq (char-after (- (point) 2)) ?:))) - (progn - (delete-region (point) (1- here)) - (setq is-scope-op t))) - (goto-char (- (point-max) pos))) - ;; indent the current line if it's done syntactically. - (if c-syntactic-indentation - ;; Cannot use the same syntax analysis as we find below, - ;; since that's made with c-syntactic-indentation-in-macros - ;; always set to t. - (indent-according-to-mode)) - (c-save-buffer-state - ((c-syntactic-indentation-in-macros t) - (c-auto-newline-analysis t) - ;; Turn on syntactic macro analysis to help with auto newlines - ;; only. - (syntax (c-guess-basic-syntax)) - (elem syntax)) - ;; Translate substatement-label to label for this operation. - (while elem - (if (eq (car (car elem)) 'substatement-label) - (setcar (car elem) 'label)) - (setq elem (cdr elem))) - ;; some language elements can only be determined by checking - ;; the following line. Lets first look for ones that can be - ;; found when looking on the line with the colon - (setq newlines - (and c-auto-newline - (or (c-lookup-lists '(case-label label access-label) - syntax c-hanging-colons-alist) - (c-lookup-lists '(member-init-intro inher-intro) - (progn - (insert ?\n) - (unwind-protect - (c-guess-basic-syntax) - (delete-char -1))) - c-hanging-colons-alist))))) - ;; does a newline go before the colon? Watch out for already - ;; non-hung colons. However, we don't unhang them because that - ;; would be a cleanup (and anti-social). - (if (and (memq 'before newlines) - (not is-scope-op) - (save-excursion - (skip-chars-backward ": \t") - (not (bolp)))) - (let ((pos (- (point-max) (point)))) - (forward-char -1) - (c-newline-and-indent) - (goto-char (- (point-max) pos)))) - ;; does a newline go after the colon? - (if (and (memq 'after (cdr-safe newlines)) - (not is-scope-op)) - (c-newline-and-indent)) - )))) + (self-insert-command (prefix-numeric-value arg)) + ;; Any electric action? + (if (and c-electric-flag (not literal) (not arg)) + ;; Unless we're at EOL, only re-indentation happens. + (if (not (looking-at "[ \t]*\\\\?$")) + (if c-syntactic-indentation + (indent-according-to-mode)) + + ;; scope-operator clean-up? + (let ((pos (- (point-max) (point))) + (here (point))) + (if (c-save-buffer-state () ; Why do we need this? [ACM, 2003-03-12] + (and c-auto-newline + (memq 'scope-operator c-cleanup-list) + (eq (char-before) ?:) + (progn + (forward-char -1) + (c-skip-ws-backward) + (eq (char-before) ?:)) + (not (c-in-literal)) + (not (eq (char-after (- (point) 2)) ?:)))) + (progn + (delete-region (point) (1- here)) + (setq is-scope-op t))) + (goto-char (- (point-max) pos))) + + ;; indent the current line if it's done syntactically. + (if c-syntactic-indentation + ;; Cannot use the same syntax analysis as we find below, + ;; since that's made with c-syntactic-indentation-in-macros + ;; always set to t. + (indent-according-to-mode)) + + ;; Calculate where, if anywhere, we want newlines. + (c-save-buffer-state + ((c-syntactic-indentation-in-macros t) + (c-auto-newline-analysis t) + ;; Turn on syntactic macro analysis to help with auto newlines + ;; only. + (syntax (c-guess-basic-syntax)) + (elem syntax)) + ;; Translate substatement-label to label for this operation. + (while elem + (if (eq (car (car elem)) 'substatement-label) + (setcar (car elem) 'label)) + (setq elem (cdr elem))) + ;; some language elements can only be determined by checking + ;; the following line. Lets first look for ones that can be + ;; found when looking on the line with the colon + (setq newlines + (and c-auto-newline + (or (c-lookup-lists '(case-label label access-label) + syntax c-hanging-colons-alist) + (c-lookup-lists '(member-init-intro inher-intro) + (progn + (insert ?\n) + (unwind-protect + (c-guess-basic-syntax) + (delete-char -1))) + c-hanging-colons-alist))))) + ;; does a newline go before the colon? Watch out for already + ;; non-hung colons. However, we don't unhang them because that + ;; would be a cleanup (and anti-social). + (if (and (memq 'before newlines) + (not is-scope-op) + (save-excursion + (skip-chars-backward ": \t") + (not (bolp)))) + (let ((pos (- (point-max) (point)))) + (forward-char -1) + (c-newline-and-indent) + (goto-char (- (point-max) pos)))) + ;; does a newline go after the colon? + (if (and (memq 'after (cdr-safe newlines)) + (not is-scope-op)) + (c-newline-and-indent)) + )))) (defun c-electric-lt-gt (arg) - "Insert a less-than, or greater-than character. -The line will be re-indented if the character inserted is the second -of a C++ style stream operator and the buffer is in C++ mode. -Exceptions are when a numeric argument is supplied, point is inside a -literal, or `c-syntactic-indentation' is nil, in which case the line -will not be re-indented." + "Insert a \"<\" or \">\" character. +If the current language uses angle bracket parens (e.g. template +arguments in C++), try to find out if the inserted character is a +paren and give it paren syntax if appropriate. + +If `c-electric-flag' and `c-syntactic-indentation' are both non-nil, the +line will be reindented if the inserted character is a paren or if it +finishes a C++ style stream operator in C++ mode. Exceptions are when a +numeric argument is supplied, or the point is inside a literal." + (interactive "*P") - (let ((indentp (and c-syntactic-indentation - (not arg) - (eq (char-before) last-command-char) - (not (c-in-literal)))) - ;; shut this up - (c-echo-syntactic-information-p nil)) + (let ((c-echo-syntactic-information-p nil) + final-pos close-paren-inserted) + (self-insert-command (prefix-numeric-value arg)) - (if indentp - (indent-according-to-mode)))) + (setq final-pos (point)) + + (c-save-buffer-state (c-parse-and-markup-<>-arglists + c-restricted-<>-arglists + <-pos) + + (when c-recognize-<>-arglists + (if (eq last-command-char ?<) + (when (and (progn + (backward-char) + (= (point) + (progn + (c-beginning-of-current-token) + (point)))) + (progn + (c-backward-token-2) + (looking-at c-opt-<>-sexp-key))) + (c-mark-<-as-paren (1- final-pos))) + + ;; It's a ">". Check if there's an earlier "<" which either has + ;; open paren syntax already or that can be recognized as an arglist + ;; together with this ">". Note that this won't work in cases like + ;; "template <x, a < b, y>" but they ought to be rare. + + (save-restriction + ;; Narrow to avoid that `c-forward-<>-arglist' below searches past + ;; our position. + (narrow-to-region (point-min) final-pos) + + (while (and + (progn + (goto-char final-pos) + (c-syntactic-skip-backward "^<;}" nil t) + (eq (char-before) ?<)) + (progn + (backward-char) + ;; If the "<" already got open paren syntax we know we + ;; have the matching closer. Handle it and exit the + ;; loop. + (if (looking-at "\\s\(") + (progn + (c-mark->-as-paren (1- final-pos)) + (setq close-paren-inserted t) + nil) + t)) + + (progn + (setq <-pos (point)) + (c-backward-syntactic-ws) + (c-simple-skip-symbol-backward)) + (or (looking-at c-opt-<>-sexp-key) + (not (looking-at c-keywords-regexp))) + + (let ((c-parse-and-markup-<>-arglists t) + c-restricted-<>-arglists + (containing-sexp + (c-most-enclosing-brace (c-parse-state)))) + (when (and containing-sexp + (progn (goto-char containing-sexp) + (eq (char-after) ?\()) + (not (eq (get-text-property (point) 'c-type) + 'c-decl-arg-start))) + (setq c-restricted-<>-arglists t)) + (goto-char <-pos) + (c-forward-<>-arglist nil)) + + ;; Loop here if the "<" we found above belongs to a nested + ;; angle bracket sexp. When we start over we'll find the + ;; previous or surrounding sexp. + (if (< (point) final-pos) + t + (setq close-paren-inserted t) + nil))))))) + (goto-char final-pos) + + ;; Indent the line if appropriate. + (when (and c-electric-flag c-syntactic-indentation) + (backward-char) + (when (prog1 (or (looking-at "\\s\(\\|\\s\)") + (and (c-major-mode-is 'c++-mode) + (progn + (c-beginning-of-current-token) + (looking-at "<<\\|>>")) + (= (match-end 0) final-pos))) + (goto-char final-pos)) + (indent-according-to-mode))) + + (when (and close-paren-inserted + (not executing-kbd-macro) + blink-paren-function) + ;; Note: Most paren blink functions, such as the standard + ;; `blink-matching-open', currently doesn't handle paren chars + ;; marked with text properties very well. Maybe we should avoid + ;; this call for the time being? + (funcall blink-paren-function)))) (defun c-electric-paren (arg) "Insert a parenthesis. -Some newline cleanups are done if appropriate; see the variable -`c-cleanup-list'. - -Also, the line is re-indented unless a numeric ARG is supplied, the -parenthesis is inserted inside a literal, or `c-syntactic-indentation' -is nil." +If `c-syntactic-indentation' and `c-electric-flag' are both non-nil, the +line is reindented unless a numeric ARG is supplied, or the parenthesis +is inserted inside a literal. + +Whitespace between a function name and the parenthesis may get added or +removed; see the variable `c-cleanup-list'. + +Also, if `c-electric-flag' and `c-auto-newline' are both non-nil, some +newline cleanups are done if appropriate; see the variable `c-cleanup-list'." (interactive "*P") - (let ((literal (c-in-literal (c-point 'bod))) + (let ((literal (c-save-buffer-state () (c-in-literal))) ;; shut this up (c-echo-syntactic-information-p nil)) - (if (or arg literal) - (self-insert-command (prefix-numeric-value arg)) - ;; do some special stuff with the character - (let* (;; We want to inhibit blinking the paren since this will - ;; be most disruptive. We'll blink it ourselves - ;; afterwards. - (old-blink-paren blink-paren-function) - blink-paren-function - (noblink (eq last-input-event ?\())) - (self-insert-command (prefix-numeric-value arg)) - (if c-syntactic-indentation - (indent-according-to-mode)) - (when (looking-at "[ \t]*\\\\?$") - (when c-auto-newline - ;; Do all appropriate clean ups - (let ((here (point)) - (pos (- (point-max) (point))) - mbeg mend) - ;; clean up brace-elseif-brace - (if (and (memq 'brace-elseif-brace c-cleanup-list) - (eq last-command-char ?\() - (re-search-backward - (concat "}" - "\\([ \t\n]\\|\\\\\n\\)*" - "else" - "\\([ \t\n]\\|\\\\\n\\)+" - "if" - "\\([ \t\n]\\|\\\\\n\\)*" - "(") - nil t) - (save-excursion - (setq mbeg (match-beginning 0) - mend (match-end 0)) - (= mend here)) - (not (c-in-literal))) - (progn - (delete-region mbeg mend) - (insert-and-inherit "} else if (")) - ;; clean up brace-catch-brace - (goto-char here) - (if (and (memq 'brace-catch-brace c-cleanup-list) - (eq last-command-char ?\() - (re-search-backward - (concat "}" - "\\([ \t\n]\\|\\\\\n\\)*" - "catch" - "\\([ \t\n]\\|\\\\\n\\)*" - "(") - nil t) - (save-excursion - (setq mbeg (match-beginning 0) - mend (match-end 0)) - (= mend here)) - (not (c-in-literal))) - (progn - (delete-region mbeg mend) - (insert-and-inherit "} catch (")))) - (goto-char (- (point-max) pos)) - ))) - (let (beg (end (1- (point)))) - (cond ((and (memq 'space-before-funcall c-cleanup-list) - (eq last-command-char ?\() - (save-excursion - (backward-char) - (skip-chars-backward " \t") - (setq beg (point)) - (c-on-identifier))) - (save-excursion - (delete-region beg end) - (goto-char beg) - (insert ?\ ))) - ((and (memq 'compact-empty-funcall c-cleanup-list) - (eq last-command-char ?\)) - (save-excursion - (c-safe (backward-char 2)) - (when (looking-at "()") - (setq end (point)) - (skip-chars-backward " \t") - (setq beg (point)) - (c-on-identifier)))) - (delete-region beg end)))) - (and (not executing-kbd-macro) - old-blink-paren - (not noblink) - (funcall old-blink-paren)))))) + (self-insert-command (prefix-numeric-value arg)) + + (if (and (not arg) (not literal)) + (let* ( ;; We want to inhibit blinking the paren since this will + ;; be most disruptive. We'll blink it ourselves + ;; afterwards. + (old-blink-paren blink-paren-function) + blink-paren-function) + (if (and c-syntactic-indentation c-electric-flag) + (indent-according-to-mode)) + + ;; If we're at EOL, check for new-line clean-ups. + (when (and c-electric-flag c-auto-newline + (looking-at "[ \t]*\\\\?$")) + + ;; clean up brace-elseif-brace + (when + (and (memq 'brace-elseif-brace c-cleanup-list) + (eq last-command-char ?\() + (re-search-backward + (concat "}" + "\\([ \t\n]\\|\\\\\n\\)*" + "else" + "\\([ \t\n]\\|\\\\\n\\)+" + "if" + "\\([ \t\n]\\|\\\\\n\\)*" + "(" + "\\=") + nil t) + (not (c-save-buffer-state () (c-in-literal)))) + (delete-region (match-beginning 0) (match-end 0)) + (insert-and-inherit "} else if (")) + + ;; clean up brace-catch-brace + (when + (and (memq 'brace-catch-brace c-cleanup-list) + (eq last-command-char ?\() + (re-search-backward + (concat "}" + "\\([ \t\n]\\|\\\\\n\\)*" + "catch" + "\\([ \t\n]\\|\\\\\n\\)*" + "(" + "\\=") + nil t) + (not (c-save-buffer-state () (c-in-literal)))) + (delete-region (match-beginning 0) (match-end 0)) + (insert-and-inherit "} catch ("))) + + ;; Check for clean-ups at function calls. These two DON'T need + ;; `c-electric-flag' or `c-syntactic-indentation' set. + ;; Point is currently just after the inserted paren. + (let (beg (end (1- (point)))) + (cond + + ;; space-before-funcall clean-up? + ((and (memq 'space-before-funcall c-cleanup-list) + (eq last-command-char ?\() + (save-excursion + (backward-char) + (skip-chars-backward " \t") + (setq beg (point)) + (c-save-buffer-state () (c-on-identifier)))) + (save-excursion + (delete-region beg end) + (goto-char beg) + (insert ?\ ))) + + ;; compact-empty-funcall clean-up? + ((c-save-buffer-state () + (and (memq 'compact-empty-funcall c-cleanup-list) + (eq last-command-char ?\)) + (save-excursion + (c-safe (backward-char 2)) + (when (looking-at "()") + (setq end (point)) + (skip-chars-backward " \t") + (setq beg (point)) + (c-on-identifier))))) + (delete-region beg end)))) + (and (eq last-input-event ?\)) + (not executing-kbd-macro) + old-blink-paren + (funcall old-blink-paren)))))) (defun c-electric-continued-statement () "Reindent the current line if appropriate. @@ -995,16 +1275,18 @@ The line is reindented if there is nothing but whitespace before the keyword on the line, the keyword is not inserted inside a literal, and -`c-syntactic-indentation' is non-nil." +`c-electric-flag' and `c-syntactic-indentation' are both non-nil." (let (;; shut this up (c-echo-syntactic-information-p nil)) - (when (and c-syntactic-indentation - (not (eq last-command-char ?_)) - (= (save-excursion - (skip-syntax-backward "w") - (point)) - (c-point 'boi)) - (not (c-in-literal (c-point 'bod)))) + (when (c-save-buffer-state () + (and c-electric-flag + c-syntactic-indentation + (not (eq last-command-char ?_)) + (= (save-excursion + (skip-syntax-backward "w") + (point)) + (c-point 'boi)) + (not (c-in-literal (c-point 'bod))))) ;; Have to temporarily insert a space so that ;; c-guess-basic-syntax recognizes the keyword. Follow the ;; space with a nonspace to avoid messing up any whitespace @@ -1016,36 +1298,19 @@ (delete-char -2))))) -;; better movement routines for ThisStyleOfVariablesCommonInCPlusPlus -;; originally contributed by Terry_Glanfield.Southern@rxuk.xerox.com (defun c-forward-into-nomenclature (&optional arg) - "Move forward to end of a nomenclature section or word. -With arg, do it arg times." + "Compatibility alias for `c-forward-subword'." (interactive "p") - (let ((case-fold-search nil)) - (if (> arg 0) - (re-search-forward - (cc-eval-when-compile - (concat "\\W*\\([" c-upper "]*[" c-lower c-digit "]*\\)")) - (point-max) t arg) - (while (and (< arg 0) - (re-search-backward - (cc-eval-when-compile - (concat - "\\(\\(\\W\\|[" c-lower c-digit "]\\)[" c-upper "]+" - "\\|\\W\\w+\\)")) - (point-min) 0)) - (forward-char 1) - (setq arg (1+ arg))))) - (c-keep-region-active)) + (require 'cc-subword) + (c-forward-subword arg)) +(make-obsolete 'c-forward-into-nomenclature 'c-forward-subword) (defun c-backward-into-nomenclature (&optional arg) - "Move backward to beginning of a nomenclature section or word. -With optional ARG, move that many times. If ARG is negative, move -forward." + "Compatibility alias for `c-backward-subword'." (interactive "p") - (c-forward-into-nomenclature (- arg)) - (c-keep-region-active)) + (require 'cc-subword) + (c-backward-subword arg)) +(make-obsolete 'c-backward-into-nomenclature 'c-backward-subword) (defun c-scope-operator () "Insert a double colon scope operator at point. @@ -1246,6 +1511,8 @@ ;; following one is chosen instead (if there is any). The end ;; position is at the next line, providing there is one before the ;; declaration. + ;; + ;; This function might do hidden buffer changes. (save-excursion ;; Note: Some code duplication in `c-beginning-of-defun' and @@ -1369,6 +1636,604 @@ (push-mark (cdr decl-limits) nil t)))) +(defun c-in-comment-line-prefix-p () + ;; Point is within a comment. Is it also within a comment-prefix? + ;; Space at BOL which precedes a comment-prefix counts as part of it. + ;; + ;; This function might do hidden buffer changes. + (let ((here (point))) + (save-excursion + (beginning-of-line) + (skip-chars-forward " \t") + (and (looking-at c-current-comment-prefix) + (/= (match-beginning 0) (match-end 0)) + (< here (match-end 0)))))) + +(defun c-narrow-to-comment-innards (range) + ;; Narrow to the "inside" of the comment (block) defined by range, as + ;; follows: + ;; + ;; A c-style block comment has its opening "/*" and its closing "*/" (if + ;; present) removed. A c++-style line comment retains its opening "//" but + ;; has any final NL removed. If POINT is currently outwith these innards, + ;; move it to the appropriate boundary. + ;; + ;; This narrowing simplifies the sentence movement functions, since it + ;; eliminates awkward things at the boundaries of the comment (block). + ;; + ;; This function might do hidden buffer changes. + (let* ((lit-type (c-literal-type range)) + (beg (if (eq lit-type 'c) (+ (car range) 2) (car range))) + (end (if (eq lit-type 'c) + (if (and (eq (char-before (cdr range)) ?/) + (eq (char-before (1- (cdr range))) ?*)) + (- (cdr range) 2) + (point-max)) + (if (eq (cdr range) (point-max)) + (point-max) + (- (cdr range) 1))))) + (if (> (point) end) + (goto-char end)) ; This would be done automatically by ... + (if (< (point) beg) + (goto-char beg)) ; ... narrow-to-region but is not documented. + (narrow-to-region beg end))) + +(defun c-beginning-of-sentence-in-comment (range) + ;; Move backwards to the "beginning of a sentence" within the comment + ;; defined by RANGE, a cons of its starting and ending positions. If we + ;; find a BOS, return NIL. Otherwise, move point to just before the start + ;; of the comment and return T. + ;; + ;; The BOS is either text which follows a regexp match of sentence-end, + ;; or text which is a beginning of "paragraph". + ;; Comment-prefixes are treated like WS when calculating BOSes or BOPs. + ;; + ;; This code was adapted from GNU Emacs's forward-sentence in paragraphs.el. + ;; It is not a general function, but is intended only for calling from + ;; c-move-over-sentence. Not all preconditions have been explicitly stated. + ;; + ;; This function might do hidden buffer changes. + (save-match-data + (let ((start-point (point))) + (save-restriction + (c-narrow-to-comment-innards range) ; This may move point back. + (let* ((here (point)) + last + (here-filler ; matches WS and comment-prefices at point. + (concat "\\=\\(^[ \t]*\\(" c-current-comment-prefix "\\)" + "\\|[ \t\n\r\f]\\)*")) + (prefix-at-bol-here ; matches WS and prefix at BOL, just before point + (concat "^[ \t]*\\(" c-current-comment-prefix "\\)[ \t\n\r\f]*\\=")) + ;; First, find the previous paragraph start, if any. + (par-beg ; point where non-WS/non-prefix text of paragraph starts. + (save-excursion + (forward-paragraph -1) ; uses cc-mode values of + ; paragraph-\(start\|separate\) + (if (> (re-search-forward here-filler nil t) here) + (goto-char here)) + (when (>= (point) here) + (forward-paragraph -2) + (if (> (re-search-forward here-filler nil t) here) + (goto-char here))) + (point)))) + + ;; Now seek successively earlier sentence ends between PAR-BEG and + ;; HERE, until the "start of sentence" following it is earlier than + ;; HERE, or we hit PAR-BEG. Beware of comment prefices! + (while (and (re-search-backward (c-sentence-end) par-beg 'limit) + (setq last (point)) + (goto-char (match-end 0)) ; tentative beginning of sentence + (or (>= (point) here) + (and (not (bolp)) ; Found a non-blank comment-prefix? + (save-excursion + (if (re-search-backward prefix-at-bol-here nil t) + (/= (match-beginning 1) (match-end 1))))) + (progn ; Skip the crud to find a real b-o-s. + (if (c-in-comment-line-prefix-p) + (beginning-of-line)) + (re-search-forward here-filler) ; always succeeds. + (>= (point) here)))) + (goto-char last)) + (re-search-forward here-filler))) + + (if (< (point) start-point) + nil + (goto-char (car range)) + t)))) + +(defun c-end-of-sentence-in-comment (range) + ;; Move forward to the "end of a sentence" within the comment defined by + ;; RANGE, a cons of its starting and ending positions (enclosing the opening + ;; comment delimiter and the terminating */ or newline). If we find an EOS, + ;; return NIL. Otherwise, move point to just after the end of the comment + ;; and return T. + ;; + ;; The EOS is just after the non-WS part of the next match of the regexp + ;; sentence-end. Typically, this is just after one of [.!?]. If there is + ;; no sentence-end match following point, any WS before the end of the + ;; comment will count as EOS, providing we're not already in it. + ;; + ;; This code was adapted from GNU Emacs's forward-sentence in paragraphs.el. + ;; It is not a general function, but is intended only for calling from + ;; c-move-over-sentence. + ;; + ;; This function might do hidden buffer changes. + (save-match-data + (let ((start-point (point)) + ;; (lit-type (c-literal-type range)) ; Commented out, 2005/11/23, ACM + ) + (save-restriction + (c-narrow-to-comment-innards range) ; This might move point forwards. + (let* ((here (point)) + (par-end ; EOL position of last text in current/next paragraph. + (save-excursion + ;; The cc-mode values of paragraph-\(start\|separate\), set + ;; in c-setup-paragraph-variables, are used in the + ;; following. + (forward-paragraph 1) + (if (eq (preceding-char) ?\n) (forward-char -1)) + (when (<= (point) here) ; can happen, e.g., when HERE is at EOL. + (goto-char here) + (forward-paragraph 2) + (if (eq (preceding-char) ?\n) (forward-char -1))) + (point))) + + last + (prefix-at-bol-here + (concat "^[ \t]*\\(" c-current-comment-prefix "\\)\\="))) + ;; Go forward one "comment-prefix which looks like sentence-end" + ;; each time round the following: + (while (and (re-search-forward (c-sentence-end) par-end 'limit) + (progn + (setq last (point)) + (skip-chars-backward " \t\n") + (or (and (not (bolp)) + (re-search-backward prefix-at-bol-here nil t) + (/= (match-beginning 1) (match-end 1))) + (<= (point) here)))) + (goto-char last)) + + ;; Take special action if we're up against the end of a comment (of + ;; either sort): Leave point just after the last non-ws text. + (if (eq (point) (point-max)) + (while (or (/= (skip-chars-backward " \t\n") 0) + (and (re-search-backward prefix-at-bol-here nil t) + (/= (match-beginning 1) (match-end 1)))))))) + + (if (> (point) start-point) + nil + (goto-char (cdr range)) + t)))) + +(defun c-beginning-of-sentence-in-string (range) + ;; Move backwards to the "beginning of a sentence" within the string defined + ;; by RANGE, a cons of its starting and ending positions (enclosing the + ;; string quotes). If we find a BOS, return NIL. Otherwise, move point to + ;; just before the start of the string and return T. + ;; + ;; The BOS is either the text which follows a regexp match of sentence-end + ;; or text which is a beginning of "paragraph". For the purposes of + ;; determining paragraph boundaries, escaped newlines are treated as + ;; ordinary newlines. + ;; + ;; This code was adapted from GNU Emacs's forward-sentence in paragraphs.el. + ;; It is not a general function, but is intended only for calling from + ;; c-move-over-sentence. + ;; + ;; This function might do hidden buffer changes. + (save-match-data + (let* ((here (point)) last + (end (1- (cdr range))) + (here-filler ; matches WS and escaped newlines at point. + "\\=\\([ \t\n\r\f]\\|\\\\[\n\r]\\)*") + ;; Enhance paragraph-start and paragraph-separate also to recognise + ;; blank lines terminated by escaped EOLs. IT MAY WELL BE that + ;; these values should be customizable user options, or something. + (paragraph-start c-string-par-start) + (paragraph-separate c-string-par-separate) + + (par-beg ; beginning of current (or previous) paragraph. + (save-excursion + (save-restriction + (narrow-to-region (1+ (car range)) end) + (forward-paragraph -1) ; uses above values of + ; paragraph-\(start\|separate\) + (if (> (re-search-forward here-filler nil t) here) + (goto-char here)) + (when (>= (point) here) + (forward-paragraph -2) + (if (> (re-search-forward here-filler nil t) here) + (goto-char here))) + (point))))) + ;; Now see if we can find a sentence end after PAR-BEG. + (while (and (re-search-backward c-sentence-end-with-esc-eol par-beg 'limit) + (setq last (point)) + (goto-char (match-end 0)) + (or (> (point) end) + (progn + (re-search-forward + here-filler end t) ; always succeeds. Use end rather + ; than here, in case point starts + ; beyond the closing quote. + (>= (point) here)))) + (goto-char last)) + (re-search-forward here-filler here t) + (if (< (point) here) + nil + (goto-char (car range)) + t)))) + +(defun c-end-of-sentence-in-string (range) + ;; Move forward to the "end of a sentence" within the string defined by + ;; RANGE, a cons of its starting and ending positions. If we find an EOS, + ;; return NIL. Otherwise, move point to just after the end of the string + ;; and return T. + ;; + ;; The EOS is just after the non-WS part of the next match of the regexp + ;; sentence-end. Typically, this is just after one of [.!?]. If there is + ;; no sentence-end match following point, any WS before the end of the + ;; string will count as EOS, providing we're not already in it. + ;; + ;; This code was adapted from GNU Emacs's forward-sentence in paragraphs.el. + ;; It is not a general function, but is intended only for calling from + ;; c-move-over-sentence. + ;; + ;; This function might do hidden buffer changes. + (save-match-data + (let* ((here (point)) + last + ;; Enhance paragraph-start and paragraph-separate to recognise + ;; blank lines terminated by escaped EOLs. + (paragraph-start c-string-par-start) + (paragraph-separate c-string-par-separate) + + (par-end ; EOL position of last text in current/next paragraph. + (save-excursion + (save-restriction + (narrow-to-region (car range) (1- (cdr range))) + ;; The above values of paragraph-\(start\|separate\) are used + ;; in the following. + (forward-paragraph 1) + (setq last (point)) + ;; (re-search-backward filler-here nil t) would find an empty + ;; string. Therefore we simulate it by the following: + (while (or (/= (skip-chars-backward " \t\n\r\f") 0) + (re-search-backward "\\\\\\($\\)\\=" nil t))) + (unless (> (point) here) + (goto-char last) + (forward-paragraph 1) + (while (or (/= (skip-chars-backward " \t\n\r\f") 0) + (re-search-backward "\\\\\\($\\)\\=" nil t)))) + (point))))) + ;; Try to go forward a sentence. + (when (re-search-forward c-sentence-end-with-esc-eol par-end 'limit) + (setq last (point)) + (while (or (/= (skip-chars-backward " \t\n") 0) + (re-search-backward "\\\\\\($\\)\\=" nil t)))) + ;; Did we move a sentence, or did we hit the end of the string? + (if (> (point) here) + nil + (goto-char (cdr range)) + t)))) + +(defun c-ascertain-preceding-literal () + ;; Point is not in a literal (i.e. comment or string (include AWK regexp)). + ;; If a literal is the next thing (aside from whitespace) to be found before + ;; point, return a cons of its start.end positions (enclosing the + ;; delimiters). Otherwise return NIL. + ;; + ;; This function might do hidden buffer changes. + (save-excursion + (c-collect-line-comments + (let ((here (point)) + pos) + (if (c-backward-single-comment) + (cons (point) (progn (c-forward-single-comment) (point))) + (save-restriction + ;; to prevent `looking-at' seeing a " at point. + (narrow-to-region (point-min) here) + (when + (or + ;; An EOL can act as an "open string" terminator in AWK. + (looking-at c-ws*-string-limit-regexp) + (and (not (bobp)) + (progn (backward-char) + (looking-at c-string-limit-regexp)))) + (goto-char (match-end 0)) ; just after the string terminator. + (setq pos (point)) + (c-safe (c-backward-sexp 1) ; move back over the string. + (cons (point) pos))))))))) + +(defun c-ascertain-following-literal () + ;; Point is not in a literal (i.e. comment or string (include AWK regexp)). + ;; If a literal is the next thing (aside from whitespace) following point, + ;; return a cons of its start.end positions (enclosing the delimiters). + ;; Otherwise return NIL. + ;; + ;; This function might do hidden buffer changes. + (save-excursion + (c-collect-line-comments + (let (pos) + (c-skip-ws-forward) + (if (looking-at c-string-limit-regexp) ; string-delimiter. + (cons (point) (or (c-safe (progn (c-forward-sexp 1) (point))) + (point-max))) + (setq pos (point)) + (if (c-forward-single-comment) + (cons pos (point)))))))) + +(defun c-after-statement-terminator-p () ; Should we pass in LIM here? + ;; Does point immediately follow a statement "terminator"? A virtual + ;; semicolon is regarded here as such. So is a an opening brace ;-) + ;; + ;; This function might do hidden buffer changes. + (or (save-excursion + (backward-char) + (and (looking-at "[;{}]") + (not (and c-special-brace-lists ; Pike special brace lists. + (eq (char-after) ?{) + (c-looking-at-special-brace-list))))) + (c-at-vsemi-p) + ;; The following (for macros) is not strict about exactly where we are + ;; wrt white space at the end of the macro. Doesn't seem to matter too + ;; much. ACM 2004/3/29. + (let (eom) + (save-excursion + (if (c-beginning-of-macro) + (setq eom (progn (c-end-of-macro) + (point))))) + (when eom + (save-excursion + (c-forward-comments) + (>= (point) eom)))))) + +(defun c-back-over-illiterals (macro-start) + ;; Move backwards over code which isn't a literal (i.e. comment or string), + ;; stopping before reaching BOB or a literal or the boundary of a + ;; preprocessor statement or the "beginning of a statement". MACRO-START is + ;; the position of the '#' beginning the current preprocessor directive, or + ;; NIL if we're not in such. + ;; + ;; Return a cons (A.B), where + ;; A is NIL if we moved back to a BOS (and know it), T otherwise (we + ;; didn't move, or we hit a literal, or we're not sure about BOS). + ;; B is MACRO-BOUNDARY if we are about to cross the boundary out of or + ;; into a macro, otherwise LITERAL if we've hit a literal, otherwise NIL + ;; + ;; The total collection of returned values is as follows: + ;; (nil . nil): Found a BOS whilst remaining inside the illiterals. + ;; (t . literal): No BOS found: only a comment/string. We _might_ be at + ;; a BOS - the caller must check this. + ;; (nil . macro-boundary): only happens with non-nil macro-start. We've + ;; moved and reached the opening # of the macro. + ;; (t . macro-boundary): Every other circumstance in which we're at a + ;; macro-boundary. We might be at a BOS. + ;; + ;; Point is left either at the beginning-of-statement, or at the last non-ws + ;; code before encountering the literal/BOB or macro-boundary. + ;; + ;; Note that this function moves within either preprocessor commands + ;; (macros) or normal code, but will not cross a boundary between the two, + ;; or between two distinct preprocessor commands. + ;; + ;; Stop before `{' and after `;', `{', `}' and `};' when not followed by `}' + ;; or `)', but on the other side of the syntactic ws. Move by sexps and + ;; move into parens. Also stop before `#' when it's at boi on a line. + ;; + ;; This function might do hidden buffer changes. + (save-match-data + (let ((here (point)) + last) ; marks the position of non-ws code, what'll be BOS if, say, a + ; semicolon precedes it. + (catch 'done + (while t ;; We go back one "token" each iteration of the loop. + (setq last (point)) + (cond + ;; Stop at the token after a comment. + ((c-backward-single-comment) ; Also functions as backwards-ws. + (goto-char last) + (throw 'done '(t . literal))) + + ;; If we've gone back over a LF, we might have moved into or out of + ;; a preprocessor line. + ((and (save-excursion + (beginning-of-line) + (re-search-forward "\\(^\\|[^\\]\\)[\n\r]" last t)) + (if macro-start + (< (point) macro-start) + (c-beginning-of-macro))) + (goto-char last) + ;; Return a car of NIL ONLY if we've hit the opening # of a macro. + (throw 'done (cons (or (eq (point) here) + (not macro-start)) + 'macro-boundary))) + + ;; Have we found a virtual semicolon? If so, stop, unless the next + ;; statement is where we started from. + ((and (c-at-vsemi-p) + (< last here) + (not (memq (char-after last) '(?\) ?})))) ; we've moved back from ) or } + (goto-char last) + (throw 'done '(nil . nil))) + + ;; Hit the beginning of the buffer/region? + ((bobp) + (if (/= here last) + (goto-char last)) + (throw 'done '(nil . nil))) + + ;; Move back a character. + ((progn (backward-char) nil)) + + ;; Stop at "{" (unless it's a PIKE special brace list.) + ((eq (char-after) ?\{) + (if (and c-special-brace-lists + (c-looking-at-special-brace-list)) + (skip-syntax-backward "w_") ; Speedup only. + (if (/= here last) + (goto-char last)) + (throw 'done '(nil . nil)))) + + ;; Have we reached the start of a macro? This always counts as + ;; BOS. (N.B. I don't think (eq (point) here) can ever be true + ;; here. FIXME!!! ACM 2004/3/29) + ((and macro-start (eq (point) macro-start)) + (throw 'done (cons (eq (point) here) 'macro-boundary))) + + ;; Stop at token just after "}" or ";". + ((looking-at "[;}]") + ;; If we've gone back over ;, {, or }, we're done. + (if (or (= here last) + (memq (char-after last) '(?\) ?}))) ; we've moved back from ) or } + (if (and (eq (char-before) ?}) ; If };, treat them as a unit. + (eq (char-after) ?\;)) + (backward-char)) + (goto-char last) ; To the statement starting after the ; or }. + (throw 'done '(nil . nil)))) + + ;; Stop at the token after a string. + ((looking-at c-string-limit-regexp) ; Just gone back over a string terminator? + (goto-char last) + (throw 'done '(t . literal))) + + ;; Nothing special: go back word characters. + (t (skip-syntax-backward "w_")) ; Speedup only. + )))))) + +(defun c-forward-over-illiterals (macro-end allow-early-stop) + ;; Move forwards over code, stopping before reaching EOB or a literal + ;; (i.e. a comment/string) or the boundary of a preprocessor statement or + ;; the "end of a statement". MACRO-END is the position of the EOL/EOB which + ;; terminates the current preprocessor directive, or NIL if we're not in + ;; such. + ;; + ;; ALLOW-EARLY-STOP is non-nil if it is permissible to return without moving + ;; forward at all, should we encounter a `{'. This is an ugly kludge, but + ;; seems unavoidable. Depending on the context this function is called + ;; from, we _sometimes_ need to stop there. Currently (2004/4/3), + ;; ALLOW-EARLY-STOP is applied only to open braces, not to virtual + ;; semicolons, or anything else. + ;; + ;; Return a cons (A.B), where + ;; A is NIL if we moved forward to an EOS, or stay at one (when + ;; ALLOW-EARLY-STOP is set), T otherwise (we hit a literal). + ;; B is 'MACRO-BOUNDARY if we are about to cross the boundary out of or + ;; into a macro, otherwise 'LITERAL if we've hit a literal, otherwise NIL + ;; + ;; Point is left either after the end-of-statement, or at the last non-ws + ;; code before encountering the literal, or the # of the preprocessor + ;; statement, or at EOB [or just after last non-WS stuff??]. + ;; + ;; As a clarification of "after the end-of-statement", if a comment or + ;; whitespace follows a completed AWK statement, that statement is treated + ;; as ending just after the last non-ws character before the comment. + ;; + ;; Note that this function moves within either preprocessor commands + ;; (macros) or normal code, but not both within the same invocation. + ;; + ;; Stop before `{', `}', and `#' when it's at boi on a line, but on the + ;; other side of the syntactic ws, and after `;', `}' and `};'. Only + ;; stop before `{' if at top level or inside braces, though. Move by + ;; sexps and move into parens. Also stop at eol of lines with `#' at + ;; the boi. + ;; + ;; This function might do hidden buffer changes. + (let ((here (point)) + last) + (catch 'done + (while t ;; We go one "token" forward each time round this loop. + (setq last (point)) + + ;; If we've moved forward to a virtual semicolon, we're done. + (if (and (> last here) ; Should we check ALLOW-EARLY-STOP, here? 2004/4/3 + (c-at-vsemi-p)) + (throw 'done '(nil . nil))) + + (c-skip-ws-forward) + (cond + ;; Gone past the end of a macro? + ((and macro-end (> (point) macro-end)) + (goto-char last) + (throw 'done (cons (eq (point) here) 'macro-boundary))) + + ;; About to hit a comment? + ((save-excursion (c-forward-single-comment)) + (goto-char last) + (throw 'done '(t . literal))) + + ;; End of buffer? + ((eobp) + (if (/= here last) + (goto-char last)) + (throw 'done '(nil . nil))) + + ;; If we encounter a '{', stop just after the previous token. + ((and (eq (char-after) ?{) + (not (and c-special-brace-lists + (c-looking-at-special-brace-list))) + (or allow-early-stop (/= here last)) + (save-excursion ; Is this a check that we're NOT at top level? +;;;; NO! This seems to check that (i) EITHER we're at the top level; OR (ii) The next enclosing +;;;; level of bracketing is a '{'. HMM. Doesn't seem to make sense. +;;;; 2003/8/8 This might have something to do with the GCC extension "Statement Expressions", e.g. +;;;; while ({stmt1 ; stmt2 ; exp ;}). This form excludes such Statement Expressions. + (or (not (c-safe (up-list -1) t)) + (= (char-after) ?{)))) + (goto-char last) + (throw 'done '(nil . nil))) + + ;; End of a PIKE special brace list? If so, step over it and continue. + ((and c-special-brace-lists + (eq (char-after) ?}) + (save-excursion + (and (c-safe (up-list -1) t) + (c-looking-at-special-brace-list)))) + (forward-char) + (skip-syntax-forward "w_")) ; Speedup only. + + ;; Have we got a '}' after having moved? If so, stop after the + ;; previous token. + ((and (eq (char-after) ?}) + (/= here last)) + (goto-char last) + (throw 'done '(nil . nil))) + + ;; Stop if we encounter a preprocessor line. + ((and (not macro-end) + (eq (char-after) ?#) + (= (point) (c-point 'boi))) + (goto-char last) + ;(throw 'done (cons (eq (point) here) 'macro-boundary))) ; Changed 2003/3/26 + (throw 'done '(t . macro-boundary))) + + ;; Stop after a ';', '}', or "};" + ((looking-at ";\\|};?") + (goto-char (match-end 0)) + (throw 'done '(nil . nil))) + + ;; Found a string (this subsumes AWK regexps)? + ((looking-at c-string-limit-regexp) + (goto-char last) + (throw 'done '(t . literal))) + + (t + (forward-char) ; Can't fail - we checked (eobp) earlier on. + (skip-syntax-forward "w_") ; Speedup only. + (when (and macro-end (> (point) macro-end)) + (goto-char last) + (throw 'done (cons (eq (point) here) 'macro-boundary)))) + ))))) + +(defun c-one-line-string-p (range) + ;; Is the literal defined by RANGE a string contained in a single line? + ;; + ;; This function might do hidden buffer changes. + (save-excursion + (goto-char (car range)) + (and (looking-at c-string-limit-regexp) + (progn (skip-chars-forward "^\n" (cdr range)) + (eq (point) (cdr range)))))) + (defun c-beginning-of-statement (&optional count lim sentence-flag) "Go to the beginning of the innermost C statement. With prefix arg, go back N - 1 statements. If already at the @@ -1382,318 +2247,93 @@ to search for the syntactic context, and a flag saying whether to do sentence motion in or near comments and multiline strings. -Note that `c-beginning-of-statement-1' is usually better to use from -programs. It has much more well defined semantics than this one, -which is intended for interactive use and might therefore change to be -more \"DWIM:ey\"." +Note that for use in programs, `c-beginning-of-statement-1' is +usually better. It has much better defined semantics than this one, +which is intended for interactive use, and might therefore change to +be more \"DWIM:ey\"." (interactive (list (prefix-numeric-value current-prefix-arg) nil t)) - (c-save-buffer-state - ((count (or count 1)) - here - (range (c-collect-line-comments (c-literal-limits lim)))) - (while (and (/= count 0) - (or (not lim) (> (point) lim))) - (setq here (point)) - (if (and (not range) sentence-flag) - (save-excursion - ;; Find the comment next to point if we're not in one. - (if (> count 0) - (if (c-backward-single-comment) - (setq range (cons (point) - (progn (c-forward-single-comment) - (point)))) - (c-skip-ws-backward) - (setq range (point)) - (setq range - (if (eq (char-before) ?\") - (c-safe (c-backward-sexp 1) - (cons (point) range))))) - (c-skip-ws-forward) - (if (eq (char-after) ?\") - (setq range (cons (point) - (progn - (c-forward-sexp 1) - (point)))) - (setq range (point)) - (setq range (if (c-forward-single-comment) - (cons range (point)) - nil)))) - (setq range (c-collect-line-comments range)))) - (if (and (< count 0) (= here (point-max))) - ;; Special case because eob might be in a literal. - (setq range nil)) - (if range - (if (and sentence-flag - (or (/= (char-syntax (char-after (car range))) ?\") - ;; Only visit a string if it spans more than one line. - (save-excursion - (goto-char (car range)) - (skip-chars-forward "^\n" (cdr range)) - (< (point) (cdr range))))) - (let* ((lit-type (c-literal-type range)) - (line-prefix (concat "[ \t]*\\(" - c-current-comment-prefix - "\\)[ \t]*")) - (beg (if (eq lit-type 'string) - (1+ (car range)) - (save-excursion - (goto-char (car range)) - (max (progn - (looking-at comment-start-skip) - (match-end 0)) - (progn - (looking-at line-prefix) - (match-end 0)))))) - (end (- (cdr range) (if (eq lit-type 'c) 2 1))) - (beg-of-para (if (eq lit-type 'string) - (lambda ()) - (lambda () - (beginning-of-line) - (if (looking-at line-prefix) - (goto-char (match-end 0))))))) - (save-restriction - ;; Move by sentence, but not past the limit of the - ;; literal, narrowed to the appropriate - ;; paragraph(s). - (narrow-to-region (save-excursion - (let ((pos (min here end))) - (goto-char pos) - (forward-paragraph -1) - (if (looking-at paragraph-separate) - (forward-line)) - (when (> (point) beg) - (funcall beg-of-para) - (when (>= (point) pos) - (forward-paragraph -2) - (funcall beg-of-para))) - (max (point) beg))) - end) - (c-safe (forward-sentence (if (< count 0) 1 -1))) - (if (and (memq lit-type '(c c++)) - ;; Check if we stopped due to a comment - ;; prefix and not a sentence end. - (/= (point) (point-min)) - (/= (point) (point-max)) - (save-excursion - (beginning-of-line) - (looking-at line-prefix)) - (>= (point) (match-beginning 0)) - (/= (match-beginning 1) (match-end 1)) - (or (< (point) (match-end 0)) - (and - (= (point) (match-end 0)) - ;; The comment prefix may contain - ;; characters that is regarded as end - ;; of sentence. - (or (eolp) - (and - (save-excursion - (forward-paragraph -1) - (< (point) (match-beginning 0))) - (save-excursion - (beginning-of-line) - (or (not (re-search-backward - (sentence-end) - (c-point 'bopl) - t)) - (< (match-end 0) - (c-point 'eol))))))))) - (setq count (+ count (if (< count 0) -1 1))) - (if (< count 0) - (progn - ;; In block comments, if there's only - ;; horizontal ws between the text and the - ;; comment ender, stop before it. Stop after - ;; the ender if there's either nothing or - ;; newlines between. - (when (and (eq lit-type 'c) - (eq (point) (point-max))) - (widen) - (when (or (= (skip-chars-backward " \t") 0) - (eq (point) (point-max)) - (bolp)) - (goto-char (cdr range))))) - (when (and (eq (point) (point-min)) - (looking-at "[ \t]*\\\\?$")) - ;; Stop before instead of after the comment - ;; starter if nothing follows it. - (widen) - (goto-char (car range)) - (if (and (eq lit-type 'string) (/= (point) here)) - (setq count (1+ count) - range nil)))))) - ;; See if we should escape the literal. - (if (> count 0) - (if (< (point) here) - (setq count (1- count)) - (goto-char (car range)) - (setq range nil)) - (if (> (point) here) - (setq count (1+ count)) - (goto-char (cdr range)) - (setq range nil)))) - (goto-char (if (> count 0) (car range) (cdr range))) - (setq range nil)) - (goto-char here) - (if (> count 0) - (condition-case nil - ;; Stop before `{' and after `;', `{', `}' and `};' - ;; when not followed by `}' or `)', but on the other - ;; side of the syntactic ws. Move by sexps and move - ;; into parens. Also stop before `#' when it's at boi - ;; on a line. - (let ((literal-pos (not sentence-flag)) - last last-below-line) - (catch 'done - (while t - (setq last (point)) - (when (and (or (eq (char-after) ?\{) - (and (eq (char-after) ?#) - (eq (point) (c-point 'boi))) - ) - (/= here last)) - (unless (and c-special-brace-lists - (eq (char-after) ?{) - (c-looking-at-special-brace-list)) - (if (and (eq (char-after) ?#) - (numberp last-below-line) - (not (eq last-below-line here))) - (goto-char last-below-line)) - (throw 'done t))) - ;; Don't know why I added the following, but it - ;; doesn't work when point is preceded by a line - ;; style comment. /mast - ;;(c-skip-ws-backward) - (if literal-pos - (c-backward-comments) - (when (c-backward-single-comment) - ;; Record position of first comment. - (save-excursion - (c-forward-single-comment) - (setq literal-pos (point))) - (c-backward-comments))) - (unless last-below-line - (if (save-excursion - (re-search-forward "\\(^\\|[^\\]\\)$" last t)) - (setq last-below-line last))) - (cond ((bobp) ; Must handle bob specially. - (if (= here last) - (throw 'done t) - (goto-char last) - (throw 'done t))) - ((progn (backward-char) - (looking-at "[;{}]")) - (if (and c-special-brace-lists - (eq (char-after) ?{) - (c-looking-at-special-brace-list)) - (skip-syntax-backward "w_") ; Speedup only. - (if (or (= here last) - (memq (char-after last) '(?\) ?}))) - (if (and (eq (char-before) ?}) - (eq (char-after) ?\;)) - (backward-char)) - (goto-char last) - (throw 'done t)))) - ((= (char-syntax (char-after)) ?\") - (let ((end (point))) - (forward-char) - (c-backward-sexp) - (save-excursion - (skip-chars-forward "^\n" end) - (when (< (point) end) - ;; Break at multiline string. - (setq literal-pos (1+ end)) - (throw 'done t))))) - (t (skip-syntax-backward "w_")) ; Speedup only. - ))) - (if (and (numberp literal-pos) - (< (point) literal-pos)) - ;; We jumped over a comment or string that - ;; should be investigated. - (goto-char literal-pos) - (setq count (1- count)))) - (error - (goto-char (point-min)) - (setq count 0))) - (condition-case nil - ;; Stop before `{', `}', and `#' when it's at boi on a - ;; line, but on the other side of the syntactic ws, and - ;; after `;', `}' and `};'. Only stop before `{' if at - ;; top level or inside braces, though. Move by sexps - ;; and move into parens. Also stop at eol of lines - ;; with `#' at the boi. - (let ((literal-pos (not sentence-flag)) - last) - (catch 'done - (while t - (setq last (point)) - (if literal-pos - (c-forward-comments) - (if (progn - (c-skip-ws-forward) - ;; Record position of first comment. - (setq literal-pos (point)) - (c-forward-single-comment)) - (c-forward-comments) - (setq literal-pos nil))) - (cond ((and (eq (char-after) ?{) - (not (and c-special-brace-lists - (c-looking-at-special-brace-list))) - (/= here last) - (save-excursion - (or (not (c-safe (up-list -1) t)) - (= (char-after) ?{)))) - (goto-char last) - (throw 'done t)) - ((and c-special-brace-lists - (eq (char-after) ?}) - (save-excursion - (and (c-safe (up-list -1) t) - (c-looking-at-special-brace-list)))) - (forward-char 1) - (skip-syntax-forward "w_")) ; Speedup only. - ((and (eq (char-after) ?}) - (/= here last)) - (goto-char last) - (throw 'done t)) -; ((and (eq (char-after) ?#) -; (= (point) (c-point 'boi))) -; (if (= here last) -; (or (re-search-forward "\\(^\\|[^\\]\\)$" nil t) -; (goto-char (point-max))) -; (goto-char last)) -; (throw 'done t)) - ((looking-at ";\\|};?") - (goto-char (match-end 0)) - (throw 'done t)) - ((= (char-syntax (char-after)) ?\") - (let ((beg (point))) - (c-forward-sexp) - (save-excursion - (skip-chars-backward "^\n" beg) - (when (> (point) beg) - ;; Break at multiline string. - (setq literal-pos beg) - (throw 'done t))))) - (t - (forward-char 1) - (skip-syntax-forward "w_")) ; Speedup only. - ))) - (if (and (numberp literal-pos) - (> (point) literal-pos)) - ;; We jumped over a comment that should be investigated. - (goto-char literal-pos) - (setq count (1+ count)))) - (error - (goto-char (point-max)) - (setq count 0))) - )) - ;; If we haven't moved we're near a buffer limit. - (when (and (not (zerop count)) (= (point) here)) - (goto-char (if (> count 0) (point-min) (point-max))) - (setq count 0)))) - (c-keep-region-active)) + (if (< count 0) + (c-end-of-statement (- count) lim sentence-flag) + (c-save-buffer-state + ((count (or count 1)) + last ; start point for going back ONE chunk. Updated each chunk movement. + (macro-fence + (save-excursion (and (not (bobp)) (c-beginning-of-macro) (point)))) + res ; result from sub-function call + not-bos ; "not beginning-of-statement" + (range (c-collect-line-comments (c-literal-limits lim)))) ; (start.end) of current literal or NIL + + ;; Go back one statement at each iteration of the following loop. + (while (and (/= count 0) + (or (not lim) (> (point) lim))) + ;; Go back one "chunk" each time round the following loop, stopping + ;; when we reach a statement boundary, etc. + (setq last (point)) + (while + (cond ; Each arm of this cond returns NIL on reaching a desired + ; statement boundary, non-NIL otherwise. + ((bobp) + (setq count 0) + nil) + + (range ; point is within or approaching a literal. + (cond + ;; Single line string or sentence-flag is null => skip the + ;; entire literal. + ((or (null sentence-flag) + (c-one-line-string-p range)) + (goto-char (car range)) + (setq range (c-ascertain-preceding-literal)) + ;; N.B. The following is essentially testing for an AWK regexp + ;; at BOS: + ;; Was the previous non-ws thing an end of statement? + (save-excursion + (if macro-fence + (c-backward-comments) + (c-backward-syntactic-ws)) + (not (or (bobp) (c-after-statement-terminator-p))))) + + ;; Comment inside a statement or a multi-line string. + (t (when (setq res ; returns non-nil when we go out of the literal + (if (eq (c-literal-type range) 'string) + (c-beginning-of-sentence-in-string range) + (c-beginning-of-sentence-in-comment range))) + (setq range (c-ascertain-preceding-literal))) + res))) + + ;; Non-literal code. + (t (setq res (c-back-over-illiterals macro-fence)) + (setq not-bos ; "not reached beginning-of-statement". + (or (= (point) last) + (memq (char-after) '(?\) ?\})) + (and + (car res) + ;; We're at a tentative BOS. The next form goes + ;; back over WS looking for an end of previous + ;; statement. + (not (save-excursion + (if macro-fence + (c-backward-comments) + (c-backward-syntactic-ws)) + (or (bobp) (c-after-statement-terminator-p))))))) + ;; Are we about to move backwards into or out of a + ;; preprocessor command? If so, locate it's beginning. + (when (eq (cdr res) 'macro-boundary) + (save-excursion + (beginning-of-line) + (setq macro-fence + (and (not (bobp)) + (progn (c-skip-ws-backward) (c-beginning-of-macro)) + (point))))) + ;; Are we about to move backwards into a literal? + (when (memq (cdr res) '(macro-boundary literal)) + (setq range (c-ascertain-preceding-literal))) + not-bos)) + (setq last (point))) + + (if (/= count 0) (setq count (1- count)))) + (c-keep-region-active)))) (defun c-end-of-statement (&optional count lim sentence-flag) "Go to the end of the innermost C statement. @@ -1708,8 +2348,77 @@ sentence motion in or near comments and multiline strings." (interactive (list (prefix-numeric-value current-prefix-arg) nil t)) - (c-beginning-of-statement (- (or count 1)) lim sentence-flag) - (c-keep-region-active)) + (setq count (or count 1)) + (if (< count 0) (c-beginning-of-statement (- count) lim sentence-flag) + + (c-save-buffer-state + (here ; start point for going forward ONE statement. Updated each statement. + (macro-fence + (save-excursion + (and (not (eobp)) (c-beginning-of-macro) + (progn (c-end-of-macro) (point))))) + res + (range (c-collect-line-comments (c-literal-limits lim)))) ; (start.end) of current literal or NIL + + ;; Go back/forward one statement at each iteration of the following loop. + (while (and (/= count 0) + (or (not lim) (< (point) lim))) + (setq here (point)) ; ONLY HERE is HERE updated + + ;; Go forward one "chunk" each time round the following loop, stopping + ;; when we reach a statement boundary, etc. + (while + (cond ; Each arm of this cond returns NIL on reaching a desired + ; statement boundary, non-NIL otherwise. + ((eobp) + (setq count 0) + nil) + + (range ; point is within a literal. + (cond + ;; sentence-flag is null => skip the entire literal. + ;; or a Single line string. + ((or (null sentence-flag) + (c-one-line-string-p range)) + (goto-char (cdr range)) + (setq range (c-ascertain-following-literal)) + ;; Is there a virtual semicolon here (e.g. for AWK)? + (not (c-at-vsemi-p))) + + ;; Comment or multi-line string. + (t (when (setq res ; gets non-nil when we go out of the literal + (if (eq (c-literal-type range) 'string) + (c-end-of-sentence-in-string range) + (c-end-of-sentence-in-comment range))) + (setq range (c-ascertain-following-literal))) + ;; If we've just come forward out of a literal, check for + ;; vsemi. (N.B. AWK can't have a vsemi after a comment, but + ;; some other language may do in the future) + (and res + (not (c-at-vsemi-p)))))) + + ;; Non-literal code. + (t (setq res (c-forward-over-illiterals macro-fence + (> (point) here))) + ;; Are we about to move forward into or out of a + ;; preprocessor command? + (when (eq (cdr res) 'macro-boundary) + (save-excursion + (end-of-line) + (setq macro-fence + (and (not (eobp)) + (progn (c-skip-ws-forward) + (c-beginning-of-macro)) + (progn (c-end-of-macro) + (point)))))) + ;; Are we about to move forward into a literal? + (when (memq (cdr res) '(macro-boundary literal)) + (setq range (c-ascertain-following-literal))) + (car res)))) + + (if (/= count 0) (setq count (1- count)))) + (c-keep-region-active)))) + ;; set up electric character functions to work with pending-del, @@ -1737,6 +2446,7 @@ (defun c-calc-comment-indent (entry) + ;; This function might do hidden buffer changes. (if (symbolp entry) (setq entry (or (assq entry c-indent-comment-alist) (assq 'other c-indent-comment-alist) @@ -1760,7 +2470,7 @@ (let ((lim (c-literal-limits (c-point 'bol) t))) (when (consp lim) (goto-char (car lim)) - (when (looking-at "/[/*]") + (when (looking-at "/[/*]") ; FIXME!!! Adapt for AWK! (ACM, 2005/11/18) ;; Found comment to align with. (if (bolp) ;; Do not pad with one space if we're at bol. @@ -1835,15 +2545,16 @@ A prefix argument acts as a repeat count. With a negative argument, move forward to the end of the containing preprocessor conditional. -`#elif' is treated like `#else' followed by `#if', so the function -stops at them when going backward, but not when going forward." +\"#elif\" is treated like \"#else\" followed by \"#if\", so the +function stops at them when going backward, but not when going +forward." (interactive "p") (c-forward-conditional (- count) -1) (c-keep-region-active)) (defun c-up-conditional-with-else (count) - "Move back to the containing preprocessor conditional, including `#else'. -Just like `c-up-conditional', except it also stops at `#else' + "Move back to the containing preprocessor conditional, including \"#else\". +Just like `c-up-conditional', except it also stops at \"#else\" directives." (interactive "p") (c-forward-conditional (- count) -1 t) @@ -1854,15 +2565,16 @@ A prefix argument acts as a repeat count. With a negative argument, move backward into the previous preprocessor conditional. -`#elif' is treated like `#else' followed by `#if', so the function -stops at them when going forward, but not when going backward." +\"#elif\" is treated like \"#else\" followed by \"#if\", so the +function stops at them when going forward, but not when going +backward." (interactive "p") (c-forward-conditional count 1) (c-keep-region-active)) (defun c-down-conditional-with-else (count) - "Move forward into the next preprocessor conditional, including `#else'. -Just like `c-down-conditional', except it also stops at `#else' + "Move forward into the next preprocessor conditional, including \"#else\". +Just like `c-down-conditional', except it also stops at \"#else\" directives." (interactive "p") (c-forward-conditional count 1 t) @@ -1881,16 +2593,16 @@ A prefix argument acts as a repeat count. With a negative argument, move backward across a preprocessor conditional. -`#elif' is treated like `#else' followed by `#if', except that the -nesting level isn't changed when tracking subconditionals. +\"#elif\" is treated like \"#else\" followed by \"#if\", except that +the nesting level isn't changed when tracking subconditionals. The optional argument TARGET-DEPTH specifies the wanted nesting depth after each scan. I.e. if TARGET-DEPTH is -1, the function will move out of the enclosing conditional. A non-integer non-nil TARGET-DEPTH counts as -1. -If the optional argument WITH-ELSE is non-nil, `#else' directives are -treated as conditional clause limits. Normally they are ignored." +If the optional argument WITH-ELSE is non-nil, \"#else\" directives +are treated as conditional clause limits. Normally they are ignored." (interactive "p") (let* ((forward (> count 0)) (increment (if forward -1 1)) @@ -1996,15 +2708,15 @@ just inserts a tab character, or the equivalent number of spaces, depending on the variable `indent-tabs-mode'." - (interactive "p") + (interactive "P") (let ((indent-function (if c-syntactic-indentation (symbol-function 'indent-according-to-mode) (lambda () (let ((c-macro-start c-macro-start) - (steps (cond ((not current-prefix-arg) 1) - ((equal current-prefix-arg '(4)) -1) - (t arg)))) + (steps (if (equal arg '(4)) + -1 + (prefix-numeric-value arg)))) (c-shift-line-indentation (* steps c-basic-offset)) (when (and c-auto-align-backslashes (save-excursion @@ -2014,7 +2726,7 @@ ;; Realign the line continuation backslash if inside a macro. (c-backslash-region (point) (point) nil t))) )))) - (if (and c-syntactic-indentation current-prefix-arg) + (if (and c-syntactic-indentation arg) ;; If c-syntactic-indentation and got arg, always indent this ;; line as C and shift remaining lines of expression the same ;; amount. @@ -2029,7 +2741,7 @@ shift-amt)) (save-excursion (if (eq c-tab-always-indent t) - (beginning-of-line)) + (beginning-of-line)) ; FIXME!!! What is this here for? ACM 2005/10/31 (setq beg (point)) (c-forward-sexp 1) (setq end (point)) @@ -2040,7 +2752,7 @@ (indent-code-rigidly beg end shift-amt "#"))) ;; Else use c-tab-always-indent to determine behavior. (cond - ;; CASE 1: indent when at column zero or in lines indentation, + ;; CASE 1: indent when at column zero or in line's indentation, ;; otherwise insert a tab ((not c-tab-always-indent) (if (save-excursion @@ -2054,7 +2766,7 @@ ;; CASE 3: if in a literal, insert a tab, but always indent the ;; line (t - (if (c-in-literal) + (if (c-save-buffer-state () (c-in-literal)) (funcall c-insert-tab-function)) (funcall indent-function) ))))) @@ -2135,7 +2847,8 @@ ;; shut up any echo msgs on indiv lines (c-echo-syntactic-information-p nil) (in-macro (and c-auto-align-backslashes - (save-excursion (c-beginning-of-macro)) + (c-save-buffer-state () + (save-excursion (c-beginning-of-macro))) start)) (c-fix-backslashes nil) syntax) @@ -2181,8 +2894,6 @@ (defun c-fn-region-is-active-p () ;; Function version of the macro for use in places that aren't ;; compiled, e.g. in the menus. - ;; - ;; This function does not do any hidden buffer changes. (c-region-is-active-p)) (defun c-indent-line-or-region () @@ -2199,7 +2910,6 @@ (defvar c-progress-info nil) (defun c-progress-init (start end context) - ;; This function does not do any hidden buffer changes. (cond ;; Be silent ((not c-progress-interval)) @@ -2221,7 +2931,6 @@ )) (defun c-progress-update () - ;; This function does not do any hidden buffer changes. (if (not (and c-progress-info c-progress-interval)) nil (let ((now (nth 1 (current-time))) @@ -2238,7 +2947,6 @@ ))) (defun c-progress-fini (context) - ;; This function does not do any hidden buffer changes. (if (not c-progress-interval) nil (if (or (eq context (aref c-progress-info 3)) @@ -2399,7 +3107,6 @@ (set-marker point-pos nil)))) (defun c-append-backslashes-forward (to-mark column point-pos) - ;; This function does not do any hidden buffer changes. (let ((state (parse-partial-sexp (c-point 'bol) (point)))) (if column (while @@ -2473,7 +3180,6 @@ (bolp)))))) ; forward-line has funny behavior at eob. (defun c-delete-backslashes-forward (to-mark point-pos) - ;; This function does not do any hidden buffer changes. (while (and (<= (point) to-mark) (progn @@ -2518,6 +3224,8 @@ ;; comment. Return a cons of the prefix string and the column where ;; it ends. If fill-prefix is set, it'll override. Note that this ;; function also uses the value of point in some heuristics. + ;; + ;; This function might do hidden buffer changes. (let* ((here (point)) (prefix-regexp (concat "[ \t]*\\(" @@ -2877,7 +3585,7 @@ ;; If APPLY-OUTSIDE-LITERAL is nil then the function will be called ;; only if the point turns out to be inside a comment or a string. ;; - ;; This function does not do any hidden buffer changes. + ;; Note that this function does not do any hidden buffer changes. (let (fill ;; beg and end limits the region to narrow. end is a marker. @@ -2892,6 +3600,10 @@ ;; hanging. In that case it's set to the number of spaces ;; that should be between the text and the ender. hang-ender-stuck + ;; auto-fill-spaces is the exact sequence of whitespace between a + ;; comment's last word and the comment ender, temporarily replaced + ;; with 'x's before calling FUN when FILL-PARAGRAPH is nil. + auto-fill-spaces (here (point)) (c-lit-limits c-lit-limits) (c-lit-type c-lit-type)) @@ -2902,29 +3614,30 @@ (if (and buffer-undo-list (not (eq buffer-undo-list t))) (setq buffer-undo-list (cons (point) buffer-undo-list))) - (save-restriction - ;; Widen to catch comment limits correctly. - (widen) - (unless c-lit-limits - (setq c-lit-limits (c-literal-limits nil fill-paragraph))) - (setq c-lit-limits (c-collect-line-comments c-lit-limits)) - (unless c-lit-type - (setq c-lit-type (c-literal-type c-lit-limits)))) - - (save-excursion - (unless (c-safe (backward-char) - (forward-paragraph) - (>= (point) here)) - (goto-char here) - (forward-paragraph)) - (setq end (point-marker))) - (save-excursion - (unless (c-safe (forward-char) - (backward-paragraph) - (<= (point) here)) - (goto-char here) - (backward-paragraph)) - (setq beg (point))) + (c-save-buffer-state () + (save-restriction + ;; Widen to catch comment limits correctly. + (widen) + (unless c-lit-limits + (setq c-lit-limits (c-literal-limits nil fill-paragraph))) + (setq c-lit-limits (c-collect-line-comments c-lit-limits)) + (unless c-lit-type + (setq c-lit-type (c-literal-type c-lit-limits)))) + + (save-excursion + (unless (c-safe (backward-char) + (forward-paragraph) + (>= (point) here)) + (goto-char here) + (forward-paragraph)) + (setq end (point-marker))) + (save-excursion + (unless (c-safe (forward-char) + (backward-paragraph) + (<= (point) here)) + (goto-char here) + (backward-paragraph)) + (setq beg (point)))) (unwind-protect (progn @@ -2965,73 +3678,76 @@ ;; own. Keep it that way. (set-marker end (point)))) - (if fill-paragraph - ;; The comment ender should hang. Replace all - ;; cruft between it and the last word with one or - ;; two 'x' and include it in the region. We'll - ;; change them back to spaces afterwards. This - ;; isn't done when auto filling, since that'd - ;; effectively make it impossible to insert extra - ;; spaces before the comment ender. - (let* ((ender-start (save-excursion - (goto-char (cdr c-lit-limits)) - (skip-syntax-backward "^w ") - (point))) - (point-rel (- ender-start here)) - spaces) - - (save-excursion - (goto-char (cdr c-lit-limits)) - (setq tmp-post (point-marker)) - (insert ?\n) - (set-marker end (point)) - (forward-line -1) - (if (and (looking-at (concat "[ \t]*\\(\\(" - c-current-comment-prefix - "\\)[ \t]*\\)")) - (eq ender-start (match-end 0))) - ;; The comment ender is prefixed by nothing - ;; but a comment line prefix. Remove it - ;; along with surrounding ws. - (setq spaces (- (match-end 1) (match-end 2))) - (goto-char ender-start)) - (skip-chars-backward " \t\r\n") - - (if (/= (point) ender-start) - (progn - (if (<= here (point)) - ;; Don't adjust point below if it's - ;; before the string we replace. - (setq point-rel -1)) - ;; Keep one or two spaces between the - ;; text and the ender, depending on how - ;; many there are now. - (unless spaces - (setq spaces (- ender-start (point)))) + ;; The comment ender should hang. Replace all space between + ;; it and the last word either by one or two 'x's (when + ;; FILL-PARAGRAPH is non-nil), or a row of x's the same width + ;; as the whitespace (when auto filling), and include it in + ;; the region. We'll change them back to whitespace + ;; afterwards. The effect of this is to glue the comment + ;; ender to the last word in the comment during filling. + (let* ((ender-start (save-excursion + (goto-char (cdr c-lit-limits)) + (skip-syntax-backward "^w ") + (point))) + (ender-column (save-excursion + (goto-char ender-start) + (current-column))) + (point-rel (- ender-start here)) + spaces) + + (save-excursion + (goto-char (cdr c-lit-limits)) + (setq tmp-post (point-marker)) + (insert ?\n) + (set-marker end (point)) + (forward-line -1) ; last line of the comment + (if (and (looking-at (concat "[ \t]*\\(\\(" + c-current-comment-prefix + "\\)[ \t]*\\)")) + (eq ender-start (match-end 0))) + ;; The comment ender is prefixed by nothing + ;; but a comment line prefix. Remove it + ;; along with surrounding ws. + (setq spaces (- (match-end 1) (match-end 2))) + (goto-char ender-start)) + (skip-chars-backward " \t\r\n") ; Surely this can be + ; " \t"? "*/" is NOT alone on the line (ACM, 2005/8/18) + + (if (/= (point) ender-start) + (progn + (if (<= here (point)) + ;; Don't adjust point below if it's + ;; before the string we replace. + (setq point-rel -1)) + ;; Keep one or two spaces between the + ;; text and the ender, depending on how + ;; many there are now. + (unless spaces + (setq spaces (- ender-column (current-column)))) + (setq auto-fill-spaces (c-delete-and-extract-region + (point) ender-start)) + ;; paragraph filling condenses multiple spaces to + ;; single or double spaces. auto-fill doesn't. + (if fill-paragraph (setq spaces (max (min spaces (if sentence-end-double-space 2 1)) - 1)) - ;; Insert the filler first to keep marks right. - (insert-char ?x spaces t) - (delete-region (point) (+ ender-start spaces)) - (setq hang-ender-stuck spaces) - (setq point-rel - (and (>= point-rel 0) - (- (point) (min point-rel spaces))))) - (setq point-rel nil))) - - (if point-rel - ;; Point was in the middle of the string we - ;; replaced above, so put it back in the same - ;; relative position, counting from the end. - (goto-char point-rel))) - - ;; We're doing auto filling. Just move the marker - ;; to the comment end to ignore any code after the - ;; comment. - (move-marker end (cdr c-lit-limits))))) + 1))) + ;; Insert the filler first to keep marks right. + (insert-char ?x spaces t) + (setq hang-ender-stuck spaces) + (setq point-rel + (and (>= point-rel 0) + (- (point) (min point-rel spaces))))) + (setq point-rel nil))) + + (if point-rel + ;; Point was in the middle of the string we + ;; replaced above, so put it back in the same + ;; relative position, counting from the end. + (goto-char point-rel))) + )) (when (<= beg (car c-lit-limits)) ;; The region includes the comment starter. @@ -3068,14 +3784,15 @@ ;; inside macros is bogus to begin with since the line ;; continuation backslashes aren't handled). (save-excursion - (c-beginning-of-macro) - (beginning-of-line) - (if (> (point) beg) - (setq beg (point))) - (c-end-of-macro) - (forward-line) - (if (< (point) end) - (set-marker end (point))))) + (c-save-buffer-state () + (c-beginning-of-macro) + (beginning-of-line) + (if (> (point) beg) + (setq beg (point))) + (c-end-of-macro) + (forward-line) + (if (< (point) end) + (set-marker end (point)))))) (t ; Other code. ;; Try to avoid comments and macros in the paragraph to @@ -3192,7 +3909,10 @@ (goto-char tmp-post) (skip-syntax-backward "^w ") (forward-char (- hang-ender-stuck)) - (insert-char ?\ hang-ender-stuck t) + (if (or fill-paragraph (not auto-fill-spaces)) + (insert-char ?\ hang-ender-stuck t) + (insert auto-fill-spaces) + (setq here (- here (- hang-ender-stuck (length auto-fill-spaces))))) (delete-char hang-ender-stuck) (goto-char here)) (set-marker tmp-post nil)) @@ -3233,8 +3953,6 @@ (defun c-do-auto-fill () ;; Do automatic filling if not inside a context where it should be ;; ignored. - ;; - ;; This function does not do any hidden buffer changes. (let ((c-auto-fill-prefix ;; The decision whether the line should be broken is actually ;; done in c-indent-new-comment-line, which do-auto-fill @@ -3274,31 +3992,36 @@ (c-lit-limits c-lit-limits) (c-lit-type c-lit-type) (c-macro-start c-macro-start)) - (when (not (eq c-auto-fill-prefix t)) - ;; Called from do-auto-fill. - (unless c-lit-limits - (setq c-lit-limits (c-literal-limits nil nil t))) - (unless c-lit-type - (setq c-lit-type (c-literal-type c-lit-limits))) - (if (memq (cond ((c-query-and-set-macro-start) 'cpp) - ((null c-lit-type) 'code) - (t c-lit-type)) - c-ignore-auto-fill) - (setq fill-prefix t) ; Used as flag in the cond. - (if (and (null c-auto-fill-prefix) - (eq c-lit-type 'c) - (<= (c-point 'bol) (car c-lit-limits))) - ;; The adaptive fill function has generated a prefix, but - ;; we're on the first line in a block comment so it'll be - ;; wrong. Ignore it to guess a better one below. - (setq fill-prefix nil) - (when (and (eq c-lit-type 'c++) - (not (string-match "\\`[ \t]*//" (or fill-prefix "")))) - ;; Kludge: If the function that adapted the fill prefix - ;; doesn't produce the required comment starter for line - ;; comments, then we ignore it. - (setq fill-prefix nil))) - )) + + (c-save-buffer-state () + (when (not (eq c-auto-fill-prefix t)) + ;; Called from do-auto-fill. + (unless c-lit-limits + (setq c-lit-limits (c-literal-limits nil nil t))) + (unless c-lit-type + (setq c-lit-type (c-literal-type c-lit-limits))) + (if (memq (cond ((c-query-and-set-macro-start) 'cpp) + ((null c-lit-type) 'code) + (t c-lit-type)) + c-ignore-auto-fill) + (setq fill-prefix t) ; Used as flag in the cond. + (if (and (null c-auto-fill-prefix) + (eq c-lit-type 'c) + (<= (c-point 'bol) (car c-lit-limits))) + ;; The adaptive fill function has generated a prefix, but + ;; we're on the first line in a block comment so it'll be + ;; wrong. Ignore it to guess a better one below. + (setq fill-prefix nil) + (when (and (eq c-lit-type 'c++) + (not (string-match (concat "\\`[ \t]*" + c-line-comment-starter) + (or fill-prefix "")))) + ;; Kludge: If the function that adapted the fill prefix + ;; doesn't produce the required comment starter for line + ;; comments, then we ignore it. + (setq fill-prefix nil))) + ))) + (cond ((eq fill-prefix t) ;; A call from do-auto-fill which should be ignored. ) @@ -3306,7 +4029,7 @@ ;; A fill-prefix overrides anything. (funcall do-line-break) (insert-and-inherit fill-prefix)) - ((progn + ((c-save-buffer-state () (unless c-lit-limits (setq c-lit-limits (c-literal-limits))) (unless c-lit-type @@ -3440,31 +4163,38 @@ comment prefix (see the `c-comment-prefix-regexp' and `c-block-comment-prefix' variables for details). The end of a C++-style line comment doesn't count as inside it." + (interactive "*") - (let* ((c-lit-limits (c-literal-limits nil nil t)) - (c-lit-type (c-literal-type c-lit-limits)) + (let* (c-lit-limits c-lit-type (c-macro-start c-macro-start)) - (if (or (eq c-lit-type 'c) - (and (eq c-lit-type 'c++) - (< (save-excursion - (skip-chars-forward " \t") - (point)) - (1- (cdr (setq c-lit-limits - (c-collect-line-comments c-lit-limits)))))) - (and (or (not (looking-at "\\s *$")) - (eq (char-before) ?\\)) - (c-query-and-set-macro-start) - (<= (save-excursion - (goto-char c-macro-start) - (if (looking-at c-opt-cpp-start) - (goto-char (match-end 0))) - (point)) - (point)))) + + (if (c-save-buffer-state () + (setq c-lit-limits (c-literal-limits nil nil t) + c-lit-type (c-literal-type c-lit-limits)) + (or (eq c-lit-type 'c) + (and (eq c-lit-type 'c++) + (< (save-excursion + (skip-chars-forward " \t") + (point)) + (1- (cdr (setq c-lit-limits (c-collect-line-comments + c-lit-limits)))))) + (and (or (not (looking-at "\\s *$")) + (eq (char-before) ?\\)) + (c-query-and-set-macro-start) + (<= (save-excursion + (goto-char c-macro-start) + (if (looking-at c-opt-cpp-start) + (goto-char (match-end 0))) + (point)) + (point))))) + (let ((comment-multi-line t) (fill-prefix nil)) (c-indent-new-comment-line nil t)) + (delete-horizontal-space) (newline) + ;; c-indent-line may look at the current indentation, so let's ;; start out with the same indentation as the previous line. (let ((col (save-excursion @@ -3473,6 +4203,7 @@ (= (forward-line -1) 0))) (current-indentation)))) (indent-to col)) + (indent-according-to-mode)))) (defun c-context-open-line ()
--- a/lisp/progmodes/cc-compat.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/progmodes/cc-compat.el Sat Dec 10 21:18:28 2005 +0000 @@ -1,6 +1,7 @@ ;;; cc-compat.el --- cc-mode compatibility with c-mode.el confusion -;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, Inc. +;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, +;; Inc. ;; Authors: 1998- Martin Stjernholm ;; 1994-1999 Barry A. Warsaw @@ -22,7 +23,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to +;; along with this program; see the file COPYING. If not, write to ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA.
--- a/lisp/progmodes/cc-defs.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/progmodes/cc-defs.el Sat Dec 10 21:18:28 2005 +0000 @@ -1,6 +1,7 @@ ;;; cc-defs.el --- compile time definitions for CC Mode -;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, Inc. +;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, +;; Inc. ;; Authors: 1998- Martin Stjernholm ;; 1992-1999 Barry A. Warsaw @@ -24,7 +25,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to +;; along with this program; see the file COPYING. If not, write to ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. @@ -43,8 +44,8 @@ load-path))) (load "cc-bytecomp" nil t))) -;; `require' in XEmacs doesn't have the third NOERROR argument. -(condition-case nil (require 'regexp-opt) (file-error nil)) +(eval-when-compile (require 'cl)) ; was (cc-external-require 'cl). ACM 2005/11/29. +(cc-external-require 'regexp-opt) ;; Silence the compiler. (cc-bytecomp-defvar c-enable-xemacs-performance-kludge-p) ; In cc-vars.el @@ -55,31 +56,18 @@ (cc-bytecomp-defvar mark-active) ; Emacs (cc-bytecomp-defvar deactivate-mark) ; Emacs (cc-bytecomp-defvar inhibit-point-motion-hooks) ; Emacs -(cc-bytecomp-defvar parse-sexp-lookup-properties) ; Emacs 20+ +(cc-bytecomp-defvar parse-sexp-lookup-properties) ; Emacs (cc-bytecomp-defvar text-property-default-nonsticky) ; Emacs 21 -(cc-bytecomp-defvar lookup-syntax-properties) ; XEmacs 21 +(cc-bytecomp-defvar lookup-syntax-properties) ; XEmacs (cc-bytecomp-defun string-to-syntax) ; Emacs 21 -(cc-bytecomp-defun regexp-opt-depth) ; (X)Emacs 20+ ;; cc-fix.el contains compatibility macros that should be used if ;; needed. (eval-and-compile - (if (or (not (fboundp 'functionp)) - (not (condition-case nil - (progn (eval '(char-before)) t) - (error nil))) - (not (condition-case nil - (progn (eval '(char-after)) t) - (error nil))) - (not (fboundp 'when)) - (not (fboundp 'unless)) - (not (fboundp 'regexp-opt)) - (not (cc-bytecomp-fboundp 'regexp-opt-depth)) - (/= (regexp-opt-depth "\\(\\(\\)\\)") 2)) - (cc-load "cc-fix") - (defalias 'c-regexp-opt 'regexp-opt) - (defalias 'c-regexp-opt-depth 'regexp-opt-depth))) + (if (or (/= (regexp-opt-depth "\\(\\(\\)\\)") 2) + (not (fboundp 'push))) + (cc-load "cc-fix"))) (eval-after-load "font-lock" '(if (and (not (featurep 'cc-fix)) ; only load the file once. @@ -99,12 +87,10 @@ font-lock-keywords))) (cc-load "cc-fix"))) -(eval-when-compile (require 'cl)) - ;;; Variables also used at compile time. -(defconst c-version "5.30.10" +(defconst c-version "5.31" "CC Mode version number.") (defconst c-version-sym (intern c-version)) @@ -192,29 +178,29 @@ The current point is used if POINT isn't specified. POSITION can be one of the following symbols: -`bol' -- beginning of line -`eol' -- end of line -`bod' -- beginning of defun -`eod' -- end of defun -`boi' -- beginning of indentation -`ionl' -- indentation of next line -`iopl' -- indentation of previous line -`bonl' -- beginning of next line -`eonl' -- end of next line -`bopl' -- beginning of previous line -`eopl' -- end of previous line +`bol' -- beginning of line +`eol' -- end of line +`bod' -- beginning of defun +`eod' -- end of defun +`boi' -- beginning of indentation +`ionl' -- indentation of next line +`iopl' -- indentation of previous line +`bonl' -- beginning of next line +`eonl' -- end of next line +`bopl' -- beginning of previous line +`eopl' -- end of previous line +`bosws' -- beginning of syntactic whitespace +`eosws' -- end of syntactic whitespace If the referenced position doesn't exist, the closest accessible point -to it is returned. This function does not modify point or mark. - -This function does not do any hidden buffer changes." +to it is returned. This function does not modify the point or the mark." (if (eq (car-safe position) 'quote) (let ((position (eval position))) (cond ((eq position 'bol) - (if (and (fboundp 'line-beginning-position) (not point)) + (if (and (cc-bytecomp-fboundp 'line-beginning-position) (not point)) `(line-beginning-position) `(save-excursion ,@(if point `((goto-char ,point))) @@ -222,7 +208,7 @@ (point)))) ((eq position 'eol) - (if (and (fboundp 'line-end-position) (not point)) + (if (and (cc-bytecomp-fboundp 'line-end-position) (not point)) `(line-end-position) `(save-excursion ,@(if point `((goto-char ,point))) @@ -248,7 +234,7 @@ (point))) ((eq position 'bopl) - (if (and (fboundp 'line-beginning-position) (not point)) + (if (and (cc-bytecomp-fboundp 'line-beginning-position) (not point)) `(line-beginning-position 0) `(save-excursion ,@(if point `((goto-char ,point))) @@ -256,7 +242,7 @@ (point)))) ((eq position 'bonl) - (if (and (fboundp 'line-beginning-position) (not point)) + (if (and (cc-bytecomp-fboundp 'line-beginning-position) (not point)) `(line-beginning-position 2) `(save-excursion ,@(if point `((goto-char ,point))) @@ -264,7 +250,7 @@ (point)))) ((eq position 'eopl) - (if (and (fboundp 'line-end-position) (not point)) + (if (and (cc-bytecomp-fboundp 'line-end-position) (not point)) `(line-end-position 0) `(save-excursion ,@(if point `((goto-char ,point))) @@ -273,7 +259,7 @@ (point)))) ((eq position 'eonl) - (if (and (fboundp 'line-end-position) (not point)) + (if (and (cc-bytecomp-fboundp 'line-end-position) (not point)) `(line-end-position 2) `(save-excursion ,@(if point `((goto-char ,point))) @@ -295,54 +281,138 @@ (back-to-indentation) (point))) + ((eq position 'bosws) + `(save-excursion + ,@(if point `((goto-char ,point))) + (c-backward-syntactic-ws) + (point))) + + ((eq position 'eosws) + `(save-excursion + ,@(if point `((goto-char ,point))) + (c-forward-syntactic-ws) + (point))) + (t (error "Unknown buffer position requested: %s" position)))) - ;;(message "c-point long expansion") + ;; The bulk of this should perhaps be in a function to avoid large + ;; expansions, but this case is not used anywhere in CC Mode (and + ;; probably not anywhere else either) so we only have it to be on + ;; the safe side. + (message "Warning: c-point long expansion") `(save-excursion ,@(if point `((goto-char ,point))) (let ((position ,position)) (cond - ((eq position 'bol) (beginning-of-line)) - ((eq position 'eol) (end-of-line)) - ((eq position 'boi) (back-to-indentation)) - ((eq position 'bod) (c-beginning-of-defun-1)) - ((eq position 'eod) (c-end-of-defun-1)) - ((eq position 'bopl) (forward-line -1)) - ((eq position 'bonl) (forward-line 1)) - ((eq position 'eopl) (progn - (beginning-of-line) - (or (bobp) (backward-char)))) - ((eq position 'eonl) (progn - (forward-line 1) - (end-of-line))) - ((eq position 'iopl) (progn - (forward-line -1) - (back-to-indentation))) - ((eq position 'ionl) (progn - (forward-line 1) - (back-to-indentation))) + ((eq position 'bol) (beginning-of-line)) + ((eq position 'eol) (end-of-line)) + ((eq position 'boi) (back-to-indentation)) + ((eq position 'bod) (c-beginning-of-defun-1)) + ((eq position 'eod) (c-end-of-defun-1)) + ((eq position 'bopl) (forward-line -1)) + ((eq position 'bonl) (forward-line 1)) + ((eq position 'eopl) (progn + (beginning-of-line) + (or (bobp) (backward-char)))) + ((eq position 'eonl) (progn + (forward-line 1) + (end-of-line))) + ((eq position 'iopl) (progn + (forward-line -1) + (back-to-indentation))) + ((eq position 'ionl) (progn + (forward-line 1) + (back-to-indentation))) + ((eq position 'bosws) (c-backward-syntactic-ws)) + ((eq position 'eosws) (c-forward-syntactic-ws)) (t (error "Unknown buffer position requested: %s" position)))) (point)))) +(defmacro c-region-is-active-p () + ;; Return t when the region is active. The determination of region + ;; activeness is different in both Emacs and XEmacs. + (if (cc-bytecomp-fboundp 'region-active-p) + ;; XEmacs. + '(region-active-p) + ;; Emacs. + 'mark-active)) + +(defmacro c-set-region-active (activate) + ;; Activate the region if ACTIVE is non-nil, deactivate it + ;; otherwise. Covers the differences between Emacs and XEmacs. + (if (cc-bytecomp-fboundp 'zmacs-activate-region) + ;; XEmacs. + `(if ,activate + (zmacs-activate-region) + (zmacs-deactivate-region)) + ;; Emacs. + `(setq mark-active ,activate))) + +(defmacro c-delete-and-extract-region (start end) + "Delete the text between START and END and return it." + (if (cc-bytecomp-fboundp 'delete-and-extract-region) + ;; Emacs 21.1 and later + `(delete-and-extract-region ,start ,end) + ;; XEmacs and Emacs 20.x + `(prog1 + (buffer-substring ,start ,end) + (delete-region ,start ,end)))) + (defmacro c-safe (&rest body) ;; safely execute BODY, return nil if an error occurred - ;; - ;; This function does not do any hidden buffer changes. `(condition-case nil (progn ,@body) (error nil))) (put 'c-safe 'lisp-indent-function 0) +(defmacro c-int-to-char (integer) + ;; In GNU Emacs, a character is an integer. In XEmacs, a character is a + ;; type distinct from an integer. Sometimes we need to convert integers to + ;; characters. `c-int-to-char' makes this conversion, if necessary. + (if (fboundp 'int-to-char) + `(int-to-char ,integer) + integer)) + +(defmacro c-sentence-end () + ;; Get the regular expression `sentence-end'. + (if (cc-bytecomp-fboundp 'sentence-end) + ;; Emacs 22: + `(sentence-end) + ;; Emacs <22 + XEmacs + `sentence-end)) + +(defmacro c-default-value-sentence-end () + ;; Get the default value of the variable sentence end. + (if (cc-bytecomp-fboundp 'sentence-end) + ;; Emacs 22: + `(let (sentence-end) (sentence-end)) + ;; Emacs <22 + XEmacs + `(default-value 'sentence-end))) + ;; The following is essentially `save-buffer-state' from lazy-lock.el. ;; It ought to be a standard macro. (defmacro c-save-buffer-state (varlist &rest body) "Bind variables according to VARLIST (in `let*' style) and eval BODY, then restore the buffer state under the assumption that no significant -modification has been made. A change is considered significant if it -affects the buffer text in any way that isn't completely restored -again. Changes in text properties like `face' or `syntax-table' are -considered insignificant. This macro allows text properties to be -changed, even in a read-only buffer. +modification has been made in BODY. A change is considered +significant if it affects the buffer text in any way that isn't +completely restored again. Changes in text properties like `face' or +`syntax-table' are considered insignificant. This macro allows text +properties to be changed, even in a read-only buffer. + +This macro should be placed around all calculations which set +\"insignificant\" text properties in a buffer, even when the buffer is +known to be writeable. That way, these text properties remain set +even if the user undoes the command which set them. + +This macro should ALWAYS be placed around \"temporary\" internal buffer +changes \(like adding a newline to calculate a text-property then +deleting it again\), so that the user never sees them on his +`buffer-undo-list'. See also `c-tentative-buffer-changes'. + +However, any user-visible changes to the buffer \(like auto-newlines\) +must not be within a `c-save-buffer-state', since the user then +wouldn't be able to undo them. The return value is the value of the last form in BODY." `(let* ((modified (buffer-modified-p)) (buffer-undo-list t) @@ -350,12 +420,80 @@ before-change-functions after-change-functions deactivate-mark ,@varlist) - (prog1 (progn ,@body) + (unwind-protect + (progn ,@body) (and (not modified) (buffer-modified-p) (set-buffer-modified-p nil))))) (put 'c-save-buffer-state 'lisp-indent-function 1) +(defmacro c-tentative-buffer-changes (&rest body) + "Eval BODY and optionally restore the buffer contents to the state it +was in before BODY. Any changes are kept if the last form in BODY +returns non-nil. Otherwise it's undone using the undo facility, and +various other buffer state that might be affected by the changes is +restored. That includes the current buffer, point, mark, mark +activation \(similar to `save-excursion'), and the modified state. +The state is also restored if BODY exits nonlocally. + +If BODY makes a change that unconditionally is undone then wrap this +macro inside `c-save-buffer-state'. That way the change can be done +even when the buffer is read-only, and without interference from +various buffer change hooks." + `(let (-tnt-chng-keep + -tnt-chng-state) + (unwind-protect + ;; Insert an undo boundary for use with `undo-more'. We + ;; don't use `undo-boundary' since it doesn't insert one + ;; unconditionally. + (setq buffer-undo-list (cons nil buffer-undo-list) + -tnt-chng-state (c-tnt-chng-record-state) + -tnt-chng-keep (progn ,@body)) + (c-tnt-chng-cleanup -tnt-chng-keep -tnt-chng-state)))) +(put 'c-tentative-buffer-changes 'lisp-indent-function 0) + +(defun c-tnt-chng-record-state () + ;; Used internally in `c-tentative-buffer-changes'. + (vector buffer-undo-list ; 0 + (current-buffer) ; 1 + ;; No need to use markers for the point and mark; if the + ;; undo got out of synch we're hosed anyway. + (point) ; 2 + (mark t) ; 3 + (c-region-is-active-p) ; 4 + (buffer-modified-p))) ; 5 + +(defun c-tnt-chng-cleanup (keep saved-state) + ;; Used internally in `c-tentative-buffer-changes'. + + (let ((saved-undo-list (elt saved-state 0))) + (if (eq buffer-undo-list saved-undo-list) + ;; No change was done afterall. + (setq buffer-undo-list (cdr saved-undo-list)) + + (if keep + ;; Find and remove the undo boundary. + (let ((p buffer-undo-list)) + (while (not (eq (cdr p) saved-undo-list)) + (setq p (cdr p))) + (setcdr p (cdr saved-undo-list))) + + ;; `primitive-undo' will remove the boundary. + (setq saved-undo-list (cdr saved-undo-list)) + (let ((undo-in-progress t)) + (while (not (eq (setq buffer-undo-list + (primitive-undo 1 buffer-undo-list)) + saved-undo-list)))) + + (when (buffer-live-p (elt saved-state 1)) + (set-buffer (elt saved-state 1)) + (goto-char (elt saved-state 2)) + (set-mark (elt saved-state 3)) + (c-set-region-active (elt saved-state 4)) + (and (not (elt saved-state 5)) + (buffer-modified-p) + (set-buffer-modified-p nil))))))) + (defmacro c-forward-syntactic-ws (&optional limit) "Forward skip over syntactic whitespace. Syntactic whitespace is defined as whitespace characters, comments, @@ -402,91 +540,127 @@ This is like `forward-sexp' except that it isn't interactive and does not do any user friendly adjustments of the point and that it isn't susceptible to user configurations such as disabling of signals in -certain situations. - -This function does not do any hidden buffer changes." +certain situations." (or count (setq count 1)) - `(goto-char (or (scan-sexps (point) ,count) - ,(if (numberp count) - (if (> count 0) `(point-max) `(point-min)) - `(if (> ,count 0) (point-max) (point-min)))))) + `(goto-char (scan-sexps (point) ,count))) (defmacro c-backward-sexp (&optional count) "See `c-forward-sexp' and reverse directions." (or count (setq count 1)) `(c-forward-sexp ,(if (numberp count) (- count) `(- ,count)))) -(defmacro c-safe-scan-lists (from count depth) - "Like `scan-lists' but returns nil instead of signaling errors. +(defmacro c-safe-scan-lists (from count depth &optional limit) + "Like `scan-lists' but returns nil instead of signalling errors +for unbalanced parens. -This function does not do any hidden buffer changes." - (if (featurep 'xemacs) - `(scan-lists ,from ,count ,depth nil t) - `(c-safe (scan-lists ,from ,count ,depth)))) +A limit for the search may be given. FROM is assumed to be on the +right side of it." + (let ((res (if (featurep 'xemacs) + `(scan-lists ,from ,count ,depth nil t) + `(c-safe (scan-lists ,from ,count ,depth))))) + (if limit + `(save-restriction + ,(if (numberp count) + (if (< count 0) + `(narrow-to-region ,limit (point-max)) + `(narrow-to-region (point-min) ,limit)) + `(if (< ,count 0) + (narrow-to-region ,limit (point-max)) + (narrow-to-region (point-min) ,limit))) + ,res) + res))) ;; Wrappers for common scan-lists cases, mainly because it's almost ;; impossible to get a feel for how that function works. -(defmacro c-up-list-forward (&optional pos) +(defmacro c-up-list-forward (&optional pos limit) "Return the first position after the list sexp containing POS, or nil if no such position exists. The point is used if POS is left out. -This function does not do any hidden buffer changes." - `(c-safe-scan-lists ,(or pos `(point)) 1 1)) +A limit for the search may be given. The start position is assumed to +be before it." + `(c-safe-scan-lists ,(or pos `(point)) 1 1 ,limit)) -(defmacro c-up-list-backward (&optional pos) +(defmacro c-up-list-backward (&optional pos limit) "Return the position of the start of the list sexp containing POS, or nil if no such position exists. The point is used if POS is left out. -This function does not do any hidden buffer changes." - `(c-safe-scan-lists ,(or pos `(point)) -1 1)) +A limit for the search may be given. The start position is assumed to +be after it." + `(c-safe-scan-lists ,(or pos `(point)) -1 1 ,limit)) -(defmacro c-down-list-forward (&optional pos) +(defmacro c-down-list-forward (&optional pos limit) "Return the first position inside the first list sexp after POS, or nil if no such position exists. The point is used if POS is left out. -This function does not do any hidden buffer changes." - `(c-safe-scan-lists ,(or pos `(point)) 1 -1)) +A limit for the search may be given. The start position is assumed to +be before it." + `(c-safe-scan-lists ,(or pos `(point)) 1 -1 ,limit)) -(defmacro c-down-list-backward (&optional pos) +(defmacro c-down-list-backward (&optional pos limit) "Return the last position inside the last list sexp before POS, or nil if no such position exists. The point is used if POS is left out. -This function does not do any hidden buffer changes." - `(c-safe-scan-lists ,(or pos `(point)) -1 -1)) +A limit for the search may be given. The start position is assumed to +be after it." + `(c-safe-scan-lists ,(or pos `(point)) -1 -1 ,limit)) -(defmacro c-go-up-list-forward (&optional pos) +(defmacro c-go-up-list-forward (&optional pos limit) "Move the point to the first position after the list sexp containing POS, -or the point if POS is left out. Return t if such a position exists, -otherwise nil is returned and the point isn't moved. +or containing the point if POS is left out. Return t if such a +position exists, otherwise nil is returned and the point isn't moved. -This function does not do any hidden buffer changes." - `(c-safe (goto-char (scan-lists ,(or pos `(point)) 1 1)) t)) +A limit for the search may be given. The start position is assumed to +be before it." + (let ((res `(c-safe (goto-char (scan-lists ,(or pos `(point)) 1 1)) t))) + (if limit + `(save-restriction + (narrow-to-region (point-min) ,limit) + ,res) + res))) -(defmacro c-go-up-list-backward (&optional pos) +(defmacro c-go-up-list-backward (&optional pos limit) "Move the point to the position of the start of the list sexp containing POS, -or the point if POS is left out. Return t if such a position exists, -otherwise nil is returned and the point isn't moved. +or containing the point if POS is left out. Return t if such a +position exists, otherwise nil is returned and the point isn't moved. -This function does not do any hidden buffer changes." - `(c-safe (goto-char (scan-lists ,(or pos `(point)) -1 1)) t)) +A limit for the search may be given. The start position is assumed to +be after it." + (let ((res `(c-safe (goto-char (scan-lists ,(or pos `(point)) -1 1)) t))) + (if limit + `(save-restriction + (narrow-to-region ,limit (point-max)) + ,res) + res))) -(defmacro c-go-down-list-forward (&optional pos) +(defmacro c-go-down-list-forward (&optional pos limit) "Move the point to the first position inside the first list sexp after POS, -or the point if POS is left out. Return t if such a position exists, -otherwise nil is returned and the point isn't moved. +or before the point if POS is left out. Return t if such a position +exists, otherwise nil is returned and the point isn't moved. -This function does not do any hidden buffer changes." - `(c-safe (goto-char (scan-lists ,(or pos `(point)) 1 -1)) t)) +A limit for the search may be given. The start position is assumed to +be before it." + (let ((res `(c-safe (goto-char (scan-lists ,(or pos `(point)) 1 -1)) t))) + (if limit + `(save-restriction + (narrow-to-region (point-min) ,limit) + ,res) + res))) -(defmacro c-go-down-list-backward (&optional pos) +(defmacro c-go-down-list-backward (&optional pos limit) "Move the point to the last position inside the last list sexp before POS, -or the point if POS is left out. Return t if such a position exists, -otherwise nil is returned and the point isn't moved. +or before the point if POS is left out. Return t if such a position +exists, otherwise nil is returned and the point isn't moved. -This function does not do any hidden buffer changes." - `(c-safe (goto-char (scan-lists ,(or pos `(point)) -1 -1)) t)) +A limit for the search may be given. The start position is assumed to +be after it." + (let ((res `(c-safe (goto-char (scan-lists ,(or pos `(point)) -1 -1)) t))) + (if limit + `(save-restriction + (narrow-to-region ,limit (point-max)) + ,res) + res))) (defmacro c-beginning-of-defun-1 () @@ -501,8 +675,6 @@ ;; This is really a bit too large to be a macro but that isn't a ;; problem as long as it only is used in one place in ;; `c-parse-state'. - ;; - ;; This function does not do any hidden buffer changes. `(progn (if (and ,(cc-bytecomp-fboundp 'buffer-syntactic-context-depth) @@ -542,31 +714,84 @@ (looking-at defun-prompt-regexp) (goto-char (match-end 0))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; V i r t u a l S e m i c o l o n s +;; +;; In most CC Mode languages, statements are terminated explicitly by +;; semicolons or closing braces. In some of the CC modes (currently only AWK +;; Mode (April 2004)), statements are (or can be) terminated by EOLs. Such a +;; statement is said to be terminated by a "virtual semicolon" (VS). A +;; statement terminated by an actual semicolon or brace is never considered to +;; have a VS. +;; +;; The indentation engine (or whatever) tests for a VS at a specific position +;; by invoking the macro `c-at-vsemi-p', which in its turn calls the mode +;; specific function (if any) which is the value of the language variable +;; `c-at-vsemi-p-fn'. The actual details of what constitutes a VS in a +;; language are thus encapsulated in code specific to that language +;; (e.g. cc-awk.el). `c-at-vsemi-p' returns non-nil if point (or the optional +;; parameter POS) is at a VS, nil otherwise. +;; +;; The language specific function might well do extensive analysis of the +;; source text, and may use a cacheing scheme to speed up repeated calls. +;; +;; The "virtual semicolon" lies just after the last non-ws token on the line. +;; Like POINT, it is considered to lie between two characters. For example, +;; at the place shown in the following AWK source line: +;; +;; kbyte = 1024 # 1000 if you're not picky +;; ^ +;; | +;; Virtual Semicolon +;; +;; In addition to `c-at-vsemi-p-fn', a mode may need to supply a function for +;; `c-vsemi-status-unknown-p-fn'. The macro `c-vsemi-status-unknown-p' is a +;; rather recondite kludge. It exists because the function +;; `c-beginning-of-statement-1' sometimes tests for VSs as an optimisation, +;; but `c-at-vsemi-p' might well need to call `c-beginning-of-statement-1' in +;; its calculations, thus potentially leading to infinite recursion. +;; +;; The macro `c-vsemi-status-unknown-p' resolves this problem; it may return +;; non-nil at any time; returning nil is a guarantee that an immediate +;; invocation of `c-at-vsemi-p' at point will NOT call +;; `c-beginning-of-statement-1'. `c-vsemi-status-unknown-p' may not itself +;; call `c-beginning-of-statement-1'. +;; +;; The macro `c-vsemi-status-unknown-p' will typically check the cacheing +;; scheme used by the `c-at-vsemp-p-fn', hence the name - the status is +;; "unknown" if there is no cache entry current for the line. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defmacro c-at-vsemi-p (&optional pos) + ;; Is there a virtual semicolon (not a real one or a }) at POS (defaults to + ;; point)? Always returns nil for languages which don't have Virtual + ;; semicolons. + ;; This macro might do hidden buffer changes. + `(if c-at-vsemi-p-fn + (funcall c-at-vsemi-p-fn ,@(if pos `(,pos))))) + +(defmacro c-vsemi-status-unknown-p () + ;; Return NIL only if it can be guaranteed that an immediate + ;; (c-at-vsemi-p) will NOT call c-beginning-of-statement-1. Otherwise, + ;; return non-nil. (See comments above). The function invoked by this + ;; macro MUST NOT UNDER ANY CIRCUMSTANCES itself call + ;; c-beginning-of-statement-1. + ;; Languages which don't have EOL terminated statements always return NIL + ;; (they _know_ there's no vsemi ;-). + `(if c-vsemi-status-unknown-p-fn (funcall c-vsemi-status-unknown-p-fn))) + + (defmacro c-benign-error (format &rest args) ;; Formats an error message for the echo area and dings, i.e. like ;; `error' but doesn't abort. - ;; - ;; This function does not do any hidden buffer changes. `(progn (message ,format ,@args) (ding))) -(defmacro c-update-modeline () - ;; set the c-auto-hungry-string for the correct designation on the modeline - ;; - ;; This function does not do any hidden buffer changes. - `(progn - (setq c-auto-hungry-string - (if c-auto-newline - (if c-hungry-delete-key "/ah" "/a") - (if c-hungry-delete-key "/h" nil))) - (force-mode-line-update))) - (defmacro c-with-syntax-table (table &rest code) ;; Temporarily switches to the specified syntax table in a failsafe ;; way to execute code. - ;; - ;; This function does not do any hidden buffer changes. `(let ((c-with-syntax-table-orig-table (syntax-table))) (unwind-protect (progn @@ -578,9 +803,7 @@ (defmacro c-skip-ws-forward (&optional limit) "Skip over any whitespace following point. This function skips over horizontal and vertical whitespace and line -continuations. - -This function does not do any hidden buffer changes." +continuations." (if limit `(let ((limit (or ,limit (point-max)))) (while (progn @@ -601,9 +824,7 @@ (defmacro c-skip-ws-backward (&optional limit) "Skip over any whitespace preceding point. This function skips over horizontal and vertical whitespace and line -continuations. - -This function does not do any hidden buffer changes." +continuations." (if limit `(let ((limit (or ,limit (point-min)))) (while (progn @@ -624,9 +845,7 @@ (defmacro c-major-mode-is (mode) "Return non-nil if the current CC Mode major mode is MODE. -MODE is either a mode symbol or a list of mode symbols. - -This function does not do any hidden buffer changes." +MODE is either a mode symbol or a list of mode symbols." (if c-langs-are-parametric ;; Inside a `c-lang-defconst'. @@ -643,28 +862,9 @@ (memq c-buffer-is-cc-mode mode) (eq c-buffer-is-cc-mode mode)))))) -(defmacro c-mode-is-new-awk-p () - ;; Is the current mode the "new" awk mode? It is important for - ;; (e.g.) the cc-engine functions do distinguish between the old and - ;; new awk-modes. - '(and (c-major-mode-is 'awk-mode) - (memq 'syntax-properties c-emacs-features))) - -(defmacro c-parse-sexp-lookup-properties () - ;; Return the value of the variable that says whether the - ;; syntax-table property affects the sexp routines. Always return - ;; nil in (X)Emacsen without support for that. - ;; - ;; This function does not do any hidden buffer changes. - (cond ((cc-bytecomp-boundp 'parse-sexp-lookup-properties) - `parse-sexp-lookup-properties) - ((cc-bytecomp-boundp 'lookup-syntax-properties) - `lookup-syntax-properties) - (t nil))) - ;; Macros/functions to handle so-called "char properties", which are -;; properties set on a single character and that never spreads to any +;; properties set on a single character and that never spread to any ;; other characters. (eval-and-compile @@ -719,6 +919,8 @@ ;; ;; If there's a `text-property-default-nonsticky' variable (Emacs ;; 21) then it's assumed that the property is present on it. + ;; + ;; This macro does a hidden buffer change. (setq property (eval property)) (if (or c-use-extents (not (cc-bytecomp-boundp 'text-property-default-nonsticky))) @@ -761,6 +963,8 @@ ;; Remove the given property on the character at POS if it's been put ;; there by `c-put-char-property'. PROPERTY is assumed to be ;; constant. + ;; + ;; This macro does a hidden buffer change. (setq property (eval property)) (cond (c-use-extents ;; XEmacs. @@ -785,6 +989,8 @@ ;; lists of the `rear-nonsticky' properties in the region, if such ;; are used. Thus it should not be used for common properties like ;; `syntax-table'. + ;; + ;; This macro does hidden buffer changes. (setq property (eval property)) (if c-use-extents ;; XEmacs. @@ -795,12 +1001,44 @@ `(remove-text-properties ,from ,to '(,property nil)))) +;; Macros to put overlays (Emacs) or extents (XEmacs) on buffer text. +;; For our purposes, these are characterized by being possible to +;; remove again without affecting the other text properties in the +;; buffer that got overridden when they were put. + +(defmacro c-put-overlay (from to property value) + ;; Put an overlay/extent covering the given range in the current + ;; buffer. It's currently undefined whether it's front/end sticky + ;; or not. The overlay/extent object is returned. + (if (cc-bytecomp-fboundp 'make-overlay) + ;; Emacs. + `(let ((ol (make-overlay ,from ,to))) + (overlay-put ol ,property ,value) + ol) + ;; XEmacs. + `(let ((ext (make-extent ,from ,to))) + (set-extent-property ext ,property ,value) + ext))) + +(defmacro c-delete-overlay (overlay) + ;; Deletes an overlay/extent object previously retrieved using + ;; `c-put-overlay'. + (if (cc-bytecomp-fboundp 'make-overlay) + ;; Emacs. + `(delete-overlay ,overlay) + ;; XEmacs. + `(delete-extent ,overlay))) + + ;; Make edebug understand the macros. (eval-after-load "edebug" '(progn + (def-edebug-spec cc-eval-when-compile t) (def-edebug-spec c-point t) + (def-edebug-spec c-set-region-active t) (def-edebug-spec c-safe t) (def-edebug-spec c-save-buffer-state let*) + (def-edebug-spec c-tentative-buffer-changes t) (def-edebug-spec c-forward-syntactic-ws t) (def-edebug-spec c-backward-syntactic-ws t) (def-edebug-spec c-forward-sexp t) @@ -820,7 +1058,8 @@ (def-edebug-spec c-get-char-property t) (def-edebug-spec c-clear-char-property t) (def-edebug-spec c-clear-char-properties t) - (def-edebug-spec cc-eval-when-compile t))) + (def-edebug-spec c-put-overlay t) + (def-edebug-spec c-delete-overlay t))) ;;; Functions. @@ -847,25 +1086,23 @@ (defsubst c-mark-<-as-paren (pos) ;; Mark the "<" character at POS as an sexp list opener using the - ;; syntax-table property. Note that Emacs 19 and XEmacs <= 20 - ;; doesn't support syntax properties, so this function might not - ;; have any effect. + ;; syntax-table property. + ;; + ;; This function does a hidden buffer change. (c-put-char-property pos 'syntax-table c-<-as-paren-syntax)) (defconst c->-as-paren-syntax '(5 . ?<)) (defsubst c-mark->-as-paren (pos) ;; Mark the ">" character at POS as an sexp list closer using the - ;; syntax-table property. Note that Emacs 19 and XEmacs <= 20 - ;; doesn't support syntax properties, so this function might not - ;; have any effect. + ;; syntax-table property. + ;; + ;; This function does a hidden buffer change. (c-put-char-property pos 'syntax-table c->-as-paren-syntax)) (defsubst c-intersect-lists (list alist) ;; return the element of ALIST that matches the first element found ;; in LIST. Uses assq. - ;; - ;; This function does not do any hidden buffer changes. (let (match) (while (and list (not (setq match (assq (car list) alist)))) @@ -875,41 +1112,33 @@ (defsubst c-lookup-lists (list alist1 alist2) ;; first, find the first entry from LIST that is present in ALIST1, ;; then find the entry in ALIST2 for that entry. - ;; - ;; This function does not do any hidden buffer changes. (assq (car (c-intersect-lists list alist1)) alist2)) (defsubst c-langelem-sym (langelem) "Return the syntactic symbol in LANGELEM. -LANGELEM is a syntactic element, i.e. either a cons cell on the -\"old\" form given as the first argument to lineup functions or a list -on the \"new\" form as used in `c-syntactic-element'. - -This function does not do any hidden buffer changes." +LANGELEM is either a cons cell on the \"old\" form given as the first +argument to lineup functions or a syntactic element on the \"new\" +form as used in `c-syntactic-element'." (car langelem)) (defsubst c-langelem-pos (langelem) - "Return the (primary) anchor position in LANGELEM, or nil if there is none. + "Return the anchor position in LANGELEM, or nil if there is none. -LANGELEM is a syntactic element, i.e. either a cons cell on the -\"old\" form given as the first argument to lineup functions or a list -on the \"new\" form as used in `c-syntactic-element'. - -This function does not do any hidden buffer changes." +LANGELEM is either a cons cell on the \"old\" form given as the first +argument to lineup functions or a syntactic element on the \"new\" +form as used in `c-syntactic-element'." (if (consp (cdr langelem)) (car-safe (cdr langelem)) (cdr langelem))) (defun c-langelem-col (langelem &optional preserve-point) - "Return the column of the (primary) anchor position in LANGELEM. -Leave point at that position unless PRESERVE-POINT is non-nil. + "Return the column of the anchor position in LANGELEM. +Also move the point to that position unless PRESERVE-POINT is non-nil. -LANGELEM is a syntactic element, i.e. either a cons cell on the -\"old\" form given as the first argument to lineup functions or a list -on the \"new\" form as used in `c-syntactic-element'. - -This function does not do any hidden buffer changes." +LANGELEM is either a cons cell on the \"old\" form given as the first +argument to lineup functions or a syntactic element on the \"new\" +form as used in `c-syntactic-element'." (let ((pos (c-langelem-pos langelem)) (here (point))) (if pos @@ -923,38 +1152,18 @@ (defsubst c-langelem-2nd-pos (langelem) "Return the secondary position in LANGELEM, or nil if there is none. -LANGELEM is a syntactic element, typically on the \"new\" form as used -in `c-syntactic-element'. It may be on the \"old\" form that is used -as the first argument to lineup functions, but then the returned value -always will be nil. - -This function does not do any hidden buffer changes." +LANGELEM is typically a syntactic element on the \"new\" form as used +in `c-syntactic-element'. It may also be a cons cell as passed in the +first argument to lineup functions, but then the returned value always +will be nil." (car-safe (cdr-safe (cdr-safe langelem)))) (defsubst c-keep-region-active () ;; Do whatever is necessary to keep the region active in XEmacs. ;; This is not needed for Emacs. - ;; - ;; This function does not do any hidden buffer changes. (and (boundp 'zmacs-region-stays) (setq zmacs-region-stays t))) -(defsubst c-region-is-active-p () - ;; Return t when the region is active. The determination of region - ;; activeness is different in both Emacs and XEmacs. - ;; - ;; This function does not do any hidden buffer changes. - (cond - ;; XEmacs - ((and (fboundp 'region-active-p) - (boundp 'zmacs-regions) - zmacs-regions) - (region-active-p)) - ;; Emacs - ((boundp 'mark-active) mark-active) - ;; fallback; shouldn't get here - (t (mark t)))) - (put 'c-mode 'c-mode-prefix "c-") (put 'c++-mode 'c-mode-prefix "c++-") (put 'objc-mode 'c-mode-prefix "objc-") @@ -965,9 +1174,7 @@ (defsubst c-mode-symbol (suffix) "Prefix the current mode prefix (e.g. \"c-\") to SUFFIX and return -the corresponding symbol. - -This function does not do any hidden buffer changes." +the corresponding symbol." (or c-buffer-is-cc-mode (error "Not inside a CC Mode based mode")) (let ((mode-prefix (get c-buffer-is-cc-mode 'c-mode-prefix))) @@ -978,16 +1185,12 @@ (defsubst c-mode-var (suffix) "Prefix the current mode prefix (e.g. \"c-\") to SUFFIX and return -the value of the variable with that name. - -This function does not do any hidden buffer changes." +the value of the variable with that name." (symbol-value (c-mode-symbol suffix))) (defsubst c-got-face-at (pos faces) "Return non-nil if position POS in the current buffer has any of the -faces in the list FACES. - -This function does not do any hidden buffer changes." +faces in the list FACES." (let ((pos-faces (get-text-property pos 'face))) (if (consp pos-faces) (progn @@ -1003,31 +1206,72 @@ ;; face objects (while it's only their names that are used just ;; about anywhere else) without providing a predicate that tests ;; face names. - ;; - ;; This function does not do any hidden buffer changes. (memq facename (face-list))) +(defun c-concat-separated (list separator) + "Like `concat' on LIST, but separate each element with SEPARATOR. +Notably, null elements in LIST are ignored." + (mapconcat 'identity (delete nil (append list nil)) separator)) + (defun c-make-keywords-re (adorn list &optional mode) "Make a regexp that matches all the strings the list. -Duplicates in the list are removed. The resulting regexp may contain -zero or more submatch expressions. +Duplicates and nil elements in the list are removed. The resulting +regexp may contain zero or more submatch expressions. + +If ADORN is t there will be at least one submatch and the first +surrounds the matched alternative, and the regexp will also not match +a prefix of any identifier. Adorned regexps cannot be appended. The +language variable `c-nonsymbol-key' is used to make the adornment. -If ADORN is non-nil there will be at least one submatch and the first -matches the whole keyword, and the regexp will also not match a prefix -of any identifier. Adorned regexps cannot be appended. The language -variable `c-nonsymbol-key' is used to make the adornment. The -optional MODE specifies the language to get it in. The default is the -current language (taken from `c-buffer-is-cc-mode')." +A value 'appendable for ADORN is like above, but all alternatives in +the list that end with a word constituent char will have \\> appended +instead, so that the regexp remains appendable. Note that this +variant doesn't always guarantee that an identifier prefix isn't +matched since the symbol constituent '_' is normally considered a +nonword token by \\>. + +The optional MODE specifies the language to get `c-nonsymbol-key' from +when it's needed. The default is the current language taken from +`c-buffer-is-cc-mode'." (let (unique) (dolist (elt list) (unless (member elt unique) (push elt unique))) - (setq list unique)) + (setq list (delete nil unique))) (if list - (let ((re (c-regexp-opt list))) + (let (re) - ;; Emacs < 21 and XEmacs (all versions so far) has a buggy + (if (eq adorn 'appendable) + ;; This is kludgy but it works: Search for a string that + ;; doesn't occur in any word in LIST. Append it to all + ;; the alternatives where we want to add \>. Run through + ;; `regexp-opt' and then replace it with \>. + (let ((unique "") pos) + (while (let (found) + (setq unique (concat unique "@") + pos list) + (while (and pos + (if (string-match unique (car pos)) + (progn (setq found t) + nil) + t)) + (setq pos (cdr pos))) + found)) + (setq pos list) + (while pos + (if (string-match "\\w\\'" (car pos)) + (setcar pos (concat (car pos) unique))) + (setq pos (cdr pos))) + (setq re (regexp-opt list)) + (setq pos 0) + (while (string-match unique re pos) + (setq pos (+ (match-beginning 0) 2) + re (replace-match "\\>" t t re)))) + + (setq re (regexp-opt list))) + + ;; Emacs 20 and XEmacs (all versions so far) has a buggy ;; regexp-opt that doesn't always cope with strings containing ;; newlines. This kludge doesn't handle shy parens correctly ;; so we can't advice regexp-opt directly with it. @@ -1041,21 +1285,31 @@ (when fail-list (setq re (concat re "\\|" - (mapconcat 'regexp-quote - (sort fail-list - (lambda (a b) - (> (length a) (length b)))) - "\\|"))))) + (mapconcat + (if (eq adorn 'appendable) + (lambda (str) + (if (string-match "\\w\\'" str) + (concat (regexp-quote str) + "\\>") + (regexp-quote str))) + 'regexp-quote) + (sort fail-list + (lambda (a b) + (> (length a) (length b)))) + "\\|"))))) ;; Add our own grouping parenthesis around re instead of ;; passing adorn to `regexp-opt', since in XEmacs it makes the ;; top level grouping "shy". - (if adorn - (concat "\\(" re "\\)" - "\\(" - (c-get-lang-constant 'c-nonsymbol-key nil mode) - "\\|$\\)") - re)) + (cond ((eq adorn 'appendable) + (concat "\\(" re "\\)")) + (adorn + (concat "\\(" re "\\)" + "\\(" + (c-get-lang-constant 'c-nonsymbol-key nil mode) + "\\|$\\)")) + (t + re))) ;; Produce a regexp that matches nothing. (if adorn @@ -1064,6 +1318,35 @@ (put 'c-make-keywords-re 'lisp-indent-function 1) +(defun c-make-bare-char-alt (chars &optional inverted) + "Make a character alternative string from the list of characters CHARS. +The returned string is of the type that can be used with +`skip-chars-forward' and `skip-chars-backward'. If INVERTED is +non-nil, a caret is prepended to invert the set." + ;; This function ought to be in the elisp core somewhere. + (let ((str (if inverted "^" "")) char char2) + (setq chars (sort (append chars nil) `<)) + (while chars + (setq char (pop chars)) + (if (memq char '(?\\ ?^ ?-)) + ;; Quoting necessary (this method only works in the skip + ;; functions). + (setq str (format "%s\\%c" str char)) + (setq str (format "%s%c" str char))) + ;; Check for range. + (setq char2 char) + (while (and chars (>= (1+ char2) (car chars))) + (setq char2 (pop chars))) + (unless (= char char2) + (if (< (1+ char) char2) + (setq str (format "%s-%c" str char2)) + (push char2 chars)))) + str)) + +;; Leftovers from (X)Emacs 19 compatibility. +(defalias 'c-regexp-opt 'regexp-opt) +(defalias 'c-regexp-opt-depth 'regexp-opt-depth) + ;; Figure out what features this Emacs has @@ -1076,24 +1359,21 @@ ;; I've no idea what this actually is, but it's legacy. /mast (setq list (cons 'infodock list))) - ;; XEmacs 19 and beyond use 8-bit modify-syntax-entry flags. - ;; Emacs 19 uses a 1-bit flag. We will have to set up our + ;; XEmacs uses 8-bit modify-syntax-entry flags. + ;; Emacs uses a 1-bit flag. We will have to set up our ;; syntax tables differently to handle this. (let ((table (copy-syntax-table)) entry) (modify-syntax-entry ?a ". 12345678" table) (cond - ;; XEmacs 19, and beyond Emacs 19.34 + ;; Emacs ((arrayp table) (setq entry (aref table ?a)) ;; In Emacs, table entries are cons cells (if (consp entry) (setq entry (car entry)))) - ;; XEmacs 20 - ((fboundp 'get-char-table) (setq entry (get-char-table ?a table))) - ;; before and including Emacs 19.34 - ((and (fboundp 'char-table-p) - (char-table-p table)) - (setq entry (car (char-table-range table [?a])))) + ;; XEmacs + ((fboundp 'get-char-table) + (setq entry (get-char-table ?a table))) ;; incompatible (t (error "CC Mode is incompatible with this version of Emacs"))) (setq list (cons (if (= (logand (lsh entry -16) 255) 255) @@ -1120,12 +1400,16 @@ (modify-syntax-entry ?< ".") (modify-syntax-entry ?> ".") (insert "<()>") - (c-mark-<-as-paren 1) - (c-mark->-as-paren 4) - (goto-char 1) + (c-mark-<-as-paren (point-min)) + (c-mark->-as-paren (+ 3 (point-min))) + (goto-char (point-min)) (c-forward-sexp) - (if (= (point) 5) - (setq list (cons 'syntax-properties list))) + (if (= (point) (+ 4 (point-min))) + (setq list (cons 'syntax-properties list)) + (error (concat + "CC Mode is incompatible with this version of Emacs - " + "support for the `syntax-table' text property " + "is required."))) ;; Find out if generic comment delimiters work. (c-safe @@ -1153,7 +1437,7 @@ (setq list (cons 'posix-char-classes list))) ;; See if `open-paren-in-column-0-is-defun-start' exists and - ;; isn't buggy. + ;; isn't buggy (Emacs >= 21.4). (when (boundp 'open-paren-in-column-0-is-defun-start) (let ((open-paren-in-column-0-is-defun-start nil) (parse-sexp-ignore-comments t)) @@ -1180,8 +1464,11 @@ (kill-buffer buf)) ;; See if `parse-partial-sexp' returns the eighth element. - (when (c-safe (>= (length (save-excursion (parse-partial-sexp 1 1))) 10)) - (setq list (cons 'pps-extended-state list))) + (if (c-safe (>= (length (save-excursion (parse-partial-sexp 1 1))) 10)) + (setq list (cons 'pps-extended-state list)) + (error (concat + "CC Mode is incompatible with this version of Emacs - " + "`parse-partial-sexp' has to return at least 10 elements."))) ;;(message "c-emacs-features: %S" list) list) @@ -1193,14 +1480,17 @@ '8-bit 8 bit syntax entry flags (XEmacs style). '1-bit 1 bit syntax entry flags (Emacs style). 'syntax-properties It works to override the syntax for specific characters - in the buffer with the 'syntax-table property. + in the buffer with the 'syntax-table property. It's + always set - CC Mode no longer works in emacsen without + this feature. 'gen-comment-delim Generic comment delimiters work (i.e. the syntax class `!'). 'gen-string-delim Generic string delimiters work (i.e. the syntax class `|'). 'pps-extended-state `parse-partial-sexp' returns a list with at least 10 - elements, i.e. it contains the position of the - start of the last comment or string. + elements, i.e. it contains the position of the start of + the last comment or string. It's always set - CC Mode no + longer works in emacsen without this feature. 'posix-char-classes The regexp engine understands POSIX character classes. 'col-0-paren It's possible to turn off the ad-hoc rule that a paren in column zero is the start of a defun. @@ -1359,9 +1649,7 @@ one `c-lang-defconst' for each NAME is permitted per file. If there already is one it will be completely replaced; the value in the earlier definition will not affect `c-lang-const' on the same -constant. A file is identified by its base name. - -This macro does not do any hidden buffer changes." +constant. A file is identified by its base name." (let* ((sym (intern (symbol-name name) c-lang-constants)) ;; Make `c-lang-const' expand to a straightforward call to @@ -1451,8 +1739,7 @@ (&define name [&optional stringp] [&rest sexp def-form]))) (defun c-define-lang-constant (name bindings &optional pre-files) - ;; Used by `c-lang-defconst'. This function does not do any hidden - ;; buffer changes. + ;; Used by `c-lang-defconst'. (let* ((sym (intern (symbol-name name) c-lang-constants)) (source (get sym 'source)) @@ -1504,9 +1791,7 @@ \"-mode\" suffix. If used inside `c-lang-defconst' or `c-lang-defvar', LANG may be left out to refer to the current language. NAME and LANG are not evaluated so they should not be -quoted. - -This macro does not do any hidden buffer changes." +quoted." (or (symbolp name) (error "Not a symbol: %s" name)) @@ -1516,18 +1801,12 @@ (let ((sym (intern (symbol-name name) c-lang-constants)) mode source-files args) - (if lang - (progn - (setq mode (intern (concat (symbol-name lang) "-mode"))) - (unless (get mode 'c-mode-prefix) - (error - "Unknown language %S since it got no `c-mode-prefix' property" - (symbol-name lang)))) - (if c-buffer-is-cc-mode - (setq lang c-buffer-is-cc-mode) - (or c-langs-are-parametric - (error - "`c-lang-const' requires a literal language in this context")))) + (when lang + (setq mode (intern (concat (symbol-name lang) "-mode"))) + (unless (get mode 'c-mode-prefix) + (error + "Unknown language %S since it got no `c-mode-prefix' property" + (symbol-name lang)))) (if (eq c-lang-const-expansion 'immediate) ;; No need to find out the source file(s) when we evaluate @@ -1550,7 +1829,7 @@ (list (car elem)))) (get sym 'source)))))) - ;; Spend some effort to make a compact call to + ;; Make some effort to do a compact call to ;; `c-get-lang-constant' since it will be compiled in. (setq args (and mode `(',mode))) (if (or source-files args) @@ -1558,12 +1837,15 @@ args))) (if (or (eq c-lang-const-expansion 'call) + (and (not c-lang-const-expansion) + (not mode)) load-in-progress (not (boundp 'byte-compile-dest-file)) (not (stringp byte-compile-dest-file))) ;; Either a straight call is requested in the context, or - ;; we're not being byte compiled so the compile time stuff - ;; below is unnecessary. + ;; we're in an "uncontrolled" context and got no language, + ;; or we're not being byte compiled so the compile time + ;; stuff below is unnecessary. `(c-get-lang-constant ',name ,@args) ;; Being compiled. If the loading and compiling version is @@ -1577,8 +1859,7 @@ (defvar c-lang-constants-under-evaluation nil) (defun c-get-lang-constant (name &optional source-files mode) - ;; Used by `c-lang-const'. This function does not do any hidden - ;; buffer changes. + ;; Used by `c-lang-const'. (or mode (setq mode c-buffer-is-cc-mode) @@ -1755,5 +2036,5 @@ (cc-provide 'cc-defs) -;;; arch-tag: 3bb2629d-dd84-4ff0-ad39-584be0fe3cda +;; arch-tag: 3bb2629d-dd84-4ff0-ad39-584be0fe3cda ;;; cc-defs.el ends here
--- a/lisp/progmodes/cc-engine.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/progmodes/cc-engine.el Sat Dec 10 21:18:28 2005 +0000 @@ -1,6 +1,7 @@ ;;; cc-engine.el --- core syntax guessing engine for CC mode -;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, Inc. +;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, +;; Inc. ;; Authors: 1998- Martin Stjernholm ;; 1992-1999 Barry A. Warsaw @@ -44,21 +45,29 @@ ;; ;; Various functions in CC Mode use text properties for caching and ;; syntactic markup purposes, and those of them that might modify such -;; properties are said to do "hidden buffer changes". They should be -;; used within `c-save-buffer-state' or a similar function that saves -;; and restores buffer modifiedness etc. +;; properties but still don't modify the buffer in a visible way are +;; said to do "hidden buffer changes". They should be used within +;; `c-save-buffer-state' or a similar function that saves and restores +;; buffer modifiedness, disables buffer change hooks, etc. ;; -;; Interactive functions are assumed to not do hidden buffer changes -;; (this isn't applicable in the specific parts of them that do real -;; changes, though). +;; Interactive functions are assumed to not do hidden buffer changes, +;; except in the specific parts of them that do real changes. +;; +;; Lineup functions are assumed to do hidden buffer changes. They +;; must not do real changes, though. ;; -;; All other functions are assumed to do hidden buffer changes and -;; must thus be wrapped inside `c-save-buffer-state' if they're used -;; from any function that does not do hidden buffer changes. +;; All other functions that do hidden buffer changes have that noted +;; in their doc string or comment. ;; -;; Every function, except the interactive ones, that doesn't do hidden -;; buffer changes have that explicitly stated in their docstring or -;; comment. +;; The intention with this system is to avoid wrapping every leaf +;; function that do hidden buffer changes inside +;; `c-save-buffer-state'. It should be used as near the top of the +;; interactive functions as possible. +;; +;; Functions called during font locking are allowed to do hidden +;; buffer changes since the font-lock package run them in a context +;; similar to `c-save-buffer-state' (in fact, that function is heavily +;; inspired by `save-buffer-state' in the font-lock package). ;; Use of text properties ;; @@ -86,8 +95,8 @@ ;; ;; 'c-type ;; This property is used on single characters to mark positions with -;; special syntactic relevance of various sorts. It's primary use -;; is to avoid glitches when multiline constructs are refontified +;; special syntactic relevance of various sorts. Its primary use is +;; to avoid glitches when multiline constructs are refontified ;; interactively (on font lock decoration level 3). It's cleared in ;; a region before it's fontified and is then put on relevant chars ;; in that region as they are encountered during the fontification. @@ -134,19 +143,6 @@ (cc-require-when-compile 'cc-langs) (cc-require 'cc-vars) -;; Some functions/constants in cc-awk.el that are called/referenced here. -;; (Can't use cc-require due to cyclicity.) -(cc-bytecomp-defun c-awk-unstick-NL-prop) -(cc-bytecomp-defun c-awk-clear-NL-props) -(cc-bytecomp-defvar awk-mode-syntax-table) -(cc-bytecomp-defun c-awk-backward-syntactic-ws) -(cc-bytecomp-defun c-awk-after-logical-semicolon) -(cc-bytecomp-defun c-awk-NL-prop-not-set) -(cc-bytecomp-defun c-awk-completed-stmt-ws-ends-line-p) -(cc-bytecomp-defun c-awk-completed-stmt-ws-ends-prev-line-p) -(cc-bytecomp-defun c-awk-prev-line-incomplete-p) -(cc-bytecomp-defun c-awk-after-change) - ;; Silence the compiler. (cc-bytecomp-defun buffer-syntactic-context) ; XEmacs @@ -171,13 +167,20 @@ (defvar c-hungry-delete-key nil) (make-variable-buffer-local 'c-hungry-delete-key) +;; The electric flag (toggled by `c-toggle-electric-state'). +;; If t, electric actions (like automatic reindentation, and (if +;; c-auto-newline is also set) auto newlining) will happen when an electric +;; key like `{' is pressed (or an electric keyword like `else'). +(defvar c-electric-flag t) +(make-variable-buffer-local 'c-electric-flag) + ;; Internal state of auto newline feature. (defvar c-auto-newline nil) (make-variable-buffer-local 'c-auto-newline) -;; Internal auto-newline/hungry-delete designation string for mode line. -(defvar c-auto-hungry-string nil) -(make-variable-buffer-local 'c-auto-hungry-string) +;; Included in the mode line to indicate the active submodes. +(defvar c-submode-indicators nil) +(make-variable-buffer-local 'c-submode-indicators) (defun c-calculate-state (arg prevstate) ;; Calculate the new state of PREVSTATE, t or nil, based on arg. If @@ -191,11 +194,6 @@ ;; Dynamically bound cache for `c-in-literal'. (defvar c-in-literal-cache t) -;; Must be set in buffers where the `c-type' text property might be used -;; with the value `c-decl-end'. -(defvar c-type-decl-end-used nil) -(make-variable-buffer-local 'c-type-decl-end-used) - ;; Basic handling of preprocessor directives. @@ -205,19 +203,19 @@ (defvar c-macro-start 'unknown) (defsubst c-query-and-set-macro-start () - ;; This function does not do any hidden buffer changes. (if (symbolp c-macro-start) (setq c-macro-start (save-excursion - (and (c-beginning-of-macro) - (point)))) + (c-save-buffer-state () + (and (c-beginning-of-macro) + (point))))) c-macro-start)) (defsubst c-query-macro-start () - ;; This function does not do any hidden buffer changes. (if (symbolp c-macro-start) (save-excursion - (and (c-beginning-of-macro) - (point))) + (c-save-buffer-state () + (and (c-beginning-of-macro) + (point)))) c-macro-start)) (defun c-beginning-of-macro (&optional lim) @@ -225,7 +223,8 @@ Leave point at the beginning of the directive and return t if in one, otherwise return nil and leave point unchanged. -This function does not do any hidden buffer changes." +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." (when c-opt-cpp-prefix (let ((here (point))) (save-restriction @@ -242,10 +241,12 @@ (defun c-end-of-macro () "Go to the end of a preprocessor directive. -More accurately, move point to the end of the closest following line -that doesn't end with a line continuation backslash. - -This function does not do any hidden buffer changes." +More accurately, move the point to the end of the closest following +line that doesn't end with a line continuation backslash - no check is +done that the point is inside a cpp directive to begin with. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." (while (progn (end-of-line) (when (and (eq (char-before) ?\\) @@ -256,95 +257,81 @@ (defun c-forward-to-cpp-define-body () ;; Assuming point is at the "#" that introduces a preprocessor ;; directive, it's moved forward to the start of the definition body - ;; if it's a "#define". Non-nil is returned in this case, in all - ;; other cases nil is returned and point isn't moved. - (when (and (looking-at - (concat "#[ \t]*" - "define[ \t]+\\(\\sw\\|_\\)+\\(\([^\)]*\)\\)?" - "\\([ \t]\\|\\\\\n\\)*")) + ;; if it's a "#define" (or whatever c-opt-cpp-macro-define + ;; specifies). Non-nil is returned in this case, in all other cases + ;; nil is returned and point isn't moved. + ;; + ;; This function might do hidden buffer changes. + (when (and c-opt-cpp-macro-define-start + (looking-at c-opt-cpp-macro-define-start) (not (= (match-end 0) (c-point 'eol)))) (goto-char (match-end 0)))) ;;; Basic utility functions. -(defun c-syntactic-content (from to) +(defun c-syntactic-content (from to paren-level) ;; Return the given region as a string where all syntactic ;; whitespace is removed or, where necessary, replaced with a single - ;; space. + ;; space. If PAREN-LEVEL is given then all parens in the region are + ;; collapsed to "()", "[]" etc. + ;; + ;; This function might do hidden buffer changes. + (save-excursion - (goto-char from) - (let* ((parts (list nil)) (tail parts) pos) - (while (re-search-forward c-syntactic-ws-start to t) - (goto-char (setq pos (match-beginning 0))) - (c-forward-syntactic-ws to) - (if (= (point) pos) - (forward-char) - (if (and (> pos from) - (< (point) to) - (looking-at "\\w\\|\\s_") - (save-excursion - (goto-char (1- pos)) - (looking-at "\\w\\|\\s_"))) - (progn - (setcdr tail (list (buffer-substring-no-properties from pos) - " ")) - (setq tail (cddr tail))) - (setcdr tail (list (buffer-substring-no-properties from pos))) - (setq tail (cdr tail))) - (setq from (point)))) - (setcdr tail (list (buffer-substring-no-properties from to))) - (apply 'concat (cdr parts))))) - -(defsubst c-keyword-sym (keyword) - ;; Return non-nil if the string KEYWORD is a known keyword. More - ;; precisely, the value is the symbol for the keyword in - ;; `c-keywords-obarray'. - (intern-soft keyword c-keywords-obarray)) - -(defsubst c-keyword-member (keyword-sym lang-constant) - ;; Return non-nil if the symbol KEYWORD-SYM, as returned by - ;; `c-keyword-sym', is a member of LANG-CONSTANT, which is the name - ;; of a language constant that ends with "-kwds". If KEYWORD-SYM is - ;; nil then the result is nil. - (get keyword-sym lang-constant)) - -;; String syntax chars, suitable for skip-syntax-(forward|backward). -(defconst c-string-syntax (if (memq 'gen-string-delim c-emacs-features) - "\"|" - "\"")) - -;; Regexp matching string start syntax. -(defconst c-string-limit-regexp (if (memq 'gen-string-delim c-emacs-features) - "\\s\"\\|\\s|" - "\\s\"")) - -;; Holds formatted error strings for the few cases where parse errors -;; are reported. -(defvar c-parsing-error nil) -(make-variable-buffer-local 'c-parsing-error) - -(defun c-echo-parsing-error (&optional quiet) - ;; This function does not do any hidden buffer changes. - (when (and c-report-syntactic-errors c-parsing-error (not quiet)) - (c-benign-error "%s" c-parsing-error)) - c-parsing-error) - -;; Faces given to comments and string literals. This is used in some -;; situations to speed up recognition; it isn't mandatory that font -;; locking is in use. This variable is extended with the face in -;; `c-doc-face-name' when fontification is activated in cc-fonts.el. -(defvar c-literal-faces - '(font-lock-comment-face font-lock-string-face - font-lock-comment-delimiter-face)) + (save-restriction + (narrow-to-region from to) + (goto-char from) + (let* ((parts (list nil)) (tail parts) pos in-paren) + + (while (re-search-forward c-syntactic-ws-start to t) + (goto-char (setq pos (match-beginning 0))) + (c-forward-syntactic-ws) + (if (= (point) pos) + (forward-char) + + (when paren-level + (save-excursion + (setq in-paren (= (car (parse-partial-sexp from pos 1)) 1) + pos (point)))) + + (if (and (> pos from) + (< (point) to) + (looking-at "\\w\\|\\s_") + (save-excursion + (goto-char (1- pos)) + (looking-at "\\w\\|\\s_"))) + (progn + (setcdr tail (list (buffer-substring-no-properties from pos) + " ")) + (setq tail (cddr tail))) + (setcdr tail (list (buffer-substring-no-properties from pos))) + (setq tail (cdr tail))) + + (when in-paren + (when (= (car (parse-partial-sexp pos to -1)) -1) + (setcdr tail (list (buffer-substring-no-properties + (1- (point)) (point)))) + (setq tail (cdr tail)))) + + (setq from (point)))) + + (setcdr tail (list (buffer-substring-no-properties from to))) + (apply 'concat (cdr parts)))))) (defun c-shift-line-indentation (shift-amt) - ;; This function does not do any hidden buffer changes. + ;; Shift the indentation of the current line with the specified + ;; amount (positive inwards). The buffer is modified only if + ;; SHIFT-AMT isn't equal to zero. (let ((pos (- (point-max) (point))) (c-macro-start c-macro-start) tmp-char-inserted) (if (zerop shift-amt) nil + ;; If we're on an empty line inside a macro, we take the point + ;; to be at the current indentation and shift it to the + ;; appropriate column. This way we don't treat the extra + ;; whitespace out to the line continuation as indentation. (when (and (c-query-and-set-macro-start) (looking-at "[ \t]*\\\\$") (save-excursion @@ -369,6 +356,72 @@ (if (> (- (point-max) pos) (point)) (goto-char (- (point-max) pos)))))) +(defsubst c-keyword-sym (keyword) + ;; Return non-nil if the string KEYWORD is a known keyword. More + ;; precisely, the value is the symbol for the keyword in + ;; `c-keywords-obarray'. + (intern-soft keyword c-keywords-obarray)) + +(defsubst c-keyword-member (keyword-sym lang-constant) + ;; Return non-nil if the symbol KEYWORD-SYM, as returned by + ;; `c-keyword-sym', is a member of LANG-CONSTANT, which is the name + ;; of a language constant that ends with "-kwds". If KEYWORD-SYM is + ;; nil then the result is nil. + (get keyword-sym lang-constant)) + +;; String syntax chars, suitable for skip-syntax-(forward|backward). +(defconst c-string-syntax (if (memq 'gen-string-delim c-emacs-features) + "\"|" + "\"")) + +;; Regexp matching string limit syntax. +(defconst c-string-limit-regexp (if (memq 'gen-string-delim c-emacs-features) + "\\s\"\\|\\s|" + "\\s\"")) + +;; Regexp matching WS followed by string limit syntax. +(defconst c-ws*-string-limit-regexp + (concat "[ \t]*\\(" c-string-limit-regexp "\\)")) + +;; Holds formatted error strings for the few cases where parse errors +;; are reported. +(defvar c-parsing-error nil) +(make-variable-buffer-local 'c-parsing-error) + +(defun c-echo-parsing-error (&optional quiet) + (when (and c-report-syntactic-errors c-parsing-error (not quiet)) + (c-benign-error "%s" c-parsing-error)) + c-parsing-error) + +;; Faces given to comments and string literals. This is used in some +;; situations to speed up recognition; it isn't mandatory that font +;; locking is in use. This variable is extended with the face in +;; `c-doc-face-name' when fontification is activated in cc-fonts.el. +(defvar c-literal-faces + (append '(font-lock-comment-face font-lock-string-face) + (when (facep 'font-lock-comment-delimiter-face) + ;; New in Emacs 22. + '(font-lock-comment-delimiter-face)))) + +(defsubst c-put-c-type-property (pos value) + ;; Put a c-type property with the given value at POS. + (c-put-char-property pos 'c-type value)) + +(defun c-clear-c-type-property (from to value) + ;; Remove all occurences of the c-type property that has the given + ;; value in the region between FROM and TO. VALUE is assumed to not + ;; be nil. + ;; + ;; Note: This assumes that c-type is put on single chars only; it's + ;; very inefficient if matching properties cover large regions. + (save-excursion + (goto-char from) + (while (progn + (when (eq (get-text-property (point) 'c-type) value) + (c-clear-char-property (point) 'c-type)) + (goto-char (next-single-property-change (point) 'c-type nil to)) + (< (point) to))))) + ;; Some debug tools to visualize various special positions. This ;; debug code isn't as portable as the rest of CC Mode. @@ -414,7 +467,7 @@ ;; c-crosses-statement-barrier-p and c-beginning-of-statement-1. A ;; better way should be implemented, but this will at least shut up ;; the byte compiler. -(defvar c-maybe-labelp nil) +(defvar c-maybe-labelp) ;; New awk-compatible version of c-beginning-of-statement-1, ACM 2002/6/22 @@ -470,11 +523,9 @@ move to the closest containing statement if there is any. This might also stop at a continuation clause. -Labels are treated as separate statements if IGNORE-LABELS is non-nil. -The function is not overly intelligent in telling labels from other -uses of colons; if used outside a statement context it might trip up -on e.g. inherit colons, so IGNORE-LABELS should be used then. There -should be no such mistakes in a statement context, however. +Labels are treated as part of the following statements if +IGNORE-LABELS is non-nil. (FIXME: Doesn't work if we stop at a known +statement start keyword.) Macros are ignored unless point is within one, in which case the content of the macro is treated as normal code. Aside from any normal @@ -497,7 +548,10 @@ NOERROR turns off error logging to `c-parsing-error'. Normally only ';' is considered to delimit statements, but if -COMMA-DELIM is non-nil then ',' is treated likewise." +COMMA-DELIM is non-nil then ',' is treated likewise. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." ;; The bulk of this function is a pushdown automaton that looks at statement ;; boundaries and the tokens (such as "while") in c-opt-block-stmt-key. Its @@ -587,20 +641,43 @@ (c-stmt-delim-chars (if comma-delim c-stmt-delim-chars-with-comma c-stmt-delim-chars)) - pos ; Current position. - boundary-pos ; Position of last stmt boundary character (e.g. ;). - after-labels-pos ; Value of tok after first found colon. - last-label-pos ; Value of tok after last found colon. - sym ; Symbol just scanned back over (e.g. 'while or - ; 'boundary). See above - state ; Current state in the automaton. See above. - saved-pos ; Current saved positions. See above - stack ; Stack of conses (state . saved-pos). - (cond-key (or c-opt-block-stmt-key ; regexp which matches "for", "if", etc. + c-in-literal-cache c-maybe-labelp saved + ;; Current position. + pos + ;; Position of last stmt boundary character (e.g. ;). + boundary-pos + ;; The position of the last sexp or bound that follows the + ;; first found colon, i.e. the start of the nonlabel part of + ;; the statement. It's `start' if a colon is found just after + ;; the start. + after-labels-pos + ;; Like `after-labels-pos', but the first such position inside + ;; a label, i.e. the start of the last label before the start + ;; of the nonlabel part of the statement. + last-label-pos + ;; The last position where a label is possible provided the + ;; statement started there. It's nil as long as no invalid + ;; label content has been found (according to + ;; `c-nonlabel-token-key'. It's `start' if no valid label + ;; content was found in the label. Note that we might still + ;; regard it a label if it starts with `c-label-kwds'. + label-good-pos + ;; Symbol just scanned back over (e.g. 'while or 'boundary). + ;; See above. + sym + ;; Current state in the automaton. See above. + state + ;; Current saved positions. See above. + saved-pos + ;; Stack of conses (state . saved-pos). + stack + ;; Regexp which matches "for", "if", etc. + (cond-key (or c-opt-block-stmt-key "\\<\\>")) ; Matches nothing. - (ret 'same) ; Return value. - tok ptok pptok ; Pos of last three sexps or bounds. - c-in-literal-cache c-maybe-labelp saved) + ;; Return value. + (ret 'same) + ;; Positions of the last three sexps or bounds we've stopped at. + tok ptok pptok) (save-restriction (if lim (narrow-to-region lim (point-max))) @@ -614,32 +691,23 @@ ;; that we've moved. (while (progn (setq pos (point)) - (if (c-mode-is-new-awk-p) - (c-awk-backward-syntactic-ws) - (c-backward-syntactic-ws)) - (/= (skip-chars-backward "-+!*&~@`#") 0))) ; ACM, 2002/5/31; - ; Make a variable in - ; cc-langs.el, maybe + (c-backward-syntactic-ws) + ;; Protect post-++/-- operators just before a virtual semicolon. + (and (not (c-at-vsemi-p)) + (/= (skip-chars-backward "-+!*&~@`#") 0)))) ;; Skip back over any semicolon here. If it was a bare semicolon, we're - ;; done. Later on we ignore the boundaries for statements that doesn't + ;; done. Later on we ignore the boundaries for statements that don't ;; contain any sexp. The only thing that is affected is that the error ;; checking is a little less strict, and we really don't bother. (if (and (memq (char-before) delims) (progn (forward-char -1) (setq saved (point)) - (if (c-mode-is-new-awk-p) - (c-awk-backward-syntactic-ws) - (c-backward-syntactic-ws)) + (c-backward-syntactic-ws) (or (memq (char-before) delims) (memq (char-before) '(?: nil)) (eq (char-syntax (char-before)) ?\() - (and (c-mode-is-new-awk-p) - (c-awk-after-logical-semicolon))))) ; ACM 2002/6/22 - ;; ACM, 2002/7/20: What about giving a limit to the above function? - ;; ACM, 2003/6/16: The above two lines (checking for - ;; awk-logical-semicolon) are probably redundant after rewriting - ;; c-awk-backward-syntactic-ws. + (c-at-vsemi-p)))) (setq ret 'previous pos saved) @@ -657,11 +725,8 @@ (while (catch 'loop ;; Throw nil to break, non-nil to continue. (cond - ;; Check for macro start. Take this out for AWK Mode (ACM, 2002/5/31) - ;; NO!! just make sure macro-start is nil in AWK Mode (ACM, 2002/6/22) - ;; It always is (ACM, 2002/6/23) ((save-excursion - (and macro-start + (and macro-start ; Always NIL for AWK. (progn (skip-chars-backward " \t") (eq (char-before) ?#)) (progn (setq saved (1- (point))) @@ -767,23 +832,22 @@ (c-bos-save-error-info 'if 'else) (setq state 'else)) ((eq sym 'while) + ;; Is this a real while, or a do-while? + ;; The next `when' triggers unless we are SURE that + ;; the `while' is not the tailend of a `do-while'. (when (or (not pptok) (memq (char-after pptok) delims) - (and (c-mode-is-new-awk-p) - (or - ;; might we be calling this from - ;; c-awk-after-if-do-for-while-condition-p? - ;; If so, avoid infinite recursion. - (and (eq (point) start) - (c-awk-NL-prop-not-set)) - ;; The following may recursively - ;; call this function. - (c-awk-completed-stmt-ws-ends-line-p pptok)))) + ;; The following kludge is to prevent + ;; infinite recursion when called from + ;; c-awk-after-if-for-while-condition-p, + ;; or the like. + (and (eq (point) start) + (c-vsemi-status-unknown-p)) + (c-at-vsemi-p pptok)) ;; Since this can cause backtracking we do a ;; little more careful analysis to avoid it: If - ;; the while isn't followed by a semicolon it - ;; can't be a do-while. - ;; ACM, 2002/5/31; IT CAN IN AWK Mode. ;-( + ;; the while isn't followed by a (possibly + ;; virtual) semicolon it can't be a do-while. (c-bos-push-state) (setq state 'while))) ((memq sym '(catch finally)) @@ -805,80 +869,95 @@ (setq ret 'previous) ;; HERE IS THE SINGLE PLACE INSIDE THE PDA LOOP WHERE WE MOVE - ;; BACKWARDS THROUGH THE SOURCE. The following loop goes back - ;; one sexp and then only loops in special circumstances (line - ;; continuations and skipping past entire macros). - (while - (progn - (or (c-safe (goto-char (scan-sexps (point) -1)) t) - ;; Give up if we hit an unbalanced block. - ;; Since the stack won't be empty the code - ;; below will report a suitable error. + ;; BACKWARDS THROUGH THE SOURCE. + + ;; This is typically fast with the caching done by + ;; c-(backward|forward)-sws. + (c-backward-syntactic-ws) + + (let ((before-sws-pos (point)) + ;; Set as long as we have to continue jumping by sexps. + ;; It's the position to use as end in the next round. + sexp-loop-continue-pos + ;; The end position of the area to search for statement + ;; barriers in this round. + (sexp-loop-end-pos pos)) + + (while + (progn + (unless (c-safe (c-backward-sexp) t) + ;; Give up if we hit an unbalanced block. Since the + ;; stack won't be empty the code below will report a + ;; suitable error. (throw 'loop nil)) - (cond ((looking-at "\\\\$") - ;; Step again if we hit a line continuation. - t) - (macro-start - ;; If we started inside a macro then this - ;; sexp is always interesting. - nil) - ((not (c-mode-is-new-awk-p)) ; Changed from t, ACM 2002/6/25 - ;; Otherwise check that we didn't step - ;; into a macro from the end. - (let ((macro-start - (save-excursion - (and (c-beginning-of-macro) - (point))))) - (when macro-start - (goto-char macro-start) - t)))))) - - ;; Did the last movement by a sexp cross a statement boundary? - (when (save-excursion - (if (if (eq (char-after) ?{) - (c-looking-at-inexpr-block lim nil) - (looking-at "\\s\(")) - - ;; Should not include the paren sexp we've - ;; passed over in the boundary check. - (if (> (point) (- pos 100)) - (c-forward-sexp 1) - - ;; Find its end position this way instead of - ;; moving forward if the sexp is large. - (goto-char pos) - (while - (progn - (goto-char (1+ (c-down-list-backward))) - (unless macro-start - ;; Check that we didn't step into - ;; a macro from the end. - (let ((macro-start - (save-excursion - (and (c-beginning-of-macro) - (point))))) - (when macro-start - (goto-char macro-start) - t))))))) - - (setq boundary-pos (c-crosses-statement-barrier-p - (point) pos))) - - (setq pptok ptok - ptok tok - tok boundary-pos - sym 'boundary) - (throw 'loop t))) ; like a C "continue". Analyze the next sexp. - - (when (and (numberp c-maybe-labelp) - (not ignore-labels) - (not (looking-at "\\s\("))) - ;; c-crosses-statement-barrier-p has found a colon, so - ;; we might be in a label now. - (if (not after-labels-pos) - (setq after-labels-pos tok)) - (setq last-label-pos tok - c-maybe-labelp t)) + + ;; Check if the sexp movement crossed a statement or + ;; declaration boundary. But first modify the point + ;; so that `c-crosses-statement-barrier-p' only looks + ;; at the non-sexp chars following the sexp. + (save-excursion + (when (setq + boundary-pos + (cond + ((if macro-start + nil + (save-excursion + (when (c-beginning-of-macro) + ;; Set continuation position in case + ;; `c-crosses-statement-barrier-p' + ;; doesn't detect anything below. + (setq sexp-loop-continue-pos (point))))) + ;; If the sexp movement took us into a + ;; macro then there were only some non-sexp + ;; chars after it. Skip out of the macro + ;; to analyze them but not the non-sexp + ;; chars that might be inside the macro. + (c-end-of-macro) + (c-crosses-statement-barrier-p + (point) sexp-loop-end-pos)) + + ((and + (eq (char-after) ?{) + (not (c-looking-at-inexpr-block lim nil t))) + ;; Passed a block sexp. That's a boundary + ;; alright. + (point)) + + ((looking-at "\\s\(") + ;; Passed some other paren. Only analyze + ;; the non-sexp chars after it. + (goto-char (1+ (c-down-list-backward + before-sws-pos))) + ;; We're at a valid token start position + ;; (outside the `save-excursion') if + ;; `c-crosses-statement-barrier-p' failed. + (c-crosses-statement-barrier-p + (point) sexp-loop-end-pos)) + + (t + ;; Passed a symbol sexp or line + ;; continuation. It doesn't matter that + ;; it's included in the analyzed region. + (if (c-crosses-statement-barrier-p + (point) sexp-loop-end-pos) + t + ;; If it was a line continuation then we + ;; have to continue looping. + (if (looking-at "\\\\$") + (setq sexp-loop-continue-pos (point))) + nil)))) + + (setq pptok ptok + ptok tok + tok boundary-pos + sym 'boundary) + ;; Like a C "continue". Analyze the next sexp. + (throw 'loop t))) + + sexp-loop-continue-pos) + (goto-char sexp-loop-continue-pos) + (setq sexp-loop-end-pos sexp-loop-continue-pos + sexp-loop-continue-pos nil)))) ;; ObjC method def? (when (and c-opt-method-key @@ -887,7 +966,26 @@ ignore-labels t) ; Avoid the label check on exit. (throw 'loop nil)) - ;; We've moved back by a sexp, so update the token positions. + ;; Handle labels. + (unless (eq ignore-labels t) + (when (numberp c-maybe-labelp) + ;; `c-crosses-statement-barrier-p' has found a + ;; colon, so we might be in a label now. + (if after-labels-pos + (if (not last-label-pos) + (setq last-label-pos (or tok start))) + (setq after-labels-pos (or tok start))) + (setq c-maybe-labelp t + label-good-pos nil)) + + (when (and (not label-good-pos) + (looking-at c-nonlabel-token-key)) + ;; We're in a potential label and it's the first + ;; time we've found something that isn't allowed in + ;; one. + (setq label-good-pos (or tok start)))) + + ;; We've moved back by a sexp, so update the token positions. (setq sym nil pptok ptok ptok tok @@ -911,25 +1009,34 @@ (cond ((> start saved) (setq pos saved)) ((= start saved) (setq ret 'up))))) - (when (and c-maybe-labelp - (not ignore-labels) + (when (and (not ignore-labels) + (eq c-maybe-labelp t) (not (eq ret 'beginning)) - after-labels-pos) + after-labels-pos + (or (not label-good-pos) + (<= label-good-pos pos) + (progn + (goto-char (if (and last-label-pos + (< last-label-pos start)) + last-label-pos + pos)) + (looking-at c-label-kwds-regexp)))) ;; We're in a label. Maybe we should step to the statement ;; after it. (if (< after-labels-pos start) (setq pos after-labels-pos) (setq ret 'label) - (if (< last-label-pos start) + (if (and last-label-pos (< last-label-pos start)) + ;; Might have jumped over several labels. Go to the last one. (setq pos last-label-pos))))) ;; Skip over the unary operators that can start the statement. (goto-char pos) (while (progn - (if (c-mode-is-new-awk-p) - (c-awk-backward-syntactic-ws) - (c-backward-syntactic-ws)) - (/= (skip-chars-backward "-+!*&~@`#") 0)) ; Hopefully the # won't hurt awk. + (c-backward-syntactic-ws) + ;; protect AWK post-inc/decrement operators, etc. + (and (not (c-at-vsemi-p (point))) + (/= (skip-chars-backward "-+!*&~@`#") 0))) (setq pos (point))) (goto-char pos) ret))) @@ -942,7 +1049,14 @@ The variable `c-maybe-labelp' is set to the position of the first `:' that might start a label (i.e. not part of `::' and not preceded by `?'). If a -single `?' is found, then `c-maybe-labelp' is cleared." +single `?' is found, then `c-maybe-labelp' is cleared. + +For AWK, a statement which is terminated by an EOL (not a \; or a }) is +regarded as having a \"virtual semicolon\" immediately after the last token on +the line. If this virtual semicolon is _at_ from, the function recognises it. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." (let ((skip-chars c-stmt-delim-chars) lit-range) (save-excursion @@ -950,30 +1064,85 @@ (goto-char from) (while (progn (skip-chars-forward skip-chars to) (< (point) to)) - (if (setq lit-range (c-literal-limits from)) ; Have we landed in a string/comment? - (progn (goto-char (setq from (cdr lit-range))) - (if (and (c-mode-is-new-awk-p) (bolp)) ; ACM 2002/7/17. Make sure we - (backward-char))) ; don't skip over a virtual semi-colon after an awk comment. :-( - (cond ((eq (char-after) ?:) - (forward-char) - (if (and (eq (char-after) ?:) - (< (point) to)) - ;; Ignore scope operators. - (forward-char) - (setq c-maybe-labelp (1- (point))))) - ((eq (char-after) ??) - ;; A question mark. Can't be a label, so stop - ;; looking for more : and ?. - (setq c-maybe-labelp nil - skip-chars (substring c-stmt-delim-chars 0 -2))) - ((and (eolp) ; Can only happen in AWK Mode - (not (c-awk-completed-stmt-ws-ends-line-p))) - (forward-char)) - ((and (c-mode-is-new-awk-p) - (bolp) lit-range ; awk: comment/string ended prev line. - (not (c-awk-completed-stmt-ws-ends-prev-line-p)))) - (t (throw 'done (point)))))) - nil)))) + (cond + ((setq lit-range (c-literal-limits from)) ; Have we landed in a string/comment? + (goto-char (cdr lit-range))) + ((eq (char-after) ?:) + (forward-char) + (if (and (eq (char-after) ?:) + (< (point) to)) + ;; Ignore scope operators. + (forward-char) + (setq c-maybe-labelp (1- (point))))) + ((eq (char-after) ??) + ;; A question mark. Can't be a label, so stop + ;; looking for more : and ?. + (setq c-maybe-labelp nil + skip-chars (substring c-stmt-delim-chars 0 -2))) + ((memq (char-after) '(?# ?\n ?\r)) ; A virtual semicolon? + (if (and (eq (char-before) ?\\) (memq (char-after) '(?\n ?\r))) + (backward-char)) + (skip-chars-backward " \t" from) + (if (c-at-vsemi-p) + (throw 'done (point)) + (forward-line))) + (t (throw 'done (point))))) + ;; In trailing space after an as yet undetected virtual semicolon? + (c-backward-syntactic-ws from) + (if (and (< (point) to) + (c-at-vsemi-p)) + (point) + nil))))) + +(defun c-at-statement-start-p () + "Return non-nil if the point is at the first token in a statement +or somewhere in the syntactic whitespace before it. + +A \"statement\" here is not restricted to those inside code blocks. +Any kind of declaration-like construct that occur outside function +bodies is also considered a \"statement\". + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + + (save-excursion + (let ((end (point)) + c-maybe-labelp) + (c-syntactic-skip-backward (substring c-stmt-delim-chars 1) nil t) + (or (bobp) + (eq (char-before) ?}) + (and (eq (char-before) ?{) + (not (and c-special-brace-lists + (progn (backward-char) + (c-looking-at-special-brace-list))))) + (c-crosses-statement-barrier-p (point) end))))) + +(defun c-at-expression-start-p () + "Return non-nil if the point is at the first token in an expression or +statement, or somewhere in the syntactic whitespace before it. + +An \"expression\" here is a bit different from the normal language +grammar sense: It's any sequence of expression tokens except commas, +unless they are enclosed inside parentheses of some kind. Also, an +expression never continues past an enclosing parenthesis, but it might +contain parenthesis pairs of any sort except braces. + +Since expressions never cross statement boundaries, this function also +recognizes statement beginnings, just like `c-at-statement-start-p'. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + + (save-excursion + (let ((end (point)) + (c-stmt-delim-chars c-stmt-delim-chars-with-comma) + c-maybe-labelp) + (c-syntactic-skip-backward (substring c-stmt-delim-chars 1) nil t) + (or (bobp) + (memq (char-before) '(?{ ?})) + (save-excursion (backward-char) + (looking-at "\\s(")) + (c-crosses-statement-barrier-p (point) end))))) ;; A set of functions that covers various idiosyncrasies in @@ -1020,7 +1189,8 @@ Line continuations, i.e. a backslashes followed by line breaks, are treated as whitespace. -This function does not do any hidden buffer changes." +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." (while (or ;; If forward-comment in at least XEmacs 21 is given a large @@ -1054,8 +1224,7 @@ (while (progn (skip-chars-backward " \t\n\r\f\v") (and (looking-at "[\n\r]") - (eq (char-before) ?\\) - (< (point) start))) + (eq (char-before) ?\\))) (backward-char)) (if (bobp) @@ -1088,13 +1257,16 @@ Line continuations, i.e. a backslashes followed by line breaks, are treated as whitespace. The line breaks that end line comments are considered to be the comment enders, so the point cannot be at the end -of the same line to move over a line comment. - -This function does not do any hidden buffer changes." +of the same line to move over a line comment. Unlike +c-backward-syntactic-ws, this function doesn't move back over +preprocessor directives. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." (let ((start (point))) (while (and - ;; `forward-comment' in some emacsen (e.g. Emacs 19.34) + ;; `forward-comment' in some emacsen (e.g. XEmacs 21.4) ;; return t when moving backwards at bob. (not (bobp)) @@ -1189,7 +1361,7 @@ ; ;; properties in the buffer. ; (interactive) ; (save-excursion -; (let (in-face) +; (c-save-buffer-state (in-face) ; (goto-char (point-min)) ; (setq in-face (if (get-text-property (point) 'c-is-sws) ; (point))) @@ -1220,30 +1392,35 @@ ) (defmacro c-put-is-sws (beg end) + ;; This macro does a hidden buffer change. `(let ((beg ,beg) (end ,end)) (put-text-property beg end 'c-is-sws t) ,@(when (facep 'c-debug-is-sws-face) `((c-debug-add-face beg end 'c-debug-is-sws-face))))) (defmacro c-put-in-sws (beg end) + ;; This macro does a hidden buffer change. `(let ((beg ,beg) (end ,end)) (put-text-property beg end 'c-in-sws t) ,@(when (facep 'c-debug-is-sws-face) `((c-debug-add-face beg end 'c-debug-in-sws-face))))) (defmacro c-remove-is-sws (beg end) + ;; This macro does a hidden buffer change. `(let ((beg ,beg) (end ,end)) (remove-text-properties beg end '(c-is-sws nil)) ,@(when (facep 'c-debug-is-sws-face) `((c-debug-remove-face beg end 'c-debug-is-sws-face))))) (defmacro c-remove-in-sws (beg end) + ;; This macro does a hidden buffer change. `(let ((beg ,beg) (end ,end)) (remove-text-properties beg end '(c-in-sws nil)) ,@(when (facep 'c-debug-is-sws-face) `((c-debug-remove-face beg end 'c-debug-in-sws-face))))) (defmacro c-remove-is-and-in-sws (beg end) + ;; This macro does a hidden buffer change. `(let ((beg ,beg) (end ,end)) (remove-text-properties beg end '(c-is-sws nil c-in-sws nil)) ,@(when (facep 'c-debug-is-sws-face) @@ -1255,6 +1432,8 @@ ;; `c-forward-sws' or `c-backward-sws' are used outside ;; `c-save-buffer-state' or similar then this will remove the cache ;; properties right after they're added. + ;; + ;; This function does hidden buffer changes. (save-excursion ;; Adjust the end to remove the properties in any following simple @@ -1291,6 +1470,8 @@ (defun c-forward-sws () ;; Used by `c-forward-syntactic-ws' to implement the unbounded search. + ;; + ;; This function might do hidden buffer changes. (let (;; `rung-pos' is set to a position as early as possible in the ;; unmarked part of the simple ws region. @@ -1483,6 +1664,8 @@ (defun c-backward-sws () ;; Used by `c-backward-syntactic-ws' to implement the unbounded search. + ;; + ;; This function might do hidden buffer changes. (let (;; `rung-pos' is set to a position as late as possible in the unmarked ;; part of the simple ws region. @@ -1703,12 +1886,13 @@ ))) -;; A system for handling noteworthy parens before the point. +;; A system for finding noteworthy parens before the point. (defvar c-state-cache nil) (make-variable-buffer-local 'c-state-cache) ;; The state cache used by `c-parse-state' to cut down the amount of ;; searching. It's the result from some earlier `c-parse-state' call. +;; ;; The use of the cached info is more effective if the next ;; `c-parse-state' call is on a line close by the one the cached state ;; was made at; the cache can actually slow down a little if the @@ -1722,24 +1906,58 @@ ;; change of narrowing is likely to affect the parens that are visible ;; before the point. +(defvar c-state-cache-good-pos 1) +(make-variable-buffer-local 'c-state-cache-good-pos) +;; This is a position where `c-state-cache' is known to be correct. +;; It's a position inside one of the recorded unclosed parens or the +;; top level, but not further nested inside any literal or subparen +;; that is closed before the last recorded position. +;; +;; The exact position is chosen to try to be close to yet earlier than +;; the position where `c-state-cache' will be called next. Right now +;; the heuristic is to set it to the position after the last found +;; closing paren (of any type) before the line on which +;; `c-parse-state' was called. That is chosen primarily to work well +;; with refontification of the current line. + (defsubst c-invalidate-state-cache (pos) ;; Invalidate all info on `c-state-cache' that applies to the buffer ;; at POS or higher. This is much like `c-whack-state-after', but ;; it never changes a paren pair element into an open paren element. ;; Doing that would mean that the new open paren wouldn't have the ;; required preceding paren pair element. - ;; - ;; This function does not do any hidden buffer changes. - (while (and c-state-cache + (while (and (or c-state-cache + (when (< pos c-state-cache-good-pos) + (setq c-state-cache-good-pos 1) + nil)) (let ((elem (car c-state-cache))) (if (consp elem) - (or (<= pos (car elem)) - (< pos (cdr elem))) - (<= pos elem)))) + (or (< pos (cdr elem)) + (when (< pos c-state-cache-good-pos) + (setq c-state-cache-good-pos (cdr elem)) + nil)) + (or (<= pos elem) + (when (< pos c-state-cache-good-pos) + (setq c-state-cache-good-pos (1+ elem)) + nil))))) (setq c-state-cache (cdr c-state-cache)))) +(defun c-get-fallback-start-pos (here) + ;; Return the start position for building `c-state-cache' from + ;; scratch. + (save-excursion + ;; Go back 2 bods, but ignore any bogus positions returned by + ;; beginning-of-defun (i.e. open paren in column zero). + (goto-char here) + (let ((cnt 2)) + (while (not (or (bobp) (zerop cnt))) + (c-beginning-of-defun-1) + (if (eq (char-after) ?\{) + (setq cnt (1- cnt))))) + (point))) + (defun c-parse-state () - ;; Finds and records all noteworthy parens between some good point + ;; Find and record all noteworthy parens between some good point ;; earlier in the file and point. That good point is at least the ;; beginning of the top-level construct we are in, or the beginning ;; of the preceding top-level construct if we aren't in one. @@ -1750,22 +1968,32 @@ ;; the point. If an element is a cons, it gives the position of a ;; closed brace paren pair; the car is the start paren position and ;; the cdr is the position following the closing paren. Only the - ;; last closed brace paren pair before each open paren is recorded, - ;; and thus the state never contains two cons elements in - ;; succession. + ;; last closed brace paren pair before each open paren and before + ;; the point is recorded, and thus the state never contains two cons + ;; elements in succession. ;; ;; Currently no characters which are given paren syntax with the ;; syntax-table property are recorded, i.e. angle bracket arglist ;; parens are never present here. Note that this might change. ;; - ;; This function does not do any hidden buffer changes. + ;; BUG: This function doesn't cope entirely well with unbalanced + ;; parens in macros. E.g. in the following case the brace before + ;; the macro isn't balanced with the one after it: + ;; + ;; { + ;; #define X { + ;; } + ;; + ;; This function might do hidden buffer changes. (save-restriction (let* ((here (point)) + (here-bol (c-point 'bol)) (c-macro-start (c-query-macro-start)) (in-macro-start (or c-macro-start (point))) - old-state last-pos pairs pos save-pos) - (c-invalidate-state-cache (point)) + old-state last-pos brace-pair-open brace-pair-close + pos save-pos) + (c-invalidate-state-cache here) ;; If the minimum position has changed due to narrowing then we ;; have to fix the tail of `c-state-cache' accordingly. @@ -1780,12 +2008,14 @@ (setq ptr (cdr ptr))) (when (consp ptr) (if (eq (cdr ptr) c-state-cache) - (setq c-state-cache nil) + (setq c-state-cache nil + c-state-cache-good-pos 1) (setcdr ptr nil)))) ;; If point-min has moved backward then we drop the state ;; completely. It's possible to do a better job here and ;; recalculate the top only. - (setq c-state-cache nil)) + (setq c-state-cache nil + c-state-cache-good-pos 1)) (setq c-state-cache-start (point-min))) ;; Get the latest position we know are directly inside the @@ -1794,115 +2024,152 @@ (if (consp (car c-state-cache)) (cdr (car c-state-cache)) (1+ (car c-state-cache))))) - - ;; Check if the found last-pos is in a macro. If it is, and - ;; we're not in the same macro, we must discard everything on - ;; c-state-cache that is inside the macro before using it. - (when last-pos - (save-excursion - (goto-char last-pos) - (when (and (c-beginning-of-macro) - (/= (point) in-macro-start)) - (c-invalidate-state-cache (point)) - ;; Set last-pos again, just like above. - (setq last-pos (and c-state-cache - (if (consp (car c-state-cache)) - (cdr (car c-state-cache)) - (1+ (car c-state-cache)))))))) - - (setq pos - ;; Find the start position for the forward search. (Can't - ;; search in the backward direction since point might be - ;; in some kind of literal.) - (or (when last-pos - - ;; There's a cached state with a containing paren. Pop - ;; off the stale containing sexps from it by going - ;; forward out of parens as far as possible. - (narrow-to-region (point-min) here) - (let (placeholder pair-beg) - (while (and c-state-cache - (setq placeholder - (c-up-list-forward last-pos))) - (setq last-pos placeholder) - (if (consp (car c-state-cache)) - (setq pair-beg (car-safe (cdr c-state-cache)) - c-state-cache (cdr-safe (cdr c-state-cache))) - (setq pair-beg (car c-state-cache) - c-state-cache (cdr c-state-cache)))) - - (when (and pair-beg (eq (char-after pair-beg) ?{)) - ;; The last paren pair we moved out from was a brace - ;; pair. Modify the state to record this as a closed - ;; pair now. - (if (consp (car-safe c-state-cache)) - (setq c-state-cache (cdr c-state-cache))) - (setq c-state-cache (cons (cons pair-beg last-pos) - c-state-cache)))) - - ;; Check if the preceding balanced paren is within a - ;; macro; it should be ignored if we're outside the - ;; macro. There's no need to check any further upwards; - ;; if the macro contains an unbalanced opening paren then - ;; we're smoked anyway. - (when (and (<= (point) in-macro-start) - (consp (car c-state-cache))) - (save-excursion - (goto-char (car (car c-state-cache))) - (when (c-beginning-of-macro) - (setq here (point) - c-state-cache (cdr c-state-cache))))) - - (when c-state-cache - (setq old-state c-state-cache) - last-pos)) - - (save-excursion - ;; go back 2 bods, but ignore any bogus positions - ;; returned by beginning-of-defun (i.e. open paren in - ;; column zero) - (goto-char here) - (let ((cnt 2)) - (while (not (or (bobp) (zerop cnt))) - (c-beginning-of-defun-1) - (if (eq (char-after) ?\{) - (setq cnt (1- cnt))))) - (point)))) + (if (or (not last-pos) + (< last-pos c-state-cache-good-pos)) + (setq last-pos c-state-cache-good-pos) + ;; Take the opportunity to move the cached good position + ;; further down. + (if (< last-pos here-bol) + (setq c-state-cache-good-pos last-pos))) + + ;; Check if `last-pos' is in a macro. If it is, and we're not + ;; in the same macro, we must discard everything on + ;; `c-state-cache' that is inside the macro before using it. + (save-excursion + (goto-char last-pos) + (when (and (c-beginning-of-macro) + (/= (point) in-macro-start)) + (c-invalidate-state-cache (point)) + ;; Set `last-pos' again just like above except that there's + ;; no use looking at `c-state-cache-good-pos' here. + (setq last-pos (if c-state-cache + (if (consp (car c-state-cache)) + (cdr (car c-state-cache)) + (1+ (car c-state-cache))) + 1)))) + + ;; If we've moved very far from the last cached position then + ;; it's probably better to redo it from scratch, otherwise we + ;; might spend a lot of time searching from `last-pos' down to + ;; here. + (when (< last-pos (- here 20000)) + ;; First get the fallback start position. If it turns out + ;; that it's so far back that the cached state is closer then + ;; we'll keep it afterall. + (setq pos (c-get-fallback-start-pos here)) + (if (<= pos last-pos) + (setq pos nil) + (setq last-pos nil + c-state-cache nil + c-state-cache-good-pos 1))) + + ;; Find the start position for the forward search. (Can't + ;; search in the backward direction since the point might be in + ;; some kind of literal.) + + (unless pos + (setq old-state c-state-cache) + + ;; There's a cached state with a containing paren. Pop off + ;; the stale containing sexps from it by going forward out of + ;; parens as far as possible. + (narrow-to-region (point-min) here) + (let (placeholder pair-beg) + (while (and c-state-cache + (setq placeholder + (c-up-list-forward last-pos))) + (setq last-pos placeholder) + (if (consp (car c-state-cache)) + (setq pair-beg (car-safe (cdr c-state-cache)) + c-state-cache (cdr-safe (cdr c-state-cache))) + (setq pair-beg (car c-state-cache) + c-state-cache (cdr c-state-cache)))) + + (when (and pair-beg (eq (char-after pair-beg) ?{)) + ;; The last paren pair we moved out from was a brace + ;; pair. Modify the state to record this as a closed + ;; pair now. + (if (consp (car-safe c-state-cache)) + (setq c-state-cache (cdr c-state-cache))) + (setq c-state-cache (cons (cons pair-beg last-pos) + c-state-cache)))) + + ;; Check if the preceding balanced paren is within a + ;; macro; it should be ignored if we're outside the + ;; macro. There's no need to check any further upwards; + ;; if the macro contains an unbalanced opening paren then + ;; we're smoked anyway. + (when (and (<= (point) in-macro-start) + (consp (car c-state-cache))) + (save-excursion + (goto-char (car (car c-state-cache))) + (when (c-beginning-of-macro) + (setq here (point) + c-state-cache (cdr c-state-cache))))) + + (unless (eq c-state-cache old-state) + ;; Have to adjust the cached good position if state has been + ;; popped off. + (setq c-state-cache-good-pos + (if c-state-cache + (if (consp (car c-state-cache)) + (cdr (car c-state-cache)) + (1+ (car c-state-cache))) + 1) + old-state c-state-cache)) + + (when c-state-cache + (setq pos last-pos))) + + ;; Get the fallback start position. + (unless pos + (setq pos (c-get-fallback-start-pos here) + c-state-cache nil + c-state-cache-good-pos 1)) (narrow-to-region (point-min) here) (while pos - ;; Find the balanced brace pairs. (setq save-pos pos - pairs nil) - (while (and (setq last-pos (c-down-list-forward pos)) - (setq pos (c-up-list-forward last-pos))) - (if (eq (char-before last-pos) ?{) - (setq pairs (cons (cons last-pos pos) pairs)))) - - ;; Should ignore any pairs that are in a macro, providing - ;; we're not in the same one. - (when (and pairs (< (car (car pairs)) in-macro-start)) - (while (and (save-excursion - (goto-char (car (car pairs))) - (c-beginning-of-macro)) - (setq pairs (cdr pairs))))) + brace-pair-open nil) + + ;; Find the balanced brace pairs. This loop is hot, so it + ;; does ugly tricks to go faster. + (c-safe + (let (set-good-pos set-brace-pair) + (while t + (setq last-pos nil + last-pos (scan-lists pos 1 -1)) ; Might signal. + (setq pos (scan-lists last-pos 1 1) ; Might signal. + set-good-pos (< pos here-bol) + set-brace-pair (eq (char-before last-pos) ?{)) + + ;; Update the cached good position and record the brace + ;; pair, whichever is applicable for the paren we've + ;; just jumped over. But first check that it isn't + ;; inside a macro and the point isn't inside the same + ;; one. + (when (and (or set-good-pos set-brace-pair) + (or (>= pos in-macro-start) + (save-excursion + (goto-char pos) + (not (c-beginning-of-macro))))) + (if set-good-pos + (setq c-state-cache-good-pos pos)) + (if set-brace-pair + (setq brace-pair-open last-pos + brace-pair-close pos)))))) ;; Record the last brace pair. - (when pairs - (if (and (eq c-state-cache old-state) - (consp (car-safe c-state-cache))) - ;; There's a closed pair on the cached state but we've - ;; found a later one, so remove it. - (setq c-state-cache (cdr c-state-cache))) - (setq pairs (car pairs)) - (setcar pairs (1- (car pairs))) - (when (consp (car-safe c-state-cache)) - ;; There could already be a cons first in `c-state-cache' - ;; if we've e.g. jumped over an unbalanced open paren in a - ;; macro below. - (setq c-state-cache (cdr c-state-cache))) - (setq c-state-cache (cons pairs c-state-cache))) + (when brace-pair-open + (let ((head (car-safe c-state-cache))) + (if (consp head) + (progn + (setcar head (1- brace-pair-open)) + (setcdr head brace-pair-close)) + (setq c-state-cache (cons (cons (1- brace-pair-open) + brace-pair-close) + c-state-cache))))) (if last-pos ;; Prepare to loop, but record the open paren only if it's @@ -1911,16 +2178,18 @@ ;; that got an open paren syntax-table property. (progn (setq pos last-pos) - (if (and (or (>= last-pos in-macro-start) - (save-excursion - (goto-char last-pos) - (not (c-beginning-of-macro)))) - ;; Check for known types of parens that we want - ;; to record. The syntax table is not to be - ;; trusted here since the caller might be using - ;; e.g. `c++-template-syntax-table'. - (memq (char-before last-pos) '(?{ ?\( ?\[))) - (setq c-state-cache (cons (1- last-pos) c-state-cache)))) + (when (and (or (>= last-pos in-macro-start) + (save-excursion + (goto-char last-pos) + (not (c-beginning-of-macro)))) + ;; Check for known types of parens that we + ;; want to record. The syntax table is not to + ;; be trusted here since the caller might be + ;; using e.g. `c++-template-syntax-table'. + (memq (char-before last-pos) '(?{ ?\( ?\[))) + (if (< last-pos here-bol) + (setq c-state-cache-good-pos last-pos)) + (setq c-state-cache (cons (1- last-pos) c-state-cache)))) (if (setq last-pos (c-up-list-forward pos)) ;; Found a close paren without a corresponding opening @@ -1928,7 +2197,8 @@ ;; scan backward for the start paren and then start over. (progn (setq pos (c-up-list-backward pos) - c-state-cache nil) + c-state-cache nil + c-state-cache-good-pos c-state-cache-start) (when (or (not pos) ;; Emacs (up to at least 21.2) can get confused by ;; open parens in column zero inside comments: The @@ -1943,6 +2213,7 @@ (c-point 'bol last-pos))))))) (setq pos nil)))) + ;;(message "c-parse-state: %S end: %S" c-state-cache c-state-cache-good-pos) c-state-cache))) ;; Debug tool to catch cache inconsistencies. @@ -1952,11 +2223,23 @@ (cc-bytecomp-defun c-real-parse-state) (defun c-debug-parse-state () (let ((res1 (c-real-parse-state)) res2) - (let ((c-state-cache nil)) + (let ((c-state-cache nil) + (c-state-cache-start 1) + (c-state-cache-good-pos 1)) (setq res2 (c-real-parse-state))) (unless (equal res1 res2) - (error "c-parse-state inconsistency: using cache: %s, from scratch: %s" - res1 res2)) + ;; The cache can actually go further back due to the ad-hoc way + ;; the first paren is found, so try to whack off a bit of its + ;; start before complaining. + (save-excursion + (goto-char (or (c-least-enclosing-brace res2) (point))) + (c-beginning-of-defun-1) + (while (not (or (bobp) (eq (char-after) ?{))) + (c-beginning-of-defun-1)) + (unless (equal (c-whack-state-before (point) res1) res2) + (message (concat "c-parse-state inconsistency: " + "using cache: %s, from scratch: %s") + res1 res2)))) res1)) (defun c-toggle-parse-state-debug (&optional arg) (interactive "P") @@ -1965,12 +2248,12 @@ 'c-debug-parse-state 'c-real-parse-state))) (c-keep-region-active)) +(when c-debug-parse-state + (c-toggle-parse-state-debug 1)) (defun c-whack-state-before (bufpos paren-state) ;; Whack off any state information from PAREN-STATE which lies ;; before BUFPOS. Not destructive on PAREN-STATE. - ;; - ;; This function does not do any hidden buffer changes. (let* ((newstate (list nil)) (ptr newstate) car) @@ -1986,8 +2269,6 @@ (defun c-whack-state-after (bufpos paren-state) ;; Whack off any state information from PAREN-STATE which lies at or ;; after BUFPOS. Not destructive on PAREN-STATE. - ;; - ;; This function does not do any hidden buffer changes. (catch 'done (while paren-state (let ((car (car paren-state))) @@ -2018,9 +2299,7 @@ (defun c-most-enclosing-brace (paren-state &optional bufpos) ;; Return the bufpos of the innermost enclosing open paren before - ;; bufpos that hasn't been narrowed out, or nil if none was found. - ;; - ;; This function does not do any hidden buffer changes. + ;; bufpos, or nil if none was found. (let (enclosingp) (or bufpos (setq bufpos 134217727)) (while paren-state @@ -2029,34 +2308,31 @@ (if (or (consp enclosingp) (>= enclosingp bufpos)) (setq enclosingp nil) - (if (< enclosingp (point-min)) - (setq enclosingp nil)) (setq paren-state nil))) enclosingp)) -(defun c-least-enclosing-brace (paren-state &optional bufpos) - ;; Return the bufpos of the outermost enclosing open paren before - ;; bufpos that hasn't been narrowed out, or nil if none was found. - ;; - ;; This function does not do any hidden buffer changes. +(defun c-least-enclosing-brace (paren-state) + ;; Return the bufpos of the outermost enclosing open paren, or nil + ;; if none was found. (let (pos elem) - (or bufpos (setq bufpos 134217727)) (while paren-state (setq elem (car paren-state) paren-state (cdr paren-state)) - (unless (or (consp elem) - (>= elem bufpos)) - (if (>= elem (point-min)) - (setq pos elem)))) + (if (integerp elem) + (setq pos elem))) pos)) (defun c-safe-position (bufpos paren-state) - ;; Return the closest known safe position higher up than BUFPOS, or - ;; nil if PAREN-STATE doesn't contain one. Return nil if BUFPOS is - ;; nil, which is useful to find the closest limit before a given - ;; limit that might be nil. - ;; - ;; This function does not do any hidden buffer changes. + ;; Return the closest "safe" position recorded on PAREN-STATE that + ;; is higher up than BUFPOS. Return nil if PAREN-STATE doesn't + ;; contain any. Return nil if BUFPOS is nil, which is useful to + ;; find the closest limit before a given limit that might be nil. + ;; + ;; A "safe" position is a position at or after a recorded open + ;; paren, or after a recorded close paren. The returned position is + ;; thus either the first position after a close brace, or the first + ;; position after an enclosing paren, or at the enclosing paren in + ;; case BUFPOS is immediately after it. (when bufpos (let (elem) (catch 'done @@ -2118,33 +2394,61 @@ "Return non-nil if the point is on or directly after an identifier. Keywords are recognized and not considered identifiers. If an identifier is detected, the returned value is its starting position. -If an identifier both starts and stops at the point \(can only happen -in Pike) then the point for the preceding one is returned. - -This function does not do any hidden buffer changes." +If an identifier ends at the point and another begins at it \(can only +happen in Pike) then the point for the preceding one is returned. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + + ;; FIXME: Shouldn't this function handle "operator" in C++? (save-excursion - (if (zerop (skip-syntax-backward "w_")) - - (when (c-major-mode-is 'pike-mode) - ;; Handle the `<operator> syntax in Pike. - (let ((pos (point))) - (skip-chars-backward "-!%&*+/<=>^|~[]()") - (and (if (< (skip-chars-backward "`") 0) - t - (goto-char pos) - (eq (char-after) ?\`)) - (looking-at c-symbol-key) - (>= (match-end 0) pos) - (point)))) - - (and (not (looking-at c-keywords-regexp)) - (point))))) + (skip-syntax-backward "w_") + + (or + + ;; Check for a normal (non-keyword) identifier. + (and (looking-at c-symbol-start) + (not (looking-at c-keywords-regexp)) + (point)) + + (when (c-major-mode-is 'pike-mode) + ;; Handle the `<operator> syntax in Pike. + (let ((pos (point))) + (skip-chars-backward "-!%&*+/<=>^|~[]()") + (and (if (< (skip-chars-backward "`") 0) + t + (goto-char pos) + (eq (char-after) ?\`)) + (looking-at c-symbol-key) + (>= (match-end 0) pos) + (point)))) + + ;; Handle the "operator +" syntax in C++. + (when (and c-overloadable-operators-regexp + (= (c-backward-token-2 0) 0)) + + (cond ((and (looking-at c-overloadable-operators-regexp) + (or (not c-opt-op-identitier-prefix) + (and (= (c-backward-token-2 1) 0) + (looking-at c-opt-op-identitier-prefix)))) + (point)) + + ((save-excursion + (and c-opt-op-identitier-prefix + (looking-at c-opt-op-identitier-prefix) + (= (c-forward-token-2 1) 0) + (looking-at c-overloadable-operators-regexp))) + (point)))) + + ))) (defsubst c-simple-skip-symbol-backward () ;; If the point is at the end of a symbol then skip backward to the ;; beginning of it. Don't move otherwise. Return non-nil if point ;; moved. + ;; + ;; This function might do hidden buffer changes. (or (< (skip-syntax-backward "w_") 0) (and (c-major-mode-is 'pike-mode) ;; Handle the `<operator> syntax in Pike. @@ -2157,11 +2461,13 @@ (goto-char pos) nil))))) -(defsubst c-beginning-of-current-token (&optional back-limit) +(defun c-beginning-of-current-token (&optional back-limit) ;; Move to the beginning of the current token. Do not move if not ;; in the middle of one. BACK-LIMIT may be used to bound the ;; backward search; if given it's assumed to be at the boundary ;; between two tokens. + ;; + ;; This function might do hidden buffer changes. (if (looking-at "\\w\\|\\s_") (skip-syntax-backward "w_" back-limit) (let ((start (point))) @@ -2183,6 +2489,8 @@ ;; middle of one. BACK-LIMIT may be used to bound the backward ;; search; if given it's assumed to be at the boundary between two ;; tokens. Return non-nil if the point is moved, nil otherwise. + ;; + ;; This function might do hidden buffer changes. (let ((start (point))) (cond ((< (skip-syntax-backward "w_" (1- start)) 0) (skip-syntax-forward "w_")) @@ -2228,7 +2536,10 @@ that if COUNT is 0 and no appropriate token beginning is found, 1 will be returned. Thus, a return value of 0 guarantees that point is at the requested position and a return value less \(without signs) than -COUNT guarantees that point is at the beginning of some token." +COUNT guarantees that point is at the beginning of some token. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." (or count (setq count 1)) (if (< count 0) @@ -2417,7 +2728,10 @@ Bug: Unbalanced parens inside cpp directives are currently not handled correctly \(i.e. they don't get ignored as they should) when -PAREN-LEVEL is set." +PAREN-LEVEL is set. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." (or bound (setq bound (point-max))) (if paren-level (setq paren-level -1)) @@ -2601,23 +2915,39 @@ (goto-char bound)) nil))) -(defun c-syntactic-skip-backward (skip-chars &optional limit) +(defun c-syntactic-skip-backward (skip-chars &optional limit paren-level) "Like `skip-chars-backward' but only look at syntactically relevant chars, i.e. don't stop at positions inside syntactic whitespace or string literals. Preprocessor directives are also ignored, with the exception of the one that the point starts within, if any. If LIMIT is given, -it's assumed to be at a syntactically relevant position." +it's assumed to be at a syntactically relevant position. + +If PAREN-LEVEL is non-nil, the function won't stop in nested paren +sexps, and the search will also not go outside the current paren sexp. +However, if LIMIT or the buffer limit is reached inside a nested paren +then the point will be left at the limit. + +Non-nil is returned if the point moved, nil otherwise. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." (let ((start (point)) + state ;; A list of syntactically relevant positions in descending ;; order. It's used to avoid scanning repeatedly over ;; potentially large regions with `parse-partial-sexp' to verify ;; each position. safe-pos-list + ;; The position at the beginning of `safe-pos-list'. + safe-pos ;; The result from `c-beginning-of-macro' at the start position or the ;; start position itself if it isn't within a macro. Evaluated on ;; demand. - start-macro-beg) + start-macro-beg + ;; The earliest position after the current one with the same paren + ;; level. Used only when `paren-level' is set. + (paren-level-pos (point))) (while (progn (while (and @@ -2626,7 +2956,7 @@ ;; Use `parse-partial-sexp' from a safe position down to ;; the point to check if it's outside comments and ;; strings. - (let ((pos (point)) safe-pos state) + (let ((pos (point)) state-2 pps-end-pos) ;; Pick a safe position as close to the point as ;; possible. ;; @@ -2643,13 +2973,18 @@ (point-min)) safe-pos-list (list safe-pos))) + ;; Cache positions along the way to use if we have to + ;; back up more. We cache every closing paren on the + ;; same level. If the paren cache is relevant in this + ;; region then we're typically already on the same + ;; level as the target position. Note that we might + ;; cache positions after opening parens in case + ;; safe-pos is in a nested list. That's both uncommon + ;; and harmless. (while (progn (setq state (parse-partial-sexp safe-pos pos 0)) (< (point) pos)) - ;; Cache positions along the way to use if we have to - ;; back up more. Every closing paren on the same - ;; level seems like fairly well spaced positions. (setq safe-pos (point) safe-pos-list (cons safe-pos safe-pos-list))) @@ -2657,13 +2992,50 @@ ((or (elt state 3) (elt state 4)) ;; Inside string or comment. Continue search at the ;; beginning of it. - (if (setq pos (nth 8 state)) - ;; It's an emacs where `parse-partial-sexp' - ;; supplies the starting position. - (goto-char pos) - (goto-char (car (c-literal-limits safe-pos)))) + (goto-char (elt state 8)) t) + ((and paren-level + (save-excursion + (setq state-2 (parse-partial-sexp + pos paren-level-pos -1) + pps-end-pos (point)) + (/= (car state-2) 0))) + ;; Not at the right level. + + (if (and (< (car state-2) 0) + ;; We stop above if we go out of a paren. + ;; Now check whether it precedes or is + ;; nested in the starting sexp. + (save-excursion + (setq state-2 + (parse-partial-sexp + pps-end-pos paren-level-pos + nil nil state-2)) + (< (car state-2) 0))) + + ;; We've stopped short of the starting position + ;; so the hit was inside a nested list. Go up + ;; until we are at the right level. + (condition-case nil + (progn + (goto-char (scan-lists pos -1 + (- (car state-2)))) + (setq paren-level-pos (point)) + (if (and limit (>= limit paren-level-pos)) + (progn + (goto-char limit) + nil) + t)) + (error + (goto-char (or limit (point-min))) + nil)) + + ;; The hit was outside the list at the start + ;; position. Go to the start of the list and exit. + (goto-char (1+ (elt state-2 1))) + nil)) + ((c-beginning-of-macro limit) ;; Inside a macro. (if (< (point) @@ -2674,10 +3046,20 @@ (c-beginning-of-macro limit) (point))))) t + ;; It's inside the same macro we started in so it's ;; a relevant match. (goto-char pos) - nil)))))) + nil))))) + + ;; If the state contains the start of the containing sexp we + ;; cache that position too, so that parse-partial-sexp in the + ;; next run has a bigger chance of starting at the same level + ;; as the target position and thus will get more good safe + ;; positions into the list. + (if (elt state 1) + (setq safe-pos (1+ (elt state 1)) + safe-pos-list (cons safe-pos safe-pos-list)))) (> (point) (progn @@ -2686,7 +3068,124 @@ (c-backward-syntactic-ws) (point))))) - (- (point) start))) + ;; We might want to extend this with more useful return values in + ;; the future. + (/= (point) start))) + +;; The following is an alternative implementation of +;; `c-syntactic-skip-backward' that uses backward movement to keep +;; track of the syntactic context. It turned out to be generally +;; slower than the one above which uses forward checks from earlier +;; safe positions. +;; +;;(defconst c-ssb-stop-re +;; ;; The regexp matching chars `c-syntactic-skip-backward' needs to +;; ;; stop at to avoid going into comments and literals. +;; (concat +;; ;; Match comment end syntax and string literal syntax. Also match +;; ;; '/' for block comment endings (not covered by comment end +;; ;; syntax). +;; "\\s>\\|/\\|\\s\"" +;; (if (memq 'gen-string-delim c-emacs-features) +;; "\\|\\s|" +;; "") +;; (if (memq 'gen-comment-delim c-emacs-features) +;; "\\|\\s!" +;; ""))) +;; +;;(defconst c-ssb-stop-paren-re +;; ;; Like `c-ssb-stop-re' but also stops at paren chars. +;; (concat c-ssb-stop-re "\\|\\s(\\|\\s)")) +;; +;;(defconst c-ssb-sexp-end-re +;; ;; Regexp matching the ending syntax of a complex sexp. +;; (concat c-string-limit-regexp "\\|\\s)")) +;; +;;(defun c-syntactic-skip-backward (skip-chars &optional limit paren-level) +;; "Like `skip-chars-backward' but only look at syntactically relevant chars, +;;i.e. don't stop at positions inside syntactic whitespace or string +;;literals. Preprocessor directives are also ignored. However, if the +;;point is within a comment, string literal or preprocessor directory to +;;begin with, its contents is treated as syntactically relevant chars. +;;If LIMIT is given, it limits the backward search and the point will be +;;left there if no earlier position is found. +;; +;;If PAREN-LEVEL is non-nil, the function won't stop in nested paren +;;sexps, and the search will also not go outside the current paren sexp. +;;However, if LIMIT or the buffer limit is reached inside a nested paren +;;then the point will be left at the limit. +;; +;;Non-nil is returned if the point moved, nil otherwise. +;; +;;Note that this function might do hidden buffer changes. See the +;;comment at the start of cc-engine.el for more info." +;; +;; (save-restriction +;; (when limit +;; (narrow-to-region limit (point-max))) +;; +;; (let ((start (point))) +;; (catch 'done +;; (while (let ((last-pos (point)) +;; (stop-pos (progn +;; (skip-chars-backward skip-chars) +;; (point)))) +;; +;; ;; Skip back over the same region as +;; ;; `skip-chars-backward' above, but keep to +;; ;; syntactically relevant positions. +;; (goto-char last-pos) +;; (while (and +;; ;; `re-search-backward' with a single char regexp +;; ;; should be fast. +;; (re-search-backward +;; (if paren-level c-ssb-stop-paren-re c-ssb-stop-re) +;; stop-pos 'move) +;; +;; (progn +;; (cond +;; ((looking-at "\\s(") +;; ;; `paren-level' is set and we've found the +;; ;; start of the containing paren. +;; (forward-char) +;; (throw 'done t)) +;; +;; ((looking-at c-ssb-sexp-end-re) +;; ;; We're at the end of a string literal or paren +;; ;; sexp (if `paren-level' is set). +;; (forward-char) +;; (condition-case nil +;; (c-backward-sexp) +;; (error +;; (goto-char limit) +;; (throw 'done t)))) +;; +;; (t +;; (forward-char) +;; ;; At the end of some syntactic ws or possibly +;; ;; after a plain '/' operator. +;; (let ((pos (point))) +;; (c-backward-syntactic-ws) +;; (if (= pos (point)) +;; ;; Was a plain '/' operator. Go past it. +;; (backward-char))))) +;; +;; (> (point) stop-pos)))) +;; +;; ;; Now the point is either at `stop-pos' or at some +;; ;; position further back if `stop-pos' was at a +;; ;; syntactically irrelevant place. +;; +;; ;; Skip additional syntactic ws so that we don't stop +;; ;; at the end of a comment if `skip-chars' is +;; ;; something like "^/". +;; (c-backward-syntactic-ws) +;; +;; (< (point) stop-pos)))) +;; +;; ;; We might want to extend this with more useful return values +;; ;; in the future. +;; (/= (point) start)))) ;; Tools for handling comments and string literals. @@ -2702,7 +3201,9 @@ The last point calculated is cached if the cache is enabled, i.e. if `c-in-literal-cache' is bound to a two element vector. -This function does not do any hidden buffer changes." +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + (if (and (vectorp c-in-literal-cache) (= (point) (aref c-in-literal-cache 0))) (aref c-in-literal-cache 1) @@ -2748,6 +3249,7 @@ ;; (Alan Mackenzie, 2003/4/30). (defun c-fast-in-literal (&optional lim detect-cpp) + ;; This function might do hidden buffer changes. (let ((context (buffer-syntactic-context))) (cond ((eq context 'string) 'string) @@ -2775,104 +3277,8 @@ recognized. This only has effect for comments, which have starting delimiters with more than one character. -This function does not do any hidden buffer changes." - - (save-excursion - (let* ((pos (point)) - (lim (or lim (progn - (c-beginning-of-syntax) - (point)))) - (state (parse-partial-sexp lim pos))) - - (cond ((elt state 3) - ;; String. Search backward for the start. - (while (elt state 3) - (search-backward (make-string 1 (elt state 3))) - (setq state (parse-partial-sexp lim (point)))) - (cons (point) (or (c-safe (c-forward-sexp 1) (point)) - (point-max)))) - - ((elt state 7) - ;; Line comment. Search from bol for the comment starter. - (beginning-of-line) - (setq state (parse-partial-sexp lim (point)) - lim (point)) - (while (not (elt state 7)) - (search-forward "//") ; Should never fail. - (setq state (parse-partial-sexp - lim (point) nil nil state) - lim (point))) - (backward-char 2) - (cons (point) (progn (c-forward-single-comment) (point)))) - - ((elt state 4) - ;; Block comment. Search backward for the comment starter. - (while (elt state 4) - (search-backward "/*") ; Should never fail. - (setq state (parse-partial-sexp lim (point)))) - (cons (point) (progn (c-forward-single-comment) (point)))) - - ((and (not not-in-delimiter) - (not (elt state 5)) - (eq (char-before) ?/) - (looking-at "[/*]")) - ;; We're standing in a comment starter. - (backward-char 1) - (cons (point) (progn (c-forward-single-comment) (point)))) - - (near - (goto-char pos) - - ;; Search forward for a literal. - (skip-chars-forward " \t") - - (cond - ((looking-at c-string-limit-regexp) ; String. - (cons (point) (or (c-safe (c-forward-sexp 1) (point)) - (point-max)))) - - ((looking-at c-comment-start-regexp) ; Line or block comment. - (cons (point) (progn (c-forward-single-comment) (point)))) - - (t - ;; Search backward. - (skip-chars-backward " \t") - - (let ((end (point)) beg) - (cond - ((save-excursion - (< (skip-syntax-backward c-string-syntax) 0)) ; String. - (setq beg (c-safe (c-backward-sexp 1) (point)))) - - ((and (c-safe (forward-char -2) t) - (looking-at "*/")) - ;; Block comment. Due to the nature of line - ;; comments, they will always be covered by the - ;; normal case above. - (goto-char end) - (c-backward-single-comment) - ;; If LIM is bogus, beg will be bogus. - (setq beg (point)))) - - (if beg (cons beg end)))))) - )))) - -(defun c-literal-limits-fast (&optional lim near not-in-delimiter) - ;; Like c-literal-limits, but for emacsen whose `parse-partial-sexp' - ;; returns the pos of the comment start. - - "Return a cons of the beginning and end positions of the comment or -string surrounding point (including both delimiters), or nil if point -isn't in one. If LIM is non-nil, it's used as the \"safe\" position -to start parsing from. If NEAR is non-nil, then the limits of any -literal next to point is returned. \"Next to\" means there's only -spaces and tabs between point and the literal. The search for such a -literal is done first in forward direction. If NOT-IN-DELIMITER is -non-nil, the case when point is inside a starting delimiter won't be -recognized. This only has effect for comments, which have starting -delimiters with more than one character. - -This function does not do any hidden buffer changes." +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." (save-excursion (let* ((pos (point)) @@ -2935,8 +3341,8 @@ (if beg (cons beg end)))))) )))) -(if (memq 'pps-extended-state c-emacs-features) - (defalias 'c-literal-limits 'c-literal-limits-fast)) +;; In case external callers use this; it did have a docstring. +(defalias 'c-literal-limits-fast 'c-literal-limits) (defun c-collect-line-comments (range) "If the argument is a cons of two buffer positions (such as returned by @@ -2946,13 +3352,15 @@ empty lines or non-whitespace characters between them). Otherwise the argument is returned. -This function does not do any hidden buffer changes." +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + (save-excursion (condition-case nil (if (and (consp range) (progn (goto-char (car range)) - (looking-at "//"))) - (let ((col (current-column)) + (looking-at c-line-comment-starter))) + (let ((col (current-column)) (beg (point)) (bopl (c-point 'bopl)) (end (cdr range))) @@ -2960,13 +3368,13 @@ ;; comments which are preceded by code. (while (and (c-backward-single-comment) (>= (point) bopl) - (looking-at "//") + (looking-at c-line-comment-starter) (= col (current-column))) (setq beg (point) bopl (c-point 'bopl))) (goto-char end) (while (and (progn (skip-chars-forward " \t") - (looking-at "//")) + (looking-at c-line-comment-starter)) (= col (current-column)) (prog1 (zerop (forward-line 1)) (setq end (point))))) @@ -2980,7 +3388,9 @@ much faster than using `c-in-literal' and is intended to be used when you need both the type of a literal and its limits. -This function does not do any hidden buffer changes." +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + (if (consp range) (save-excursion (goto-char (car range)) @@ -3032,14 +3442,14 @@ (defmacro c-debug-put-decl-spot-faces (match-pos decl-pos) (when (facep 'c-debug-decl-spot-face) - `(let ((match-pos ,match-pos) (decl-pos ,decl-pos)) + `(c-save-buffer-state ((match-pos ,match-pos) (decl-pos ,decl-pos)) (c-debug-add-face (max match-pos (point-min)) decl-pos 'c-debug-decl-sws-face) (c-debug-add-face decl-pos (min (1+ decl-pos) (point-max)) 'c-debug-decl-spot-face)))) (defmacro c-debug-remove-decl-spot-faces (beg end) (when (facep 'c-debug-decl-spot-face) - `(progn + `(c-save-buffer-state () (c-debug-remove-face ,beg ,end 'c-debug-decl-spot-face) (c-debug-remove-face ,beg ,end 'c-debug-decl-sws-face)))) @@ -3048,6 +3458,8 @@ ;; but it contains lots of free variables that refer to things ;; inside `c-find-decl-spots'. The point is left at `cfd-match-pos' ;; if there is a match, otherwise at `cfd-limit'. + ;; + ;; This macro might do hidden buffer changes. '(progn ;; Find the next property match position if we haven't got one already. @@ -3061,21 +3473,46 @@ 'c-decl-end))))) (setq cfd-prop-match (point)))) - ;; Find the next `c-decl-prefix-re' match if we haven't got one already. + ;; Find the next `c-decl-prefix-or-start-re' match if we haven't + ;; got one already. (unless cfd-re-match - (while (and (setq cfd-re-match - (re-search-forward c-decl-prefix-re cfd-limit 'move)) - (c-got-face-at (1- (setq cfd-re-match (match-end 1))) - c-literal-faces)) - ;; Search again if the match is within a comment or a string literal. + + (if (> cfd-re-match-end (point)) + (goto-char cfd-re-match-end)) + + (while (if (setq cfd-re-match-end + (re-search-forward c-decl-prefix-or-start-re + cfd-limit 'move)) + + ;; Match. Check if it's inside a comment or string literal. + (c-got-face-at + (if (setq cfd-re-match (match-end 1)) + ;; Matched the end of a token preceding a decl spot. + (progn + (goto-char cfd-re-match) + (1- cfd-re-match)) + ;; Matched a token that start a decl spot. + (goto-char (match-beginning 0)) + (point)) + c-literal-faces) + + ;; No match. Finish up and exit the loop. + (setq cfd-re-match cfd-limit) + nil) + + ;; Skip out of comments and string literals. (while (progn (goto-char (next-single-property-change - cfd-re-match 'face nil cfd-limit)) + (point) 'face nil cfd-limit)) (and (< (point) cfd-limit) - (c-got-face-at (point) c-literal-faces))) - (setq cfd-re-match (point)))) + (c-got-face-at (point) c-literal-faces))))) + + ;; If we matched at the decl start, we have to back up over the + ;; preceding syntactic ws to set `cfd-match-pos' and to catch + ;; any decl spots in the syntactic ws. (unless cfd-re-match - (setq cfd-re-match cfd-limit))) + (c-backward-syntactic-ws) + (setq cfd-re-match (point)))) ;; Choose whichever match is closer to the start. (if (< cfd-re-match cfd-prop-match) @@ -3098,14 +3535,21 @@ (point)))))) (defun c-find-decl-spots (cfd-limit cfd-decl-re cfd-face-checklist cfd-fun) - ;; Call CFD-FUN for each possible spot for a declaration from the - ;; point to CFD-LIMIT. A spot for a declaration is the first token - ;; in the buffer and each token after the ones matched by - ;; `c-decl-prefix-re' and after the occurrences of the `c-type' - ;; property with the value `c-decl-end' (if `c-type-decl-end-used' - ;; is set). Only a spot that match CFD-DECL-RE and whose face is in - ;; the CFD-FACE-CHECKLIST list causes CFD-FUN to be called. The - ;; face check is disabled if CFD-FACE-CHECKLIST is nil. + ;; Call CFD-FUN for each possible spot for a declaration, cast or + ;; label from the point to CFD-LIMIT. Such a spot is: + ;; + ;; o The first token after bob. + ;; o The first token after the end of submatch 1 in + ;; `c-decl-prefix-or-start-re' when that submatch matches. + ;; o The start of each `c-decl-prefix-or-start-re' match when + ;; submatch 1 doesn't match. + ;; o The first token after the end of each occurence of the + ;; `c-type' text property with the value `c-decl-end', provided + ;; `c-type-decl-end-used' is set. + ;; + ;; Only a spot that match CFD-DECL-RE and whose face is in the + ;; CFD-FACE-CHECKLIST list causes CFD-FUN to be called. The face + ;; check is disabled if CFD-FACE-CHECKLIST is nil. ;; ;; If the match is inside a macro then the buffer is narrowed to the ;; end of it, so that CFD-FUN can investigate the following tokens @@ -3115,11 +3559,21 @@ ;; ;; CFD-FUN is called with point at the start of the spot. It's ;; passed two arguments: The first is the end position of the token - ;; that `c-decl-prefix-re' matched, or 0 for the implicit match at - ;; bob. The second is a flag that is t when the match is inside a - ;; macro. - ;; - ;; It's assumed that comment and strings are fontified in the + ;; preceding the spot, or 0 for the implicit match at bob. The + ;; second is a flag that is t when the match is inside a macro. If + ;; CFD-FUN adds `c-decl-end' properties somewhere below the current + ;; spot, it should return non-nil to ensure that the next search + ;; will find them. + ;; + ;; The spots are visited approximately in order from top to bottom. + ;; It's however the positions where `c-decl-prefix-or-start-re' + ;; matches and where `c-decl-end' properties are found that are in + ;; order. Since the spots often are at the following token, they + ;; might be visited out of order insofar as more spots are reported + ;; later on within the syntactic whitespace between the match + ;; positions and their spots. + ;; + ;; It's assumed that comments and strings are fontified in the ;; searched range. ;; ;; This is mainly used in fontification, and so has an elaborate @@ -3128,19 +3582,28 @@ ;; ;; All variables in this function begin with `cfd-' to avoid name ;; collision with the (dynamically bound) variables used in CFD-FUN. - - (let ((cfd-buffer-end (point-max)) - ;; The last regexp match found by `c-find-decl-prefix-search'. + ;; + ;; This function might do hidden buffer changes. + + (let ((cfd-start-pos (point)) + (cfd-buffer-end (point-max)) + ;; The end of the token preceding the decl spot last found + ;; with `c-decl-prefix-or-start-re'. `cfd-limit' if there's + ;; no match. cfd-re-match - ;; The last `c-decl-end' found by `c-find-decl-prefix-search'. - ;; If searching for the property isn't needed then we disable - ;; it by faking a first match at the limit. + ;; The end position of the last `c-decl-prefix-or-start-re' + ;; match. If this is greater than `cfd-continue-pos', the + ;; next regexp search is started here instead. + (cfd-re-match-end (point-min)) + ;; The end of the last `c-decl-end' found by + ;; `c-find-decl-prefix-search'. `cfd-limit' if there's no + ;; match. If searching for the property isn't needed then we + ;; disable it by setting it to `cfd-limit' directly. (cfd-prop-match (unless c-type-decl-end-used cfd-limit)) - ;; The position of the last match found by - ;; `c-find-decl-prefix-search'. For regexp matches it's the - ;; end of the matched token, for property matches it's the end - ;; of the property. 0 for the implicit match at bob. - ;; `cfd-limit' if there's no match. + ;; The end of the token preceding the decl spot last found by + ;; `c-find-decl-prefix-search'. 0 for the implicit match at + ;; bob. `cfd-limit' if there's no match. In other words, + ;; this is the minimum of `cfd-re-match' and `cfd-prop-match'. (cfd-match-pos cfd-limit) ;; The position to continue searching at. cfd-continue-pos @@ -3153,127 +3616,219 @@ (cfd-macro-end 0)) ;; Initialize by finding a syntactically relevant start position - ;; before the point, and do the first `c-decl-prefix-re' search - ;; unless we're at bob. - - (let ((start-pos (point)) syntactic-pos) + ;; before the point, and do the first `c-decl-prefix-or-start-re' + ;; search unless we're at bob. + + (let (start-in-literal start-in-macro syntactic-pos) ;; Must back up a bit since we look for the end of the previous ;; statement or declaration, which is earlier than the first ;; returned match. - (when (c-got-face-at (point) c-literal-faces) - ;; But first we need to move to a syntactically relevant - ;; position. Use the faces to back up to the start of the - ;; comment or string literal. - (when (and (not (bobp)) - (c-got-face-at (1- (point)) c-literal-faces)) - (while (progn - (goto-char (previous-single-property-change - (point) 'face nil (point-min))) - (and (> (point) (point-min)) - (c-got-face-at (point) c-literal-faces))))) - - ;; XEmacs doesn't fontify the quotes surrounding string - ;; literals. - (and (featurep 'xemacs) - (eq (get-text-property (point) 'face) - 'font-lock-string-face) - (not (bobp)) - (progn (backward-char) - (not (looking-at c-string-limit-regexp))) - (forward-char)) - - ;; The font lock package might not have fontified the start of - ;; the literal at all so check that we have arrived at - ;; something that looks like a start or else resort to - ;; `c-literal-limits'. - (unless (looking-at c-literal-start-regexp) - (let ((range (c-literal-limits))) - (if range (goto-char (car range)))))) - - ;; Must back out of any macro so that we don't miss any - ;; declaration that could follow after it, unless the limit is - ;; inside the macro. We only check that for the current line to - ;; save some time; it's enough for the by far most common case - ;; when font-lock refontifies the current line only. - (when (save-excursion - (and (= (forward-line 1) 0) - (bolp) ; forward-line has funny behavior at eob. - (or (< (c-point 'eol) cfd-limit) - (progn (backward-char) - (not (eq (char-before) ?\\)))))) - (c-beginning-of-macro)) - - ;; Clear the cache if it applied further down. - (c-invalidate-find-decl-cache start-pos) - - (setq syntactic-pos (point)) - (c-backward-syntactic-ws c-find-decl-syntactic-pos) - - ;; If we hit `c-find-decl-syntactic-pos' and - ;; `c-find-decl-match-pos' is set then we install the cached - ;; values. If we hit `c-find-decl-syntactic-pos' and - ;; `c-find-decl-match-pos' is nil then we know there's no decl - ;; prefix in the whitespace before `c-find-decl-syntactic-pos' - ;; and so we can continue the search from this point. If we - ;; didn't hit `c-find-decl-syntactic-pos' then we're now in the - ;; right spot to begin searching anyway. - (if (and (eq (point) c-find-decl-syntactic-pos) - c-find-decl-match-pos) - - (progn - ;; The match is always outside macros and comments so we - ;; start at the next token. The loop below will later go - ;; back using `cfd-continue-pos' to fix declarations inside - ;; the syntactic ws. + (cond + ;; First we need to move to a syntactically relevant position. + ;; Begin by backing out of comment or string literals. + ((and + (when (c-got-face-at (point) c-literal-faces) + ;; Try to use the faces to back up to the start of the + ;; literal. FIXME: What if the point is on a declaration + ;; inside a comment? + (while (and (not (bobp)) + (c-got-face-at (1- (point)) c-literal-faces)) + (goto-char (previous-single-property-change + (point) 'face nil (point-min)))) + + ;; XEmacs doesn't fontify the quotes surrounding string + ;; literals. + (and (featurep 'xemacs) + (eq (get-text-property (point) 'face) + 'font-lock-string-face) + (not (bobp)) + (progn (backward-char) + (not (looking-at c-string-limit-regexp))) + (forward-char)) + + ;; Don't trust the literal to contain only literal faces + ;; (the font lock package might not have fontified the + ;; start of it at all, for instance) so check that we have + ;; arrived at something that looks like a start or else + ;; resort to `c-literal-limits'. + (unless (looking-at c-literal-start-regexp) + (let ((range (c-literal-limits))) + (if range (goto-char (car range))))) + + (setq start-in-literal (point))) + + ;; The start is in a literal. If the limit is in the same + ;; one we don't have to find a syntactic position etc. We + ;; only check that if the limit is at or before bonl to save + ;; time; it covers the by far most common case when font-lock + ;; refontifies the current line only. + (<= cfd-limit (c-point 'bonl cfd-start-pos)) + (save-excursion + (goto-char cfd-start-pos) + (while (progn + (goto-char (next-single-property-change + (point) 'face nil cfd-limit)) + (and (< (point) cfd-limit) + (c-got-face-at (point) c-literal-faces)))) + (= (point) cfd-limit))) + + ;; Completely inside a literal. Set up variables to trig the + ;; (< cfd-continue-pos cfd-start-pos) case below and it'll + ;; find a suitable start position. + (setq cfd-continue-pos start-in-literal)) + + ;; Check if the region might be completely inside a macro, to + ;; optimize that like the completely-inside-literal above. + ((save-excursion + (and (= (forward-line 1) 0) + (bolp) ; forward-line has funny behavior at eob. + (>= (point) cfd-limit) + (progn (backward-char) + (eq (char-before) ?\\)))) + ;; (Maybe) completely inside a macro. Only need to trig the + ;; (< cfd-continue-pos cfd-start-pos) case below to make it + ;; set things up. + (setq cfd-continue-pos (1- cfd-start-pos) + start-in-macro t)) + + (t + ;; Back out of any macro so we don't miss any declaration + ;; that could follow after it. + (when (c-beginning-of-macro) + (setq start-in-macro t)) + + ;; Now we're at a proper syntactically relevant position so we + ;; can use the cache. But first clear it if it applied + ;; further down. + (c-invalidate-find-decl-cache cfd-start-pos) + + (setq syntactic-pos (point)) + (unless (eq syntactic-pos c-find-decl-syntactic-pos) + ;; Don't have to do this if the cache is relevant here, + ;; typically if the same line is refontified again. If + ;; we're just some syntactic whitespace further down we can + ;; still use the cache to limit the skipping. + (c-backward-syntactic-ws c-find-decl-syntactic-pos)) + + ;; If we hit `c-find-decl-syntactic-pos' and + ;; `c-find-decl-match-pos' is set then we install the cached + ;; values. If we hit `c-find-decl-syntactic-pos' and + ;; `c-find-decl-match-pos' is nil then we know there's no decl + ;; prefix in the whitespace before `c-find-decl-syntactic-pos' + ;; and so we can continue the search from this point. If we + ;; didn't hit `c-find-decl-syntactic-pos' then we're now in + ;; the right spot to begin searching anyway. + (if (and (eq (point) c-find-decl-syntactic-pos) + c-find-decl-match-pos) + (setq cfd-match-pos c-find-decl-match-pos + cfd-continue-pos syntactic-pos) + + (setq c-find-decl-syntactic-pos syntactic-pos) + + (when (if (bobp) + ;; Always consider bob a match to get the first + ;; declaration in the file. Do this separately instead of + ;; letting `c-decl-prefix-or-start-re' match bob, so that + ;; regexp always can consume at least one character to + ;; ensure that we won't get stuck in an infinite loop. + (setq cfd-re-match 0) + (backward-char) + (c-beginning-of-current-token) + (< (point) cfd-limit)) + ;; Do an initial search now. In the bob case above it's + ;; only done to search for a `c-decl-end' spot. + (c-find-decl-prefix-search)) + + (setq c-find-decl-match-pos (and (< cfd-match-pos cfd-start-pos) + cfd-match-pos))))) + + ;; Advance `cfd-continue-pos' if it's before the start position. + ;; The closest continue position that might have effect at or + ;; after the start depends on what we started in. This also + ;; finds a suitable start position in the special cases when the + ;; region is completely within a literal or macro. + (when (and cfd-continue-pos (< cfd-continue-pos cfd-start-pos)) + + (cond + (start-in-macro + ;; If we're in a macro then it's the closest preceding token + ;; in the macro. Check this before `start-in-literal', + ;; since if we're inside a literal in a macro, the preceding + ;; token is earlier than any `c-decl-end' spot inside the + ;; literal (comment). + (goto-char (or start-in-literal cfd-start-pos)) + ;; The only syntactic ws in macros are comments. + (c-backward-comments) + (backward-char) + (c-beginning-of-current-token)) + + (start-in-literal + ;; If we're in a comment it can only be the closest + ;; preceding `c-decl-end' position within that comment, if + ;; any. Go back to the beginning of such a property so that + ;; `c-find-decl-prefix-search' will find the end of it. + ;; (Can't stop at the end and install it directly on + ;; `cfd-prop-match' since that variable might be cleared + ;; after `cfd-fun' below.) + ;; + ;; Note that if the literal is a string then the property + ;; search will simply skip to the beginning of it right + ;; away. + (if (not c-type-decl-end-used) + (goto-char start-in-literal) + (goto-char cfd-start-pos) + (while (progn + (goto-char (previous-single-property-change + (point) 'c-type nil start-in-literal)) + (and (> (point) start-in-literal) + (not (eq (c-get-char-property (point) 'c-type) + 'c-decl-end)))))) + + (when (= (point) start-in-literal) + ;; Didn't find any property inside the comment, so we can + ;; skip it entirely. (This won't skip past a string, but + ;; that'll be handled quickly by the next + ;; `c-find-decl-prefix-search' anyway.) + (c-forward-single-comment) + (if (> (point) cfd-limit) + (goto-char cfd-limit)))) + + (t + ;; If we started in normal code, the only match that might + ;; apply before the start is what we already got in + ;; `cfd-match-pos' so we can continue at the start position. + ;; (Note that we don't get here if the first match is below + ;; it.) + (goto-char cfd-start-pos))) + + ;; Delete found matches if they are before our new continue + ;; position, so that `c-find-decl-prefix-search' won't back up + ;; to them later on. + (setq cfd-continue-pos (point)) + (when (and cfd-re-match (< cfd-re-match cfd-continue-pos)) + (setq cfd-re-match nil)) + (when (and cfd-prop-match (< cfd-prop-match cfd-continue-pos)) + (setq cfd-prop-match nil))) + + (if syntactic-pos + ;; This is the normal case and we got a proper syntactic + ;; position. If there's a match then it's always outside + ;; macros and comments, so advance to the next token and set + ;; `cfd-token-pos'. The loop below will later go back using + ;; `cfd-continue-pos' to fix declarations inside the + ;; syntactic ws. + (when (and cfd-match-pos (< cfd-match-pos syntactic-pos)) (goto-char syntactic-pos) (c-forward-syntactic-ws) - (setq cfd-match-pos c-find-decl-match-pos - cfd-continue-pos syntactic-pos) - (if (< cfd-continue-pos (point)) - (setq cfd-token-pos (point)))) - - (setq c-find-decl-syntactic-pos syntactic-pos) - - (when (if (bobp) - ;; Always consider bob a match to get the first declaration - ;; in the file. Do this separately instead of letting - ;; `c-decl-prefix-re' match bob, so that it always can - ;; consume at least one character to ensure that we won't - ;; get stuck in an infinite loop. - (setq cfd-re-match 0) - (backward-char) - (c-beginning-of-current-token) - (< (point) cfd-limit)) - ;; Do an initial search now. In the bob case above it's only done - ;; to search for the `c-type' property. - (c-find-decl-prefix-search)) - - ;; Advance `cfd-continue-pos' if we got a hit before the start - ;; position. The earliest position that could affect after - ;; the start position is the char before the preceding - ;; comments. - (when (and cfd-continue-pos (< cfd-continue-pos start-pos)) - (goto-char syntactic-pos) - (c-backward-comments) - (unless (bobp) - (backward-char) - (c-beginning-of-current-token)) - (setq cfd-continue-pos (max cfd-continue-pos (point)))) - - ;; If we got a match it's always outside macros and comments so - ;; advance to the next token and set `cfd-token-pos'. The loop - ;; below will later go back using `cfd-continue-pos' to fix - ;; declarations inside the syntactic ws. - (when (and (< cfd-match-pos cfd-limit) (< (point) syntactic-pos)) - (goto-char syntactic-pos) - (c-forward-syntactic-ws) - (and cfd-continue-pos - (< cfd-continue-pos (point)) - (setq cfd-token-pos (point)))) - - (setq c-find-decl-match-pos (and (< cfd-match-pos start-pos) - cfd-match-pos)))) + (and cfd-continue-pos + (< cfd-continue-pos (point)) + (setq cfd-token-pos (point)))) + + ;; Have one of the special cases when the region is completely + ;; within a literal or macro. `cfd-continue-pos' is set to a + ;; good start position for the search, so do it. + (c-find-decl-prefix-search))) ;; Now loop. We already got the first match. @@ -3323,33 +3878,37 @@ (< (point) cfd-limit)) - (when (progn - ;; Narrow to the end of the macro if we got a hit inside - ;; one, to avoid recognizing things that start inside - ;; the macro and end outside it. - (when (> cfd-match-pos cfd-macro-end) - ;; Not in the same macro as in the previous round. - (save-excursion - (goto-char cfd-match-pos) - (setq cfd-macro-end - (if (save-excursion (and (c-beginning-of-macro) - (< (point) cfd-match-pos))) - (progn (c-end-of-macro) - (point)) - 0)))) - - (if (zerop cfd-macro-end) - t - (if (> cfd-macro-end (point)) - (progn (narrow-to-region (point-min) cfd-macro-end) - t) - ;; The matched token was the last thing in the - ;; macro, so the whole match is bogus. - (setq cfd-macro-end 0) - nil))) + (when (and + (>= (point) cfd-start-pos) + + (progn + ;; Narrow to the end of the macro if we got a hit inside + ;; one, to avoid recognizing things that start inside the + ;; macro and end outside it. + (when (> cfd-match-pos cfd-macro-end) + ;; Not in the same macro as in the previous round. + (save-excursion + (goto-char cfd-match-pos) + (setq cfd-macro-end + (if (save-excursion (and (c-beginning-of-macro) + (< (point) cfd-match-pos))) + (progn (c-end-of-macro) + (point)) + 0)))) + + (if (zerop cfd-macro-end) + t + (if (> cfd-macro-end (point)) + (progn (narrow-to-region (point-min) cfd-macro-end) + t) + ;; The matched token was the last thing in the macro, + ;; so the whole match is bogus. + (setq cfd-macro-end 0) + nil)))) (c-debug-put-decl-spot-faces cfd-match-pos (point)) - (funcall cfd-fun cfd-match-pos (/= cfd-macro-end 0)) + (if (funcall cfd-fun cfd-match-pos (/= cfd-macro-end 0)) + (setq cfd-prop-match nil)) (when (/= cfd-macro-end 0) ;; Restore limits if we did macro narrowment above. @@ -3370,14 +3929,23 @@ ;; bother with the scoping rules of the languages, but in practice the ;; same name is seldom used as both a type and something else in a ;; file, and we only use this as a last resort in ambiguous cases (see -;; `c-font-lock-declarations'). +;; `c-forward-decl-or-cast-1'). +;; +;; Template types in C++ are added here too but with the template +;; arglist replaced with "<>" in references or "<" for the one in the +;; primary type. E.g. the type "Foo<A,B>::Bar<C>" is stored as +;; "Foo<>::Bar<". This avoids storing very long strings (since C++ +;; template specs can be fairly sized programs in themselves) and +;; improves the hit ratio (it's a type regardless of the template +;; args; it's just not the same type, but we're only interested in +;; recognizing types, not telling distinct types apart). Note that +;; template types in references are added here too; from the example +;; above there will also be an entry "Foo<". (defvar c-found-types nil) (make-variable-buffer-local 'c-found-types) (defsubst c-clear-found-types () ;; Clears `c-found-types'. - ;; - ;; This function does not do any hidden buffer changes. (setq c-found-types (make-vector 53 0))) (defun c-add-type (from to) @@ -3389,23 +3957,20 @@ ;; doesn't cover cases like when characters are removed from a type ;; or added in the middle. We'd need the position of point when the ;; font locking is invoked to solve this well. - (unless (and c-recognize-<>-arglists - (save-excursion - (goto-char from) - (c-syntactic-re-search-forward "<" to t))) - ;; To avoid storing very long strings, do not add a type that - ;; contains '<' in languages with angle bracket arglists, since - ;; the type then probably contains a C++ template spec and those - ;; can be fairly sized programs in themselves. - (let ((type (c-syntactic-content from to))) - (unless (intern-soft type c-found-types) - (unintern (substring type 0 -1) c-found-types) - (intern type c-found-types))))) + ;; + ;; This function might do hidden buffer changes. + (let ((type (c-syntactic-content from to c-recognize-<>-arglists))) + (unless (intern-soft type c-found-types) + (unintern (substring type 0 -1) c-found-types) + (intern type c-found-types)))) (defsubst c-check-type (from to) ;; Return non-nil if the given region contains a type in ;; `c-found-types'. - (intern-soft (c-syntactic-content from to) c-found-types)) + ;; + ;; This function might do hidden buffer changes. + (intern-soft (c-syntactic-content from to c-recognize-<>-arglists) + c-found-types)) (defun c-list-found-types () ;; Return all the types in `c-found-types' as a sorted list of @@ -3420,17 +3985,43 @@ ;; Handling of small scale constructs like types and names. -(defun c-remove-<>-arglist-properties (from to) - ;; Remove all the properties put by `c-forward-<>-arglist' in the - ;; specified region. Point is clobbered. - (goto-char from) - (while (progn (skip-chars-forward "^<>," to) - (< (point) to)) - (if (eq (char-after) ?,) - (when (eq (c-get-char-property (point) 'c-type) 'c-<>-arg-sep) - (c-clear-char-property (point) 'c-type)) - (c-clear-char-property (point) 'syntax-table)) - (forward-char))) +(defun c-after-change-check-<>-operators (beg end) + ;; This is called from `after-change-functions' when + ;; c-recognize-<>-arglists' is set. It ensures that no "<" or ">" + ;; chars with paren syntax become part of another operator like "<<" + ;; or ">=". + ;; + ;; This function might do hidden buffer changes. + + (save-excursion + (goto-char beg) + (when (or (looking-at "[<>]") + (< (skip-chars-backward "<>") 0)) + + (goto-char beg) + (c-beginning-of-current-token) + (when (and (< (point) beg) + (looking-at c-<>-multichar-token-regexp) + (< beg (setq beg (match-end 0)))) + (while (progn (skip-chars-forward "^<>" beg) + (< (point) beg)) + (c-clear-char-property (point) 'syntax-table) + (forward-char)))) + + (when (< beg end) + (goto-char end) + (when (or (looking-at "[<>]") + (< (skip-chars-backward "<>") 0)) + + (goto-char end) + (c-beginning-of-current-token) + (when (and (< (point) end) + (looking-at c-<>-multichar-token-regexp) + (< end (setq end (match-end 0)))) + (while (progn (skip-chars-forward "^<>" end) + (< (point) end)) + (c-clear-char-property (point) 'syntax-table) + (forward-char))))))) ;; Dynamically bound variable that instructs `c-forward-type' to also ;; treat possible types (i.e. those that it normally returns 'maybe or @@ -3440,6 +4031,20 @@ (defvar c-promote-possible-types nil) ;; Dynamically bound variable that instructs `c-forward-<>-arglist' to +;; mark up successfully parsed arglists with paren syntax properties on +;; the surrounding angle brackets and with `c-<>-arg-sep' in the +;; `c-type' property of each argument separating comma. +;; +;; Setting this variable also makes `c-forward-<>-arglist' recurse into +;; all arglists for side effects (i.e. recording types), otherwise it +;; exploits any existing paren syntax properties to quickly jump to the +;; end of already parsed arglists. +;; +;; Marking up the arglists is not the default since doing that correctly +;; depends on a proper value for `c-restricted-<>-arglists'. +(defvar c-parse-and-markup-<>-arglists nil) + +;; Dynamically bound variable that instructs `c-forward-<>-arglist' to ;; not accept arglists that contain binary operators. ;; ;; This is primarily used to handle C++ template arglists. C++ @@ -3455,31 +4060,36 @@ ;; "if (a < b || c > d)", it's probably not a template. (defvar c-restricted-<>-arglists nil) -;; Dynamically bound variables that instructs `c-forward-name', -;; `c-forward-type' and `c-forward-<>-arglist' to record the ranges of -;; all the type and reference identifiers they encounter. They will -;; build lists on these variables where each element is a cons of the -;; buffer positions surrounding each identifier. This recording is -;; only activated when `c-record-type-identifiers' is non-nil. +;; Dynamically bound variables that instructs +;; `c-forward-keyword-clause', `c-forward-<>-arglist', +;; `c-forward-name', `c-forward-type', `c-forward-decl-or-cast-1', and +;; `c-forward-label' to record the ranges of all the type and +;; reference identifiers they encounter. They will build lists on +;; these variables where each element is a cons of the buffer +;; positions surrounding each identifier. This recording is only +;; activated when `c-record-type-identifiers' is non-nil. ;; ;; All known types that can't be identifiers are recorded, and also ;; other possible types if `c-promote-possible-types' is set. ;; Recording is however disabled inside angle bracket arglists that ;; are encountered inside names and other angle bracket arglists. -;; Such occurences are taken care of by `c-font-lock-<>-arglists' +;; Such occurrences are taken care of by `c-font-lock-<>-arglists' ;; instead. ;; ;; Only the names in C++ template style references (e.g. "tmpl" in ;; "tmpl<a,b>::foo") are recorded as references, other references ;; aren't handled here. +;; +;; `c-forward-label' records the label identifier(s) on +;; `c-record-ref-identifiers'. (defvar c-record-type-identifiers nil) (defvar c-record-ref-identifiers nil) -;; If `c-record-type-identifiers' is set, this will receive a cons -;; cell of the range of the last single identifier symbol stepped over -;; by `c-forward-name' if it's successful. This is the range that -;; should be put on one of the record lists by the caller. It's -;; assigned nil if there's no such symbol in the name. +;; This variable will receive a cons cell of the range of the last +;; single identifier symbol stepped over by `c-forward-name' if it's +;; successful. This is the range that should be put on one of the +;; record lists above by the caller. It's assigned nil if there's no +;; such symbol in the name. (defvar c-last-identifier-range nil) (defmacro c-record-type-id (range) @@ -3516,45 +4126,70 @@ ;; over. The point is clobbered if nil is returned. If range ;; recording is enabled, the identifier is recorded on as a type ;; if TYPE is 'type or as a reference if TYPE is 'ref. + ;; + ;; This macro might do hidden buffer changes. `(let (res) (while (if (setq res ,(if (eq type 'type) `(c-forward-type) `(c-forward-name))) nil (and (looking-at c-keywords-regexp) - (c-forward-keyword-clause)))) + (c-forward-keyword-clause 1)))) (when (memq res '(t known found prefix)) ,(when (eq type 'ref) `(when c-record-type-identifiers (c-record-ref-id c-last-identifier-range))) t))) -(defmacro c-forward-id-comma-list (type) +(defmacro c-forward-id-comma-list (type update-safe-pos) ;; Used internally in `c-forward-keyword-clause' to move forward ;; over a comma separated list of types or names using ;; `c-forward-keyword-prefixed-id'. + ;; + ;; This macro might do hidden buffer changes. `(while (and (progn - (setq safe-pos (point)) + ,(when update-safe-pos + `(setq safe-pos (point))) (eq (char-after) ?,)) (progn (forward-char) (c-forward-syntactic-ws) (c-forward-keyword-prefixed-id ,type))))) -(defun c-forward-keyword-clause () - ;; The first submatch in the current match data is assumed to - ;; surround a token. If it's a keyword, move over it and any - ;; following clauses associated with it, stopping at the next - ;; following token. t is returned in that case, otherwise the point +(defun c-forward-keyword-clause (match) + ;; Submatch MATCH in the current match data is assumed to surround a + ;; token. If it's a keyword, move over it and any immediately + ;; following clauses associated with it, stopping at the start of + ;; the next token. t is returned in that case, otherwise the point ;; stays and nil is returned. The kind of clauses that are ;; recognized are those specified by `c-type-list-kwds', ;; `c-ref-list-kwds', `c-colon-type-list-kwds', ;; `c-paren-nontype-kwds', `c-paren-type-kwds', `c-<>-type-kwds', ;; and `c-<>-arglist-kwds'. - - (let ((kwd-sym (c-keyword-sym (match-string 1))) safe-pos pos) + ;; + ;; This function records identifier ranges on + ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if + ;; `c-record-type-identifiers' is non-nil. + ;; + ;; Note that for `c-colon-type-list-kwds', which doesn't necessary + ;; apply directly after the keyword, the type list is moved over + ;; only when there is no unaccounted token before it (i.e. a token + ;; that isn't moved over due to some other keyword list). The + ;; identifier ranges in the list are still recorded if that should + ;; be done, though. + ;; + ;; This function might do hidden buffer changes. + + (let ((kwd-sym (c-keyword-sym (match-string match))) safe-pos pos + ;; The call to `c-forward-<>-arglist' below is made after + ;; `c-<>-sexp-kwds' keywords, so we're certain they actually + ;; are angle bracket arglists and `c-restricted-<>-arglists' + ;; should therefore be nil. + (c-parse-and-markup-<>-arglists t) + c-restricted-<>-arglists) + (when kwd-sym - (goto-char (match-end 1)) + (goto-char (match-end match)) (c-forward-syntactic-ws) (setq safe-pos (point)) @@ -3562,12 +4197,12 @@ ((and (c-keyword-member kwd-sym 'c-type-list-kwds) (c-forward-keyword-prefixed-id type)) ;; There's a type directly after a keyword in `c-type-list-kwds'. - (c-forward-id-comma-list type)) + (c-forward-id-comma-list type t)) ((and (c-keyword-member kwd-sym 'c-ref-list-kwds) (c-forward-keyword-prefixed-id ref)) ;; There's a name directly after a keyword in `c-ref-list-kwds'. - (c-forward-id-comma-list ref)) + (c-forward-id-comma-list ref t)) ((and (c-keyword-member kwd-sym 'c-paren-any-kwds) (eq (char-after) ?\()) @@ -3592,9 +4227,7 @@ ((and (c-keyword-member kwd-sym 'c-<>-sexp-kwds) (eq (char-after) ?<) - (c-forward-<>-arglist (c-keyword-member kwd-sym 'c-<>-type-kwds) - (or c-record-type-identifiers - c-restricted-<>-arglists))) + (c-forward-<>-arglist (c-keyword-member kwd-sym 'c-<>-type-kwds))) (c-forward-syntactic-ws) (setq safe-pos (point))) @@ -3604,46 +4237,56 @@ (c-forward-syntactic-ws) (setq safe-pos (point)))) - (when (and (c-keyword-member kwd-sym 'c-colon-type-list-kwds) - (progn - ;; If a keyword matched both one of the types above and - ;; this one, we match `c-colon-type-list-re' after the - ;; clause matched above. - (goto-char safe-pos) - (looking-at c-colon-type-list-re)) - (progn - (goto-char (match-end 0)) - (c-forward-syntactic-ws) - (c-forward-keyword-prefixed-id type))) - ;; There's a type after the `c-colon-type-list-re' - ;; match after a keyword in `c-colon-type-list-kwds'. - (c-forward-id-comma-list type)) + (when (c-keyword-member kwd-sym 'c-colon-type-list-kwds) + (if (eq (char-after) ?:) + ;; If we are at the colon already, we move over the type + ;; list after it. + (progn + (forward-char) + (c-forward-syntactic-ws) + (when (c-forward-keyword-prefixed-id type) + (c-forward-id-comma-list type t))) + ;; Not at the colon, so stop here. But the identifier + ;; ranges in the type list later on should still be + ;; recorded. + (and c-record-type-identifiers + (progn + ;; If a keyword matched both one of the types above and + ;; this one, we match `c-colon-type-list-re' after the + ;; clause matched above. + (goto-char safe-pos) + (looking-at c-colon-type-list-re)) + (progn + (goto-char (match-end 0)) + (c-forward-syntactic-ws) + (c-forward-keyword-prefixed-id type)) + ;; There's a type after the `c-colon-type-list-re' match + ;; after a keyword in `c-colon-type-list-kwds'. + (c-forward-id-comma-list type nil)))) (goto-char safe-pos) t))) -(defun c-forward-<>-arglist (all-types reparse) - ;; The point is assumed to be at a '<'. Try to treat it as the open +(defun c-forward-<>-arglist (all-types) + ;; The point is assumed to be at a "<". Try to treat it as the open ;; paren of an angle bracket arglist and move forward to the the - ;; corresponding '>'. If successful, the point is left after the - ;; '>' and t is returned, otherwise the point isn't moved and nil is + ;; corresponding ">". If successful, the point is left after the + ;; ">" and t is returned, otherwise the point isn't moved and nil is ;; returned. If ALL-TYPES is t then all encountered arguments in ;; the arglist that might be types are treated as found types. ;; - ;; The surrounding '<' and '>' are given syntax-table properties to - ;; make them behave like parentheses. Each argument separating ',' - ;; is also set to `c-<>-arg-sep' in the `c-type' property. These - ;; properties are also cleared in a relevant region forward from the - ;; point if they seems to be set and it turns out to not be an - ;; arglist. - ;; - ;; If the arglist has been successfully parsed before then paren - ;; syntax properties will be exploited to quickly jump to the end, - ;; but that can be disabled by setting REPARSE to t. That is - ;; necessary if the various side effects, e.g. recording of type - ;; ranges, are important. Setting REPARSE to t only applies - ;; recursively to nested angle bracket arglists if - ;; `c-restricted-<>-arglists' is set. + ;; The variable `c-parse-and-markup-<>-arglists' controls how this + ;; function handles text properties on the angle brackets and argument + ;; separating commas. + ;; + ;; `c-restricted-<>-arglists' controls how lenient the template + ;; arglist recognition should be. + ;; + ;; This function records identifier ranges on + ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if + ;; `c-record-type-identifiers' is non-nil. + ;; + ;; This function might do hidden buffer changes. (let ((start (point)) ;; If `c-record-type-identifiers' is set then activate @@ -3652,7 +4295,7 @@ (c-record-found-types (if c-record-type-identifiers t))) (if (catch 'angle-bracket-arglist-escape (setq c-record-found-types - (c-forward-<>-arglist-recur all-types reparse))) + (c-forward-<>-arglist-recur all-types))) (progn (when (consp c-record-found-types) (setq c-record-type-identifiers @@ -3664,8 +4307,10 @@ (goto-char start) nil))) -(defun c-forward-<>-arglist-recur (all-types reparse) +(defun c-forward-<>-arglist-recur (all-types) ;; Recursive part of `c-forward-<>-arglist'. + ;; + ;; This function might do hidden buffer changes. (let ((start (point)) res pos tmp ;; Cover this so that any recorded found type ranges are @@ -3677,61 +4322,24 @@ ;; separating ',' in the arglist. arg-start-pos) - ;; If the '<' has paren open syntax then we've marked it as an - ;; angle bracket arglist before, so try to skip to the end and see - ;; that the close paren matches. - (if (and (c-get-char-property (point) 'syntax-table) - (progn - (forward-char) - (if (and (not (looking-at c-<-op-cont-regexp)) - (if (c-parse-sexp-lookup-properties) - (c-go-up-list-forward) - (catch 'at-end - (let ((depth 1)) - (while (c-syntactic-re-search-forward - "[<>]" nil t t) - (when (c-get-char-property (1- (point)) - 'syntax-table) - (if (eq (char-before) ?<) - (setq depth (1+ depth)) - (setq depth (1- depth)) - (when (= depth 0) (throw 'at-end t))))) - nil))) - (not (looking-at c->-op-cont-regexp)) - (save-excursion - (backward-char) - (= (point) - (progn (c-beginning-of-current-token) - (point))))) - - ;; Got an arglist that appears to be valid. - (if reparse - ;; Reparsing is requested, so zap the properties in the - ;; region and go on to redo it. It's done here to - ;; avoid leaving it behind if we exit through - ;; `angle-bracket-arglist-escape' below. - (progn - (c-remove-<>-arglist-properties start (point)) - (goto-char start) - nil) - t) - - ;; Got unmatched paren brackets or either paren was - ;; actually some other token. Recover by clearing the - ;; syntax properties on all the '<' and '>' in the - ;; range where we'll search for the arglist below. - (goto-char start) - (while (progn (skip-chars-forward "^<>,;{}") - (looking-at "[<>,]")) - (if (eq (char-after) ?,) - (when (eq (c-get-char-property (point) 'c-type) - 'c-<>-arg-sep) - (c-clear-char-property (point) 'c-type)) - (c-clear-char-property (point) 'syntax-table)) - (forward-char)) - (goto-char start) - nil))) - t + ;; If the '<' has paren open syntax then we've marked it as an angle + ;; bracket arglist before, so skip to the end. + (if (and (not c-parse-and-markup-<>-arglists) + (c-get-char-property (point) 'syntax-table)) + + (progn + (forward-char) + (if (and (c-go-up-list-forward) + (eq (char-before) ?>)) + t + + ;; Got unmatched paren angle brackets. We don't clear the paren + ;; syntax properties and retry, on the basis that it's very + ;; unlikely that paren angle brackets become operators by code + ;; manipulation. It's far more likely that it doesn't match due + ;; to narrowing or some temporary change. + (goto-char start) + nil)) (forward-char) (unless (looking-at c-<-op-cont-regexp) @@ -3793,11 +4401,6 @@ ;; balanced sexp. In that case we stop just short ;; of it so check if the following char is the closer. (when (eq (char-after) ?>) - ;; Remove its syntax so that we don't enter the - ;; recovery code below. That's not necessary - ;; since there's no real reason to suspect that - ;; things inside the arglist are unbalanced. - (c-clear-char-property (point) 'syntax-table) (forward-char) t))) @@ -3806,40 +4409,21 @@ ;; Either an operator starting with '>' or the end of ;; the angle bracket arglist. - (if (and (/= (1- (point)) pos) - (c-get-char-property (1- (point)) 'syntax-table) - (progn - (c-clear-char-property (1- (point)) 'syntax-table) - (c-parse-sexp-lookup-properties))) - - ;; We've skipped past a list that ended with '>'. It - ;; must be unbalanced since nested arglists are handled - ;; in the case below. Recover by removing all paren - ;; properties on '<' and '>' in the searched region and - ;; redo the search. + (if (looking-at c->-op-cont-regexp) (progn - (c-remove-<>-arglist-properties pos (point)) - (goto-char pos) - t) - - (if (looking-at c->-op-cont-regexp) - (progn - (when (text-property-not-all - (1- (point)) (match-end 0) 'syntax-table nil) - (c-remove-<>-arglist-properties (1- (point)) - (match-end 0))) - (goto-char (match-end 0)) - t) - - ;; The angle bracket arglist is finished. + (goto-char (match-end 0)) + t) ; Continue the loop. + + ;; The angle bracket arglist is finished. + (when c-parse-and-markup-<>-arglists (while arg-start-pos - (c-put-char-property (1- (car arg-start-pos)) - 'c-type 'c-<>-arg-sep) + (c-put-c-type-property (1- (car arg-start-pos)) + 'c-<>-arg-sep) (setq arg-start-pos (cdr arg-start-pos))) (c-mark-<-as-paren start) - (c-mark->-as-paren (1- (point))) - (setq res t) - nil))) + (c-mark->-as-paren (1- (point)))) + (setq res t) + nil)) ; Exit the loop. ((eq (char-before) ?<) ;; Either an operator starting with '<' or a nested arglist. @@ -3854,7 +4438,7 @@ (and (save-excursion - ;; There's always an identifier before a angle + ;; There's always an identifier before an angle ;; bracket arglist, or a keyword in ;; `c-<>-type-kwds' or `c-<>-arglist-kwds'. (c-backward-syntactic-ws) @@ -3872,26 +4456,11 @@ (and keyword-match (c-keyword-member (c-keyword-sym (match-string 1)) - 'c-<>-type-kwds)) - (and reparse - c-restricted-<>-arglists)))) + 'c-<>-type-kwds))))) ))) ;; It was not an angle bracket arglist. - (progn - (when (text-property-not-all - (1- pos) tmp 'syntax-table nil) - (if (c-parse-sexp-lookup-properties) - ;; Got an invalid open paren syntax on this - ;; '<'. We'll probably get an unbalanced '>' - ;; further ahead if we just remove the syntax - ;; here, so recover by removing all paren - ;; properties up to and including the - ;; balancing close paren. - (parse-partial-sexp pos (point-max) -1) - (goto-char tmp)) - (c-remove-<>-arglist-properties pos (point))) - (goto-char tmp)) + (goto-char tmp) ;; It was an angle bracket arglist. (setq c-record-found-types subres) @@ -3926,6 +4495,70 @@ (if res (or c-record-found-types t))))) +(defun c-backward-<>-arglist (all-types &optional limit) + ;; The point is assumed to be directly after a ">". Try to treat it + ;; as the close paren of an angle bracket arglist and move back to + ;; the corresponding "<". If successful, the point is left at + ;; the "<" and t is returned, otherwise the point isn't moved and + ;; nil is returned. ALL-TYPES is passed on to + ;; `c-forward-<>-arglist'. + ;; + ;; If the optional LIMIT is given, it bounds the backward search. + ;; It's then assumed to be at a syntactically relevant position. + ;; + ;; This is a wrapper around `c-forward-<>-arglist'. See that + ;; function for more details. + + (let ((start (point))) + (backward-char) + (if (and (not c-parse-and-markup-<>-arglists) + (c-get-char-property (point) 'syntax-table)) + + (if (and (c-go-up-list-backward) + (eq (char-after) ?<)) + t + ;; See corresponding note in `c-forward-<>-arglist'. + (goto-char start) + nil) + + (while (and + (c-syntactic-skip-backward "^<;{}" limit t) + + (if (eq (char-before) ?<) + t + ;; Stopped at bob or a char that isn't allowed in an + ;; arglist, so we've failed. + (goto-char start) + nil) + + (if (> (point) + (progn (c-beginning-of-current-token) + (point))) + ;; If we moved then the "<" was part of some + ;; multicharacter token. + t + + (backward-char) + (let ((beg-pos (point))) + (if (c-forward-<>-arglist all-types) + (cond ((= (point) start) + ;; Matched the arglist. Break the while. + (goto-char beg-pos) + nil) + ((> (point) start) + ;; We started from a non-paren ">" inside an + ;; arglist. + (goto-char start) + nil) + (t + ;; Matched a shorter arglist. Can be a nested + ;; one so continue looking. + (goto-char beg-pos) + t)) + t))))) + + (/= (point) start)))) + (defun c-forward-name () ;; Move forward over a complete name if at the beginning of one, ;; stopping at the next following token. If the point is not at @@ -3939,8 +4572,14 @@ ;; name is found, 'template if it's an identifier ending with an ;; angle bracket arglist, 'operator of it's an operator identifier, ;; or t if it's some other kind of name. - - (let ((pos (point)) res id-start id-end + ;; + ;; This function records identifier ranges on + ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if + ;; `c-record-type-identifiers' is non-nil. + ;; + ;; This function might do hidden buffer changes. + + (let ((pos (point)) (start (point)) res id-start id-end ;; Turn off `c-promote-possible-types' here since we might ;; call `c-forward-<>-arglist' and we don't want it to promote ;; every suspect thing in the arglist to a type. We're @@ -3955,12 +4594,9 @@ (progn ;; Check for keyword. We go to the last symbol in ;; `c-identifier-key' first. - (if (eq c-identifier-key c-symbol-key) - (setq id-start (point) - id-end (match-end 0)) - (goto-char (setq id-end (match-end 0))) - (c-simple-skip-symbol-backward) - (setq id-start (point))) + (goto-char (setq id-end (match-end 0))) + (c-simple-skip-symbol-backward) + (setq id-start (point)) (if (looking-at c-keywords-regexp) (when (and (c-major-mode-is 'c++-mode) @@ -4018,9 +4654,8 @@ ((looking-at c-overloadable-operators-regexp) ;; Got some other operator. - (when c-record-type-identifiers - (setq c-last-identifier-range - (cons (point) (match-end 0)))) + (setq c-last-identifier-range + (cons (point) (match-end 0))) (goto-char (match-end 0)) (c-forward-syntactic-ws) (setq pos (point) @@ -4028,7 +4663,11 @@ nil) - (when c-record-type-identifiers + ;; `id-start' is equal to `id-end' if we've jumped over + ;; an identifier that doesn't end with a symbol token. + ;; That can occur e.g. for Java import directives on the + ;; form "foo.bar.*". + (when (and id-start (/= id-start id-end)) (setq c-last-identifier-range (cons id-start id-end))) (goto-char id-end) @@ -4054,29 +4693,30 @@ ((and c-recognize-<>-arglists (eq (char-after) ?<)) ;; Maybe an angle bracket arglist. - (when (let ((c-record-type-identifiers nil) - (c-record-found-types nil)) - (c-forward-<>-arglist - nil c-restricted-<>-arglists)) + + (when (let (c-record-type-identifiers + c-record-found-types) + (c-forward-<>-arglist nil)) + + (c-add-type start (1+ pos)) (c-forward-syntactic-ws) - (setq pos (point)) + (setq pos (point) + c-last-identifier-range nil) + (if (and c-opt-identifier-concat-key (looking-at c-opt-identifier-concat-key)) + ;; Continue if there's an identifier concatenation ;; operator after the template argument. (progn - (when c-record-type-identifiers - (c-record-ref-id (cons id-start id-end)) - (setq c-last-identifier-range nil)) + (when (and c-record-type-identifiers id-start) + (c-record-ref-id (cons id-start id-end))) (forward-char 2) (c-forward-syntactic-ws) t) - ;; `c-add-type' isn't called here since we don't - ;; want to add types containing angle bracket - ;; arglists. - (when c-record-type-identifiers - (c-record-type-id (cons id-start id-end)) - (setq c-last-identifier-range nil)) + + (when (and c-record-type-identifiers id-start) + (c-record-type-id (cons id-start id-end))) (setq res 'template) nil))) ))))) @@ -4098,7 +4738,14 @@ ;; Note that this function doesn't skip past the brace definition ;; that might be considered part of the type, e.g. ;; "enum {a, b, c} foo". - (let ((start (point)) pos res res2 id-start id-end id-range) + ;; + ;; This function records identifier ranges on + ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if + ;; `c-record-type-identifiers' is non-nil. + ;; + ;; This function might do hidden buffer changes. + + (let ((start (point)) pos res name-res id-start id-end id-range) ;; Skip leading type modifiers. If any are found we know it's a ;; prefix of a type. @@ -4115,13 +4762,14 @@ (goto-char (match-end 1)) (c-forward-syntactic-ws) (setq pos (point)) - (if (memq (setq res2 (c-forward-name)) '(t template)) + (if (memq (setq name-res (c-forward-name)) '(t template)) (progn - (when (eq res2 t) + (when (eq name-res t) ;; In many languages the name can be used without the ;; prefix, so we add it to `c-found-types'. (c-add-type pos (point)) - (when c-record-type-identifiers + (when (and c-record-type-identifiers + c-last-identifier-range) (c-record-type-id c-last-identifier-range))) (setq res t)) ;; Invalid syntax. @@ -4133,8 +4781,8 @@ (if (looking-at c-identifier-start) (save-excursion (setq id-start (point) - res2 (c-forward-name)) - (when res2 + name-res (c-forward-name)) + (when name-res (setq id-end (point) id-range c-last-identifier-range)))) (and (cond ((looking-at c-primitive-type-key) @@ -4165,7 +4813,7 @@ (looking-at c-opt-type-component-key))) ;; There might be more keywords for the type. (let (safe-pos) - (c-forward-keyword-clause) + (c-forward-keyword-clause 1) (while (progn (setq safe-pos (point)) (looking-at c-opt-type-component-key)) @@ -4173,30 +4821,30 @@ (looking-at c-primitive-type-key)) (c-record-type-id (cons (match-beginning 1) (match-end 1)))) - (c-forward-keyword-clause)) + (c-forward-keyword-clause 1)) (if (looking-at c-primitive-type-key) (progn (when c-record-type-identifiers (c-record-type-id (cons (match-beginning 1) (match-end 1)))) - (c-forward-keyword-clause) + (c-forward-keyword-clause 1) (setq res t)) (goto-char safe-pos) (setq res 'prefix))) - (unless (save-match-data (c-forward-keyword-clause)) + (unless (save-match-data (c-forward-keyword-clause 1)) (if pos (goto-char pos) (goto-char (match-end 1)) (c-forward-syntactic-ws))))) - (res2 - (cond ((eq res2 t) + (name-res + (cond ((eq name-res t) ;; A normal identifier. (goto-char id-end) (if (or res c-promote-possible-types) (progn (c-add-type id-start id-end) - (when c-record-type-identifiers + (when (and c-record-type-identifiers id-range) (c-record-type-id id-range)) (unless res (setq res 'found))) @@ -4206,7 +4854,7 @@ 'found ;; It's an identifier that might be a type. 'maybe)))) - ((eq res2 'template) + ((eq name-res 'template) ;; A template is a type. (goto-char id-end) (setq res t)) @@ -4234,9 +4882,11 @@ (c-forward-syntactic-ws))) (when c-opt-type-concat-key - ;; Look for a trailing operator that concatenate the type with - ;; a following one, and if so step past that one through a - ;; recursive call. + ;; Look for a trailing operator that concatenates the type + ;; with a following one, and if so step past that one through + ;; a recursive call. Note that we don't record concatenated + ;; types in `c-found-types' - it's the component types that + ;; are recorded when appropriate. (setq pos (point)) (let* ((c-promote-possible-types (or (memq res '(t known)) c-promote-possible-types)) @@ -4244,29 +4894,31 @@ ;; we can merge in the types from the second part afterwards if ;; it turns out to be a known type there. (c-record-found-types (and c-record-type-identifiers - (not c-promote-possible-types)))) + (not c-promote-possible-types))) + subres) (if (and (looking-at c-opt-type-concat-key) (progn (goto-char (match-end 1)) (c-forward-syntactic-ws) - (setq res2 (c-forward-type)))) + (setq subres (c-forward-type)))) (progn ;; If either operand certainly is a type then both are, but we ;; don't let the existence of the operator itself promote two ;; uncertain types to a certain one. (cond ((eq res t)) - ((eq res2 t) - (c-add-type id-start id-end) - (when c-record-type-identifiers + ((eq subres t) + (unless (eq name-res 'template) + (c-add-type id-start id-end)) + (when (and c-record-type-identifiers id-range) (c-record-type-id id-range)) (setq res t)) ((eq res 'known)) - ((eq res2 'known) + ((eq subres 'known) (setq res 'known)) ((eq res 'found)) - ((eq res2 'found) + ((eq subres 'found) (setq res 'found)) (t (setq res 'maybe))) @@ -4294,23 +4946,1099 @@ ;; Handling of large scale constructs like statements and declarations. +;; Macro used inside `c-forward-decl-or-cast-1'. It ought to be a +;; defsubst or perhaps even a defun, but it contains lots of free +;; variables that refer to things inside `c-forward-decl-or-cast-1'. +(defmacro c-fdoc-shift-type-backward (&optional short) + ;; `c-forward-decl-or-cast-1' can consume an arbitrary length list + ;; of types when parsing a declaration, which means that it + ;; sometimes consumes the identifier in the declaration as a type. + ;; This is used to "backtrack" and make the last type be treated as + ;; an identifier instead. + `(progn + ,(unless short + ;; These identifiers are bound only in the inner let. + '(setq identifier-type at-type + identifier-start type-start + got-parens nil + got-identifier t + got-suffix t + got-suffix-after-parens id-start + paren-depth 0)) + + (if (setq at-type (if (eq backup-at-type 'prefix) + t + backup-at-type)) + (setq type-start backup-type-start + id-start backup-id-start) + (setq type-start start-pos + id-start start-pos)) + + ;; When these flags already are set we've found specifiers that + ;; unconditionally signal these attributes - backtracking doesn't + ;; change that. So keep them set in that case. + (or at-type-decl + (setq at-type-decl backup-at-type-decl)) + (or maybe-typeless + (setq maybe-typeless backup-maybe-typeless)) + + ,(unless short + ;; This identifier is bound only in the inner let. + '(setq start id-start)))) + +(defun c-forward-decl-or-cast-1 (preceding-token-end context last-cast-end) + ;; Move forward over a declaration or a cast if at the start of one. + ;; The point is assumed to be at the start of some token. Nil is + ;; returned if no declaration or cast is recognized, and the point + ;; is clobbered in that case. + ;; + ;; If a declaration is parsed: + ;; + ;; The point is left at the first token after the first complete + ;; declarator, if there is one. The return value is a cons where + ;; the car is the position of the first token in the declarator. + ;; Some examples: + ;; + ;; void foo (int a, char *b) stuff ... + ;; car ^ ^ point + ;; float (*a)[], b; + ;; car ^ ^ point + ;; unsigned int a = c_style_initializer, b; + ;; car ^ ^ point + ;; unsigned int a (cplusplus_style_initializer), b; + ;; car ^ ^ point (might change) + ;; class Foo : public Bar {} + ;; car ^ ^ point + ;; class PikeClass (int a, string b) stuff ... + ;; car ^ ^ point + ;; enum bool; + ;; car ^ ^ point + ;; enum bool flag; + ;; car ^ ^ point + ;; void cplusplus_function (int x) throw (Bad); + ;; car ^ ^ point + ;; Foo::Foo (int b) : Base (b) {} + ;; car ^ ^ point + ;; + ;; The cdr of the return value is non-nil iff a + ;; `c-typedef-decl-kwds' specifier is found in the declaration, + ;; i.e. the declared identifier(s) are types. + ;; + ;; If a cast is parsed: + ;; + ;; The point is left at the first token after the closing paren of + ;; the cast. The return value is `cast'. Note that the start + ;; position must be at the first token inside the cast parenthesis + ;; to recognize it. + ;; + ;; PRECEDING-TOKEN-END is the first position after the preceding + ;; token, i.e. on the other side of the syntactic ws from the point. + ;; Use a value less than or equal to (point-min) if the point is at + ;; the first token in (the visible part of) the buffer. + ;; + ;; CONTEXT is a symbol that describes the context at the point: + ;; 'decl In a comma-separatded declaration context (typically + ;; inside a function declaration arglist). + ;; '<> In an angle bracket arglist. + ;; 'arglist Some other type of arglist. + ;; nil Some other context or unknown context. + ;; + ;; LAST-CAST-END is the first token after the closing paren of a + ;; preceding cast, or nil if none is known. If + ;; `c-forward-decl-or-cast-1' is used in succession, it should be + ;; the position after the closest preceding call where a cast was + ;; matched. In that case it's used to discover chains of casts like + ;; "(a) (b) c". + ;; + ;; This function records identifier ranges on + ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if + ;; `c-record-type-identifiers' is non-nil. + ;; + ;; This function might do hidden buffer changes. + + (let (;; `start-pos' is used below to point to the start of the + ;; first type, i.e. after any leading specifiers. It might + ;; also point at the beginning of the preceding syntactic + ;; whitespace. + (start-pos (point)) + ;; Set to the result of `c-forward-type'. + at-type + ;; The position of the first token in what we currently + ;; believe is the type in the declaration or cast, after any + ;; specifiers and their associated clauses. + type-start + ;; The position of the first token in what we currently + ;; believe is the declarator for the first identifier. Set + ;; when the type is found, and moved forward over any + ;; `c-decl-hangon-kwds' and their associated clauses that + ;; occurs after the type. + id-start + ;; These store `at-type', `type-start' and `id-start' of the + ;; identifier before the one in those variables. The previous + ;; identifier might turn out to be the real type in a + ;; declaration if the last one has to be the declarator in it. + ;; If `backup-at-type' is nil then the other variables have + ;; undefined values. + backup-at-type backup-type-start backup-id-start + ;; Set if we've found a specifier that makes the defined + ;; identifier(s) types. + at-type-decl + ;; Set if we've found a specifier that can start a declaration + ;; where there's no type. + maybe-typeless + ;; If a specifier is found that also can be a type prefix, + ;; these flags are set instead of those above. If we need to + ;; back up an identifier, they are copied to the real flag + ;; variables. Thus they only take effect if we fail to + ;; interpret it as a type. + backup-at-type-decl backup-maybe-typeless + ;; Whether we've found a declaration or a cast. We might know + ;; this before we've found the type in it. It's 'ids if we've + ;; found two consecutive identifiers (usually a sure sign, but + ;; we should allow that in labels too), and t if we've found a + ;; specifier keyword (a 100% sure sign). + at-decl-or-cast + ;; Set when we need to back up to parse this as a declaration + ;; but not as a cast. + backup-if-not-cast + ;; For casts, the return position. + cast-end + ;; Save `c-record-type-identifiers' and + ;; `c-record-ref-identifiers' since ranges are recorded + ;; speculatively and should be thrown away if it turns out + ;; that it isn't a declaration or cast. + (save-rec-type-ids c-record-type-identifiers) + (save-rec-ref-ids c-record-ref-identifiers)) + + ;; Check for a type. Unknown symbols are treated as possible + ;; types, but they could also be specifiers disguised through + ;; macros like __INLINE__, so we recognize both types and known + ;; specifiers after them too. + (while + (let* ((start (point)) kwd-sym kwd-clause-end found-type) + + ;; Look for a specifier keyword clause. + (when (looking-at c-prefix-spec-kwds-re) + (setq kwd-sym (c-keyword-sym (match-string 1))) + (save-excursion + (c-forward-keyword-clause 1) + (setq kwd-clause-end (point)))) + + (when (setq found-type (c-forward-type)) + ;; Found a known or possible type or a prefix of a known type. + + (when at-type + ;; Got two identifiers with nothing but whitespace + ;; between them. That can only happen in declarations. + (setq at-decl-or-cast 'ids) + + (when (eq at-type 'found) + ;; If the previous identifier is a found type we + ;; record it as a real one; it might be some sort of + ;; alias for a prefix like "unsigned". + (save-excursion + (goto-char type-start) + (let ((c-promote-possible-types t)) + (c-forward-type))))) + + (setq backup-at-type at-type + backup-type-start type-start + backup-id-start id-start + at-type found-type + type-start start + id-start (point) + ;; The previous ambiguous specifier/type turned out + ;; to be a type since we've parsed another one after + ;; it, so clear these backup flags. + backup-at-type-decl nil + backup-maybe-typeless nil)) + + (if kwd-sym + (progn + ;; Handle known specifier keywords and + ;; `c-decl-hangon-kwds' which can occur after known + ;; types. + + (if (c-keyword-member kwd-sym 'c-decl-hangon-kwds) + ;; It's a hang-on keyword that can occur anywhere. + (progn + (setq at-decl-or-cast t) + (if at-type + ;; Move the identifier start position if + ;; we've passed a type. + (setq id-start kwd-clause-end) + ;; Otherwise treat this as a specifier and + ;; move the fallback position. + (setq start-pos kwd-clause-end)) + (goto-char kwd-clause-end)) + + ;; It's an ordinary specifier so we know that + ;; anything before this can't be the type. + (setq backup-at-type nil + start-pos kwd-clause-end) + + (if found-type + ;; It's ambiguous whether this keyword is a + ;; specifier or a type prefix, so set the backup + ;; flags. (It's assumed that `c-forward-type' + ;; moved further than `c-forward-keyword-clause'.) + (progn + (when (c-keyword-member kwd-sym 'c-typedef-decl-kwds) + (setq backup-at-type-decl t)) + (when (c-keyword-member kwd-sym 'c-typeless-decl-kwds) + (setq backup-maybe-typeless t))) + + (when (c-keyword-member kwd-sym 'c-typedef-decl-kwds) + (setq at-type-decl t)) + (when (c-keyword-member kwd-sym 'c-typeless-decl-kwds) + (setq maybe-typeless t)) + + ;; Haven't matched a type so it's an umambiguous + ;; specifier keyword and we know we're in a + ;; declaration. + (setq at-decl-or-cast t) + + (goto-char kwd-clause-end)))) + + ;; If the type isn't known we continue so that we'll jump + ;; over all specifiers and type identifiers. The reason + ;; to do this for a known type prefix is to make things + ;; like "unsigned INT16" work. + (and found-type (not (eq found-type t)))))) + + (cond + ((eq at-type t) + ;; If a known type was found, we still need to skip over any + ;; hangon keyword clauses after it. Otherwise it has already + ;; been done in the loop above. + (while (looking-at c-decl-hangon-key) + (c-forward-keyword-clause 1)) + (setq id-start (point))) + + ((eq at-type 'prefix) + ;; A prefix type is itself a primitive type when it's not + ;; followed by another type. + (setq at-type t)) + + ((not at-type) + ;; Got no type but set things up to continue anyway to handle + ;; the various cases when a declaration doesn't start with a + ;; type. + (setq id-start start-pos)) + + ((and (eq at-type 'maybe) + (c-major-mode-is 'c++-mode)) + ;; If it's C++ then check if the last "type" ends on the form + ;; "foo::foo" or "foo::~foo", i.e. if it's the name of a + ;; (con|de)structor. + (save-excursion + (let (name end-2 end-1) + (goto-char id-start) + (c-backward-syntactic-ws) + (setq end-2 (point)) + (when (and + (c-simple-skip-symbol-backward) + (progn + (setq name + (buffer-substring-no-properties (point) end-2)) + ;; Cheating in the handling of syntactic ws below. + (< (skip-chars-backward ":~ \t\n\r\v\f") 0)) + (progn + (setq end-1 (point)) + (c-simple-skip-symbol-backward)) + (>= (point) type-start) + (equal (buffer-substring-no-properties (point) end-1) + name)) + ;; It is a (con|de)structor name. In that case the + ;; declaration is typeless so zap out any preceding + ;; identifier(s) that we might have taken as types. + (goto-char type-start) + (setq at-type nil + backup-at-type nil + id-start type-start)))))) + + ;; Check for and step over a type decl expression after the thing + ;; that is or might be a type. This can't be skipped since we + ;; need the correct end position of the declarator for + ;; `max-type-decl-end-*'. + (let ((start (point)) (paren-depth 0) pos + ;; True if there's a non-open-paren match of + ;; `c-type-decl-prefix-key'. + got-prefix + ;; True if the declarator is surrounded by a parenthesis pair. + got-parens + ;; True if there is an identifier in the declarator. + got-identifier + ;; True if there's a non-close-paren match of + ;; `c-type-decl-suffix-key'. + got-suffix + ;; True if there's a prefix match outside the outermost + ;; paren pair that surrounds the declarator. + got-prefix-before-parens +y ;; True if there's a suffix match outside the outermost + ;; paren pair that surrounds the declarator. The value is + ;; the position of the first suffix match. + got-suffix-after-parens + ;; True if we've parsed the type decl to a token that is + ;; known to end declarations in this context. + at-decl-end + ;; The earlier values of `at-type' and `type-start' if we've + ;; shifted the type backwards. + identifier-type identifier-start + ;; If `c-parse-and-markup-<>-arglists' is set we need to + ;; turn it off during the name skipping below to avoid + ;; getting `c-type' properties that might be bogus. That + ;; can happen since we don't know if + ;; `c-restricted-<>-arglists' will be correct inside the + ;; arglist paren that gets entered. + c-parse-and-markup-<>-arglists) + + (goto-char id-start) + + ;; Skip over type decl prefix operators. (Note similar code in + ;; `c-font-lock-declarators'.) + (while (and (looking-at c-type-decl-prefix-key) + (if (and (c-major-mode-is 'c++-mode) + (match-beginning 2)) + ;; If the second submatch matches in C++ then + ;; we're looking at an identifier that's a + ;; prefix only if it specifies a member pointer. + (when (setq got-identifier (c-forward-name)) + (if (looking-at "\\(::\\)") + ;; We only check for a trailing "::" and + ;; let the "*" that should follow be + ;; matched in the next round. + (progn (setq got-identifier nil) t) + ;; It turned out to be the real identifier, + ;; so stop. + nil)) + t)) + + (if (eq (char-after) ?\() + (progn + (setq paren-depth (1+ paren-depth)) + (forward-char)) + (unless got-prefix-before-parens + (setq got-prefix-before-parens (= paren-depth 0))) + (setq got-prefix t) + (goto-char (match-end 1))) + (c-forward-syntactic-ws)) + + (setq got-parens (> paren-depth 0)) + + ;; Skip over an identifier. + (or got-identifier + (and (looking-at c-identifier-start) + (setq got-identifier (c-forward-name)))) + + ;; Skip over type decl suffix operators. + (while (if (looking-at c-type-decl-suffix-key) + + (if (eq (char-after) ?\)) + (when (> paren-depth 0) + (setq paren-depth (1- paren-depth)) + (forward-char) + t) + (when (if (save-match-data (looking-at "\\s\(")) + (c-safe (c-forward-sexp 1) t) + (goto-char (match-end 1)) + t) + (when (and (not got-suffix-after-parens) + (= paren-depth 0)) + (setq got-suffix-after-parens (match-beginning 0))) + (setq got-suffix t))) + + ;; No suffix matched. We might have matched the + ;; identifier as a type and the open paren of a + ;; function arglist as a type decl prefix. In that + ;; case we should "backtrack": Reinterpret the last + ;; type as the identifier, move out of the arglist and + ;; continue searching for suffix operators. + ;; + ;; Do this even if there's no preceding type, to cope + ;; with old style function declarations in K&R C, + ;; (con|de)structors in C++ and `c-typeless-decl-kwds' + ;; style declarations. That isn't applicable in an + ;; arglist context, though. + (when (and (= paren-depth 1) + (not got-prefix-before-parens) + (not (eq at-type t)) + (or backup-at-type + maybe-typeless + backup-maybe-typeless + (when c-recognize-typeless-decls + (not context))) + (setq pos (c-up-list-forward (point))) + (eq (char-before pos) ?\))) + (c-fdoc-shift-type-backward) + (goto-char pos) + t)) + + (c-forward-syntactic-ws)) + + (when (and (or maybe-typeless backup-maybe-typeless) + (not got-identifier) + (not got-prefix) + at-type) + ;; Have found no identifier but `c-typeless-decl-kwds' has + ;; matched so we know we're inside a declaration. The + ;; preceding type must be the identifier instead. + (c-fdoc-shift-type-backward)) + + (setq + at-decl-or-cast + (catch 'at-decl-or-cast + + (when (> paren-depth 0) + ;; Encountered something inside parens that isn't matched by + ;; the `c-type-decl-*' regexps, so it's not a type decl + ;; expression. Try to skip out to the same paren depth to + ;; not confuse the cast check below. + (c-safe (goto-char (scan-lists (point) 1 paren-depth))) + ;; If we've found a specifier keyword then it's a + ;; declaration regardless. + (throw 'at-decl-or-cast (eq at-decl-or-cast t))) + + (setq at-decl-end + (looking-at (cond ((eq context '<>) "[,>]") + (context "[,\)]") + (t "[,;]")))) + + ;; Now we've collected info about various characteristics of + ;; the construct we're looking at. Below follows a decision + ;; tree based on that. It's ordered to check more certain + ;; signs before less certain ones. + + (if got-identifier + (progn + + (when (and (or at-type maybe-typeless) + (not (or got-prefix got-parens))) + ;; Got another identifier directly after the type, so it's a + ;; declaration. + (throw 'at-decl-or-cast t)) + + (when (and got-parens + (not got-prefix) + (not got-suffix-after-parens) + (or backup-at-type + maybe-typeless + backup-maybe-typeless)) + ;; Got a declaration of the form "foo bar (gnu);" where we've + ;; recognized "bar" as the type and "gnu" as the declarator. + ;; In this case it's however more likely that "bar" is the + ;; declarator and "gnu" a function argument or initializer (if + ;; `c-recognize-paren-inits' is set), since the parens around + ;; "gnu" would be superfluous if it's a declarator. Shift the + ;; type one step backward. + (c-fdoc-shift-type-backward))) + + ;; Found no identifier. + + (if backup-at-type + (progn + + (when (= (point) start) + ;; Got a plain list of identifiers. If a colon follows it's + ;; a valid label. Otherwise the last one probably is the + ;; declared identifier and we should back up to the previous + ;; type, providing it isn't a cast. + (if (eq (char-after) ?:) + ;; If we've found a specifier keyword then it's a + ;; declaration regardless. + (throw 'at-decl-or-cast (eq at-decl-or-cast t)) + (setq backup-if-not-cast t) + (throw 'at-decl-or-cast t))) + + (when (and got-suffix + (not got-prefix) + (not got-parens)) + ;; Got a plain list of identifiers followed by some suffix. + ;; If this isn't a cast then the last identifier probably is + ;; the declared one and we should back up to the previous + ;; type. + (setq backup-if-not-cast t) + (throw 'at-decl-or-cast t))) + + (when (eq at-type t) + ;; If the type is known we know that there can't be any + ;; identifier somewhere else, and it's only in declarations in + ;; e.g. function prototypes and in casts that the identifier may + ;; be left out. + (throw 'at-decl-or-cast t)) + + (when (= (point) start) + ;; Only got a single identifier (parsed as a type so far). + (if (and + ;; Check that the identifier isn't at the start of an + ;; expression. + at-decl-end + (cond + ((eq context 'decl) + ;; Inside an arglist that contains declarations. If K&R + ;; style declarations and parenthesis style initializers + ;; aren't allowed then the single identifier must be a + ;; type, else we require that it's known or found + ;; (primitive types are handled above). + (or (and (not c-recognize-knr-p) + (not c-recognize-paren-inits)) + (memq at-type '(known found)))) + ((eq context '<>) + ;; Inside a template arglist. Accept known and found + ;; types; other identifiers could just as well be + ;; constants in C++. + (memq at-type '(known found))))) + (throw 'at-decl-or-cast t) + ;; Can't be a valid declaration or cast, but if we've found a + ;; specifier it can't be anything else either, so treat it as + ;; an invalid/unfinished declaration or cast. + (throw 'at-decl-or-cast at-decl-or-cast)))) + + (if (and got-parens + (not got-prefix) + (not context) + (not (eq at-type t)) + (or backup-at-type + maybe-typeless + backup-maybe-typeless + (when c-recognize-typeless-decls + (or (not got-suffix) + (not (looking-at + c-after-suffixed-type-maybe-decl-key)))))) + ;; Got an empty paren pair and a preceding type that probably + ;; really is the identifier. Shift the type backwards to make + ;; the last one the identifier. This is analogous to the + ;; "backtracking" done inside the `c-type-decl-suffix-key' loop + ;; above. + ;; + ;; Exception: In addition to the conditions in that + ;; "backtracking" code, do not shift backward if we're not + ;; looking at either `c-after-suffixed-type-decl-key' or "[;,]". + ;; Since there's no preceding type, the shift would mean that + ;; the declaration is typeless. But if the regexp doesn't match + ;; then we will simply fall through in the tests below and not + ;; recognize it at all, so it's better to try it as an abstract + ;; declarator instead. + (c-fdoc-shift-type-backward) + + ;; Still no identifier. + + (when (and got-prefix (or got-parens got-suffix)) + ;; Require `got-prefix' together with either `got-parens' or + ;; `got-suffix' to recognize it as an abstract declarator: + ;; `got-parens' only is probably an empty function call. + ;; `got-suffix' only can build an ordinary expression together + ;; with the preceding identifier which we've taken as a type. + ;; We could actually accept on `got-prefix' only, but that can + ;; easily occur temporarily while writing an expression so we + ;; avoid that case anyway. We could do a better job if we knew + ;; the point when the fontification was invoked. + (throw 'at-decl-or-cast t)) + + (when (and at-type + (not got-prefix) + (not got-parens) + got-suffix-after-parens + (eq (char-after got-suffix-after-parens) ?\()) + ;; Got a type, no declarator but a paren suffix. I.e. it's a + ;; normal function call afterall (or perhaps a C++ style object + ;; instantiation expression). + (throw 'at-decl-or-cast nil)))) + + (when at-decl-or-cast + ;; By now we've located the type in the declaration that we know + ;; we're in. + (throw 'at-decl-or-cast t)) + + (when (and got-identifier + (not context) + (looking-at c-after-suffixed-type-decl-key) + (if (and got-parens + (not got-prefix) + (not got-suffix) + (not (eq at-type t))) + ;; Shift the type backward in the case that there's a + ;; single identifier inside parens. That can only + ;; occur in K&R style function declarations so it's + ;; more likely that it really is a function call. + ;; Therefore we only do this after + ;; `c-after-suffixed-type-decl-key' has matched. + (progn (c-fdoc-shift-type-backward) t) + got-suffix-after-parens)) + ;; A declaration according to `c-after-suffixed-type-decl-key'. + (throw 'at-decl-or-cast t)) + + (when (and (or got-prefix (not got-parens)) + (memq at-type '(t known))) + ;; It's a declaration if a known type precedes it and it can't be a + ;; function call. + (throw 'at-decl-or-cast t)) + + ;; If we get here we can't tell if this is a type decl or a normal + ;; expression by looking at it alone. (That's under the assumption + ;; that normal expressions always can look like type decl expressions, + ;; which isn't really true but the cases where it doesn't hold are so + ;; uncommon (e.g. some placements of "const" in C++) it's not worth + ;; the effort to look for them.) + + (unless (or at-decl-end (looking-at "=[^=]")) + ;; If this is a declaration it should end here or its initializer(*) + ;; should start here, so check for allowed separation tokens. Note + ;; that this rule doesn't work e.g. with a K&R arglist after a + ;; function header. + ;; + ;; *) Don't check for C++ style initializers using parens + ;; since those already have been matched as suffixes. + ;; + ;; If `at-decl-or-cast' is then we've found some other sign that + ;; it's a declaration or cast, so then it's probably an + ;; invalid/unfinished one. + (throw 'at-decl-or-cast at-decl-or-cast)) + + ;; Below are tests that only should be applied when we're certain to + ;; not have parsed halfway through an expression. + + (when (memq at-type '(t known)) + ;; The expression starts with a known type so treat it as a + ;; declaration. + (throw 'at-decl-or-cast t)) + + (when (and (c-major-mode-is 'c++-mode) + ;; In C++ we check if the identifier is a known type, since + ;; (con|de)structors use the class name as identifier. + ;; We've always shifted over the identifier as a type and + ;; then backed up again in this case. + identifier-type + (or (memq identifier-type '(found known)) + (and (eq (char-after identifier-start) ?~) + ;; `at-type' probably won't be 'found for + ;; destructors since the "~" is then part of the + ;; type name being checked against the list of + ;; known types, so do a check without that + ;; operator. + (or (save-excursion + (goto-char (1+ identifier-start)) + (c-forward-syntactic-ws) + (c-with-syntax-table + c-identifier-syntax-table + (looking-at c-known-type-key))) + (save-excursion + (goto-char (1+ identifier-start)) + ;; We have already parsed the type earlier, + ;; so it'd be possible to cache the end + ;; position instead of redoing it here, but + ;; then we'd need to keep track of another + ;; position everywhere. + (c-check-type (point) + (progn (c-forward-type) + (point)))))))) + (throw 'at-decl-or-cast t)) + + (if got-identifier + (progn + (when (and got-prefix-before-parens + at-type + (or at-decl-end (looking-at "=[^=]")) + (not context) + (not got-suffix)) + ;; Got something like "foo * bar;". Since we're not inside an + ;; arglist it would be a meaningless expression because the + ;; result isn't used. We therefore choose to recognize it as + ;; a declaration. Do not allow a suffix since it could then + ;; be a function call. + (throw 'at-decl-or-cast t)) + + (when (and (or got-suffix-after-parens + (looking-at "=[^=]")) + (eq at-type 'found) + (not (eq context 'arglist))) + ;; Got something like "a (*b) (c);" or "a (b) = c;". It could + ;; be an odd expression or it could be a declaration. Treat + ;; it as a declaration if "a" has been used as a type + ;; somewhere else (if it's a known type we won't get here). + (throw 'at-decl-or-cast t))) + + (when (and context + (or got-prefix + (and (eq context 'decl) + (not c-recognize-paren-inits) + (or got-parens got-suffix)))) + ;; Got a type followed by an abstract declarator. If `got-prefix' + ;; is set it's something like "a *" without anything after it. If + ;; `got-parens' or `got-suffix' is set it's "a()", "a[]", "a()[]", + ;; or similar, which we accept only if the context rules out + ;; expressions. + (throw 'at-decl-or-cast t))) + + ;; If we had a complete symbol table here (which rules out + ;; `c-found-types') we should return t due to the disambiguation rule + ;; (in at least C++) that anything that can be parsed as a declaration + ;; is a declaration. Now we're being more defensive and prefer to + ;; highlight things like "foo (bar);" as a declaration only if we're + ;; inside an arglist that contains declarations. + (eq context 'decl)))) + + ;; The point is now after the type decl expression. + + (cond + ;; Check for a cast. + ((save-excursion + (and + c-cast-parens + + ;; Should be the first type/identifier in a cast paren. + (> preceding-token-end (point-min)) + (memq (char-before preceding-token-end) c-cast-parens) + + ;; The closing paren should follow. + (progn + (c-forward-syntactic-ws) + (looking-at "\\s\)")) + + ;; There should be a primary expression after it. + (let (pos) + (forward-char) + (c-forward-syntactic-ws) + (setq cast-end (point)) + (and (looking-at c-primary-expr-regexp) + (progn + (setq pos (match-end 0)) + (or + ;; Check if the expression begins with a prefix keyword. + (match-beginning 2) + (if (match-beginning 1) + ;; Expression begins with an ambiguous operator. Treat + ;; it as a cast if it's a type decl or if we've + ;; recognized the type somewhere else. + (or at-decl-or-cast + (memq at-type '(t known found))) + ;; Unless it's a keyword, it's the beginning of a primary + ;; expression. + (not (looking-at c-keywords-regexp))))) + ;; If `c-primary-expr-regexp' matched a nonsymbol token, check + ;; that it matched a whole one so that we don't e.g. confuse + ;; the operator '-' with '->'. It's ok if it matches further, + ;; though, since it e.g. can match the float '.5' while the + ;; operator regexp only matches '.'. + (or (not (looking-at c-nonsymbol-token-regexp)) + (<= (match-end 0) pos)))) + + ;; There should either be a cast before it or something that isn't an + ;; identifier or close paren. + (> preceding-token-end (point-min)) + (progn + (goto-char (1- preceding-token-end)) + (or (eq (point) last-cast-end) + (progn + (c-backward-syntactic-ws) + (if (< (skip-syntax-backward "w_") 0) + ;; It's a symbol. Accept it only if it's one of the + ;; keywords that can precede an expression (without + ;; surrounding parens). + (looking-at c-simple-stmt-key) + (and + ;; Check that it isn't a close paren (block close is ok, + ;; though). + (not (memq (char-before) '(?\) ?\]))) + ;; Check that it isn't a nonsymbol identifier. + (not (c-on-identifier))))))))) + + ;; Handle the cast. + (when (and c-record-type-identifiers at-type (not (eq at-type t))) + (let ((c-promote-possible-types t)) + (goto-char type-start) + (c-forward-type))) + + (goto-char cast-end) + 'cast) + + (at-decl-or-cast + ;; We're at a declaration. Highlight the type and the following + ;; declarators. + + (when backup-if-not-cast + (c-fdoc-shift-type-backward t)) + + (when (and (eq context 'decl) (looking-at ",")) + ;; Make sure to propagate the `c-decl-arg-start' property to + ;; the next argument if it's set in this one, to cope with + ;; interactive refontification. + (c-put-c-type-property (point) 'c-decl-arg-start)) + + (when (and c-record-type-identifiers at-type (not (eq at-type t))) + (let ((c-promote-possible-types t)) + (save-excursion + (goto-char type-start) + (c-forward-type)))) + + (cons id-start at-type-decl)) + + (t + ;; False alarm. Restore the recorded ranges. + (setq c-record-type-identifiers save-rec-type-ids + c-record-ref-identifiers save-rec-ref-ids) + nil)))) + +(defun c-forward-label (&optional assume-markup preceding-token-end limit) + ;; Assuming the point is at the beginning of a token, check if it + ;; starts a label and if so move over it and return t, otherwise + ;; don't move and return nil. The end of the label is taken to be + ;; the end of the first submatch in `c-opt-extra-label-key' if it + ;; matched, otherwise it's the colon. The point is directly after + ;; the end on return. The terminating char is marked with + ;; `c-decl-end' to improve recognition of the following declaration + ;; or statement. + ;; + ;; If ASSUME-MARKUP is non-nil, it's assumed that the preceding + ;; label, if any, has been marked up like that. + ;; + ;; If PRECEDING-TOKEN-END is given, it should be the first position + ;; after the preceding token, i.e. on the other side of the + ;; syntactic ws from the point. Use a value less than or equal to + ;; (point-min) if the point is at the first token in (the visible + ;; part of) the buffer. + ;; + ;; The optional LIMIT limits the forward scan for the colon. + ;; + ;; This function records the ranges of the label symbols on + ;; `c-record-ref-identifiers' if `c-record-type-identifiers' (!) is + ;; non-nil. + ;; + ;; This function might do hidden buffer changes. + + (let ((start (point))) + (cond + ((looking-at c-label-kwds-regexp) + (let ((kwd-end (match-end 1))) + ;; Record only the keyword itself for fontification, since in + ;; case labels the following is a constant expression and not + ;; a label. + (when c-record-type-identifiers + (c-record-ref-id (cons (match-beginning 1) kwd-end))) + + ;; Find the label end. + (goto-char kwd-end) + (if (and (c-syntactic-re-search-forward + ;; Stop on chars that aren't allowed in expressions, + ;; and on operator chars that would be meaningless + ;; there. FIXME: This doesn't cope with ?: operators. + "[;{=,@]\\|\\(\\=\\|[^:]\\):\\([^:]\\|\\'\\)" + limit t t nil 1) + (match-beginning 2)) + + (progn + (goto-char (match-beginning 2)) + (c-put-c-type-property (1- (point)) 'c-decl-end) + t) + + ;; It's an unfinished label. We consider the keyword enough + ;; to recognize it as a label, so that it gets fontified. + ;; Leave the point at the end of it, but don't put any + ;; `c-decl-end' marker. + (goto-char kwd-end) + t))) + + ((and c-opt-extra-label-key + (looking-at c-opt-extra-label-key)) + ;; For a `c-opt-extra-label-key' match, we record the whole + ;; thing for fontification. That's to get the leading '@' in + ;; Objective-C protection labels fontified. + (goto-char (match-end 1)) + (when c-record-type-identifiers + (c-record-ref-id (cons (match-beginning 1) (point)))) + (c-put-c-type-property (1- (point)) 'c-decl-end) + t) + + ((and c-recognize-colon-labels + + ;; A colon label must have something before the colon. + (not (eq (char-after) ?:)) + + ;; Check that we're not after a token that can't precede a label. + (or + ;; Trivially succeeds when there's no preceding token. + (if preceding-token-end + (<= preceding-token-end (point-min)) + (save-excursion + (c-backward-syntactic-ws) + (setq preceding-token-end (point)) + (bobp))) + + ;; Check if we're after a label, if we're after a closing + ;; paren that belong to statement, and with + ;; `c-label-prefix-re'. It's done in different order + ;; depending on `assume-markup' since the checks have + ;; different expensiveness. + (if assume-markup + (or + (eq (c-get-char-property (1- preceding-token-end) 'c-type) + 'c-decl-end) + + (save-excursion + (goto-char (1- preceding-token-end)) + (c-beginning-of-current-token) + (looking-at c-label-prefix-re)) + + (and (eq (char-before preceding-token-end) ?\)) + (c-after-conditional))) + + (or + (save-excursion + (goto-char (1- preceding-token-end)) + (c-beginning-of-current-token) + (looking-at c-label-prefix-re)) + + (cond + ((eq (char-before preceding-token-end) ?\)) + (c-after-conditional)) + + ((eq (char-before preceding-token-end) ?:) + ;; Might be after another label, so check it recursively. + (save-excursion + (goto-char (1- preceding-token-end)) + ;; Essentially the same as the + ;; `c-syntactic-re-search-forward' regexp below. + (c-syntactic-skip-backward "^-]:?;}=*/%&|,<>!@+" nil t) + (let ((pte (point)) + ;; If the caller turned on recording for us, + ;; it shouldn't apply when we check the + ;; preceding label. + c-record-type-identifiers) + (c-forward-syntactic-ws) + (c-forward-label nil pte start)))))))) + + ;; Check that the next nonsymbol token is ":". Allow '(' + ;; for the sake of macro arguments. FIXME: Should build + ;; this regexp from the language constants. + (c-syntactic-re-search-forward + "[[:?;{=*/%&|,<>!@+-]" limit t t) + (eq (char-before) ?:) + (not (eq (char-after) ?:))) + + (save-restriction + (narrow-to-region start (point)) + + ;; Check that `c-nonlabel-token-key' doesn't match anywhere. + (catch 'check-label + (goto-char start) + (while (progn + (when (looking-at c-nonlabel-token-key) + (goto-char start) + (throw 'check-label nil)) + (and (c-safe (c-forward-sexp) + (c-forward-syntactic-ws) + t) + (not (eobp))))) + + ;; Record the identifiers in the label for fontification, unless + ;; it begins with `c-label-kwds' in which case the following + ;; identifiers are part of a (constant) expression that + ;; shouldn't be fontified. + (when (and c-record-type-identifiers + (progn (goto-char start) + (not (looking-at c-label-kwds-regexp)))) + (while (c-syntactic-re-search-forward c-symbol-key nil t) + (c-record-ref-id (cons (match-beginning 0) + (match-end 0))))) + + (c-put-c-type-property (1- (point-max)) 'c-decl-end) + (goto-char (point-max)) + t))) + + (t + ;; Not a label. + (goto-char start) + nil)))) + +(defun c-forward-objc-directive () + ;; Assuming the point is at the beginning of a token, try to move + ;; forward to the end of the Objective-C directive that starts + ;; there. Return t if a directive was fully recognized, otherwise + ;; the point is moved as far as one could be successfully parsed and + ;; nil is returned. + ;; + ;; This function records identifier ranges on + ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if + ;; `c-record-type-identifiers' is non-nil. + ;; + ;; This function might do hidden buffer changes. + + (let ((start (point)) + start-char + (c-promote-possible-types t) + ;; Turn off recognition of angle bracket arglists while parsing + ;; types here since the protocol reference list might then be + ;; considered part of the preceding name or superclass-name. + c-recognize-<>-arglists) + + (if (or + (when (looking-at + (eval-when-compile + (c-make-keywords-re t + (append (c-lang-const c-protection-kwds objc) + '("@end")) + 'objc-mode))) + (goto-char (match-end 1)) + t) + + (and + (looking-at + (eval-when-compile + (c-make-keywords-re t + '("@interface" "@implementation" "@protocol") + 'objc-mode))) + + ;; Handle the name of the class itself. + (progn + (c-forward-token-2) + (c-forward-type)) + + (catch 'break + ;; Look for ": superclass-name" or "( category-name )". + (when (looking-at "[:\(]") + (setq start-char (char-after)) + (forward-char) + (c-forward-syntactic-ws) + (unless (c-forward-type) (throw 'break nil)) + (when (eq start-char ?\() + (unless (eq (char-after) ?\)) (throw 'break nil)) + (forward-char) + (c-forward-syntactic-ws))) + + ;; Look for a protocol reference list. + (if (eq (char-after) ?<) + (let ((c-recognize-<>-arglists t) + (c-parse-and-markup-<>-arglists t) + c-restricted-<>-arglists) + (c-forward-<>-arglist t)) + t)))) + + (progn + (c-backward-syntactic-ws) + (c-clear-c-type-property start (1- (point)) 'c-decl-end) + (c-put-c-type-property (1- (point)) 'c-decl-end) + t) + + (c-clear-c-type-property start (point) 'c-decl-end) + nil))) + (defun c-beginning-of-inheritance-list (&optional lim) ;; Go to the first non-whitespace after the colon that starts a ;; multiple inheritance introduction. Optional LIM is the farthest ;; back we should search. - (let* ((lim (or lim (save-excursion - (c-beginning-of-syntax) - (point))))) - (c-with-syntax-table c++-template-syntax-table - (c-backward-token-2 0 t lim) - (while (and (or (looking-at c-symbol-start) - (looking-at "[<,]\\|::")) - (zerop (c-backward-token-2 1 t lim)))) - (skip-chars-forward "^:")))) + ;; + ;; This function might do hidden buffer changes. + (c-with-syntax-table c++-template-syntax-table + (c-backward-token-2 0 t lim) + (while (and (or (looking-at c-symbol-start) + (looking-at "[<,]\\|::")) + (zerop (c-backward-token-2 1 t lim)))))) (defun c-in-method-def-p () ;; Return nil if we aren't in a method definition, otherwise the ;; position of the initial [+-]. + ;; + ;; This function might do hidden buffer changes. (save-excursion (beginning-of-line) (and c-opt-method-key @@ -4327,6 +6055,8 @@ ;; Only one level of enclosing parentheses is considered, so for ;; instance `nil' is returned when in a function call within an asm ;; operand. + ;; + ;; This function might do hidden buffer changes. (and c-opt-asm-stmt-key (save-excursion @@ -4347,79 +6077,65 @@ Otherwise, a 2-vector is returned where the zeroth element is the buffer position of the start of the class declaration, and the first element is the buffer position of the enclosing class's opening -brace." +brace. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." (let ((paren-state (c-parse-state))) (or (not (c-most-enclosing-brace paren-state)) (c-search-uplist-for-classkey paren-state)))) (defun c-just-after-func-arglist-p (&optional lim) - ;; Return non-nil if we are between a function's argument list closing - ;; paren and its opening brace. Note that the list close brace - ;; could be followed by a "const" specifier or a member init hanging - ;; colon. LIM is used as bound for some backward buffer searches; - ;; the search might continue past it. - ;; - ;; Note: This test is easily fooled. It only works reasonably well - ;; in the situations where `c-guess-basic-syntax' uses it. - (save-excursion - (if (c-mode-is-new-awk-p) - (c-awk-backward-syntactic-ws lim) - (c-backward-syntactic-ws lim)) - (let ((checkpoint (point))) - ;; could be looking at const specifier - (if (and (eq (char-before) ?t) - (forward-word -1) - (looking-at "\\<const\\>[^_]")) - (c-backward-syntactic-ws lim) - ;; otherwise, we could be looking at a hanging member init - ;; colon - (goto-char checkpoint) - (while (and - (eq (char-before) ?,) - ;; this will catch member inits with multiple - ;; line arglists - (progn - (forward-char -1) - (c-backward-syntactic-ws (c-point 'bol)) - (c-safe (c-backward-sexp 1) t)) - (or (not (looking-at "\\s\(")) - (c-safe (c-backward-sexp 1) t))) - (c-backward-syntactic-ws lim)) - (if (and (eq (char-before) ?:) - (progn - (forward-char -1) - (c-backward-syntactic-ws lim) - (looking-at "\\([ \t\n]\\|\\\\\n\\)*:\\([^:]+\\|$\\)"))) - nil - (goto-char checkpoint)) - ) - (setq checkpoint (point)) - (and (eq (char-before) ?\)) - ;; Check that it isn't a cpp expression, e.g. the - ;; expression of an #if directive or the "function header" - ;; of a #define. - (or (not (c-beginning-of-macro)) - (and (c-forward-to-cpp-define-body) - (< (point) checkpoint))) - ;; Check if we are looking at an ObjC method def or a class - ;; category. - (not (and c-opt-method-key - (progn - (goto-char checkpoint) - (c-safe (c-backward-sexp) t)) - (progn - (c-backward-syntactic-ws lim) - (or (memq (char-before) '(?- ?+)) - (and (c-safe (c-forward-sexp -2) t) - (looking-at c-class-key)))))) - ;; Pike has compound types that include parens, - ;; e.g. "array(string)". Check that we aren't after one. - (not (and (c-major-mode-is 'pike-mode) - (progn - (goto-char checkpoint) - (c-safe (c-backward-sexp 2) t)) - (looking-at c-primitive-type-key))) - )))) + ;; Return non-nil if the point is in the region after the argument + ;; list of a function and its opening brace (or semicolon in case it + ;; got no body). If there are K&R style argument declarations in + ;; that region, the point has to be inside the first one for this + ;; function to recognize it. + ;; + ;; If successful, the point is moved to the first token after the + ;; function header (see `c-forward-decl-or-cast-1' for details) and + ;; the position of the opening paren of the function arglist is + ;; returned. + ;; + ;; The point is clobbered if not successful. + ;; + ;; LIM is used as bound for backward buffer searches. + ;; + ;; This function might do hidden buffer changes. + + (let ((beg (point)) end id-start) + (and + (eq (c-beginning-of-statement-1 lim) 'same) + + (not (or (c-major-mode-is 'objc-mode) + (c-forward-objc-directive))) + + (setq id-start + (car-safe (c-forward-decl-or-cast-1 (c-point 'bosws) nil nil))) + (< id-start beg) + + ;; There should not be a '=' or ',' between beg and the + ;; start of the declaration since that means we were in the + ;; "expression part" of the declaration. + (or (> (point) beg) + (not (looking-at "[=,]"))) + + (save-excursion + ;; Check that there's an arglist paren in the + ;; declaration. + (goto-char id-start) + (cond ((eq (char-after) ?\() + ;; The declarator is a paren expression, so skip past it + ;; so that we don't get stuck on that instead of the + ;; function arglist. + (c-forward-sexp)) + ((and c-opt-op-identitier-prefix + (looking-at c-opt-op-identitier-prefix)) + ;; Don't trip up on "operator ()". + (c-forward-token-2 2 t))) + (and (< (point) beg) + (c-syntactic-re-search-forward "(" beg t t) + (1- (point))))))) (defun c-in-knr-argdecl (&optional lim) ;; Return the position of the first argument declaration if point is @@ -4429,6 +6145,8 @@ ;; ;; Note: A declaration level context is assumed; the test can return ;; false positives for statements. + ;; + ;; This function might do hidden buffer changes. (save-excursion (save-restriction @@ -4488,6 +6206,8 @@ (defun c-skip-conditional () ;; skip forward over conditional at point, including any predicate ;; statements in parentheses. No error checking is performed. + ;; + ;; This function might do hidden buffer changes. (c-forward-sexp (cond ;; else if() ((looking-at (concat "\\<else" @@ -4505,6 +6225,8 @@ (defun c-after-conditional (&optional lim) ;; If looking at the token after a conditional then return the ;; position of its start, otherwise return nil. + ;; + ;; This function might do hidden buffer changes. (save-excursion (and (zerop (c-backward-token-2 1 t lim)) (or (looking-at c-block-stmt-1-key) @@ -4513,12 +6235,32 @@ (looking-at c-block-stmt-2-key))) (point)))) +(defun c-after-special-operator-id (&optional lim) + ;; If the point is after an operator identifier that isn't handled + ;; like an ordinary symbol (i.e. like "operator =" in C++) then the + ;; position of the start of that identifier is returned. nil is + ;; returned otherwise. The point may be anywhere in the syntactic + ;; whitespace after the last token of the operator identifier. + ;; + ;; This function might do hidden buffer changes. + (save-excursion + (and c-overloadable-operators-regexp + (zerop (c-backward-token-2 1 nil lim)) + (looking-at c-overloadable-operators-regexp) + (or (not c-opt-op-identitier-prefix) + (and + (zerop (c-backward-token-2 1 nil lim)) + (looking-at c-opt-op-identitier-prefix))) + (point)))) + (defsubst c-backward-to-block-anchor (&optional lim) ;; Assuming point is at a brace that opens a statement block of some ;; kind, move to the proper anchor point for that block. It might ;; need to be adjusted further by c-add-stmt-syntax, but the ;; position at return is suitable as start position for that ;; function. + ;; + ;; This function might do hidden buffer changes. (unless (= (point) (c-point 'boi)) (let ((start (c-after-conditional lim))) (if start @@ -4528,6 +6270,8 @@ ;; Assuming point is at a brace that opens the block of a top level ;; declaration of some kind, move to the proper anchor point for ;; that block. + ;; + ;; This function might do hidden buffer changes. (unless (= (point) (c-point 'boi)) (c-beginning-of-statement-1 lim))) @@ -4538,6 +6282,8 @@ ;; semicolon. I.e. search forward for the closest following ;; (syntactically relevant) '{', '=' or ';' token. Point is left ;; _after_ the first found token, or at point-max if none is found. + ;; + ;; This function might do hidden buffer changes. (let ((base (point))) (if (c-major-mode-is 'c++-mode) @@ -4552,7 +6298,7 @@ ;; operator token preceded by "operator". (save-excursion (and (c-safe (c-backward-sexp) t) - (looking-at "operator\\>\\([^_]\\|$\\)"))) + (looking-at c-opt-op-identitier-prefix))) (and (eq (char-before) ?<) (c-with-syntax-table c++-template-syntax-table (if (c-safe (goto-char (c-up-list-forward (point)))) @@ -4569,7 +6315,7 @@ (defun c-beginning-of-decl-1 (&optional lim) ;; Go to the beginning of the current declaration, or the beginning ;; of the previous one if already at the start of it. Point won't - ;; be moved out of any surrounding paren. Return a cons cell on the + ;; be moved out of any surrounding paren. Return a cons cell of the ;; form (MOVE . KNR-POS). MOVE is like the return value from ;; `c-beginning-of-statement-1'. If point skipped over some K&R ;; style argument declarations (and they are to be recognized) then @@ -4580,10 +6326,12 @@ ;; NB: Cases where the declaration continues after the block, as in ;; "struct foo { ... } bar;", are currently recognized as two ;; declarations, e.g. "struct foo { ... }" and "bar;" in this case. + ;; + ;; This function might do hidden buffer changes. (catch 'return (let* ((start (point)) (last-stmt-start (point)) - (move (c-beginning-of-statement-1 lim t t))) + (move (c-beginning-of-statement-1 lim nil t))) ;; `c-beginning-of-statement-1' stops at a block start, but we ;; want to continue if the block doesn't begin a top level @@ -4604,7 +6352,7 @@ ;; Check that we don't move from the first thing in a ;; macro to its header. (not (eq (setq tentative-move - (c-beginning-of-statement-1 lim t t)) + (c-beginning-of-statement-1 lim nil t)) 'macro))) (setq last-stmt-start beg beg (point) @@ -4625,7 +6373,7 @@ (< knr-argdecl-start start) (progn (goto-char knr-argdecl-start) - (not (eq (c-beginning-of-statement-1 lim t t) 'macro)))) + (not (eq (c-beginning-of-statement-1 lim nil t) 'macro)))) (throw 'return (cons (if (eq (char-after fallback-pos) ?{) 'previous @@ -4633,17 +6381,6 @@ knr-argdecl-start)) (goto-char fallback-pos)))) - (when c-opt-access-key - ;; Might have ended up before a protection label. This should - ;; perhaps be checked before `c-recognize-knr-p' to be really - ;; accurate, but we know that no language has both. - (while (looking-at c-opt-access-key) - (goto-char (match-end 0)) - (c-forward-syntactic-ws) - (when (>= (point) start) - (goto-char start) - (throw 'return (cons 'same nil))))) - ;; `c-beginning-of-statement-1' counts each brace block as a ;; separate statement, so the result will be 'previous if we've ;; moved over any. If they were brace list initializers we might @@ -4675,6 +6412,8 @@ ;; point is moved as far as possible within the current sexp and nil ;; is returned. This function doesn't handle macros; use ;; `c-end-of-macro' instead in those cases. + ;; + ;; This function might do hidden buffer changes. (let ((start (point)) (decl-syntax-table (if (c-major-mode-is 'c++-mode) c++-template-syntax-table @@ -4729,178 +6468,171 @@ (c-syntactic-re-search-forward ";" nil 'move t)))) nil))) -(defun c-beginning-of-member-init-list (&optional limit) - ;; Go to the beginning of a member init list (i.e. just after the - ;; ':') if inside one. Returns t in that case, nil otherwise. - (or limit - (setq limit (point-min))) - (skip-chars-forward " \t") - - (if (eq (char-after) ?,) - (forward-char 1) - (c-backward-syntactic-ws limit)) - - (catch 'exit - (while (and (< limit (point)) - (eq (char-before) ?,)) - - ;; this will catch member inits with multiple - ;; line arglists - (forward-char -1) - (c-backward-syntactic-ws limit) - (if (eq (char-before) ?\)) - (unless (c-safe (c-backward-sexp 1)) - (throw 'exit nil))) - (c-backward-syntactic-ws limit) - - ;; Skip over any template arg to the class. This way with a - ;; syntax table is bogus but it'll have to do for now. - (if (and (eq (char-before) ?>) - (c-major-mode-is 'c++-mode)) - (c-with-syntax-table c++-template-syntax-table - (unless (c-safe (c-backward-sexp 1)) - (throw 'exit nil)))) - (c-safe (c-backward-sexp 1)) - (c-backward-syntactic-ws limit) - - ;; Skip backwards over a fully::qualified::name. - (while (and (eq (char-before) ?:) - (save-excursion - (forward-char -1) - (eq (char-before) ?:))) - (backward-char 2) - (c-safe (c-backward-sexp 1))) - - ;; If we've stepped over a number then this is a bitfield. - (when (and c-opt-bitfield-key - (looking-at "[0-9]")) - (throw 'exit nil)) - - ;; now continue checking - (c-backward-syntactic-ws limit)) - - (and (< limit (point)) - (eq (char-before) ?:)))) +(defun c-looking-at-decl-block (containing-sexp goto-start &optional limit) + ;; Assuming the point is at an open brace, check if it starts a + ;; block that contains another declaration level, i.e. that isn't a + ;; statement block or a brace list, and if so return non-nil. + ;; + ;; If the check is successful, the return value is the start of the + ;; keyword that tells what kind of construct it is, i.e. typically + ;; what `c-decl-block-key' matched. Also, if GOTO-START is set then + ;; the point will be at the start of the construct, before any + ;; leading specifiers, otherwise it's at the returned position. + ;; + ;; The point is clobbered if the check is unsuccessful. + ;; + ;; CONTAINING-SEXP is the position of the open of the surrounding + ;; paren, or nil if none. + ;; + ;; The optional LIMIT limits the backward search for the start of + ;; the construct. It's assumed to be at a syntactically relevant + ;; position. + ;; + ;; If any template arglists are found in the searched region before + ;; the open brace, they get marked with paren syntax. + ;; + ;; This function might do hidden buffer changes. + + (let ((open-brace (point)) kwd-start first-specifier-pos) + (c-syntactic-skip-backward c-block-prefix-charset limit t) + + (when (and c-recognize-<>-arglists + (eq (char-before) ?>)) + ;; Could be at the end of a template arglist. + (let ((c-parse-and-markup-<>-arglists t) + (c-disallow-comma-in-<>-arglists + (and containing-sexp + (not (eq (char-after containing-sexp) ?{))))) + (while (and + (c-backward-<>-arglist nil limit) + (progn + (c-syntactic-skip-backward c-block-prefix-charset limit t) + (eq (char-before) ?>)))))) + + ;; Note: Can't get bogus hits inside template arglists below since they + ;; have gotten paren syntax above. + (when (and + ;; If `goto-start' is set we begin by searching for the + ;; first possible position of a leading specifier list. + ;; The `c-decl-block-key' search continues from there since + ;; we know it can't match earlier. + (if goto-start + (when (c-syntactic-re-search-forward c-symbol-start + open-brace t t) + (goto-char (setq first-specifier-pos (match-beginning 0))) + t) + t) + + (cond + ((c-syntactic-re-search-forward c-decl-block-key open-brace t t t) + (goto-char (setq kwd-start (match-beginning 0))) + (or + + ;; Found a keyword that can't be a type? + (match-beginning 1) + + ;; Can be a type too, in which case it's the return type of a + ;; function (under the assumption that no declaration level + ;; block construct starts with a type). + (not (c-forward-type)) + + ;; Jumped over a type, but it could be a declaration keyword + ;; followed by the declared identifier that we've jumped over + ;; instead (e.g. in "class Foo {"). If it indeed is a type + ;; then we should be at the declarator now, so check for a + ;; valid declarator start. + ;; + ;; Note: This doesn't cope with the case when a declared + ;; identifier is followed by e.g. '(' in a language where '(' + ;; also might be part of a declarator expression. Currently + ;; there's no such language. + (not (or (looking-at c-symbol-start) + (looking-at c-type-decl-prefix-key))))) + + ;; In Pike a list of modifiers may be followed by a brace + ;; to make them apply to many identifiers. Note that the + ;; match data will be empty on return in this case. + ((and (c-major-mode-is 'pike-mode) + (progn + (goto-char open-brace) + (= (c-backward-token-2) 0)) + (looking-at c-specifier-key) + ;; Use this variant to avoid yet another special regexp. + (c-keyword-member (c-keyword-sym (match-string 1)) + 'c-modifier-kwds)) + (setq kwd-start (point)) + t))) + + ;; Got a match. + + (if goto-start + ;; Back up over any preceding specifiers and their clauses + ;; by going forward from `first-specifier-pos', which is the + ;; earliest possible position where the specifier list can + ;; start. + (progn + (goto-char first-specifier-pos) + + (while (< (point) kwd-start) + (if (looking-at c-symbol-key) + ;; Accept any plain symbol token on the ground that + ;; it's a specifier masked through a macro (just + ;; like `c-forward-decl-or-cast-1' skip forward over + ;; such tokens). + ;; + ;; Could be more restrictive wrt invalid keywords, + ;; but that'd only occur in invalid code so there's + ;; no use spending effort on it. + (let ((end (match-end 0))) + (unless (c-forward-keyword-clause 0) + (goto-char end) + (c-forward-syntactic-ws))) + + ;; Can't parse a declaration preamble and is still + ;; before `kwd-start'. That means `first-specifier-pos' + ;; was in some earlier construct. Search again. + (if (c-syntactic-re-search-forward c-symbol-start + kwd-start 'move t) + (goto-char (setq first-specifier-pos (match-beginning 0))) + ;; Got no preamble before the block declaration keyword. + (setq first-specifier-pos kwd-start)))) + + (goto-char first-specifier-pos)) + (goto-char kwd-start)) + + kwd-start))) (defun c-search-uplist-for-classkey (paren-state) - ;; search for the containing class, returning a 2 element vector if - ;; found. aref 0 contains the bufpos of the boi of the class key - ;; line, and aref 1 contains the bufpos of the open brace. - (if (null paren-state) - ;; no paren-state means we cannot be inside a class - nil - (let ((carcache (car paren-state)) - search-start search-end) - (if (consp carcache) - ;; a cons cell in the first element means that there is some - ;; balanced sexp before the current bufpos. this we can - ;; ignore. the nth 1 and nth 2 elements define for us the - ;; search boundaries - (setq search-start (nth 2 paren-state) - search-end (nth 1 paren-state)) - ;; if the car was not a cons cell then nth 0 and nth 1 define - ;; for us the search boundaries - (setq search-start (nth 1 paren-state) - search-end (nth 0 paren-state))) - ;; if search-end is nil, or if the search-end character isn't an - ;; open brace, we are definitely not in a class - (if (or (not search-end) - (< search-end (point-min)) - (not (eq (char-after search-end) ?{))) - nil - ;; now, we need to look more closely at search-start. if - ;; search-start is nil, then our start boundary is really - ;; point-min. - (if (not search-start) - (setq search-start (point-min)) - ;; if search-start is a cons cell, then we can start - ;; searching from the end of the balanced sexp just ahead of - ;; us - (if (consp search-start) - (setq search-start (cdr search-start)) - ;; Otherwise we start searching within the surrounding paren sexp. - (setq search-start (1+ search-start)))) - ;; now we can do a quick regexp search from search-start to - ;; search-end and see if we can find a class key. watch for - ;; class like strings in literals - (save-excursion - (save-restriction - (goto-char search-start) - (let (foundp class match-end) - (while (and (not foundp) - (progn - (c-forward-syntactic-ws search-end) - (> search-end (point))) - ;; Add one to the search limit, to allow - ;; matching of the "{" in the regexp. - (re-search-forward c-decl-block-key - (1+ search-end) - t)) - (setq class (match-beginning 0) - match-end (match-end 0)) - (goto-char class) - (if (c-in-literal search-start) - (goto-char match-end) ; its in a comment or string, ignore - (c-skip-ws-forward) - (setq foundp (vector (c-point 'boi) search-end)) - (cond - ;; check for embedded keywords - ((let ((char (char-after (1- class)))) - (and char - (memq (char-syntax char) '(?w ?_)))) - (goto-char match-end) - (setq foundp nil)) - ;; make sure we're really looking at the start of a - ;; class definition, and not an ObjC method. - ((and c-opt-method-key - (re-search-forward c-opt-method-key search-end t) - (not (c-in-literal class))) - (setq foundp nil)) - ;; Check if this is an anonymous inner class. - ((and c-opt-inexpr-class-key - (looking-at c-opt-inexpr-class-key)) - (while (and (zerop (c-forward-token-2 1 t)) - (looking-at "(\\|\\w\\|\\s_\\|\\."))) - (if (eq (point) search-end) - ;; We're done. Just trap this case in the cond. - nil - ;; False alarm; all conditions aren't satisfied. - (setq foundp nil))) - ;; Its impossible to define a regexp for this, and - ;; nearly so to do it programmatically. - ;; - ;; ; picks up forward decls - ;; = picks up init lists - ;; ) picks up return types - ;; > picks up templates, but remember that we can - ;; inherit from templates! - ((let ((skipchars "^;=)")) - ;; try to see if we found the `class' keyword - ;; inside a template arg list - (save-excursion - (skip-chars-backward "^<>" search-start) - (if (eq (char-before) ?<) - (setq skipchars (concat skipchars ">")))) - (while (progn - (skip-chars-forward skipchars search-end) - (c-in-literal class)) - (forward-char)) - (/= (point) search-end)) - (setq foundp nil)) - ))) - foundp)) - ))))) + ;; Check if the closest containing paren sexp is a declaration + ;; block, returning a 2 element vector in that case. Aref 0 + ;; contains the bufpos at boi of the class key line, and aref 1 + ;; contains the bufpos of the open brace. This function is an + ;; obsolete wrapper for `c-looking-at-decl-block'. + ;; + ;; This function might do hidden buffer changes. + (let ((open-paren-pos (c-most-enclosing-brace paren-state))) + (when open-paren-pos + (save-excursion + (goto-char open-paren-pos) + (when (and (eq (char-after) ?{) + (c-looking-at-decl-block + (c-safe-position open-paren-pos paren-state) + nil)) + (back-to-indentation) + (vector (point) open-paren-pos)))))) (defun c-inside-bracelist-p (containing-sexp paren-state) ;; return the buffer position of the beginning of the brace list ;; statement if we're inside a brace list, otherwise return nil. ;; CONTAINING-SEXP is the buffer pos of the innermost containing - ;; paren. BRACE-STATE is the remainder of the state of enclosing + ;; paren. PAREN-STATE is the remainder of the state of enclosing ;; braces ;; ;; N.B.: This algorithm can potentially get confused by cpp macros - ;; places in inconvenient locations. Its a trade-off we make for + ;; placed in inconvenient locations. It's a trade-off we make for ;; speed. + ;; + ;; This function might do hidden buffer changes. (or ;; This will pick up brace list declarations. (c-safe @@ -4977,7 +6709,9 @@ (setq braceassignp (cond ;; Check for operator = - ((looking-at "operator\\>[^_]") nil) + ((and c-opt-op-identitier-prefix + (looking-at c-opt-op-identitier-prefix)) + nil) ;; Check for `<opchar>= in Pike. ((and (c-major-mode-is 'pike-mode) (or (eq (char-after) ?`) @@ -5033,6 +6767,8 @@ ;; matching closer, but assumes it's correct if no balanced paren is ;; found (i.e. the case `({ ... } ... )' is detected as _not_ being ;; a special brace list). + ;; + ;; This function might do hidden buffer changes. (if c-special-brace-lists (condition-case () (save-excursion @@ -5087,82 +6823,103 @@ (defun c-looking-at-bos (&optional lim) ;; Return non-nil if between two statements or declarations, assuming ;; point is not inside a literal or comment. - (save-excursion - (c-backward-syntactic-ws lim) - (or (bobp) - ;; Return t if at the start inside some parenthesis expression - ;; too, to catch macros that have statements as arguments. - (memq (char-before) '(?\; ?} ?\()) - (and (eq (char-before) ?{) - (not (and c-special-brace-lists - (progn (backward-char) - (c-looking-at-special-brace-list)))))))) - -(defun c-looking-at-inexpr-block (lim containing-sexp) - ;; Returns non-nil if we're looking at the beginning of a block + ;; + ;; Obsolete - `c-at-statement-start-p' or `c-at-expression-start-p' + ;; are recommended instead. + ;; + ;; This function might do hidden buffer changes. + (c-at-statement-start-p)) +(make-obsolete 'c-looking-at-bos 'c-at-statement-start-p) + +(defun c-looking-at-inexpr-block (lim containing-sexp &optional check-at-end) + ;; Return non-nil if we're looking at the beginning of a block ;; inside an expression. The value returned is actually a cons of ;; either 'inlambda, 'inexpr-statement or 'inexpr-class and the - ;; position of the beginning of the construct. LIM limits the - ;; backward search. CONTAINING-SEXP is the start position of the - ;; closest containing list. If it's nil, the containing paren isn't - ;; used to decide whether we're inside an expression or not. If - ;; both LIM and CONTAINING-SEXP is used, LIM needs to be farther - ;; back. + ;; position of the beginning of the construct. + ;; + ;; LIM limits the backward search. CONTAINING-SEXP is the start + ;; position of the closest containing list. If it's nil, the + ;; containing paren isn't used to decide whether we're inside an + ;; expression or not. If both LIM and CONTAINING-SEXP are used, LIM + ;; needs to be farther back. + ;; + ;; If CHECK-AT-END is non-nil then extra checks at the end of the + ;; brace block might be done. It should only be used when the + ;; construct can be assumed to be complete, i.e. when the original + ;; starting position was further down than that. + ;; + ;; This function might do hidden buffer changes. + (save-excursion - (let ((res 'maybe) passed-bracket + (let ((res 'maybe) passed-paren (closest-lim (or containing-sexp lim (point-min))) ;; Look at the character after point only as a last resort ;; when we can't disambiguate. (block-follows (and (eq (char-after) ?{) (point)))) + (while (and (eq res 'maybe) (progn (c-backward-syntactic-ws) (> (point) closest-lim)) (not (bobp)) (progn (backward-char) (looking-at "[\]\).]\\|\\w\\|\\s_")) - (progn (forward-char) - (goto-char (scan-sexps (point) -1)))) + (c-safe (forward-char) + (goto-char (scan-sexps (point) -1)))) + (setq res - (cond - ((and block-follows - c-opt-inexpr-class-key - (looking-at c-opt-inexpr-class-key)) - (and (not passed-bracket) - (or (not (looking-at c-class-key)) - ;; If the class definition is at the start of - ;; a statement, we don't consider it an - ;; in-expression class. - (let ((prev (point))) - (while (and - (= (c-backward-token-2 1 nil closest-lim) 0) - (eq (char-syntax (char-after)) ?w)) - (setq prev (point))) - (goto-char prev) - (not (c-looking-at-bos))) - ;; Also, in Pike we treat it as an - ;; in-expression class if it's used in an - ;; object clone expression. - (save-excursion - (and (c-major-mode-is 'pike-mode) - (progn (goto-char block-follows) - (zerop (c-forward-token-2 1 t))) - (eq (char-after) ?\()))) - (cons 'inexpr-class (point)))) - ((and c-opt-inexpr-block-key - (looking-at c-opt-inexpr-block-key)) - (cons 'inexpr-statement (point))) - ((and c-opt-lambda-key - (looking-at c-opt-lambda-key)) - (cons 'inlambda (point))) - ((and c-opt-block-stmt-key - (looking-at c-opt-block-stmt-key)) - nil) - (t - (if (eq (char-after) ?\[) - (setq passed-bracket t)) - 'maybe)))) + (if (looking-at c-keywords-regexp) + (let ((kw-sym (c-keyword-sym (match-string 1)))) + (cond + ((and block-follows + (c-keyword-member kw-sym 'c-inexpr-class-kwds)) + (and (not (eq passed-paren ?\[)) + (or (not (looking-at c-class-key)) + ;; If the class definition is at the start of + ;; a statement, we don't consider it an + ;; in-expression class. + (let ((prev (point))) + (while (and + (= (c-backward-token-2 1 nil closest-lim) 0) + (eq (char-syntax (char-after)) ?w)) + (setq prev (point))) + (goto-char prev) + (not (c-at-statement-start-p))) + ;; Also, in Pike we treat it as an + ;; in-expression class if it's used in an + ;; object clone expression. + (save-excursion + (and check-at-end + (c-major-mode-is 'pike-mode) + (progn (goto-char block-follows) + (zerop (c-forward-token-2 1 t))) + (eq (char-after) ?\()))) + (cons 'inexpr-class (point)))) + ((c-keyword-member kw-sym 'c-inexpr-block-kwds) + (when (not passed-paren) + (cons 'inexpr-statement (point)))) + ((c-keyword-member kw-sym 'c-lambda-kwds) + (when (or (not passed-paren) + (eq passed-paren ?\()) + (cons 'inlambda (point)))) + ((c-keyword-member kw-sym 'c-block-stmt-kwds) + nil) + (t + 'maybe))) + + (if (looking-at "\\s(") + (if passed-paren + (if (and (eq passed-paren ?\[) + (eq (char-after) ?\[)) + ;; Accept several square bracket sexps for + ;; Java array initializations. + 'maybe) + (setq passed-paren (char-after)) + 'maybe) + 'maybe)))) + (if (eq res 'maybe) - (when (and block-follows + (when (and c-recognize-paren-inexpr-blocks + block-follows containing-sexp (eq (char-after containing-sexp) ?\()) (goto-char containing-sexp) @@ -5174,12 +6931,15 @@ (c-looking-at-special-brace-list))) nil (cons 'inexpr-statement (point)))) + res)))) (defun c-looking-at-inexpr-block-backward (paren-state) ;; Returns non-nil if we're looking at the end of an in-expression ;; block, otherwise the same as `c-looking-at-inexpr-block'. ;; PAREN-STATE is the paren state relevant at the current position. + ;; + ;; This function might do hidden buffer changes. (save-excursion ;; We currently only recognize a block. (let ((here (point)) @@ -5196,31 +6956,6 @@ paren-state) containing-sexp))))) -(defun c-narrow-out-enclosing-class (paren-state lim) - ;; Narrow the buffer so that the enclosing class is hidden. Uses - ;; and returns the value from c-search-uplist-for-classkey. - (setq paren-state (c-whack-state-after (point) paren-state)) - (let (inclass-p) - (and paren-state - (setq inclass-p (c-search-uplist-for-classkey paren-state)) - (narrow-to-region - (progn - (goto-char (1+ (aref inclass-p 1))) - (c-skip-ws-forward lim) - ;; if point is now left of the class opening brace, we're - ;; hosed, so try a different tact - (if (<= (point) (aref inclass-p 1)) - (progn - (goto-char (1+ (aref inclass-p 1))) - (c-forward-syntactic-ws lim))) - (point)) - ;; end point is the end of the current line - (progn - (goto-char lim) - (c-point 'eol)))) - ;; return the class vector - inclass-p)) - ;; `c-guess-basic-syntax' and the functions that precedes it below ;; implements the main decision tree for determining the syntactic @@ -5247,7 +6982,6 @@ (defun c-add-stmt-syntax (syntax-symbol syntax-extra-args stop-at-boi-only - at-block-start containing-sexp paren-state) ;; Do the generic processing to anchor the given syntax symbol on @@ -5264,177 +6998,170 @@ ;; SYNTAX-EXTRA-ARGS are a list of the extra arguments for the ;; syntax symbol. They are appended after the anchor point. ;; - ;; If STOP-AT-BOI-ONLY is nil, we might stop in the middle of the - ;; line if another statement precedes the current one on this line. - ;; - ;; If AT-BLOCK-START is non-nil, point is taken to be at the - ;; beginning of a block or brace list, which then might be nested - ;; inside an expression. If AT-BLOCK-START is nil, this is found - ;; out by checking whether the character at point is "{" or not. + ;; If STOP-AT-BOI-ONLY is nil, we can stop in the middle of the line + ;; if the current statement starts there. + ;; + ;; Note: It's not a problem if PAREN-STATE "overshoots" + ;; CONTAINING-SEXP, i.e. contains info about parens further down. + ;; + ;; This function might do hidden buffer changes. + (if (= (point) (c-point 'boi)) ;; This is by far the most common case, so let's give it special ;; treatment. (apply 'c-add-syntax syntax-symbol (point) syntax-extra-args) - (let ((savepos (point)) - (syntax-last c-syntactic-context) + (let ((syntax-last c-syntactic-context) (boi (c-point 'boi)) - (prev-paren (if at-block-start ?{ (char-after))) - step-type step-tmp at-comment special-list) + ;; Set when we're on a label, so that we don't stop there. + ;; FIXME: To be complete we should check if we're on a label + ;; now at the start. + on-label) + (apply 'c-add-syntax syntax-symbol nil syntax-extra-args) - ;; Begin by skipping any labels and containing statements that - ;; are on the same line. - (while (and (/= (point) boi) - (if (memq (setq step-tmp - (c-beginning-of-statement-1 boi nil t)) - '(up label)) - t - (goto-char savepos) - nil) - (/= (point) savepos)) - (setq savepos (point) - step-type step-tmp)) - - (catch 'done - ;; Loop if we have to back out of the containing block. - (while - (progn - - ;; Loop if we have to back up another statement. - (while - (progn - - ;; Always start by skipping over any comments that - ;; stands between the statement and boi. - (while (and (/= (setq savepos (point)) boi) - (c-backward-single-comment)) - (setq at-comment t - boi (c-point 'boi))) - (goto-char savepos) - - (and - (or at-comment - (eq step-type 'label) - (/= savepos boi)) - - (let ((save-step-type step-type)) - ;; Current position might not be good enough; - ;; skip backward another statement. - (setq step-type (c-beginning-of-statement-1 - containing-sexp)) - - (if (and (not stop-at-boi-only) - (/= savepos boi) - (memq step-type '(up previous))) - ;; If stop-at-boi-only is nil, we shouldn't - ;; back up over previous or containing - ;; statements to try to reach boi, so go - ;; back to the last position and exit. + ;; Loop while we have to back out of containing blocks. + (while + (and + (catch 'back-up-block + + ;; Loop while we have to back up statements. + (while (or (/= (point) boi) + on-label + (looking-at c-comment-start-regexp)) + + ;; Skip past any comments that stands between the + ;; statement start and boi. + (let ((savepos (point))) + (while (and (/= savepos boi) + (c-backward-single-comment)) + (setq savepos (point) + boi (c-point 'boi))) + (goto-char savepos)) + + ;; Skip to the beginning of this statement or backward + ;; another one. + (let ((old-pos (point)) + (old-boi boi) + (step-type (c-beginning-of-statement-1 containing-sexp))) + (setq boi (c-point 'boi) + on-label (eq step-type 'label)) + + (cond ((= (point) old-pos) + ;; If we didn't move we're at the start of a block and + ;; have to continue outside it. + (throw 'back-up-block t)) + + ((and (eq step-type 'up) + (>= (point) old-boi) + (looking-at "else\\>[^_]") + (save-excursion + (goto-char old-pos) + (looking-at "if\\>[^_]"))) + ;; Special case to avoid deeper and deeper indentation + ;; of "else if" clauses. + ) + + ((and (not stop-at-boi-only) + (/= old-pos old-boi) + (memq step-type '(up previous))) + ;; If stop-at-boi-only is nil, we shouldn't back up + ;; over previous or containing statements to try to + ;; reach boi, so go back to the last position and + ;; exit. + (goto-char old-pos) + (throw 'back-up-block nil)) + + (t + (if (and (not stop-at-boi-only) + (memq step-type '(up previous beginning))) + ;; If we've moved into another statement then we + ;; should no longer try to stop in the middle of a + ;; line. + (setq stop-at-boi-only t)) + + ;; Record this as a substatement if we skipped up one + ;; level. + (when (eq step-type 'up) + (c-add-syntax 'substatement nil)))) + ))) + + containing-sexp) + + ;; Now we have to go out of this block. + (goto-char containing-sexp) + + ;; Don't stop in the middle of a special brace list opener + ;; like "({". + (when c-special-brace-lists + (let ((special-list (c-looking-at-special-brace-list))) + (when (and special-list + (< (car (car special-list)) (point))) + (setq containing-sexp (car (car special-list))) + (goto-char containing-sexp)))) + + (setq paren-state (c-whack-state-after containing-sexp paren-state) + containing-sexp (c-most-enclosing-brace paren-state) + boi (c-point 'boi)) + + ;; Analyze the construct in front of the block we've stepped out + ;; from and add the right syntactic element for it. + (let ((paren-pos (point)) + (paren-char (char-after)) + step-type) + + (if (eq paren-char ?\() + ;; Stepped out of a parenthesis block, so we're in an + ;; expression now. + (progn + (when (/= paren-pos boi) + (if (and c-recognize-paren-inexpr-blocks (progn - (goto-char savepos) - nil) - (if (and (not stop-at-boi-only) - (memq step-type '(up previous beginning))) - ;; If we've moved into another statement - ;; then we should no longer try to stop - ;; after boi. - (setq stop-at-boi-only t)) - - ;; Record this a substatement if we skipped up - ;; one level, but not if we're still on the - ;; same line. This so e.g. a sequence of "else - ;; if" clauses won't indent deeper and deeper. - (when (and (eq step-type 'up) - (< (point) boi)) - (c-add-syntax 'substatement nil)) - - (setq boi (c-point 'boi)) - (if (= (point) savepos) - (progn - (setq step-type save-step-type) - nil) - t))))) - - (setq savepos (point) - at-comment nil)) - (setq at-comment nil) - - (when (and containing-sexp - (if (memq step-type '(nil same)) - (/= (point) boi) - (eq step-type 'label))) - (goto-char containing-sexp) - - ;; Don't stop in the middle of a special brace list opener - ;; like "({". - (when (and c-special-brace-lists - (setq special-list - (c-looking-at-special-brace-list))) - (setq containing-sexp (car (car special-list))) - (goto-char containing-sexp)) - - (setq paren-state (c-whack-state-after containing-sexp - paren-state) - containing-sexp (c-most-enclosing-brace paren-state) - savepos (point) - boi (c-point 'boi)) - - (if (eq (setq prev-paren (char-after)) ?\() - (progn - (c-backward-syntactic-ws containing-sexp) - (when (/= savepos boi) - (if (and (or (not (looking-at "\\>")) - (not (c-on-identifier))) - (not special-list) - (save-excursion - (c-forward-syntactic-ws) - (forward-char) - (c-forward-syntactic-ws) - (eq (char-after) ?{))) - ;; We're in an in-expression statement. - ;; This syntactic element won't get an anchor pos. - (c-add-syntax 'inexpr-statement) - (c-add-syntax 'arglist-cont-nonempty nil savepos))) - (goto-char (max boi - (if containing-sexp - (1+ containing-sexp) - (point-min)))) - (setq step-type 'same)) - (setq step-type - (c-beginning-of-statement-1 containing-sexp))) - - (let ((at-bod (and (eq step-type 'same) - (/= savepos (point)) - (eq prev-paren ?{)))) - - (when (= savepos boi) - ;; If the open brace was at boi, we're always - ;; done. The c-beginning-of-statement-1 call - ;; above is necessary anyway, to decide the type - ;; of block-intro to add. - (goto-char savepos) - (setq savepos nil)) - - (when (eq prev-paren ?{) - (c-add-syntax (if at-bod - 'defun-block-intro - 'statement-block-intro) - nil)) - - (when (and (not at-bod) savepos) - ;; Loop if the brace wasn't at boi, and we didn't - ;; arrive at a defun block. - (if (eq step-type 'same) - ;; Avoid backing up another sexp if the point - ;; we're at now is found to be good enough in - ;; the loop above. - (setq step-type nil)) - (if (and (not stop-at-boi-only) - (memq step-type '(up previous beginning))) - (setq stop-at-boi-only t)) - (setq boi (c-point 'boi))))) - ))) + (c-backward-syntactic-ws containing-sexp) + (or (not (looking-at "\\>")) + (not (c-on-identifier)))) + (save-excursion + (goto-char (1+ paren-pos)) + (c-forward-syntactic-ws) + (eq (char-after) ?{))) + ;; Stepped out of an in-expression statement. This + ;; syntactic element won't get an anchor pos. + (c-add-syntax 'inexpr-statement) + + ;; A parenthesis normally belongs to an arglist. + (c-add-syntax 'arglist-cont-nonempty nil paren-pos))) + + (goto-char (max boi + (if containing-sexp + (1+ containing-sexp) + (point-min)))) + (setq step-type 'same + on-label nil)) + + (setq step-type (c-beginning-of-statement-1 containing-sexp) + on-label (eq step-type 'label)) + + (if (and (eq step-type 'same) + (/= paren-pos (point))) + (save-excursion + (goto-char paren-pos) + (let ((inexpr (c-looking-at-inexpr-block + (c-safe-position containing-sexp + paren-state) + containing-sexp))) + (if (and inexpr + (not (eq (car inexpr) 'inlambda))) + (c-add-syntax 'statement-block-intro nil) + (c-add-syntax 'defun-block-intro nil)))) + (c-add-syntax 'statement-block-intro nil))) + + (if (= paren-pos boi) + ;; Always done if the open brace was at boi. The + ;; c-beginning-of-statement-1 call above is necessary + ;; anyway, to decide the type of block-intro to add. + (goto-char paren-pos) + (setq boi (c-point 'boi))) + )) ;; Fill in the current point as the anchor for all the symbols ;; added above. @@ -5443,30 +7170,33 @@ (if (cdr (car p)) (setcar (cdr (car p)) (point))) (setq p (cdr p)))) - ))) -(defun c-add-class-syntax (symbol classkey paren-state) +(defun c-add-class-syntax (symbol + containing-decl-open + containing-decl-start + containing-decl-kwd + paren-state) ;; The inclass and class-close syntactic symbols are added in ;; several places and some work is needed to fix everything. ;; Therefore it's collected here. - (save-restriction - (widen) - (let (inexpr anchor containing-sexp) - (goto-char (aref classkey 1)) - (if (and (eq symbol 'inclass) (= (point) (c-point 'boi))) - (c-add-syntax symbol (setq anchor (point))) - (c-add-syntax symbol (setq anchor (aref classkey 0))) - (if (and c-opt-inexpr-class-key - (setq containing-sexp (c-most-enclosing-brace paren-state - (point)) - inexpr (cdr (c-looking-at-inexpr-block - (c-safe-position containing-sexp - paren-state) - containing-sexp))) - (/= inexpr (c-point 'boi inexpr))) - (c-add-syntax 'inexpr-class))) - anchor))) + ;; + ;; This function might do hidden buffer changes. + (goto-char containing-decl-open) + (if (and (eq symbol 'inclass) (= (point) (c-point 'boi))) + (progn + (c-add-syntax symbol containing-decl-open) + containing-decl-open) + (goto-char containing-decl-start) + ;; Ought to use `c-add-stmt-syntax' instead of backing up to boi + ;; here, but we have to do like this for compatibility. + (back-to-indentation) + (c-add-syntax symbol (point)) + (if (and (c-keyword-member containing-decl-kwd + 'c-inexpr-class-kwds) + (/= containing-decl-start (c-point 'boi containing-decl-start))) + (c-add-syntax 'inexpr-class)) + (point))) (defun c-guess-continued-construct (indent-point char-after-ip @@ -5476,6 +7206,8 @@ ;; This function contains the decision tree reached through both ;; cases 18 and 10. It's a continued statement or top level ;; construct of some kind. + ;; + ;; This function might do hidden buffer changes. (let (special-brace-list) (goto-char indent-point) @@ -5492,11 +7224,9 @@ (cond ;; CASE B.1: class-open ((save-excursion - (skip-chars-forward "{") - (let ((decl (c-search-uplist-for-classkey (c-parse-state)))) - (and decl - (setq beg-of-same-or-containing-stmt (aref decl 0))) - )) + (and (eq (char-after) ?{) + (c-looking-at-decl-block containing-sexp t) + (setq beg-of-same-or-containing-stmt (point)))) (c-add-syntax 'class-open beg-of-same-or-containing-stmt)) ;; CASE B.2: brace-list-open @@ -5518,26 +7248,23 @@ ;; for the auto newline feature. 'brace-list-open 'statement-cont) - nil nil nil + nil nil containing-sexp paren-state)) ;; CASE B.3: The body of a function declared inside a normal ;; block. Can occur e.g. in Pike and when using gcc ;; extensions, but watch out for macros followed by blocks. ;; C.f. cases E, 16F and 17G. - ((and (not (c-looking-at-bos)) + ((and (not (c-at-statement-start-p)) (eq (c-beginning-of-statement-1 containing-sexp nil nil t) 'same) (save-excursion - ;; Look for a type followed by a symbol, i.e. the start of a - ;; function declaration. Doesn't work for declarations like - ;; "int *foo() ..."; we'd need to refactor the more competent - ;; analysis in `c-font-lock-declarations' for that. - (and (c-forward-type) - (progn - (c-forward-syntactic-ws) - (looking-at c-symbol-start))))) - (c-add-stmt-syntax 'defun-open nil t nil + (let ((c-recognize-typeless-decls nil)) + ;; Turn off recognition of constructs that lacks a + ;; type in this case, since that's more likely to be + ;; a macro followed by a block. + (c-forward-decl-or-cast-1 (c-point 'bosws) nil nil)))) + (c-add-stmt-syntax 'defun-open nil t containing-sexp paren-state)) ;; CASE B.4: Continued statement with block open. The most @@ -5547,7 +7274,7 @@ ;; followed by a block which makes it very similar to a ;; statement with a substatement block. (t - (c-add-stmt-syntax 'substatement-open nil nil nil + (c-add-stmt-syntax 'substatement-open nil nil containing-sexp paren-state)) )) @@ -5577,94 +7304,89 @@ ;; prototype in a code block without resorting to this. (c-forward-syntactic-ws) (eq (char-after) ?{)) - (not (c-looking-at-bos)) + (not (c-at-statement-start-p)) (eq (c-beginning-of-statement-1 containing-sexp nil nil t) 'same) (save-excursion - ;; Look for a type followed by a symbol, i.e. the start of a - ;; function declaration. Doesn't work for declarations like "int - ;; *foo() ..."; we'd need to refactor the more competent analysis - ;; in `c-font-lock-declarations' for that. - (and (c-forward-type) - (progn - (c-forward-syntactic-ws) - (looking-at c-symbol-start))))) - (c-add-stmt-syntax 'func-decl-cont nil t nil + (let ((c-recognize-typeless-decls nil)) + ;; Turn off recognition of constructs that lacks a + ;; type in this case, since that's more likely to be + ;; a macro followed by a block. + (c-forward-decl-or-cast-1 (c-point 'bosws) nil nil)))) + (c-add-stmt-syntax 'func-decl-cont nil t containing-sexp paren-state)) ;; CASE D: continued statement. (t (c-beginning-of-statement-1 containing-sexp) - (c-add-stmt-syntax 'statement-cont nil nil nil + (c-add-stmt-syntax 'statement-cont nil nil containing-sexp paren-state)) ))) +;; The next autoload was added by RMS on 2005/8/9 - don't know why (ACM, +;; 2005/11/29). ;;;###autoload (defun c-guess-basic-syntax () - "Return the syntactic context of the current line. -This function does not do any hidden buffer changes." + "Return the syntactic context of the current line." (save-excursion - (save-restriction (beginning-of-line) (c-save-buffer-state ((indent-point (point)) (case-fold-search nil) + ;; A whole ugly bunch of various temporary variables. Have + ;; to declare them here since it's not possible to declare + ;; a variable with only the scope of a cond test and the + ;; following result clauses, and most of this function is a + ;; single gigantic cond. :P + literal char-before-ip before-ws-ip char-after-ip macro-start + in-macro-expr c-syntactic-context placeholder c-in-literal-cache + step-type tmpsymbol keyword injava-inher special-brace-list tmp-pos + ;; The following record some positions for the containing + ;; declaration block if we're directly within one: + ;; `containing-decl-open' is the position of the open + ;; brace. `containing-decl-start' is the start of the + ;; declaration. `containing-decl-kwd' is the keyword + ;; symbol of the keyword that tells what kind of block it + ;; is. + containing-decl-open + containing-decl-start + containing-decl-kwd + ;; The open paren of the closest surrounding sexp or nil if + ;; there is none. + containing-sexp + ;; The position after the closest preceding brace sexp + ;; (nested sexps are ignored), or the position after + ;; `containing-sexp' if there is none, or (point-min) if + ;; `containing-sexp' is nil. + lim + ;; The paren state outside `containing-sexp', or at + ;; `indent-point' if `containing-sexp' is nil. (paren-state (c-parse-state)) - literal containing-sexp char-before-ip char-after-ip lim - c-syntactic-context placeholder c-in-literal-cache step-type - tmpsymbol keyword injava-inher special-brace-list - ;; narrow out any enclosing class or extern "C" block - (inclass-p (c-narrow-out-enclosing-class paren-state - indent-point)) - ;; `c-state-cache' is shadowed here so that we don't - ;; throw it away due to the narrowing that might be done - ;; by the function above. That means we must not do any - ;; changes during the execution of this function, since - ;; `c-invalidate-state-cache' then would change this local - ;; variable and leave a bogus value in the global one. - (c-state-cache (if inclass-p - (c-whack-state-before (point-min) paren-state) - paren-state)) - (c-state-cache-start (point-min)) - inenclosing-p macro-start in-macro-expr ;; There's always at most one syntactic element which got - ;; a relpos. It's stored in syntactic-relpos. + ;; an anchor pos. It's stored in syntactic-relpos. syntactic-relpos (c-stmt-delim-chars c-stmt-delim-chars)) - ;; Check for meta top-level enclosing constructs such as - ;; extern language definitions. - (save-excursion - (save-restriction - (widen) - (when (and inclass-p - (progn - (goto-char (aref inclass-p 0)) - (looking-at c-other-decl-block-key))) - (setq inenclosing-p (match-string 1)) - (if (string-equal inenclosing-p "extern") - ;; Compatibility with legacy choice of name for the - ;; extern-lang syntactic symbols. - (setq inenclosing-p "extern-lang"))))) - - ;; Init some position variables: - ;; - ;; containing-sexp is the open paren of the closest - ;; surrounding sexp or nil if there is none that hasn't been - ;; narrowed out. - ;; - ;; lim is the position after the closest preceding brace sexp - ;; (nested sexps are ignored), or the position after - ;; containing-sexp if there is none, or (point-min) if - ;; containing-sexp is nil. - ;; - ;; c-state-cache is the state from c-parse-state at - ;; indent-point, without any parens outside the region - ;; narrowed by c-narrow-out-enclosing-class. - ;; - ;; paren-state is the state from c-parse-state outside - ;; containing-sexp, or at indent-point if containing-sexp is - ;; nil. paren-state is not limited to the narrowed region, as - ;; opposed to c-state-cache. + + ;; Check if we're directly inside an enclosing declaration + ;; level block. + (when (and (setq containing-sexp + (c-most-enclosing-brace paren-state)) + (progn + (goto-char containing-sexp) + (eq (char-after) ?{)) + (setq placeholder + (c-looking-at-decl-block + (c-most-enclosing-brace paren-state + containing-sexp) + t))) + (setq containing-decl-open containing-sexp + containing-decl-start (point) + containing-sexp nil) + (goto-char placeholder) + (setq containing-decl-kwd (and (looking-at c-keywords-regexp) + (c-keyword-sym (match-string 1))))) + + ;; Init some position variables. (if c-state-cache (progn (setq containing-sexp (car paren-state) @@ -5697,7 +7419,8 @@ ;; the most likely position to perform the majority of tests (goto-char indent-point) (c-backward-syntactic-ws lim) - (setq char-before-ip (char-before)) + (setq before-ws-ip (point) + char-before-ip (char-before)) (goto-char indent-point) (skip-chars-forward " \t") (setq char-after-ip (char-after)) @@ -5707,9 +7430,11 @@ ;; now figure out syntactic qualities of the current line (cond + ;; CASE 1: in a string. ((eq literal 'string) (c-add-syntax 'string (c-point 'bopl))) + ;; CASE 2: in a C or C++ style comment. ((and (memq literal '(c c++)) ;; This is a kludge for XEmacs where we use @@ -5722,6 +7447,7 @@ ;; we're inside a comment. (setq placeholder (c-literal-limits lim))) (c-add-syntax literal (car placeholder))) + ;; CASE 3: in a cpp preprocessor macro continuation. ((and (save-excursion (when (c-beginning-of-macro) @@ -5747,11 +7473,13 @@ nil))))) (c-add-syntax tmpsymbol macro-start) (setq macro-start nil)) + ;; CASE 11: an else clause? ((looking-at "else\\>[^_]") (c-beginning-of-statement-1 containing-sexp) - (c-add-stmt-syntax 'else-clause nil t nil + (c-add-stmt-syntax 'else-clause nil t containing-sexp paren-state)) + ;; CASE 12: while closure of a do/while construct? ((and (looking-at "while\\>[^_]") (save-excursion @@ -5759,8 +7487,9 @@ 'beginning) (setq placeholder (point))))) (goto-char placeholder) - (c-add-stmt-syntax 'do-while-closure nil t nil + (c-add-stmt-syntax 'do-while-closure nil t containing-sexp paren-state)) + ;; CASE 13: A catch or finally clause? This case is simpler ;; than if-else and do-while, because a block is required ;; after every try, catch and finally. @@ -5782,14 +7511,14 @@ (looking-at "\\(try\\|catch\\)\\>[^_]") (setq placeholder (point)))) (goto-char placeholder) - (c-add-stmt-syntax 'catch-clause nil t nil + (c-add-stmt-syntax 'catch-clause nil t containing-sexp paren-state)) + ;; CASE 18: A substatement we can recognize by keyword. ((save-excursion (and c-opt-block-stmt-key - (if (c-mode-is-new-awk-p) - (c-awk-prev-line-incomplete-p containing-sexp) ; ACM 2002/3/29 - (not (eq char-before-ip ?\;))) + (not (eq char-before-ip ?\;)) + (not (c-at-vsemi-p before-ws-ip)) (not (memq char-after-ip '(?\) ?\] ?,))) (or (not (eq char-before-ip ?})) (c-looking-at-inexpr-block-backward c-state-cache)) @@ -5826,23 +7555,25 @@ (and (zerop (c-forward-token-2 1 nil)) (eq (char-after) ?\()) (looking-at c-opt-block-stmt-key)))) + (if (eq step-type 'up) ;; CASE 18A: Simple substatement. (progn (goto-char placeholder) (cond ((eq char-after-ip ?{) - (c-add-stmt-syntax 'substatement-open nil nil nil + (c-add-stmt-syntax 'substatement-open nil nil containing-sexp paren-state)) ((save-excursion (goto-char indent-point) (back-to-indentation) - (looking-at c-label-key)) - (c-add-stmt-syntax 'substatement-label nil nil nil + (c-forward-label)) + (c-add-stmt-syntax 'substatement-label nil nil containing-sexp paren-state)) (t - (c-add-stmt-syntax 'substatement nil nil nil + (c-add-stmt-syntax 'substatement nil nil containing-sexp paren-state)))) + ;; CASE 18B: Some other substatement. This is shared ;; with case 10. (c-guess-continued-construct indent-point @@ -5850,14 +7581,66 @@ placeholder lim paren-state))) + + ;; CASE 14: A case or default label + ((looking-at c-label-kwds-regexp) + (if containing-sexp + (progn + (goto-char containing-sexp) + (setq lim (c-most-enclosing-brace c-state-cache + containing-sexp)) + (c-backward-to-block-anchor lim) + (c-add-stmt-syntax 'case-label nil t lim paren-state)) + ;; Got a bogus label at the top level. In lack of better + ;; alternatives, anchor it on (point-min). + (c-add-syntax 'case-label (point-min)))) + + ;; CASE 15: any other label + ((save-excursion + (back-to-indentation) + (and (not (looking-at c-syntactic-ws-start)) + (c-forward-label))) + (cond (containing-decl-open + (setq placeholder (c-add-class-syntax 'inclass + containing-decl-open + containing-decl-start + containing-decl-kwd + paren-state)) + ;; Append access-label with the same anchor point as + ;; inclass gets. + (c-append-syntax 'access-label placeholder)) + + (containing-sexp + (goto-char containing-sexp) + (setq lim (c-most-enclosing-brace c-state-cache + containing-sexp)) + (save-excursion + (setq tmpsymbol + (if (and (eq (c-beginning-of-statement-1 lim) 'up) + (looking-at "switch\\>[^_]")) + ;; If the surrounding statement is a switch then + ;; let's analyze all labels as switch labels, so + ;; that they get lined up consistently. + 'case-label + 'label))) + (c-backward-to-block-anchor lim) + (c-add-stmt-syntax tmpsymbol nil t lim paren-state)) + + (t + ;; A label on the top level. Treat it as a class + ;; context. (point-min) is the closest we get to the + ;; class open brace. + (c-add-syntax 'access-label (point-min))))) + ;; CASE 4: In-expression statement. C.f. cases 7B, 16A and ;; 17E. - ((and (or c-opt-inexpr-class-key - c-opt-inexpr-block-key - c-opt-lambda-key) - (setq placeholder (c-looking-at-inexpr-block - (c-safe-position containing-sexp paren-state) - containing-sexp))) + ((setq placeholder (c-looking-at-inexpr-block + (c-safe-position containing-sexp paren-state) + containing-sexp + ;; Have to turn on the heuristics after + ;; the point even though it doesn't work + ;; very well. C.f. test case class-16.pike. + t)) (setq tmpsymbol (assq (car placeholder) '((inexpr-class . class-open) (inexpr-statement . block-open)))) @@ -5872,14 +7655,16 @@ 'lambda-intro-cont))) (goto-char (cdr placeholder)) (back-to-indentation) - (c-add-stmt-syntax tmpsymbol nil t nil + (c-add-stmt-syntax tmpsymbol nil t (c-most-enclosing-brace c-state-cache (point)) - (c-whack-state-after (point) paren-state)) + paren-state) (unless (eq (point) (cdr placeholder)) (c-add-syntax (car placeholder)))) - ;; CASE 5: Line is at top level. - ((null containing-sexp) + + ;; CASE 5: Line is inside a declaration level block or at top level. + ((or containing-decl-open (null containing-sexp)) (cond + ;; CASE 5A: we are looking at a defun, brace list, class, ;; or inline-inclass method opening brace ((setq special-brace-list @@ -5887,36 +7672,36 @@ (c-looking-at-special-brace-list)) (eq char-after-ip ?{))) (cond + ;; CASE 5A.1: Non-class declaration block open. ((save-excursion + (let (tmp) + (and (eq char-after-ip ?{) + (setq tmp (c-looking-at-decl-block containing-sexp t)) + (progn + (setq placeholder (point)) + (goto-char tmp) + (looking-at c-symbol-key)) + (c-keyword-member + (c-keyword-sym (setq keyword (match-string 0))) + 'c-other-block-decl-kwds)))) + (goto-char placeholder) + (c-add-stmt-syntax + (if (string-equal keyword "extern") + ;; Special case for extern-lang-open. + 'extern-lang-open + (intern (concat keyword "-open"))) + nil t containing-sexp paren-state)) + + ;; CASE 5A.2: we are looking at a class opening brace + ((save-excursion (goto-char indent-point) (skip-chars-forward " \t") - (and (c-safe (c-backward-sexp 2) t) - (looking-at c-other-decl-block-key) - (setq keyword (match-string 1) - placeholder (point)) - (if (string-equal keyword "extern") - ;; Special case for extern-lang-open. The - ;; check for a following string is disabled - ;; since it doesn't disambiguate anything. - (and ;;(progn - ;; (c-forward-sexp 1) - ;; (c-forward-syntactic-ws) - ;; (eq (char-after) ?\")) - (setq tmpsymbol 'extern-lang-open)) - (setq tmpsymbol (intern (concat keyword "-open")))) - )) - (goto-char placeholder) - (c-add-syntax tmpsymbol (c-point 'boi))) - ;; CASE 5A.2: we are looking at a class opening brace - ((save-excursion - (goto-char indent-point) - (skip-chars-forward " \t{") - (let ((decl (c-search-uplist-for-classkey (c-parse-state)))) - (and decl - (setq placeholder (aref decl 0))) - )) + (and (eq (char-after) ?{) + (c-looking-at-decl-block containing-sexp t) + (setq placeholder (point)))) (c-add-syntax 'class-open placeholder)) + ;; CASE 5A.3: brace list open ((save-excursion (c-beginning-of-decl-1 lim) @@ -5958,65 +7743,69 @@ (c-beginning-of-statement-1 lim) (c-add-syntax 'topmost-intro-cont (c-point 'boi))) (c-add-syntax 'brace-list-open placeholder))) + ;; CASE 5A.4: inline defun open - ((and inclass-p (not inenclosing-p)) + ((and containing-decl-open + (not (c-keyword-member containing-decl-kwd + 'c-other-block-decl-kwds))) (c-add-syntax 'inline-open) - (c-add-class-syntax 'inclass inclass-p paren-state)) + (c-add-class-syntax 'inclass + containing-decl-open + containing-decl-start + containing-decl-kwd + paren-state)) + ;; CASE 5A.5: ordinary defun open (t (goto-char placeholder) - (if (or inclass-p macro-start) + (if (or containing-decl-open macro-start) (c-add-syntax 'defun-open (c-point 'boi)) ;; Bogus to use bol here, but it's the legacy. (c-add-syntax 'defun-open (c-point 'bol))) ))) - ;; CASE 5B: first K&R arg decl or member init - ((c-just-after-func-arglist-p lim) + + ;; CASE 5B: After a function header but before the body (or + ;; the ending semicolon if there's no body). + ((save-excursion + (when (setq placeholder (c-just-after-func-arglist-p lim)) + (setq tmp-pos (point)))) (cond - ;; CASE 5B.1: a member init - ((or (eq char-before-ip ?:) - (eq char-after-ip ?:)) - ;; this line should be indented relative to the beginning - ;; of indentation for the topmost-intro line that contains - ;; the prototype's open paren - ;; TBD: is the following redundant? - (if (eq char-before-ip ?:) - (forward-char -1)) - (c-backward-syntactic-ws lim) - ;; TBD: is the preceding redundant? - (if (eq (char-before) ?:) - (progn (forward-char -1) - (c-backward-syntactic-ws lim))) - (if (eq (char-before) ?\)) - (c-backward-sexp 1)) - (setq placeholder (point)) - (save-excursion - (and (c-safe (c-backward-sexp 1) t) - (looking-at "throw[^_]") - (c-safe (c-backward-sexp 1) t) - (setq placeholder (point)))) - (goto-char placeholder) - (c-add-syntax 'member-init-intro (c-point 'boi)) - ;; we don't need to add any class offset since this - ;; should be relative to the ctor's indentation - ) + + ;; CASE 5B.1: Member init list. + ((eq (char-after tmp-pos) ?:) + (if (or (> tmp-pos indent-point) + (= (c-point 'bosws) (1+ tmp-pos))) + (progn + ;; There is no preceding member init clause. + ;; Indent relative to the beginning of indentation + ;; for the topmost-intro line that contains the + ;; prototype's open paren. + (goto-char placeholder) + (c-add-syntax 'member-init-intro (c-point 'boi))) + ;; Indent relative to the first member init clause. + (goto-char (1+ tmp-pos)) + (c-forward-syntactic-ws) + (c-add-syntax 'member-init-cont (point)))) + ;; CASE 5B.2: K&R arg decl intro ((and c-recognize-knr-p (c-in-knr-argdecl lim)) (c-beginning-of-statement-1 lim) (c-add-syntax 'knr-argdecl-intro (c-point 'boi)) - (if inclass-p - (c-add-class-syntax 'inclass inclass-p paren-state))) - ;; CASE 5B.3: Inside a member init list. - ((c-beginning-of-member-init-list lim) - (c-forward-syntactic-ws) - (c-add-syntax 'member-init-cont (point))) + (if containing-decl-open + (c-add-class-syntax 'inclass + containing-decl-open + containing-decl-start + containing-decl-kwd + paren-state))) + ;; CASE 5B.4: Nether region after a C++ or Java func ;; decl, which could include a `throws' declaration. (t (c-beginning-of-statement-1 lim) (c-add-syntax 'func-decl-cont (c-point 'boi)) ))) + ;; CASE 5C: inheritance line. could be first inheritance ;; line, or continuation of a multiple inheritance ((or (and (c-major-mode-is 'c++-mode) @@ -6061,6 +7850,7 @@ (point))) )) (cond + ;; CASE 5C.1: non-hanging colon on an inher intro ((eq char-after-ip ?:) (c-beginning-of-statement-1 lim) @@ -6068,12 +7858,18 @@ ;; don't add inclass symbol since relative point already ;; contains any class offset ) + ;; CASE 5C.2: hanging colon on an inher intro ((eq char-before-ip ?:) (c-beginning-of-statement-1 lim) (c-add-syntax 'inher-intro (c-point 'boi)) - (if inclass-p - (c-add-class-syntax 'inclass inclass-p paren-state))) + (if containing-decl-open + (c-add-class-syntax 'inclass + containing-decl-open + containing-decl-start + containing-decl-kwd + paren-state))) + ;; CASE 5C.3: in a Java implements/extends (injava-inher (let ((where (cdr injava-inher)) @@ -6089,6 +7885,7 @@ (c-beginning-of-statement-1 lim) (point)))) ))) + ;; CASE 5C.4: a continued inheritance line (t (c-beginning-of-inheritance-list lim) @@ -6096,77 +7893,67 @@ ;; don't add inclass symbol since relative point already ;; contains any class offset ))) + ;; CASE 5D: this could be a top-level initialization, a ;; member init list continuation, or a template argument ;; list continuation. - ((c-with-syntax-table (if (c-major-mode-is 'c++-mode) - c++-template-syntax-table - (syntax-table)) - (save-excursion - ;; Note: We use the fact that lim is always after any - ;; preceding brace sexp. - (while (and (zerop (c-backward-token-2 1 t lim)) - (or (not (looking-at "[;<,=]")) - (and c-overloadable-operators-regexp - (looking-at c-overloadable-operators-regexp) - (save-excursion - (c-backward-token-2 1 nil lim) - (looking-at "operator\\>[^_]")))))) - (or (memq (char-after) '(?, ?=)) - (and (c-major-mode-is 'c++-mode) - (zerop (c-backward-token-2 1 nil lim)) - (eq (char-after) ?<))))) - (goto-char indent-point) - (setq placeholder - (c-beginning-of-member-init-list lim)) + ((save-excursion + ;; Note: We use the fact that lim always is after any + ;; preceding brace sexp. + (if c-recognize-<>-arglists + (while (and + (progn + (c-syntactic-skip-backward "^;,=<>" lim t) + (> (point) lim)) + (or + (when c-overloadable-operators-regexp + (when (setq placeholder (c-after-special-operator-id lim)) + (goto-char placeholder) + t)) + (cond + ((eq (char-before) ?>) + (or (c-backward-<>-arglist nil lim) + (backward-char)) + t) + ((eq (char-before) ?<) + (backward-char) + (if (save-excursion + (c-forward-<>-arglist nil)) + (progn (forward-char) + nil) + t)) + (t nil))))) + ;; NB: No c-after-special-operator-id stuff in this + ;; clause - we assume only C++ needs it. + (c-syntactic-skip-backward "^;,=" lim t)) + (memq (char-before) '(?, ?= ?<))) (cond - ;; CASE 5D.1: hanging member init colon, but watch out - ;; for bogus matches on access specifiers inside classes. - ((and placeholder - (save-excursion - (setq placeholder (point)) - (c-backward-token-2 1 t lim) - (and (eq (char-after) ?:) - (not (eq (char-before) ?:)))) - (save-excursion - (goto-char placeholder) - (back-to-indentation) - (or - (/= (car (save-excursion - (parse-partial-sexp (point) placeholder))) - 0) - (and - (if c-opt-access-key - (not (looking-at c-opt-access-key)) t) - (not (looking-at c-class-key)) - (if c-opt-bitfield-key - (not (looking-at c-opt-bitfield-key)) t)) - ))) - (goto-char placeholder) - (c-forward-syntactic-ws) - (c-add-syntax 'member-init-cont (point)) - ;; we do not need to add class offset since relative - ;; point is the member init above us - ) - ;; CASE 5D.2: non-hanging member init colon - ((progn - (c-forward-syntactic-ws indent-point) - (eq (char-after) ?:)) - (skip-chars-forward " \t:") - (c-add-syntax 'member-init-cont (point))) + ;; CASE 5D.3: perhaps a template list continuation? ((and (c-major-mode-is 'c++-mode) (save-excursion (save-restriction (c-with-syntax-table c++-template-syntax-table (goto-char indent-point) - (setq placeholder (c-up-list-backward (point))) + (setq placeholder (c-up-list-backward)) (and placeholder (eq (char-after placeholder) ?<)))))) - ;; we can probably indent it just like an arglist-cont - (goto-char placeholder) - (c-beginning-of-statement-1 lim t) - (c-add-syntax 'template-args-cont (c-point 'boi))) + (c-with-syntax-table c++-template-syntax-table + (goto-char placeholder) + (c-beginning-of-statement-1 lim t) + (if (save-excursion + (c-backward-syntactic-ws lim) + (eq (char-before) ?<)) + ;; In a nested template arglist. + (progn + (goto-char placeholder) + (c-syntactic-skip-backward "^,;" lim t) + (c-forward-syntactic-ws)) + (back-to-indentation))) + ;; FIXME: Should use c-add-stmt-syntax, but it's not yet + ;; template aware. + (c-add-syntax 'template-args-cont (point))) + ;; CASE 5D.4: perhaps a multiple inheritance line? ((and (c-major-mode-is 'c++-mode) (save-excursion @@ -6183,6 +7970,7 @@ (eq (char-after) ?:)))) (goto-char placeholder) (c-add-syntax 'inher-cont (c-point 'boi))) + ;; CASE 5D.5: Continuation of the "expression part" of a ;; top level construct. (t @@ -6199,33 +7987,38 @@ ;; the first variable declaration. C.f. case 5N. 'topmost-intro-cont 'statement-cont) - nil nil nil containing-sexp paren-state)) + nil nil containing-sexp paren-state)) )) - ;; CASE 5E: we are looking at a access specifier - ((and inclass-p - c-opt-access-key - (looking-at c-opt-access-key)) - (setq placeholder (c-add-class-syntax 'inclass inclass-p - paren-state)) - ;; Append access-label with the same anchor point as inclass gets. - (c-append-syntax 'access-label placeholder)) + ;; CASE 5F: Close of a non-class declaration level block. - ((and inenclosing-p - (eq char-after-ip ?})) - (c-add-syntax (intern (concat inenclosing-p "-close")) - (aref inclass-p 0))) + ((and (eq char-after-ip ?}) + (c-keyword-member containing-decl-kwd + 'c-other-block-decl-kwds)) + ;; This is inconsistent: Should use `containing-decl-open' + ;; here if it's at boi, like in case 5J. + (goto-char containing-decl-start) + (c-add-stmt-syntax + (if (string-equal (symbol-name containing-decl-kwd) "extern") + ;; Special case for compatibility with the + ;; extern-lang syntactic symbols. + 'extern-lang-close + (intern (concat (symbol-name containing-decl-kwd) + "-close"))) + nil t + (c-most-enclosing-brace paren-state (point)) + paren-state)) + ;; CASE 5G: we are looking at the brace which closes the ;; enclosing nested class decl - ((and inclass-p + ((and containing-sexp (eq char-after-ip ?}) - (save-excursion - (save-restriction - (widen) - (forward-char 1) - (and (c-safe (c-backward-sexp 1) t) - (= (point) (aref inclass-p 1)) - )))) - (c-add-class-syntax 'class-close inclass-p paren-state)) + (eq containing-decl-open containing-sexp)) + (c-add-class-syntax 'class-close + containing-decl-open + containing-decl-start + containing-decl-kwd + paren-state)) + ;; CASE 5H: we could be looking at subsequent knr-argdecls ((and c-recognize-knr-p (not (eq char-before-ip ?})) @@ -6241,6 +8034,7 @@ (< placeholder indent-point)) (goto-char placeholder) (c-add-syntax 'knr-argdecl (point))) + ;; CASE 5I: ObjC method definition. ((and c-opt-method-key (looking-at c-opt-method-key)) @@ -6254,17 +8048,19 @@ ;; directive. (goto-char (point-min))) (c-add-syntax 'objc-method-intro (c-point 'boi))) + ;; CASE 5P: AWK pattern or function or continuation ;; thereof. - ((c-mode-is-new-awk-p) + ((c-major-mode-is 'awk-mode) (setq placeholder (point)) (c-add-stmt-syntax (if (and (eq (c-beginning-of-statement-1) 'same) (/= (point) placeholder)) 'topmost-intro-cont 'topmost-intro) - nil nil nil + nil nil containing-sexp paren-state)) + ;; CASE 5N: At a variable declaration that follows a class ;; definition or some other block declaration that doesn't ;; end at the closing '}'. C.f. case 5D.5. @@ -6273,9 +8069,9 @@ (and (eq (char-before) ?}) (save-excursion (let ((start (point))) - (if paren-state + (if c-state-cache ;; Speed up the backward search a bit. - (goto-char (car (car paren-state)))) + (goto-char (caar c-state-cache))) (c-beginning-of-decl-1 containing-sexp) (setq placeholder (point)) (if (= start (point)) @@ -6284,71 +8080,102 @@ (c-end-of-decl-1) (>= (point) indent-point)))))) (goto-char placeholder) - (c-add-stmt-syntax 'topmost-intro-cont nil nil nil + (c-add-stmt-syntax 'topmost-intro-cont nil nil containing-sexp paren-state)) + + ;; NOTE: The point is at the end of the previous token here. + ;; CASE 5J: we are at the topmost level, make ;; sure we skip back past any access specifiers - ((progn - (while (and inclass-p - c-opt-access-key - (not (bobp)) - (save-excursion - (c-safe (c-backward-sexp 1) t) - (looking-at c-opt-access-key))) - (c-backward-sexp 1) - (c-backward-syntactic-ws lim)) - (or (bobp) - (if (c-mode-is-new-awk-p) - (not (c-awk-prev-line-incomplete-p)) - (memq (char-before) '(?\; ?}))) + ((save-excursion + (setq placeholder (point)) + (or (memq char-before-ip '(?\; ?{ ?} nil)) + (c-at-vsemi-p before-ws-ip) + (when (and (eq char-before-ip ?:) + (eq (c-beginning-of-statement-1 lim) + 'label)) + (c-backward-syntactic-ws lim) + (setq placeholder (point))) (and (c-major-mode-is 'objc-mode) - (progn + (catch 'not-in-directive (c-beginning-of-statement-1 lim) - (eq (char-after) ?@))))) - ;; real beginning-of-line could be narrowed out due to - ;; enclosure in a class block - (save-restriction - (widen) - (c-add-syntax 'topmost-intro (c-point 'bol)) - ;; Using bol instead of boi above is highly bogus, and - ;; it makes our lives hard to remain compatible. :P - (if inclass-p - (progn - (goto-char (aref inclass-p 1)) - (or (= (point) (c-point 'boi)) - (goto-char (aref inclass-p 0))) - (if inenclosing-p - (c-add-syntax (intern (concat "in" inenclosing-p)) - (c-point 'boi)) - (c-add-class-syntax 'inclass inclass-p paren-state)) - )) - (when (and c-syntactic-indentation-in-macros - macro-start - (/= macro-start (c-point 'boi indent-point))) - (c-add-syntax 'cpp-define-intro) - (setq macro-start nil)) - )) + (setq placeholder (point)) + (while (and (c-forward-objc-directive) + (< (point) indent-point)) + (c-forward-syntactic-ws) + (if (>= (point) indent-point) + (throw 'not-in-directive t)) + (setq placeholder (point))) + nil)))) + ;; For historic reasons we anchor at bol of the last + ;; line of the previous declaration. That's clearly + ;; highly bogus and useless, and it makes our lives hard + ;; to remain compatible. :P + (goto-char placeholder) + (c-add-syntax 'topmost-intro (c-point 'bol)) + (if containing-decl-open + (if (c-keyword-member containing-decl-kwd + 'c-other-block-decl-kwds) + (progn + (goto-char containing-decl-open) + (unless (= (point) (c-point 'boi)) + (goto-char containing-decl-start)) + (c-add-stmt-syntax + (if (string-equal (symbol-name containing-decl-kwd) + "extern") + ;; Special case for compatibility with the + ;; extern-lang syntactic symbols. + 'inextern-lang + (intern (concat "in" + (symbol-name containing-decl-kwd)))) + nil t + (c-most-enclosing-brace paren-state (point)) + paren-state)) + (c-add-class-syntax 'inclass + containing-decl-open + containing-decl-start + containing-decl-kwd + paren-state))) + (when (and c-syntactic-indentation-in-macros + macro-start + (/= macro-start (c-point 'boi indent-point))) + (c-add-syntax 'cpp-define-intro) + (setq macro-start nil))) + ;; CASE 5K: we are at an ObjC method definition ;; continuation line. ((and c-opt-method-key (save-excursion - (goto-char indent-point) (c-beginning-of-statement-1 lim) (beginning-of-line) (when (looking-at c-opt-method-key) (setq placeholder (point))))) (c-add-syntax 'objc-method-args-cont placeholder)) + ;; CASE 5L: we are at the first argument of a template ;; arglist that begins on the previous line. - ((eq (char-before) ?<) + ((and c-recognize-<>-arglists + (eq (char-before) ?<) + (not (and c-overloadable-operators-regexp + (c-after-special-operator-id lim)))) (c-beginning-of-statement-1 (c-safe-position (point) paren-state)) (c-add-syntax 'template-args-cont (c-point 'boi))) + ;; CASE 5M: we are at a topmost continuation line (t (c-beginning-of-statement-1 (c-safe-position (point) paren-state)) + (when (c-major-mode-is 'objc-mode) + (setq placeholder (point)) + (while (and (c-forward-objc-directive) + (< (point) indent-point)) + (c-forward-syntactic-ws) + (setq placeholder (point))) + (goto-char placeholder)) (c-add-syntax 'topmost-intro-cont (c-point 'boi))) )) + ;; (CASE 6 has been removed.) + ;; CASE 7: line is an expression, not a statement. Most ;; likely we are either in a function prototype or a function ;; call argument list @@ -6358,6 +8185,7 @@ (c-looking-at-special-brace-list))) (eq (char-after containing-sexp) ?{))) (cond + ;; CASE 7A: we are looking at the arglist closing paren. ;; C.f. case 7F. ((memq char-after-ip '(?\) ?\])) @@ -6369,16 +8197,17 @@ (forward-char) (skip-chars-forward " \t")) (goto-char placeholder)) - (c-add-stmt-syntax 'arglist-close (list containing-sexp) t nil + (c-add-stmt-syntax 'arglist-close (list containing-sexp) t (c-most-enclosing-brace paren-state (point)) - (c-whack-state-after (point) paren-state))) + paren-state)) + ;; CASE 7B: Looking at the opening brace of an ;; in-expression block or brace list. C.f. cases 4, 16A ;; and 17E. ((and (eq char-after-ip ?{) (progn (setq placeholder (c-inside-bracelist-p (point) - c-state-cache)) + paren-state)) (if placeholder (setq tmpsymbol '(brace-list-open . inexpr-class)) (setq tmpsymbol '(block-open . inexpr-statement) @@ -6393,23 +8222,28 @@ ))) (goto-char placeholder) (back-to-indentation) - (c-add-stmt-syntax (car tmpsymbol) nil t nil + (c-add-stmt-syntax (car tmpsymbol) nil t (c-most-enclosing-brace paren-state (point)) - (c-whack-state-after (point) paren-state)) + paren-state) (if (/= (point) placeholder) (c-add-syntax (cdr tmpsymbol)))) + ;; CASE 7C: we are looking at the first argument in an empty ;; argument list. Use arglist-close if we're actually ;; looking at a close paren or bracket. ((memq char-before-ip '(?\( ?\[)) (goto-char containing-sexp) (setq placeholder (c-point 'boi)) - (when (and (c-safe (backward-up-list 1) t) - (>= (point) placeholder)) - (forward-char) - (skip-chars-forward " \t") - (setq placeholder (point))) - (c-add-syntax 'arglist-intro placeholder)) + (if (and (c-safe (backward-up-list 1) t) + (>= (point) placeholder)) + (progn + (forward-char) + (skip-chars-forward " \t")) + (goto-char placeholder)) + (c-add-stmt-syntax 'arglist-intro (list containing-sexp) t + (c-most-enclosing-brace paren-state (point)) + paren-state)) + ;; CASE 7D: we are inside a conditional test clause. treat ;; these things as statements ((progn @@ -6422,6 +8256,7 @@ (c-add-syntax 'statement (point)) (c-add-syntax 'statement-cont (point)) )) + ;; CASE 7E: maybe a continued ObjC method call. This is the ;; case when we are inside a [] bracketed exp, and what ;; precede the opening bracket is not an identifier. @@ -6433,6 +8268,7 @@ (if (not (looking-at c-symbol-key)) (c-add-syntax 'objc-method-call-cont containing-sexp)) ))) + ;; CASE 7F: we are looking at an arglist continuation line, ;; but the preceding argument is on the same line as the ;; opening paren. This case includes multi-line @@ -6440,9 +8276,10 @@ ;; for-list continuation line. C.f. case 7A. ((progn (goto-char (1+ containing-sexp)) - (skip-chars-forward " \t") - (and (not (eolp)) - (not (looking-at "\\\\$")))) + (< (save-excursion + (c-forward-syntactic-ws) + (point)) + (c-point 'bonl))) (goto-char containing-sexp) (setq placeholder (c-point 'boi)) (if (and (c-safe (backward-up-list 1) t) @@ -6451,15 +8288,16 @@ (forward-char) (skip-chars-forward " \t")) (goto-char placeholder)) - (c-add-stmt-syntax 'arglist-cont-nonempty (list containing-sexp) - t nil + (c-add-stmt-syntax 'arglist-cont-nonempty (list containing-sexp) t (c-most-enclosing-brace c-state-cache (point)) - (c-whack-state-after (point) paren-state))) + paren-state)) + ;; CASE 7G: we are looking at just a normal arglist ;; continuation line (t (c-forward-syntactic-ws indent-point) (c-add-syntax 'arglist-cont (c-point 'boi))) )) + ;; CASE 8: func-local multi-inheritance line ((and (c-major-mode-is 'c++-mode) (save-excursion @@ -6469,27 +8307,32 @@ (goto-char indent-point) (skip-chars-forward " \t") (cond + ;; CASE 8A: non-hanging colon on an inher intro ((eq char-after-ip ?:) (c-backward-syntactic-ws lim) (c-add-syntax 'inher-intro (c-point 'boi))) + ;; CASE 8B: hanging colon on an inher intro ((eq char-before-ip ?:) (c-add-syntax 'inher-intro (c-point 'boi))) + ;; CASE 8C: a continued inheritance line (t (c-beginning-of-inheritance-list lim) (c-add-syntax 'inher-cont (point)) ))) + ;; CASE 9: we are inside a brace-list - ((and (not (c-mode-is-new-awk-p)) ; Maybe this isn't needed (ACM, 2002/3/29) + ((and (not (c-major-mode-is 'awk-mode)) ; Maybe this isn't needed (ACM, 2002/3/29) (setq special-brace-list - (or (and c-special-brace-lists + (or (and c-special-brace-lists ;;;; ALWAYS NIL FOR AWK!! (save-excursion (goto-char containing-sexp) (c-looking-at-special-brace-list))) (c-inside-bracelist-p containing-sexp paren-state)))) (cond + ;; CASE 9A: In the middle of a special brace list opener. ((and (consp special-brace-list) (save-excursion @@ -6509,6 +8352,7 @@ (goto-char (match-end 1)) (c-forward-syntactic-ws)) (c-add-syntax 'brace-list-open (c-point 'boi)))) + ;; CASE 9B: brace-list-close brace ((if (consp special-brace-list) ;; Check special brace list closer. @@ -6533,8 +8377,8 @@ (c-add-syntax 'brace-list-close (point)) (setq lim (c-most-enclosing-brace c-state-cache (point))) (c-beginning-of-statement-1 lim) - (c-add-stmt-syntax 'brace-list-close nil t t lim - (c-whack-state-after (point) paren-state)))) + (c-add-stmt-syntax 'brace-list-close nil t lim paren-state))) + (t ;; Prepare for the rest of the cases below by going to the ;; token following the opening brace @@ -6549,6 +8393,7 @@ (goto-char (max start (c-point 'bol)))) (c-skip-ws-forward indent-point) (cond + ;; CASE 9C: we're looking at the first line in a brace-list ((= (point) indent-point) (if (consp special-brace-list) @@ -6558,8 +8403,8 @@ (c-add-syntax 'brace-list-intro (point)) (setq lim (c-most-enclosing-brace c-state-cache (point))) (c-beginning-of-statement-1 lim) - (c-add-stmt-syntax 'brace-list-intro nil t t lim - (c-whack-state-after (point) paren-state)))) + (c-add-stmt-syntax 'brace-list-intro nil t lim paren-state))) + ;; CASE 9D: this is just a later brace-list-entry or ;; brace-entry-open (t (if (or (eq char-after-ip ?{) @@ -6572,12 +8417,12 @@ (c-add-syntax 'brace-list-entry (point)) )) )))) + ;; CASE 10: A continued statement or top level construct. - ((and (if (c-mode-is-new-awk-p) - (c-awk-prev-line-incomplete-p containing-sexp) ; ACM 2002/3/29 - (and (not (memq char-before-ip '(?\; ?:))) - (or (not (eq char-before-ip ?})) - (c-looking-at-inexpr-block-backward c-state-cache)))) + ((and (not (memq char-before-ip '(?\; ?:))) + (not (c-at-vsemi-p before-ws-ip)) + (or (not (eq char-before-ip ?})) + (c-looking-at-inexpr-block-backward c-state-cache)) (> (point) (save-excursion (c-beginning-of-statement-1 containing-sexp) @@ -6589,29 +8434,7 @@ placeholder containing-sexp paren-state)) - ;; CASE 14: A case or default label - ((looking-at c-label-kwds-regexp) - (goto-char containing-sexp) - (setq lim (c-most-enclosing-brace c-state-cache containing-sexp)) - (c-backward-to-block-anchor lim) - (c-add-stmt-syntax 'case-label nil t nil - lim paren-state)) - ;; CASE 15: any other label - ((looking-at c-label-key) - (goto-char containing-sexp) - (setq lim (c-most-enclosing-brace c-state-cache containing-sexp)) - (save-excursion - (setq tmpsymbol - (if (and (eq (c-beginning-of-statement-1 lim) 'up) - (looking-at "switch\\>[^_]")) - ;; If the surrounding statement is a switch then - ;; let's analyze all labels as switch labels, so - ;; that they get lined up consistently. - 'case-label - 'label))) - (c-backward-to-block-anchor lim) - (c-add-stmt-syntax tmpsymbol nil t nil - lim paren-state)) + ;; CASE 16: block close brace, possibly closing the defun or ;; the class ((eq char-after-ip ?}) @@ -6619,14 +8442,15 @@ (setq lim (c-most-enclosing-brace paren-state)) (goto-char containing-sexp) (cond + ;; CASE 16E: Closing a statement block? This catches ;; cases where it's preceded by a statement keyword, ;; which works even when used in an "invalid" context, ;; e.g. a macro argument. ((c-after-conditional) (c-backward-to-block-anchor lim) - (c-add-stmt-syntax 'block-close nil t nil - lim paren-state)) + (c-add-stmt-syntax 'block-close nil t lim paren-state)) + ;; CASE 16A: closing a lambda defun or an in-expression ;; block? C.f. cases 4, 7B and 17E. ((setq placeholder (c-looking-at-inexpr-block @@ -6641,56 +8465,59 @@ (c-add-syntax tmpsymbol (point)) (goto-char (cdr placeholder)) (back-to-indentation) - (c-add-stmt-syntax tmpsymbol nil t nil + (c-add-stmt-syntax tmpsymbol nil t (c-most-enclosing-brace paren-state (point)) - (c-whack-state-after (point) paren-state)) + paren-state) (if (/= (point) (cdr placeholder)) (c-add-syntax (car placeholder))))) + ;; CASE 16B: does this close an inline or a function in ;; a non-class declaration level block? - ((setq placeholder (c-search-uplist-for-classkey paren-state)) + ((save-excursion + (and lim + (progn + (goto-char lim) + (c-looking-at-decl-block + (c-most-enclosing-brace paren-state lim) + nil)) + (setq placeholder (point)))) (c-backward-to-decl-anchor lim) (back-to-indentation) (if (save-excursion - (goto-char (aref placeholder 0)) + (goto-char placeholder) (looking-at c-other-decl-block-key)) (c-add-syntax 'defun-close (point)) (c-add-syntax 'inline-close (point)))) + ;; CASE 16F: Can be a defun-close of a function declared ;; in a statement block, e.g. in Pike or when using gcc ;; extensions, but watch out for macros followed by ;; blocks. Let it through to be handled below. ;; C.f. cases B.3 and 17G. - ((and (not inenclosing-p) - lim - (save-excursion - (and (not (c-looking-at-bos)) - (eq (c-beginning-of-statement-1 lim nil nil t) 'same) - (setq placeholder (point)) - ;; Look for a type or identifier followed by a - ;; symbol, i.e. the start of a function declaration. - ;; Doesn't work for declarations like "int *foo() - ;; ..."; we'd need to refactor the more competent - ;; analysis in `c-font-lock-declarations' for that. - (c-forward-type) - (progn - (c-forward-syntactic-ws) - (looking-at c-symbol-start))))) + ((save-excursion + (and (not (c-at-statement-start-p)) + (eq (c-beginning-of-statement-1 lim nil nil t) 'same) + (setq placeholder (point)) + (let ((c-recognize-typeless-decls nil)) + ;; Turn off recognition of constructs that + ;; lacks a type in this case, since that's more + ;; likely to be a macro followed by a block. + (c-forward-decl-or-cast-1 (c-point 'bosws) nil nil)))) (back-to-indentation) (if (/= (point) containing-sexp) (goto-char placeholder)) - (c-add-stmt-syntax 'defun-close nil t nil - lim paren-state)) - ;; CASE 16C: if there an enclosing brace that hasn't - ;; been narrowed out by a class, then this is a - ;; block-close. C.f. case 17H. - ((and (not inenclosing-p) lim) + (c-add-stmt-syntax 'defun-close nil t lim paren-state)) + + ;; CASE 16C: If there is an enclosing brace then this is + ;; a block close since defun closes inside declaration + ;; level blocks have been handled above. + (lim ;; If the block is preceded by a case/switch label on ;; the same line, we anchor at the first preceding label - ;; at boi. The default handling in c-add-stmt-syntax is + ;; at boi. The default handling in c-add-stmt-syntax ;; really fixes it better, but we do like this to keep ;; the indentation compatible with version 5.28 and - ;; earlier. + ;; earlier. C.f. case 17H. (while (and (/= (setq placeholder (point)) (c-point 'boi)) (eq (c-beginning-of-statement-1 lim) 'label))) (goto-char placeholder) @@ -6699,21 +8526,17 @@ (goto-char containing-sexp) ;; c-backward-to-block-anchor not necessary here; those ;; situations are handled in case 16E above. - (c-add-stmt-syntax 'block-close nil t nil - lim paren-state))) - ;; CASE 16D: find out whether we're closing a top-level - ;; class or a defun + (c-add-stmt-syntax 'block-close nil t lim paren-state))) + + ;; CASE 16D: Only top level defun close left. (t - (save-restriction - (narrow-to-region (point-min) indent-point) - (let ((decl (c-search-uplist-for-classkey (c-parse-state)))) - (if decl - (c-add-class-syntax 'class-close decl paren-state) - (goto-char containing-sexp) - (c-backward-to-decl-anchor lim) - (back-to-indentation) - (c-add-syntax 'defun-close (point))))) - ))) + (goto-char containing-sexp) + (c-backward-to-decl-anchor lim) + (c-add-stmt-syntax 'defun-close nil nil + (c-most-enclosing-brace paren-state) + paren-state)) + )) + ;; CASE 17: Statement or defun catchall. (t (goto-char indent-point) @@ -6728,11 +8551,13 @@ (setq step-type last-step-type) (/= (point) (c-point 'boi))))) (cond + ;; CASE 17B: continued statement ((and (eq step-type 'same) (/= (point) indent-point)) - (c-add-stmt-syntax 'statement-cont nil nil nil + (c-add-stmt-syntax 'statement-cont nil nil containing-sexp paren-state)) + ;; CASE 17A: After a case/default label? ((progn (while (and (eq step-type 'label) @@ -6743,17 +8568,19 @@ (c-add-stmt-syntax (if (eq char-after-ip ?{) 'statement-case-open 'statement-case-intro) - nil t nil containing-sexp paren-state)) + nil t containing-sexp paren-state)) + ;; CASE 17D: any old statement ((progn (while (eq step-type 'label) (setq step-type (c-beginning-of-statement-1 containing-sexp))) (eq step-type 'previous)) - (c-add-stmt-syntax 'statement nil t nil + (c-add-stmt-syntax 'statement nil t containing-sexp paren-state) (if (eq char-after-ip ?{) (c-add-syntax 'block-open))) + ;; CASE 17I: Inside a substatement block. ((progn ;; The following tests are all based on containing-sexp. @@ -6762,10 +8589,11 @@ (setq lim (c-most-enclosing-brace paren-state containing-sexp)) (c-after-conditional)) (c-backward-to-block-anchor lim) - (c-add-stmt-syntax 'statement-block-intro nil t nil + (c-add-stmt-syntax 'statement-block-intro nil t lim paren-state) (if (eq char-after-ip ?{) (c-add-syntax 'block-open))) + ;; CASE 17E: first statement in an in-expression block. ;; C.f. cases 4, 7B and 16A. ((setq placeholder (c-looking-at-inexpr-block @@ -6779,54 +8607,58 @@ (c-add-syntax tmpsymbol (point)) (goto-char (cdr placeholder)) (back-to-indentation) - (c-add-stmt-syntax tmpsymbol nil t nil + (c-add-stmt-syntax tmpsymbol nil t (c-most-enclosing-brace c-state-cache (point)) - (c-whack-state-after (point) paren-state)) + paren-state) (if (/= (point) (cdr placeholder)) (c-add-syntax (car placeholder)))) (if (eq char-after-ip ?{) (c-add-syntax 'block-open))) + ;; CASE 17F: first statement in an inline, or first ;; statement in a top-level defun. we can tell this is it ;; if there are no enclosing braces that haven't been ;; narrowed out by a class (i.e. don't use bod here). ((save-excursion - (save-restriction - (widen) - (c-narrow-out-enclosing-class paren-state containing-sexp) - (not (c-most-enclosing-brace paren-state)))) + (or (not (setq placeholder (c-most-enclosing-brace + paren-state))) + (and (progn + (goto-char placeholder) + (eq (char-after) ?{)) + (c-looking-at-decl-block (c-most-enclosing-brace + paren-state (point)) + nil)))) (c-backward-to-decl-anchor lim) (back-to-indentation) (c-add-syntax 'defun-block-intro (point))) + ;; CASE 17G: First statement in a function declared inside ;; a normal block. This can occur in Pike and with ;; e.g. the gcc extensions, but watch out for macros ;; followed by blocks. C.f. cases B.3 and 16F. ((save-excursion - (and (not (c-looking-at-bos)) + (and (not (c-at-statement-start-p)) (eq (c-beginning-of-statement-1 lim nil nil t) 'same) (setq placeholder (point)) - ;; Look for a type or identifier followed by a - ;; symbol, i.e. the start of a function declaration. - ;; Doesn't work for declarations like "int *foo() - ;; ..."; we'd need to refactor the more competent - ;; analysis in `c-font-lock-declarations' for that. - (c-forward-type) - (progn - (c-forward-syntactic-ws) - (looking-at c-symbol-start)))) + (let ((c-recognize-typeless-decls nil)) + ;; Turn off recognition of constructs that lacks + ;; a type in this case, since that's more likely + ;; to be a macro followed by a block. + (c-forward-decl-or-cast-1 (c-point 'bosws) nil nil)))) (back-to-indentation) (if (/= (point) containing-sexp) (goto-char placeholder)) - (c-add-stmt-syntax 'defun-block-intro nil t nil + (c-add-stmt-syntax 'defun-block-intro nil t lim paren-state)) - ;; CASE 17H: First statement in a block. C.f. case 16C. + + ;; CASE 17H: First statement in a block. (t ;; If the block is preceded by a case/switch label on the ;; same line, we anchor at the first preceding label at ;; boi. The default handling in c-add-stmt-syntax is ;; really fixes it better, but we do like this to keep the ;; indentation compatible with version 5.28 and earlier. + ;; C.f. case 16C. (while (and (/= (setq placeholder (point)) (c-point 'boi)) (eq (c-beginning-of-statement-1 lim) 'label))) (goto-char placeholder) @@ -6835,19 +8667,22 @@ (goto-char containing-sexp) ;; c-backward-to-block-anchor not necessary here; those ;; situations are handled in case 17I above. - (c-add-stmt-syntax 'statement-block-intro nil t nil + (c-add-stmt-syntax 'statement-block-intro nil t lim paren-state)) (if (eq char-after-ip ?{) (c-add-syntax 'block-open))) )) ) + ;; now we need to look at any modifiers (goto-char indent-point) (skip-chars-forward " \t") + ;; are we looking at a comment only line? (when (and (looking-at c-comment-start-regexp) (/= (c-forward-token-2 0 nil (c-point 'eol)) 0)) (c-append-syntax 'comment-intro)) + ;; we might want to give additional offset to friends (in C++). (when (and c-opt-friend-key (looking-at c-opt-friend-key)) @@ -6856,9 +8691,9 @@ ;; Set syntactic-relpos. (let ((p c-syntactic-context)) (while (and p - (if (integerp (car-safe (cdr-safe (car p)))) + (if (integerp (c-langelem-pos (car p))) (progn - (setq syntactic-relpos (car (cdr (car p)))) + (setq syntactic-relpos (c-langelem-pos (car p))) nil) t)) (setq p (cdr p)))) @@ -6897,8 +8732,9 @@ ;; we add cpp-define-intro to get the extra ;; indentation of the #define body. (c-add-syntax 'cpp-define-intro))))) + ;; return the syntax - c-syntactic-context)))) + c-syntactic-context))) ;; Indentation calculation. @@ -6906,44 +8742,118 @@ (defun c-evaluate-offset (offset langelem symbol) ;; offset can be a number, a function, a variable, a list, or one of ;; the symbols + or - - (cond - ((eq offset '+) c-basic-offset) - ((eq offset '-) (- c-basic-offset)) - ((eq offset '++) (* 2 c-basic-offset)) - ((eq offset '--) (* 2 (- c-basic-offset))) - ((eq offset '*) (/ c-basic-offset 2)) - ((eq offset '/) (/ (- c-basic-offset) 2)) - ((numberp offset) offset) - ((functionp offset) (c-evaluate-offset - (funcall offset - (cons (car langelem) - (car-safe (cdr langelem)))) - langelem symbol)) - ((vectorp offset) offset) - ((null offset) nil) - ((listp offset) - (if (eq (car offset) 'quote) - (error -"Setting in c-offsets-alist element \"(%s . '%s)\" was mistakenly quoted" - symbol (cadr offset))) - (let (done) - (while (and (not done) offset) - (setq done (c-evaluate-offset (car offset) langelem symbol) - offset (cdr offset))) - (if (and c-strict-syntax-p (not done)) - (c-benign-error "No offset found for syntactic symbol %s" symbol)) - done)) - (t (symbol-value offset)) - )) + ;; + ;; This function might do hidden buffer changes. + (let ((res + (cond + ((numberp offset) offset) + ((vectorp offset) offset) + ((null offset) nil) + + ((eq offset '+) c-basic-offset) + ((eq offset '-) (- c-basic-offset)) + ((eq offset '++) (* 2 c-basic-offset)) + ((eq offset '--) (* 2 (- c-basic-offset))) + ((eq offset '*) (/ c-basic-offset 2)) + ((eq offset '/) (/ (- c-basic-offset) 2)) + + ((functionp offset) + (c-evaluate-offset + (funcall offset + (cons (c-langelem-sym langelem) + (c-langelem-pos langelem))) + langelem symbol)) + + ((listp offset) + (cond + ((eq (car offset) 'quote) + (c-benign-error "The offset %S for %s was mistakenly quoted" + offset symbol) + nil) + + ((memq (car offset) '(min max)) + (let (res val (method (car offset))) + (setq offset (cdr offset)) + (while offset + (setq val (c-evaluate-offset (car offset) langelem symbol)) + (cond + ((not val)) + ((not res) + (setq res val)) + ((integerp val) + (if (vectorp res) + (c-benign-error "\ +Error evaluating offset %S for %s: \ +Cannot combine absolute offset %S with relative %S in `%s' method" + (car offset) symbol res val method) + (setq res (funcall method res val)))) + (t + (if (integerp res) + (c-benign-error "\ +Error evaluating offset %S for %s: \ +Cannot combine relative offset %S with absolute %S in `%s' method" + (car offset) symbol res val method) + (setq res (vector (funcall method (aref res 0) + (aref val 0))))))) + (setq offset (cdr offset))) + res)) + + ((eq (car offset) 'add) + (let (res val) + (setq offset (cdr offset)) + (while offset + (setq val (c-evaluate-offset (car offset) langelem symbol)) + (cond + ((not val)) + ((not res) + (setq res val)) + ((integerp val) + (if (vectorp res) + (setq res (vector (+ (aref res 0) val))) + (setq res (+ res val)))) + (t + (if (vectorp res) + (c-benign-error "\ +Error evaluating offset %S for %s: \ +Cannot combine absolute offsets %S and %S in `add' method" + (car offset) symbol res val) + (setq res val)))) ; Override. + (setq offset (cdr offset))) + res)) + + (t + (let (res) + (when (eq (car offset) 'first) + (setq offset (cdr offset))) + (while (and (not res) offset) + (setq res (c-evaluate-offset (car offset) langelem symbol) + offset (cdr offset))) + res)))) + + ((and (symbolp offset) (boundp offset)) + (symbol-value offset)) + + (t + (c-benign-error "Unknown offset format %S for %s" offset symbol) + nil)))) + + (if (or (null res) (integerp res) + (and (vectorp res) (= (length res) 1) (integerp (aref res 0)))) + res + (c-benign-error "Error evaluating offset %S for %s: Got invalid value %S" + offset symbol res) + nil))) (defun c-calc-offset (langelem) ;; Get offset from LANGELEM which is a list beginning with the ;; syntactic symbol and followed by any analysis data it provides. ;; That data may be zero or more elements, but if at least one is - ;; given then the first is the relpos (or nil). The symbol is - ;; matched against `c-offsets-alist' and the offset calculated from - ;; that is returned. - (let* ((symbol (car langelem)) + ;; given then the first is the anchor position (or nil). The symbol + ;; is matched against `c-offsets-alist' and the offset calculated + ;; from that is returned. + ;; + ;; This function might do hidden buffer changes. + (let* ((symbol (c-langelem-sym langelem)) (match (assq symbol c-offsets-alist)) (offset (cdr-safe match))) (if match @@ -6961,21 +8871,26 @@ (defun c-get-offset (langelem) ;; This is a compatibility wrapper for `c-calc-offset' in case ;; someone is calling it directly. It takes an old style syntactic - ;; element on the form (SYMBOL . RELPOS) and converts it to the new - ;; list form. - (if (cdr langelem) - (c-calc-offset (list (car langelem) (cdr langelem))) + ;; element on the form (SYMBOL . ANCHOR-POS) and converts it to the + ;; new list form. + ;; + ;; This function might do hidden buffer changes. + (if (c-langelem-pos langelem) + (c-calc-offset (list (c-langelem-sym langelem) + (c-langelem-pos langelem))) (c-calc-offset langelem))) (defun c-get-syntactic-indentation (langelems) ;; Calculate the syntactic indentation from a syntactic description ;; as returned by `c-guess-syntax'. ;; - ;; Note that topmost-intro always has a relpos at bol, for + ;; Note that topmost-intro always has an anchor position at bol, for ;; historical reasons. It's often used together with other symbols ;; that has more sane positions. Since we always use the first - ;; found relpos, we rely on that these other symbols always precede - ;; topmost-intro in the LANGELEMS list. + ;; found anchor position, we rely on that these other symbols always + ;; precede topmost-intro in the LANGELEMS list. + ;; + ;; This function might do hidden buffer changes. (let ((indent 0) anchor) (while langelems @@ -6997,9 +8912,7 @@ ;; Use the anchor position from the first syntactic ;; element with one. (unless anchor - (let ((relpos (car-safe (cdr (car langelems))))) - (if relpos - (setq anchor relpos))))) + (setq anchor (c-langelem-pos (car langelems))))) (setq langelems (cdr langelems))))
--- a/lisp/progmodes/cc-fonts.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/progmodes/cc-fonts.el Sat Dec 10 21:18:28 2005 +0000 @@ -1,6 +1,6 @@ ;;; cc-fonts.el --- font lock support for CC Mode -;; Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +;; Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. ;; Authors: 2003- Alan Mackenzie ;; 2002- Martin Stjernholm @@ -30,8 +30,8 @@ ;; Some comments on the use of faces: ;; -;; o `c-label-face-name' is either `font-lock-constant-face' (in Emacs -;; 20 and later), or `font-lock-reference-face'. +;; o `c-label-face-name' is either `font-lock-constant-face' (in +;; Emacs), or `font-lock-reference-face'. ;; ;; o `c-constant-face-name', `c-reference-face-name' and ;; `c-doc-markup-face-name' are essentially set up like @@ -47,10 +47,6 @@ ;; documentation are actually comments in these languages, as opposed ;; to elisp). ;; -;; o `c-invalid-face-name' is `font-lock-warning-face' in Emacs. In -;; older XEmacs there's no corresponding standard face, so there -;; it's mapped to a special `c-invalid-face'. -;; ;; TBD: We should probably provide real faces for the above uses and ;; instead initialize them from the standard faces. @@ -103,17 +99,9 @@ (cc-bytecomp-defvar c-reference-face-name) (cc-bytecomp-defun c-fontify-recorded-types-and-refs) (cc-bytecomp-defun c-font-lock-declarators) -(cc-bytecomp-defun c-font-lock-objc-iip-decl) (cc-bytecomp-defun c-font-lock-objc-method) (cc-bytecomp-defun c-font-lock-invalid-string) -;; Emacs 19 doesn't have `defface'. This "replacement" leaves a lot -;; to be wished for but at least it avoids any errors. -(cc-eval-when-compile - (or (fboundp 'defface) - (cc-bytecomp-defmacro defface (face spec doc &rest args) - `(make-face ',face)))) - ;; Note that font-lock in XEmacs doesn't expand face names as ;; variables, so we have to use the (eval . FORM) in the font lock @@ -124,8 +112,8 @@ ;; XEmacs has a font-lock-preprocessor-face. 'font-lock-preprocessor-face) ((c-face-name-p 'font-lock-builtin-face) - ;; In Emacs 20 and later font-lock-builtin-face has - ;; traditionally been used for preprocessor directives. + ;; In Emacs font-lock-builtin-face has traditionally been + ;; used for preprocessor directives. 'font-lock-builtin-face) (t 'font-lock-reference-face))) @@ -150,19 +138,19 @@ (defconst c-constant-face-name (if (and (c-face-name-p 'font-lock-constant-face) (eq font-lock-constant-face 'font-lock-constant-face)) - ;; This doesn't exist in XEmacs <= 20 and some earlier versions - ;; of XEmacs 21. + ;; This doesn't exist in some earlier versions of XEmacs 21. 'font-lock-constant-face c-label-face-name)) (defconst c-reference-face-name - (if (and (c-face-name-p 'font-lock-reference-face) - (eq font-lock-reference-face 'font-lock-reference-face)) - ;; This is considered obsolete in Emacs 20 and later, but it - ;; still maps well to this use. (Another reason to do this is - ;; to get unique faces for the test suite.) - 'font-lock-reference-face - c-label-face-name)) + (with-no-warnings + (if (and (c-face-name-p 'font-lock-reference-face) + (eq font-lock-reference-face 'font-lock-reference-face)) + ;; This is considered obsolete in Emacs, but it still maps well + ;; to this use. (Another reason to do this is to get unique + ;; faces for the test suite.) + 'font-lock-reference-face + c-label-face-name))) ;; This should not mapped to a face that also is used to fontify things ;; that aren't comments or string literals. @@ -184,31 +172,10 @@ 'font-lock-doc-markup-face c-label-face-name)) -(defconst c-invalid-face-name - (if (c-face-name-p 'font-lock-warning-face) - ;; Emacs >= 20 and XEmacs >= 21 has a font-lock-warning-face. - 'font-lock-warning-face - ;; Otherwise we provide a face. - 'c-invalid-face)) - -(unless (c-face-name-p c-invalid-face-name) - (defconst c-invalid-face 'c-invalid-face) ; Necessary in Emacs 19. - ;; This face should be called `c-invalid' for consistency with the - ;; rest of emacs, but as it's only used in very old versions of Emacs, - ;; we leave it unchanged (the face-alias mechanism doesn't exist in - ;; those old versions). - (defface c-invalid-face - '((((class color) (background light)) (:foreground "red1")) - (((class color)) (:foreground "hotpink")) - (t (:inverse-video t))) - "Face used to highlight invalid syntax." - :group 'c-fonts)) - -;; To make hard spaces visible an inverted version of -;; `c-invalid-face-name' is used. Since font-lock in Emacs expands -;; all face names in `font-lock-keywords' as variables we need to have -;; a variable for it. -(defconst c-nonbreakable-space-face 'c-nonbreakable-space) +(defconst c-negation-char-face-name + (if (c-face-name-p 'font-lock-negation-char-face) + ;; Emacs 22 has a special face for negation chars. + 'font-lock-negation-char-face)) (cc-bytecomp-defun face-inverse-video-p) ; Only in Emacs. (cc-bytecomp-defun face-property-instance) ; Only in XEmacs. @@ -216,25 +183,18 @@ (defun c-make-inverse-face (oldface newface) ;; Emacs and XEmacs have completely different face manipulation ;; routines. :P - ;; - ;; This function does not do any hidden buffer changes (copy-face oldface newface) (cond ((fboundp 'face-inverse-video-p) - ;; Emacs 20 and later. This only looks at the inverse flag - ;; in the current frame. Other display configurations might - ;; be different, but it can only show if the same Emacs has - ;; frames on e.g. a color and a monochrome display - ;; simultaneously. + ;; Emacs. This only looks at the inverse flag in the current + ;; frame. Other display configurations might be different, + ;; but it can only show if the same Emacs has frames on + ;; e.g. a color and a monochrome display simultaneously. (unless (face-inverse-video-p oldface) (invert-face newface))) ((fboundp 'face-property-instance) ;; XEmacs. Same pitfall here. (unless (face-property-instance oldface 'reverse) - (invert-face newface))) - (t - ;; Emacs 19 has no inverse flag at all. Just inverse the - ;; face and hope it wasn't inversed already. - (invert-face newface)))) + (invert-face newface))))) (eval-and-compile ;; We need the following functions during compilation since they're @@ -247,6 +207,8 @@ ;; additional font-lock property, or else the font-lock package ;; won't recognize it as fontified and might override it ;; incorrectly. + ;; + ;; This function does a hidden buffer change. (if (fboundp 'font-lock-set-face) ;; Note: This function has no docstring in XEmacs so it might be ;; considered internal. @@ -255,6 +217,8 @@ (defmacro c-remove-font-lock-face (from to) ;; This is the inverse of `c-put-font-lock-face'. + ;; + ;; This function does a hidden buffer change. (if (fboundp 'font-lock-remove-face) `(font-lock-remove-face ,from ,to) `(remove-text-properties ,from ,to '(face nil)))) @@ -263,6 +227,8 @@ ;; Put `font-lock-string-face' on a string. The surrounding ;; quotes are included in Emacs but not in XEmacs. The passed ;; region should include them. + ;; + ;; This function does a hidden buffer change. (if (featurep 'xemacs) `(c-put-font-lock-face (1+ ,from) (1- ,to) 'font-lock-string-face) `(c-put-font-lock-face ,from ,to 'font-lock-string-face))) @@ -271,19 +237,22 @@ ;; Like `let', but additionally activates `c-record-type-identifiers' ;; and `c-record-ref-identifiers', and fontifies the recorded ranges ;; accordingly on exit. + ;; + ;; This function does hidden buffer changes. `(let ((c-record-type-identifiers t) c-record-ref-identifiers ,@varlist) (prog1 (progn ,@body) (c-fontify-recorded-types-and-refs)))) (put 'c-fontify-types-and-refs 'lisp-indent-function 1) - (eval-after-load "edebug" '(def-edebug-spec c-fontify-types-and-refs let*)) (defun c-skip-comments-and-strings (limit) ;; If the point is within a region fontified as a comment or ;; string literal skip to the end of it or to LIMIT, whichever ;; comes first, and return t. Otherwise return nil. The match ;; data is not clobbered. + ;; + ;; This function might do hidden buffer changes. (when (c-got-face-at (point) c-literal-faces) (while (progn (goto-char (next-single-property-change @@ -292,6 +261,26 @@ (c-got-face-at (point) c-literal-faces)))) t)) + (defun c-make-syntactic-matcher (regexp) + ;; Returns a byte compiled function suitable for use in place of a + ;; regexp string in a `font-lock-keywords' matcher, except that + ;; only matches outside comments and string literals count. + ;; + ;; This function does not do any hidden buffer changes, but the + ;; generated functions will. (They are however used in places + ;; covered by the font-lock context.) + (byte-compile + `(lambda (limit) + (let (res) + (while (and (setq res (re-search-forward ,regexp limit t)) + (progn + (goto-char (match-beginning 0)) + (or (c-skip-comments-and-strings limit) + (progn + (goto-char (match-end 0)) + nil))))) + res)))) + (defun c-make-font-lock-search-function (regexp &rest highlights) ;; This function makes a byte compiled function that works much like ;; a matcher element in `font-lock-keywords'. It cuts out a little @@ -315,32 +304,30 @@ ;; the anchored matcher forms. ;; ;; This function does not do any hidden buffer changes, but the - ;; generated functions will. They are however used in places - ;; covered by the font-lock context. + ;; generated functions will. (They are however used in places + ;; covered by the font-lock context.) ;; Note: Replace `byte-compile' with `eval' to debug the generated ;; lambda easier. (byte-compile `(lambda (limit) - (let (-match-end-pos- - ;; The font-lock package in Emacs is known to clobber + (let (;; The font-lock package in Emacs is known to clobber ;; `parse-sexp-lookup-properties' (when it exists). (parse-sexp-lookup-properties (cc-eval-when-compile (boundp 'parse-sexp-lookup-properties)))) (while (re-search-forward ,regexp limit t) - (setq -match-end-pos- (point)) (unless (progn (goto-char (match-beginning 0)) (c-skip-comments-and-strings limit)) - (goto-char -match-end-pos-) + (goto-char (match-end 0)) ,@(mapcar (lambda (highlight) (if (integerp (car highlight)) (progn - (unless (nth 2 highlight) + (unless (eq (nth 2 highlight) t) (error - "The override flag must currently be set in %s" + "The override flag must currently be t in %s" highlight)) (when (nth 3 highlight) (error @@ -359,11 +346,23 @@ (save-match-data ,(car highlight)) ,(nth 2 highlight)))) highlights)))) - nil)))) + nil))) + + (eval-after-load "edebug" + '(progn + (def-edebug-spec c-fontify-types-and-refs let*) + (def-edebug-spec c-make-syntactic-matcher t) + ;; If there are literal quoted or backquoted highlight specs in + ;; the call to `c-make-font-lock-search-function' then let's + ;; instrument the forms in them. + (def-edebug-spec c-make-font-lock-search-function + (form &rest &or ("quote" (&rest form)) ("`" (&rest form)) form))))) (defun c-fontify-recorded-types-and-refs () - ;; Converts the ranges recorded on `c-record-type-identifiers' and + ;; Convert the ranges recorded on `c-record-type-identifiers' and ;; `c-record-ref-identifiers' to fontification. + ;; + ;; This function does hidden buffer changes. (let (elem) (while (consp c-record-type-identifiers) (setq elem (car c-record-type-identifiers) @@ -388,108 +387,123 @@ t `(,@(when (c-lang-const c-opt-cpp-prefix) (let* ((noncontinued-line-end "\\(\\=\\|\\(\\=\\|[^\\]\\)[\n\r]\\)") - (ncle-depth (c-regexp-opt-depth noncontinued-line-end)) - (sws-depth (c-lang-const c-syntactic-ws-depth))) + (ncle-depth (regexp-opt-depth noncontinued-line-end)) + (sws-depth (c-lang-const c-syntactic-ws-depth)) + (nsws-depth (c-lang-const c-nonempty-syntactic-ws-depth))) + `(;; The stuff after #error and #warning is a message, so ;; fontify it as a string. - (,(concat noncontinued-line-end - (c-lang-const c-opt-cpp-prefix) - "\\(error\\|warning\\)\\>\\s *\\(.*\\)$") - ,(+ ncle-depth 2) font-lock-string-face) + ,@(when (c-lang-const c-cpp-message-directives) + (let* ((re (c-make-keywords-re nil + (c-lang-const c-cpp-message-directives))) + (re-depth (regexp-opt-depth re))) + `((,(concat noncontinued-line-end + (c-lang-const c-opt-cpp-prefix) + re + "\\s +\\(.*\\)$") + ,(+ ncle-depth re-depth 1) font-lock-string-face)))) ;; Fontify filenames in #include <...> as strings. - (,(concat noncontinued-line-end - (c-lang-const c-opt-cpp-prefix) - "\\(import\\|include\\)\\>" - (c-lang-const c-syntactic-ws) - "\\(<[^>\n\r]*>?\\)") - (,(+ ncle-depth sws-depth 2) - font-lock-string-face) + ,@(when (c-lang-const c-cpp-include-directives) + (let* ((re (c-make-keywords-re nil + (c-lang-const c-cpp-include-directives))) + (re-depth (regexp-opt-depth re))) + `((,(concat noncontinued-line-end + (c-lang-const c-opt-cpp-prefix) + re + (c-lang-const c-syntactic-ws) + "\\(<[^>\n\r]*>?\\)") + (,(+ ncle-depth re-depth sws-depth 1) + font-lock-string-face) - ;; Use an anchored matcher to put paren syntax on the brackets. - (,(byte-compile - `(lambda (limit) - (let ((beg-pos - (match-beginning ,(+ ncle-depth sws-depth 2))) - (end-pos - (1- (match-end ,(+ ncle-depth sws-depth 2))))) - (if (eq (char-after end-pos) ?>) - (progn - (c-mark-<-as-paren beg-pos) - (c-mark->-as-paren end-pos)) - (c-clear-char-property beg-pos 'syntax-table))) - nil)))) + ;; Use an anchored matcher to put paren syntax + ;; on the brackets. + (,(byte-compile + `(lambda (limit) + (let ((beg (match-beginning + ,(+ ncle-depth re-depth sws-depth 1))) + (end (1- (match-end ,(+ ncle-depth re-depth + sws-depth 1))))) + (if (eq (char-after end) ?>) + (progn + (c-mark-<-as-paren beg) + (c-mark->-as-paren end)) + (c-clear-char-property beg 'syntax-table))) + nil))))))) ;; #define. - (,(c-make-font-lock-search-function - (concat - noncontinued-line-end - (c-lang-const c-opt-cpp-prefix) - "define\\>" - (c-lang-const c-syntactic-ws) - "\\(" (c-lang-const c-symbol-key) "\\)" ; 1 + ncle + sws - (concat "\\(" ; 2 + ncle + sws + c-sym-key - ;; Macro with arguments - a "function". - "\\(\(\\)" ; 3 + ncle + sws + c-sym-key - "\\|" - ;; Macro without arguments - a "variable". - "\\([^\(]\\|$\\)" - "\\)")) - `((if (match-beginning ,(+ 3 ncle-depth sws-depth - (c-lang-const c-symbol-key-depth))) - ;; "Function". Fontify the name and the arguments. - (save-restriction - (c-put-font-lock-face - (match-beginning ,(+ 1 ncle-depth sws-depth)) - (match-end ,(+ 1 ncle-depth sws-depth)) - 'font-lock-function-name-face) - (goto-char (match-end - ,(+ 3 ncle-depth sws-depth - (c-lang-const c-symbol-key-depth)))) + ,@(when (c-lang-const c-opt-cpp-macro-define) + `((,(c-make-font-lock-search-function + (concat + noncontinued-line-end + (c-lang-const c-opt-cpp-prefix) + (c-lang-const c-opt-cpp-macro-define) + (c-lang-const c-nonempty-syntactic-ws) + "\\(" (c-lang-const ; 1 + ncle + nsws + c-symbol-key) "\\)" + (concat "\\(" ; 2 + ncle + nsws + c-sym-key + ;; Macro with arguments - a "function". + "\\(\(\\)" ; 3 + ncle + nsws + c-sym-key + "\\|" + ;; Macro without arguments - a "variable". + "\\([^\(]\\|$\\)" + "\\)")) + `((if (match-beginning + ,(+ 3 ncle-depth nsws-depth + (c-lang-const c-symbol-key-depth))) - (narrow-to-region (point-min) limit) - (while (and - (progn - (c-forward-syntactic-ws) - (looking-at c-symbol-key)) - (progn - (c-put-font-lock-face - (match-beginning 0) (match-end 0) - 'font-lock-variable-name-face) - (goto-char (match-end 0)) - (c-forward-syntactic-ws) - (eq (char-after) ?,))) - (forward-char))) + ;; "Function". Fontify the name and the arguments. + (save-restriction + (c-put-font-lock-face + (match-beginning ,(+ 1 ncle-depth nsws-depth)) + (match-end ,(+ 1 ncle-depth nsws-depth)) + 'font-lock-function-name-face) + (goto-char + (match-end + ,(+ 3 ncle-depth nsws-depth + (c-lang-const c-symbol-key-depth)))) - ;; "Variable". - (c-put-font-lock-face - (match-beginning ,(+ 1 ncle-depth sws-depth)) - (match-end ,(+ 1 ncle-depth sws-depth)) - 'font-lock-variable-name-face))))) + (narrow-to-region (point-min) limit) + (while (and + (progn + (c-forward-syntactic-ws) + (looking-at c-symbol-key)) + (progn + (c-put-font-lock-face + (match-beginning 0) (match-end 0) + 'font-lock-variable-name-face) + (goto-char (match-end 0)) + (c-forward-syntactic-ws) + (eq (char-after) ?,))) + (forward-char))) + + ;; "Variable". + (c-put-font-lock-face + (match-beginning ,(+ 1 ncle-depth nsws-depth)) + (match-end ,(+ 1 ncle-depth nsws-depth)) + 'font-lock-variable-name-face))))))) ;; Fontify cpp function names in preprocessor ;; expressions in #if and #elif. - ,(when (c-lang-const c-cpp-defined-fns) - `(,(c-make-font-lock-search-function - (concat noncontinued-line-end - (c-lang-const c-opt-cpp-prefix) - "\\(if\\|elif\\)\\>" ; 1 + ncle-depth - ;; Match the whole logical line to look - ;; for the functions in. - "\\(\\\\\\(.\\|[\n\r]\\)\\|[^\n\r]\\)*") - `((let ((limit (match-end 0))) - (while (re-search-forward - ,(concat "\\<\\(" - (c-regexp-opt - (c-lang-const c-cpp-defined-fns) - nil) - "\\)\\>" - "\\s *\(?") - limit 'move) - (c-put-font-lock-face (match-beginning 1) - (match-end 1) - c-preprocessor-face-name))) - (goto-char (match-end ,(1+ ncle-depth))))))) + ,@(when (and (c-lang-const c-cpp-expr-directives) + (c-lang-const c-cpp-expr-functions)) + (let ((ced-re (c-make-keywords-re t + (c-lang-const c-cpp-expr-directives))) + (cef-re (c-make-keywords-re t + (c-lang-const c-cpp-expr-functions)))) + `((,(c-make-font-lock-search-function + (concat noncontinued-line-end + (c-lang-const c-opt-cpp-prefix) + ced-re ; 1 + ncle-depth + ;; Match the whole logical line to look + ;; for the functions in. + "\\(\\\\\\(.\\|[\n\r]\\)\\|[^\n\r]\\)*") + `((let ((limit (match-end 0))) + (while (re-search-forward ,cef-re limit 'move) + (c-put-font-lock-face (match-beginning 1) + (match-end 1) + c-preprocessor-face-name))) + (goto-char (match-end ,(1+ ncle-depth))))))))) ;; Fontify the directive names. (,(c-make-font-lock-search-function @@ -500,45 +514,52 @@ "\\)") `(,(1+ ncle-depth) c-preprocessor-face-name t))) - ;; fontify the n in ifndef - (,(concat noncontinued-line-end - (c-lang-const c-opt-cpp-prefix) - "if\\(n\\)def\\>") - ,(+ ncle-depth 1) font-lock-negation-char-face prepend) + (eval . (list ,(c-make-syntactic-matcher + (concat noncontinued-line-end + (c-lang-const c-opt-cpp-prefix) + "if\\(n\\)def\\>")) + ,(+ ncle-depth 1) + c-negation-char-face-name + 'append)) ))) ,@(when (c-major-mode-is 'pike-mode) + ;; Recognize hashbangs in Pike. `((eval . (list "\\`#![^\n\r]*" 0 c-preprocessor-face-name)))) - ;; Make hard spaces visible through an inverted `c-invalid-face-name'. + ;; Make hard spaces visible through an inverted `font-lock-warning-face'. (eval . (list "\240" 0 (progn - (unless (c-face-name-p c-nonbreakable-space-face) - (c-make-inverse-face c-invalid-face-name - c-nonbreakable-space-face)) - 'c-nonbreakable-space-face))) + (unless (c-face-name-p 'c-nonbreakable-space-face) + (c-make-inverse-face 'font-lock-warning-face + 'c-nonbreakable-space-face)) + ''c-nonbreakable-space-face))) )) (defun c-font-lock-invalid-string () ;; Assuming the point is after the opening character of a string, - ;; fontify that char with `c-invalid-face-name' if the string + ;; fontify that char with `font-lock-warning-face' if the string ;; decidedly isn't terminated properly. + ;; + ;; This function does hidden buffer changes. (let ((start (1- (point)))) (save-excursion - (and (nth 3 (parse-partial-sexp start (c-point 'eol))) - (if (c-major-mode-is '(c-mode c++-mode objc-mode pike-mode)) + (and (eq (elt (parse-partial-sexp start (c-point 'eol)) 8) start) + (if (integerp c-multiline-string-start-char) + ;; There's no multiline string start char before the + ;; string, so newlines aren't allowed. + (not (eq (char-before start) c-multiline-string-start-char)) + ;; Multiline strings are allowed anywhere if + ;; c-multiline-string-start-char is t. + (not c-multiline-string-start-char)) + (if c-string-escaped-newlines ;; There's no \ before the newline. (not (eq (char-before (point)) ?\\)) - ;; Quoted newlines aren't supported. + ;; Escaped newlines aren't supported. t) - (if (c-major-mode-is 'pike-mode) - ;; There's no # before the string, so newlines - ;; aren't allowed. - (not (eq (char-before start) ?#)) - t) - (c-put-font-lock-face start (1+ start) c-invalid-face-name))))) + (c-put-font-lock-face start (1+ start) 'font-lock-warning-face))))) (c-lang-defconst c-basic-matchers-before "Font lock matchers for basic keywords, labels, references and various @@ -566,18 +587,18 @@ (let ((re (c-make-keywords-re nil (c-lang-const c-constant-kwds)))) (if (c-major-mode-is 'pike-mode) ;; No symbol is a keyword after "->" in Pike. - `((eval . (list ,(concat "\\(\\=\\|\\(\\=\\|[^-]\\)[^>]\\)" + `((eval . (list ,(concat "\\(\\=.?\\|[^>]\\|[^-]>\\)" "\\<\\(" re "\\)\\>") - 3 c-constant-face-name))) + 2 c-constant-face-name))) `((eval . (list ,(concat "\\<\\(" re "\\)\\>") 1 c-constant-face-name)))))) ;; Fontify all keywords except the primitive types. ,(if (c-major-mode-is 'pike-mode) ;; No symbol is a keyword after "->" in Pike. - `(,(concat "\\(\\=\\|\\(\\=\\|[^-]\\)[^>]\\)" + `(,(concat "\\(\\=.?\\|[^>]\\|[^-]>\\)" "\\<" (c-lang-const c-regular-keywords-regexp)) - 3 font-lock-keyword-face) + 2 font-lock-keyword-face) `(,(concat "\\<" (c-lang-const c-regular-keywords-regexp)) 1 font-lock-keyword-face)) @@ -596,9 +617,10 @@ ;; Search for class identifiers preceded by ".". The ;; anchored matcher takes it from there. (concat (c-lang-const c-opt-identifier-concat-key) - "[ \t\n\r\f\v]*" + (c-lang-const c-simple-ws) "*" (concat "\\(" - "[" c-upper "][" (c-lang-const c-symbol-chars) "]*" + "[" c-upper "]" + "[" (c-lang-const c-symbol-chars) "]*" "\\|" "\\*" "\\)")) @@ -612,24 +634,26 @@ (< (skip-chars-backward ,(c-lang-const c-symbol-chars)) 0)) (not (get-text-property (point) 'face))) - (c-put-font-lock-face (point) id-end c-reference-face-name) + (c-put-font-lock-face (point) id-end + c-reference-face-name) (c-backward-syntactic-ws))) nil (goto-char (match-end 0))))) `((,(byte-compile - ;; Must use a function here since we match longer than we - ;; want to move before doing a new search. This is not - ;; necessary for XEmacs >= 20 since it restarts the search - ;; from the end of the first highlighted submatch (something - ;; that causes problems in other places). + ;; Must use a function here since we match longer than + ;; we want to move before doing a new search. This is + ;; not necessary for XEmacs since it restarts the + ;; search from the end of the first highlighted + ;; submatch (something that causes problems in other + ;; places). `(lambda (limit) (while (re-search-forward ,(concat "\\(\\<" ; 1 "\\(" (c-lang-const c-symbol-key) "\\)" ; 2 - "[ \t\n\r\f\v]*" + (c-lang-const c-simple-ws) "*" (c-lang-const c-opt-identifier-concat-key) - "[ \t\n\r\f\v]*" + (c-lang-const c-simple-ws) "*" "\\)" "\\(" (c-lang-const c-opt-after-id-concat-key) @@ -660,29 +684,30 @@ (if (> (point) limit) (goto-char limit))))) ;; The @interface/@implementation/@protocol directives. - (,(concat "\\<" - (c-regexp-opt + ,(c-make-font-lock-search-function + (concat "\\<" + (regexp-opt '("@interface" "@implementation" "@protocol") t) "\\>") - (,(byte-compile - (lambda (limit) - (let (;; The font-lock package in Emacs is known to clobber - ;; `parse-sexp-lookup-properties' (when it exists). - (parse-sexp-lookup-properties - (cc-eval-when-compile - (boundp 'parse-sexp-lookup-properties)))) - (save-restriction - (narrow-to-region (point-min) limit) - (c-font-lock-objc-iip-decl))) - nil)))))) + '((c-fontify-types-and-refs + (;; The font-lock package in Emacs is known to clobber + ;; `parse-sexp-lookup-properties' (when it exists). + (parse-sexp-lookup-properties + (cc-eval-when-compile + (boundp 'parse-sexp-lookup-properties)))) + (c-forward-objc-directive) + nil) + (goto-char (match-beginning 0)))))) - ("\\(!\\)[^=]" 1 font-lock-negation-char-face) + (eval . (list "\\(!\\)[^=]" 1 c-negation-char-face-name)) )) (defun c-font-lock-complex-decl-prepare (limit) ;; Called before any of the matchers in `c-complex-decl-matchers'. ;; Nil is always returned. + ;; + ;; This function does hidden buffer changes. ;;(message "c-font-lock-complex-decl-prepare %s %s" (point) limit) @@ -718,17 +743,20 @@ (defun c-font-lock-<>-arglists (limit) ;; Fontify types and references in names containing angle bracket - ;; arglists from the point to LIMIT. This will also fontify cases - ;; like normal function calls on the form "foo (a < b, c > d)", but - ;; `c-font-lock-declarations' will undo that later. Nil is always - ;; returned. + ;; arglists from the point to LIMIT. Note that + ;; `c-font-lock-declarations' already has handled many of them. Nil + ;; is always returned. + ;; + ;; This function might do hidden buffer changes. (let (;; The font-lock package in Emacs is known to clobber ;; `parse-sexp-lookup-properties' (when it exists). (parse-sexp-lookup-properties (cc-eval-when-compile (boundp 'parse-sexp-lookup-properties))) - id-start id-end pos kwd-sym) + (c-parse-and-markup-<>-arglists t) + c-restricted-<>-arglists + id-start id-end id-face pos kwd-sym) (while (and (< (point) limit) (re-search-forward c-opt-<>-arglist-start limit t)) @@ -739,28 +767,51 @@ (goto-char id-start) (unless (c-skip-comments-and-strings limit) - (setq kwd-sym nil) - (if (or (not (eq (get-text-property id-start 'face) - 'font-lock-keyword-face)) - (when (looking-at c-opt-<>-sexp-key) - (setq kwd-sym (c-keyword-sym (match-string 1))))) + (setq kwd-sym nil + c-restricted-<>-arglists nil + id-face (get-text-property id-start 'face)) + + (if (cond + ((eq id-face 'font-lock-type-face) + ;; The identifier got the type face so it has already been + ;; handled in `c-font-lock-declarations'. + nil) + + ((eq id-face 'font-lock-keyword-face) + (when (looking-at c-opt-<>-sexp-key) + ;; There's a special keyword before the "<" that tells + ;; that it's an angle bracket arglist. + (setq kwd-sym (c-keyword-sym (match-string 1))))) + + (t + ;; There's a normal identifier before the "<". If we're not in + ;; a declaration context then we set `c-restricted-<>-arglists' + ;; to avoid recognizing templates in function calls like "foo (a + ;; < b, c > d)". + (c-backward-syntactic-ws) + (when (and (memq (char-before) '(?\( ?,)) + (not (eq (get-text-property (1- (point)) 'c-type) + 'c-decl-arg-start))) + (setq c-restricted-<>-arglists t)) + t)) + (progn (goto-char (1- pos)) ;; Check for comment/string both at the identifier and ;; at the "<". (unless (c-skip-comments-and-strings limit) - (when (c-forward-<>-arglist (c-keyword-member kwd-sym - 'c-<>-type-kwds) - t) - (when (and c-opt-identifier-concat-key - (not (get-text-property id-start 'face))) - (c-forward-syntactic-ws) - (if (looking-at c-opt-identifier-concat-key) + (c-fontify-types-and-refs () + (when (c-forward-<>-arglist (c-keyword-member + kwd-sym 'c-<>-type-kwds)) + (when (and c-opt-identifier-concat-key + (not (get-text-property id-start 'face))) + (c-forward-syntactic-ws) + (if (looking-at c-opt-identifier-concat-key) + (c-put-font-lock-face id-start id-end + c-reference-face-name) (c-put-font-lock-face id-start id-end - c-reference-face-name) - (c-put-font-lock-face id-start id-end - 'font-lock-type-face)))) + 'font-lock-type-face))))) (goto-char pos))) (goto-char pos))))) @@ -773,6 +824,8 @@ ;; "bar" in "int foo = 17, bar;"). Stop at LIMIT. If TYPES is ;; non-nil, fontify all identifiers as types. Nil is always ;; returned. + ;; + ;; This function might do hidden buffer changes. ;;(message "c-font-lock-declarators from %s to %s" (point) limit) (c-fontify-types-and-refs @@ -789,7 +842,7 @@ (let (got-identifier) (setq paren-depth 0) ;; Skip over type decl prefix operators. (Note similar - ;; code in `c-font-lock-declarations'.) + ;; code in `c-forward-decl-or-cast-1'.) (while (and (looking-at c-type-decl-prefix-key) (if (and (c-major-mode-is 'c++-mode) (match-beginning 2)) @@ -830,6 +883,11 @@ (<= (point) limit) + (progn + (when (looking-at c-decl-hangon-key) + (c-forward-keyword-clause 1)) + (<= (point) limit)) + ;; Search syntactically to the end of the declarator (";", ;; ",", a closen paren, eob etc) or to the beginning of an ;; initializer or function prototype ("=" or "\\s\("). @@ -883,6 +941,9 @@ (looking-at "{")) (c-safe (c-forward-sexp) t) t) + ;; FIXME: Should look for c-decl-end markers here; + ;; we might go far into the following declarations + ;; in e.g. ObjC mode (see e.g. methods-4.m). (c-syntactic-re-search-forward "[;,{]" limit 'move t) (backward-char))) @@ -905,106 +966,50 @@ c-reference-face-name font-lock-keyword-face)) -;; Macro used inside `c-font-lock-declarations'. It ought to be a -;; defsubst or perhaps even a defun, but it contains lots of free -;; variables that refer to things inside `c-font-lock-declarations'. -(defmacro c-fl-shift-type-backward (&optional short) - ;; `c-font-lock-declarations' can consume an arbitrary length list - ;; of types when parsing a declaration, which means that it - ;; sometimes consumes the identifier in the declaration as a type. - ;; This is used to "backtrack" and make the last type be treated - ;; as an identifier instead. - `(progn - ,(unless short - ;; These identifiers are bound only in the inner let. - '(setq identifier-type at-type - identifier-start type-start - identifier-end type-end)) - (if (setq at-type (if (eq prev-at-type 'prefix) - t - prev-at-type)) - (setq type-start prev-type-start - type-end prev-type-end) - (setq type-start start-pos - type-end start-pos)) - ,(unless short - ;; These identifiers are bound only in the inner let. - '(setq start type-end - got-parens nil - got-identifier t - got-suffix t - got-suffix-after-parens t - paren-depth 0)))) - (defun c-font-lock-declarations (limit) - ;; Fontify all the declarations and casts from the point to LIMIT. - ;; Assumes that strings and comments have been fontified already. - ;; Nil is always returned. + ;; Fontify all the declarations, casts and labels from the point to LIMIT. + ;; Assumes that strings and comments have been fontified already. Nil is + ;; always returned. ;; - ;; This function can make hidden buffer changes, but the font-lock - ;; context covers that. + ;; This function might do hidden buffer changes. ;;(message "c-font-lock-declarations search from %s to %s" (point) limit) (save-restriction - (let (start-pos - c-restricted-<>-arglists - ;; Nonzero if the `c-decl-prefix-re' match is in an arglist context, - ;; as opposed to a statement-level context. The major difference is - ;; that "," works as declaration delimiter in an arglist context, - ;; whereas it only separates declarators in the same declaration in - ;; a statement context. If it's nonzero then the value is the - ;; matched char, e.g. ?\( or ?,. - arglist-match - ;; 'decl if we're in an arglist containing declarations (but if - ;; `c-recognize-paren-inits' is set it might also be an initializer - ;; arglist), '<> if the arglist is of angle bracket type, 'other if - ;; it's some other arglist, or nil if not in an arglist at all. - arglist-type - ;; Set to the result of `c-forward-type'. - at-type - ;; These record the start and end of the type or possible type found - ;; by `c-forward-type'. `type-start' is at the start of the first - ;; type token, and `type-end' is at the start of the first token - ;; after the type (and after any specifiers). - type-start type-end - ;; These store `at-type', `type-start' and `type-end' of the - ;; identifier before the one in those variables. The previous - ;; identifier might turn out to be the real type in a declaration if - ;; the last one has to be the declarator in it. If `prev-at-type' - ;; is nil then the other variables have undefined values. - prev-at-type prev-type-start prev-type-end - ;; Whether we've found a declaration or a cast. We might know this - ;; before we've found the type in it. - at-decl-or-cast - ;; Set when we need to back up to parse this as a declaration but - ;; not as a cast. - backup-if-not-cast - ;; Set if we've found a "typedef" specifier. The identifiers in the - ;; declaration are then fontified as types. - at-typedef - ;; Set if we've found a specifier that can start a declaration where - ;; there's no type. - maybe-typeless - ;; The position of the next token after the closing paren of the - ;; last fontified cast. + (let (;; The position where `c-find-decl-spots' stopped. + start-pos + ;; 'decl if we're in an arglist containing declarations (but + ;; if `c-recognize-paren-inits' is set it might also be an + ;; initializer arglist), '<> if the arglist is of angle + ;; bracket type, 'arglist if it's some other arglist, or nil + ;; if not in an arglist at all. + context + ;; The position of the next token after the closing paren of + ;; the last detected cast. last-cast-end - ;; The same for the currently investigated cast. - cast-end - ;; The maximum of the end positions of all the checked type decl - ;; expressions in the successfully identified declarations. The - ;; position might be either before or after the syntactic whitespace - ;; following the last token in the type decl expression. + ;; The result from `c-forward-decl-or-cast-1'. + decl-or-cast + ;; The maximum of the end positions of all the checked type + ;; decl expressions in the successfully identified + ;; declarations. The position might be either before or + ;; after the syntactic whitespace following the last token + ;; in the type decl expression. (max-type-decl-end 0) ;; Same as `max-type-decl-*', but used when we're before ;; `token-pos'. (max-type-decl-end-before-token 0) - ;; Allow recording of identifier ranges in `c-forward-type' etc for - ;; later fontification. Not using `c-fontify-types-and-refs' here - ;; since the ranges should be fontified selectively only when a - ;; declaration or cast has been successfully recognized. - c-record-type-identifiers + ;; Set according to the context to direct the heuristics for + ;; recognizing C++ templates. + c-restricted-<>-arglists + ;; Turn on recording of identifier ranges in + ;; `c-forward-decl-or-cast-1' and `c-forward-label' for + ;; later fontification. + (c-record-type-identifiers t) c-record-ref-identifiers + ;; Make `c-forward-type' calls mark up template arglists if + ;; it finds any. That's necessary so that we later will + ;; stop inside them to fontify types there. + (c-parse-and-markup-<>-arglists t) ;; The font-lock package in Emacs is known to clobber ;; `parse-sexp-lookup-properties' (when it exists). (parse-sexp-lookup-properties @@ -1024,737 +1029,162 @@ ;; "some_other_variable" as an identifier, and the latter will not ;; correct itself until the second line is changed. To avoid that we ;; narrow to the limit if the region to fontify is a single line. - (when (<= limit (c-point 'bonl)) - (narrow-to-region - (point-min) - (save-excursion - ;; Narrow after any operator chars following the limit though, since - ;; those characters can be useful in recognizing a declaration (in - ;; particular the '{' that opens a function body after the header). - (goto-char limit) - (skip-chars-forward c-nonsymbol-chars) - (point)))) + (narrow-to-region + (point-min) + (if (<= limit (c-point 'bonl)) + (save-excursion + ;; Narrow after any operator chars following the limit though, + ;; since those characters can be useful in recognizing a + ;; declaration (in particular the '{' that opens a function body + ;; after the header). + (goto-char limit) + (skip-chars-forward c-nonsymbol-chars) + (point)) + limit)) (c-find-decl-spots limit - c-identifier-start + c-decl-start-re c-font-lock-maybe-decl-faces (lambda (match-pos inside-macro) - (catch 'false-alarm - ;; Don't do anything more if we're looking at a keyword - ;; that can't start a declaration. - (when (and (eq (get-text-property (point) 'face) - 'font-lock-keyword-face) - (looking-at c-not-decl-init-keywords)) - (throw 'false-alarm t)) - - ;; Set `arglist-match' and `arglist-type'. Look for "<" for the - ;; sake of C++-style template arglists. - (setq arglist-match (char-before match-pos)) - (if (memq arglist-match '(?\( ?, ?\[ ?<)) - - ;; Find out the type of the arglist. - (if (<= match-pos (point-min)) - (setq arglist-type 'other) - (let ((type (c-get-char-property (1- match-pos) 'c-type))) - (cond ((eq type 'c-decl-arg-start) - ;; Got a cached hit in a declaration arglist. - (setq arglist-type 'decl)) - ((or (eq type 'c-<>-arg-sep) - (eq arglist-match ?<)) - ;; Inside an angle bracket arglist. - (setq arglist-type '<>)) - (type - ;; Got a cached hit in some other type of arglist. - (setq arglist-type 'other)) - ((if inside-macro - (< match-pos max-type-decl-end-before-token) - (< match-pos max-type-decl-end)) - ;; The point is within the range of a previously - ;; encountered type decl expression, so the arglist - ;; is probably one that contains declarations. - ;; However, if `c-recognize-paren-inits' is set it - ;; might also be an initializer arglist. - (setq arglist-type 'decl) - ;; The result of this check is cached with a char - ;; property on the match token, so that we can look - ;; it up again when refontifying single lines in a - ;; multiline declaration. - (c-put-char-property (1- match-pos) - 'c-type 'c-decl-arg-start)) - (t - (setq arglist-type 'other))))) - - (setq arglist-match nil - arglist-type nil)) - - (setq at-type nil - at-decl-or-cast nil - backup-if-not-cast nil - at-typedef nil - maybe-typeless nil - c-record-type-identifiers t - c-record-ref-identifiers nil - ;; `start-pos' is used below to point to the start of the - ;; first type, i.e. after any leading specifiers. It might - ;; also point at the beginning of the preceding syntactic - ;; whitespace. - start-pos (point) - ;; If we're in a normal arglist context we don't want to - ;; recognize commas in nested angle bracket arglists since - ;; those commas could be part of our own arglist. - c-restricted-<>-arglists - (and c-recognize-<>-arglists - (eq arglist-type 'other))) + (setq start-pos (point)) + (when + ;; The result of the form below is true when we don't recognize a + ;; declaration or cast. + (if (and (eq (get-text-property (point) 'face) + 'font-lock-keyword-face) + (looking-at c-not-decl-init-keywords)) + ;; Don't do anything more if we're looking at a keyword that + ;; can't start a declaration. + t - (when (and c-restricted-<>-arglists - (/= arglist-match ?,)) - ;; We're standing at the start of a normal arglist so remove any - ;; angle bracket arglists containing commas that's been - ;; recognized inside it by the preceding slightly opportunistic - ;; scan in `c-font-lock-<>-arglists'. - (while (and (c-syntactic-re-search-forward - c-opt-<>-arglist-start-in-paren nil t t) - (match-beginning 1)) - (backward-char) - (when (save-match-data - (and (c-get-char-property (point) 'syntax-table) - (not (c-forward-<>-arglist nil t)))) - (c-remove-font-lock-face (match-beginning 2) (match-end 2)))) - (goto-char start-pos)) - - ;; Check for a type, but be prepared to skip over leading - ;; specifiers like "static". Unknown symbols are treated as - ;; possible types, but they could also be specifiers disguised - ;; through macros like __INLINE__, so we recognize both types and - ;; known specifiers after them too. - (while (let ((start (point)) - (res (unless (eq at-type t) - ;; Don't look for a type if we already found a - ;; positive one; we only loop for the - ;; `c-specifier-key' check then. - (c-forward-type)))) - - (when res - ;; Found a known or possible type or a prefix of a known - ;; type. - - (when at-type - ;; Got two identifiers with nothing but whitespace - ;; between them. That can only happen in - ;; declarations. - (setq at-decl-or-cast t) - - (when (eq at-type 'found) - ;; If the previous identifier is a found type we - ;; record it as a real one; it might be some sort of - ;; alias for a prefix like "unsigned". - (save-excursion - (goto-char type-start) - (let ((c-promote-possible-types t)) - (c-forward-type))))) - - (setq prev-at-type at-type - prev-type-start type-start - prev-type-end type-end - at-type res - type-start start - type-end (point)) - - ;; If the type isn't known we continue so that we'll - ;; jump over all specifiers and type identifiers. The - ;; reason to do this for a known type prefix is to make - ;; things like "unsigned INT16" work. - (setq res (not (eq res t)))) - - (if (looking-at c-specifier-key) - ;; Found a known specifier keyword. The specifier - ;; keywords are restrictive, so we check for them - ;; anywhere inside or around the type(s). We thereby - ;; avoid having special cases for specifiers like MSVC - ;; '__declspec' which can come after the type. - (progn - (setq at-decl-or-cast t) - (let ((kwd-sym (c-keyword-sym (match-string 1)))) - (when (c-keyword-member - kwd-sym 'c-typedef-decl-kwds) - (setq at-typedef t)) - (when (c-keyword-member - kwd-sym 'c-typeless-decl-kwds) - (setq maybe-typeless t))) - (c-forward-keyword-clause) - ;; Move type-end forward if we've passed a type, - ;; otherwise move start-pos forward. - (if at-type - (setq type-end (point)) - (setq start-pos (point)))) - - res))) - - (cond - ((eq at-type 'prefix) - ;; A prefix type is itself a primitive type when it's not - ;; followed by another type. - (setq at-type t)) - - ((not at-type) - ;; Got no type but set things up to continue anyway to handle the - ;; various cases when a declaration doesn't start with a type. - (setq type-end start-pos)) + ;; Set `context'. Look for "<" for the sake of C++-style template + ;; arglists. + (if (memq (char-before match-pos) '(?\( ?, ?\[ ?<)) - ((and (eq at-type 'maybe) - (c-major-mode-is 'c++-mode)) - ;; If it's C++ then check if the last "type" ends on the form - ;; "foo::foo" or "foo::~foo", i.e. if it's the name of a - ;; (con|de)structor. - (save-excursion - (let (name end-2 end-1) - (goto-char type-end) - (c-backward-syntactic-ws) - (setq end-2 (point)) - (when (and - (c-simple-skip-symbol-backward) - (progn - (setq name - (buffer-substring-no-properties (point) end-2)) - ;; Cheating in the handling of syntactic ws below. - (< (skip-chars-backward ":~ \t\n\r\v\f") 0)) - (progn - (setq end-1 (point)) - (c-simple-skip-symbol-backward)) - (>= (point) type-start) - (equal (buffer-substring-no-properties (point) end-1) - name)) - ;; It is a (con|de)structor name. In that case the - ;; declaration is typeless so zap out any preceding - ;; identifier(s) that we might have taken as types. - (goto-char type-start) - (setq at-type nil - prev-at-type nil - type-end type-start)))))) - - ;; Check for and step over a type decl expression after the thing - ;; that is or might be a type. This can't be skipped since we need - ;; the correct end position of the declarator for - ;; `max-type-decl-end-*'. - (let ((start (point)) (paren-depth 0) pos - ;; True if there's a non-open-paren match of - ;; `c-type-decl-prefix-key'. - got-prefix - ;; True if the declarator is surrounded by a parenthesis pair. - got-parens - ;; True if there is an identifier in the declarator. - got-identifier - ;; True if there's a non-close-paren match of - ;; `c-type-decl-suffix-key'. - got-suffix - ;; True if there's a prefix or suffix match outside the - ;; outermost paren pair that surrounds the declarator. - got-prefix-before-parens - got-suffix-after-parens - ;; True if we've parsed the type decl to a token that - ;; is known to end declarations in this context. - at-decl-end - ;; The earlier values of `at-type', `type-start' and - ;; `type-end' if we've shifted the type backwards. - identifier-type identifier-start identifier-end) - (goto-char type-end) - - ;; Skip over type decl prefix operators. (Note similar code in - ;; `c-font-lock-declarators'.) - (while (and (looking-at c-type-decl-prefix-key) - (if (and (c-major-mode-is 'c++-mode) - (match-beginning 2)) - ;; If the second submatch matches in C++ then - ;; we're looking at an identifier that's a prefix - ;; only if it specifies a member pointer. - (when (setq got-identifier (c-forward-name)) - (if (looking-at "\\(::\\)") - ;; We only check for a trailing "::" and - ;; let the "*" that should follow be - ;; matched in the next round. - (progn (setq got-identifier nil) t) - ;; It turned out to be the real identifier, - ;; so stop. - nil)) - t)) - (if (eq (char-after) ?\() - (progn - (setq paren-depth (1+ paren-depth)) - (forward-char)) - (unless got-prefix-before-parens - (setq got-prefix-before-parens (= paren-depth 0))) - (setq got-prefix t) - (goto-char (match-end 1))) - (c-forward-syntactic-ws)) - (setq got-parens (> paren-depth 0)) - - ;; Skip over an identifier. - (or got-identifier - (and (looking-at c-identifier-start) - (setq got-identifier (c-forward-name)))) + ;; Find out the type of the arglist. + (if (<= match-pos (point-min)) + (setq context 'arglist) + (let ((type (c-get-char-property (1- match-pos) 'c-type))) + (cond ((eq type 'c-decl-arg-start) + ;; Got a cached hit in a declaration arglist. + (setq context 'decl)) + ((or (eq type 'c-<>-arg-sep) + (eq (char-before match-pos) ?<)) + ;; Inside an angle bracket arglist. + (setq context '<>)) + (type + ;; Got a cached hit in some other type of arglist. + (setq context 'arglist)) + ((if inside-macro + (< match-pos max-type-decl-end-before-token) + (< match-pos max-type-decl-end)) + ;; The point is within the range of a previously + ;; encountered type decl expression, so the arglist + ;; is probably one that contains declarations. + ;; However, if `c-recognize-paren-inits' is set it + ;; might also be an initializer arglist. + (setq context 'decl) + ;; The result of this check is cached with a char + ;; property on the match token, so that we can look + ;; it up again when refontifying single lines in a + ;; multiline declaration. + (c-put-char-property (1- match-pos) + 'c-type 'c-decl-arg-start)) + (t + (setq context 'arglist))))) - ;; Skip over type decl suffix operators. - (while (if (looking-at c-type-decl-suffix-key) - (if (eq (char-after) ?\)) - (when (> paren-depth 0) - (setq paren-depth (1- paren-depth)) - (forward-char) - t) - (when (if (save-match-data (looking-at "\\s\(")) - (c-safe (c-forward-sexp 1) t) - (goto-char (match-end 1)) - t) - (unless got-suffix-after-parens - (setq got-suffix-after-parens (= paren-depth 0))) - (setq got-suffix t))) - ;; No suffix matched. We might have matched the - ;; identifier as a type and the open paren of a function - ;; arglist as a type decl prefix. In that case we - ;; should "backtrack": Reinterpret the last type as the - ;; identifier, move out of the arglist and continue - ;; searching for suffix operators. - ;; - ;; Do this even if there's no preceding type, to cope - ;; with old style function declarations in K&R C, - ;; (con|de)structors in C++ and `c-typeless-decl-kwds' - ;; style declarations. That isn't applicable in an - ;; arglist context, though. - (when (and (= paren-depth 1) - (not got-prefix-before-parens) - (not (eq at-type t)) - (or prev-at-type - maybe-typeless - (when c-recognize-typeless-decls - (not arglist-type))) - (setq pos (c-up-list-forward (point))) - (eq (char-before pos) ?\))) - (c-fl-shift-type-backward) - (goto-char pos) - t)) - (c-forward-syntactic-ws)) + (setq context nil)) + + ;; If we're in a normal arglist context we don't want to + ;; recognize commas in nested angle bracket arglists since + ;; those commas could be part of our own arglist. + (setq c-restricted-<>-arglists (and c-recognize-<>-arglists + (eq context 'arglist)) - (when (and maybe-typeless - (not got-identifier) - (not got-prefix) - at-type - (not (eq at-type t))) - ;; Have found no identifier but `c-typeless-decl-kwds' has - ;; matched so we know we're inside a declaration. The - ;; preceding type must be the identifier instead. - (c-fl-shift-type-backward)) - - (setq - at-decl-or-cast - (catch 'at-decl-or-cast - - (when (> paren-depth 0) - ;; Encountered something inside parens that isn't matched by - ;; the `c-type-decl-*' regexps, so it's not a type decl - ;; expression. Try to skip out to the same paren depth to - ;; not confuse the cast check below. - (c-safe (goto-char (scan-lists (point) 1 paren-depth))) - (throw 'at-decl-or-cast nil)) - - (setq at-decl-end - (looking-at (cond ((eq arglist-type '<>) "[,>]") - (arglist-type "[,\)]") - (t "[,;]")))) + ;; Now analyze the construct. + decl-or-cast (c-forward-decl-or-cast-1 + match-pos context last-cast-end)) - ;; Now we've collected info about various characteristics of - ;; the construct we're looking at. Below follows a decision - ;; tree based on that. It's ordered to check more certain - ;; signs before less certain ones. - - (if got-identifier - (progn - - (when (and (or at-type maybe-typeless) - (not (or got-prefix got-parens))) - ;; Got another identifier directly after the type, so - ;; it's a declaration. - (throw 'at-decl-or-cast t)) + (if (not decl-or-cast) + ;; False alarm. Return t to go on to the next check. + t - (when (and got-parens - (not got-prefix) - (not got-suffix-after-parens) - (or prev-at-type maybe-typeless)) - ;; Got a declaration of the form "foo bar (gnu);" - ;; where we've recognized "bar" as the type and "gnu" - ;; as the declarator. In this case it's however more - ;; likely that "bar" is the declarator and "gnu" a - ;; function argument or initializer (if - ;; `c-recognize-paren-inits' is set), since the parens - ;; around "gnu" would be superfluous if it's a - ;; declarator. Shift the type one step backward. - (c-fl-shift-type-backward))) - - ;; Found no identifier. + (if (eq decl-or-cast 'cast) + ;; Save the position after the previous cast so we can feed + ;; it to `c-forward-decl-or-cast-1' in the next round. That + ;; helps it discover cast chains like "(a) (b) c". + (setq last-cast-end (point)) - (if prev-at-type - (when (or (= (point) start) - (and got-suffix - (not got-prefix) - (not got-parens))) - ;; Got two types after each other, so if this isn't a - ;; cast then the latter probably is the identifier and - ;; we should back up to the previous type. - (setq backup-if-not-cast t) - (throw 'at-decl-or-cast t)) - - (when (eq at-type t) - ;; If the type is known we know that there can't be any - ;; identifier somewhere else, and it's only in - ;; declarations in e.g. function prototypes and in casts - ;; that the identifier may be left out. - (throw 'at-decl-or-cast t)) - - (when (= (point) start) - ;; Only got a single identifier (parsed as a type so - ;; far). - (if (and - ;; Check that the identifier isn't at the start of - ;; an expression. - at-decl-end - (cond - ((eq arglist-type 'decl) - ;; Inside an arglist that contains declarations. - ;; If K&R style declarations and parenthesis - ;; style initializers aren't allowed then the - ;; single identifier must be a type, else we - ;; require that it's known or found (primitive - ;; types are handled above). - (or (and (not c-recognize-knr-p) - (not c-recognize-paren-inits)) - (memq at-type '(known found)))) - ((eq arglist-type '<>) - ;; Inside a template arglist. Accept known and - ;; found types; other identifiers could just as - ;; well be constants in C++. - (memq at-type '(known found))))) - (throw 'at-decl-or-cast t) - (throw 'at-decl-or-cast nil)))) - - (if (and - got-parens - (not got-prefix) - (not arglist-type) - (not (eq at-type t)) - (or - prev-at-type - maybe-typeless - (when c-recognize-typeless-decls - (or (not got-suffix) - (not (looking-at - c-after-suffixed-type-maybe-decl-key)))))) - ;; Got an empty paren pair and a preceding type that - ;; probably really is the identifier. Shift the type - ;; backwards to make the last one the identifier. This - ;; is analogous to the "backtracking" done inside the - ;; `c-type-decl-suffix-key' loop above. - ;; - ;; Exception: In addition to the conditions in that - ;; "backtracking" code, do not shift backward if we're - ;; not looking at either `c-after-suffixed-type-decl-key' - ;; or "[;,]". Since there's no preceding type, the - ;; shift would mean that the declaration is typeless. - ;; But if the regexp doesn't match then we will simply - ;; fall through in the tests below and not recognize it - ;; at all, so it's better to try it as an abstract - ;; declarator instead. - (c-fl-shift-type-backward) - - ;; Still no identifier. + ;; Set `max-type-decl-end' or `max-type-decl-end-before-token' + ;; under the assumption that we're after the first type decl + ;; expression in the declaration now. That's not really true; + ;; we could also be after a parenthesized initializer + ;; expression in C++, but this is only used as a last resort + ;; to slant ambiguous expression/declarations, and overall + ;; it's worth the risk to occasionally fontify an expression + ;; as a declaration in an initializer expression compared to + ;; getting ambiguous things in normal function prototypes + ;; fontified as expressions. + (if inside-macro + (when (> (point) max-type-decl-end-before-token) + (setq max-type-decl-end-before-token (point))) + (when (> (point) max-type-decl-end) + (setq max-type-decl-end (point)))) - (when (and got-prefix (or got-parens got-suffix)) - ;; Require `got-prefix' together with either - ;; `got-parens' or `got-suffix' to recognize it as an - ;; abstract declarator: `got-parens' only is probably an - ;; empty function call. `got-suffix' only can build an - ;; ordinary expression together with the preceding - ;; identifier which we've taken as a type. We could - ;; actually accept on `got-prefix' only, but that can - ;; easily occur temporarily while writing an expression - ;; so we avoid that case anyway. We could do a better - ;; job if we knew the point when the fontification was - ;; invoked. - (throw 'at-decl-or-cast t)))) - - (when at-decl-or-cast - ;; By now we've located the type in the declaration that we - ;; know we're in. - (throw 'at-decl-or-cast t)) - - (when (and got-identifier - (not arglist-type) - (looking-at c-after-suffixed-type-decl-key) - (if (and got-parens - (not got-prefix) - (not got-suffix) - (not (eq at-type t))) - ;; Shift the type backward in the case that - ;; there's a single identifier inside parens. - ;; That can only occur in K&R style function - ;; declarations so it's more likely that it - ;; really is a function call. Therefore we - ;; only do this after - ;; `c-after-suffixed-type-decl-key' has - ;; matched. - (progn (c-fl-shift-type-backward) t) - got-suffix-after-parens)) - ;; A declaration according to - ;; `c-after-suffixed-type-decl-key'. - (throw 'at-decl-or-cast t)) - - (when (and (or got-prefix (not got-parens)) - (memq at-type '(t known))) - ;; It's a declaration if a known type precedes it and it - ;; can't be a function call. - (throw 'at-decl-or-cast t)) + ;; Back up to the type to fontify the declarator(s). + (goto-char (car decl-or-cast)) - ;; If we get here we can't tell if this is a type decl or a - ;; normal expression by looking at it alone. (That's under - ;; the assumption that normal expressions always can look like - ;; type decl expressions, which isn't really true but the - ;; cases where it doesn't hold are so uncommon (e.g. some - ;; placements of "const" in C++) it's not worth the effort to - ;; look for them.) - - (unless (or at-decl-end (looking-at "=[^=]")) - ;; If this is a declaration it should end here or its - ;; initializer(*) should start here, so check for allowed - ;; separation tokens. Note that this rule doesn't work - ;; e.g. with a K&R arglist after a function header. - ;; - ;; *) Don't check for C++ style initializers using parens - ;; since those already have been matched as suffixes. - (throw 'at-decl-or-cast nil)) - - ;; Below are tests that only should be applied when we're - ;; certain to not have parsed halfway through an expression. - - (when (memq at-type '(t known)) - ;; The expression starts with a known type so treat it as a - ;; declaration. - (throw 'at-decl-or-cast t)) - - (when (and (c-major-mode-is 'c++-mode) - ;; In C++ we check if the identifier is a known - ;; type, since (con|de)structors use the class name - ;; as identifier. We've always shifted over the - ;; identifier as a type and then backed up again in - ;; this case. - identifier-type - (or (memq identifier-type '(found known)) - (and (eq (char-after identifier-start) ?~) - ;; `at-type' probably won't be 'found for - ;; destructors since the "~" is then part - ;; of the type name being checked against - ;; the list of known types, so do a check - ;; without that operator. - (or (save-excursion - (goto-char (1+ identifier-start)) - (c-forward-syntactic-ws) - (c-with-syntax-table - c-identifier-syntax-table - (looking-at c-known-type-key))) - (c-check-type (1+ identifier-start) - identifier-end))))) - (throw 'at-decl-or-cast t)) + (let ((decl-list + (if context + ;; Should normally not fontify a list of + ;; declarators inside an arglist, but the first + ;; argument in the ';' separated list of a "for" + ;; statement is an exception. + (when (eq (char-before match-pos) ?\() + (save-excursion + (goto-char (1- match-pos)) + (c-backward-syntactic-ws) + (and (c-simple-skip-symbol-backward) + (looking-at c-paren-stmt-key)))) + t))) - (if got-identifier - (progn - (when (and got-prefix-before-parens - at-type - (or at-decl-end (looking-at "=[^=]")) - (not arglist-type) - (not got-suffix)) - ;; Got something like "foo * bar;". Since we're not - ;; inside an arglist it would be a meaningless - ;; expression because the result isn't used. We - ;; therefore choose to recognize it as a declaration. - ;; Do not allow a suffix since it could then be a - ;; function call. - (throw 'at-decl-or-cast t)) - - (when (and (or got-suffix-after-parens - (looking-at "=[^=]")) - (eq at-type 'found) - (not (eq arglist-type 'other))) - ;; Got something like "a (*b) (c);" or "a (b) = c;". - ;; It could be an odd expression or it could be a - ;; declaration. Treat it as a declaration if "a" has - ;; been used as a type somewhere else (if it's a known - ;; type we won't get here). - (throw 'at-decl-or-cast t))) - - (when (and arglist-type - (or got-prefix - (and (eq arglist-type 'decl) - (not c-recognize-paren-inits) - (or got-parens got-suffix)))) - ;; Got a type followed by an abstract declarator. If - ;; `got-prefix' is set it's something like "a *" without - ;; anything after it. If `got-parens' or `got-suffix' is - ;; set it's "a()", "a[]", "a()[]", or similar, which we - ;; accept only if the context rules out expressions. - (throw 'at-decl-or-cast t))) + ;; Fix the `c-decl-id-start' or `c-decl-type-start' property + ;; before the first declarator if it's a list. + ;; `c-font-lock-declarators' handles the rest. + (when decl-list + (save-excursion + (c-backward-syntactic-ws) + (unless (bobp) + (c-put-char-property (1- (point)) 'c-type + (if (cdr decl-or-cast) + 'c-decl-type-start + 'c-decl-id-start))))) - ;; If we had a complete symbol table here (which rules out - ;; `c-found-types') we should return t due to the - ;; disambiguation rule (in at least C++) that anything that - ;; can be parsed as a declaration is a declaration. Now we're - ;; being more defensive and prefer to highlight things like - ;; "foo (bar);" as a declaration only if we're inside an - ;; arglist that contains declarations. - (eq arglist-type 'decl)))) - - ;; Point is now after the type decl expression. - - (cond - ;; Check for a cast. - ((save-excursion - (and - c-cast-parens - - ;; Should be the first type/identifier in a cast paren. - (memq arglist-match c-cast-parens) - - ;; The closing paren should follow. - (progn - (c-forward-syntactic-ws) - (looking-at "\\s\)")) - - ;; There should be a primary expression after it. - (let (pos) - (forward-char) - (c-forward-syntactic-ws) - (setq cast-end (point)) - (and (looking-at c-primary-expr-regexp) - (progn - (setq pos (match-end 0)) - (or - ;; Check if the expression begins with a prefix - ;; keyword. - (match-beginning 2) - (if (match-beginning 1) - ;; Expression begins with an ambiguous operator. - ;; Treat it as a cast if it's a type decl or if - ;; we've recognized the type somewhere else. - (or at-decl-or-cast - (memq at-type '(t known found))) - ;; Unless it's a keyword, it's the beginning of a - ;; primary expression. - (not (looking-at c-keywords-regexp))))) - ;; If `c-primary-expr-regexp' matched a nonsymbol - ;; token, check that it matched a whole one so that we - ;; don't e.g. confuse the operator '-' with '->'. It's - ;; ok if it matches further, though, since it e.g. can - ;; match the float '.5' while the operator regexp only - ;; matches '.'. - (or (not (looking-at c-nonsymbol-token-regexp)) - (<= (match-end 0) pos)))) + (c-font-lock-declarators + (point-max) decl-list (cdr decl-or-cast)))) - ;; There should either be a cast before it or something that - ;; isn't an identifier or close paren. - (/= match-pos 0) - (progn - (goto-char (1- match-pos)) - (or (eq (point) last-cast-end) - (progn - (c-backward-syntactic-ws) - (if (< (skip-syntax-backward "w_") 0) - ;; It's a symbol. Accept it only if it's one of - ;; the keywords that can precede an expression - ;; (without surrounding parens). - (looking-at c-simple-stmt-key) - (and - ;; Check that it isn't a close paren (block close - ;; is ok, though). - (not (memq (char-before) '(?\) ?\]))) - ;; Check that it isn't a nonsymbol identifier. - (not (c-on-identifier))))))))) - - ;; Handle the cast. - (setq last-cast-end cast-end) - (when (and at-type (not (eq at-type t))) - (let ((c-promote-possible-types t)) - (goto-char type-start) - (c-forward-type)))) - - (at-decl-or-cast - ;; We're at a declaration. Highlight the type and the following - ;; declarators. - - (when backup-if-not-cast - (c-fl-shift-type-backward t)) - - (when (and (eq arglist-type 'decl) (looking-at ",")) - ;; Make sure to propagate the `c-decl-arg-start' property to - ;; the next argument if it's set in this one, to cope with - ;; interactive refontification. - (c-put-char-property (point) 'c-type 'c-decl-arg-start)) + ;; A cast or declaration has been successfully identified, so do + ;; all the fontification of types and refs that's been recorded. + (c-fontify-recorded-types-and-refs) + nil)) - ;; Set `max-type-decl-end' or `max-type-decl-end-before-token' - ;; under the assumption that we're after the first type decl - ;; expression in the declaration now. That's not really true; we - ;; could also be after a parenthesized initializer expression in - ;; C++, but this is only used as a last resort to slant ambiguous - ;; expression/declarations, and overall it's worth the risk to - ;; occasionally fontify an expression as a declaration in an - ;; initializer expression compared to getting ambiguous things in - ;; normal function prototypes fontified as expressions. - (if inside-macro - (when (> (point) max-type-decl-end-before-token) - (setq max-type-decl-end-before-token (point))) - (when (> (point) max-type-decl-end) - (setq max-type-decl-end (point)))) - - (when (and at-type (not (eq at-type t))) - (let ((c-promote-possible-types t)) - (goto-char type-start) - (c-forward-type))) - - (goto-char type-end) - - (let ((decl-list - (if arglist-type - ;; Should normally not fontify a list of declarators - ;; inside an arglist, but the first argument in the - ;; ';' separated list of a "for" statement is an - ;; exception. - (when (and (eq arglist-match ?\() (/= match-pos 0)) - (save-excursion - (goto-char (1- match-pos)) - (c-backward-syntactic-ws) - (and (c-simple-skip-symbol-backward) - (looking-at c-paren-stmt-key)))) - t))) - - ;; Fix the `c-decl-id-start' or `c-decl-type-start' property - ;; before the first declarator if it's a list. - ;; `c-font-lock-declarators' handles the rest. - (when decl-list - (save-excursion - (c-backward-syntactic-ws) - (unless (bobp) - (c-put-char-property (1- (point)) 'c-type - (if at-typedef - 'c-decl-type-start - 'c-decl-id-start))))) - - (c-font-lock-declarators (point-max) decl-list at-typedef))) - - (t - ;; False alarm. Skip the fontification done below. - (throw 'false-alarm t))) - - ;; A cast or declaration has been successfully identified, so do - ;; all the fontification of types and refs that's been recorded by - ;; the calls to `c-forward-type' and `c-forward-name' above. - (c-fontify-recorded-types-and-refs) - nil))) + ;; It was a false alarm. Check if we're in a label instead. + (goto-char start-pos) + (when (c-forward-label t match-pos nil) + ;; Can't use `c-fontify-types-and-refs' here since we + ;; should use the label face. + (let (elem) + (while c-record-ref-identifiers + (setq elem (car c-record-ref-identifiers) + c-record-ref-identifiers (cdr c-record-ref-identifiers)) + (c-put-font-lock-face (car elem) (cdr elem) + c-label-face-name))) + ;; `c-forward-label' probably has added a `c-decl-end' + ;; marker, so return t to `c-find-decl-spots' to signal + ;; that. + t)))) nil))) @@ -1794,32 +1224,40 @@ ;; Fontify types preceded by `c-type-prefix-kwds' and the ;; identifiers in the declarations they might start. ,@(when (c-lang-const c-type-prefix-kwds) - (let ((prefix-re (c-make-keywords-re nil - (c-lang-const c-type-prefix-kwds)))) + (let* ((prefix-re (c-make-keywords-re nil + (c-lang-const c-type-prefix-kwds))) + (type-match (+ 2 + (regexp-opt-depth prefix-re) + (c-lang-const c-simple-ws-depth)))) `((,(c-make-font-lock-search-function - (concat "\\<\\(" prefix-re "\\)" - "[ \t\n\r\f\v]+" - "\\(" (c-lang-const c-symbol-key) "\\)") - `(,(+ (c-regexp-opt-depth prefix-re) 2) + (concat "\\<\\(" prefix-re "\\)" ; 1 + (c-lang-const c-simple-ws) "+" + (concat "\\(" ; 2 + prefix-re + c-simple-ws + (c-lang-const c-symbol-key) + "\\)")) + `(,type-match 'font-lock-type-face t) - '((c-font-lock-declarators limit t nil) + `((c-font-lock-declarators limit t nil) (save-match-data - (goto-char (match-end 2)) + (goto-char (match-end ,type-match)) (c-forward-syntactic-ws)) - (goto-char (match-end 2)))))))) + (goto-char (match-end ,type-match)))))))) ;; Fontify special declarations that lacks a type. ,@(when (c-lang-const c-typeless-decl-kwds) `((,(c-make-font-lock-search-function (concat "\\<\\(" - (c-regexp-opt (c-lang-const c-typeless-decl-kwds)) + (regexp-opt (c-lang-const c-typeless-decl-kwds)) "\\)\\>") '((c-font-lock-declarators limit t nil) (save-match-data (goto-char (match-end 1)) (c-forward-syntactic-ws)) (goto-char (match-end 1))))))) - )) + + ;; Fontify generic colon labels in languages that support them. + ,@(when (c-lang-const c-recognize-colon-labels) + `(c-font-lock-labels)))) (c-lang-defconst c-complex-decl-matchers "Complex font lock matchers for types and declarations. Used on level @@ -1828,10 +1266,6 @@ t `(;; Initialize some things before the search functions below. c-font-lock-complex-decl-prepare - ;; Fontify angle bracket arglists like templates in C++. - ,@(when (c-lang-const c-recognize-<>-arglists) - `(c-font-lock-<>-arglists)) - ,@(if (c-major-mode-is 'objc-mode) ;; Fontify method declarations in Objective-C, but first ;; we have to put the `c-decl-end' `c-type' property on @@ -1847,17 +1281,14 @@ nil))) '((c-put-char-property (1- (match-end 1)) 'c-type 'c-decl-end))) - - c-font-lock-objc-methods) + c-font-lock-objc-methods)) - (when (c-lang-const c-opt-access-key) - `(,(c-make-font-lock-search-function - (c-lang-const c-opt-access-key) - '((c-put-char-property (1- (match-end 0)) - 'c-type 'c-decl-end)))))) + ;; Fontify all declarations, casts and normal labels. + c-font-lock-declarations - ;; Fontify all declarations and casts. - c-font-lock-declarations + ;; Fontify angle bracket arglists like templates in C++. + ,@(when (c-lang-const c-recognize-<>-arglists) + `(c-font-lock-<>-arglists)) ;; The first two rules here mostly find occurences that ;; `c-font-lock-declarations' has found already, but not @@ -1870,9 +1301,9 @@ (c-lang-const c-primitive-type-kwds)))) (if (c-major-mode-is 'pike-mode) ;; No symbol is a keyword after "->" in Pike. - `(,(concat "\\(\\=\\|\\(\\=\\|[^-]\\)[^>]\\)" + `(,(concat "\\(\\=.?\\|[^>]\\|[^-]>\\)" "\\<\\(" re "\\)\\>") - 3 font-lock-type-face) + 2 font-lock-type-face) `(,(concat "\\<\\(" re "\\)\\>") 1 'font-lock-type-face))) @@ -1900,8 +1331,8 @@ (unless (c-skip-comments-and-strings limit) (c-forward-syntactic-ws) ;; Handle prefix declaration specifiers. - (when (looking-at c-specifier-key) - (c-forward-keyword-clause)) + (when (looking-at c-prefix-spec-kwds-re) + (c-forward-keyword-clause 1)) ,(if (c-major-mode-is 'c++-mode) `(when (and (c-forward-type) (eq (char-after) ?=)) @@ -1949,12 +1380,15 @@ )) (defun c-font-lock-labels (limit) - ;; Fontify all the declarations from the point to LIMIT. Assumes + ;; Fontify all statement labels from the point to LIMIT. Assumes ;; that strings and comments have been fontified already. Nil is ;; always returned. ;; - ;; This function can make hidden buffer changes, but the font-lock - ;; context covers that. + ;; Note: This function is only used on decoration level 2; this is + ;; taken care of directly by the gargantuan + ;; `c-font-lock-declarations' on higher levels. + ;; + ;; This function might do hidden buffer changes. (let (continue-pos id-start ;; The font-lock package in Emacs is known to clobber @@ -2027,11 +1461,9 @@ (c-forward-syntactic-ws)) (goto-char (match-end 0))))))) - ;; Fontify labels in languages that supports them. - ,@(when (c-lang-const c-label-key) - - `(;; Fontify labels after goto etc. - ;; (Got three different interpretation levels here, + ;; Fontify labels after goto etc. + ,@(when (c-lang-const c-before-label-kwds) + `(;; (Got three different interpretation levels here, ;; which makes it a bit complicated: 1) The backquote ;; stuff is expanded when compiled or loaded, 2) the ;; eval form is evaluated at font-lock setup (to @@ -2048,11 +1480,8 @@ "\\(" ; identifier-offset (c-lang-const c-symbol-key) "\\)") - (list ,(+ (c-regexp-opt-depth c-before-label-re) 2) - c-label-face-name nil t)))) - - ;; Fontify normal labels. - c-font-lock-labels)) + (list ,(+ (regexp-opt-depth c-before-label-re) 2) + c-label-face-name nil t)))))) ;; Fontify the clauses after various keywords. ,@(when (or (c-lang-const c-type-list-kwds) @@ -2068,7 +1497,7 @@ (c-lang-const c-paren-type-kwds))) "\\)\\>") '((c-fontify-types-and-refs ((c-promote-possible-types t)) - (c-forward-keyword-clause) + (c-forward-keyword-clause 1) (if (> (point) limit) (goto-char limit)))))))) )) @@ -2135,8 +1564,6 @@ ;; to override, but we should otoh avoid clobbering a user setting. ;; This heuristic for that isn't perfect, but I can't think of any ;; better. /mast - ;; - ;; This function does not do any hidden buffer changes. (when (and (boundp def-var) (memq (symbol-value def-var) (cons nil @@ -2193,6 +1620,8 @@ ;; ;; As usual, C++ takes the prize in coming up with a hard to parse ;; syntax. :P + ;; + ;; This function might do hidden buffer changes. (unless (c-skip-comments-and-strings limit) (save-excursion @@ -2338,50 +1767,13 @@ ;;; Objective-C. -(defun c-font-lock-objc-iip-decl () - ;; Assuming the point is after an "@interface", "@implementation", - ;; "@protocol" declaration, fontify all the types in the directive. - ;; Return t if the directive was fully recognized. Point will then - ;; be at the end of it. - - (c-fontify-types-and-refs - (start-char - (c-promote-possible-types t) - ;; Turn off recognition of angle bracket arglists while parsing - ;; types here since the protocol reference list might then be - ;; considered part of the preceding name or superclass-name. - c-recognize-<>-arglists) - (catch 'break - - ;; Handle the name of the class itself. - (c-forward-syntactic-ws) - (unless (c-forward-type) (throw 'break nil)) - - ;; Look for ": superclass-name" or "( category-name )". - (when (looking-at "[:\(]") - (setq start-char (char-after)) - (forward-char) - (c-forward-syntactic-ws) - (unless (c-forward-type) (throw 'break nil)) - (when (eq start-char ?\() - (unless (eq (char-after) ?\)) (throw 'break nil)) - (forward-char) - (c-forward-syntactic-ws))) - - ;; Look for a protocol reference list. - (when (if (eq (char-after) ?<) - (progn - (setq c-recognize-<>-arglists t) - (c-forward-<>-arglist t t)) - t) - (c-put-char-property (1- (point)) 'c-type 'c-decl-end) - t)))) - (defun c-font-lock-objc-method () ;; Assuming the point is after the + or - that starts an Objective-C ;; method declaration, fontify it. This must be done before normal ;; casts, declarations and labels are fontified since they will get ;; false matches in these things. + ;; + ;; This function might do hidden buffer changes. (c-fontify-types-and-refs ((first t) @@ -2430,6 +1822,8 @@ (defun c-font-lock-objc-methods (limit) ;; Fontify method declarations in Objective-C. Nil is always ;; returned. + ;; + ;; This function might do hidden buffer changes. (let (;; The font-lock package in Emacs is known to clobber ;; `parse-sexp-lookup-properties' (when it exists). @@ -2605,6 +1999,8 @@ ;; Note that faces added through KEYWORDS should never replace the ;; existing `c-doc-face-name' face since the existence of that face ;; is used as a flag in other code to skip comments. + ;; + ;; This function might do hidden buffer changes. (let (comment-beg region-beg) (if (eq (get-text-property (point) 'face) @@ -2686,6 +2082,8 @@ ;; between the point and LIMIT that only is fontified with ;; `c-doc-face-name'. If a match is found then submatch 0 surrounds ;; the first char and t is returned, otherwise nil is returned. + ;; + ;; This function might do hidden buffer changes. (let (start) (while (if (re-search-forward regexp limit t) (not (eq (get-text-property @@ -2697,11 +2095,40 @@ (copy-marker (1+ start)))) t))) +;; GtkDoc patterns contributed by Masatake YAMATO <jet@gyve.org>. + +(defconst gtkdoc-font-lock-doc-comments + (let ((symbol "[a-zA-Z0-9_]+") + (header "^ \\* ")) + `((,(concat header "\\(" symbol "\\):[ \t]*$") + 1 ,c-doc-markup-face-name prepend nil) + (,(concat symbol "()") + 0 ,c-doc-markup-face-name prepend nil) + (,(concat header "\\(" "@" symbol "\\):") + 1 ,c-doc-markup-face-name prepend nil) + (,(concat "[#%]" symbol) + 0 ,c-doc-markup-face-name prepend nil)) + )) + +(defconst gtkdoc-font-lock-doc-protection + `(("< \\(public\\|private\\|protected\\) >" + 1 ,c-doc-markup-face-name prepend nil))) + +(defconst gtkdoc-font-lock-keywords + `((,(lambda (limit) + (c-font-lock-doc-comments "/\\*\\*$" limit + gtkdoc-font-lock-doc-comments) + (c-font-lock-doc-comments "/\\*< " limit + gtkdoc-font-lock-doc-protection) + )))) + +;; Javadoc. + (defconst javadoc-font-lock-doc-comments `(("{@[a-z]+[^}\n\r]*}" ; "{@foo ...}" markup. 0 ,c-doc-markup-face-name prepend nil) - ("^\\(/\\*\\)?[ \t*]*\\(@[a-z]+\\)" ; "@foo ..." markup. - 2 ,c-doc-markup-face-name prepend nil) + ("^\\(/\\*\\)?\\(\\s \\|\\*\\)*\\(@[a-z]+\\)" ; "@foo ..." markup. + 3 ,c-doc-markup-face-name prepend nil) (,(concat "</?\\sw" ; HTML tags. "\\(" (concat "\\sw\\|\\s \\|[=\n\r*.:]\\|" @@ -2715,13 +2142,15 @@ ;; allowed in non-markup use. (,(lambda (limit) (c-find-invalid-doc-markup "[<>&]\\|{@" limit)) - 0 ,c-invalid-face-name prepend nil))) + 0 'font-lock-warning-face prepend nil))) (defconst javadoc-font-lock-keywords `((,(lambda (limit) (c-font-lock-doc-comments "/\\*\\*" limit javadoc-font-lock-doc-comments))))) +;; Pike autodoc. + (defconst autodoc-decl-keywords ;; Adorned regexp matching the keywords that introduce declarations ;; in Pike Autodoc. @@ -2736,6 +2165,8 @@ (defun autodoc-font-lock-line-markup (limit) ;; Fontify all line oriented keywords between the point and LIMIT. ;; Nil is always returned. + ;; + ;; This function might do hidden buffer changes. (let ((line-re (concat "^\\(\\(/\\*!\\|\\s *\\(" c-current-comment-prefix @@ -2765,7 +2196,7 @@ (and (eq (char-before) ?@) (not (eobp)) (progn (forward-char) - (skip-chars-forward " \t") + (skip-syntax-forward " ") (looking-at c-current-comment-prefix)))) (goto-char (match-end 0)) (c-remove-font-lock-face pos (1- end)) @@ -2804,7 +2235,7 @@ (and (eq (char-before) ?@) (not (eobp)) (progn (forward-char) - (skip-chars-forward " \t") + (skip-syntax-forward " ") (looking-at c-current-comment-prefix)))) (goto-char (match-end 0)))))) @@ -2818,12 +2249,14 @@ ;; Fontify remaining markup characters as invalid. (,(lambda (limit) (c-find-invalid-doc-markup "@" limit)) - 0 ,c-invalid-face-name prepend nil) + 0 'font-lock-warning-face prepend nil) )) (defun autodoc-font-lock-keywords () ;; Note that we depend on that `c-current-comment-prefix' has got ;; its proper value here. + ;; + ;; This function might do hidden buffer changes. ;; The `c-type' text property with `c-decl-end' is used to mark the ;; end of the `autodoc-decl-keywords' occurrences to fontify the @@ -2846,13 +2279,13 @@ ',(eval-when-compile ; Evaluate while compiling cc-fonts (list ;; Function names. - '("^[ \t]*\\(func\\(tion\\)?\\)\\>[ \t]*\\(\\sw+\\)?" + '("^\\s *\\(func\\(tion\\)?\\)\\>\\s *\\(\\sw+\\)?" (1 font-lock-keyword-face) (3 font-lock-function-name-face nil t)) ;; ;; Variable names. (cons (concat "\\<" - (c-regexp-opt + (regexp-opt '("ARGC" "ARGIND" "ARGV" "BINMODE" "CONVFMT" "ENVIRON" "ERRNO" "FIELDWIDTHS" "FILENAME" "FNR" "FS" "IGNORECASE" "LINT" "NF" "NR" "OFMT" "OFS" "ORS" "PROCINFO" "RLENGTH" @@ -2861,7 +2294,7 @@ ;; Special file names. (acm, 2002/7/22) ;; The following regexp was created by first evaluating this in GNU Emacs 21.1: - ;; (c-regexp-opt '("/dev/stdin" "/dev/stdout" "/dev/stderr" "/dev/fd/n" "/dev/pid" + ;; (regexp-opt '("/dev/stdin" "/dev/stdout" "/dev/stderr" "/dev/fd/n" "/dev/pid" ;; "/dev/ppid" "/dev/pgrpid" "/dev/user") 'words) ;; , removing the "?:" from each "\\(?:" (for backward compatibility with older Emacsen) ;; , replacing the "n" in "dev/fd/n" with "[0-9]+" @@ -2875,7 +2308,7 @@ (1 font-lock-variable-name-face t) (8 font-lock-variable-name-face t t)) ;; Do the same (almost) with - ;; (c-regexp-opt '("/inet/tcp/lport/rhost/rport" "/inet/udp/lport/rhost/rport" + ;; (regexp-opt '("/inet/tcp/lport/rhost/rport" "/inet/udp/lport/rhost/rport" ;; "/inet/raw/lport/rhost/rport") 'words) ;; This cannot be combined with the above pattern, because the match number ;; for the (optional) closing \" would then exceed 9. @@ -2886,7 +2319,7 @@ ;; Keywords. (concat "\\<" - (c-regexp-opt + (regexp-opt '("BEGIN" "END" "break" "continue" "delete" "do" "else" "exit" "for" "getline" "if" "in" "next" "nextfile" "return" "while") @@ -2896,7 +2329,7 @@ `(eval . (list ,(concat "\\<" - (c-regexp-opt + (regexp-opt '("adump" "and" "asort" "atan2" "bindtextdomain" "close" "compl" "cos" "dcgettext" "exp" "extension" "fflush" "gensub" "gsub" "index" "int" "length" "log" "lshift" @@ -2909,17 +2342,17 @@ ;; gawk debugging keywords. (acm, 2002/7/21) ;; (Removed, 2003/6/6. These functions are now fontified as built-ins) -;; (list (concat "\\<" (c-regexp-opt '("adump" "stopme") t) "\\>") +;; (list (concat "\\<" (regexp-opt '("adump" "stopme") t) "\\>") ;; 0 'font-lock-warning-face) ;; User defined functions with an apparent spurious space before the ;; opening parenthesis. acm, 2002/5/30. - `(,(concat "\\(\\w\\|_\\)" c-awk-escaped-nls* "[ \t]" + `(,(concat "\\(\\w\\|_\\)" c-awk-escaped-nls* "\\s " c-awk-escaped-nls*-with-space* "(") (0 'font-lock-warning-face)) ;; Space after \ in what looks like an escaped newline. 2002/5/31 - '("\\\\[ \t]+$" 0 font-lock-warning-face t) + '("\\\\\\s +$" 0 font-lock-warning-face t) ;; Unbalanced string (") or regexp (/) delimiters. 2002/02/16. '("\\s|" 0 font-lock-warning-face t nil)
--- a/lisp/progmodes/cc-langs.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/progmodes/cc-langs.el Sat Dec 10 21:18:28 2005 +0000 @@ -1,6 +1,7 @@ ;;; cc-langs.el --- language specific settings for CC Mode -;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, Inc. +;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, +;; Inc. ;; Authors: 1998- Martin Stjernholm ;; 1992-1999 Barry A. Warsaw @@ -24,7 +25,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to +;; along with this program; see the file COPYING. If not, write to ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. @@ -124,6 +125,7 @@ (cc-require 'cc-defs) (cc-require 'cc-vars) + ;; This file is not always loaded. See note above. (cc-external-require 'cl) @@ -140,16 +142,14 @@ c-lang-variable-inits-tail c-lang-variable-inits)) (defmacro c-lang-defvar (var val &optional doc) - "Declares the buffer local variable VAR to get the value VAL at mode -initialization, at which point VAL is evaluated. More accurately, VAL -is evaluated and bound to VAR when the result from the macro + "Declares the buffer local variable VAR to get the value VAL. VAL is +evaluated and assigned at mode initialization. More precisely, VAL is +evaluated and bound to VAR when the result from the macro `c-init-language-vars' is evaluated. `c-lang-const' is typically used in VAL to get the right value for the language being initialized, and such calls will be macro expanded to -the evaluated constant value at compile time. - -This macro does not do any hidden buffer changes." +the evaluated constant value at compile time." (when (and (not doc) (eq (car-safe val) 'c-lang-const) @@ -177,6 +177,57 @@ '(def-edebug-spec c-lang-defvar (&define name def-form &optional stringp))) +(eval-when-compile + ;; Some helper functions used when building the language constants. + + (defun c-filter-ops (ops opgroup-filter op-filter &optional xlate) + ;; Used to filter operators from the list OPS in a DWIM:ey way: + ;; OPS either has the structure of `c-operators', as a single + ;; group in `c-operators', or is a plain list of operators. + ;; OPGROUP-FILTER is used filter out the operator groups. It can + ;; be t to choose all groups, a list of the group type symbols to + ;; accept, or a function which will be called with the group + ;; symbol for each group and should return non-nil for those to + ;; include. OP-FILTER filters the individual operators in each + ;; group. It can be t to choose all operators, a regexp to test + ;; against each operator, or a function which will be called for + ;; each operator and should return non-nil for those to include. + ;; If XLATE is given, it's a function which is called for each + ;; matching operator and its return value is collected instead. + ;; If it returns a list, the elements are spliced directly into + ;; the final result, which is returned as a list with duplicates + ;; removed using `equal'. `c-mode-syntax-table' for the current + ;; mode is in effect during the whole procedure. + (unless (listp (car-safe ops)) + (setq ops (list ops))) + (cond ((eq opgroup-filter t) + (setq opgroup-filter (lambda (opgroup) t))) + ((not (functionp opgroup-filter)) + (setq opgroup-filter `(lambda (opgroup) + (memq opgroup ',opgroup-filter))))) + (cond ((eq op-filter t) + (setq op-filter (lambda (op) t))) + ((stringp op-filter) + (setq op-filter `(lambda (op) + (string-match ,op-filter op))))) + (unless xlate + (setq xlate 'identity)) + (c-with-syntax-table (c-lang-const c-mode-syntax-table) + (delete-duplicates + (mapcan (lambda (opgroup) + (when (if (symbolp (car opgroup)) + (when (funcall opgroup-filter (car opgroup)) + (setq opgroup (cdr opgroup)) + t) + t) + (mapcan (lambda (op) + (when (funcall op-filter op) + (let ((res (funcall xlate op))) + (if (listp res) res (list res))))) + opgroup))) + ops) + :test 'equal)))) + ;;; Various mode specific values that aren't language related. @@ -208,7 +259,7 @@ "----" ("Toggle..." ["Syntactic indentation" c-toggle-syntactic-indentation t] - ["Auto newline" c-toggle-auto-state t] + ["Auto newline" c-toggle-auto-newline t] ["Hungry delete" c-toggle-hungry-state t]))) @@ -261,6 +312,10 @@ (c-populate-syntax-table table) ;; Mode specific syntaxes. ,(cond ((c-major-mode-is 'objc-mode) + ;; Let '@' be part of symbols in ObjC to cope with + ;; its compiler directives as single keyword tokens. + ;; This is then necessary since it's assumed that + ;; every keyword is a single symbol. `(modify-syntax-entry ?@ "_" table)) ((c-major-mode-is 'pike-mode) `(modify-syntax-entry ?@ "." table))) @@ -328,6 +383,7 @@ keyword. It's unspecified how far it matches. Does not contain a \\| operator at the top level." t (concat "[" c-alpha "_]") + objc (concat "[" c-alpha "@]") pike (concat "[" c-alpha "_`]")) (c-lang-defvar c-symbol-start (c-lang-const c-symbol-start)) @@ -340,8 +396,8 @@ objc (concat c-alnum "_$@")) (c-lang-defconst c-symbol-key - "Regexp matching identifiers and keywords. Assumed to match if -`c-symbol-start' matches on the same position." + "Regexp matching identifiers and keywords (with submatch 0). Assumed +to match if `c-symbol-start' matches on the same position." t (concat (c-lang-const c-symbol-start) "[" (c-lang-const c-symbol-chars) "]*") pike (concat @@ -355,7 +411,7 @@ (c-lang-defconst c-symbol-key-depth ;; Number of regexp grouping parens in `c-symbol-key'. - t (c-regexp-opt-depth (c-lang-const c-symbol-key))) + t (regexp-opt-depth (c-lang-const c-symbol-key))) (c-lang-defconst c-nonsymbol-chars "This is the set of chars that can't be part of a symbol, i.e. the @@ -371,165 +427,181 @@ ;; `c-symbol-key'. t (concat "[" (c-lang-const c-nonsymbol-chars) "]")) -(c-lang-defconst c-opt-identifier-concat-key - "Regexp matching the operators that join symbols to fully qualified -identifiers, or nil in languages that don't have such things. Does -not contain a \\| operator at the top level." +(c-lang-defconst c-identifier-ops + "The operators that make up fully qualified identifiers. nil in +languages that don't have such things. See `c-operators' for a +description of the format. Binary operators can concatenate symbols, +e.g. \"::\" in \"A::B::C\". Prefix operators can precede identifiers, +e.g. \"~\" in \"~A::B\". Other types of operators aren't supported. + +This value is by default merged into `c-operators'." t nil - c++ "::" + c++ '((prefix "~" "??-" "compl") + (right-assoc "::") + (prefix "::")) ;; Java has "." to concatenate identifiers but it's also used for ;; normal indexing. There's special code in the Java font lock ;; rules to fontify qualified identifiers based on the standard ;; naming conventions. We still define "." here to make ;; `c-forward-name' move over as long names as possible which is ;; necessary to e.g. handle throws clauses correctly. - java "\\." - idl "::" - pike "\\(::\\|\\.\\)") + java '((left-assoc ".")) + idl '((left-assoc "::") + (prefix "::")) + pike '((left-assoc "::") + (prefix "::") + (left-assoc "."))) + +(c-lang-defconst c-opt-identifier-concat-key + ;; Appendable adorned regexp matching the operators that join + ;; symbols to fully qualified identifiers, or nil in languages that + ;; don't have such things. + ;; + ;; This was a docstring constant in 5.30. It still works but is now + ;; considered internal - change `c-identifier-ops' instead. + t (let ((ops (c-filter-ops (c-lang-const c-identifier-ops) + '(left-assoc right-assoc) + t))) + (when ops + (c-make-keywords-re 'appendable ops)))) (c-lang-defvar c-opt-identifier-concat-key (c-lang-const c-opt-identifier-concat-key) 'dont-doc) +(c-lang-defconst c-opt-identifier-concat-key-depth + ;; Number of regexp grouping parens in `c-opt-identifier-concat-key'. + t (regexp-opt-depth (c-lang-const c-opt-identifier-concat-key))) + +(c-lang-defconst c-opt-identifier-prefix-key + ;; Appendable adorned regexp matching operators that might precede + ;; an identifier and that are part of the identifier in that case. + ;; nil in languages without such things. + t (let ((ops (c-filter-ops (c-lang-const c-identifier-ops) + '(prefix) + t))) + (when ops + (c-make-keywords-re 'appendable ops)))) + +(c-lang-defconst c-after-id-concat-ops + "Operators that can occur after a binary operator on `c-identifier-ops' +in identifiers. nil in languages that don't have such things. + +Operators here should also have appropriate entries in `c-operators' - +it's not taken care of by default." + t nil + ;; '~' for destructors in C++, '*' for member pointers. + c++ '("~" "*") + ;; In Java we recognize '*' to deal with "foo.bar.*" that can occur + ;; in import declarations. (This will also match bogus things like + ;; "foo.*bar" but we don't bother.) + java '("*")) + (c-lang-defconst c-opt-after-id-concat-key - "Regexp that must match the token after `c-opt-identifier-concat-key' -for it to be considered an identifier concatenation operator (which -e.g. causes the preceding identifier to be fontified as a reference). -Assumed to be a string if `c-opt-identifier-concat-key' is." - t (if (c-lang-const c-opt-identifier-concat-key) - (c-lang-const c-symbol-start)) - c++ (concat (c-lang-const c-symbol-start) - "\\|[~*]") - java (concat (c-lang-const c-symbol-start) - "\\|\\*")) + ;; Regexp that must match the token after + ;; `c-opt-identifier-concat-key' for it to be considered an + ;; identifier concatenation operator (which e.g. causes the + ;; preceding identifier to be fontified as a reference). Assumed to + ;; be a string if `c-opt-identifier-concat-key' is. + ;; + ;; This was a docstring constant in 5.30. It still works but is now + ;; considered internal - change `c-after-id-concat-ops' instead. + t (concat (c-lang-const c-symbol-start) + (if (c-lang-const c-after-id-concat-ops) + (concat "\\|" (c-make-keywords-re 'appendable + (c-lang-const c-after-id-concat-ops))) + ""))) (c-lang-defconst c-identifier-start - "Regexp that matches the start of an \(optionally qualified) -identifier. It should also match all keywords. It's unspecified how -far it matches." - t (concat (c-lang-const c-symbol-start) - (if (c-lang-const c-opt-identifier-concat-key) - (concat "\\|" (c-lang-const c-opt-identifier-concat-key)) - "")) - c++ (concat (c-lang-const c-identifier-start) - "\\|" - "[~*][ \t\n\r\f\v]*" (c-lang-const c-symbol-start)) - ;; Java does not allow a leading qualifier operator. - java (c-lang-const c-symbol-start)) + "Regexp that matches the start of an (optionally qualified) identifier. +It should also match all keywords. It's unspecified how far it +matches." + t (concat (c-lang-const c-symbol-start) + (if (c-lang-const c-opt-identifier-prefix-key) + (concat "\\|" + (c-lang-const c-opt-identifier-prefix-key)) + ""))) (c-lang-defvar c-identifier-start (c-lang-const c-identifier-start)) (c-lang-defconst c-identifier-key "Regexp matching a fully qualified identifier, like \"A::B::c\" in C++. It does not recognize the full range of syntactic whitespace -between the tokens; `c-forward-name' has to be used for that." - t (c-lang-const c-symbol-key) ; Default to `c-symbol-key'. - ;; C++ allows a leading qualifier operator and a `~' before the last - ;; symbol. This regexp is more complex than strictly necessary to - ;; ensure that it can be matched with a minimum of backtracking. - c++ (concat - "\\(" (c-lang-const c-opt-identifier-concat-key) "[ \t\n\r\f\v]*\\)?" - (concat - "\\(" - ;; The submatch below is depth of `c-opt-identifier-concat-key' + 3. - "\\(" (c-lang-const c-symbol-key) "\\)" - (concat "\\(" - "[ \t\n\r\f\v]*" - (c-lang-const c-opt-identifier-concat-key) - "[ \t\n\r\f\v]*" - ;; The submatch below is: `c-symbol-key-depth' + - ;; 2 * depth of `c-opt-identifier-concat-key' + 5. - "\\(" (c-lang-const c-symbol-key) "\\)" - "\\)*") - (concat "\\(" - "[ \t\n\r\f\v]*" - (c-lang-const c-opt-identifier-concat-key) - "[ \t\n\r\f\v]*" - "[~*]" - "[ \t\n\r\f\v]*" - ;; The submatch below is: 2 * `c-symbol-key-depth' + - ;; 3 * depth of `c-opt-identifier-concat-key' + 7. - "\\(" (c-lang-const c-symbol-key) "\\)" +between the tokens; `c-forward-name' has to be used for that. It +should also not match identifiers containing parenthesis groupings, +e.g. identifiers with template arguments such as \"A<X,Y>\" in C++." + ;; This regexp is more complex than strictly necessary to ensure + ;; that it can be matched with a minimum of backtracking. + t (concat (if (c-lang-const c-opt-identifier-prefix-key) + (concat + "\\(" + (c-lang-const c-opt-identifier-prefix-key) + (c-lang-const c-simple-ws) "*" "\\)?") - "\\|" - "~[ \t\n\r\f\v]*" - ;; The submatch below is: 3 * `c-symbol-key-depth' + - ;; 3 * depth of `c-opt-identifier-concat-key' + 8. - "\\(" (c-lang-const c-symbol-key) "\\)" - "\\)")) - ;; IDL and Pike allows a leading qualifier operator. - (idl pike) (concat - "\\(" - (c-lang-const c-opt-identifier-concat-key) - "[ \t\n\r\f\v]*" - "\\)?" - ;; The submatch below is depth of - ;; `c-opt-identifier-concat-key' + 2. - "\\(" (c-lang-const c-symbol-key) "\\)" - (concat "\\(" - "[ \t\n\r\f\v]*" - (c-lang-const c-opt-identifier-concat-key) - "[ \t\n\r\f\v]*" - ;; The submatch below is: `c-symbol-key-depth' + - ;; 2 * depth of `c-opt-identifier-concat-key' + 4. + "") + "\\(" (c-lang-const c-symbol-key) "\\)" + (if (c-lang-const c-opt-identifier-concat-key) + (concat + "\\(" + (c-lang-const c-simple-ws) "*" + (c-lang-const c-opt-identifier-concat-key) + (c-lang-const c-simple-ws) "*" + (if (c-lang-const c-after-id-concat-ops) + (concat + "\\(" + (c-make-keywords-re 'appendable + (c-lang-const c-after-id-concat-ops)) + (concat + ;; For flexibility, consider the symbol match + ;; optional if we've hit a + ;; `c-after-id-concat-ops' operator. This is + ;; also necessary to handle the "*" that can + ;; end import declaration identifiers in Java. + "\\(" + (c-lang-const c-simple-ws) "*" + "\\(" (c-lang-const c-symbol-key) "\\)" + "\\)?") + "\\|" "\\(" (c-lang-const c-symbol-key) "\\)" - "\\)*")) - ;; Java does not allow a leading qualifier operator. If it ends - ;; with ".*" (used in import declarations) we also consider that as - ;; part of the name. ("*" is actually recognized in any position - ;; except the first by this regexp, but we don't bother.) - java (concat "\\(" (c-lang-const c-symbol-key) "\\)" ; 1 - (concat "\\(" - "[ \t\n\r\f\v]*" - (c-lang-const c-opt-identifier-concat-key) - "[ \t\n\r\f\v]*" - (concat "\\(" - ;; The submatch below is `c-symbol-key-depth' + - ;; depth of `c-opt-identifier-concat-key' + 4. - "\\(" (c-lang-const c-symbol-key) "\\)" - "\\|\\*\\)") - "\\)*"))) + "\\)") + (concat "\\(" (c-lang-const c-symbol-key) "\\)")) + "\\)*") + ""))) (c-lang-defvar c-identifier-key (c-lang-const c-identifier-key)) (c-lang-defconst c-identifier-last-sym-match - "Used to identify the submatch in `c-identifier-key' that surrounds -the last symbol in the qualified identifier. It's a list of submatch -numbers, of which the first that has a match is taken. It's assumed -that at least one does when the regexp has matched." - t '(0) - c++ (list (+ (* 3 (c-lang-const c-symbol-key-depth)) - (* 3 (c-regexp-opt-depth - (c-lang-const c-opt-identifier-concat-key))) - 8) - (+ (* 2 (c-lang-const c-symbol-key-depth)) - (* 3 (c-regexp-opt-depth - (c-lang-const c-opt-identifier-concat-key))) - 7) - (+ (c-lang-const c-symbol-key-depth) - (* 2 (c-regexp-opt-depth - (c-lang-const c-opt-identifier-concat-key))) - 5) - (+ (c-regexp-opt-depth - (c-lang-const c-opt-identifier-concat-key)) - 3)) - (idl pike) (list (+ (c-lang-const c-symbol-key-depth) - (* 2 (c-regexp-opt-depth - (c-lang-const c-opt-identifier-concat-key))) - 4) - (+ (c-regexp-opt-depth - (c-lang-const c-opt-identifier-concat-key)) - 2)) - java (list (+ (c-lang-const c-symbol-key-depth) - (c-regexp-opt-depth - (c-lang-const c-opt-identifier-concat-key)) - 4) - 1)) -(c-lang-defvar c-identifier-last-sym-match - (c-lang-const c-identifier-last-sym-match) - 'dont-doc) + ;; This was a docstring constant in 5.30 but it's no longer used. + ;; It's only kept to avoid breaking third party code. + ;; + ;; Used to identify the submatch in `c-identifier-key' that + ;; surrounds the last symbol in the qualified identifier. It's a + ;; list of submatch numbers, of which the first that has a match is + ;; taken. It's assumed that at least one does when the regexp has + ;; matched. + t nil) + +(c-lang-defconst c-string-escaped-newlines + "Set if the language support backslash escaped newlines inside string +literals." + t nil + (c c++ objc pike) t) +(c-lang-defvar c-string-escaped-newlines + (c-lang-const c-string-escaped-newlines)) + +(c-lang-defconst c-multiline-string-start-char + "Set if the language supports multiline string literals without escaped +newlines. If t, all string literals are multiline. If a character, +only literals where the open quote is immediately preceded by that +literal are multiline." + t nil + pike ?#) +(c-lang-defvar c-multiline-string-start-char + (c-lang-const c-multiline-string-start-char)) (c-lang-defconst c-opt-cpp-prefix "Regexp matching the prefix of a cpp directive in the languages that normally use that macro preprocessor. Tested at bol or at boi. Assumed to not contain any submatches or \\| operators." + ;; TODO (ACM, 2005-04-01). Amend the following to recognise escaped NLs; + ;; amend all uses of c-opt-cpp-prefix which count regexp-depth. t "\\s *#\\s *" (java awk) nil) (c-lang-defvar c-opt-cpp-prefix (c-lang-const c-opt-cpp-prefix)) @@ -546,9 +618,46 @@ "\\([" c-alnum "]+\\|!\\)")) (c-lang-defvar c-opt-cpp-start (c-lang-const c-opt-cpp-start)) -(c-lang-defconst c-cpp-defined-fns - ;; Name of functions in cpp expressions that take an identifier as - ;; the argument. +(c-lang-defconst c-cpp-message-directives + "List of cpp directives (without the prefix) that are followed by a +string message." + t (if (c-lang-const c-opt-cpp-prefix) + '("error")) + pike '("error" "warning")) + +(c-lang-defconst c-cpp-include-directives + "List of cpp directives (without the prefix) that are followed by a +file name in angle brackets or quotes." + t (if (c-lang-const c-opt-cpp-prefix) + '("include")) + objc '("include" "import")) + +(c-lang-defconst c-opt-cpp-macro-define + "Cpp directive (without the prefix) that is followed by a macro +definition, or nil if the language doesn't have any." + t (if (c-lang-const c-opt-cpp-prefix) + "define")) + +(c-lang-defconst c-opt-cpp-macro-define-start + ;; Regexp matching everything up to the macro body of a cpp define, + ;; or the end of the logical line if there is none. Set if + ;; c-opt-cpp-macro-define is. + t (if (c-lang-const c-opt-cpp-macro-define) + (concat (c-lang-const c-opt-cpp-prefix) + (c-lang-const c-opt-cpp-macro-define) + "[ \t]+\\(\\sw\\|_\\)+\\(\([^\)]*\)\\)?" + "\\([ \t]\\|\\\\\n\\)*"))) +(c-lang-defvar c-opt-cpp-macro-define-start + (c-lang-const c-opt-cpp-macro-define-start)) + +(c-lang-defconst c-cpp-expr-directives + "List if cpp directives (without the prefix) that are followed by an +expression." + t (if (c-lang-const c-opt-cpp-prefix) + '("if" "elif"))) + +(c-lang-defconst c-cpp-expr-functions + "List of functions in cpp expressions." t (if (c-lang-const c-opt-cpp-prefix) '("defined")) pike '("defined" "efun" "constant")) @@ -559,7 +668,7 @@ java (append (c-lang-const c-assignment-operators) '(">>>=")) c++ (append (c-lang-const c-assignment-operators) - '("and_eq" "or_eq" "xor_eq")) + '("and_eq" "or_eq" "xor_eq" "??!=" "??'=")) idl nil) (c-lang-defconst c-operators @@ -573,6 +682,9 @@ 'prefix Unary prefix operators. 'postfix Unary postfix operators. +'postfix-if-paren + Unary postfix operators if and only if the chars have + parenthesis syntax. 'left-assoc Binary left associative operators (i.e. a+b+c means (a+b)+c). 'right-assoc Binary right associative operators (i.e. a=b=c means a=(b=c)). 'right-assoc-sequence @@ -605,20 +717,14 @@ ,@(when (c-major-mode-is '(c-mode c++-mode)) '("%:%:" "??=??="))))) - ;; Primary. Info duplicated in `c-opt-identifier-concat-key' - ;; and `c-identifier-key'. + ;; Primary. + ,@(c-lang-const c-identifier-ops) ,@(cond ((c-major-mode-is 'c++-mode) - `((postfix-if-paren "<" ">") ; Templates. - (prefix "~" "??-" "compl") - (right-assoc "::") - (prefix "::"))) + `((postfix-if-paren "<" ">"))) ; Templates. ((c-major-mode-is 'pike-mode) - `((left-assoc "::") - (prefix "::" "global" "predef"))) + `((prefix "global" "predef"))) ((c-major-mode-is 'java-mode) - `(;; Not necessary since it's also in the postfix group below. - ;;(left-assoc ".") - (prefix "super")))) + `((prefix "super")))) ;; Postfix. ,@(when (c-major-mode-is 'c++-mode) @@ -718,10 +824,8 @@ idl `(;; Preprocessor. (prefix "#") (left-assoc "##") - ;; Primary. Info duplicated in `c-opt-identifier-concat-key' - ;; and `c-identifier-key'. - (left-assoc "::") - (prefix "::") + ;; Primary. + ,@(c-lang-const c-identifier-ops) ;; Unary. (prefix "+" "-" "~") ;; Multiplicative. @@ -739,14 +843,12 @@ (c-lang-defconst c-operator-list ;; The operators as a flat list (without duplicates). - t (delete-duplicates (mapcan (lambda (elem) (append (cdr elem) nil)) - (c-lang-const c-operators)) - :test 'string-equal)) + t (c-filter-ops (c-lang-const c-operators) t t)) (c-lang-defconst c-overloadable-operators - "List of the operators that are overloadable, in their \"identifier form\"." + "List of the operators that are overloadable, in their \"identifier +form\". See also `c-op-identitier-prefix'." t nil - ;; The preceding "operator" keyword is treated separately in C++. c++ '("new" "delete" ;; Can be followed by "[]" but we ignore that. "+" "-" "*" "/" "%" "^" "??'" "xor" "&" "bitand" "|" "??!" "bitor" "~" "??-" "compl" @@ -768,6 +870,20 @@ (c-lang-defvar c-overloadable-operators-regexp (c-lang-const c-overloadable-operators-regexp)) +(c-lang-defconst c-opt-op-identitier-prefix + "Regexp matching the token before the ones in +`c-overloadable-operators' when operators are specified in their +\"identifier form\". This typically matches \"operator\" in C++ where +operator functions are specified as e.g. \"operator +\". It's nil in +languages without operator functions or where the complete operator +identifier is listed in `c-overloadable-operators'. + +This regexp is assumed to not match any non-operator identifier." + t nil + c++ (c-make-keywords-re t '("operator"))) +(c-lang-defvar c-opt-op-identitier-prefix + (c-lang-const c-opt-op-identitier-prefix)) + (c-lang-defconst c-other-op-syntax-tokens "List of the tokens made up of characters in the punctuation or parenthesis syntax classes that have uses other than as expression @@ -776,9 +892,9 @@ (c c++ pike) (append '("#" "##" ; Used by cpp. "::" "...") (c-lang-const c-other-op-syntax-tokens)) - (c c++) (append '("<%" "%>" "<:" ":>" "%:" "%:%:" "*") - (c-lang-const c-other-op-syntax-tokens)) - c++ (append '("&") (c-lang-const c-other-op-syntax-tokens)) + (c c++) (append '("*") (c-lang-const c-other-op-syntax-tokens)) + c++ (append '("&" "<%" "%>" "<:" ":>" "%:" "%:%:") + (c-lang-const c-other-op-syntax-tokens)) objc (append '("#" "##" ; Used by cpp. "+" "-") (c-lang-const c-other-op-syntax-tokens)) idl (append '("#" "##") ; Used by cpp. @@ -788,17 +904,35 @@ (c-lang-const c-overloadable-operators)) awk '("{" "}" "(" ")" "[" "]" ";" "," "=" "/")) +(c-lang-defconst c-all-op-syntax-tokens + ;; List of all tokens in the punctuation and parenthesis syntax + ;; classes. + t (delete-duplicates (append (c-lang-const c-other-op-syntax-tokens) + (c-lang-const c-operator-list)) + :test 'string-equal)) + +(c-lang-defconst c-nonsymbol-token-char-list + ;; List containing all chars not in the word, symbol or + ;; syntactically irrelevant syntax classes, i.e. all punctuation, + ;; parenthesis and string delimiter chars. + t (c-with-syntax-table (c-lang-const c-mode-syntax-table) + ;; Only go through the chars in the printable ASCII range. No + ;; language so far has 8-bit or widestring operators. + (let (list (char 32)) + (while (< char 127) + (or (memq (char-syntax char) '(?w ?_ ?< ?> ?\ )) + (setq list (cons (c-int-to-char char) list))) + (setq char (1+ char))) + list))) + (c-lang-defconst c-nonsymbol-token-regexp ;; Regexp matching all tokens in the punctuation and parenthesis ;; syntax classes. Note that this also matches ".", which can start ;; a float. t (c-make-keywords-re nil - (c-with-syntax-table (c-lang-const c-mode-syntax-table) - (mapcan (lambda (op) - (if (string-match "\\`\\(\\s.\\|\\s\(\\|\\s\)\\)+\\'" op) - (list op))) - (append (c-lang-const c-other-op-syntax-tokens) - (c-lang-const c-operator-list)))))) + (c-filter-ops (c-lang-const c-all-op-syntax-tokens) + t + "\\`\\(\\s.\\|\\s\(\\|\\s\)\\)+\\'"))) (c-lang-defvar c-nonsymbol-token-regexp (c-lang-const c-nonsymbol-token-regexp)) @@ -819,26 +953,34 @@ (c-lang-defvar c-assignment-op-regexp (c-lang-const c-assignment-op-regexp)) +(c-lang-defconst c-<>-multichar-token-regexp + ;; Regexp matching all tokens containing "<" or ">" which are longer + ;; than one char. + t (c-make-keywords-re nil + (c-filter-ops (c-lang-const c-all-op-syntax-tokens) + t + ".[<>]\\|[<>]."))) +(c-lang-defvar c-<>-multichar-token-regexp + (c-lang-const c-<>-multichar-token-regexp)) + (c-lang-defconst c-<-op-cont-regexp ;; Regexp matching the second and subsequent characters of all ;; multicharacter tokens that begin with "<". t (c-make-keywords-re nil - (mapcan (lambda (op) - (if (string-match "\\`<." op) - (list (substring op 1)))) - (append (c-lang-const c-other-op-syntax-tokens) - (c-lang-const c-operator-list))))) + (c-filter-ops (c-lang-const c-all-op-syntax-tokens) + t + "\\`<." + (lambda (op) (substring op 1))))) (c-lang-defvar c-<-op-cont-regexp (c-lang-const c-<-op-cont-regexp)) (c-lang-defconst c->-op-cont-regexp ;; Regexp matching the second and subsequent characters of all ;; multicharacter tokens that begin with ">". t (c-make-keywords-re nil - (mapcan (lambda (op) - (if (string-match "\\`>." op) - (list (substring op 1)))) - (append (c-lang-const c-other-op-syntax-tokens) - (c-lang-const c-operator-list))))) + (c-filter-ops (c-lang-const c-all-op-syntax-tokens) + t + "\\`>." + (lambda (op) (substring op 1))))) (c-lang-defvar c->-op-cont-regexp (c-lang-const c->-op-cont-regexp)) (c-lang-defconst c-stmt-delim-chars @@ -847,7 +989,7 @@ ;; begin with "^" to negate the set. If ? : operators should be ;; detected then the string must end with "?:". t "^;{}?:" - awk "^;{}\n\r?:") ; The newline chars gets special treatment. + awk "^;{}#\n\r?:") ; The newline chars gets special treatment. (c-lang-defvar c-stmt-delim-chars (c-lang-const c-stmt-delim-chars)) (c-lang-defconst c-stmt-delim-chars-with-comma @@ -860,15 +1002,69 @@ ;;; Syntactic whitespace. +(c-lang-defconst c-simple-ws + "Regexp matching an ordinary whitespace character. +Does not contain a \\| operator at the top level." + ;; "\\s " is not enough since it doesn't match line breaks. + t "\\(\\s \\|[\n\r]\\)") + +(c-lang-defconst c-simple-ws-depth + ;; Number of regexp grouping parens in `c-simple-ws'. + t (regexp-opt-depth (c-lang-const c-simple-ws))) + +(c-lang-defconst c-line-comment-starter + "String that starts line comments, or nil if such don't exist. +Line comments are always terminated by newlines. At least one of +`c-block-comment-starter' and this one is assumed to be set. + +Note that it's currently not enough to set this to support a new +comment style. Other stuff like the syntax table must also be set up +properly." + t "//" + awk "#") +(c-lang-defvar c-line-comment-starter (c-lang-const c-line-comment-starter)) + +(c-lang-defconst c-block-comment-starter + "String that starts block comments, or nil if such don't exist. +Block comments are ended by `c-block-comment-ender', which is assumed +to be set if this is. At least one of `c-line-comment-starter' and +this one is assumed to be set. + +Note that it's currently not enough to set this to support a new +comment style. Other stuff like the syntax table must also be set up +properly." + t "/*" + awk nil) + +(c-lang-defconst c-block-comment-ender + "String that ends block comments, or nil if such don't exist. + +Note that it's currently not enough to set this to support a new +comment style. Other stuff like the syntax table must also be set up +properly." + t "*/" + awk nil) + (c-lang-defconst c-comment-start-regexp ;; Regexp to match the start of any type of comment. - ;; - ;; TODO: Ought to use `c-comment-prefix-regexp' with some - ;; modifications instead of this. - t "/[/*]" - awk "#") + t (let ((re (c-make-keywords-re nil + (list (c-lang-const c-line-comment-starter) + (c-lang-const c-block-comment-starter))))) + (if (memq 'gen-comment-delim c-emacs-features) + (concat re "\\|\\s!") + re))) (c-lang-defvar c-comment-start-regexp (c-lang-const c-comment-start-regexp)) +;;;; Added by ACM, 2003/9/18. +(c-lang-defconst c-block-comment-start-regexp + ;; Regexp which matches the start of a block comment (if such exists in the + ;; language) + t (if (c-lang-const c-block-comment-starter) + (regexp-quote (c-lang-const c-block-comment-starter)) + "\\<\\>")) +(c-lang-defvar c-block-comment-start-regexp + (c-lang-const c-block-comment-start-regexp)) + (c-lang-defconst c-literal-start-regexp ;; Regexp to match the start of comments and string literals. t (concat (c-lang-const c-comment-start-regexp) @@ -891,129 +1087,235 @@ (c-lang-defconst comment-start "String that starts comments inserted with M-; etc. `comment-start' is initialized from this." - t "// " - c "/* " - awk "# ") + ;; Default: Prefer line comments to block comments, and pad with a space. + t (concat (or (c-lang-const c-line-comment-starter) + (c-lang-const c-block-comment-starter)) + " ") + ;; In C we still default to the block comment style since line + ;; comments aren't entirely portable. + c "/* ") (c-lang-defvar comment-start (c-lang-const comment-start) 'dont-doc) (c-lang-defconst comment-end "String that ends comments inserted with M-; etc. `comment-end' is initialized from this." - t "" - c " */") + ;; Default: Use block comment style if comment-start uses block + ;; comments, and pad with a space in that case. + t (if (string-match (concat "\\`\\(" + (c-lang-const c-block-comment-start-regexp) + "\\)") + (c-lang-const comment-start)) + (concat " " (c-lang-const c-block-comment-ender)) + "")) (c-lang-defvar comment-end (c-lang-const comment-end) 'dont-doc) (c-lang-defconst comment-start-skip "Regexp to match the start of a comment plus everything up to its body. `comment-start-skip' is initialized from this." - t "/\\*+ *\\|//+ *" - awk "#+ *") + ;; Default: Allow the last char of the comment starter(s) to be + ;; repeated, then allow any amount of horizontal whitespace. + t (concat "\\(" + (c-concat-separated + (mapcar (lambda (cs) + (when cs + (concat (regexp-quote cs) "+"))) + (list (c-lang-const c-line-comment-starter) + (c-lang-const c-block-comment-starter))) + "\\|") + "\\)\\s *")) (c-lang-defvar comment-start-skip (c-lang-const comment-start-skip) 'dont-doc) (c-lang-defconst c-syntactic-ws-start - "Regexp matching any sequence that can start syntactic whitespace. -The only uncertain case is '#' when there are cpp directives." - t "[ \n\t\r\v\f#]\\|/[/*]\\|\\\\[\n\r]" - awk "[ \n\t\r\v\f#]\\|\\\\[\n\r]") -(c-lang-defvar c-syntactic-ws-start (c-lang-const c-syntactic-ws-start) - 'dont-doc) + ;; Regexp matching any sequence that can start syntactic whitespace. + ;; The only uncertain case is '#' when there are cpp directives. + t (concat "\\s \\|" + (c-make-keywords-re nil + (append (list (c-lang-const c-line-comment-starter) + (c-lang-const c-block-comment-starter) + (when (c-lang-const c-opt-cpp-prefix) + "#")) + '("\n" "\r"))) + "\\|\\\\[\n\r]" + (when (memq 'gen-comment-delim c-emacs-features) + "\\|\\s!"))) +(c-lang-defvar c-syntactic-ws-start (c-lang-const c-syntactic-ws-start)) (c-lang-defconst c-syntactic-ws-end - "Regexp matching any single character that might end syntactic whitespace." - t "[ \n\t\r\v\f/]" - awk "[ \n\t\r\v\f]") -(c-lang-defvar c-syntactic-ws-end (c-lang-const c-syntactic-ws-end) - 'dont-doc) + ;; Regexp matching any single character that might end syntactic whitespace. + t (concat "\\s \\|" + (c-make-keywords-re nil + (append (when (c-lang-const c-block-comment-ender) + (list + (string + (elt (c-lang-const c-block-comment-ender) + (1- (length + (c-lang-const c-block-comment-ender))))))) + '("\n" "\r"))) + (when (memq 'gen-comment-delim c-emacs-features) + "\\|\\s!"))) +(c-lang-defvar c-syntactic-ws-end (c-lang-const c-syntactic-ws-end)) + +(c-lang-defconst c-unterminated-block-comment-regexp + ;; Regexp matching an unterminated block comment that doesn't + ;; contain line breaks, or nil in languages without block comments. + ;; Does not contain a \| operator at the top level. + t (when (c-lang-const c-block-comment-starter) + (concat + (regexp-quote (c-lang-const c-block-comment-starter)) + ;; It's messy to cook together a regexp that matches anything + ;; but c-block-comment-ender. + (let ((end (c-lang-const c-block-comment-ender))) + (cond ((= (length end) 1) + (concat "[^" end "\n\r]*")) + ((= (length end) 2) + (concat "[^" (substring end 0 1) "\n\r]*" + "\\(" + (regexp-quote (substring end 0 1)) "+" + "[^" + ;; The quoting rules inside char classes are silly. :P + (cond ((= (elt end 0) (elt end 1)) + (concat (substring end 0 1) "\n\r")) + ((= (elt end 1) ?\]) + (concat (substring end 1 2) "\n\r" + (substring end 0 1))) + (t + (concat (substring end 0 1) "\n\r" + (substring end 1 2)))) + "]" + "[^" (substring end 0 1) "\n\r]*" + "\\)*")) + (t + (error "Can't handle a block comment ender of length %s" + (length end)))))))) + +(c-lang-defconst c-block-comment-regexp + ;; Regexp matching a block comment that doesn't contain line breaks, + ;; or nil in languages without block comments. The reason we don't + ;; allow line breaks is to avoid going very far and risk running out + ;; of regexp stack; this regexp is intended to handle only short + ;; comments that might be put in the middle of limited constructs + ;; like declarations. Does not contain a \| operator at the top + ;; level. + t (when (c-lang-const c-unterminated-block-comment-regexp) + (concat + (c-lang-const c-unterminated-block-comment-regexp) + (let ((end (c-lang-const c-block-comment-ender))) + (cond ((= (length end) 1) + (regexp-quote end)) + ((= (length end) 2) + (concat (regexp-quote (substring end 0 1)) "+" + (regexp-quote (substring end 1 2)))) + (t + (error "Can't handle a block comment ender of length %s" + (length end)))))))) (c-lang-defconst c-nonwhite-syntactic-ws ;; Regexp matching a piece of syntactic whitespace that isn't a ;; sequence of simple whitespace characters. As opposed to ;; `c-(forward|backward)-syntactic-ws', this doesn't regard cpp ;; directives as syntactic whitespace. - t (concat "/" (concat - "\\(" - "/[^\n\r]*[\n\r]" ; Line comment. - "\\|" - ;; Block comment. We intentionally don't allow line - ;; breaks in them to avoid going very far and risk - ;; running out of regexp stack; this regexp is - ;; intended to handle only short comments that - ;; might be put in the middle of limited constructs - ;; like declarations. - "\\*\\([^*\n\r]\\|\\*[^/\n\r]\\)*\\*/" - "\\)") - "\\|" - "\\\\[\n\r]") ; Line continuations. - awk ("#.*[\n\r]\\|\\\\[\n\r]")) + t (c-concat-separated + (list (when (c-lang-const c-line-comment-starter) + (concat (regexp-quote (c-lang-const c-line-comment-starter)) + "[^\n\r]*[\n\r]")) + (c-lang-const c-block-comment-regexp) + "\\\\[\n\r]" + (when (memq 'gen-comment-delim c-emacs-features) + "\\s!\\S!*\\s!")) + "\\|")) (c-lang-defconst c-syntactic-ws ;; Regexp matching syntactic whitespace, including possibly the ;; empty string. As opposed to `c-(forward|backward)-syntactic-ws', ;; this doesn't regard cpp directives as syntactic whitespace. Does ;; not contain a \| operator at the top level. - t (concat "[ \t\n\r\f\v]*\\(" - "\\(" (c-lang-const c-nonwhite-syntactic-ws) "\\)" - "[ \t\n\r\f\v]*\\)*")) + t (concat (c-lang-const c-simple-ws) "*" + "\\(" + (concat "\\(" (c-lang-const c-nonwhite-syntactic-ws) "\\)" + (c-lang-const c-simple-ws) "*") + "\\)*")) (c-lang-defconst c-syntactic-ws-depth ;; Number of regexp grouping parens in `c-syntactic-ws'. - t (c-regexp-opt-depth (c-lang-const c-syntactic-ws))) + t (regexp-opt-depth (c-lang-const c-syntactic-ws))) (c-lang-defconst c-nonempty-syntactic-ws ;; Regexp matching syntactic whitespace, which is at least one ;; character long. As opposed to `c-(forward|backward)-syntactic-ws', ;; this doesn't regard cpp directives as syntactic whitespace. Does ;; not contain a \| operator at the top level. - t (concat "\\([ \t\n\r\f\v]\\|" + t (concat "\\(" + (c-lang-const c-simple-ws) + "\\|" (c-lang-const c-nonwhite-syntactic-ws) "\\)+")) (c-lang-defconst c-nonempty-syntactic-ws-depth ;; Number of regexp grouping parens in `c-nonempty-syntactic-ws'. - t (c-regexp-opt-depth (c-lang-const c-nonempty-syntactic-ws))) + t (regexp-opt-depth (c-lang-const c-nonempty-syntactic-ws))) (c-lang-defconst c-single-line-syntactic-ws ;; Regexp matching syntactic whitespace without any line breaks. As ;; opposed to `c-(forward|backward)-syntactic-ws', this doesn't ;; regard cpp directives as syntactic whitespace. Does not contain ;; a \| operator at the top level. - t (concat "[ \t]*\\(" - "/\\*\\([^*\n\r]\\|\\*[^/\n\r]\\)*\\*/" ; Block comment - "[ \t]*\\)*") - awk ("[ \t]*\\(#.*$\\)?")) + t (if (c-lang-const c-block-comment-regexp) + (concat "\\s *\\(" + (c-lang-const c-block-comment-regexp) + "\\s *\\)*") + "\\s *")) (c-lang-defconst c-single-line-syntactic-ws-depth ;; Number of regexp grouping parens in `c-single-line-syntactic-ws'. - t (c-regexp-opt-depth (c-lang-const c-single-line-syntactic-ws))) + t (regexp-opt-depth (c-lang-const c-single-line-syntactic-ws))) -(c-lang-defvar c-syntactic-eol +(c-lang-defconst c-syntactic-eol ;; Regexp that matches when there is no syntactically significant ;; text before eol. Macros are regarded as syntactically ;; significant text here. - (concat (concat - ;; Match horizontal whitespace and block comments that - ;; don't contain newlines. - "\\(\\s \\|" - (concat "/\\*" - "\\([^*\n\r]\\|\\*[^/\n\r]\\)*" - "\\*/") - "\\)*") - (concat - ;; Match eol (possibly inside a block comment or preceded - ;; by a line continuation backslash), or the beginning of a - ;; line comment. Note: This has to be modified for awk - ;; where line comments start with '#'. - "\\(" - (concat "\\(" - "/\\*\\([^*\n\r]\\|\\*[^/\n\r]\\)*" - "\\|" - "\\\\" - "\\)?" + t (concat (c-lang-const c-single-line-syntactic-ws) + ;; Match eol (possibly inside a block comment or preceded + ;; by a line continuation backslash), or the beginning of a + ;; line comment. Note: This has to be modified for awk + ;; where line comments start with '#'. + "\\(" + (c-concat-separated + (list (when (c-lang-const c-line-comment-starter) + (regexp-quote (c-lang-const c-line-comment-starter))) + (when (c-lang-const c-unterminated-block-comment-regexp) + (concat (c-lang-const c-unterminated-block-comment-regexp) + "$")) + "\\\\$" "$") - "\\|//\\)"))) + "\\|") + "\\)")) +(c-lang-defvar c-syntactic-eol (c-lang-const c-syntactic-eol)) + + +;;; Syntactic analysis ("virtual semicolons") for line-oriented languages (AWK). +(c-lang-defconst c-at-vsemi-p-fn + "Contains a function \"Is there a virtual semicolon at POS or point?\". +Such a function takes one optional parameter, a buffer position (defaults to +point), and returns NIL or t. This variable contains NIL for languages which +don't have EOL terminated statements. " + t nil + awk 'c-awk-at-vsemi-p) +(c-lang-defvar c-at-vsemi-p-fn (c-lang-const c-at-vsemi-p-fn)) + +(c-lang-defconst c-vsemi-status-unknown-p-fn + "Contains a function \"are we unsure whether there is a virtual semicolon on this line?\". +The (admittedly kludgey) purpose of such a function is to prevent an infinite +recursion in c-beginning-of-statement-1 when point starts at a `while' token. +The function MUST NOT UNDER ANY CIRCUMSTANCES call c-beginning-of-statement-1, +even indirectly. This variable contains NIL for languages which don't have +EOL terminated statements." + t nil + awk 'c-awk-vsemi-status-unknown-p) +(c-lang-defvar c-vsemi-status-unknown-p-fn + (c-lang-const c-vsemi-status-unknown-p-fn)) ;;; In-comment text handling. @@ -1137,6 +1439,14 @@ (c-lang-defvar c-opt-type-component-key (c-lang-const c-opt-type-component-key)) +(c-lang-defconst c-type-start-kwds + ;; All keywords that can start a type (i.e. are either a type prefix + ;; or a complete type). + t (delete-duplicates (append (c-lang-const c-primitive-type-kwds) + (c-lang-const c-type-prefix-kwds) + (c-lang-const c-type-modifier-kwds)) + :test 'string-equal)) + (c-lang-defconst c-class-decl-kwds "Keywords introducing declarations where the following block (if any) contains another declaration level that should be considered a class. @@ -1187,14 +1497,26 @@ (c-lang-defconst c-other-block-decl-kwds "Keywords where the following block (if any) contains another -declaration level that should not be considered a class. +declaration level that should not be considered a class. For every +keyword here, CC Mode will add a set of special syntactic symbols for +those blocks. E.g. if the keyword is \"foo\" then there will be +`foo-open', `foo-close', and `infoo' symbols. + +The intention is that this category should be used for block +constructs that aren't related to object orientation concepts like +classes (which thus also include e.g. interfaces, templates, +contracts, structs, etc). The more pragmatic distinction is that +while most want some indentation inside classes, it's fairly common +that they don't want it in some of these constructs, so it should be +simple to configure that differently from classes. See also +`c-class-decl-kwds'. If any of these also are on `c-type-list-kwds', `c-ref-list-kwds', `c-colon-type-list-kwds', `c-paren-nontype-kwds', `c-paren-type-kwds', `c-<>-type-kwds', or `c-<>-arglist-kwds' then the associated clauses will be handled." t nil - c '("extern") + (c objc) '("extern") c++ '("namespace" "extern") idl '("module" ;; In CORBA CIDL: @@ -1207,39 +1529,52 @@ (c-lang-defvar c-other-decl-block-key (c-lang-const c-other-decl-block-key)) (c-lang-defconst c-typedef-decl-kwds - "Keywords introducing declarations where the identifiers are defined -to be types. + "Keywords introducing declarations where the identifier(s) being +declared are types. If any of these also are on `c-type-list-kwds', `c-ref-list-kwds', `c-colon-type-list-kwds', `c-paren-nontype-kwds', `c-paren-type-kwds', `c-<>-type-kwds', or `c-<>-arglist-kwds' then the associated clauses will be handled." - t '("typedef") - (java awk) nil) + ;; Default to `c-class-decl-kwds' and `c-brace-list-decl-kwds' + ;; (since e.g. "Foo" is a type that's being defined in "class Foo + ;; {...}"). + t (append (c-lang-const c-class-decl-kwds) + (c-lang-const c-brace-list-decl-kwds)) + ;; Languages that have a "typedef" construct. + (c c++ objc idl pike) (append (c-lang-const c-typedef-decl-kwds) + '("typedef")) + ;; Unlike most other languages, exception names are not handled as + ;; types in IDL since they only can occur in "raises" specs. + idl (delete "exception" (append (c-lang-const c-typedef-decl-kwds) nil))) (c-lang-defconst c-typeless-decl-kwds - "Keywords introducing declarations where the identifier (declarator) -list follows directly after the keyword, without any type. + "Keywords introducing declarations where the \(first) identifier +\(declarator) follows directly after the keyword, without any type. If any of these also are on `c-type-list-kwds', `c-ref-list-kwds', `c-colon-type-list-kwds', `c-paren-nontype-kwds', `c-paren-type-kwds', `c-<>-type-kwds', or `c-<>-arglist-kwds' then the associated clauses will be handled." - t nil - ;; Unlike most other languages, exception names are not handled as - ;; types in IDL since they only can occur in "raises" specs. - idl '("exception" "factory" "finder" "native" - ;; In CORBA PSDL: - "key" "stores" - ;; In CORBA CIDL: - ;; Note that "manages" here clashes with its presence on - ;; `c-type-list-kwds' for IDL. - "executor" "facet" "manages" "segment") - pike '("constant")) + ;; Default to `c-class-decl-kwds' and `c-brace-list-decl-kwds' + ;; (since e.g. "Foo" is the identifier being defined in "class Foo + ;; {...}"). + t (append (c-lang-const c-class-decl-kwds) + (c-lang-const c-brace-list-decl-kwds)) + ;; Note: "manages" for CORBA CIDL clashes with its presence on + ;; `c-type-list-kwds' for IDL. + idl (append (c-lang-const c-typeless-decl-kwds) + '("factory" "finder" "native" + ;; In CORBA PSDL: + "key" "stores" + ;; In CORBA CIDL: + "facet")) + pike (append (c-lang-const c-class-decl-kwds) + '("constant"))) (c-lang-defconst c-modifier-kwds "Keywords that can prefix normal declarations of identifiers -\(and typically acts as flags). Things like argument declarations +\(and typically act as flags). Things like argument declarations inside function headers are also considered declarations in this sense. @@ -1270,53 +1605,119 @@ "Keywords that can start or prefix any declaration level construct, besides those on `c-class-decl-kwds', `c-brace-list-decl-kwds', `c-other-block-decl-kwds', `c-typedef-decl-kwds', -`c-typeless-decl-kwds' and `c-modifier-kwds'. In a declaration, these -keywords are also recognized inside or after the identifiers that -makes up the type. +`c-typeless-decl-kwds' and `c-modifier-kwds'. If any of these also are on `c-type-list-kwds', `c-ref-list-kwds', `c-colon-type-list-kwds', `c-paren-nontype-kwds', `c-paren-type-kwds', `c-<>-type-kwds', or `c-<>-arglist-kwds' then the associated clauses will be handled." t nil - (c c++) '("__declspec") ; MSVC extension. objc '("@class" "@end" "@defs") java '("import" "package") pike '("import" "inherit")) +(c-lang-defconst c-decl-start-kwds + "Keywords that always start declarations, wherever they occur. +This can be used for declarations that aren't recognized by the normal +combination of `c-decl-prefix-re' and `c-decl-start-re'." + t nil + ;; Classes can be declared anywhere in a Pike expression. + pike '("class")) + +(c-lang-defconst c-decl-hangon-kwds + "Keywords that can occur anywhere in a declaration level construct. +This is used for self-contained things that can be tacked on anywhere +on a declaration and that should be ignored to be able to recognize it +correctly. Typical cases are compiler extensions like +\"__attribute__\" or \"__declspec\": + + __declspec(noreturn) void foo(); + class __declspec(dllexport) classname {...}; + void foo() __attribute__((noreturn)); + +Note that unrecognized plain symbols are skipped anyway if they occur +before the type, so such things are not necessary to mention here. +Mentioning them here is necessary only if they can occur in other +places, or if they are followed by a construct that must be skipped +over \(like the parens in the \"__attribute__\" and \"__declspec\" +examples above). In the last case, they alse need to be present on +one of `c-type-list-kwds', `c-ref-list-kwds', +`c-colon-type-list-kwds', `c-paren-nontype-kwds', `c-paren-type-kwds', +`c-<>-type-kwds', or `c-<>-arglist-kwds'." + ;; NB: These are currently not recognized in all parts of a + ;; declaration. Specifically, they aren't recognized in the middle + ;; of multi-token types, inside declarators, and between the + ;; identifier and the arglist paren of a function declaration. + ;; + ;; FIXME: This ought to be user customizable since compiler stuff + ;; like this usually is wrapped in project specific macros. (It'd + ;; of course be even better if we could cope without knowing this.) + t nil + (c c++) '(;; GCC extension. + "__attribute__" + ;; MSVC extension. + "__declspec")) + +(c-lang-defconst c-decl-hangon-key + ;; Adorned regexp matching `c-decl-hangon-kwds'. + t (c-make-keywords-re t (c-lang-const c-decl-hangon-kwds))) +(c-lang-defvar c-decl-hangon-key (c-lang-const c-decl-hangon-key)) + +(c-lang-defconst c-prefix-spec-kwds + ;; All keywords that can occur in the preamble of a declaration. + ;; They typically occur before the type, but they are also matched + ;; after presumptive types since we often can't be sure that + ;; something is a type or just some sort of macro in front of the + ;; declaration. They might be ambiguous with types or type + ;; prefixes. + t (delete-duplicates (append (c-lang-const c-class-decl-kwds) + (c-lang-const c-brace-list-decl-kwds) + (c-lang-const c-other-block-decl-kwds) + (c-lang-const c-typedef-decl-kwds) + (c-lang-const c-typeless-decl-kwds) + (c-lang-const c-modifier-kwds) + (c-lang-const c-other-decl-kwds) + (c-lang-const c-decl-start-kwds) + (c-lang-const c-decl-hangon-kwds)) + :test 'string-equal)) + +(c-lang-defconst c-prefix-spec-kwds-re + ;; Adorned regexp of `c-prefix-spec-kwds'. + t (c-make-keywords-re t (c-lang-const c-prefix-spec-kwds))) +(c-lang-defvar c-prefix-spec-kwds-re (c-lang-const c-prefix-spec-kwds-re)) + (c-lang-defconst c-specifier-key - ;; Adorned regexp matching keywords that can start a declaration but - ;; not a type. + ;; Adorned regexp of the keywords in `c-prefix-spec-kwds' that + ;; aren't ambiguous with types or type prefixes. t (c-make-keywords-re t - (set-difference (append (c-lang-const c-class-decl-kwds) - (c-lang-const c-brace-list-decl-kwds) - (c-lang-const c-other-block-decl-kwds) - (c-lang-const c-typedef-decl-kwds) - (c-lang-const c-typeless-decl-kwds) - (c-lang-const c-modifier-kwds) - (c-lang-const c-other-decl-kwds)) - (append (c-lang-const c-primitive-type-kwds) - (c-lang-const c-type-prefix-kwds) - (c-lang-const c-type-modifier-kwds)) + (set-difference (c-lang-const c-prefix-spec-kwds) + (c-lang-const c-type-start-kwds) :test 'string-equal))) (c-lang-defvar c-specifier-key (c-lang-const c-specifier-key)) +(c-lang-defconst c-postfix-spec-kwds + ;; Keywords that can occur after argument list of a function header + ;; declaration, i.e. in the "K&R region". + t (append (c-lang-const c-postfix-decl-spec-kwds) + (c-lang-const c-decl-hangon-kwds))) + +(c-lang-defconst c-not-decl-init-keywords + ;; Adorned regexp matching all keywords that can't appear at the + ;; start of a declaration. + t (c-make-keywords-re t + (set-difference (c-lang-const c-keywords) + (append (c-lang-const c-type-start-kwds) + (c-lang-const c-prefix-spec-kwds)) + :test 'string-equal))) +(c-lang-defvar c-not-decl-init-keywords + (c-lang-const c-not-decl-init-keywords)) + (c-lang-defconst c-protection-kwds - "Protection label keywords in classes." + "Access protection label keywords in classes." t nil c++ '("private" "protected" "public") objc '("@private" "@protected" "@public")) -(c-lang-defconst c-opt-access-key - ;; Regexp matching an access protection label in a class, or nil in - ;; languages that don't have such things. - t (if (c-lang-const c-protection-kwds) - (c-make-keywords-re t (c-lang-const c-protection-kwds))) - c++ (concat "\\(" - (c-make-keywords-re nil (c-lang-const c-protection-kwds)) - "\\)[ \t\n\r\f\v]*:")) -(c-lang-defvar c-opt-access-key (c-lang-const c-opt-access-key)) - (c-lang-defconst c-block-decls-with-vars "Keywords introducing declarations that can contain a block which might be followed by variable declarations, e.g. like \"foo\" in @@ -1342,7 +1743,6 @@ between the header and the body \(i.e. the \"K&R-region\") in declarations." t nil - (c c++) '("__attribute__") ; GCC extension. java '("extends" "implements" "throws") idl '("context" "getraises" "manages" "primarykey" "raises" "setraises" "supports" @@ -1366,22 +1766,18 @@ There's also no reason to add keywords that prefixes a normal declaration consisting of a type followed by a declarator (list), so the keywords on `c-modifier-kwds' should normally not be listed here -too. +either. Note: Use `c-typeless-decl-kwds' for keywords followed by a function or variable identifier (that's being defined)." - t '("struct" "union" "enum") - (c awk) nil + t nil c++ '("operator") - objc (append '("@class" "@interface" "@implementation" "@protocol") - (c-lang-const c-type-list-kwds)) - java '("class" "import" "interface" "new" "extends" "implements" "throws") - idl (append '("component" "eventtype" "home" "interface" "manages" "native" - "primarykey" "supports" "valuetype" - ;; In CORBA PSDL: - "as" "implements" "of" "scope" "storagehome" "storagetype") - (c-lang-const c-type-list-kwds)) - pike '("class" "enum" "inherit")) + objc '("@class") + java '("import" "new" "extends" "implements" "throws") + idl '("manages" "native" "primarykey" "supports" + ;; In CORBA PSDL: + "as" "implements" "of" "scope") + pike '("inherit")) (c-lang-defconst c-ref-list-kwds "Keywords that may be followed by a comma separated list of @@ -1414,9 +1810,8 @@ (c-lang-defconst c-colon-type-list-re "Regexp matched after the keywords in `c-colon-type-list-kwds' to skip forward to the colon. The end of the match is assumed to be directly -after the colon, so the regexp should end with \":\" although that -isn't necessary. Must be a regexp if `c-colon-type-list-kwds' isn't -nil." +after the colon, so the regexp should end with \":\". Must be a +regexp if `c-colon-type-list-kwds' isn't nil." t (if (c-lang-const c-colon-type-list-kwds) ;; Disallow various common punctuation chars that can't come ;; before the ":" that starts the inherit list after "class" @@ -1429,7 +1824,10 @@ "Keywords that may be followed by a parenthesis expression that doesn't contain type identifiers." t nil - (c c++) '("__declspec")) ; MSVC extension. + (c c++) '(;; GCC extension. + "__attribute__" + ;; MSVC extension. + "__declspec")) (c-lang-defconst c-paren-type-kwds "Keywords that may be followed by a parenthesis expression containing @@ -1512,6 +1910,12 @@ t (c-make-keywords-re t (c-lang-const c-block-stmt-2-kwds))) (c-lang-defvar c-block-stmt-2-key (c-lang-const c-block-stmt-2-key)) +(c-lang-defconst c-block-stmt-kwds + ;; Union of `c-block-stmt-1-kwds' and `c-block-stmt-2-kwds'. + t (delete-duplicates (append (c-lang-const c-block-stmt-1-kwds) + (c-lang-const c-block-stmt-2-kwds)) + :test 'string-equal)) + (c-lang-defconst c-opt-block-stmt-key ;; Regexp matching the start of any statement that has a ;; substatement (except a bare block). Nil in languages that @@ -1563,10 +1967,15 @@ (c-lang-defvar c-opt-asm-stmt-key (c-lang-const c-opt-asm-stmt-key)) (c-lang-defconst c-label-kwds - "Keywords introducing labels in blocks." + "Keywords introducing colon terminated labels in blocks." t '("case" "default") awk nil) +(c-lang-defconst c-label-kwds-regexp + ;; Adorned regexp matching any keyword that introduces a label. + t (c-make-keywords-re t (c-lang-const c-label-kwds))) +(c-lang-defvar c-label-kwds-regexp (c-lang-const c-label-kwds-regexp)) + (c-lang-defconst c-before-label-kwds "Keywords that might be followed by a label identifier." t '("goto") @@ -1575,11 +1984,6 @@ idl nil awk nil) -(c-lang-defconst c-label-kwds-regexp - ;; Regexp matching any keyword that introduces a label. - t (c-make-keywords-re t (c-lang-const c-label-kwds))) -(c-lang-defvar c-label-kwds-regexp (c-lang-const c-label-kwds-regexp)) - (c-lang-defconst c-constant-kwds "Keywords for constants." t nil @@ -1602,11 +2006,9 @@ ;; `c-primary-expr-kwds' and all keyword operators in `c-operators'. t (delete-duplicates (append (c-lang-const c-primary-expr-kwds) - (c-with-syntax-table (c-lang-const c-mode-syntax-table) - (mapcan (lambda (op) - (and (string-match "\\`\\(\\w\\|\\s_\\)+\\'" op) - (list op))) - (c-lang-const c-operator-list)))) + (c-filter-ops (c-lang-const c-operator-list) + t + "\\`\\(\\w\\|\\s_\\)+\\'")) :test 'string-equal)) (c-lang-defconst c-lambda-kwds @@ -1615,40 +2017,19 @@ t nil pike '("lambda")) -(c-lang-defconst c-opt-lambda-key - ;; Adorned regexp matching the start of lambda constructs, or nil in - ;; languages that don't have such things. - t (and (c-lang-const c-lambda-kwds) - (c-make-keywords-re t (c-lang-const c-lambda-kwds)))) -(c-lang-defvar c-opt-lambda-key (c-lang-const c-opt-lambda-key)) - (c-lang-defconst c-inexpr-block-kwds "Keywords that start constructs followed by statement blocks which can be used in expressions \(the gcc extension for this in C and C++ is -handled separately)." +handled separately by `c-recognize-paren-inexpr-blocks')." t nil pike '("catch" "gauge")) -(c-lang-defconst c-opt-inexpr-block-key - ;; Regexp matching the start of in-expression statements, or nil in - ;; languages that don't have such things. - t nil - pike (c-make-keywords-re t (c-lang-const c-inexpr-block-kwds))) -(c-lang-defvar c-opt-inexpr-block-key (c-lang-const c-opt-inexpr-block-key)) - (c-lang-defconst c-inexpr-class-kwds "Keywords that can start classes inside expressions." t nil java '("new") pike '("class")) -(c-lang-defconst c-opt-inexpr-class-key - ;; Regexp matching the start of a class in an expression, or nil in - ;; languages that don't have such things. - t (and (c-lang-const c-inexpr-class-kwds) - (c-make-keywords-re t (c-lang-const c-inexpr-class-kwds)))) -(c-lang-defvar c-opt-inexpr-class-key (c-lang-const c-opt-inexpr-class-key)) - (c-lang-defconst c-inexpr-brace-list-kwds "Keywords that can start brace list blocks inside expressions. Note that Java specific rules are currently applied to tell this from @@ -1665,30 +2046,26 @@ (c-lang-defvar c-opt-inexpr-brace-list-key (c-lang-const c-opt-inexpr-brace-list-key)) -(c-lang-defconst c-any-class-key - ;; Regexp matching the start of any class, both at top level and in - ;; expressions. - t (c-make-keywords-re t - (append (c-lang-const c-class-decl-kwds) - (c-lang-const c-inexpr-class-kwds)))) -(c-lang-defvar c-any-class-key (c-lang-const c-any-class-key)) - (c-lang-defconst c-decl-block-key - ;; Regexp matching the start of any declaration-level block that - ;; contain another declaration level, i.e. that isn't a function - ;; block or brace list. - t (c-make-keywords-re t - (append (c-lang-const c-class-decl-kwds) - (c-lang-const c-other-block-decl-kwds) - (c-lang-const c-inexpr-class-kwds))) - ;; In Pike modifiers might be followed by a block - ;; to apply to several declarations. - pike (concat (c-lang-const c-decl-block-key) - "\\|" - "\\(" (c-make-keywords-re nil - (c-lang-const c-modifier-kwds)) "\\)" - (c-lang-const c-syntactic-ws) - "{")) + ;; Regexp matching keywords in any construct that contain another + ;; declaration level, i.e. that isn't followed by a function block + ;; or brace list. When the first submatch matches, it's an + ;; unambiguous construct, otherwise it's an ambiguous match that + ;; might also be the return type of a function declaration. + t (let* ((decl-kwds (append (c-lang-const c-class-decl-kwds) + (c-lang-const c-other-block-decl-kwds) + (c-lang-const c-inexpr-class-kwds))) + (unambiguous (set-difference decl-kwds + (c-lang-const c-type-start-kwds) + :test 'string-equal)) + (ambiguous (intersection decl-kwds + (c-lang-const c-type-start-kwds) + :test 'string-equal))) + (if ambiguous + (concat (c-make-keywords-re t unambiguous) + "\\|" + (c-make-keywords-re t ambiguous)) + (c-make-keywords-re t unambiguous)))) (c-lang-defvar c-decl-block-key (c-lang-const c-decl-block-key)) (c-lang-defconst c-bitfield-kwds @@ -1794,7 +2171,7 @@ alist (cdr alist)) (setplist (intern kwd obarray) ;; Emacs has an odd bug that causes `mapcan' to fail - ;; with unintelligible errors. (XEmacs >= 20 works.) + ;; with unintelligible errors. (XEmacs works.) ;;(mapcan (lambda (lang-const) ;; (list lang-const t)) ;; lang-const-list) @@ -1804,8 +2181,8 @@ obarray)) (c-lang-defconst c-regular-keywords-regexp - ;; Adorned regexp matching all keywords that aren't types or - ;; constants. + ;; Adorned regexp matching all keywords that should be fontified + ;; with the keywords face. I.e. that aren't types or constants. t (c-make-keywords-re t (set-difference (c-lang-const c-keywords) (append (c-lang-const c-primitive-type-kwds) @@ -1814,25 +2191,6 @@ (c-lang-defvar c-regular-keywords-regexp (c-lang-const c-regular-keywords-regexp)) -(c-lang-defconst c-not-decl-init-keywords - ;; Adorned regexp matching all keywords that can't appear at the - ;; start of a declaration. - t (c-make-keywords-re t - (set-difference (c-lang-const c-keywords) - (append (c-lang-const c-primitive-type-kwds) - (c-lang-const c-type-prefix-kwds) - (c-lang-const c-type-modifier-kwds) - (c-lang-const c-class-decl-kwds) - (c-lang-const c-brace-list-decl-kwds) - (c-lang-const c-other-block-decl-kwds) - (c-lang-const c-typedef-decl-kwds) - (c-lang-const c-typeless-decl-kwds) - (c-lang-const c-modifier-kwds) - (c-lang-const c-other-decl-kwds)) - :test 'string-equal))) -(c-lang-defvar c-not-decl-init-keywords - (c-lang-const c-not-decl-init-keywords)) - (c-lang-defconst c-primary-expr-regexp ;; Regexp matching the start of any primary expression, i.e. any ;; literal, symbol, prefix operator, and '('. It doesn't need to @@ -1842,92 +2200,108 @@ ;; be a match of e.g. an infix operator. (The case with ambiguous ;; keyword operators isn't handled.) - t (c-with-syntax-table (c-lang-const c-mode-syntax-table) - (let* ((prefix-ops - (mapcan (lambda (op) - ;; Filter out the special case prefix - ;; operators that are close parens. - (unless (string-match "\\s\)" op) - (list op))) - (mapcan - (lambda (opclass) - (when (eq (car opclass) 'prefix) - (append (cdr opclass) nil))) - (c-lang-const c-operators)))) + t (let* ((prefix-ops + (c-filter-ops (c-lang-const c-operators) + '(prefix) + (lambda (op) + ;; Filter out the special case prefix + ;; operators that are close parens. + (not (string-match "\\s)" op))))) + + (nonkeyword-prefix-ops + (c-filter-ops prefix-ops + t + "\\`\\(\\s.\\|\\s(\\|\\s)\\)+\\'")) - (nonkeyword-prefix-ops - (mapcan (lambda (op) - (unless (string-match "\\`\\(\\w\\|\\s_\\)+\\'" op) - (list op))) - prefix-ops)) + (in-or-postfix-ops + (c-filter-ops (c-lang-const c-operators) + '(postfix + postfix-if-paren + left-assoc + right-assoc + right-assoc-sequence) + t)) - (in-or-postfix-ops - (mapcan (lambda (opclass) - (when (memq (car opclass) - '(postfix - left-assoc - right-assoc - right-assoc-sequence)) - (append (cdr opclass) nil))) - (c-lang-const c-operators))) - - (unambiguous-prefix-ops (set-difference nonkeyword-prefix-ops - in-or-postfix-ops - :test 'string-equal)) - (ambiguous-prefix-ops (intersection nonkeyword-prefix-ops - in-or-postfix-ops - :test 'string-equal))) + (unambiguous-prefix-ops (set-difference nonkeyword-prefix-ops + in-or-postfix-ops + :test 'string-equal)) + (ambiguous-prefix-ops (intersection nonkeyword-prefix-ops + in-or-postfix-ops + :test 'string-equal))) - (concat - "\\(" - ;; Take out all symbol class operators from `prefix-ops' and make the - ;; first submatch from them together with `c-primary-expr-kwds'. - (c-make-keywords-re t - (append (c-lang-const c-primary-expr-kwds) - (set-difference prefix-ops nonkeyword-prefix-ops - :test 'string-equal))) + (concat + "\\(" + ;; Take out all symbol class operators from `prefix-ops' and make the + ;; first submatch from them together with `c-primary-expr-kwds'. + (c-make-keywords-re t + (append (c-lang-const c-primary-expr-kwds) + (set-difference prefix-ops nonkeyword-prefix-ops + :test 'string-equal))) - "\\|" - ;; Match all ambiguous operators. - (c-make-keywords-re nil - (intersection nonkeyword-prefix-ops in-or-postfix-ops - :test 'string-equal)) - "\\)" + "\\|" + ;; Match all ambiguous operators. + (c-make-keywords-re nil + (intersection nonkeyword-prefix-ops in-or-postfix-ops + :test 'string-equal)) + "\\)" - "\\|" - ;; Now match all other symbols. - (c-lang-const c-symbol-start) + "\\|" + ;; Now match all other symbols. + (c-lang-const c-symbol-start) - "\\|" - ;; The chars that can start integer and floating point - ;; constants. - "\\.?[0-9]" + "\\|" + ;; The chars that can start integer and floating point + ;; constants. + "\\.?[0-9]" - "\\|" - ;; The nonambiguous operators from `prefix-ops'. - (c-make-keywords-re nil - (set-difference nonkeyword-prefix-ops in-or-postfix-ops - :test 'string-equal)) + "\\|" + ;; The nonambiguous operators from `prefix-ops'. + (c-make-keywords-re nil + (set-difference nonkeyword-prefix-ops in-or-postfix-ops + :test 'string-equal)) - "\\|" - ;; Match string and character literals. - "\\s\"" - (if (memq 'gen-string-delim c-emacs-features) - "\\|\\s|" - ""))))) + "\\|" + ;; Match string and character literals. + "\\s\"" + (if (memq 'gen-string-delim c-emacs-features) + "\\|\\s|" + "")))) (c-lang-defvar c-primary-expr-regexp (c-lang-const c-primary-expr-regexp)) ;;; Additional constants for parser-level constructs. (c-lang-defconst c-decl-prefix-re - "Regexp matching something that might precede a declaration or a cast, -such as the last token of a preceding statement or declaration. It -should not match bob, though. It can't require a match longer than -one token. The end of the token is taken to be at the end of the -first submatch. It must not include any following whitespace. It's -undefined whether identifier syntax (see `c-identifier-syntax-table') -is in effect or not." + "Regexp matching something that might precede a declaration, cast or +label, such as the last token of a preceding statement or declaration. +This is used in the common situation where a declaration or cast +doesn't start with any specific token that can be searched for. + +The regexp should not match bob; that is done implicitly. It can't +require a match longer than one token. The end of the token is taken +to be at the end of the first submatch, which is assumed to always +match. It's undefined whether identifier syntax (see +`c-identifier-syntax-table') is in effect or not. This regexp is +assumed to be a superset of `c-label-prefix-re' if +`c-recognize-colon-labels' is set. + +Besides this, `c-decl-start-kwds' is used to find declarations. + +Note: This variable together with `c-decl-start-re' and +`c-decl-start-kwds' is only used to detect \"likely\" +declaration/cast/label starts. I.e. they might produce more matches +but should not miss anything (or else it's necessary to use text +properties - see the next note). Wherever they match, the following +construct is analyzed to see if it indeed is a declaration, cast or +label. That analysis is not cheap, so it's important that not too +many false matches are triggered. + +Note: If a declaration/cast/label start can't be detected with this +variable, it's necessary to use the `c-type' text property with the +value `c-decl-end' on the last char of the last token preceding the +declaration. See the comment blurb at the start of cc-engine.el for +more info." + ;; We match a sequence of characters to skip over things like \"};\" ;; more quickly. We match ")" in C for K&R region declarations, and ;; in all languages except Java for when a cpp macro definition @@ -1937,12 +2311,7 @@ ;; Match "<" in C++ to get the first argument in a template arglist. ;; In that case there's an additional check in `c-find-decl-spots' ;; that it got open paren syntax. - ;; - ;; Also match a single ":" for protection labels. We cheat a little - ;; and require a symbol immediately before to avoid false matches - ;; when starting directly on a single ":", which can be the start of - ;; the base class initializer list in a constructor. - c++ "\\([\{\}\(\);,<]+\\|\\(\\w\\|\\s_\\):\\)\\([^:]\\|\\'\\)" + c++ "\\([\{\}\(\);,<]+\\)" ;; Additionally match the protection directives in Objective-C. ;; Note that this doesn't cope with the longer directives, which we ;; would have to match from start to end since they don't end with @@ -1950,37 +2319,135 @@ objc (concat "\\([\{\}\(\);,]+\\|" (c-make-keywords-re nil (c-lang-const c-protection-kwds)) "\\)") - ;; Match ":" for switch labels inside union declarations in IDL. - idl "\\([\{\}\(\);:,]+\\)\\([^:]\\|\\'\\)" ;; Pike is like C but we also match "[" for multiple value ;; assignments and type casts. pike "\\([\{\}\(\)\[;,]+\\)") (c-lang-defvar c-decl-prefix-re (c-lang-const c-decl-prefix-re) 'dont-doc) +(c-lang-defconst c-decl-start-re + "Regexp matching the start of any declaration, cast or label. +It's used on the token after the one `c-decl-prefix-re' matched. This +regexp should not try to match those constructs accurately as it's +only used as a sieve to avoid spending more time checking other +constructs." + t (c-lang-const c-identifier-start)) +(c-lang-defvar c-decl-start-re (c-lang-const c-decl-start-re)) + +(c-lang-defconst c-decl-prefix-or-start-re + ;; Regexp matching something that might precede or start a + ;; declaration, cast or label. + ;; + ;; If the first submatch matches, it's taken to match the end of a + ;; token that might precede such a construct, e.g. ';', '}' or '{'. + ;; It's built from `c-decl-prefix-re'. + ;; + ;; If the first submatch did not match, the match of the whole + ;; regexp is taken to be at the first token in the declaration. + ;; `c-decl-start-re' is not checked in this case. + ;; + ;; Design note: The reason the same regexp is used to match both + ;; tokens that precede declarations and start them is to avoid an + ;; extra regexp search from the previous declaration spot in + ;; `c-find-decl-spots'. Users of `c-find-decl-spots' also count on + ;; that it finds all declaration/cast/label starts in approximately + ;; linear order, so we can't do the searches in two separate passes. + t (if (c-lang-const c-decl-start-kwds) + (concat (c-lang-const c-decl-prefix-re) + "\\|" + (c-make-keywords-re t (c-lang-const c-decl-start-kwds))) + (c-lang-const c-decl-prefix-re))) +(c-lang-defvar c-decl-prefix-or-start-re + (c-lang-const c-decl-prefix-or-start-re) + 'dont-doc) + (c-lang-defconst c-cast-parens ;; List containing the paren characters that can open a cast, or nil in ;; languages without casts. - t (c-with-syntax-table (c-lang-const c-mode-syntax-table) - (mapcan (lambda (opclass) - (when (eq (car opclass) 'prefix) - (mapcan (lambda (op) - (when (string-match "\\`\\s\(\\'" op) - (list (elt op 0)))) - (cdr opclass)))) - (c-lang-const c-operators)))) + t (c-filter-ops (c-lang-const c-operators) + '(prefix) + "\\`\\s\(\\'" + (lambda (op) (elt op 0)))) (c-lang-defvar c-cast-parens (c-lang-const c-cast-parens)) +(c-lang-defconst c-block-prefix-disallowed-chars + "List of syntactically relevant characters that never can occur before +the open brace in any construct that contains a brace block, e.g. in +the \"class Foo: public Bar\" part of: + + class Foo: public Bar {int x();} a, *b; + +If parens can occur, the chars inside those aren't filtered with this +list. + +'<' and '>' should be disallowed even if angle bracket arglists can +occur. That since the search function needs to stop at them anyway to +ensure they are given paren syntax. + +This is used to skip backward from the open brace to find the region +in which to look for a construct like \"class\", \"enum\", +\"namespace\" or whatever. That skipping should be as tight as +possible for good performance." + + ;; Default to all chars that only occurs in nonsymbol tokens outside + ;; identifiers. + t (set-difference + (c-lang-const c-nonsymbol-token-char-list) + (c-filter-ops (append (c-lang-const c-identifier-ops) + (list (cons nil + (c-lang-const c-after-id-concat-ops)))) + t + t + (lambda (op) + (let ((pos 0) res) + (while (string-match "\\(\\s.\\|\\s(\\|\\s)\\)" + op pos) + (setq res (cons (aref op (match-beginning 1)) res) + pos (match-end 0))) + res)))) + + ;; Allow cpp operatios (where applicable). + t (if (c-lang-const c-opt-cpp-prefix) + (set-difference (c-lang-const c-block-prefix-disallowed-chars) + '(?#)) + (c-lang-const c-block-prefix-disallowed-chars)) + + ;; Allow ':' for inherit list starters. + (c++ objc idl) (set-difference (c-lang-const c-block-prefix-disallowed-chars) + '(?:)) + + ;; Allow ',' for multiple inherits. + (c++ java) (set-difference (c-lang-const c-block-prefix-disallowed-chars) + '(?,)) + + ;; Allow parentheses for anonymous inner classes in Java and class + ;; initializer lists in Pike. + (java pike) (set-difference (c-lang-const c-block-prefix-disallowed-chars) + '(?\( ?\))) + + ;; Allow '"' for extern clauses (e.g. extern "C" {...}). + (c c++ objc) (set-difference (c-lang-const c-block-prefix-disallowed-chars) + '(?\" ?'))) + +(c-lang-defconst c-block-prefix-charset + ;; `c-block-prefix-disallowed-chars' as an inverted charset suitable + ;; for `c-syntactic-skip-backward'. + t (c-make-bare-char-alt (c-lang-const c-block-prefix-disallowed-chars) t)) +(c-lang-defvar c-block-prefix-charset (c-lang-const c-block-prefix-charset)) + (c-lang-defconst c-type-decl-prefix-key - "Regexp matching the operators that might precede the identifier in a -declaration, e.g. the \"*\" in \"char *argv\". This regexp should -match \"(\" if parentheses are valid in type declarations. The end of -the first submatch is taken as the end of the operator. Identifier -syntax is in effect when this is matched (see `c-identifier-syntax-table')." + "Regexp matching the declarator operators that might precede the +identifier in a declaration, e.g. the \"*\" in \"char *argv\". This +regexp should match \"(\" if parentheses are valid in declarators. +The end of the first submatch is taken as the end of the operator. +Identifier syntax is in effect when this is matched \(see +`c-identifier-syntax-table')." t (if (c-lang-const c-type-modifier-kwds) - (concat (c-regexp-opt (c-lang-const c-type-modifier-kwds) t) "\\>") + (concat (regexp-opt (c-lang-const c-type-modifier-kwds) t) "\\>") ;; Default to a regexp that never matches. "\\<\\>") + ;; Check that there's no "=" afterwards to avoid matching tokens + ;; like "*=". (c objc) (concat "\\(" "[*\(]" "\\|" @@ -2001,14 +2468,14 @@ (c-lang-const c-type-decl-prefix-key) "\\)" "\\([^=]\\|$\\)") - pike "\\([*\(!~]\\)\\([^=]\\|$\\)") + pike "\\(\\*\\)\\([^=]\\|$\\)") (c-lang-defvar c-type-decl-prefix-key (c-lang-const c-type-decl-prefix-key) 'dont-doc) (c-lang-defconst c-type-decl-suffix-key - "Regexp matching the operators that might follow after the identifier -in a declaration, e.g. the \"[\" in \"char argv[]\". This regexp -should match \")\" if parentheses are valid in type declarations. If + "Regexp matching the declarator operators that might follow after the +identifier in a declaration, e.g. the \"[\" in \"char argv[]\". This +regexp should match \")\" if parentheses are valid in declarators. If it matches an open paren of some kind, the type declaration check continues at the corresponding close paren, otherwise the end of the first submatch is taken as the end of the operator. Identifier syntax @@ -2017,24 +2484,28 @@ ;; function argument list parenthesis. t (if (c-lang-const c-type-modifier-kwds) (concat "\\(\(\\|" - (c-regexp-opt (c-lang-const c-type-modifier-kwds) t) "\\>" + (regexp-opt (c-lang-const c-type-modifier-kwds) t) "\\>" "\\)") "\\(\(\\)") (c c++ objc) (concat "\\(" "[\)\[\(]" - "\\|" - ;; "throw" in `c-type-modifier-kwds' is followed by a - ;; parenthesis list, but no extra measures are - ;; necessary to handle that. - (c-regexp-opt (c-lang-const c-type-modifier-kwds) t) "\\>" + (if (c-lang-const c-type-modifier-kwds) + (concat + "\\|" + ;; "throw" in `c-type-modifier-kwds' is followed + ;; by a parenthesis list, but no extra measures + ;; are necessary to handle that. + (regexp-opt (c-lang-const c-type-modifier-kwds) t) + "\\>") + "") "\\)") (java idl) "\\([\[\(]\\)") (c-lang-defvar c-type-decl-suffix-key (c-lang-const c-type-decl-suffix-key) 'dont-doc) (c-lang-defconst c-after-suffixed-type-decl-key - "This regexp is matched after a type declaration expression where + "This regexp is matched after a declarator expression where `c-type-decl-suffix-key' has matched. If it matches then the construct is taken as a declaration. It's typically used to match the beginning of a function body or whatever might occur after the @@ -2052,11 +2523,11 @@ ;; could however produce false matches on code like "FOO(bar) x" ;; where FOO is a cpp macro, so it's better to leave it out and rely ;; on the other heuristics in that case. - t (if (c-lang-const c-postfix-decl-spec-kwds) - ;; Add on the keywords in `c-postfix-decl-spec-kwds'. + t (if (c-lang-const c-postfix-spec-kwds) + ;; Add on the keywords in `c-postfix-spec-kwds'. (concat (c-lang-const c-after-suffixed-type-decl-key) "\\|" - (c-make-keywords-re t (c-lang-const c-postfix-decl-spec-kwds))) + (c-make-keywords-re t (c-lang-const c-postfix-spec-kwds))) (c-lang-const c-after-suffixed-type-decl-key)) ;; Also match the colon that starts a base class initializer list in ;; C++. That can be confused with a function call before the colon @@ -2096,7 +2567,7 @@ is in effect or not." t nil (c c++ objc pike) "\\(\\.\\.\\.\\)" - java "\\(\\[[ \t\n\r\f\v]*\\]\\)") + java (concat "\\(\\[" (c-lang-const c-simple-ws) "*\\]\\)")) (c-lang-defvar c-opt-type-suffix-key (c-lang-const c-opt-type-suffix-key)) (c-lang-defvar c-known-type-key @@ -2105,13 +2576,28 @@ ;; submatch is the one that matches the type. Note that this regexp ;; assumes that symbol constituents like '_' and '$' have word ;; syntax. - (let ((extra-types (when (boundp (c-mode-symbol "font-lock-extra-types")) - (c-mode-var "font-lock-extra-types")))) + (let* ((extra-types + (when (boundp (c-mode-symbol "font-lock-extra-types")) + (c-mode-var "font-lock-extra-types"))) + (regexp-strings + (apply 'nconc + (mapcar (lambda (re) + (when (string-match "[][.*+?^$\\]" re) + (list re))) + extra-types))) + (plain-strings + (apply 'nconc + (mapcar (lambda (re) + (unless (string-match "[][.*+?^$\\]" re) + (list re))) + extra-types)))) (concat "\\<\\(" - (c-make-keywords-re nil (c-lang-const c-primitive-type-kwds)) - (if (consp extra-types) - (concat "\\|" (mapconcat 'identity extra-types "\\|")) - "") + (c-concat-separated + (append (list (c-make-keywords-re nil + (append (c-lang-const c-primitive-type-kwds) + plain-strings))) + regexp-strings) + "\\|") "\\)\\>"))) (c-lang-defconst c-special-brace-lists @@ -2163,6 +2649,14 @@ c++ t) (c-lang-defvar c-recognize-paren-inits (c-lang-const c-recognize-paren-inits)) +(c-lang-defconst c-recognize-paren-inexpr-blocks + "Non-nil to recognize gcc style in-expression blocks, +i.e. compound statements surrounded by parentheses inside expressions." + t nil + (c c++) t) +(c-lang-defvar c-recognize-paren-inexpr-blocks + (c-lang-const c-recognize-paren-inexpr-blocks)) + (c-lang-defconst c-opt-<>-arglist-start ;; Regexp matching the start of angle bracket arglists in languages ;; where `c-recognize-<>-arglists' is set. Does not exclude @@ -2188,52 +2682,117 @@ (c-lang-defvar c-opt-<>-arglist-start-in-paren (c-lang-const c-opt-<>-arglist-start-in-paren)) -(c-lang-defconst c-label-key - "Regexp matching a normal label, i.e. a label that doesn't begin with -a keyword like switch labels. It's only used at the beginning of a -statement." - t "\\<\\>" - (c c++ objc java pike) (concat "\\(" (c-lang-const c-symbol-key) "\\)" - "[ \t\n\r\f\v]*:\\([^:]\\|$\\)")) -(c-lang-defvar c-label-key (c-lang-const c-label-key) - 'dont-doc) - (c-lang-defconst c-opt-postfix-decl-spec-key ;; Regexp matching the beginning of a declaration specifier in the ;; region between the header and the body of a declaration. ;; ;; TODO: This is currently not used uniformly; c++-mode and ;; java-mode each have their own ways of using it. - t nil - c++ (concat ":?[ \t\n\r\f\v]*\\(virtual[ \t\n\r\f\v]+\\)?\\(" - (c-make-keywords-re nil (c-lang-const c-protection-kwds)) - "\\)[ \t\n\r\f\v]+" - "\\(" (c-lang-const c-symbol-key) "\\)") - java (c-make-keywords-re t (c-lang-const c-postfix-decl-spec-kwds))) + t nil + c++ (concat ":?" + (c-lang-const c-simple-ws) "*" + "\\(virtual" (c-lang-const c-simple-ws) "+\\)?\\(" + (c-make-keywords-re nil (c-lang-const c-protection-kwds)) + "\\)" (c-lang-const c-simple-ws) "+" + "\\(" (c-lang-const c-symbol-key) "\\)") + java (c-make-keywords-re t (c-lang-const c-postfix-spec-kwds))) (c-lang-defvar c-opt-postfix-decl-spec-key (c-lang-const c-opt-postfix-decl-spec-key)) +(c-lang-defconst c-recognize-colon-labels + "Non-nil if generic labels ending with \":\" should be recognized. +That includes labels in code and access keys in classes. This does +not apply to labels recognized by `c-label-kwds' and +`c-opt-extra-label-key'." + t nil + (c c++ objc java pike) t) +(c-lang-defvar c-recognize-colon-labels + (c-lang-const c-recognize-colon-labels)) + +(c-lang-defconst c-label-prefix-re + "Regexp like `c-decl-prefix-re' that matches any token that can precede +a generic colon label. Not used if `c-recognize-colon-labels' is +nil." + t "\\([{};]+\\)") +(c-lang-defvar c-label-prefix-re + (c-lang-const c-label-prefix-re)) + +(c-lang-defconst c-nonlabel-token-key + "Regexp matching things that can't occur in generic colon labels, +neither in a statement nor in a declaration context. The regexp is +tested at the beginning of every sexp in a suspected label, +i.e. before \":\". Only used if `c-recognize-colon-labels' is set." + t (concat + ;; Don't allow string literals. + "[\"']\\|" + ;; All keywords except `c-label-kwds' and `c-protection-kwds'. + (c-make-keywords-re t + (set-difference (c-lang-const c-keywords) + (append (c-lang-const c-label-kwds) + (c-lang-const c-protection-kwds)) + :test 'string-equal))) + ;; Also check for open parens in C++, to catch member init lists in + ;; constructors. We normally allow it so that macros with arguments + ;; work in labels. + c++ (concat "\\s\(\\|" (c-lang-const c-nonlabel-token-key))) +(c-lang-defvar c-nonlabel-token-key (c-lang-const c-nonlabel-token-key)) + +(c-lang-defconst c-opt-extra-label-key + "Optional regexp matching labels. +Normally, labels are detected according to `c-nonlabel-token-key', +`c-decl-prefix-re' and `c-nonlabel-decl-prefix-re'. This regexp can +be used if there are additional labels that aren't recognized that +way." + t nil + objc (c-make-keywords-re t (c-lang-const c-protection-kwds))) +(c-lang-defvar c-opt-extra-label-key (c-lang-const c-opt-extra-label-key)) + (c-lang-defconst c-opt-friend-key ;; Regexp describing friend declarations classes, or nil in ;; languages that don't have such things. ;; - ;; TODO: Ought to use `c-specifier-key' or similar, and the template - ;; skipping isn't done properly. This will disappear soon. - t nil - c++ "friend[ \t]+\\|template[ \t]*<.+>[ \t]*friend[ \t]+") + ;; TODO: Ought to use `c-prefix-spec-kwds-re' or similar, and the + ;; template skipping isn't done properly. This will disappear soon. + t nil + c++ (concat "friend" (c-lang-const c-simple-ws) "+" + "\\|" + (concat "template" + (c-lang-const c-simple-ws) "*" + "<.+>" + (c-lang-const c-simple-ws) "*" + "friend" + (c-lang-const c-simple-ws) "+"))) (c-lang-defvar c-opt-friend-key (c-lang-const c-opt-friend-key)) (c-lang-defconst c-opt-method-key ;; Special regexp to match the start of Objective-C methods. The ;; first submatch is assumed to end after the + or - key. - t nil + t nil objc (concat ;; TODO: Ought to use a better method than anchoring on bol. - "^[ \t]*\\([+-]\\)[ \t\n\r\f\v]*" - "\\(([^)]*)[ \t\n\r\f\v]*\\)?" ; return type + "^\\s *" + "\\([+-]\\)" + (c-lang-const c-simple-ws) "*" + (concat "\\(" ; Return type. + "([^\)]*)" + (c-lang-const c-simple-ws) "*" + "\\)?") "\\(" (c-lang-const c-symbol-key) "\\)")) (c-lang-defvar c-opt-method-key (c-lang-const c-opt-method-key)) +(c-lang-defconst c-type-decl-end-used + ;; Must be set in buffers where the `c-type' text property might be + ;; used with the value `c-decl-end'. + ;; + ;; `c-decl-end' is used to mark the ends of labels and access keys + ;; to make interactive refontification work better. + t (or (c-lang-const c-recognize-colon-labels) + (and (c-lang-const c-label-kwds) t)) + ;; `c-decl-end' is used to mark the end of the @-style directives in + ;; Objective-C. + objc t) +(c-lang-defvar c-type-decl-end-used (c-lang-const c-type-decl-end-used)) + ;;; Wrap up the `c-lang-defvar' system. @@ -2249,9 +2808,7 @@ This function should be evaluated at compile time, so that the function it returns is byte compiled with all the evaluated results from the language constants. Use the `c-init-language-vars' macro to -accomplish that conveniently. - -This function does not do any hidden buffer changes." +accomplish that conveniently." (if (and (not load-in-progress) (boundp 'byte-compile-dest-file) @@ -2282,12 +2839,14 @@ (elt init 1)))) (cdr c-lang-variable-inits)))) - (unless (get ',mode 'c-has-warned-lang-consts) - (message ,(concat "%s compiled with CC Mode %s " - "but loaded with %s - evaluating " - "language constants from source") - ',mode ,c-version c-version) - (put ',mode 'c-has-warned-lang-consts t)) + ;; This diagnostic message isn't useful for end + ;; users, so it's disabled. + ;;(unless (get ',mode 'c-has-warned-lang-consts) + ;; (message ,(concat "%s compiled with CC Mode %s " + ;; "but loaded with %s - evaluating " + ;; "language constants from source") + ;; ',mode ,c-version c-version) + ;; (put ',mode 'c-has-warned-lang-consts t)) (require 'cc-langs) (let ((init (cdr c-lang-variable-inits))) @@ -2328,9 +2887,7 @@ "Initialize all the language dependent variables for the given mode. This macro is expanded at compile time to a form tailored for the mode in question, so MODE must be a constant. Therefore MODE is not -evaluated and should not be quoted. - -This macro does not do any hidden buffer changes." +evaluated and should not be quoted." `(funcall ,(c-make-init-lang-vars-fun mode)))
--- a/lisp/progmodes/cc-menus.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/progmodes/cc-menus.el Sat Dec 10 21:18:28 2005 +0000 @@ -1,6 +1,7 @@ ;;; cc-menus.el --- imenu support for CC Mode -;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, Inc. +;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, +;; Inc. ;; Authors: 1998- Martin Stjernholm ;; 1992-1999 Barry A. Warsaw @@ -24,7 +25,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to +;; along with this program; see the file COPYING. If not, write to ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. @@ -240,7 +241,6 @@ - perform: (SEL)aSelector withObject: object1 withObject: object2; /* METHOD */ => -perform:withObject:withObject:withObject: /* selector */" - ;; This function does not do any hidden buffer changes. (let ((return "") ; String to be returned (p 0) ; Current scanning position in METHOD (pmax (length method)) ; @@ -281,7 +281,6 @@ (defun cc-imenu-objc-remove-white-space (str) "Remove all spaces and tabs from STR." - ;; This function does not do any hidden buffer changes. (let ((return "") (p 0) (max (length str)) @@ -296,7 +295,6 @@ (defun cc-imenu-objc-function () "imenu supports for objc-mode." - ;; This function does not do any hidden buffer changes. (let (methodlist clist ;; @@ -415,7 +413,6 @@ (defun cc-imenu-init (mode-generic-expression &optional mode-create-index-function) - ;; This function does not do any hidden buffer changes. (setq imenu-generic-expression mode-generic-expression imenu-case-fold-search nil) (when mode-create-index-function
--- a/lisp/progmodes/cc-mode.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/progmodes/cc-mode.el Sat Dec 10 21:18:28 2005 +0000 @@ -1,6 +1,7 @@ ;;; cc-mode.el --- major mode for editing C and similar languages -;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, Inc. +;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, +;; Inc. ;; Authors: 2003- Alan Mackenzie ;; 1998- Martin Stjernholm @@ -92,10 +93,9 @@ (cc-require 'cc-menus) ;; Silence the compiler. -(cc-bytecomp-defvar comment-line-break-function) ; (X)Emacs 20+ -(cc-bytecomp-defvar adaptive-fill-first-line-regexp) ; Emacs 20+ +(cc-bytecomp-defvar adaptive-fill-first-line-regexp) ; Emacs (cc-bytecomp-defun set-keymap-parents) ; XEmacs -(cc-bytecomp-defun run-mode-hooks) ; Emacs 21.1+ +(cc-bytecomp-defun run-mode-hooks) ; Emacs 21.1 (cc-bytecomp-obsolete-fun make-local-hook) ; Marked obsolete in Emacs 21.1. ;; We set these variables during mode init, yet we don't require @@ -107,6 +107,11 @@ ;; with your version of Emacs, you are incompatible! (cc-external-require 'easymenu) +;; Autoload directive for emacsen that doesn't have an older CC Mode +;; version in the dist. +(autoload 'c-subword-mode "cc-subword" + "Mode enabling subword movement and editing keys." t) + ;; Load cc-fonts first after font-lock is loaded, since it isn't ;; necessary until font locking is requested. (eval-after-load "font-lock" @@ -153,7 +158,6 @@ `c-init-language-vars' macro if the language you want to use is one of those, rather than a derived language defined through the language variable system (see \"cc-langs.el\")." - ;; This function does not do any hidden buffer changes. (cond ((eq mode 'c-mode) (c-init-language-vars c-mode)) ((eq mode 'c++-mode) (c-init-language-vars c++-mode)) ((eq mode 'objc-mode) (c-init-language-vars objc-mode)) @@ -171,8 +175,6 @@ only some basic setup is done, and a call to `c-init-language-vars' or `c-init-language-vars-for' is necessary too (which gives more control). See \"cc-mode.el\" for more info." - ;; - ;; This function does not do any hidden buffer changes. (setq c-buffer-is-cc-mode t) @@ -220,7 +222,7 @@ (defun c-define-abbrev-table (name defs) ;; Compatibility wrapper for `define-abbrev' which passes a non-nil ;; sixth argument for SYSTEM-FLAG in emacsen that support it - ;; (currently only Emacs 21.2). + ;; (currently only Emacs >= 21.2). (let ((table (or (symbol-value name) (progn (define-abbrev-table name nil) (symbol-value name))))) @@ -232,20 +234,25 @@ (setq defs (cdr defs))))) (put 'c-define-abbrev-table 'lisp-indent-function 1) +(defun c-bind-special-erase-keys () + ;; Only used in Emacs to bind C-c C-<delete> and C-c C-<backspace> + ;; to the proper keys depending on `normal-erase-is-backspace'. + (if normal-erase-is-backspace + (progn + (define-key c-mode-base-map (kbd "C-c C-<delete>") + 'c-hungry-delete-forward) + (define-key c-mode-base-map (kbd "C-c C-<backspace>") + 'c-hungry-backspace)) + (define-key c-mode-base-map (kbd "C-c C-<delete>") + 'c-hungry-backspace) + (define-key c-mode-base-map (kbd "C-c C-<backspace>") + 'c-hungry-delete-forward))) + (if c-mode-base-map nil - ;; TBD: should we even worry about naming this keymap. My vote: no, - ;; because Emacs and XEmacs do it differently. + (setq c-mode-base-map (make-sparse-keymap)) - ;; put standard keybindings into MAP - ;; the following mappings correspond more or less directly to BOCM - (define-key c-mode-base-map "{" 'c-electric-brace) - (define-key c-mode-base-map "}" 'c-electric-brace) - (define-key c-mode-base-map ";" 'c-electric-semi&comma) - (define-key c-mode-base-map "#" 'c-electric-pound) - (define-key c-mode-base-map ":" 'c-electric-colon) - (define-key c-mode-base-map "(" 'c-electric-paren) - (define-key c-mode-base-map ")" 'c-electric-paren) + ;; Separate M-BS from C-M-h. The former should remain ;; backward-kill-word. (define-key c-mode-base-map [(control meta h)] 'c-mark-function) @@ -259,21 +266,23 @@ (substitute-key-definition 'indent-new-comment-line 'c-indent-new-comment-line c-mode-base-map global-map) + (substitute-key-definition 'indent-for-tab-command + 'c-indent-command + c-mode-base-map global-map) (when (fboundp 'comment-indent-new-line) ;; indent-new-comment-line has changed name to ;; comment-indent-new-line in Emacs 21. (substitute-key-definition 'comment-indent-new-line 'c-indent-new-comment-line c-mode-base-map global-map)) + ;; RMS says don't make these the default. ;; (define-key c-mode-base-map "\e\C-a" 'c-beginning-of-defun) ;; (define-key c-mode-base-map "\e\C-e" 'c-end-of-defun) + (define-key c-mode-base-map "\C-c\C-n" 'c-forward-conditional) (define-key c-mode-base-map "\C-c\C-p" 'c-backward-conditional) (define-key c-mode-base-map "\C-c\C-u" 'c-up-conditional) - (substitute-key-definition 'indent-for-tab-command - 'c-indent-command - c-mode-base-map global-map) ;; It doesn't suffice to put `c-fill-paragraph' on ;; `fill-paragraph-function' since `c-fill-paragraph' must be called @@ -290,34 +299,74 @@ (substitute-key-definition 'fill-paragraph-or-region 'c-fill-paragraph c-mode-base-map global-map) + ;; We bind the forward deletion key and (implicitly) C-d to + ;; `c-electric-delete-forward', and the backward deletion key to + ;; `c-electric-backspace'. The hungry variants are bound to the + ;; same keys but prefixed with C-c. This implies that C-c C-d is + ;; `c-hungry-delete-forward'. For consistency, we bind not only C-c + ;; <backspace> to `c-hungry-backspace' but also C-c C-<backspace>, + ;; so that the Ctrl key can be held down during the whole sequence + ;; regardless of the direction. This in turn implies that we bind + ;; C-c C-<delete> to `c-hungry-delete-forward', for the same reason. + ;; Bind the electric deletion functions to C-d and DEL. Emacs 21 ;; automatically maps the [delete] and [backspace] keys to these two ;; depending on window system and user preferences. (In earlier ;; versions it's possible to do the same by using `function-key-map'.) (define-key c-mode-base-map "\C-d" 'c-electric-delete-forward) (define-key c-mode-base-map "\177" 'c-electric-backspace) - (when (boundp 'delete-key-deletes-forward) - ;; In XEmacs 20 and later we fix the forward and backward deletion - ;; behavior by binding the keysyms for the [delete] and - ;; [backspace] keys directly, and use `delete-forward-p' or - ;; `delete-key-deletes-forward' to decide what [delete] should do. + (define-key c-mode-base-map "\C-c\C-d" 'c-hungry-delete-forward) + (define-key c-mode-base-map [?\C-c ?\d] 'c-hungry-backspace) + (define-key c-mode-base-map [?\C-c ?\C-\d] 'c-hungry-backspace) + (define-key c-mode-base-map [?\C-c deletechar] 'c-hungry-delete-forward) ; C-c <delete> on a tty. + (define-key c-mode-base-map [?\C-c (control deletechar)] ; C-c C-<delete> on a tty. + 'c-hungry-delete-forward) + (when (boundp 'normal-erase-is-backspace) + ;; The automatic C-d and DEL mapping functionality doesn't extend + ;; to special combinations like C-c C-<delete>, so we have to hook + ;; into the `normal-erase-is-backspace' system to bind it directly + ;; as appropriate. + (add-hook 'normal-erase-is-backspace-hook 'c-bind-special-erase-keys) + (c-bind-special-erase-keys)) + + (when (fboundp 'delete-forward-p) + ;; In XEmacs we fix the forward and backward deletion behavior by + ;; binding the keysyms for the [delete] and [backspace] keys + ;; directly, and use `delete-forward-p' to decide what [delete] + ;; should do. That's done in the XEmacs specific + ;; `c-electric-delete' and `c-hungry-delete' functions. (define-key c-mode-base-map [delete] 'c-electric-delete) - (define-key c-mode-base-map [backspace] 'c-electric-backspace)) - (define-key c-mode-base-map "," 'c-electric-semi&comma) - (define-key c-mode-base-map "*" 'c-electric-star) + (define-key c-mode-base-map [backspace] 'c-electric-backspace) + (define-key c-mode-base-map (kbd "C-c <delete>") 'c-hungry-delete) + (define-key c-mode-base-map (kbd "C-c C-<delete>") 'c-hungry-delete) + (define-key c-mode-base-map (kbd "C-c <backspace>") 'c-hungry-backspace) + (define-key c-mode-base-map (kbd "C-c C-<backspace>") 'c-hungry-backspace)) + + (define-key c-mode-base-map "#" 'c-electric-pound) + (define-key c-mode-base-map "{" 'c-electric-brace) + (define-key c-mode-base-map "}" 'c-electric-brace) (define-key c-mode-base-map "/" 'c-electric-slash) - (define-key c-mode-base-map "\C-c\C-q" 'c-indent-defun) + (define-key c-mode-base-map "*" 'c-electric-star) + (define-key c-mode-base-map ";" 'c-electric-semi&comma) + (define-key c-mode-base-map "," 'c-electric-semi&comma) + (define-key c-mode-base-map ":" 'c-electric-colon) + (define-key c-mode-base-map "(" 'c-electric-paren) + (define-key c-mode-base-map ")" 'c-electric-paren) + (define-key c-mode-base-map "\C-c\C-\\" 'c-backslash-region) - (define-key c-mode-base-map "\C-c\C-a" 'c-toggle-auto-state) + (define-key c-mode-base-map "\C-c\C-a" 'c-toggle-auto-newline) (define-key c-mode-base-map "\C-c\C-b" 'c-submit-bug-report) (define-key c-mode-base-map "\C-c\C-c" 'comment-region) - (define-key c-mode-base-map "\C-c\C-d" 'c-toggle-hungry-state) + (define-key c-mode-base-map "\C-c\C-l" 'c-toggle-electric-state) (define-key c-mode-base-map "\C-c\C-o" 'c-set-offset) + (define-key c-mode-base-map "\C-c\C-q" 'c-indent-defun) (define-key c-mode-base-map "\C-c\C-s" 'c-show-syntactic-information) - (define-key c-mode-base-map "\C-c\C-t" 'c-toggle-auto-hungry-state) + ;; (define-key c-mode-base-map "\C-c\C-t" 'c-toggle-auto-hungry-state) Commented out by ACM, 2005-03-05. (define-key c-mode-base-map "\C-c." 'c-set-style) ;; conflicts with OOBR ;;(define-key c-mode-base-map "\C-c\C-v" 'c-version) + ;; (define-key c-mode-base-map "\C-c\C-y" 'c-toggle-hungry-state) Commented out by ACM, 2005-11-22. + (define-key c-mode-base-map "\C-c\C-w" 'c-subword-mode) ) ;; We don't require the outline package, but we configure it a bit anyway. @@ -341,32 +390,47 @@ (let ((f (symbol-function 'c-populate-syntax-table))) (if (byte-code-function-p f) f (byte-compile f))))) +;; CAUTION: Try to avoid installing things on +;; `before-change-functions'. The macro `combine-after-change-calls' +;; is used and it doesn't work if there are things on that hook. That +;; can cause font lock functions to run in inconvenient places during +;; temporary changes in some font lock support modes, causing extra +;; unnecessary work and font lock glitches due to interactions between +;; various text properties. + (defun c-after-change (beg end len) - ;; Function put on `after-change-functions' to adjust various - ;; caches. Prefer speed to finesse here, since there will be an - ;; order of magnitude more calls to this function than any of the + ;; Function put on `after-change-functions' to adjust various caches + ;; etc. Prefer speed to finesse here, since there will be an order + ;; of magnitude more calls to this function than any of the ;; functions that use the caches. ;; ;; Note that care must be taken so that this is called before any ;; font-lock callbacks since we might get calls to functions using ;; these caches from inside them, and we must thus be sure that this ;; has already been executed. - ;; - ;; This function does not do any hidden buffer changes. (c-save-buffer-state () - (when (> end (point-max)) - ;; Some emacsen might return positions past the end. This has been - ;; observed in Emacs 20.7 when rereading a buffer changed on disk - ;; (haven't been able to minimize it, but Emacs 21.3 appears to - ;; work). - (setq end (point-max)) - (when (> beg end) - (setq beg end))) + ;; When `combine-after-change-calls' is used we might get calls + ;; with regions outside the current narrowing. This has been + ;; observed in Emacs 20.7. + (save-restriction + (widen) - (c-invalidate-sws-region-after beg end) - (c-invalidate-state-cache beg) - (c-invalidate-find-decl-cache beg))) + (when (> end (point-max)) + ;; Some emacsen might return positions past the end. This has been + ;; observed in Emacs 20.7 when rereading a buffer changed on disk + ;; (haven't been able to minimize it, but Emacs 21.3 appears to + ;; work). + (setq end (point-max)) + (when (> beg end) + (setq beg end))) + + (c-invalidate-sws-region-after beg end) + (c-invalidate-state-cache beg) + (c-invalidate-find-decl-cache beg) + + (when c-recognize-<>-arglists + (c-after-change-check-<>-operators beg end))))) (defun c-basic-common-init (mode default-style) "Do the necessary initialization for the syntax handling routines @@ -380,8 +444,6 @@ Note that `c-init-language-vars' must be called before this function. This function cannot do that since `c-init-language-vars' is a macro that requires a literal mode spec at compile time." - ;; - ;; This function does not do any hidden buffer changes. (setq c-buffer-is-cc-mode mode) @@ -395,13 +457,20 @@ (make-local-variable 'comment-end) (make-local-variable 'comment-start-skip) (make-local-variable 'comment-multi-line) + (make-local-variable 'comment-line-break-function) + (make-local-variable 'paragraph-start) + (make-local-variable 'paragraph-separate) + (make-local-variable 'paragraph-ignore-fill-prefix) + (make-local-variable 'adaptive-fill-mode) + (make-local-variable 'adaptive-fill-regexp) ;; now set their values (setq parse-sexp-ignore-comments t indent-line-function 'c-indent-line indent-region-function 'c-indent-region normal-auto-fill-function 'c-do-auto-fill - comment-multi-line t) + comment-multi-line t + comment-line-break-function 'c-indent-new-comment-line) ;; Install `c-fill-paragraph' on `fill-paragraph-function' so that a ;; direct call to `fill-paragraph' behaves better. This still @@ -409,21 +478,25 @@ (make-local-variable 'fill-paragraph-function) (setq fill-paragraph-function 'c-fill-paragraph) - ;; (X)Emacs 20 and later. - (when (boundp 'comment-line-break-function) - (make-local-variable 'comment-line-break-function) - (setq comment-line-break-function - 'c-indent-new-comment-line)) + (when (or c-recognize-<>-arglists + (c-major-mode-is 'awk-mode)) + ;; We'll use the syntax-table text property to change the syntax + ;; of some chars for this language, so do the necessary setup for + ;; that. + ;; + ;; Note to other package developers: It's ok to turn this on in CC + ;; Mode buffers when CC Mode doesn't, but it's not ok to turn it + ;; off if CC Mode has turned it on. - ;; Emacs 20 and later. - (when (boundp 'parse-sexp-lookup-properties) - (make-local-variable 'parse-sexp-lookup-properties) - (setq parse-sexp-lookup-properties t)) + ;; Emacs. + (when (boundp 'parse-sexp-lookup-properties) + (make-local-variable 'parse-sexp-lookup-properties) + (setq parse-sexp-lookup-properties t)) - ;; Same as above for XEmacs 21 (although currently undocumented). - (when (boundp 'lookup-syntax-properties) - (make-local-variable 'lookup-syntax-properties) - (setq lookup-syntax-properties t)) + ;; Same as above for XEmacs. + (when (boundp 'lookup-syntax-properties) + (make-local-variable 'lookup-syntax-properties) + (setq lookup-syntax-properties t))) ;; Use this in Emacs 21 to avoid meddling with the rear-nonsticky ;; property on each character. @@ -441,18 +514,12 @@ ;; In Emacs 21 and later it's possible to turn off the ad-hoc ;; heuristic that open parens in column 0 are defun starters. Since - ;; we have c-state-cache that isn't useful and only causes trouble - ;; so turn it off. + ;; we have c-state-cache, that heuristic isn't useful and only causes + ;; trouble, so turn it off. (when (memq 'col-0-paren c-emacs-features) (make-local-variable 'open-paren-in-column-0-is-defun-start) (setq open-paren-in-column-0-is-defun-start nil)) - ;; The `c-type' text property with `c-decl-end' is used to mark the - ;; ends of access keys to make interactive refontification work - ;; better. - (when c-opt-access-key - (setq c-type-decl-end-used t)) - (c-clear-found-types) ;; now set the mode style based on default-style @@ -483,14 +550,15 @@ (make-local-variable 'comment-indent-function) (setq comment-indent-function 'c-comment-indent) - ;; put auto-hungry designators onto minor-mode-alist, but only once - (or (assq 'c-auto-hungry-string minor-mode-alist) + ;; Put submode indicators onto minor-mode-alist, but only once. + (or (assq 'c-submode-indicators minor-mode-alist) (setq minor-mode-alist - (cons '(c-auto-hungry-string c-auto-hungry-string) + (cons '(c-submode-indicators c-submode-indicators) minor-mode-alist))) ;; Install the functions that ensure that various internal caches ;; don't become invalid due to buffer changes. + (make-local-hook 'after-change-functions) (add-hook 'after-change-functions 'c-after-change nil t)) (defun c-after-font-lock-init () @@ -505,7 +573,7 @@ (make-local-variable 'font-lock-defaults) (setq font-lock-defaults - `(,(if (c-mode-is-new-awk-p) + `(,(if (c-major-mode-is 'awk-mode) ;; awk-mode currently has only one font lock level. 'awk-font-lock-keywords (mapcar 'c-mode-symbol @@ -517,6 +585,8 @@ (font-lock-lines-before . 1) (font-lock-mark-block-function . c-mark-function))) + + (make-local-hook 'font-lock-mode-hook) (add-hook 'font-lock-mode-hook 'c-after-font-lock-init nil t)) (defun c-setup-doc-comment-style () @@ -536,9 +606,7 @@ MODE is the symbol for the mode to initialize, like 'c-mode. See `c-basic-common-init' for details. It's only optional to be -compatible with old code; callers should always specify it. - -This function does not do any hidden buffer changes." +compatible with old code; callers should always specify it." (unless mode ;; Called from an old third party package. The fallback is to @@ -569,8 +637,6 @@ it finds in `c-file-offsets'. Note that the style variables are always made local to the buffer." - ;; - ;; This function does not do any hidden buffer changes. ;; apply file styles and offsets (when c-buffer-is-cc-mode @@ -584,7 +650,18 @@ (let ((langelem (car langentry)) (offset (cdr langentry))) (c-set-offset langelem offset))) - c-file-offsets)))) + c-file-offsets)) + ;; Problem: The file local variable block might have explicitly set a + ;; style variable. The `c-set-style' or `mapcar' call might have + ;; overwritten this. So we run `hack-local-variables' again to remedy + ;; this. There are no guarantees this will work properly, particularly as + ;; we have no control over what the other hook functions on + ;; `hack-local-variables-hook' would have done, or what any "eval" + ;; expression will do when evaluated again. C'est la vie! ACM, + ;; 2005/11/2. + (if (or c-file-style c-file-offsets) + (let ((hack-local-variables-hook nil)) + (hack-local-variables))))) (add-hook 'hack-local-variables-hook 'c-postprocess-file-styles) @@ -794,9 +871,6 @@ mode-name "ObjC" local-abbrev-table objc-mode-abbrev-table abbrev-mode t) - ;; The `c-type' text property with `c-decl-end' is used to mark the - ;; end of the @-style directives. - (setq c-type-decl-end-used t) (use-local-map objc-mode-map) (c-init-language-vars-for 'objc-mode) (c-common-init 'objc-mode) @@ -996,8 +1070,7 @@ (c-update-modeline)) -;; Support for awk. This is purposely disabled for older (X)Emacsen which -;; don't support syntax-table properties. +;; Support for AWK ;;;###autoload (add-to-list 'auto-mode-alist '("\\.awk\\'" . awk-mode)) ;;;###autoload (add-to-list 'interpreter-mode-alist '("awk" . awk-mode)) @@ -1009,37 +1082,34 @@ ;;; autoload form instead. ;;;###autoload (autoload 'awk-mode "cc-mode" "Major mode for editing AWK code." t) -(if (not (memq 'syntax-properties c-emacs-features)) - (autoload 'awk-mode "awk-mode" "Major mode for editing AWK code." t) - - (defvar awk-mode-abbrev-table nil - "Abbreviation table used in awk-mode buffers.") - (c-define-abbrev-table 'awk-mode-abbrev-table - '(("else" "else" c-electric-continued-statement 0) - ("while" "while" c-electric-continued-statement 0))) +(defvar awk-mode-abbrev-table nil + "Abbreviation table used in awk-mode buffers.") +(c-define-abbrev-table 'awk-mode-abbrev-table + '(("else" "else" c-electric-continued-statement 0) + ("while" "while" c-electric-continued-statement 0))) - (defvar awk-mode-map () - "Keymap used in awk-mode buffers.") - (if awk-mode-map - nil - (setq awk-mode-map (c-make-inherited-keymap)) - ;; add bindings which are only useful for awk. - (define-key awk-mode-map "#" 'self-insert-command) - (define-key awk-mode-map "/" 'self-insert-command) - (define-key awk-mode-map "*" 'self-insert-command) - (define-key awk-mode-map "\C-c\C-n" 'undefined) ; #if doesn't exist in awk. - (define-key awk-mode-map "\C-c\C-p" 'undefined) - (define-key awk-mode-map "\C-c\C-u" 'undefined) - (define-key awk-mode-map "\M-a" 'undefined) ; c-awk-beginning-of-statement isn't yet implemented. - (define-key awk-mode-map "\M-e" 'undefined) ; c-awk-end-of-statement isn't yet implemented. - (define-key awk-mode-map "\C-\M-a" 'c-awk-beginning-of-defun) - (define-key awk-mode-map "\C-\M-e" 'c-awk-end-of-defun)) +(defvar awk-mode-map () + "Keymap used in awk-mode buffers.") +(if awk-mode-map + nil + (setq awk-mode-map (c-make-inherited-keymap)) + ;; add bindings which are only useful for awk. + (define-key awk-mode-map "#" 'self-insert-command) + (define-key awk-mode-map "/" 'self-insert-command) + (define-key awk-mode-map "*" 'self-insert-command) + (define-key awk-mode-map "\C-c\C-n" 'undefined) ; #if doesn't exist in awk. + (define-key awk-mode-map "\C-c\C-p" 'undefined) + (define-key awk-mode-map "\C-c\C-u" 'undefined) + (define-key awk-mode-map "\M-a" 'c-beginning-of-statement) ; 2003/10/7 + (define-key awk-mode-map "\M-e" 'c-end-of-statement) ; 2003/10/7 + (define-key awk-mode-map "\C-\M-a" 'c-awk-beginning-of-defun) + (define-key awk-mode-map "\C-\M-e" 'c-awk-end-of-defun)) - (easy-menu-define c-awk-menu awk-mode-map "AWK Mode Commands" - (cons "AWK" (c-lang-const c-mode-menu awk))) +(easy-menu-define c-awk-menu awk-mode-map "AWK Mode Commands" + (cons "AWK" (c-lang-const c-mode-menu awk))) - (defun awk-mode () - "Major mode for editing AWK code. +(defun awk-mode () + "Major mode for editing AWK code. To submit a problem report, enter `\\[c-submit-bug-report]' from an awk-mode buffer. This automatically sets up a mail buffer with version information already added. You just need to add a description of the @@ -1052,41 +1122,40 @@ Key bindings: \\{awk-mode-map}" - (interactive) - (require 'cc-awk) ; Added 2003/6/10. - (kill-all-local-variables) - (c-initialize-cc-mode t) - (set-syntax-table awk-mode-syntax-table) - (setq major-mode 'awk-mode - mode-name "AWK" - local-abbrev-table awk-mode-abbrev-table - abbrev-mode t) - (use-local-map awk-mode-map) - (c-init-language-vars-for 'awk-mode) - (c-common-init 'awk-mode) - ;; The rest of CC Mode does not (yet) use `font-lock-syntactic-keywords', - ;; so it's not set by `c-font-lock-init'. - (make-local-variable 'font-lock-syntactic-keywords) - (setq font-lock-syntactic-keywords - '((c-awk-set-syntax-table-properties - 0 (0) ; Everything on this line is a dummy. - nil t))) - (c-awk-unstick-NL-prop) - (add-hook 'before-change-functions 'c-awk-before-change nil t) - (add-hook 'after-change-functions 'c-awk-after-change nil t) - (c-save-buffer-state nil - (save-restriction - (widen) - (c-awk-clear-NL-props (point-min) (point-max)) - (c-awk-after-change (point-min) (point-max) 0))) ; Set syntax-table props. + (interactive) + (require 'cc-awk) ; Added 2003/6/10. + (kill-all-local-variables) + (c-initialize-cc-mode t) + (set-syntax-table awk-mode-syntax-table) + (setq major-mode 'awk-mode + mode-name "AWK" + local-abbrev-table awk-mode-abbrev-table + abbrev-mode t) + (use-local-map awk-mode-map) + (c-init-language-vars-for 'awk-mode) + (c-common-init 'awk-mode) + ;; The rest of CC Mode does not (yet) use `font-lock-syntactic-keywords', + ;; so it's not set by `c-font-lock-init'. + (make-local-variable 'font-lock-syntactic-keywords) + (setq font-lock-syntactic-keywords + '((c-awk-set-syntax-table-properties + 0 (0) ; Everything on this line is a dummy. + nil t))) + (c-awk-unstick-NL-prop) + (add-hook 'before-change-functions 'c-awk-before-change nil t) + (add-hook 'after-change-functions 'c-awk-after-change nil t) + (c-save-buffer-state nil + (save-restriction + (widen) + (c-awk-clear-NL-props (point-min) (point-max)) + (c-awk-after-change (point-min) (point-max) 0))) ; Set syntax-table props. - ;; Prevent Xemacs's buffer-syntactic-context being used. See the comment - ;; in cc-engine.el, just before (defun c-fast-in-literal ... - (defalias 'c-in-literal 'c-slow-in-literal) + ;; Prevent Xemacs's buffer-syntactic-context being used. See the comment + ;; in cc-engine.el, just before (defun c-fast-in-literal ... + (defalias 'c-in-literal 'c-slow-in-literal) - (c-run-mode-hooks 'c-mode-common-hook 'awk-mode-hook) - (c-update-modeline)) -) ;; closes the (if (not (memq 'syntax-properties c-emacs-features)) + (c-run-mode-hooks 'c-mode-common-hook 'awk-mode-hook) + (c-update-modeline)) ;; bug reporting @@ -1175,5 +1244,5 @@ (cc-provide 'cc-mode) -;; arch-tag: 7825e5c4-fd09-439f-a04d-4c13208ba3d7 +;;; arch-tag: 7825e5c4-fd09-439f-a04d-4c13208ba3d7 ;;; cc-mode.el ends here
--- a/lisp/progmodes/cc-styles.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/progmodes/cc-styles.el Sat Dec 10 21:18:28 2005 +0000 @@ -1,6 +1,7 @@ ;;; cc-styles.el --- support for styles in CC Mode -;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, Inc. +;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, +;; Inc. ;; Authors: 1998- Martin Stjernholm ;; 1992-1999 Barry A. Warsaw @@ -24,7 +25,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to +;; along with this program; see the file COPYING. If not, write to ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. @@ -55,6 +56,7 @@ '(("gnu" (c-basic-offset . 2) (c-comment-only-line-offset . (0 . 0)) + (c-hanging-braces-alist . ((substatement-open before after))) (c-offsets-alist . ((statement-block-intro . +) (knr-argdecl-intro . 5) (substatement-open . +) @@ -65,11 +67,10 @@ (arglist-intro . c-lineup-arglist-intro-after-paren) (arglist-close . c-lineup-arglist) (inline-open . 0) - (brace-list-open . +) - )) + (brace-list-open . +))) (c-special-indent-hook . c-gnu-impose-minimum) - (c-block-comment-prefix . "") - ) + (c-block-comment-prefix . "")) + ("k&r" (c-basic-offset . 5) (c-comment-only-line-offset . 0) @@ -78,9 +79,8 @@ (substatement-open . 0) (substatement-label . 0) (label . 0) - (statement-cont . +) - )) - ) + (statement-cont . +)))) + ("bsd" (c-basic-offset . 8) (c-comment-only-line-offset . 0) @@ -91,9 +91,8 @@ (label . 0) (statement-cont . +) (inline-open . 0) - (inexpr-class . 0) - )) - ) + (inexpr-class . 0)))) + ("stroustrup" (c-basic-offset . 4) (c-comment-only-line-offset . 0) @@ -101,46 +100,61 @@ (substatement-open . 0) (substatement-label . 0) (label . 0) - (statement-cont . +) - )) - ) + (statement-cont . +)))) + ("whitesmith" (c-basic-offset . 4) (c-comment-only-line-offset . 0) - (c-offsets-alist . ((knr-argdecl-intro . +) - (label . 0) - (statement-cont . +) + ;; It's obvious that the CC Mode way of choosing anchor positions + ;; doesn't fit this style at all. :P + (c-offsets-alist . ((defun-open . +) + (defun-close . c-lineup-whitesmith-in-block) + (defun-block-intro . (add c-lineup-whitesmith-in-block + c-indent-multi-line-block)) + (class-open . +) + (class-close . +) + (inline-open . +) + (inline-close . c-lineup-whitesmith-in-block) + (knr-argdecl-intro . +) + (block-open . 0) ; Get indentation from `statement' instead. + (block-close . c-lineup-whitesmith-in-block) + (brace-list-open . +) + (brace-list-close . c-lineup-whitesmith-in-block) + (brace-list-intro . (add c-lineup-whitesmith-in-block + c-indent-multi-line-block)) + (brace-list-entry . (add c-lineup-after-whitesmith-blocks + c-indent-multi-line-block)) + (brace-entry-open . (add c-lineup-after-whitesmith-blocks + c-indent-multi-line-block)) + (statement . (add c-lineup-after-whitesmith-blocks + c-indent-multi-line-block)) + (statement-block-intro . (add c-lineup-whitesmith-in-block + c-indent-multi-line-block)) (substatement-open . +) (substatement-label . +) - (block-open . +) - (statement-block-intro . c-lineup-whitesmith-in-block) - (block-close . c-lineup-whitesmith-in-block) - (inline-open . +) - (defun-open . +) - (defun-block-intro . c-lineup-whitesmith-in-block) - (defun-close . c-lineup-whitesmith-in-block) - (brace-list-open . +) - (brace-list-intro . c-lineup-whitesmith-in-block) - (brace-entry-open . c-indent-multi-line-block) - (brace-list-close . c-lineup-whitesmith-in-block) - (class-open . +) + (label . 0) + (arglist-intro . (add c-lineup-whitesmith-in-block + c-indent-multi-line-block)) + (arglist-cont . (add c-lineup-after-whitesmith-blocks + c-indent-multi-line-block)) + (arglist-cont-nonempty . (add c-lineup-whitesmith-in-block + c-indent-multi-line-block)) + (arglist-close . c-lineup-whitesmith-in-block) (inclass . c-lineup-whitesmith-in-block) - (class-close . +) - (inexpr-class . 0) (extern-lang-open . +) - (inextern-lang . c-lineup-whitesmith-in-block) + (namespace-open . +) + (module-open . +) + (composition-open . +) (extern-lang-close . +) - (namespace-open . +) - (innamespace . c-lineup-whitesmith-in-block) (namespace-close . +) - (module-open . +) + (module-close . +) + (composition-close . +) + (inextern-lang . c-lineup-whitesmith-in-block) + (innamespace . c-lineup-whitesmith-in-block) (inmodule . c-lineup-whitesmith-in-block) - (module-close . +) - (composition-open . +) (incomposition . c-lineup-whitesmith-in-block) - (composition-close . +) - )) - ) + (inexpr-class . 0)))) + ("ellemtel" (c-basic-offset . 3) (c-comment-only-line-offset . 0) @@ -151,9 +165,8 @@ (case-label . +) (access-label . -) (inclass . ++) - (inline-open . 0) - )) - ) + (inline-open . 0)))) + ("linux" (c-basic-offset . 8) (c-comment-only-line-offset . 0) @@ -167,9 +180,8 @@ (substatement-open . 0) (substatement-label . 0) (label . 0) - (statement-cont . +) - )) - ) + (statement-cont . +)))) + ("python" (indent-tabs-mode . t) (fill-column . 78) @@ -177,17 +189,15 @@ (c-offsets-alist . ((substatement-open . 0) (inextern-lang . 0) (arglist-intro . +) - (knr-argdecl-intro . +) - )) + (knr-argdecl-intro . +))) (c-hanging-braces-alist . ((brace-list-open) (brace-list-intro) (brace-list-close) (brace-entry-open) (substatement-open after) - (block-close . c-snug-do-while) - )) - (c-block-comment-prefix . "") - ) + (block-close . c-snug-do-while))) + (c-block-comment-prefix . "")) + ("java" (c-basic-offset . 4) (c-comment-only-line-offset . (0 . 0)) @@ -205,9 +215,23 @@ (arglist-close . c-lineup-arglist) (access-label . 0) (inher-cont . c-lineup-java-inher) - (func-decl-cont . c-lineup-java-throws) - )) - ) + (func-decl-cont . c-lineup-java-throws)))) + + ;; awk style exists primarily for auto-newline settings. Otherwise it's + ;; pretty much like k&r. + ("awk" + (c-basic-offset . 4) + (c-comment-only-line-offset . 0) + (c-hanging-braces-alist . ((defun-open after) + (defun-close . c-snug-1line-defun-close) + (substatement-open after) + (block-close . c-snug-do-while))) + (c-hanging-semi&comma-criteria . nil) + (c-cleanup-list . nil) ; You might want one-liner-defun here. + (c-offsets-alist . ((statement-block-intro . +) + (substatement-open . 0) + (statement-cont . +)))) + ) "Styles of indentation. Elements of this alist are of the form: @@ -246,8 +270,6 @@ ;; Functions that manipulate styles (defun c-set-style-1 (conscell dont-override) ;; Set the style for one variable - ;; - ;; This function does not do any hidden buffer changes. (let ((attr (car conscell)) (val (cdr conscell))) (cond @@ -291,8 +313,6 @@ (defun c-get-style-variables (style basestyles) ;; Return all variables in a style by resolving inheritances. - ;; - ;; This function does not do any hidden buffer changes. (if (not style) (copy-alist c-fallback-style) (let ((vars (cdr (or (assoc (downcase style) c-style-alist) @@ -314,48 +334,36 @@ ;;;###autoload (defun c-set-style (stylename &optional dont-override) - "Set CC Mode variables to use one of several different indentation styles. -STYLENAME is a string representing the desired style from the list of -styles described in the variable `c-style-alist'. See that variable -for details of setting up styles. + "Set the current buffer to use the style STYLENAME. +STYLENAME, a string, must be an existing CC Mode style - These are contained +in the variable `c-style-alist'. -The variable `c-indentation-style' always contains the buffer's current -style name. +The variable `c-indentation-style' will get set to STYLENAME. + +\"Setting the style\" is done by setting CC Mode's \"style variables\" to the +values indicated by the pertinent entry in `c-style-alist'. Other variables +might get set too. -If the optional argument DONT-OVERRIDE is t, no style variables that -already have values will be overridden. I.e. in the case of -`c-offsets-alist', syntactic symbols will only be added, and in the -case of all other style variables, only those set to `set-from-style' -will be reassigned. +If DONT-OVERRIDE is neither nil nor t, style variables whose default values +have been set (more precisely, whose default values are not the symbol +`set-from-style') will not be changed. This avoids overriding global settings +done in ~/.emacs. It is useful to call c-set-style from a mode hook in this +way. -If DONT-OVERRIDE is neither nil nor t, only those style variables that -have default (i.e. non-buffer local) values will keep their settings -while the rest will be overridden. This is useful to avoid overriding -global settings done in ~/.emacs when setting a style from a mode hook -\(providing the style variables are buffer local, which is the -default). - -Obviously, setting DONT-OVERRIDE to t is useful mainly when the -initial style is chosen for a CC Mode buffer by a major mode. Since -that is done internally by CC Mode, it typically won't have any effect -when used elsewhere." +If DONT-OVERRIDE is t, style variables that already have values (i.e., whose +values are not the symbol `set-from-style') will not be overridden. CC Mode +calls c-set-style internally in this way whilst initializing a buffer; if +cc-set-style is called like this from anywhere else, it will usually behave as +a null operation." (interactive (list (let ((completion-ignore-case t) (prompt (format "Which %s indentation style? " mode-name))) - (condition-case nil - ;; The default argument is preferred over - ;; initial-contents, but it only exists in Emacs >= 20 - ;; and XEmacs >= 21. - (completing-read prompt c-style-alist nil t nil - 'c-set-style-history - c-indentation-style) - (wrong-number-of-arguments - ;; If the call above failed, we fall back to the old way - ;; of specifying the default value. - (completing-read prompt c-style-alist nil t - (cons c-indentation-style 0) - 'c-set-style-history)))))) + (completing-read prompt c-style-alist nil t nil + 'c-set-style-history + c-indentation-style)))) + (or c-buffer-is-cc-mode + (error "Buffer %s is not a CC Mode buffer (c-set-style)" (buffer-name))) (or (stringp stylename) (error "Argument to c-set-style was not a string")) (c-initialize-builtin-style) @@ -406,8 +414,6 @@ (defun c-read-offset (langelem) ;; read new offset value for LANGELEM from minibuffer. return a ;; legal value only - ;; - ;; This function does not do any hidden buffer changes. (let* ((oldoff (cdr-safe (or (assq langelem c-offsets-alist) (assq langelem (get 'c-offsets-alist 'c-stylevar-fallback))))) @@ -475,20 +481,22 @@ (setq c-offsets-alist (cons (cons symbol offset) c-offsets-alist)) (c-benign-error "%s is not a valid syntactic symbol" symbol)))) - (c-benign-error "Invalid indentation setting for symbol %s: %s" + (c-benign-error "Invalid indentation setting for symbol %s: %S" symbol offset)) (c-keep-region-active)) (defun c-setup-paragraph-variables () - "Fix things up for paragraph recognition and filling inside comments by -incorporating the value of `c-comment-prefix-regexp' in the relevant + "Fix things up for paragraph recognition and filling inside comments and +strings by incorporating the values of `c-comment-prefix-regexp', +`sentence-end', `paragraph-start' and `paragraph-separate' in the relevant variables." - ;; - ;; This function does not do any hidden buffer changes. (interactive) - + (or c-buffer-is-cc-mode + (error "Buffer %s is not a CC Mode buffer (c-setup-paragraph-variables)" + (buffer-name))) + ;; Set up the values for use in comments. (setq c-current-comment-prefix (if (listp c-comment-prefix-regexp) (cdr-safe (or (assoc major-mode c-comment-prefix-regexp) @@ -498,34 +506,48 @@ (let ((comment-line-prefix (concat "[ \t]*\\(" c-current-comment-prefix "\\)[ \t]*"))) - (set (make-local-variable 'paragraph-start) - (concat comment-line-prefix - c-paragraph-start - "\\|" - page-delimiter)) - (set (make-local-variable 'paragraph-separate) - (concat comment-line-prefix - c-paragraph-separate - "\\|" - page-delimiter)) - (set (make-local-variable 'paragraph-ignore-fill-prefix) t) - (set (make-local-variable 'adaptive-fill-mode) t) - (set (make-local-variable 'adaptive-fill-regexp) - (concat comment-line-prefix - (if (default-value 'adaptive-fill-regexp) - (concat "\\(" - (default-value 'adaptive-fill-regexp) - "\\)") - ""))) + (setq paragraph-start (concat comment-line-prefix + c-paragraph-start + "\\|" + page-delimiter) + paragraph-separate (concat comment-line-prefix + c-paragraph-separate + "\\|" + page-delimiter) + paragraph-ignore-fill-prefix t + adaptive-fill-mode t + adaptive-fill-regexp + (concat comment-line-prefix + (if (default-value 'adaptive-fill-regexp) + (concat "\\(" + (default-value 'adaptive-fill-regexp) + "\\)") + ""))) (when (boundp 'adaptive-fill-first-line-regexp) - ;; XEmacs (20.x) adaptive fill mode doesn't have this. - (set (make-local-variable 'adaptive-fill-first-line-regexp) - (concat "\\`" comment-line-prefix - ;; Maybe we should incorporate the old value here, - ;; but then we have to do all sorts of kludges to - ;; deal with the \` and \' it probably contains. - "\\'"))))) + ;; XEmacs adaptive fill mode doesn't have this. + (make-local-variable 'adaptive-fill-first-line-regexp) + (setq adaptive-fill-first-line-regexp + (concat "\\`" comment-line-prefix + ;; Maybe we should incorporate the old value here, + ;; but then we have to do all sorts of kludges to + ;; deal with the \` and \' it probably contains. + "\\'")))) + + ;; Set up the values for use in strings. These are the default + ;; paragraph-start/separate values, enhanced to accept escaped EOLs as + ;; whitespace. Used in c-beginning/end-of-sentence-in-string in cc-cmds. + (setq c-string-par-start + ;;(concat "\\(" (default-value 'paragraph-start) "\\)\\|[ \t]*\\\\$")) + "\f\\|[ \t]*\\\\?$") + (setq c-string-par-separate + ;;(concat "\\(" (default-value 'paragraph-separate) "\\)\\|[ \t]*\\\\$")) + "[ \t\f]*\\\\?$") + (setq c-sentence-end-with-esc-eol + (concat "\\(\\(" (c-default-value-sentence-end) "\\)" + ;; N.B.: "$" would be illegal when not enclosed like "\\($\\)". + "\\|" "[.?!][]\"')}]* ?\\\\\\($\\)[ \t\n]*" + "\\)"))) ;; Helper for setting up Filladapt mode. It's not used by CC Mode itself. @@ -542,8 +564,6 @@ `c-mode-common-hook' or similar." ;; This function is intended to be used explicitly by the end user ;; only. - ;; - ;; This function does not do any hidden buffer changes. ;; The default configuration already handles C++ comments, but we ;; need to add handling of C block comments. A new filladapt token @@ -573,8 +593,6 @@ ;; crucial because future c-set-style calls will always reset the ;; variables first to the `cc-mode' style before instituting the new ;; style. Only do this once! - ;; - ;; This function does not do any hidden buffer changes. (unless (get 'c-initialize-builtin-style 'is-run) (put 'c-initialize-builtin-style 'is-run t) ;;(c-initialize-cc-mode) @@ -601,13 +619,11 @@ "Make all CC Mode style variables buffer local. If `this-buf-only-p' is non-nil, the style variables will be made buffer local only in the current buffer. Otherwise they'll be made -permanently buffer local in any buffer that change their values. +permanently buffer local in any buffer that changes their values. The buffer localness of the style variables are normally controlled with the variable `c-style-variables-are-local-p', so there's seldom any reason to call this function directly." - ;; - ;; This function does not do any hidden buffer changes. ;; style variables (let ((func (if this-buf-only-p @@ -619,7 +635,7 @@ ;; Hooks must be handled specially (if this-buf-only-p (make-local-hook 'c-special-indent-hook) - (make-variable-buffer-local 'c-special-indent-hook) + (with-no-warnings (make-variable-buffer-local 'c-special-indent-hook)) (setq c-style-variables-are-local-p t)) )) @@ -627,5 +643,5 @@ (cc-provide 'cc-styles) -;; arch-tag: c764f61a-96ba-484a-a68f-101c0e9d5d2c +;;; arch-tag: c764f61a-96ba-484a-a68f-101c0e9d5d2c ;;; cc-styles.el ends here
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/progmodes/cc-subword.el Sat Dec 10 21:18:28 2005 +0000 @@ -0,0 +1,312 @@ +;;; cc-subword.el --- Handling capitalized subwords in a nomenclature + +;; Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +;; Author: Masatake YAMATO + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. + +;;; Commentary: + +;; This package provides `subword' oriented commands and a minor mode +;; (`c-subword-mode') that substitutes the common word handling +;; functions with them. + +;; In spite of GNU Coding Standards, it is popular to name a symbol by +;; mixing uppercase and lowercase letters, e.g. "GtkWidget", +;; "EmacsFrameClass", "NSGraphicsContext", etc. Here we call these +;; mixed case symbols `nomenclatures'. Also, each capitalized (or +;; completely uppercase) part of a nomenclature is called a `subword'. +;; Here are some examples: + +;; Nomenclature Subwords +;; =========================================================== +;; GtkWindow => "Gtk" and "Window" +;; EmacsFrameClass => "Emacs", "Frame" and "Class" +;; NSGraphicsContext => "NS", "Graphics" and "Context" + +;; The subword oriented commands defined in this package recognize +;; subwords in a nomenclature to move between them and to edit them as +;; words. + +;; In the minor mode, all common key bindings for word oriented +;; commands are overridden by the subword oriented commands: + +;; Key Word oriented command Subword oriented command +;; ============================================================ +;; M-f `forward-word' `c-forward-subword' +;; M-b `backward-word' `c-backward-subword' +;; M-@ `mark-word' `c-mark-subword' +;; M-d `kill-word' `c-kill-subword' +;; M-DEL `backward-kill-word' `c-backward-kill-subword' +;; M-t `transpose-words' `c-transpose-subwords' +;; M-c `capitalize-word' `c-capitalize-subword' +;; M-u `upcase-word' `c-upcase-subword' +;; M-l `downcase-word' `c-downcase-subword' +;; +;; Note: If you have changed the key bindings for the word oriented +;; commands in your .emacs or a similar place, the keys you've changed +;; to are also used for the corresponding subword oriented commands. + +;; To make the mode turn on automatically, put the following code in +;; your .emacs: +;; +;; (add-hook 'c-mode-common-hook +;; (lambda () (c-subword-mode 1))) +;; + +;; Acknowledgment: +;; The regular expressions to detect subwords are mostly based on +;; the old `c-forward-into-nomenclature' originally contributed by +;; Terry_Glanfield dot Southern at rxuk dot xerox dot com. + +;; TODO: ispell-word and subword oriented C-w in isearch. + +;;; Code: + +(eval-when-compile + (let ((load-path + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) + load-path))) + (load "cc-bytecomp" nil t))) + +(cc-require 'cc-defs) +(cc-require 'cc-cmds) + +;; Don't complain about the `define-minor-mode' form if it isn't defined. +(cc-bytecomp-defvar c-subword-mode) + +;;; Autoload directives must be on the top level, so we construct an +;;; autoload form instead. +;;;###autoload (autoload 'c-subword-mode "cc-subword" "Mode enabling subword movement and editing keys." t) + +(if (not (fboundp 'define-minor-mode)) + (defun c-subword-mode () + "(Missing) mode enabling subword movement and editing keys. +This mode is not (yet) available in this version of (X)Emacs. Sorry! If +you really want it, please send a request to <bug-gnu-emacs@gnu.org>, +telling us which (X)Emacs version you're using." + (interactive) + (error + "c-subword-mode is not (yet) available in this version of (X)Emacs. Sorry!")) + + (defvar c-subword-mode-map + (let ((map (make-sparse-keymap))) + (substitute-key-definition 'forward-word + 'c-forward-subword + map global-map) + (substitute-key-definition 'backward-word + 'c-backward-subword + map global-map) + (substitute-key-definition 'mark-word + 'c-mark-subword + map global-map) + + (substitute-key-definition 'kill-word + 'c-kill-subword + map global-map) + (substitute-key-definition 'backward-kill-word + 'c-backward-kill-subword + map global-map) + + (substitute-key-definition 'transpose-words + 'c-transpose-subwords + map global-map) + + (substitute-key-definition 'capitalize-word + 'c-capitalize-subword + map global-map) + (substitute-key-definition 'upcase-word + 'c-upcase-subword + map global-map) + (substitute-key-definition 'downcase-word + 'c-downcase-subword + map global-map) + map) + "Keymap used in command `c-subword-mode' minor mode.") + + (define-minor-mode c-subword-mode + "Mode enabling subword movement and editing keys. +In spite of GNU Coding Standards, it is popular to name a symbol by +mixing uppercase and lowercase letters, e.g. \"GtkWidget\", +\"EmacsFrameClass\", \"NSGraphicsContext\", etc. Here we call these +mixed case symbols `nomenclatures'. Also, each capitalized (or +completely uppercase) part of a nomenclature is called a `subword'. +Here are some examples: + + Nomenclature Subwords + =========================================================== + GtkWindow => \"Gtk\" and \"Window\" + EmacsFrameClass => \"Emacs\", \"Frame\" and \"Class\" + NSGraphicsContext => \"NS\", \"Graphics\" and \"Context\" + +The subword oriented commands activated in this minor mode recognize +subwords in a nomenclature to move between subwords and to edit them +as words. + +\\{c-subword-mode-map}" + nil + nil + c-subword-mode-map + (c-update-modeline)) + + ) + +(defun c-forward-subword (&optional arg) + "Do the same as `forward-word' but on subwords. +See the command `c-subword-mode' for a description of subwords. +Optional argument ARG is the same as for `forward-word'." + (interactive "p") + (unless arg (setq arg 1)) + (c-keep-region-active) + (cond + ((< 0 arg) + (dotimes (i arg (point)) + (c-forward-subword-internal))) + ((> 0 arg) + (dotimes (i (- arg) (point)) + (c-backward-subword-internal))) + (t + (point)))) + +(defun c-backward-subword (&optional arg) + "Do the same as `backward-word' but on subwords. +See the command `c-subword-mode' for a description of subwords. +Optional argument ARG is the same as for `backward-word'." + (interactive "p") + (c-forward-subword (- (or arg 1)))) + +(defun c-mark-subword (arg) + "Do the same as `mark-word' but on subwords. +See the command `c-subword-mode' for a description of subwords. +Optional argument ARG is the same as for `mark-word'." + ;; This code is almost copied from `mark-word' in GNU Emacs. + (interactive "p") + (cond ((and (eq last-command this-command) (mark t)) + (set-mark + (save-excursion + (goto-char (mark)) + (c-forward-subword arg) + (point)))) + (t + (push-mark + (save-excursion + (c-forward-subword arg) + (point)) + nil t)))) + +(defun c-kill-subword (arg) + "Do the same as `kill-word' but on subwords. +See the command `c-subword-mode' for a description of subwords. +Optional argument ARG is the same as for `kill-word'." + (interactive "p") + (kill-region (point) (c-forward-subword arg))) + +(defun c-backward-kill-subword (arg) + "Do the same as `backward-kill-word' but on subwords. +See the command `c-subword-mode' for a description of subwords. +Optional argument ARG is the same as for `backward-kill-word'." + (interactive "p") + (c-kill-subword (- arg))) + +(defun c-transpose-subwords (arg) + "Do the same as `transpose-words' but on subwords. +See the command `c-subword-mode' for a description of subwords. +Optional argument ARG is the same as for `transpose-words'." + (interactive "*p") + (transpose-subr 'c-forward-subword arg)) + +(defun c-capitalize-subword (arg) + "Do the same as `capitalize-word' but on subwords. +See the command `c-subword-mode' for a description of subwords. +Optional argument ARG is the same as for `capitalize-word'." + (interactive "p") + (let ((count (abs arg)) + (direction (if (< 0 arg) 1 -1))) + (dotimes (i count) + (when (re-search-forward + (concat "[" c-alpha "]") + nil t) + (goto-char (match-beginning 0))) + (let* ((p (point)) + (pp (1+ p)) + (np (c-forward-subword direction))) + (upcase-region p pp) + (downcase-region pp np) + (goto-char np))))) + +(defun c-downcase-subword (arg) + "Do the same as `downcase-word' but on subwords. +See the command `c-subword-mode' for a description of subwords. +Optional argument ARG is the same as for `downcase-word'." + (interactive "p") + (downcase-region (point) (c-forward-subword arg))) + +(defun c-upcase-subword (arg) + "Do the same as `upcase-word' but on subwords. +See the command `c-subword-mode' for a description of subwords. +Optional argument ARG is the same as for `upcase-word'." + (interactive "p") + (upcase-region (point) (c-forward-subword arg))) + + +;; +;; Internal functions +;; +(defun c-forward-subword-internal () + (if (and + (save-excursion + (let ((case-fold-search nil)) + (re-search-forward + (concat "\\W*\\(\\([" c-upper "]*\\W?\\)[" c-lower c-digit "]*\\)") + nil t))) + (> (match-end 0) (point))) ; So we don't get stuck at a + ; "word-constituent" which isn't c-upper, + ; c-lower or c-digit + (goto-char + (cond + ((< 1 (- (match-end 2) (match-beginning 2))) + (1- (match-end 2))) + (t + (match-end 0)))) + (forward-word 1))) + + +(defun c-backward-subword-internal () + (if (save-excursion + (let ((case-fold-search nil)) + (re-search-backward + (concat + "\\(\\(\\W\\|[" c-lower c-digit "]\\)\\([" c-upper "]+\\W*\\)" + "\\|\\W\\w+\\)") + nil t))) + (goto-char + (cond + ((and (match-end 3) + (< 1 (- (match-end 3) (match-beginning 3))) + (not (eq (point) (match-end 3)))) + (1- (match-end 3))) + (t + (1+ (match-beginning 0))))) + (backward-word 1))) + + +(cc-provide 'cc-subword) + +;;; arch-tag: 2be9d294-7f30-4626-95e6-9964bb93c7a3 +;;; cc-subword.el ends here
--- a/lisp/progmodes/cc-vars.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/progmodes/cc-vars.el Sat Dec 10 21:18:28 2005 +0000 @@ -1,6 +1,7 @@ ;;; cc-vars.el --- user customization variables for CC Mode -;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, Inc. +;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software +;; Foundation, Inc. ;; Authors: 1998- Martin Stjernholm ;; 1992-1999 Barry A. Warsaw @@ -24,7 +25,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to +;; along with this program; see the file COPYING. If not, write to ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. @@ -43,33 +44,11 @@ (cc-require 'cc-defs) ;; Silence the compiler. -(cc-bytecomp-defun get-char-table) ; XEmacs 20+ -(cc-bytecomp-defun char-table-range) ; Emacs 19+ -(cc-bytecomp-defun char-table-p) ; Emacs 19+, XEmacs 20+ +(cc-bytecomp-defun get-char-table) ; XEmacs -;; Pull in custom if it exists and is recent enough (the one in Emacs -;; 19.34 isn't). -(eval - (cc-eval-when-compile - (condition-case nil - (progn - (require 'custom) - (or (fboundp 'defcustom) (error "")) - (require 'widget) - '(progn ; Compile in the require's. - (require 'custom) - (require 'widget))) - (error - (message "Warning: Compiling without Customize support \ -since a (good enough) custom library wasn't found") - (cc-bytecomp-defmacro define-widget (name class doc &rest args)) - (cc-bytecomp-defmacro defgroup (symbol members doc &rest args)) - (cc-bytecomp-defmacro defcustom (symbol value doc &rest args) - `(defvar ,symbol ,value ,doc)) - (cc-bytecomp-defmacro custom-declare-variable (symbol value doc - &rest args) - `(defvar ,(eval symbol) ,(eval value) ,doc)) - nil)))) +(cc-eval-when-compile + (require 'custom) + (require 'widget)) (cc-eval-when-compile ;; Need the function form of `backquote', which isn't standardized @@ -207,7 +186,6 @@ (defun c-valid-offset (offset) "Return non-nil iff OFFSET is a valid offset for a syntactic symbol. See `c-offsets-alist'." - ;; This function does not do any hidden buffer changes. (or (eq offset '+) (eq offset '-) (eq offset '++) @@ -216,17 +194,19 @@ (eq offset '/) (integerp offset) (functionp offset) - (and (symbolp offset) - (or (boundp offset) - (fboundp offset))) + (and (symbolp offset) (boundp offset)) (and (vectorp offset) (= (length offset) 1) (integerp (elt offset 0))) - (progn - (while (and (consp offset) - (c-valid-offset (car offset))) - (setq offset (cdr offset))) - (null offset)))) + (and (consp offset) + (not (eq (car offset) 'quote)) ; Detect misquoted lists. + (progn + (when (memq (car offset) '(first min max add)) + (setq offset (cdr offset))) + (while (and (consp offset) + (c-valid-offset (car offset))) + (setq offset (cdr offset))) + (null offset))))) @@ -311,6 +291,7 @@ e.g. `c-special-indent-hook'." :type 'boolean :group 'c) +(make-variable-buffer-local 'c-syntactic-indentation) (defcustom c-syntactic-indentation-in-macros t "*Enable syntactic analysis inside macros. @@ -470,6 +451,7 @@ (defcustom-c-stylevar c-comment-prefix-regexp '((pike-mode . "//+!?\\|\\**") + (awk-mode . "#+") (other . "//+\\|\\**")) "*Regexp to match the line prefix inside comments. This regexp is used to recognize the fill prefix inside comments for @@ -517,14 +499,17 @@ (cons :format "%v" (const :format "IDL " idl-mode) (regexp :format "%v")) (cons :format "%v" - (const :format "Pike " pike-mode) (regexp :format "%v"))) + (const :format "Pike " pike-mode) (regexp :format "%v")) + (cons :format "%v" + (const :format "AWK " awk-mode) (regexp :format "%v"))) (cons :format " %v" (const :format "Other " other) (regexp :format "%v")))) :group 'c) (defcustom-c-stylevar c-doc-comment-style '((java-mode . javadoc) - (pike-mode . autodoc)) + (pike-mode . autodoc) + (c-mode . gtkdoc)) "*Specifies documentation comment style(s) to recognize. This is primarily used to fontify doc comments and the markup within them, e.g. Javadoc comments. @@ -534,6 +519,7 @@ javadoc -- Javadoc style for \"/** ... */\" comments (default in Java mode). autodoc -- Pike autodoc style for \"//! ...\" comments (default in Pike mode). + gtkdoc -- GtkDoc style for \"/** ... **/\" comments (default in C mode). The value may also be a list of doc comment styles, in which case all of them are recognized simultaneously (presumably with markup cues @@ -586,6 +572,9 @@ (const :format "Pike " pike-mode) (c-symbol-list :format "%v")) (cons :format "%v" + (const :format "AWK " awk-mode) + (c-symbol-list :format "%v")) + (cons :format "%v" (const :format "Other " other) (c-symbol-list :format "%v"))))) :group 'c) @@ -613,8 +602,8 @@ (defcustom-c-stylevar c-cleanup-list '(scope-operator) "*List of various C/C++/ObjC constructs to \"clean up\". The following clean ups only take place when the auto-newline feature -is turned on, as evidenced by the `/a' or `/ah' appearing next to the -mode name: +is turned on, as evidenced by the `/la' appearing next to the mode +name: brace-else-brace -- Clean up \"} else {\" constructs by placing entire construct on a single line. This clean @@ -630,21 +619,28 @@ \"} catch (...) {\" constructs. empty-defun-braces -- Clean up empty defun braces by placing the braces on the same line. Clean up occurs when - the defun closing brace is typed. + the defun closing brace is typed. + one-liner-defun -- If the code inside a function body is a single + line then remove any newlines between that + line and the defun braces so that the whole + body becomes a single line. + `c-max-one-liner-length' gives the maximum + length allowed for the resulting line. Clean + up occurs when the closing brace is typed. defun-close-semi -- Clean up the terminating semi-colon on defuns - by placing the semi-colon on the same line as - the closing brace. Clean up occurs when the - semi-colon is typed. + by placing the semi-colon on the same line as + the closing brace. Clean up occurs when the + semi-colon is typed. list-close-comma -- Clean up commas following braces in array and aggregate initializers. Clean up occurs - when the comma is typed. + when the comma is typed. scope-operator -- Clean up double colons which may designate - a C++ scope operator split across multiple - lines. Note that certain C++ constructs can - generate ambiguous situations. This clean up - only takes place when there is nothing but - whitespace between colons. Clean up occurs - when the second colon is typed. + a C++ scope operator split across multiple + lines. Note that certain C++ constructs can + generate ambiguous situations. This clean up + only takes place when there is nothing but + whitespace between colons. Clean up occurs + when the second colon is typed. The following clean ups always take place when they are on this list, regardless of the auto-newline feature, since they typically don't @@ -654,31 +650,39 @@ parenthesis of a function call. Clean up occurs when the opening parenthesis is typed. compact-empty-funcall -- Clean up any space before the function call - opening parenthesis if and only if the + opening parenthesis if and only if the argument list is empty. This is typically useful together with `space-before-funcall' to get the style \"foo (bar)\" and \"foo()\". Clean up occurs when the closing parenthesis - is typed." + is typed. + comment-close-slash -- When a slash is typed after the comment prefix + on a bare line in a c-style comment, the comment + is closed by cleaning up preceding space and + inserting a star if needed." :type '(set - (const :tag "Put \"} else {\" on one line" + (const :tag "Put \"} else {\" on one line (brace-else-brace)" brace-else-brace) - (const :tag "Put \"} else if (...) {\" on one line" + (const :tag "Put \"} else if (...) {\" on one line (brace-elseif-brace)" brace-elseif-brace) - (const :tag "Put \"} catch (...) {\" on one line" + (const :tag "Put \"} catch (...) {\" on one line (brace-catch-brace)" brace-catch-brace) - (const :tag "Put empty defun braces on one line" + (const :tag "Put empty defun braces on one line (empty-defun-braces)" empty-defun-braces) - (const :tag "Put \"};\" ending defuns on one line" + (const :tag "Put short function bodies on one line (one-liner-defun)" + one-liner-defun) + (const :tag "Put \"};\" ending defuns on one line (defun-close-semi)" defun-close-semi) - (const :tag "Put \"},\" in aggregates on one line" + (const :tag "Put \"},\" in aggregates on one line (list-close-comma)" list-close-comma) - (const :tag "Put C++ style \"::\" on one line" + (const :tag "Put C++ style \"::\" on one line (scope-operator)" scope-operator) - (const :tag "Put a space before funcall parens, e.g. \"foo (bar)\"" + (const :tag "Put a space before funcall parens, e.g. \"foo (bar)\" (space-before-funcall)" space-before-funcall) - (const :tag "Remove space before empty funcalls, e.g. \"foo()\"" - compact-empty-funcall)) + (const :tag "Remove space before empty funcalls, e.g. \"foo()\" (compact-empty-funcall)" + compact-empty-funcall) + (const :tag "Make / on a bare line of a C-style comment close it (comment-close-slash)" + comment-close-slash)) :group 'c) (defcustom-c-stylevar c-hanging-braces-alist '((brace-list-open) @@ -751,6 +755,12 @@ inexpr-class-open inexpr-class-close))) :group 'c) +(defcustom c-max-one-liner-length 80 + "Maximum length of line that clean-up \"one-liner-defun\" will compact to. +Zero or nil means no limit." + :type 'integer + :group 'c) + (defcustom-c-stylevar c-hanging-colons-alist nil "*Controls the insertion of newlines before and after certain colons. This variable contains an association list with elements of the @@ -832,35 +842,40 @@ :group 'c) (defcustom c-require-final-newline - ;; C and C++ mandates that all nonempty files should end with a + ;; C and C++ mandate that all nonempty files should end with a ;; newline. Objective-C refers to C for all things it doesn't - ;; specify, so the same holds there. The other languages does not + ;; specify, so the same holds there. The other languages do not ;; require it (at least not explicitly in a normative text). '((c-mode . t) (c++-mode . t) (objc-mode . t)) - "*Controls `require-final-newline' in C-related major modes. -The value is an association list specifying, for each specific mode, -whether to override `require-final-newline'. If the cdr of the element -is non-nil, that means to use `mode-require-final-newline' instead." + "*Controls whether a final newline is ensured when the file is saved. +The value is an association list that for each language mode specifies +the value to give to `require-final-newline' at mode initialization; +see that variable for details about the value. If a language isn't +present on the association list, CC Mode won't touch +`require-final-newline' in buffers for that language." :type `(set (cons :format "%v" (const :format "C " c-mode) - (const t)) + (symbol :format "%v" :value ,require-final-newline)) (cons :format "%v" (const :format "C++ " c++-mode) - (const t)) + (symbol :format "%v" :value ,require-final-newline)) (cons :format "%v" (const :format "ObjC " objc-mode) - (const t)) + (symbol :format "%v" :value ,require-final-newline)) (cons :format "%v" (const :format "Java " java-mode) - (const t)) + (symbol :format "%v" :value ,require-final-newline)) (cons :format "%v" (const :format "IDL " idl-mode) - (const t)) + (symbol :format "%v" :value ,require-final-newline)) (cons :format "%v" (const :format "Pike " pike-mode) - (const t))) + (symbol :format "%v" :value ,require-final-newline)) + (cons :format "%v" + (const :format "AWK " awk-mode) + (symbol :format "%v" :value ,require-final-newline))) :group 'c) (defcustom c-electric-pound-behavior nil @@ -892,7 +907,8 @@ :type 'integer :group 'c) -(defcustom c-default-style '((java-mode . "java") (other . "gnu")) +(defcustom c-default-style '((java-mode . "java") (awk-mode . "awk") + (other . "gnu")) "*Style which gets installed by default when a file is visited. The value of this variable can be any style defined in @@ -927,6 +943,8 @@ (cons :format "%v" (const :format "Pike " pike-mode) (string :format "%v")) (cons :format "%v" + (const :format "AWK " awk-mode) (string :format "%v")) + (cons :format "%v" (const :format "Other " other) (string :format "%v")))) :group 'c) @@ -939,170 +957,170 @@ ;; symbol and continue searching. (c-set-stylevar-fallback 'c-offsets-alist '((string . c-lineup-dont-change) - ;; Relpos: Beg of previous line. + ;; Anchor pos: Beg of previous line. (c . c-lineup-C-comments) - ;; Relpos: Beg of the comment. + ;; Anchor pos: Beg of the comment. (defun-open . 0) - ;; Relpos: When inside a class: Boi at the func decl start. + ;; Anchor pos: When inside a class: Boi at the func decl start. ;; When at top level: Bol at the func decl start. When inside ;; a code block (only possible in Pike): At the func decl ;; start(*). (defun-close . 0) - ;; Relpos: At the defun block open if it's at boi, otherwise - ;; boi at the func decl start. + ;; Anchor pos: At the defun block open if it's at boi, + ;; otherwise boi at the func decl start. (defun-block-intro . +) - ;; Relpos: At the block open(*). + ;; Anchor pos: At the block open(*). (class-open . 0) - ;; Relpos: Boi at the class decl start. + ;; Anchor pos: Boi at the class decl start. (class-close . 0) - ;; Relpos: Boi at the class decl start. + ;; Anchor pos: Boi at the class decl start. (inline-open . +) - ;; Relpos: None for functions (inclass got the relpos then), - ;; boi at the lambda start for lambdas. + ;; Anchor pos: None for functions (inclass got the relpos + ;; then), boi at the lambda start for lambdas. (inline-close . 0) - ;; Relpos: Inexpr functions: At the lambda block open if it's - ;; at boi, else at the statement(*) at boi of the start of the - ;; lambda construct. Otherwise: At the inline block open if - ;; it's at boi, otherwise boi at the func decl start. + ;; Anchor pos: Inexpr functions: At the lambda block open if + ;; it's at boi, else at the statement(*) at boi of the start of + ;; the lambda construct. Otherwise: At the inline block open + ;; if it's at boi, otherwise boi at the func decl start. (func-decl-cont . +) - ;; Relpos: Boi at the func decl start. + ;; Anchor pos: Boi at the func decl start. (knr-argdecl-intro . +) - ;; Relpos: Boi at the topmost intro line. + ;; Anchor pos: Boi at the topmost intro line. (knr-argdecl . 0) - ;; Relpos: At the beginning of the first K&R argdecl. + ;; Anchor pos: At the beginning of the first K&R argdecl. (topmost-intro . 0) - ;; Relpos: Bol at the last line of previous construct. + ;; Anchor pos: Bol at the last line of previous construct. (topmost-intro-cont . c-lineup-topmost-intro-cont) - ;; Relpos: Boi at the topmost intro line. + ;; Anchor pos: Boi at the topmost intro line. (member-init-intro . +) - ;; Relpos: Boi at the func decl arglist open. + ;; Anchor pos: Boi at the func decl arglist open. (member-init-cont . c-lineup-multi-inher) - ;; Relpos: Beg of the first member init. + ;; Anchor pos: Beg of the first member init. (inher-intro . +) - ;; Relpos: Boi at the class decl start. + ;; Anchor pos: Boi at the class decl start. (inher-cont . c-lineup-multi-inher) - ;; Relpos: Java: At the implements/extends keyword start. + ;; Anchor pos: Java: At the implements/extends keyword start. ;; Otherwise: At the inher start colon, or boi at the class ;; decl start if the first inherit clause hangs and it's not a ;; func-local inherit clause (when does that occur?). (block-open . 0) - ;; Relpos: Inexpr statement: At the statement(*) at boi of the - ;; start of the inexpr construct. Otherwise: None. + ;; Anchor pos: Inexpr statement: At the statement(*) at boi of + ;; the start of the inexpr construct. Otherwise: None. (block-close . 0) - ;; Relpos: Inexpr statement: At the inexpr block open if it's - ;; at boi, else at the statement(*) at boi of the start of the - ;; inexpr construct. Block hanging on a case/default label: At - ;; the closest preceding label that starts at boi. Otherwise: - ;; At the block open(*). + ;; Anchor pos: Inexpr statement: At the inexpr block open if + ;; it's at boi, else at the statement(*) at boi of the start of + ;; the inexpr construct. Block hanging on a case/default + ;; label: At the closest preceding label that starts at boi. + ;; Otherwise: At the block open(*). (brace-list-open . 0) - ;; Relpos: Boi at the brace list decl start, but a starting + ;; Anchor pos: Boi at the brace list decl start, but a starting ;; "typedef" token is ignored. (brace-list-close . 0) - ;; Relpos: At the brace list decl start(*). + ;; Anchor pos: At the brace list decl start(*). (brace-list-intro . +) - ;; Relpos: At the brace list decl start(*). + ;; Anchor pos: At the brace list decl start(*). (brace-list-entry . 0) - ;; Relpos: At the first non-ws char after the open paren if the - ;; first token is on the same line, otherwise boi at that + ;; Anchor pos: At the first non-ws char after the open paren if + ;; the first token is on the same line, otherwise boi at that ;; token. (brace-entry-open . 0) - ;; Relpos: Same as brace-list-entry. + ;; Anchor pos: Same as brace-list-entry. (statement . 0) - ;; Relpos: After a `;' in the condition clause of a for + ;; Anchor pos: After a `;' in the condition clause of a for ;; statement: At the first token after the starting paren. ;; Otherwise: At the preceding statement(*). (statement-cont . +) - ;; Relpos: After the first token in the condition clause of a - ;; for statement: At the first token after the starting paren. - ;; Otherwise: At the containing statement(*). + ;; Anchor pos: After the first token in the condition clause of + ;; a for statement: At the first token after the starting + ;; paren. Otherwise: At the containing statement(*). (statement-block-intro . +) - ;; Relpos: In inexpr statement block: At the inexpr block open - ;; if it's at boi, else at the statement(*) at boi of the start - ;; of the inexpr construct. In a block hanging on a + ;; Anchor pos: In inexpr statement block: At the inexpr block + ;; open if it's at boi, else at the statement(*) at boi of the + ;; start of the inexpr construct. In a block hanging on a ;; case/default label: At the closest preceding label that ;; starts at boi. Otherwise: At the start of the containing ;; block(*). (statement-case-intro . +) - ;; Relpos: At the case/default label(*). + ;; Anchor pos: At the case/default label(*). (statement-case-open . 0) - ;; Relpos: At the case/default label(*). + ;; Anchor pos: At the case/default label(*). (substatement . +) - ;; Relpos: At the containing statement(*). + ;; Anchor pos: At the containing statement(*). (substatement-open . +) - ;; Relpos: At the containing statement(*). + ;; Anchor pos: At the containing statement(*). (substatement-label . 2) - ;; Relpos: At the containing statement(*). + ;; Anchor pos: At the containing statement(*). (case-label . 0) - ;; Relpos: At the start of the switch block(*). + ;; Anchor pos: At the start of the switch block(*). (access-label . -) - ;; Relpos: Same as inclass. + ;; Anchor pos: Same as inclass. (label . 2) - ;; Relpos: At the start of the containing block(*). + ;; Anchor pos: At the start of the containing block(*). (do-while-closure . 0) - ;; Relpos: At the corresponding while statement(*). + ;; Anchor pos: At the corresponding while statement(*). (else-clause . 0) - ;; Relpos: At the corresponding if statement(*). + ;; Anchor pos: At the corresponding if statement(*). (catch-clause . 0) - ;; Relpos: At the previous try or catch statement clause(*). + ;; Anchor pos: At the previous try or catch statement clause(*). (comment-intro . (c-lineup-knr-region-comment c-lineup-comment)) - ;; Relpos: None. + ;; Anchor pos: None. (arglist-intro . +) - ;; Relpos: Boi at the open paren, or at the first non-ws after - ;; the open paren of the surrounding sexp, whichever is later. + ;; Anchor pos: At the containing statement(*). + ;; 2nd pos: At the open paren. (arglist-cont . (c-lineup-gcc-asm-reg 0)) - ;; Relpos: At the first token after the open paren. + ;; Anchor pos: At the first token after the open paren. (arglist-cont-nonempty . (c-lineup-gcc-asm-reg c-lineup-arglist)) - ;; Relpos: At the containing statement(*). + ;; Anchor pos: At the containing statement(*). ;; 2nd pos: At the open paren. (arglist-close . +) - ;; Relpos: At the containing statement(*). + ;; Anchor pos: At the containing statement(*). ;; 2nd pos: At the open paren. (stream-op . c-lineup-streamop) - ;; Relpos: Boi at the first stream op in the statement. + ;; Anchor pos: Boi at the first stream op in the statement. (inclass . +) - ;; Relpos: At the class open brace if it's at boi, otherwise - ;; boi at the class decl start. + ;; Anchor pos: At the class open brace if it's at boi, + ;; otherwise boi at the class decl start. (cpp-macro . [0]) - ;; Relpos: None. + ;; Anchor pos: None. (cpp-macro-cont . +) - ;; Relpos: At the macro start (always at boi). + ;; Anchor pos: At the macro start (always at boi). (cpp-define-intro . (c-lineup-cpp-define +)) - ;; Relpos: None. + ;; Anchor pos: None. (friend . 0) - ;; Relpos: None. + ;; Anchor pos: None. (objc-method-intro . [0]) - ;; Relpos: Boi. + ;; Anchor pos: Boi. (objc-method-args-cont . c-lineup-ObjC-method-args) - ;; Relpos: At the method start (always at boi). + ;; Anchor pos: At the method start (always at boi). (objc-method-call-cont . c-lineup-ObjC-method-call) - ;; Relpos: At the open bracket. + ;; Anchor pos: At the open bracket. (extern-lang-open . 0) (namespace-open . 0) (module-open . 0) (composition-open . 0) - ;; Relpos: Boi at the extern/namespace/etc keyword. + ;; Anchor pos: Boi at the extern/namespace/etc keyword. (extern-lang-close . 0) (namespace-close . 0) (module-close . 0) (composition-close . 0) - ;; Relpos: Boi at the corresponding extern/namespace/etc keyword. + ;; Anchor pos: Boi at the corresponding extern/namespace/etc keyword. (inextern-lang . +) (innamespace . +) (inmodule . +) (incomposition . +) - ;; Relpos: At the extern/namespace/etc block open brace if it's - ;; at boi, otherwise boi at the keyword. + ;; Anchor pos: At the extern/namespace/etc block open brace if + ;; it's at boi, otherwise boi at the keyword. (template-args-cont . (c-lineup-template-args +)) - ;; Relpos: Boi at the decl start. This might be changed; the - ;; logical position is clearly the opening '<'. + ;; Anchor pos: Boi at the decl start. This might be changed; + ;; the logical position is clearly the opening '<'. (inlambda . c-lineup-inexpr-block) - ;; Relpos: None. + ;; Anchor pos: None. (lambda-intro-cont . +) - ;; Relpos: Boi at the lambda start. + ;; Anchor pos: Boi at the lambda start. (inexpr-statement . +) - ;; Relpos: None. + ;; Anchor pos: None. (inexpr-class . +) - ;; Relpos: None. + ;; Anchor pos: None. )) (defcustom c-offsets-alist nil "Association list of syntactic element symbols and indentation offsets. @@ -1112,50 +1130,66 @@ When a line is indented, CC Mode first determines the syntactic context of it by generating a list of symbols called syntactic -elements. This list can contain more than one syntactic element and -the global variable `c-syntactic-context' contains the context list -for the line being indented. Each element in this list is actually a -cons cell of the syntactic symbol and a buffer position. This buffer -position is called the relative indent point for the line. Some -syntactic symbols may not have a relative indent point associated with -them. +elements. The global variable `c-syntactic-context' is bound to the +that list. Each element in the list is in turn a list where the first +element is a syntactic symbol which tells what kind of construct the +indentation point is located within. More elements in the syntactic +element lists are optional. If there is one more and it isn't nil, +then it's the anchor position for that construct. -After the syntactic context list for a line is generated, CC Mode -calculates the absolute indentation for the line by looking at each -syntactic element in the list. It compares the syntactic element -against the SYNTACTIC-SYMBOL's in `c-offsets-alist'. When it finds a -match, it adds the OFFSET to the column of the relative indent point. -The sum of this calculation for each element in the syntactic list is +After generating the syntactic context for the line, CC Mode +calculates the absolute indentation: First the base indentation is +found by using the anchor position for the first syntactic element +that provides one. If none does, zero is used as base indentation. +Then CC Mode looks at each syntactic element in the context in turn. +It compares the car of the syntactic element against the +SYNTACTIC-SYMBOL's in `c-offsets-alist'. When it finds a match, it +adds OFFSET to the base indentation. The sum of this calculation is the absolute offset for line being indented. If the syntactic element does not match any in the `c-offsets-alist', the element is ignored. -If OFFSET is nil, the syntactic element is ignored in the offset -calculation. +OFFSET can specify an offset in several different ways: + + If OFFSET is nil then it's ignored. + + If OFFSET is an integer then it's used as relative offset, i.e. it's + added to the base indentation. -If OFFSET is an integer, it's added to the relative indent. + If OFFSET is one of the symbols `+', `-', `++', `--', `*', or `/' + then a positive or negative multiple of `c-basic-offset' is added to + the base indentation; 1, -1, 2, -2, 0.5, and -0.5, respectively. -If OFFSET is one of the symbols `+', `-', `++', `--', `*', or `/', a -positive or negative multiple of `c-basic-offset' is added; 1, -1, 2, --2, 0.5, and -0.5, respectively. + If OFFSET is a symbol with a value binding then that value, which + must be an integer, is used as relative offset. + + If OFFSET is a vector then it's first element, which must be an + integer, is used as an absolute indentation column. This overrides + the previous base indentation and the relative offsets applied to + it, and it becomes the new base indentation. -If OFFSET is a vector, it's first element, which must be an integer, -is used as an absolute indentation column. This overrides all -relative offsets. If there are several syntactic elements which -evaluates to absolute indentation columns, the first one takes -precedence. You can see in which order CC Mode combines the syntactic -elements in a certain context by using \\[c-show-syntactic-information] on the line. + If OFFSET is a function or a lambda expression then it's called with + a single argument containing the cons of the syntactic symbol and + the anchor position (or nil if there is none). The return value + from the function is then reinterpreted as an offset specification. -If OFFSET is a function, it's called with a single argument -containing the cons of the syntactic element symbol and the relative -indent point. The return value from the function is then -reinterpreted as an OFFSET value. + If OFFSET is a list then its elements are evaluated recursively as + offset specifications. If the first element is any of the symbols + below then it isn't evaluated but instead specifies how the + remaining offsets in the list should be combined. If it's something + else then the list is combined according the method `first'. The + valid combination methods are: -If OFFSET is a list, it's recursively evaluated using the semantics -described above. The first element of the list to return a non-nil -value succeeds. If none of the elements returns a non-nil value, the -syntactic element is ignored. + `first' -- Use the first offset (that doesn't evaluate to nil). + `min' -- Use the minimum of all the offsets. All must be either + relative or absolute - they can't be mixed. + `max' -- Use the maximum of all the offsets. All must be either + relative or absolute - they can't be mixed. + `add' -- Add all the evaluated offsets together. Exactly one of + them may be absolute, in which case the result is + absolute. Any relative offsets that preceded the + absolute one in the list will be ignored in that case. `c-offsets-alist' is a style variable. This means that the offsets on this variable are normally taken from the style system in CC Mode @@ -1336,6 +1370,11 @@ :type 'hook :group 'c) +(defcustom awk-mode-hook nil + "*Hook called by `awk-mode'." + :type 'hook + :group 'c) + (defcustom c-mode-common-hook nil "*Hook called by all CC Mode modes for common initializations." :type 'hook @@ -1380,16 +1419,17 @@ :args '((const :tag "none" nil) (repeat :tag "types" regexp))) -(eval-and-compile - ;; XEmacs 19 evaluates this at compile time below, while most other - ;; versions delays the evaluation until the package is loaded. - (defun c-make-font-lock-extra-types-blurb (mode1 mode2 example) - (concat "\ +(defun c-make-font-lock-extra-types-blurb (mode1 mode2 example) + (concat "\ *List of extra types (aside from the type keywords) to recognize in " mode1 " mode. Each list item should be a regexp matching a single identifier. " example " +Note that items on this list that don't include any regexp special +characters are automatically optimized using `regexp-opt', so you +should not use `regexp-opt' explicitly to build regexps here. + On decoration level 3 (and higher, where applicable), a method is used that finds most types and declarations by syntax alone. This variable is still used as a first step, but other types are recognized @@ -1401,43 +1441,58 @@ by doing \\[" mode2 "]. Despite the name, this variable is not only used for font locking but -also elsewhere in CC Mode to tell types from other identifiers."))) +also elsewhere in CC Mode to tell types from other identifiers.")) ;; Note: Most of the variables below are also defined in font-lock.el -;; in older versions in Emacs, so depending on the load order we might +;; in older versions of Emacs, so depending on the load order we might ;; not install the values below. There's no kludge to cope with this ;; (as opposed to the *-font-lock-keywords-* variables) since the old ;; values work fairly well anyway. (defcustom c-font-lock-extra-types - '("FILE" "\\sw+_t" - "bool" "complex" "imaginary" ; Defined in C99. + '("\\sw+_t" + ;; Defined in C99: + "bool" "complex" "imaginary" + ;; Standard library types (except those matched by the _t pattern): + "FILE" "lconv" "tm" "va_list" "jmp_buf" ;; I do not appreciate the following very Emacs-specific luggage ;; in the default value, but otoh it can hardly get in the way for ;; other users, and removing it would cause unnecessary grief for ;; the old timers that are used to it. /mast "Lisp_Object") (c-make-font-lock-extra-types-blurb "C" "c-mode" -"For example, a value of (\"FILE\" \"\\\\sw+_t\") means the word FILE -and words ending in _t are treated as type names.") +"For example, a value of (\"FILE\" \"\\\\sw+_t\") means the word \"FILE\" +and words ending in \"_t\" are treated as type names.") :type 'c-extra-types-widget :group 'c) (defcustom c++-font-lock-extra-types '("\\sw+_t" - "\\([iof]\\|str\\)+stream\\(buf\\)?" "ios" + ;; C library types (except those matched by the _t pattern): + "FILE" "lconv" "tm" "va_list" "jmp_buf" + ;; Some standard C++ types that came from font-lock.el. + ;; Experienced C++ users says there's no clear benefit in + ;; extending this to all the types in the standard library, at + ;; least not when they'll be recognized without "std::" too. + "istream" "istreambuf" + "ostream" "ostreambuf" + "ifstream" "ofstream" "fstream" + "strstream" "strstreambuf" "istrstream" "ostrstream" + "ios" "string" "rope" "list" "slist" "deque" "vector" "bit_vector" "set" "multiset" "map" "multimap" - "hash\\(_\\(m\\(ap\\|ulti\\(map\\|set\\)\\)\\|set\\)\\)?" + "hash" + "hash_set" "hash_multiset" + "hash_map" "hash_multimap" "stack" "queue" "priority_queue" "type_info" "iterator" "const_iterator" "reverse_iterator" "const_reverse_iterator" "reference" "const_reference") (c-make-font-lock-extra-types-blurb "C++" "c++-mode" -"For example, a value of (\"string\") means the word string is treated +"For example, a value of (\"string\") means the word \"string\" is treated as a type name.") :type 'c-extra-types-widget :group 'c) @@ -1499,40 +1554,49 @@ as designated in the variable `c-file-style'.") (make-variable-buffer-local 'c-file-offsets) -;; It isn't possible to specify a docstring without specifying an -;; initial value with `defvar', so the following two variables have -;; only doc comments even though they are part of the API. It's -;; really good not to have an initial value for variables like these -;; that always should be dynamically bound, so it's worth the -;; inconvenience. +;; It isn't possible to specify a doc-string without specifying an +;; initial value with `defvar', so the following two variables have been +;; given doc-strings by setting the property `variable-documentation' +;; directly. C-h v will read this documentation only for versions of GNU +;; Emacs from 22.1. It's really good not to have an initial value for +;; variables like these that always should be dynamically bound, so it's +;; worth the inconvenience. (cc-bytecomp-defvar c-syntactic-context) (defvar c-syntactic-context) -;; Variable containing the syntactic analysis list during indentation. -;; It is a list with one element for each found syntactic symbol. See -;; `c-syntactic-element' for further info. -;; -;; This is always bound dynamically. It should never be set -;; statically (e.g. with `setq'). +(put 'c-syntactic-context 'variable-documentation + "Variable containing the syntactic analysis list for a line of code. + +It is a list with one element for each syntactic symbol pertinent to the +line, for example \"((defun-block-intro 1) (comment-intro))\". + +It is dynamically bound when calling \(i) a brace hanging \"action +function\"; \(ii) a semicolon/comma hanging \"criteria function\"; \(iii) a +\"line-up function\"; \(iv) a c-special-indent-hook function. It is also +used internally by CC Mode. + +c-syntactic-context is always bound dynamically. It must NEVER be set +statically (e.g. with `setq').") + (cc-bytecomp-defvar c-syntactic-element) (defvar c-syntactic-element) -;; Variable containing the info regarding the current syntactic -;; element during calls to the lineup functions. The value is one of -;; the elements in the list in `c-syntactic-context' and is a list -;; with the symbol name in the first position, followed by zero or -;; more elements containing any additional info associated with the -;; syntactic symbol. There are accessor functions `c-langelem-sym', -;; `c-langelem-pos', `c-langelem-col', and `c-langelem-2nd-pos' to -;; access the list. -;; -;; Specifically, the element returned by `c-langelem-pos' is the -;; relpos (a.k.a. anchor position), or nil if there isn't any. See -;; the comments in the `c-offsets-alist' variable for more detailed -;; info about the data each syntactic symbol provides. -;; -;; This is always bound dynamically. It should never be set -;; statically (e.g. with `setq'). +(put 'c-syntactic-element 'variable-documentation + "Variable containing the current syntactic element during calls to +the lineup functions. The value is one of the elements in the list in +`c-syntactic-context' and is a list with the symbol name in the first +position, followed by zero or more elements containing any additional +info associated with the syntactic symbol. There are accessor functions +`c-langelem-sym', `c-langelem-pos', `c-langelem-col', and +`c-langelem-2nd-pos' to access the list. + +Specifically, the element returned by `c-langelem-pos' is the anchor +position, or nil if there isn't any. See the comments in the +`c-offsets-alist' variable and the CC Mode manual for more detailed info +about the data each syntactic symbol provides. + +This is always bound dynamically. It should never be set +statically (e.g. with `setq').") (defvar c-indentation-style nil "Name of the currently installed style. @@ -1543,6 +1607,29 @@ Set from `c-comment-prefix-regexp' at mode initialization.") (make-variable-buffer-local 'c-current-comment-prefix) +;; N.B. The next three variables are initialized in +;; c-setup-paragraph-variables. Their initializations here are "just in +;; case". ACM, 2004/2/15. They are NOT buffer local (yet?). +(defvar c-string-par-start +;; (concat "\\(" (default-value 'paragraph-start) "\\)\\|[ \t]*\\\\$") + "\f\\|[ \t]*\\\\?$" + "Value of paragraph-start used when scanning strings. +It treats escaped EOLs as whitespace.") + +(defvar c-string-par-separate + ;; (concat "\\(" (default-value 'paragraph-separate) "\\)\\|[ \t]*\\\\$") + "[ \t\f]*\\\\?$" + "Value of paragraph-separate used when scanning strings. +It treats escaped EOLs as whitespace.") + +(defvar c-sentence-end-with-esc-eol + (concat "\\(\\(" (c-default-value-sentence-end) "\\)" + ;; N.B.: "$" would be illegal when not enclosed like "\\($\\)". + "\\|" "[.?!][]\"')}]* ?\\\\\\($\\)[ \t\n]*" + "\\)") + "Value used like sentence-end used when scanning strings. +It treats escaped EOLs as whitespace.") + (cc-provide 'cc-vars)
--- a/lisp/progmodes/cwarn.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/progmodes/cwarn.el Sat Dec 10 21:18:28 2005 +0000 @@ -372,8 +372,8 @@ (if (cwarn-is-enabled major-mode) (turn-on-cwarn-mode))) ;;;###autoload -(easy-mmode-define-global-mode global-cwarn-mode cwarn-mode - turn-on-cwarn-mode-if-enabled) +(define-global-minor-mode global-cwarn-mode + cwarn-mode turn-on-cwarn-mode-if-enabled) (provide 'cwarn)
--- a/lisp/progmodes/gdb-ui.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/progmodes/gdb-ui.el Sat Dec 10 21:18:28 2005 +0000 @@ -78,7 +78,7 @@ ;; 1) Use MI command -data-read-memory for memory window. ;; 2) Highlight changed register values (use MI commands ;; -data-list-register-values and -data-list-changed-registers instead -;; of 'info registers'. +;; of 'info registers' after release of 22.1. ;; 3) Use tree-widget.el instead of the speedbar for watch-expressions? ;; 4) Mark breakpoint locations on scroll-bar of source buffer? ;; 5) After release of 22.1, use "-var-list-children --all-values" @@ -93,6 +93,7 @@ (require 'gud) (defvar tool-bar-map) +(defvar speedbar-initial-expansion-list-name) (defvar gdb-frame-address "main" "Initialization for Assembler buffer.") (defvar gdb-previous-frame-address nil) @@ -109,7 +110,6 @@ (defvar gdb-flush-pending-output nil) (defvar gdb-location-alist nil "Alist of breakpoint numbers and full filenames.") -(defvar gdb-find-file-unhook nil) (defvar gdb-active-process nil "GUD tooltips display variable values when t, \ and #define directives otherwise.") (defvar gdb-error "Non-nil when GDB is reporting an error.") @@ -156,7 +156,44 @@ "A list of trigger functions that have run later than their output handlers.") -;; end of gdb variables +(defvar gdb-first-post-prompt nil) +(defvar gdb-version nil) +(defvar gdb-locals-font-lock-keywords nil) +(defvar gdb-source-file-list nil + "List of source files for the current executable") +(defconst gdb-error-regexp "\\^error,msg=\"\\(.+\\)\"") + +(defvar gdb-locals-font-lock-keywords-1 + '( + ;; var = (struct struct_tag) value + ( "\\(^\\(\\sw\\|[_.]\\)+\\) += +(\\(struct\\) \\(\\(\\sw\\|[_.]\\)+\\)" + (1 font-lock-variable-name-face) + (3 font-lock-keyword-face) + (4 font-lock-type-face)) + ;; var = (type) value + ( "\\(^\\(\\sw\\|[_.]\\)+\\) += +(\\(\\(\\sw\\|[_.]\\)+\\)" + (1 font-lock-variable-name-face) + (3 font-lock-type-face)) + ;; var = val + ( "\\(^\\(\\sw\\|[_.]\\)+\\) += +[^(]" + (1 font-lock-variable-name-face)) + ) + "Font lock keywords used in `gdb-local-mode'.") + +(defvar gdb-locals-font-lock-keywords-2 + '( + ;; var = type value + ( "\\(^\\(\\sw\\|[_.]\\)+\\)\t+\\(\\(\\sw\\|[_.]\\)+\\)" + (1 font-lock-variable-name-face) + (3 font-lock-type-face)) + ) + "Font lock keywords used in `gdb-local-mode'.") + +;; Variables for GDB 6.4+ + +(defvar gdb-register-names nil "List of register names.") +(defvar gdb-changed-registers nil + "List of changed register numbers (strings).") ;;;###autoload (defun gdba (command-line) @@ -213,7 +250,7 @@ ;; ;; Let's start with a basic gud-gdb buffer and then modify it a bit. (gdb command-line) - (gdb-ann3)) + (gdb-init-1)) (defvar gdb-debug-log nil) @@ -263,6 +300,8 @@ (if (null arg) (not gdb-use-inferior-io-buffer) (> (prefix-numeric-value arg) 0))) + (message (format "Separate inferior IO %sabled" + (if gdb-use-inferior-io-buffer "en" "dis"))) (if (and gud-comint-buffer (buffer-name gud-comint-buffer)) (condition-case nil @@ -311,39 +350,25 @@ (list (concat gdb-server-prefix "print " expr "\n") 'gdb-tooltip-print)))))) -(defun gdb-set-gud-minor-mode (buffer) - "Set `gud-minor-mode' from find-file if appropriate." - (goto-char (point-min)) - (unless (search-forward "No source file named " nil t) - (condition-case nil - (gdb-enqueue-input - (list (concat gdb-server-prefix "info source\n") - `(lambda () (gdb-set-gud-minor-mode-1 ,buffer)))) - (error (setq gdb-find-file-unhook t))))) - -(defun gdb-set-gud-minor-mode-1 (buffer) - (goto-char (point-min)) - (when (and (search-forward "Located in " nil t) - (looking-at "\\S-+") - (string-equal (buffer-file-name buffer) - (match-string 0))) - (with-current-buffer buffer - (set (make-local-variable 'gud-minor-mode) 'gdba) - (set (make-local-variable 'tool-bar-map) gud-tool-bar-map) - (when gud-tooltip-mode - (make-local-variable 'gdb-define-alist) - (gdb-create-define-alist) - (add-hook 'after-save-hook 'gdb-create-define-alist nil t))))) +(defconst gdb-source-file-regexp "\\(.+?\\), \\|\\([^, \n].*$\\)") (defun gdb-set-gud-minor-mode-existing-buffers () - (dolist (buffer (buffer-list)) - (let ((file (buffer-file-name buffer))) - (if file - (progn - (gdb-enqueue-input - (list (concat gdb-server-prefix "list " - (file-name-nondirectory file) ":1\n") - `(lambda () (gdb-set-gud-minor-mode ,buffer))))))))) + "Create list of source files for current GDB session." + (goto-char (point-min)) + (when (search-forward "read in on demand:" nil t) + (while (re-search-forward gdb-source-file-regexp nil t) + (push (or (match-string 1) (match-string 2)) gdb-source-file-list)) + (dolist (buffer (buffer-list)) + (with-current-buffer buffer + (when (and buffer-file-name + (member (file-name-nondirectory buffer-file-name) + gdb-source-file-list)) + (set (make-local-variable 'gud-minor-mode) 'gdba) + (set (make-local-variable 'tool-bar-map) gud-tool-bar-map) + (when gud-tooltip-mode + (make-local-variable 'gdb-define-alist) + (gdb-create-define-alist) + (add-hook 'after-save-hook 'gdb-create-define-alist nil t))))))) (defun gdb-find-watch-expression () (let* ((var (nth (- (line-number-at-pos (point)) 2) gdb-var-list)) @@ -354,7 +379,7 @@ (setq expr (concat (car var1) "." (match-string 2 varno))))) expr)) -(defun gdb-ann3 () +(defun gdb-init-1 () (setq gdb-debug-log nil) (set (make-local-variable 'gud-minor-mode) 'gdba) (set (make-local-variable 'gud-marker-filter) 'gud-gdba-marker-filter) @@ -376,11 +401,11 @@ "\C-d" "Remove breakpoint at current line or address.") ;; (gud-def gud-until (if (not (string-match "Machine" mode-name)) - (gud-call "until %f:%l" arg) - (save-excursion - (beginning-of-line) - (forward-char 2) - (gud-call "until *%a" arg))) + (gud-call "until %f:%l" arg) + (save-excursion + (beginning-of-line) + (forward-char 2) + (gud-call "until *%a" arg))) "\C-u" "Continue to current line or address.") ;; (gud-def gud-go (gud-call (if gdb-active-process "continue" "run") arg) @@ -411,7 +436,7 @@ 'gdb-mouse-toggle-breakpoint-fringe) (setq comint-input-sender 'gdb-send) - ;; + ;; (re-)initialize (setq gdb-frame-address (if gdb-show-main "main" nil)) (setq gdb-previous-frame-address nil @@ -422,7 +447,7 @@ gdb-frame-number nil gdb-var-list nil gdb-var-changed nil - gdb-first-prompt nil + gdb-first-post-prompt t gdb-prompting nil gdb-input-queue nil gdb-current-item nil @@ -431,27 +456,55 @@ gdb-server-prefix "server " gdb-flush-pending-output nil gdb-location-alist nil - gdb-find-file-unhook nil + gdb-source-file-list nil gdb-error nil gdb-macro-info nil gdb-buffer-fringe-width (car (window-fringes))) - ;; + (setq gdb-buffer-type 'gdba) - ;; + (if gdb-use-inferior-io-buffer (gdb-clear-inferior-io)) - ;; + + ;; Hack to see test for GDB 6.4+ (-stack-info-frame was implemented in 6.4) + (setq gdb-version nil) + (gdb-enqueue-input (list "server interpreter mi -stack-info-frame\n" + 'gdb-get-version))) + +(defun gdb-init-2 () (if (eq window-system 'w32) (gdb-enqueue-input (list "set new-console off\n" 'ignore))) (gdb-enqueue-input (list "set height 0\n" 'ignore)) (gdb-enqueue-input (list "set width 0\n" 'ignore)) + + (if (string-equal gdb-version "pre-6.4") + (progn + (gdb-enqueue-input (list (concat gdb-server-prefix "info sources\n") + 'gdb-set-gud-minor-mode-existing-buffers)) + (setq gdb-locals-font-lock-keywords gdb-locals-font-lock-keywords-1)) + (gdb-enqueue-input + (list "server interpreter mi -data-list-register-names\n" + 'gdb-get-register-names)) + ; Needs GDB 6.2 onwards. + (gdb-enqueue-input + (list "server interpreter mi \"-file-list-exec-source-files\"\n" + 'gdb-set-gud-minor-mode-existing-buffers-1)) + (setq gdb-locals-font-lock-keywords gdb-locals-font-lock-keywords-2)) + ;; find source file and compilation directory here (gdb-enqueue-input (list "server list main\n" 'ignore)) ; C program (gdb-enqueue-input (list "server list MAIN__\n" 'ignore)) ; Fortran program (gdb-enqueue-input (list "server info source\n" 'gdb-source-info)) - ;; - (gdb-set-gud-minor-mode-existing-buffers) + (run-hooks 'gdba-mode-hook)) +(defun gdb-get-version () + (goto-char (point-min)) + (if (and (re-search-forward gdb-error-regexp nil t) + (string-match ".*(missing implementation)" (match-string 1))) + (setq gdb-version "pre-6.4") + (setq gdb-version "6.4+")) + (gdb-init-2)) + (defun gdb-mouse-until (event) "Execute source lines by dragging the overlay arrow (fringe) with the mouse." (interactive "e") @@ -492,7 +545,9 @@ (setq gdb-speedbar-auto-raise (if (null arg) (not gdb-speedbar-auto-raise) - (> (prefix-numeric-value arg) 0)))) + (> (prefix-numeric-value arg) 0))) + (message (format "Auto raising %sabled" + (if gdb-speedbar-auto-raise "en" "dis")))) (defcustom gdb-use-colon-colon-notation nil "If non-nil use FUN::VAR format to display variables in the speedbar." @@ -500,9 +555,10 @@ :group 'gud :version "22.1") -(defun gud-watch () +(defun gud-watch (&optional event) "Watch expression at point." - (interactive) + (interactive (list last-input-event)) + (if event (posn-set-point (event-end event))) (require 'tooltip) (save-selected-window (let ((expr (tooltip-identifier-from-point (point)))) @@ -524,47 +580,45 @@ "name=\"\\(.*?\\)\",numchild=\"\\(.*?\\)\",type=\"\\(.*?\\)\"") (defun gdb-var-create-handler (expr) - (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer) - (goto-char (point-min)) - (if (re-search-forward gdb-var-create-regexp nil t) - (let ((var (list expr - (match-string 1) - (match-string 2) - (match-string 3) - nil nil))) - (push var gdb-var-list) - (speedbar 1) - (unless (string-equal - speedbar-initial-expansion-list-name "GUD") - (speedbar-change-initial-expansion-list "GUD")) - (gdb-enqueue-input - (list - (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) - 'gdba) - (concat "server interpreter mi \"-var-evaluate-expression " - (nth 1 var) "\"\n") - (concat "-var-evaluate-expression " (nth 1 var) "\n")) - `(lambda () (gdb-var-evaluate-expression-handler - ,(nth 1 var) nil)))) - (setq gdb-var-changed t)) - (if (re-search-forward "Undefined command" nil t) - (message-box "Watching expressions requires gdb 6.0 onwards") - (message "No symbol \"%s\" in current context." expr))))) + (goto-char (point-min)) + (if (re-search-forward gdb-var-create-regexp nil t) + (let ((var (list expr + (match-string 1) + (match-string 2) + (match-string 3) + nil nil))) + (push var gdb-var-list) + (speedbar 1) + (unless (string-equal + speedbar-initial-expansion-list-name "GUD") + (speedbar-change-initial-expansion-list "GUD")) + (gdb-enqueue-input + (list + (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) + 'gdba) + (concat "server interpreter mi \"-var-evaluate-expression " + (nth 1 var) "\"\n") + (concat "-var-evaluate-expression " (nth 1 var) "\n")) + `(lambda () (gdb-var-evaluate-expression-handler + ,(nth 1 var) nil)))) + (setq gdb-var-changed t)) + (if (search-forward "Undefined command" nil t) + (message-box "Watching expressions requires gdb 6.0 onwards") + (message "No symbol \"%s\" in current context." expr)))) (defun gdb-var-evaluate-expression-handler (varnum changed) - (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer) - (goto-char (point-min)) - (re-search-forward ".*value=\\(\".*\"\\)" nil t) - (catch 'var-found - (let ((num 0)) - (dolist (var gdb-var-list) - (if (string-equal varnum (cadr var)) - (progn - (if changed (setcar (nthcdr 5 var) t)) - (setcar (nthcdr 4 var) (read (match-string 1))) - (setcar (nthcdr num gdb-var-list) var) - (throw 'var-found nil))) - (setq num (+ num 1)))))) + (goto-char (point-min)) + (re-search-forward ".*value=\\(\".*\"\\)" nil t) + (catch 'var-found + (let ((num 0)) + (dolist (var gdb-var-list) + (if (string-equal varnum (cadr var)) + (progn + (if changed (setcar (nthcdr 5 var) t)) + (setcar (nthcdr 4 var) (read (match-string 1))) + (setcar (nthcdr num gdb-var-list) var) + (throw 'var-found nil))) + (setq num (+ num 1))))) (setq gdb-var-changed t)) (defun gdb-var-list-children (varnum) @@ -577,33 +631,32 @@ type=\"\\(.*?\\)\"") (defun gdb-var-list-children-handler (varnum) - (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer) - (goto-char (point-min)) - (let ((var-list nil)) - (catch 'child-already-watched - (dolist (var gdb-var-list) - (if (string-equal varnum (cadr var)) - (progn - (push var var-list) - (while (re-search-forward gdb-var-list-children-regexp nil t) - (let ((varchild (list (match-string 2) - (match-string 1) - (match-string 3) - (match-string 4) - nil nil))) - (dolist (var1 gdb-var-list) - (if (string-equal (cadr var1) (cadr varchild)) - (throw 'child-already-watched nil))) - (push varchild var-list) - (gdb-enqueue-input - (list - (concat - "server interpreter mi \"-var-evaluate-expression " - (nth 1 varchild) "\"\n") - `(lambda () (gdb-var-evaluate-expression-handler - ,(nth 1 varchild) nil))))))) - (push var var-list))) - (setq gdb-var-list (nreverse var-list)))))) + (goto-char (point-min)) + (let ((var-list nil)) + (catch 'child-already-watched + (dolist (var gdb-var-list) + (if (string-equal varnum (cadr var)) + (progn + (push var var-list) + (while (re-search-forward gdb-var-list-children-regexp nil t) + (let ((varchild (list (match-string 2) + (match-string 1) + (match-string 3) + (match-string 4) + nil nil))) + (dolist (var1 gdb-var-list) + (if (string-equal (cadr var1) (cadr varchild)) + (throw 'child-already-watched nil))) + (push varchild var-list) + (gdb-enqueue-input + (list + (concat + "server interpreter mi \"-var-evaluate-expression " + (nth 1 varchild) "\"\n") + `(lambda () (gdb-var-evaluate-expression-handler + ,(nth 1 varchild) nil))))))) + (push var var-list))) + (setq gdb-var-list (nreverse var-list))))) (defun gdb-var-update () (when (not (member 'gdb-var-update gdb-pending-triggers)) @@ -615,20 +668,19 @@ (defconst gdb-var-update-regexp "name=\"\\(.*?\\)\"") (defun gdb-var-update-handler () - (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer) - (goto-char (point-min)) - (while (re-search-forward gdb-var-update-regexp nil t) - (catch 'var-found-1 - (let ((varnum (match-string 1))) - (dolist (var gdb-var-list) - (gdb-enqueue-input - (list - (concat "server interpreter mi \"-var-evaluate-expression " - varnum "\"\n") - `(lambda () (gdb-var-evaluate-expression-handler ,varnum t)))) - (throw 'var-found-1 nil)))))) + (goto-char (point-min)) + (while (re-search-forward gdb-var-update-regexp nil t) + (catch 'var-found-1 + (let ((varnum (match-string 1))) + (dolist (var gdb-var-list) + (gdb-enqueue-input + (list + (concat "server interpreter mi \"-var-evaluate-expression " + varnum "\"\n") + `(lambda () (gdb-var-evaluate-expression-handler ,varnum t)))) + (throw 'var-found-1 nil))))) (setq gdb-pending-triggers - (delq 'gdb-var-update gdb-pending-triggers)) + (delq 'gdb-var-update gdb-pending-triggers)) (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame)) ;; Dummy command to update speedbar at right time. (gdb-enqueue-input (list "server pwd\n" 'gdb-speedbar-timer-fn)) @@ -692,7 +744,9 @@ INDENT is the current indentation depth." (cond ((string-match "+" text) ;expand this node (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba) - (gdb-var-list-children token) + (if (string-equal gdb-version "pre-6.4") + (gdb-var-list-children token) + (gdb-var-list-children-1 token)) (progn (gdbmi-var-update) (gdbmi-var-list-children token)))) @@ -781,7 +835,6 @@ ;; GUD buffers are an exception to the rules (gdb-set-buffer-rules 'gdba 'error) -;; ;; Partial-output buffer : This accumulates output from a command executed on ;; behalf of emacs (rather than the user). ;; @@ -877,7 +930,6 @@ (get-buffer-process gud-comint-buffer))) -;; ;; gdb communications ;; @@ -1031,7 +1083,9 @@ (defun gdb-prompt (ignored) "An annotation handler for `prompt'. This sends the next command (if any) to gdb." - (when gdb-first-prompt (gdb-ann3)) + (when gdb-first-prompt + (gdb-init-1) + (setq gdb-first-prompt nil)) (let ((sink gdb-output-sink)) (cond ((eq sink 'user) t) @@ -1128,16 +1182,25 @@ "An annotation handler for `post-prompt'. This begins the collection of output from the current command if that happens to be appropriate." - (unless gdb-pending-triggers + ;; Don't add to queue if there outstanding items or GDB is not known yet. + (unless (or gdb-pending-triggers gdb-first-post-prompt) (gdb-get-selected-frame) (gdb-invalidate-frames) (gdb-invalidate-breakpoints) ;; Do this through gdb-get-selected-frame -> gdb-frame-handler ;; so gdb-frame-address is updated. ;; (gdb-invalidate-assembler) - (gdb-invalidate-registers) + + (if (string-equal gdb-version "pre-6.4") + (gdb-invalidate-registers) + (gdb-get-changed-registers) + (gdb-invalidate-registers-1)) + (gdb-invalidate-memory) - (gdb-invalidate-locals) + (if (string-equal gdb-version "pre-6.4") + (gdb-invalidate-locals) + (gdb-invalidate-locals-1)) + (gdb-invalidate-threads) (unless (eq system-type 'darwin) ;Breaks on Darwin's GDB-5.3. ;; FIXME: with GDB-6 on Darwin, this might very well work. @@ -1146,7 +1209,10 @@ (setq gdb-var-changed t) ; force update (dolist (var gdb-var-list) (setcar (nthcdr 5 var) nil)) - (gdb-var-update)))) + (if (string-equal gdb-version "pre-6.4") + (gdb-var-update) + (gdb-var-update-1))))) + (setq gdb-first-post-prompt nil) (let ((sink gdb-output-sink)) (cond ((eq sink 'user) t) @@ -1736,7 +1802,6 @@ (setq mode-name "Frames") (setq buffer-read-only t) (use-local-map gdb-frames-mode-map) - (font-lock-mode -1) (run-mode-hooks 'gdb-frames-mode-hook) (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba) 'gdb-invalidate-frames @@ -1899,7 +1964,7 @@ (suppress-keymap map) (define-key map "\r" 'gdb-edit-register-value) (define-key map [mouse-2] 'gdb-edit-register-value) - (define-key map " " 'toggle-gdb-all-registers) + (define-key map " " 'gdb-all-registers) (define-key map "q" 'kill-this-buffer) map)) @@ -1909,13 +1974,15 @@ \\{gdb-registers-mode-map}" (kill-all-local-variables) (setq major-mode 'gdb-registers-mode) - (setq mode-name "Registers:") + (setq mode-name "Registers") (setq buffer-read-only t) (use-local-map gdb-registers-mode-map) (run-mode-hooks 'gdb-registers-mode-hook) - (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba) - 'gdb-invalidate-registers - 'gdbmi-invalidate-registers)) + (if (string-equal gdb-version "pre-6.4") + (progn + (if gdb-all-registers (setq mode-name "Registers:All")) + 'gdb-invalidate-registers) + 'gdb-invalidate-registers-1)) (defun gdb-registers-buffer-name () (with-current-buffer gud-comint-buffer @@ -1934,18 +2001,21 @@ (special-display-frame-alist gdb-frame-parameters)) (display-buffer (gdb-get-create-buffer 'gdb-registers-buffer)))) -(defun toggle-gdb-all-registers () - "Toggle the display of floating-point registers." +(defun gdb-all-registers () + "Toggle the display of floating-point registers (pre GDB 6.4 only)." (interactive) - (if gdb-all-registers - (progn - (setq gdb-all-registers nil) - (with-current-buffer (gdb-get-buffer 'gdb-registers-buffer) - (setq mode-name "Registers:"))) - (setq gdb-all-registers t) - (with-current-buffer (gdb-get-buffer 'gdb-registers-buffer) - (setq mode-name "Registers:All"))) - (gdb-invalidate-registers)) + (when (string-equal gdb-version "pre-6.4") + (if gdb-all-registers + (progn + (setq gdb-all-registers nil) + (with-current-buffer (gdb-get-create-buffer 'gdb-registers-buffer) + (setq mode-name "Registers"))) + (setq gdb-all-registers t) + (with-current-buffer (gdb-get-create-buffer 'gdb-registers-buffer) + (setq mode-name "Registers:All"))) + (message (format "Display of floating-point registers %sabled" + (if gdb-all-registers "en" "dis"))) + (gdb-invalidate-registers))) ;; Memory buffer. @@ -2049,7 +2119,7 @@ (customize-set-variable 'gdb-memory-format "x") (gdb-invalidate-memory)) -(defvar gdb-memory-format-keymap +(defvar gdb-memory-format-map (let ((map (make-sparse-keymap))) (define-key map [header-line down-mouse-3] 'gdb-memory-format-menu-1) map) @@ -2111,7 +2181,7 @@ (customize-set-variable 'gdb-memory-unit "b") (gdb-invalidate-memory)) -(defvar gdb-memory-unit-keymap +(defvar gdb-memory-unit-map (let ((map (make-sparse-keymap))) (define-key map [header-line down-mouse-3] 'gdb-memory-unit-menu-1) map) @@ -2226,13 +2296,13 @@ 'face font-lock-warning-face 'help-echo "mouse-3: Select display format" 'mouse-face 'mode-line-highlight - 'local-map gdb-memory-format-keymap) + 'local-map gdb-memory-format-map) " Unit Size: " (propertize gdb-memory-unit 'face font-lock-warning-face 'help-echo "mouse-3: Select unit size" 'mouse-face 'mode-line-highlight - 'local-map gdb-memory-unit-keymap)))) + 'local-map gdb-memory-unit-map)))) (set (make-local-variable 'font-lock-defaults) '(gdb-memory-font-lock-keywords)) (run-mode-hooks 'gdb-memory-mode-hook) @@ -2267,7 +2337,7 @@ "server info locals\n" gdb-info-locals-handler) -(defvar gdb-locals-watch-keymap +(defvar gdb-locals-watch-map (let ((map (make-sparse-keymap))) (define-key map "\r" '(lambda () (interactive) (beginning-of-line) @@ -2283,13 +2353,13 @@ (concat (propertize "[struct/union]" 'mouse-face 'highlight 'help-echo "mouse-2: create watch expression" - 'local-map gdb-locals-watch-keymap) "\n")) + 'local-map gdb-locals-watch-map) "\n")) (defconst gdb-array-string (concat " " (propertize "[array]" 'mouse-face 'highlight 'help-echo "mouse-2: create watch expression" - 'local-map gdb-locals-watch-keymap) "\n")) + 'local-map gdb-locals-watch-map) "\n")) ;; Abbreviate for arrays and structures. ;; These can be expanded using gud-display. @@ -2325,23 +2395,6 @@ (define-key map "q" 'kill-this-buffer) map)) -(defvar gdb-locals-font-lock-keywords - '( - ;; var = (struct struct_tag) value - ( "\\(^\\(\\sw\\|[_.]\\)+\\) += +(\\(struct\\) \\(\\(\\sw\\|[_.]\\)+\\)" - (1 font-lock-variable-name-face) - (3 font-lock-keyword-face) - (4 font-lock-type-face)) - ;; var = (type) value - ( "\\(^\\(\\sw\\|[_.]\\)+\\) += +(\\(\\(\\sw\\|[_.]\\)+\\)" - (1 font-lock-variable-name-face) - (3 font-lock-type-face)) - ;; var = val - ( "\\(^\\(\\sw\\|[_.]\\)+\\) += +[^(]" - (1 font-lock-variable-name-face)) - ) - "Font lock keywords used in `gdb-local-mode'.") - (defun gdb-locals-mode () "Major mode for gdb locals. @@ -2355,7 +2408,9 @@ '(gdb-locals-font-lock-keywords)) (run-mode-hooks 'gdb-locals-mode-hook) (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba) - 'gdb-invalidate-locals + (if (string-equal gdb-version "pre-6.4") + 'gdb-invalidate-locals + 'gdb-invalidate-locals-1) 'gdbmi-invalidate-locals)) (defun gdb-locals-buffer-name () @@ -2613,21 +2668,17 @@ (add-hook 'find-file-hook 'gdb-find-file-hook) (defun gdb-find-file-hook () -"Set up buffer for debugging if file is part of the source code + "Set up buffer for debugging if file is part of the source code of the current session." - (if (and (not gdb-find-file-unhook) + (if (and (buffer-name gud-comint-buffer) ;; in case gud or gdb-ui is just loaded gud-comint-buffer - (buffer-name gud-comint-buffer) (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba)) - (condition-case nil - (gdb-enqueue-input - (list (concat gdb-server-prefix "list " - (file-name-nondirectory buffer-file-name) - ":1\n") - `(lambda () (gdb-set-gud-minor-mode ,(current-buffer))))) - (error (setq gdb-find-file-unhook t))))) + (if (member buffer-file-name gdb-source-file-list) + (with-current-buffer (find-buffer-visiting buffer-file-name) + (set (make-local-variable 'gud-minor-mode) 'gdba) + (set (make-local-variable 'tool-bar-map) gud-tool-bar-map))))) ;;from put-image (defun gdb-put-string (putstring pos &optional dprop &rest sprops) @@ -2758,7 +2809,7 @@ (progn (goto-char (point-min)) (if (and gdb-frame-address - (re-search-forward gdb-frame-address nil t)) + (search-forward gdb-frame-address nil t)) (progn (setq pos (point)) (beginning-of-line) @@ -2782,7 +2833,7 @@ (with-current-buffer buffer (save-excursion (goto-char (point-min)) - (if (re-search-forward address nil t) + (if (search-forward address nil t) (gdb-put-breakpoint-icon (eq flag ?y) bptno)))))))) (if (not (equal gdb-frame-address "main")) (with-current-buffer buffer @@ -2886,26 +2937,268 @@ (defun gdb-frame-handler () (setq gdb-pending-triggers (delq 'gdb-get-selected-frame gdb-pending-triggers)) - (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer) - (goto-char (point-min)) - (if (re-search-forward "Stack level \\([0-9]+\\)" nil t) - (setq gdb-frame-number (match-string 1))) + (goto-char (point-min)) + (if (re-search-forward "Stack level \\([0-9]+\\)" nil t) + (setq gdb-frame-number (match-string 1))) + (goto-char (point-min)) + (if (re-search-forward + ".*=\\s-+0x0*\\(\\S-*\\)\\s-+in\\s-+\\(\\S-*?\\);? " nil t) + (progn + (setq gdb-selected-frame (match-string 2)) + (if (gdb-get-buffer 'gdb-locals-buffer) + (with-current-buffer (gdb-get-buffer 'gdb-locals-buffer) + (setq mode-name (concat "Locals:" gdb-selected-frame)))) + (if (gdb-get-buffer 'gdb-assembler-buffer) + (with-current-buffer (gdb-get-buffer 'gdb-assembler-buffer) + (setq mode-name (concat "Machine:" gdb-selected-frame)))) + (setq gdb-frame-address (match-string 1)))) + (goto-char (point-min)) + (if (re-search-forward " source language \\(\\S-*\\)\." nil t) + (setq gdb-current-language (match-string 1))) + (gdb-invalidate-assembler)) + + +;; Code specific to GDB 6.4 +(defconst gdb-source-file-regexp-1 "fullname=\"\\(.*?\\)\"") + +(defun gdb-set-gud-minor-mode-existing-buffers-1 () + "Create list of source files for current GDB session." + (goto-char (point-min)) + (while (re-search-forward gdb-source-file-regexp-1 nil t) + (push (match-string 1) gdb-source-file-list)) + (dolist (buffer (buffer-list)) + (with-current-buffer buffer + (when (member buffer-file-name gdb-source-file-list) + (set (make-local-variable 'gud-minor-mode) 'gdba) + (set (make-local-variable 'tool-bar-map) gud-tool-bar-map) + (when gud-tooltip-mode + (make-local-variable 'gdb-define-alist) + (gdb-create-define-alist) + (add-hook 'after-save-hook 'gdb-create-define-alist nil t)))))) + +; Uses "-var-list-children --all-values". Needs GDB 6.1 onwards. +(defun gdb-var-list-children-1 (varnum) + (gdb-enqueue-input + (list (concat "server interpreter mi \"-var-update " varnum "\"\n") + 'ignore)) + (gdb-enqueue-input + (list (concat "server interpreter mi \"-var-list-children --all-values " + varnum "\"\n") + `(lambda () (gdb-var-list-children-handler-1 ,varnum))))) + +(defconst gdb-var-list-children-regexp-1 + "name=\"\\(.+?\\)\",exp=\"\\(.+?\\)\",numchild=\"\\(.+?\\)\",\ +value=\\(\".*?\"\\),type=\"\\(.+?\\)\"}") + +(defun gdb-var-list-children-handler-1 (varnum) + (goto-char (point-min)) + (let ((var-list nil)) + (catch 'child-already-watched + (dolist (var gdb-var-list) + (if (string-equal varnum (cadr var)) + (progn + (push var var-list) + (while (re-search-forward gdb-var-list-children-regexp-1 nil t) + (let ((varchild (list (match-string 2) + (match-string 1) + (match-string 3) + (match-string 5) + (read (match-string 4)) + nil))) + (dolist (var1 gdb-var-list) + (if (string-equal (cadr var1) (cadr varchild)) + (throw 'child-already-watched nil))) + (push varchild var-list)))) + (push var var-list))) + (setq gdb-var-changed t) + (setq gdb-var-list (nreverse var-list))))) + +; Uses "-var-update --all-values". Needs GDB 6.4 onwards. +(defun gdb-var-update-1 () + (if (not (member 'gdb-var-update gdb-pending-triggers)) + (progn + (gdb-enqueue-input + (list + (if (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdba)) + "server interpreter mi \"-var-update --all-values *\"\n" + "-var-update --all-values *\n") + 'gdb-var-update-handler-1)) + (push 'gdb-var-update gdb-pending-triggers)))) + +(defconst gdb-var-update-regexp-1 "name=\"\\(.*?\\)\",value=\\(\".*?\"\\),") + +(defun gdb-var-update-handler-1 () + (goto-char (point-min)) + (while (re-search-forward gdb-var-update-regexp-1 nil t) + (let ((varnum (match-string 1))) + (catch 'var-found1 + (let ((num 0)) + (dolist (var gdb-var-list) + (if (string-equal varnum (cadr var)) + (progn + (setcar (nthcdr 5 var) t) + (setcar (nthcdr 4 var) (read (match-string 2))) + (setcar (nthcdr num gdb-var-list) var) + (throw 'var-found1 nil))) + (setq num (+ num 1)))))) + (setq gdb-var-changed t)) + (setq gdb-pending-triggers + (delq 'gdb-var-update gdb-pending-triggers)) + (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame)) + ;; dummy command to update speedbar at right time + (gdb-enqueue-input (list "server pwd\n" 'gdb-speedbar-timer-fn)) + ;; keep gdb-pending-triggers non-nil till end + (push 'gdb-speedbar-timer gdb-pending-triggers))) + +;; Registers buffer. +;; +(gdb-set-buffer-rules 'gdb-registers-buffer + 'gdb-registers-buffer-name + 'gdb-registers-mode) + +(def-gdb-auto-update-trigger gdb-invalidate-registers-1 + (gdb-get-buffer 'gdb-registers-buffer) + (if (eq gud-minor-mode 'gdba) + "server interpreter mi \"-data-list-register-values x\"\n" + "-data-list-register-values x\n") + gdb-data-list-register-values-handler) + +(defconst gdb-data-list-register-values-regexp + "number=\"\\(.*?\\)\",value=\"\\(.*?\\)\"") + +(defun gdb-data-list-register-values-handler () + (setq gdb-pending-triggers (delq 'gdb-invalidate-registers-1 + gdb-pending-triggers)) + (goto-char (point-min)) + (if (re-search-forward gdb-error-regexp nil t) + (with-current-buffer (gdb-get-buffer 'gdb-registers-buffer) + (let ((buffer-read-only nil)) + (erase-buffer) + (insert (match-string 1)) + (goto-char (point-min)))) + (let ((register-list (reverse gdb-register-names)) + (register nil) (register-string nil) (register-values nil)) + (goto-char (point-min)) + (while (re-search-forward gdb-data-list-register-values-regexp nil t) + (setq register (pop register-list)) + (setq register-string (concat register "\t" (match-string 2) "\n")) + (if (member (match-string 1) gdb-changed-registers) + (put-text-property 0 (length register-string) + 'face 'font-lock-warning-face + register-string)) + (setq register-values + (concat register-values register-string))) + (let ((buf (gdb-get-buffer 'gdb-registers-buffer))) + (with-current-buffer buf + (let ((p (window-point (get-buffer-window buf 0))) + (buffer-read-only nil)) + (erase-buffer) + (insert register-values) + (set-window-point (get-buffer-window buf 0) p)))))) + (gdb-data-list-register-values-custom)) + +(defun gdb-data-list-register-values-custom () + (with-current-buffer (gdb-get-buffer 'gdb-registers-buffer) + (save-excursion + (let ((buffer-read-only nil) + start end) + (goto-char (point-min)) + (while (< (point) (point-max)) + (setq start (line-beginning-position)) + (setq end (line-end-position)) + (when (looking-at "^[^\t]+") + (unless (string-equal (match-string 0) "No registers.") + (put-text-property start (match-end 0) + 'face font-lock-variable-name-face) + (add-text-properties start end + '(help-echo "mouse-2: edit value" + mouse-face highlight)))) + (forward-line 1)))))) + +;; Needs GDB 6.4 onwards (used to fail with no stack). +(defun gdb-get-changed-registers () + (if (not (member 'gdb-get-changed-registers gdb-pending-triggers)) + (progn + (gdb-enqueue-input + (list + (if (eq gud-minor-mode 'gdba) + "server interpreter mi -data-list-changed-registers\n" + "-data-list-changed-registers\n") + 'gdb-get-changed-registers-handler)) + (push 'gdb-get-changed-registers gdb-pending-triggers)))) + +(defconst gdb-data-list-register-names-regexp "\"\\(.*?\\)\"") + +(defun gdb-get-changed-registers-handler () + (setq gdb-pending-triggers + (delq 'gdb-get-changed-registers gdb-pending-triggers)) + (setq gdb-changed-registers nil) + (goto-char (point-min)) + (while (re-search-forward gdb-data-list-register-names-regexp nil t) + (push (match-string 1) gdb-changed-registers))) + + +;; Locals buffer. +;; +;; uses "-stack-list-locals --simple-values". Needs GDB 6.1 onwards. +(gdb-set-buffer-rules 'gdb-locals-buffer + 'gdb-locals-buffer-name + 'gdb-locals-mode) + +(def-gdb-auto-update-trigger gdb-invalidate-locals-1 + (gdb-get-buffer 'gdb-locals-buffer) + "server interpreter mi -\"stack-list-locals --simple-values\"\n" + gdb-stack-list-locals-handler) + +(defconst gdb-stack-list-locals-regexp + "name=\"\\(.*?\\)\",type=\"\\(.*?\\)\"") + +(defvar gdb-locals-watch-map-1 + (let ((map (make-sparse-keymap))) + (define-key map [mouse-2] 'gud-watch) + map) + "Keymap to create watch expression of a complex data type local variable.") + +;; Dont display values of arrays or structures. +;; These can be expanded using gud-watch. +(defun gdb-stack-list-locals-handler () + (setq gdb-pending-triggers (delq 'gdb-invalidate-locals-1 + gdb-pending-triggers)) + (let (local locals-list) (goto-char (point-min)) - (if (re-search-forward - ".*=\\s-+0x0*\\(\\S-*\\)\\s-+in\\s-+\\(\\S-*?\\);? " nil t) - (progn - (setq gdb-selected-frame (match-string 2)) - (if (gdb-get-buffer 'gdb-locals-buffer) - (with-current-buffer (gdb-get-buffer 'gdb-locals-buffer) - (setq mode-name (concat "Locals:" gdb-selected-frame)))) - (if (gdb-get-buffer 'gdb-assembler-buffer) - (with-current-buffer (gdb-get-buffer 'gdb-assembler-buffer) - (setq mode-name (concat "Machine:" gdb-selected-frame)))) - (setq gdb-frame-address (match-string 1)))) - (goto-char (point-min)) - (if (re-search-forward " source language \\(\\S-*\\)\." nil t) - (setq gdb-current-language (match-string 1)))) - (gdb-invalidate-assembler)) + (while (re-search-forward gdb-stack-list-locals-regexp nil t) + (let ((local (list (match-string 1) + (match-string 2) + nil))) + (if (looking-at ",value=\\(\".*\"\\)}") + (setcar (nthcdr 2 local) (read (match-string 1)))) + (push local locals-list))) + (let ((buf (gdb-get-buffer 'gdb-locals-buffer))) + (and buf (with-current-buffer buf + (let* ((window (get-buffer-window buf 0)) + (p (window-point window)) + (buffer-read-only nil)) + (erase-buffer) + (dolist (local locals-list) + (setq name (car local)) + (if (or (not (nth 2 local)) + (string-match "\\*$" (nth 1 local))) + (add-text-properties 0 (length name) + `(mouse-face highlight + help-echo "mouse-2: create watch expression" + local-map ,gdb-locals-watch-map-1) + name)) + (insert + (concat name "\t" (nth 1 local) + "\t" (nth 2 local) "\n"))) + (set-window-point window p))))))) + +(defun gdb-get-register-names () + "Create a list of register names." + (goto-char (point-min)) + (setq gdb-register-names nil) + (while (re-search-forward gdb-data-list-register-names-regexp nil t) + (push (match-string 1) gdb-register-names))) (provide 'gdb-ui)
--- a/lisp/progmodes/gud.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/progmodes/gud.el Sat Dec 10 21:18:28 2005 +0000 @@ -189,6 +189,9 @@ :enable (not gud-running)) ([watch] menu-item "Watch Expression" gud-watch :enable (and (not gud-running) + (memq gud-minor-mode '(gdbmi gdba)))) + ([finish] menu-item "Finish Function" gud-finish + :enable (and (not gud-running) (memq gud-minor-mode '(gdbmi gdba gdb xdb jdb pdb bashdb)))) ([stepi] menu-item "Step Instruction" gud-stepi
--- a/lisp/progmodes/idlw-shell.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/progmodes/idlw-shell.el Sat Dec 10 21:18:28 2005 +0000 @@ -4188,7 +4188,7 @@ (defvar idlwave-shell-electric-debug-read-only) (defvar idlwave-shell-electric-debug-buffers nil) -(easy-mmode-define-minor-mode idlwave-shell-electric-debug-mode +(define-minor-mode idlwave-shell-electric-debug-mode "Toggle Electric Debug mode. With no argument, this command toggles the mode. Non-null prefix argument turns on the mode. @@ -4196,9 +4196,9 @@ When Electric Debug mode is enabled, the many debugging commands are available as single key sequences." -nil -" *Debugging*" -idlwave-shell-electric-debug-mode-map) + nil + " *Debugging*" + idlwave-shell-electric-debug-mode-map) (add-hook 'idlwave-shell-electric-debug-mode-on-hook
--- a/lisp/simple.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/simple.el Sat Dec 10 21:18:28 2005 +0000 @@ -3264,7 +3264,7 @@ Invoke \\[apropos-documentation] and type \"transient\" or \"mark.*active\" at the prompt, to see the documentation of commands which are sensitive to the Transient Mark mode." - :global t :group 'editing-basics :require nil) + :global t :group 'editing-basics) (defvar widen-automatically t "Non-nil means it is ok for commands to call `widen' when they want to. @@ -4234,21 +4234,21 @@ Line numbers do not appear for very large buffers and buffers with very long lines; see variables `line-number-display-limit' and `line-number-display-limit-width'." - :init-value t :global t :group 'editing-basics :require nil) + :init-value t :global t :group 'editing-basics) (define-minor-mode column-number-mode "Toggle Column Number mode. With arg, turn Column Number mode on iff arg is positive. When Column Number mode is enabled, the column number appears in the mode line." - :global t :group 'editing-basics :require nil) + :global t :group 'editing-basics) (define-minor-mode size-indication-mode "Toggle Size Indication mode. With arg, turn Size Indication mode on iff arg is positive. When Size Indication mode is enabled, the size of the accessible part of the buffer appears in the mode line." - :global t :group 'editing-basics :require nil) + :global t :group 'editing-basics) (defgroup paren-blinking nil "Blinking matching of parens and expressions." @@ -4974,12 +4974,13 @@ (< (setq element-common-end (+ element-start common-string-length)) maxp)) - (when (and (get-char-property element-start 'mouse-face) - (get-char-property element-common-end 'mouse-face)) - (put-text-property element-start element-common-end - 'font-lock-face 'completions-common-part) - (put-text-property element-common-end (1+ element-common-end) - 'font-lock-face 'completions-first-difference))))) + (when (get-char-property element-start 'mouse-face) + (if (get-char-property (1- element-common-end) 'mouse-face) + (put-text-property element-start element-common-end + 'font-lock-face 'completions-common-part)) + (if (get-char-property element-common-end 'mouse-face) + (put-text-property element-common-end (1+ element-common-end) + 'font-lock-face 'completions-first-difference)))))) ;; Insert help string. (goto-char (point-min)) (if (display-mouse-p)
--- a/lisp/subr.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/subr.el Sat Dec 10 21:18:28 2005 +0000 @@ -1602,6 +1602,7 @@ This mechanism is transparent to ordinary use of undo; if undo is enabled in the buffer and BODY succeeds, the user can undo the change normally." + (declare (indent 0) (debug t)) (let ((handle (make-symbol "--change-group-handle--")) (success (make-symbol "--change-group-success--"))) `(let ((,handle (prepare-change-group))
--- a/lisp/textmodes/flyspell.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/textmodes/flyspell.el Sat Dec 10 21:18:28 2005 +0000 @@ -1307,50 +1307,75 @@ The list of incorrect words should be in `flyspell-external-ispell-buffer'. \(We finish by killing that buffer and setting the variable to nil.) The buffer to mark them in is `flyspell-large-region-buffer'." - - (with-current-buffer flyspell-external-ispell-buffer - (goto-char (point-min)) - ;; Loop over incorrect words. - (while (re-search-forward "\\([^\n]+\\)\n" (point-max) t) - ;; Bind WORD to the next one. - (let ((word (match-string 1)) (wordpos (point))) - ;; Here there used to be code to see if WORD is the same - ;; as the previous iteration, and count the number of consecutive - ;; identical words, and the loop below would search for that many. - ;; That code seemed to be incorrect, and on principle, should - ;; be unnecessary too. -- rms. - (if flyspell-issue-message-flag - (message "Spell Checking...%d%% [%s]" - (* 100 (/ (float (point)) (point-max))) - word)) - ;; Search the other buffer for occurrences of this word, - ;; and check them. Stop when we find one that reports "incorrect". - ;; (I don't understand the reason for that logic, - ;; but I didn't want to change it. -- rms.) - (with-current-buffer flyspell-large-region-buffer - (goto-char flyspell-large-region-beg) - (let ((keep t)) - (while keep - (if (search-forward word - flyspell-large-region-end t) - (progn - (setq flyspell-large-region-beg (point)) - (goto-char (- (point) 1)) - (setq keep - ;; Detect when WORD can't be checked properly - ;; because flyspell-get-word finds - ;; just part of it, and treat that as ok. - (if (< (length (car (flyspell-get-word nil))) - (length word)) - nil - (flyspell-word)))) - (error "Bug: misspelled word `%s' (output pos %d) not found in buffer" - word wordpos))))))) - ;; we are done - (if flyspell-issue-message-flag (message "Spell Checking completed."))) - ;; Kill and forget the buffer with the list of incorrect words. - (kill-buffer flyspell-external-ispell-buffer) - (setq flyspell-external-ispell-buffer nil)) + (let (words-not-found + (ispell-otherchars (ispell-get-otherchars))) + (with-current-buffer flyspell-external-ispell-buffer + (goto-char (point-min)) + ;; Loop over incorrect words. + (while (re-search-forward "\\([^\n]+\\)\n" (point-max) t) + ;; Bind WORD to the next one. + (let ((word (match-string 1)) (wordpos (point))) + ;; Here there used to be code to see if WORD is the same + ;; as the previous iteration, and count the number of consecutive + ;; identical words, and the loop below would search for that many. + ;; That code seemed to be incorrect, and on principle, should + ;; be unnecessary too. -- rms. + (if flyspell-issue-message-flag + (message "Spell Checking...%d%% [%s]" + (* 100 (/ (float (point)) (point-max))) + word)) + (with-current-buffer flyspell-large-region-buffer + (goto-char flyspell-large-region-beg) + (let ((keep t)) + ;; Iterate on string search until string is found as word, + ;; not as substring + (while keep + (if (search-forward word + flyspell-large-region-end t) + (progn + (goto-char (- (point) 1)) + (let* ((match-point (point)) ; flyspell-get-word might move it + (flyword-prev-l (flyspell-get-word nil)) + (flyword-prev (car flyword-prev-l)) + (size-match (= (length flyword-prev) (length word)))) + (when (or + ;; size matches, we are done + size-match + ;; Matches as part of a boundary-char separated word + (member word + (split-string flyword-prev ispell-otherchars)) + ;; ispell treats beginning of some TeX + ;; commands as nroff control sequences + ;; and strips them in the list of + ;; misspelled words thus giving a + ;; non-existent word. Skip if ispell + ;; is used, string is a TeX command + ;; (char before beginning of word is + ;; backslash) and none of the previous + ;; contitions match + (and (not ispell-really-aspell) + (save-excursion + (goto-char (- (nth 1 flyword-prev-l) 1)) + (if (looking-at "[\\]" ) + t + nil)))) + (setq keep nil) + (flyspell-word) + ;; Next search will begin from end of last match + (setq flyspell-large-region-beg match-point)))) + ;; Record if misspelling is not found and try new one + (add-to-list 'words-not-found + (concat " -> " word " - " + (int-to-string wordpos))) + (setq keep nil))))))) + ;; we are done + (if flyspell-issue-message-flag (message "Spell Checking completed."))) + ;; Warn about not found misspellings + (dolist (word words-not-found) + (message "%s: word not found" word)) + ;; Kill and forget the buffer with the list of incorrect words. + (kill-buffer flyspell-external-ispell-buffer) + (setq flyspell-external-ispell-buffer nil))) ;;*---------------------------------------------------------------------*/ ;;* flyspell-process-localwords ... */ @@ -1375,7 +1400,7 @@ (match-end 1))) ;; This can fail when string contains a word with invalid chars. ;; Error handling needs to be added between Ispell and Emacs. - (if (and (< 1 (length string)) + (if (and (< 1 (length string)) (equal 0 (string-match ispell-casechars string))) (push string localwords)))))) ;; Remove localwords matches from misspellings-buffer. @@ -1419,8 +1444,6 @@ (if ispell-local-dictionary (setq ispell-dictionary ispell-local-dictionary)) (setq args (ispell-get-ispell-args)) - (if (eq ispell-parser 'tex) - (setq args (cons "-t" args))) (if ispell-dictionary ; use specified dictionary (setq args (append (list "-d" ispell-dictionary) args)))
--- a/lisp/textmodes/org.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/textmodes/org.el Sat Dec 10 21:18:28 2005 +0000 @@ -5,7 +5,7 @@ ;; Author: Carsten Dominik <dominik at science dot uva dot nl> ;; Keywords: outlines, hypermedia, calendar ;; Homepage: http://www.astro.uva.nl/~dominik/Tools/org/ -;; Version: 3.21 +;; Version: 3.22 ;; ;; This file is part of GNU Emacs. ;; @@ -59,6 +59,7 @@ ;; (autoload 'org-mode "org" "Org mode" t) ;; (autoload 'org-diary "org" "Diary entries from Org mode") ;; (autoload 'org-agenda "org" "Multi-file agenda from Org mode" t) +;; (autoload 'org-todo-list "org" "Multi-file todo list from Org mode" t) ;; (autoload 'org-store-link "org" "Store a link to the current location" t) ;; (autoload 'orgtbl-mode "org" "Org tables as a minor mode" t) ;; (autoload 'turn-on-orgtbl "org" "Org tables as a minor mode") @@ -81,6 +82,17 @@ ;; ;; Changes: ;; ------- +;; Version 3.22 +;; - CamelCase words link to other locations in the same file. +;; - File links accept search options, to link to specific locations. +;; - Plain list items can be folded with `org-cycle'. See new option +;; `org-cycle-include-plain-lists'. +;; - Sparse trees for specific TODO keywords through numeric prefix +;; argument to `C-c C-v'. +;; - Global TODO list, also for specific keywords. +;; - Matches in sparse trees are highlighted (highlights disappear with +;; next buffer change due to editing). +;; ;; Version 3.21 ;; - Improved CSS support for the HTML export. Thanks to Christian Egli. ;; - Editing support for hand-formatted lists @@ -241,7 +253,7 @@ ;;; Customization variables -(defvar org-version "3.21" +(defvar org-version "3.22" "The version number of the file org.el.") (defun org-version () (interactive) @@ -785,6 +797,27 @@ :tag "Org Structure" :group 'org) +(defcustom org-cycle-include-plain-lists nil + "Non-nil means, include plain lists into visibility cycling. +This means that during cycling, plain list items will *temporarily* be +interpreted as outline headlines with a level given by 1000+i where i is the +indentation of the bullet. In all other operations, plain list items are +not seen as headlines. For example, you cannot assign a TODO keyword to +such an item." + :group 'org-structure + :type 'boolean) + +(defcustom org-cycle-emulate-tab t + "Where should `org-cycle' emulate TAB. +nil Never +white Only in completely white lines +t Everywhere except in headlines" + :group 'org-structure + :type '(choice (const :tag "Never" nil) + (const :tag "Only in completely white lines" white) + (const :tag "Everywhere except in headlines" t) + )) + (defcustom org-cycle-hook '(org-optimize-window-after-visibility-change) "Hook that is run after `org-cycle' has changed the buffer visibility. The function(s) in this hook must accept a single argument which indicates @@ -795,6 +828,29 @@ :group 'org-structure :type 'hook) +(defcustom org-highlight-sparse-tree-matches t + "Non-nil means, highlight all matches that define a sparse tree. +The highlights will automatically disappear the next time the buffer is +changed by an edit command." + :group 'org-structure + :type 'boolean) + +(defcustom org-show-hierarchy-above t + "Non-nil means, show full hierarchy when showing a spot in the tree. +Turning this off makes sparse trees more compact, but also less clear." + :group 'org-structure + :type 'boolean) + +(defcustom org-show-following-heading t + "Non-nil means, show heading following match in `org-occur'. +When doing an `org-occur' it is useful to show the headline which +follows the match, even if they do not match the regexp. This makes it +easier to edit directly inside the sparse tree. However, if you use +org-occur mainly as an overview, the following headlines are +unnecessary clutter." + :group 'org-structure + :type 'boolean) + (defcustom org-occur-hook '(org-first-headline-recenter) "Hook that is run after `org-occur' has constructed a sparse tree. This can be used to recenter the window to show as much of the structure @@ -818,6 +874,25 @@ :group 'org-structure :type 'boolean) +(defcustom org-plain-list-ordered-item-terminator t + "The character that makes a line with leading number an ordered list item. +Valid values are ?. and ?\). To get both terminators, use t. While +?. may look nicer, it creates the danger that a line with leading +number may be incorrectly interpreted as an item. ?\) therefore is +the safe choice." + :group 'org-structure + :type '(choice (const :tag "dot like in \"2.\"" ?.) + (const :tag "paren like in \"2)\"" ?\)) + (const :tab "both" t))) + +(defcustom org-auto-renumber-ordered-lists t + "Non-nil means, automatically renumber ordered plain lists. +Renumbering happens when the sequence have been changed with +\\[org-shiftmetaup] or \\[org-shiftmetadown]. After other editing commands, +use \\[org-ctrl-c-ctrl-c] to trigger renumbering." + :group 'org-structure + :type 'boolean) + (defcustom org-enable-fixed-width-editor t "Non-nil means, lines starting with \":\" are treated as fixed-width. This currently only means, they are never auto-wrapped. @@ -826,27 +901,6 @@ :group 'org-structure :type 'boolean) -(defcustom org-cycle-emulate-tab t - "Where should `org-cycle' emulate TAB. -nil Never -white Only in completely white lines -t Everywhere except in headlines" - :group 'org-structure - :type '(choice (const :tag "Never" nil) - (const :tag "Only in completely white lines" white) - (const :tag "Everywhere except in headlines" t) - )) - -(defcustom org-show-following-heading t - "Non-nil means, show heading following match in `org-occur'. -When doing an `org-occur' it is useful to show the headline which -follows the match, even if they do not match the regexp. This makes it -easier to edit directly inside the sparse tree. However, if you use -org-occur mainly as an overview, the following headlines are -unnecessary clutter." - :group 'org-structure - :type 'boolean) - (defcustom org-archive-location "%s_archive::" "The location where subtrees should be archived. This string consists of two parts, separated by a double-colon. @@ -896,25 +950,6 @@ :group 'org-structure :type 'boolean) -(defcustom org-plain-list-ordered-item-terminator t - "The character that makes a line with leading number an ordered list item. -Valid values are ?. and ?\). To get both terminators, use t. While -?. may look nicer, it creates the danger that a line with leading -number may be incorrectly interpreted as an item. ?\) therefore is -the safe choice." - :group 'org-structure - :type '(choice (const :tag "dot like in \"2.\"" ?.) - (const :tag "paren like in \"2)\"" ?\)) - (const :tab "both" t))) - -(defcustom org-auto-renumber-ordered-lists t - "Non-nil means, automatically renumber ordered plain lists. -Renumbering happens when the sequence have been changed with -\\[org-shiftmetaup] or \\[org-shiftmetadown]. After other editing commands, -use \\[org-ctrl-c-ctrl-c] to trigger renumbering." - :group 'org-structure - :type 'boolean) - (defgroup org-link nil "Options concerning links in Org-mode." :tag "Org Link" @@ -942,10 +977,11 @@ :group 'org-link :type 'boolean) -(defcustom org-line-numbers-in-file-links t - "Non-nil means, file links from `org-store-link' contain line numbers. -The line number will be added to the file name with :NNN and interpreted -by the command `org-open-at-point'. +(defcustom org-context-in-file-links t + "Non-nil means, file links from `org-store-link' contain context. +The line number will be added to the file name with :: as separator and +used to find the context when the link is activated by the command +`org-open-at-point'. Using a prefix arg to the command \\[org-store-link] (`org-store-link') negates this setting for the duration of the command." :group 'org-link @@ -1168,7 +1204,7 @@ (const :tag "on" t) (const :tag "on, optimized" optimized))) -;; FIXME: We could have a third option which makes it jump onle over the first +;; FIXME: We could have a third option which makes it jump only over the first ;; hline in a table. (defcustom org-table-tab-jumps-over-hlines t "Non-nil means, tab in the last column of a table with jump over a hline. @@ -1443,7 +1479,7 @@ :group 'org-export :type 'boolean) -(defcustom org-export-plain-list-max-depth 3 +(defcustom org-export-plain-list-max-depth 20 "Maximum depth of hand-formatted lists in HTML export. Org-mode parses hand-formatted enumeration and bullet lists and @@ -1626,7 +1662,6 @@ :group 'org-export :type 'boolean) -;; FIXME: not yet used. (defcustom org-icalendar-combined-name "OrgMode" "Calendar name for the combined iCalendar representing all agenda files." :group 'org-export @@ -1983,6 +2018,7 @@ (easy-menu-add org-tbl-menu) (org-install-agenda-files-menu) (setq outline-regexp "\\*+") + (setq outline-level 'org-outline-level) (if org-startup-truncated (setq truncate-lines t)) (org-set-regexps-and-options) (set (make-local-variable 'font-lock-unfontify-region-function) @@ -2088,11 +2124,28 @@ 'keymap org-mouse-map)) t))) +(defvar org-camel-regexp "\\*?\\<[A-Z]+[a-z]+[A-Z][a-zA-Z]*\\>") +(defun org-activate-camels (limit) + "Run through the buffer and add overlays to dates." + (if (re-search-forward org-camel-regexp limit t) + (progn + (add-text-properties (match-beginning 0) (match-end 0) + (list 'mouse-face 'highlight + 'keymap org-mouse-map)) + t))) + (defun org-font-lock-level () (save-excursion (org-back-to-heading t) (- (match-end 0) (match-beginning 0)))) +(defun org-outline-level () + (save-excursion + (looking-at outline-regexp) + (if (match-beginning 1) + (+ (org-get-string-indentation (match-string 1)) 1000) + (- (match-end 0) (match-beginning 0))))) + (defvar org-font-lock-keywords nil) (defun org-set-font-lock-defaults () @@ -2100,6 +2153,7 @@ (list '(org-activate-links (0 'org-link)) '(org-activate-dates (0 'org-link)) + '(org-activate-camels (0 'org-link)) (list (concat "^\\*+[ \t]*" org-not-done-regexp) '(1 'org-warning t)) (list (concat "\\[#[A-Z]\\]") '(0 'org-special-keyword t)) @@ -2199,120 +2253,125 @@ ;; special case: use global cycling (setq arg t)) - (cond - - ((org-at-table-p 'any) - ;; Enter the table or move to the next field in the table - (or (org-table-recognize-table.el) - (progn - (org-table-justify-field-maybe) - (org-table-next-field)))) - - ((eq arg t) ;; Global cycling + (let ((outline-regexp + (if org-cycle-include-plain-lists + "\\*+\\|\\([ \t]*\\)\\([-+*]\\|[0-9]+[.)]\\) " + outline-regexp))) (cond - ((and (eq last-command this-command) - (eq org-cycle-global-status 'overview)) - ;; We just created the overview - now do table of contents - ;; This can be slow in very large buffers, so indicate action - (message "CONTENTS...") - (save-excursion - ;; Visit all headings and show their offspring - (goto-char (point-max)) - (catch 'exit - (while (and (progn (condition-case nil - (outline-previous-visible-heading 1) - (error (goto-char (point-min)))) - t) - (looking-at outline-regexp)) - (show-branches) - (if (bobp) (throw 'exit nil)))) - (message "CONTENTS...done")) - (setq org-cycle-global-status 'contents) - (run-hook-with-args 'org-cycle-hook 'contents)) - - ((and (eq last-command this-command) - (eq org-cycle-global-status 'contents)) - ;; We just showed the table of contents - now show everything - (show-all) - (message "SHOW ALL") - (setq org-cycle-global-status 'all) - (run-hook-with-args 'org-cycle-hook 'all)) - - (t - ;; Default action: go to overview - (hide-sublevels 1) - (message "OVERVIEW") - (setq org-cycle-global-status 'overview) - (run-hook-with-args 'org-cycle-hook 'overview)))) - - ((integerp arg) - ;; Show-subtree, ARG levels up from here. - (save-excursion - (org-back-to-heading) - (outline-up-heading (if (< arg 0) (- arg) - (- (outline-level) arg))) - (org-show-subtree))) - - ((save-excursion (beginning-of-line 1) (looking-at outline-regexp)) - ;; At a heading: rotate between three different views - (org-back-to-heading) - (let ((goal-column 0) eoh eol eos) - ;; First, some boundaries + + ((org-at-table-p 'any) + ;; Enter the table or move to the next field in the table + (or (org-table-recognize-table.el) + (progn + (org-table-justify-field-maybe) + (org-table-next-field)))) + + ((eq arg t) ;; Global cycling + + (cond + ((and (eq last-command this-command) + (eq org-cycle-global-status 'overview)) + ;; We just created the overview - now do table of contents + ;; This can be slow in very large buffers, so indicate action + (message "CONTENTS...") + (save-excursion + ;; Visit all headings and show their offspring + (goto-char (point-max)) + (catch 'exit + (while (and (progn (condition-case nil + (outline-previous-visible-heading 1) + (error (goto-char (point-min)))) + t) + (looking-at outline-regexp)) + (show-branches) + (if (bobp) (throw 'exit nil)))) + (message "CONTENTS...done")) + (setq org-cycle-global-status 'contents) + (run-hook-with-args 'org-cycle-hook 'contents)) + + ((and (eq last-command this-command) + (eq org-cycle-global-status 'contents)) + ;; We just showed the table of contents - now show everything + (show-all) + (message "SHOW ALL") + (setq org-cycle-global-status 'all) + (run-hook-with-args 'org-cycle-hook 'all)) + + (t + ;; Default action: go to overview + (hide-sublevels 1) + (message "OVERVIEW") + (setq org-cycle-global-status 'overview) + (run-hook-with-args 'org-cycle-hook 'overview)))) + + ((integerp arg) + ;; Show-subtree, ARG levels up from here. (save-excursion (org-back-to-heading) + (outline-up-heading (if (< arg 0) (- arg) + (- (outline-level) arg))) + (org-show-subtree))) + + ((save-excursion (beginning-of-line 1) (looking-at outline-regexp)) + ;; At a heading: rotate between three different views + (org-back-to-heading) + (let ((goal-column 0) eoh eol eos) + ;; First, some boundaries (save-excursion - (beginning-of-line 2) - (while (and (not (eobp)) ;; this is like `next-line' - (get-char-property (1- (point)) 'invisible)) - (beginning-of-line 2)) (setq eol (point))) - (outline-end-of-heading) (setq eoh (point)) - (outline-end-of-subtree) (setq eos (point)) - (outline-next-heading)) - ;; Find out what to do next and set `this-command' - (cond - ((= eos eoh) - ;; Nothing is hidden behind this heading - (message "EMPTY ENTRY") - (setq org-cycle-subtree-status nil)) - ((>= eol eos) - ;; Entire subtree is hidden in one line: open it - (org-show-entry) - (show-children) - (message "CHILDREN") - (setq org-cycle-subtree-status 'children) - (run-hook-with-args 'org-cycle-hook 'children)) - ((and (eq last-command this-command) - (eq org-cycle-subtree-status 'children)) - ;; We just showed the children, now show everything. - (org-show-subtree) - (message "SUBTREE") - (setq org-cycle-subtree-status 'subtree) - (run-hook-with-args 'org-cycle-hook 'subtree)) - (t - ;; Default action: hide the subtree. - (hide-subtree) - (message "FOLDED") - (setq org-cycle-subtree-status 'folded) - (run-hook-with-args 'org-cycle-hook 'folded))))) - - ;; TAB emulation - (buffer-read-only (org-back-to-heading)) - ((if (and (eq org-cycle-emulate-tab 'white) - (save-excursion (beginning-of-line 1) (looking-at "[ \t]+$"))) - t - (eq org-cycle-emulate-tab t)) - (if (and (looking-at "[ \n\r\t]") - (string-match "^[ \t]*$" (buffer-substring - (point-at-bol) (point)))) - (progn - (beginning-of-line 1) - (and (looking-at "[ \t]+") (replace-match "")))) - (indent-relative)) - - (t (save-excursion - (org-back-to-heading) - (org-cycle))))) + (org-back-to-heading) + (save-excursion + (beginning-of-line 2) + (while (and (not (eobp)) ;; this is like `next-line' + (get-char-property (1- (point)) 'invisible)) + (beginning-of-line 2)) (setq eol (point))) + (outline-end-of-heading) (setq eoh (point)) + (outline-end-of-subtree) (setq eos (point)) + (outline-next-heading)) + ;; Find out what to do next and set `this-command' + (cond + ((= eos eoh) + ;; Nothing is hidden behind this heading + (message "EMPTY ENTRY") + (setq org-cycle-subtree-status nil)) + ((>= eol eos) + ;; Entire subtree is hidden in one line: open it + (org-show-entry) + (show-children) + (message "CHILDREN") + (setq org-cycle-subtree-status 'children) + (run-hook-with-args 'org-cycle-hook 'children)) + ((and (eq last-command this-command) + (eq org-cycle-subtree-status 'children)) + ;; We just showed the children, now show everything. + (org-show-subtree) + (message "SUBTREE") + (setq org-cycle-subtree-status 'subtree) + (run-hook-with-args 'org-cycle-hook 'subtree)) + (t + ;; Default action: hide the subtree. + (hide-subtree) + (message "FOLDED") + (setq org-cycle-subtree-status 'folded) + (run-hook-with-args 'org-cycle-hook 'folded))))) + + ;; TAB emulation + (buffer-read-only (org-back-to-heading)) + ((if (and (eq org-cycle-emulate-tab 'white) + (save-excursion (beginning-of-line 1) (looking-at "[ \t]+$"))) + t + (eq org-cycle-emulate-tab t)) + (if (and (looking-at "[ \n\r\t]") + (string-match "^[ \t]*$" (buffer-substring + (point-at-bol) (point)))) + (progn + (beginning-of-line 1) + (and (looking-at "[ \t]+") (replace-match "")))) + (indent-relative)) + + (t (save-excursion + (org-back-to-heading) + (org-cycle)))))) (defun org-optimize-window-after-visibility-change (state) "Adjust the window after a change in outline visibility. @@ -3150,6 +3209,7 @@ (if (equal (char-before (point)) ?\ ) (backward-char 1)) (skip-chars-backward "a-zA-Z0-9_:$") (point))) + (camel (equal (char-before beg) ?*)) (texp (equal (char-before beg) ?\\)) (opt (equal (buffer-substring (max (point-at-bol) (- beg 2)) beg) @@ -3157,6 +3217,7 @@ (pattern (buffer-substring-no-properties beg end)) (completion-ignore-case opt) (type nil) + (tbl nil) (table (cond (opt (setq type :opt) @@ -3171,6 +3232,14 @@ (buffer-substring (point-at-bol) beg)) (setq type :todo) (mapcar 'list org-todo-keywords)) + (camel + (setq type :camel) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward org-todo-line-regexp nil t) + (push (list (org-make-org-heading-camel (match-string 3))) + tbl))) + tbl) (t (progn (ispell-complete-word arg) (throw 'exit nil))))) (completion (try-completion pattern table))) (cond ((eq completion t) @@ -3251,6 +3320,17 @@ (completing-read "State: " (mapcar (lambda(x) (list x)) org-todo-keywords) nil t)) + ((eq arg 'right) + (if this + (if tail (car tail) nil) + (car org-todo-keywords))) + ((eq arg 'left) + (if (equal member org-todo-keywords) + nil + (if this + (nth (- (length org-todo-keywords) (length tail) 2) + org-todo-keywords) + org-done-string))) (arg ;; user requests a specific state (nth (1- (prefix-numeric-value arg)) @@ -3282,10 +3362,19 @@ (defun org-show-todo-tree (arg) "Make a compact tree which shows all headlines marked with TODO. The tree will show the lines where the regexp matches, and all higher -headlines above the match." +headlines above the match. +With \\[universal-argument] prefix, also show the DONE entries. +With a numeric prefix N, construct a sparse tree for the Nth element +of `org-todo-keywords'." (interactive "P") (let ((case-fold-search nil) - (kwd-re (if arg org-todo-regexp org-not-done-regexp))) + (kwd-re + (cond ((null arg) org-not-done-regexp) + ((equal arg '(4)) org-todo-regexp) + ((<= (prefix-numeric-value arg) (length org-todo-keywords)) + (regexp-quote (nth (1- (prefix-numeric-value arg)) + org-todo-keywords))) + (t (error "Invalid prefix argument: %s" arg))))) (message "%d TODO entries found" (org-occur (concat "^" outline-regexp " +" kwd-re ))))) @@ -3322,6 +3411,7 @@ if CALLBACK is non-nil, it is a function which is called to confirm that the match should indeed be shown." (interactive "sRegexp: ") + (org-remove-occur-highlights nil nil t) (setq regexp (org-check-occur-regexp regexp)) (let ((cnt 0)) (save-excursion @@ -3329,8 +3419,11 @@ (hide-sublevels 1) (while (re-search-forward regexp nil t) (when (or (not callback) - (funcall callback)) + (save-match-data (funcall callback))) (setq cnt (1+ cnt)) + (org-highlight-new-match (match-beginning 0) (match-end 0)) + (add-hook 'before-change-functions 'org-remove-occur-highlights + nil 'local) (org-show-hierarchy-above)))) (run-hooks 'org-occur-hook) (if (interactive-p) @@ -3341,17 +3434,36 @@ "Make sure point and the headings hierarchy above is visible." (if (org-on-heading-p t) (org-flag-heading nil) ; only show the heading - (org-show-hidden-entry)) ; show entire entry + (and (org-invisible-p) (org-show-hidden-entry))) ; show entire entry (save-excursion (and org-show-following-heading (outline-next-heading) (org-flag-heading nil))) ; show the next heading - (save-excursion ; show all higher headings - (while (condition-case nil - (progn (org-up-heading-all 1) t) - (error nil)) - (org-flag-heading nil)))) - + (when org-show-hierarchy-above + (save-excursion ; show all higher headings + (while (condition-case nil + (progn (org-up-heading-all 1) t) + (error nil)) + (org-flag-heading nil))))) + +(defvar org-occur-highlights nil) +(defun org-highlight-new-match (beg end) + "Highlight from BEG to END and mark the highlight is an occur headline." + (let ((ov (make-overlay beg end))) + (overlay-put ov 'face 'secondary-selection) + (push ov org-occur-highlights))) + +(defun org-remove-occur-highlights (&optional beg end noremove) + "Remove the occur highlights from the buffer. +BEG and END are ignored. If NOREMOVE is nil, remove this function +from the before-change-functions in the current buffer." + (interactive) + (mapc 'delete-overlay org-occur-highlights) + (setq org-occur-highlights nil) + (unless noremove + (remove-hook 'before-change-functions + 'org-remove-occur-highlights 'local))) + ;;; Priorities (defvar org-priority-regexp ".*?\\(\\[#\\([A-Z]\\)\\] ?\\)" @@ -3767,13 +3879,19 @@ "Increase the date in the time stamp by one day. With prefix ARG, change that many days." (interactive "p") - (org-timestamp-change (prefix-numeric-value arg) 'day)) + (if (and (not (org-at-timestamp-p)) + (org-on-heading-p)) + (org-todo 'up) + (org-timestamp-change (prefix-numeric-value arg) 'day))) (defun org-timestamp-down-day (&optional arg) "Decrease the date in the time stamp by one day. With prefix ARG, change that many days." (interactive "p") - (org-timestamp-change (- (prefix-numeric-value arg)) 'day)) + (if (and (not (org-at-timestamp-p)) + (org-on-heading-p)) + (org-todo 'down) + (org-timestamp-change (- (prefix-numeric-value arg)) 'day))) (defsubst org-pos-in-match-range (pos n) (and (match-beginning n) @@ -3781,7 +3899,7 @@ (>= (match-end n) pos))) (defun org-at-timestamp-p () - "Determine if the cursor is or at a timestamp." + "Determine if the cursor is in or at a timestamp." (interactive) (let* ((tsr org-ts-regexp2) (pos (point)) @@ -4269,7 +4387,7 @@ (put-text-property s (1- (point)) 'face 'org-link) (if rtnall (insert - (org-finalize-agenda-entries ;; FIXME: condition needed + (org-finalize-agenda-entries (org-agenda-add-time-grid-maybe rtnall nd todayp)) "\n")) @@ -4291,6 +4409,65 @@ (if (not org-select-agenda-window) (select-window win)) (message ""))) +(defvar org-select-this-todo-keyword nil) + +;;;###autoload +(defun org-todo-list (arg) + "Show all TODO entries from all agenda file in a single list. +The prefix arg can be used to select a specific TODO keyword and limit +the list to these. When using \\[universal-argument], you will be prompted +for a keyword. A numeric prefix directly selects the Nth keyword in +`org-todo-keywords'." + (interactive "P") + (org-agenda-maybe-reset-markers 'force) + (org-compile-prefix-format org-agenda-prefix-format) + (let* ((today (time-to-days (current-time))) + (date (calendar-gregorian-from-absolute today)) + (win (selected-window)) + (kwds org-todo-keywords) + (completion-ignore-case t) + (org-select-this-todo-keyword + (and arg (integerp arg) (nth (1- arg) org-todo-keywords))) + rtn rtnall files file pos) + (when (equal arg '(4)) + (setq org-select-this-todo-keyword + (completing-read "Keyword: " (mapcar 'list org-todo-keywords) + nil t))) + (and (equal 0 arg) (setq org-select-this-todo-keyword nil)) + (if (not (equal (current-buffer) (get-buffer org-agenda-buffer-name))) + (progn + (delete-other-windows) + (switch-to-buffer-other-window + (get-buffer-create org-agenda-buffer-name)))) + (setq buffer-read-only nil) + (erase-buffer) + (org-agenda-mode) (setq buffer-read-only nil) + (set (make-local-variable 'last-arg) arg) + (set (make-local-variable 'org-todo-keywords) kwds) + (set (make-local-variable 'org-agenda-redo-command) + '(org-todo-list (or current-prefix-arg last-arg))) + (setq files org-agenda-files + rtnall nil) + (while (setq file (pop files)) + (catch 'nextfile + (org-check-agenda-file file) + (setq rtn (org-agenda-get-day-entries file date :todo)) + (setq rtnall (append rtnall rtn)))) + (insert "Global list of TODO items of type: ") + (add-text-properties (point-min) (1- (point)) + (list 'face 'org-link)) + (setq pos (point)) + (insert (or org-select-this-todo-keyword "ALL") "\n") + (add-text-properties pos (1- (point)) (list 'face 'org-warning)) + (when rtnall + (insert (org-finalize-agenda-entries rtnall) "\n")) + (goto-char (point-min)) + (setq buffer-read-only t) + (if org-fit-agenda-window + (fit-window-to-buffer nil (/ (* (frame-height) 3) 4) + (/ (frame-height) 2))) + (if (not org-select-agenda-window) (select-window win)))) + (defun org-check-agenda-file (file) "Make sure FILE exists. If not, ask user what to do." ;; FIXME: this does not correctly change the menus @@ -4323,7 +4500,8 @@ (org-agenda-quit)) (defun org-agenda-redo () - "Rebuild Agenda." + "Rebuild Agenda. +When this is the global TODO list, a prefix argument will be interpreted." (interactive) (eval org-agenda-redo-command)) @@ -4719,6 +4897,25 @@ (setq results (append results rtn))) (if results (concat (org-finalize-agenda-entries results) "\n")))) +(defvar org-category-table nil) +(defun org-get-category-table () + "Get the table of categories and positions in current buffer." + (let (tbl) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "^#\\+CATEGORY:[ \t]*\\(.*\\)" nil t) + (push (cons (point) (org-trim (match-string 1))) tbl))) + tbl)) + (defun org-get-category (&optional pos) + "Get the category applying to position POS." + (if (not org-category-table) + org-category + (let ((tbl org-category-table) + (pos (or pos (point)))) + (while (and tbl (> (caar tbl) pos)) + (pop tbl)) + (or (cdar tbl) (cdr (nth (1- (length org-category-table)) + org-category-table)))))) (defun org-agenda-get-day-entries (file date &rest args) "Does the work for `org-diary' and `org-agenda'. @@ -4739,6 +4936,7 @@ (with-current-buffer buffer (unless (eq major-mode 'org-mode) (error "Agenda file %s is not in `org-mode'" file)) + (setq org-category-table (org-get-category-table)) (let ((case-fold-search nil)) (save-excursion (save-restriction @@ -4803,15 +5001,20 @@ 'help-echo (format "mouse-2 or RET jump to org file %s" (abbreviate-file-name (buffer-file-name))))) - (regexp (concat "[\n\r]\\*+ *\\(" org-not-done-regexp + (regexp (concat "[\n\r]\\*+ *\\(" + (if org-select-this-todo-keyword + (concat "\\<\\(" org-select-this-todo-keyword + "\\)\\>") + org-not-done-regexp) "[^\n\r]*\\)")) - marker priority + marker priority category ee txt) (goto-char (point-min)) (while (re-search-forward regexp nil t) (goto-char (match-beginning 1)) (setq marker (org-agenda-new-marker (point-at-bol)) - txt (org-format-agenda-item "" (match-string 1)) + category (org-get-category) + txt (org-format-agenda-item "" (match-string 1) category) priority (+ (org-get-priority txt) (if org-todo-kwd-priority-p @@ -4821,7 +5024,7 @@ 1))) (add-text-properties 0 (length txt) (append (list 'org-marker marker 'org-hd-marker marker - 'priority priority) + 'priority priority 'category category) props) txt) (push txt ee) @@ -4846,13 +5049,14 @@ (apply 'encode-time ; DATE bound by calendar (list 0 0 0 (nth 1 date) (car date) (nth 2 date)))) 0 11))) - marker hdmarker deadlinep scheduledp donep tmp priority + marker hdmarker deadlinep scheduledp donep tmp priority category ee txt timestr) (goto-char (point-min)) (while (re-search-forward regexp nil t) (if (not (save-match-data (org-at-date-range-p))) (progn (setq marker (org-agenda-new-marker (match-beginning 0)) + category (org-get-category (match-beginning 0)) tmp (buffer-substring (max (point-min) (- (match-beginning 0) org-ds-keyword-length)) @@ -4874,7 +5078,7 @@ (format "%s%s" (if deadlinep "Deadline: " "") (if scheduledp "Scheduled: " "")) - (match-string 1) nil timestr))) + (match-string 1) category timestr))) (setq txt org-agenda-no-heading-message)) (setq priority (org-get-priority txt)) (add-text-properties @@ -4900,7 +5104,7 @@ txt) (add-text-properties 0 (length txt) - (list 'priority priority) txt))) + (list 'priority priority 'category category) txt))) (push txt ee)) (outline-next-heading)))) (nreverse ee))) @@ -4916,7 +5120,7 @@ (regexp org-deadline-time-regexp) (todayp (equal date (calendar-current-date))) ; DATE bound by calendar (d1 (calendar-absolute-from-gregorian date)) ; DATE bound by calendar - d2 diff pos pos1 + d2 diff pos pos1 category ee txt head) (goto-char (point-min)) (while (re-search-forward regexp nil t) @@ -4929,6 +5133,7 @@ ;; Past-due deadlines are only shown on the current date (if (and (< diff wdays) todayp (not (= diff 0))) (save-excursion + (setq category (org-get-category)) (if (re-search-backward "\\(^\\|\r\\)\\*+[ \t]*" nil t) (progn (goto-char (match-end 0)) @@ -4940,7 +5145,7 @@ (if (string-match org-looking-at-done-regexp head) (setq txt nil) (setq txt (org-format-agenda-item - (format "In %3d d.: " diff) head)))) + (format "In %3d d.: " diff) head category)))) (setq txt org-agenda-no-heading-message)) (when txt (add-text-properties @@ -4949,6 +5154,7 @@ (list 'org-marker (org-agenda-new-marker pos) 'org-hd-marker (org-agenda-new-marker pos1) 'priority (+ (- 10 diff) (org-get-priority txt)) + 'category category 'face (cond ((<= diff 0) 'org-warning) ((<= diff 5) 'org-scheduled-previously) (t nil)) @@ -4975,7 +5181,7 @@ (regexp org-scheduled-time-regexp) (todayp (equal date (calendar-current-date))) ; DATE bound by calendar (d1 (calendar-absolute-from-gregorian date)) ; DATE bound by calendar - d2 diff pos pos1 + d2 diff pos pos1 category ee txt head) (goto-char (point-min)) (while (re-search-forward regexp nil t) @@ -4987,6 +5193,7 @@ ;; If it is on or past the date. (if (and (< diff 0) todayp) (save-excursion + (setq category (org-get-category)) (if (re-search-backward "\\(^\\|\r\\)\\*+[ \t]*" nil t) (progn (goto-char (match-end 0)) @@ -4997,14 +5204,16 @@ (if (string-match org-looking-at-done-regexp head) (setq txt nil) (setq txt (org-format-agenda-item - (format "Sched.%2dx: " (- 1 diff)) head)))) + (format "Sched.%2dx: " (- 1 diff)) head + category)))) (setq txt org-agenda-no-heading-message)) (when txt (add-text-properties 0 (length txt) (append (list 'org-marker (org-agenda-new-marker pos) 'org-hd-marker (org-agenda-new-marker pos1) - 'priority (+ (- 5 diff) (org-get-priority txt))) + 'priority (+ (- 5 diff) (org-get-priority txt)) + 'category category) props) txt) (push txt ee))))) ee)) @@ -5019,7 +5228,7 @@ (abbreviate-file-name (buffer-file-name))))) (regexp org-tr-regexp) (d0 (calendar-absolute-from-gregorian date)) - marker hdmarker ee txt d1 d2 s1 s2 timestr) + marker hdmarker ee txt d1 d2 s1 s2 timestr category) (goto-char (point-min)) (while (re-search-forward regexp nil t) (setq timestr (match-string 0) @@ -5032,6 +5241,7 @@ ;; date stamps will catch the limits. (save-excursion (setq marker (org-agenda-new-marker (point))) + (setq category (org-get-category)) (if (re-search-backward "\\(^\\|\r\\)\\*+" nil t) (progn (setq hdmarker (org-agenda-new-marker (match-end 1))) @@ -5040,12 +5250,14 @@ (setq txt (org-format-agenda-item (format (if (= d1 d2) "" "(%d/%d): ") (1+ (- d0 d1)) (1+ (- d2 d1))) - (match-string 1) nil (if (= d0 d1) timestr)))) + (match-string 1) category + (if (= d0 d1) timestr)))) (setq txt org-agenda-no-heading-message)) (add-text-properties 0 (length txt) (append (list 'org-marker marker 'org-hd-marker hdmarker - 'priority (org-get-priority txt)) + 'priority (org-get-priority txt) + 'category category) props) txt) (push txt ee))) @@ -5053,8 +5265,6 @@ ;; Sort the entries by expiration date. (nreverse ee))) - - (defconst org-plain-time-of-day-regexp (concat "\\(\\<[012]?[0-9]" @@ -5359,11 +5569,11 @@ "Marker pointing to the headline that last changed its TODO state by a remote command from the agenda.") -(defun org-agenda-todo () +(defun org-agenda-todo (&optional arg) "Cycle TODO state of line at point, also in Org-mode file. This changes the line at point, all other lines in the agenda referring to the same tree node, and the headline of the tree node in the Org-mode file." - (interactive) + (interactive "P") (org-agenda-check-no-diary) (let* ((col (current-column)) (marker (or (get-text-property (point) 'org-marker) @@ -5380,7 +5590,7 @@ (save-excursion (and (outline-next-heading) (org-flag-heading nil))) ; show the next heading - (org-todo) + (org-todo arg) (forward-char 1) (setq newhead (org-get-heading)) (save-excursion @@ -5398,7 +5608,7 @@ `equal' against all `org-hd-marker' text properties in the file. If FIXFACE is non-nil, the face of each item is modified acording to the new TODO state." - (let* (props m pl undone-face done-face finish new dotime) + (let* (props m pl undone-face done-face finish new dotime cat) ; (setq newhead (org-format-agenda-item "x" newhead "x" nil 'noprefix)) (save-excursion (goto-char (point-max)) @@ -5409,7 +5619,8 @@ (equal m hdmarker)) (setq props (text-properties-at (point)) dotime (get-text-property (point) 'dotime) - new (org-format-agenda-item "x" newhead "x" dotime 'noprefix) + cat (get-text-property (point) 'category) + new (org-format-agenda-item "x" newhead cat dotime 'noprefix) pl (get-text-property (point) 'prefix-length) undone-face (get-text-property (point) 'undone-face) done-face (get-text-property (point) 'done-face)) @@ -5507,6 +5718,7 @@ (defun org-get-heading () "Return the heading of the current entry, without the stars." (save-excursion + (and (bolp) (end-of-line 1)) (if (and (re-search-backward "[\r\n]\\*" nil t) (looking-at "[\r\n]\\*+[ \t]+\\(.*\\)")) (match-string 1) @@ -5662,90 +5874,206 @@ Normally, files will be opened by an appropriate application. If the optional argument IN-EMACS is non-nil, Emacs will visit the file." (interactive "P") + (org-remove-occur-highlights nil nil t) (if (org-at-timestamp-p) (org-agenda nil (time-to-days (org-time-string-to-time (substring (match-string 1) 0 10))) 1) - (let (type path line (pos (point))) - (save-excursion - (skip-chars-backward - (concat (if org-allow-space-in-links "^" "^ ") - org-non-link-chars)) - (if (re-search-forward - org-link-regexp - (save-excursion - (condition-case nil - (progn (outline-end-of-subtree) (max pos (point))) - (error (end-of-line 1) (point)))) - t) + (let (type path line search (pos (point))) + (catch 'match + (save-excursion + (skip-chars-backward + (concat (if org-allow-space-in-links "^" "^ ") + org-non-link-chars)) + (when (looking-at org-link-regexp) (setq type (match-string 1) - path (match-string 2))) - (unless path - (error "No link found")) - ;; Remove any trailing spaces in path - (if (string-match " +\\'" path) - (setq path (replace-match "" t t path))) - - (cond - - ((string= type "file") - (if (string-match ":\\([0-9]+\\)\\'" path) - (setq line (string-to-number (match-string 1 path)) - path (substring path 0 (match-beginning 0)))) - (org-open-file path in-emacs line)) - - ((string= type "news") - (org-follow-gnus-link path)) - - ((string= type "bbdb") - (org-follow-bbdb-link path)) - - ((string= type "gnus") - (let (group article) - (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path)) - (error "Error in Gnus link")) - (setq group (match-string 1 path) - article (match-string 3 path)) - (org-follow-gnus-link group article))) - - ((string= type "vm") - (let (folder article) - (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path)) - (error "Error in VM link")) - (setq folder (match-string 1 path) - article (match-string 3 path)) - ;; in-emacs is the prefix arg, will be interpreted as read-only - (org-follow-vm-link folder article in-emacs))) - - ((string= type "wl") - (let (folder article) - (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path)) - (error "Error in Wanderlust link")) - (setq folder (match-string 1 path) - article (match-string 3 path)) - (org-follow-wl-link folder article))) - - ((string= type "rmail") - (let (folder article) - (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path)) - (error "Error in RMAIL link")) - (setq folder (match-string 1 path) - article (match-string 3 path)) - (org-follow-rmail-link folder article))) - - ((string= type "shell") - (let ((cmd path)) - (while (string-match "@{" cmd) - (setq cmd (replace-match "<" t t cmd))) - (while (string-match "@}" cmd) - (setq cmd (replace-match ">" t t cmd))) - (if (or (not org-confirm-shell-links) - (yes-or-no-p (format "Execute \"%s\" in the shell? " cmd))) - (shell-command cmd) - (error "Abort")))) - - (t - (browse-url-at-point))))))) + path (match-string 2)) + (throw 'match t))) + (save-excursion + (skip-chars-backward "a-zA-Z_") + (when (looking-at org-camel-regexp) + (setq type "camel" path (match-string 0)) + (if (equal (char-before) ?*) + (setq path (concat "*" path)))) + (throw 'match t)) + (save-excursion + (when (re-search-forward + org-link-regexp + (save-excursion + (condition-case nil + (progn (outline-end-of-subtree) (max pos (point))) + (error (end-of-line 1) (point)))) + t) + (setq type (match-string 1) + path (match-string 2))))) + (unless path + (error "No link found")) + ;; Remove any trailing spaces in path + (if (string-match " +\\'" path) + (setq path (replace-match "" t t path))) + + (cond + + ((string= type "camel") + (org-link-search + path + (cond ((equal in-emacs '(4)) 'occur) + ((equal in-emacs '(16)) 'org-occur) + (t nil)))) + + ((string= type "file") + (if (string-match "::?\\([0-9]+\\)\\'" path) ;; second : optional + (setq line (string-to-number (match-string 1 path)) + path (substring path 0 (match-beginning 0))) + (if (string-match "::\\(.+\\)\\'" path) + (setq search (match-string 1 path) + path (substring path 0 (match-beginning 0))))) + (org-open-file path in-emacs line search)) + + ((string= type "news") + (org-follow-gnus-link path)) + + ((string= type "bbdb") + (org-follow-bbdb-link path)) + + ((string= type "gnus") + (let (group article) + (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path)) + (error "Error in Gnus link")) + (setq group (match-string 1 path) + article (match-string 3 path)) + (org-follow-gnus-link group article))) + + ((string= type "vm") + (let (folder article) + (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path)) + (error "Error in VM link")) + (setq folder (match-string 1 path) + article (match-string 3 path)) + ;; in-emacs is the prefix arg, will be interpreted as read-only + (org-follow-vm-link folder article in-emacs))) + + ((string= type "wl") + (let (folder article) + (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path)) + (error "Error in Wanderlust link")) + (setq folder (match-string 1 path) + article (match-string 3 path)) + (org-follow-wl-link folder article))) + + ((string= type "rmail") + (let (folder article) + (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path)) + (error "Error in RMAIL link")) + (setq folder (match-string 1 path) + article (match-string 3 path)) + (org-follow-rmail-link folder article))) + + ((string= type "shell") + (let ((cmd path)) + (while (string-match "@{" cmd) + (setq cmd (replace-match "<" t t cmd))) + (while (string-match "@}" cmd) + (setq cmd (replace-match ">" t t cmd))) + (if (or (not org-confirm-shell-links) + (yes-or-no-p (format "Execute \"%s\" in the shell? " cmd))) + (shell-command cmd) + (error "Abort")))) + + (t + (browse-url-at-point)))))) + +(defun org-link-search (s &optional type) + "Search for a link search option. +When S is a CamelCaseWord, search for a target, or for a sentence containing +the words. If S is surrounded by forward slashes, it is interpreted as a +regular expression. In org-mode files, this will create an `org-occur' +sparse tree. In ordinary files, `occur' will be used to list matched. +If the current buffer is in `dired-mode', grep will be used to search +in all files." + (let ((case-fold-search t) + (s0 s) + (pos (point)) + (pre "") (post "") + words re0 re1 re2 re3 re4 re5 reall) + (cond ((string-match "^/\\(.*\\)/$" s) + ;; A regular expression + (cond + ((eq major-mode 'org-mode) + (org-occur (match-string 1 s))) + ;;((eq major-mode 'dired-mode) + ;; (grep (concat "grep -n -e '" (match-string 1 s) "' *"))) + (t (org-do-occur (match-string 1 s))))) + ((string-match (concat "^" org-camel-regexp) s) + ;; A camel + (if (equal (string-to-char s) ?*) + (setq pre "^\\*+[ \t]*\\(\\sw+\\)?[ \t]*" + post "[ \t]*$" + s (substring s 1))) + (remove-text-properties + 0 (length s) + '(face nil mouse-face nil keymap nil fontified nil) s) + ;; Make a series of regular expressions to find a match + (setq words (org-camel-to-words s) + re0 (concat "<<" (regexp-quote s0) ">>") + re2 (concat "\\<" (mapconcat 'downcase words "[ \t]+") "\\>") + re4 (concat "\\<" (mapconcat 'downcase words "[^a-zA-Z_\r\n]+") "\\>") + re1 (concat pre re2 post) + re3 (concat pre re4 post) + re5 (concat pre ".*" re4) + re2 (concat pre re2) + re4 (concat pre re4) + reall (concat "\\(" re0 "\\)\\|\\(" re1 "\\)\\|\\(" re2 + "\\)\\|\\(" re3 "\\)\\|\\(" re4 "\\)\\|\\(" + re5 "\\)" + )) + (cond + ((eq type 'org-occur) (org-occur reall)) + ((eq type 'occur) (org-do-occur (downcase reall) 'cleanup)) + (t (goto-char (point-min)) + (if (or (re-search-forward re0 nil t) + (re-search-forward re1 nil t) + (re-search-forward re2 nil t) + (re-search-forward re3 nil t) + (re-search-forward re4 nil t) + (re-search-forward re5 nil t)) + (goto-char (match-beginning 0)) + (goto-char pos) + (error "No match"))))) + (t + ;; Normal string-search + (goto-char (point-min)) + (if (search-forward s nil t) + (goto-char (match-beginning 0)) + (error "No match")))))) + +(defun org-do-occur (regexp &optional cleanup) + "Call the Emacs command `occur'. +If CLEANUP is non-nil, remove the printout of the regular expression +in the *Occur* buffer. This is useful if the regex is long and not useful +to read." + (occur regexp) + (when cleanup + (let ((cwin (selected-window)) win beg end) + (when (setq win (get-buffer-window "*Occur*")) + (select-window win)) + (goto-char (point-min)) + (when (re-search-forward "match[a-z]+" nil t) + (setq beg (match-end 0)) + (if (re-search-forward "^[ \t]*[0-9]+" nil t) + (setq end (1- (match-beginning 0))))) + (and beg end (let ((buffer-read-only)) (delete-region beg end))) + (goto-char (point-min)) + (select-window cwin)))) + +(defun org-camel-to-words (s) + "Split \"CamelCaseWords\" to (\"Camel \" \"Case\" \"Words\")." + (let ((case-fold-search nil) + words) + (while (string-match "[a-z][A-Z]" s) + (push (substring s 0 (1+ (match-beginning 0))) words) + (setq s (substring s (1+ (match-beginning 0))))) + (nreverse (cons s words)))) (defun org-follow-bbdb-link (name) "Follow a BBDB link to NAME." @@ -5845,15 +6173,21 @@ message-number) (error "Message not found")))) -(defun org-open-file (path &optional in-emacs line) +(defun org-open-file (path &optional in-emacs line search) "Open the file at PATH. First, this expands any special file name abbreviations. Then the configuration variable `org-file-apps' is checked if it contains an entry for this file type, and if yes, the corresponding command is launched. If no application is found, Emacs simply visits the file. With optional argument IN-EMACS, Emacs will visit the file. +Optional LINE specifies a line to go to, optional SEARCH a string to +search for. If LINE or SEARCH is given, the file will always be +openen in emacs. If the file does not exist, an error is thrown." - (let* ((file (convert-standard-filename (org-expand-file-name path))) + (setq in-emacs (or in-emacs line search)) + (let* ((file (if (equal path "") + (buffer-file-name) + (convert-standard-filename (org-expand-file-name path)))) (dfile (downcase file)) ext cmd apps) (if (and (not (file-exists-p file)) @@ -5875,8 +6209,10 @@ (shell-command (concat cmd " & &")))) ((or (stringp cmd) (eq cmd 'emacs)) - (funcall (cdr (assq 'file org-link-frame-setup)) file) - (if line (goto-line line))) + (unless (equal (file-truename file) (file-truename (buffer-file-name))) + (funcall (cdr (assq 'file org-link-frame-setup)) file)) + (if line (goto-line line) + (if search (org-link-search search)))) ((consp cmd) (eval cmd)) (t (funcall (cdr (assq 'file org-link-frame-setup)) file))))) @@ -5908,7 +6244,7 @@ \\[org-insert-link]. For some link types, a prefix arg is interpreted: For links to usenet articles, arg negates `org-usenet-links-prefer-google'. -For file links, arg negates `org-line-numbers-in-file-links'." +For file links, arg negates `org-context-in-file-links'." (interactive "P") (let (link cpltxt) (cond @@ -6018,17 +6354,39 @@ (setq cpltxt w3m-current-url link (org-make-link cpltxt))) + ((eq major-mode 'org-mode) + ;; Just link to current headline + (setq cpltxt (concat "file:" + (abbreviate-file-name (buffer-file-name)))) + ;; Add a context search string + (when (org-xor org-context-in-file-links arg) + (if (save-excursion + (skip-chars-backward "a-zA-Z<") + (looking-at (concat "<<\\(" org-camel-regexp "\\)>>"))) + (setq cpltxt (concat cpltxt "::" (match-string 1))) + (setq cpltxt + (concat cpltxt "::" + (org-make-org-heading-camel + (cond + ((org-on-heading-p) nil) + ((org-region-active-p) + (buffer-substring (region-beginning) (region-end))) + (t (buffer-substring (point-at-bol) (point-at-eol)))) + ))))) + (setq link (org-make-link cpltxt))) + ((buffer-file-name) ;; Just link to this file here. (setq cpltxt (concat "file:" (abbreviate-file-name (buffer-file-name)))) - ;; Add the line number? - (if (org-xor org-line-numbers-in-file-links arg) - (setq cpltxt - (concat cpltxt - ":" (int-to-string - (+ (if (bolp) 1 0) (count-lines - (point-min) (point))))))) + ;; Add a context string + (when (org-xor org-context-in-file-links arg) + (setq cpltxt + (concat cpltxt "::" + (org-make-org-heading-camel + (if (org-region-active-p) + (buffer-substring (region-beginning) (region-end)) + (buffer-substring (point-at-bol) (point-at-eol))))))) (setq link (org-make-link cpltxt))) ((interactive-p) @@ -6043,6 +6401,25 @@ (message "Stored: %s" (or cpltxt link))) link))) +(defun org-make-org-heading-camel (&optional string) + "Make a CamelCase string for S or the current headline." + (interactive) + (let ((s (or string (org-get-heading)))) + (unless string + ;; We are using a headline, clean up garbage in there. + (if (string-match org-todo-regexp s) + (setq s (replace-match "" t t s))) + (setq s (org-trim s)) + (if (string-match (concat "^\\(" org-quote-string "\\|" + org-comment-string "\\)") s) + (setq s (replace-match "" t t s))) + (while (string-match org-ts-regexp s) + (setq s (replace-match "" t t s)))) + (while (string-match "[^a-zA-Z_ \t]+" s) + (setq s (replace-match " " t t s))) + (or string (setq s (concat "*" s))) ; Add * for headlines + (mapconcat 'capitalize (org-split-string s "[ \t]+") ""))) + (defun org-make-link (&rest strings) "Concatenate STRINGS, format resulting string with `org-link-format'." (format org-link-format (apply 'concat strings))) @@ -6130,9 +6507,23 @@ (setq org-stored-links (delq (assoc link org-stored-links) org-stored-links))) (if (not linktxt) (setq link (org-make-link link))) - (let ((lines (org-split-string (or linktxt link) "\n"))) + (setq link (or linktxt link)) + (when (string-match "<\\<file:\\(.+?\\)::\\([^>]+\\)>" link) + (let* ((path (match-string 1 link)) + (case-fold-search nil) + (search (match-string 2 link))) + (when (save-match-data + (equal (file-truename (buffer-file-name)) + (file-truename path))) + (if (save-match-data + (string-match (concat "^" org-camel-regexp "$") search)) + (setq link (replace-match search t t link) + matched t) + (setq link (replace-match (concat "<file:::" search ">") + t t link)))))) + (let ((lines (org-split-string link "\n"))) (insert (car lines)) - (setq matched (string-match org-link-regexp (car lines))) + (setq matched (or matched (string-match org-link-regexp (car lines)))) (setq lines (cdr lines)) (while lines (insert "\n") @@ -9857,7 +10248,6 @@ "Terminate one level in HTML export." (insert "</ul>")) - ;; Variable holding the vector with section numbers (defvar org-section-numbers (make-vector org-level-max 0)) @@ -10036,13 +10426,13 @@ (let ((user user-full-name) (calname "something") (name (or name "unknown")) - (timezone "FIXME")) + (timezone "Europe/Amsterdam")) ;; FIXME: How can I get the real timezone? (princ (format "BEGIN:VCALENDAR VERSION:2.0 X-WR-CALNAME:%s PRODID:-//%s//Emacs with Org-mode//EN -X-WR-TIMEZONE:Europe/Amsterdam +X-WR-TIMEZONE:%s CALSCALE:GREGORIAN\n" name user timezone)))) (defun org-finish-icalendar-file () @@ -10123,10 +10513,10 @@ (define-key org-mode-map [?\C-c ?\C-x (up)] 'org-shiftup) (define-key org-mode-map (org-key 'S-down) 'org-shiftdown) (define-key org-mode-map [?\C-c ?\C-x (down)] 'org-shiftdown) -(define-key org-mode-map (org-key 'S-left) 'org-timestamp-down-day) -(define-key org-mode-map [?\C-c ?\C-x (left)] 'org-timestamp-down-day) -(define-key org-mode-map (org-key 'S-right) 'org-timestamp-up-day) -(define-key org-mode-map [?\C-c ?\C-x (right)] 'org-timestamp-up-day) +(define-key org-mode-map (org-key 'S-left) 'org-shiftleft) +(define-key org-mode-map [?\C-c ?\C-x (left)] 'org-shiftleft) +(define-key org-mode-map (org-key 'S-right) 'org-shiftright) +(define-key org-mode-map [?\C-c ?\C-x (right)] 'org-shiftright) ;; All the other keys (define-key org-mode-map "\C-c$" 'org-archive-subtree) @@ -10277,7 +10667,7 @@ (defun org-shiftcursor-error () "Throw an error because Shift-Cursor command was applied in wrong context." - (error "This command is only active in tables and on headlines")) + (error "This command is active in special context like tables, headlines or timestamps")) (defun org-shifttab () "Global visibility cycling or move to previous table field. @@ -10397,6 +10787,22 @@ ((org-at-timestamp-p) (org-timestamp-down arg)) (t (org-priority-down)))) +(defun org-shiftright () + "Next TODO keyword or timestamp one day later, depending on context." + (interactive) + (cond + ((org-at-timestamp-p) (org-timestamp-up-day)) + ((org-on-heading-p) (org-todo 'right)) + (t (org-shiftcursor-error)))) + +(defun org-shiftleft () + "Previous TODO keyword or timestamp one day earlier, depending on context." + (interactive) + (cond + ((org-at-timestamp-p) (org-timestamp-down-day)) + ((org-on-heading-p) (org-todo 'left)) + (t (org-shiftcursor-error)))) + (defun org-copy-special () "Copy region in table or copy current subtree. Calls `org-table-copy' or `org-copy-subtree', depending on context. @@ -10588,6 +10994,7 @@ ("TODO Lists" ["TODO/DONE/-" org-todo t] ["Show TODO Tree" org-show-todo-tree t] + ["Global TODO list" org-todo-list t] "--" ["Set Priority" org-priority t] ["Priority Up" org-shiftup t] @@ -11003,4 +11410,3 @@ ;; arch-tag: e77da1a7-acc7-4336-b19e-efa25af3f9fd ;;; org.el ends here -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/tumme.el Sat Dec 10 21:18:28 2005 +0000 @@ -0,0 +1,2634 @@ +;;; tumme.el --- use dired to browse and manipulate your images +;; +;; Copyright (C) 2005 Free Software Foundation, Inc. +;; +;; Version: 0.4.10 +;; Keywords: images, thumbnails, dired +;; Author: Mathias Dahl <mathias.rem0veth1s.dahl@gmail.com> + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. + +;;; Commentary: +;; +;; BACKGROUND +;; ========== +;; +;; I needed a program to browse, organize and tag my pictures. I got +;; tired of the old gallery program I used as it did not allow +;; multi-file operations easily. Also, it put things out of my +;; control. Image viewing programs I tested did not allow multi-file +;; operations or did not do what I wanted it to. +;; +;; So, I got the idea to use the wonderful functionality of Emacs and +;; `dired' to do it. It would allow me to do almost anything I wanted, +;; which is basically just to browse all my pictures in an easy way, +;; letting me manipulate and tag them in various ways. `dired' already +;; provide all the file handling and navigation facilities; I only +;; needed to add some functions to display the images. +;; +;; I briefly tried out thumbs.el, and although it seemed more +;; powerful than this package, it did not work the way I wanted to. It +;; was too slow to created thumbnails of all files in a directory (I +;; currently keep all my 2000+ images in the same directory) and +;; browsing the thumbnail buffer was slow too. tumme.el will not +;; create thumbnails until they are needed and the browsing is done +;; quickly and easily in dired. I copied a great deal of ideas and +;; code from there though... :) +;; +;; About the name: tumme means thumb in Swedish and it is used for +;; working with thumbnails, so... :) If you want to know how to +;; pronounce it, go to the page on EmacsWiki and download the .ogg +;; file from there. +;; +;; `tumme' stores the thumbnail files in `tumme-dir' using the file +;; name format ORIGNAME.thumb.ORIGEXT. For example +;; ~/.tumme/myimage01.thumb.jpg. The "database" is for now just a +;; plain text file with the following format: +;; +;; file-name-non-directory;comment:comment-text;tag1;tag2;tag3;...;tagN +;; +;; +;; PREREQUISITES +;; ============= +;; +;; * The ImageMagick package. Currently, `convert' and `mogrify' are +;; used. Find it here: http://www.imagemagick.org. +;; +;; * For non-lossy rotation of JPEG images, the JpegTRAN program is +;; needed. +;; +;; * For `tumme-get-exif-data' and `tumme-write-exif-data' to work, +;; the command line tool `exiftool' is needed. It can be found here: +;; http://www.sno.phy.queensu.ca/~phil/exiftool/. These two functions +;; are, among other things, used for writing comments to image files +;; using `tumme-thumbnail-set-image-description' and to create +;; "unique" file names using `tumme-get-exif-file-name' (used by +;; `tumme-copy-with-exif-file-name'). +;; +;; +;; USAGE +;; ===== +;; +;; If you plan to use tumme much, setting up key bindings for it in +;; dired is a good idea: +;; +;; (tumme-setup-dired-keybindings) +;; +;; Next, do M-x tumme-dired RET. This will ask you for a directory +;; where image files are stored, setup a useful window configuration +;; and enable the two special modes that tumme provides. NOTE: If you +;; do not want tumme to split your windows, call it with a prefix +;; argument. +;; +;; Start viewing thumbnails by doing C-S-n and C-S-p to go up and down +;; in the dired buffer while at the same time displaying a thumbnail +;; image. The thumbnail images will be created on the fly, and +;; cached. This means that the first time you browse your images, it +;; will be a bit slow because the thumbnails are created. If you want +;; to avoid this, you can pre-create the thumbnail images by marking +;; all images in dired (% m \.jpg$ RET) and then do M-x +;; tumme-create-thumbs. +;; +;; Next, try `tumme-display-thumbs' (C-t d). If no file is marked, a +;; thumbnail for the file at point will show up in +;; `tumme-thumbnail-buffer'. If one or more files are marked, +;; thumbnails for those files will be displayed. +;; +;; Pressing TAB will switch to the window containing the +;; `tumme-thumbnail-buffer' buffer. In there you can move between +;; thumbnail images and display a semi-sized version in an Emacs +;; buffer (RET), or the original image in an external viewer +;; (C-RET). By pressing SPC or DEL you will navigate back and fort +;; while at the same time displaying each image in Emacs. You can also +;; navigate using arrow keys. Comment a file by pressing "c". Press +;; TAB to get back to dired. +;; +;; While in dired mode, you can tag and comment files, you can tell +;; `tumme' to mark files with a certain tag (using a regexp) etc. +;; +;; The easiest way to see the available commands is to use the Tumme +;; menus added in tumme-thumbnail-mode and dired-mode. +;; +;; +;; LIMITATIONS +;; =========== +;; +;; * In order to work well, `tumme' require that all your images have +;; unique names. The reason is the way thumbnail file names are +;; generated. I will probably not fix this problem as my images all +;; have unique names. +;; +;; * Supports all image formats that Emacs and convert supports, but +;; the thumbnails are hard-coded to JPEG format. +;; +;; * WARNING: The "database" format used might be changed so keep a +;; backup of `tumme-db-file' when testing new versions. +;; +;; +;;; History: +;; ======== +;; +;; Version 0.1, 2005-04-16 +;; +;; * First release, only browsing support for now. +;; +;; Version 0.2, 2005-04-21 +;; +;; * Changed calls to dired-filename-at-point to dired-get-filename +;; +;; Version 0.3, 2005-04-25 +;; +;; Quite a lot of changes: +;; +;; * Added basic image tagging support. No commands that make use of +;; it yet. +;; +;; * Added text properties for the thumbnail images to be able to +;; track where they came from originally. Used in `tumme-mode'. +;; +;; * Added `tumme-mode' to be used when navigating the thumbnail +;; buffer. Currently, there are commands to mark, unmark, flag and +;; jump to the original file in associated dired buffer. +;; +;; * When moving around in the thumbnail buffer (in `tumme-mode'), the +;; user can turn on tracking of the movements and let them be +;; mirrored in the associated dired buffer. +;; +;; * In this version I have been looking at some ideas in thumbs.el, +;; for example the image margin and relief and the `thumbs-mode' +;; which I copied and made the `tumme-mode' from. +;; +;; Version 0.4, 2005-05-02 +;; +;; * Renamed the functions that are to be used in `tumme-mode' in the +;; thumbnail buffer. +;; +;; * The mark, unmark and flag commands in `tumme-mode' now also moves +;; to next thumbnail, like how dired normally works. +;; +;; * Added `tumme-mode-line-up', `tumme-display-thumbs-append' and +;; `tumme-mode-delete-char'. +;; +;; * Each thumbnail's tags is now displayed when navigating among the +;; thumbnails in the thumbnail buffer. +;; +;; * Added simple slideshow functionality. +;; +;; Version 0.4.1, 2005-05-05 +;; +;; * Fixed bug in `tumme-flag-thumb-original-file' +;; +;; * Added commands to display original image in external viewer +;; (`tumme-display-external') and in a Emacs buffer +;; (`tumme-display-image'). +;; +;; * Minor code clean-up +;; +;; * Renamed some functions back again... +;; +;; * Added rotation of thumbnail images (90 degrees left and right) +;; +;; Version 0.4.2, 2005-05-06 +;; +;; * Removed need for `tumme-display-image-size' in +;; `tumme-display-image'. Now, the maximum image size that fits in +;; `tumme-display-buffer' is calculated automatically. Introduced +;; two correction variables, `tumme-display-window-width-correction' +;; and `tumme-display-window-height-correction' to be used to +;; correct width and height depending on width and height of window +;; decorations, fringes etc. This works really well! +;; +;; Version 0.4.3, 2005-05-07 +;; +;; * Added menus to `dired-mode' and `tumme-mode' +;; +;; * Added `tumme-mark-and-display-next' +;; +;; * Added `tumme-jump-thumbnail-buffer' +;; +;; * Bound TAB in `dired-mode-map' and `tumme-mode-map' to +;; `tumme-jump-thumbnail-buffer' and +;; `tumme-jump-original-dired-buffer', respectively. +;; +;; * Changed `tumme-display-image' to be more general. Now, it can be +;; used from both thumbnail buffer and dired buffer by calling +;; `tumme-display-thumbnail-original-image' and +;; `tumme-display-dired-image', respectively. +;; +;; Version 0.4.4, 2005-05-10 +;; +;; * Added `tumme-get-exif-file-name' and +;; `tumme-copy-with-exif-file-name'. These commands might not be +;; useful for all people because they are very specific. See the +;; documentation for each function for more information. +;; +;; * Added `tumme-display-next-thumbnail-original' and +;; `tumme-display-previous-thumbnail-original' to be used for easy +;; image browsing in thumbnail buffer. +;; +;; * Added support for comments. New function +;; `tumme-comment-thumbnail' added, to be used in thumbnail buffer. +;; +;; * Added `tumme-mark-tagged-files'. Use it in dired buffer to mark +;; tagged files. +;; +;; * Added `mouse-face' property `highlight' for mouse highlighting +;; and had to add a space between each thumbnail to avoid whole rows +;; to be highlighted. Doing this meant that I had to update +;; `tumme-line-up' too... +;; +;; * Added `tumme-mouse-display-image'. Use mouse-2 to display image +;; thumbnail when is highlighted. +;; +;; * As suggested by Ehud Karni on gnu.emacs.help, changed +;; `tumme-window-DIMENSION-pixels' to use `frame-char-DIMENSION' +;; instead of `frame-pixel-DIMENSION'. Feels better +;; +;; * Corrected a bug in `tumme-window-height-pixels'. I did not know +;; that the mode-line consumed one line. Also, after experimenting, it +;; seems that the only correction needed for the image display width +;; is one single pixel. I left the corection variables in there, just +;; in case someone has a system that differs. +;; +;; Version 0.4.5, 2005-05-19 +;; +;; * Added `tumme-line-up-dynamic' that calculates the number of +;; thumbnails that will fit in the thumbnail buffer's window and +;; `tumme-line-up-interactive' that asks the user. +;; +;; * Changed `tumme-display-thumbs' to call one of the `tumme-line-up' +;; functions instead of doing the line-up itself. +;; +;; * Finally! Added experimental gallery creation. See customizable +;; variables `tumme-gallery-dir', `tumme-gallery-image-root-url' and +;; `tumme-gallery-thumb-image-root-url' and new command +;; `tumme-gallery-generate'. Not beatiful, but it works quite +;; well. Probably needs some CSS-stuff in it eventually. Also, I'm not +;; sure this is the way I want to generate my image galleries in the +;; future. After all, static pages cannot do what dynamic pages using +;; PHP et al can do. Serves like a proof-of-concept of the tagging +;; though. +;; +;; * Added option to hide images with certain tags. See +;; `tumme-gallery-hidden-tags'. +;; +;; * Added `tumme-tag-thumbnail' for tagging files from thumbnail +;; buffer. +;; +;; * Added `tumme-tag-remove' and `tumme-tag-thumbnail-remove' so that +;; you can remove tags. Sorry if I have kept you waiting for +;; this... :) +;; +;; * Added option `tumme-append-when-browsing' and new command +;; `tumme-toggle-append-browsing'. +;; +;; Version 0.4.6, 2005-05-21 +;; +;; * Changed `tumme-thumb-name' to always use ".jpg" as file extension +;; for thumbnail files, instead of using the extension from the +;; original file's name. This was a very easy way to open up for +;; allowing browsing of all image file types that Emacs support, +;; assuming ImageMagick supports it too. +;; +;; * Fixed bug in `tumme-create-thumb' `tumme-rotate-thumbnail' and +;; `tumme-display-image' by adding quotes around the file names. The +;; conversion failed if the file name, or path, contained a +;; space. Also expanded the file name, as convert (or is it bash?) +;; does not work as expected for paths like "~/.tumme...". +;; +;; * Fixed another "space bug" :) in `tumme-display-external'. +;; +;; * In call to convert, added "jpeg:" in front of the output file +;; name, so that all generated files becomes JPEG files. For now, only +;; useful if `tumme-temp-image-file' does not end in .jpg. +;; +;; Version 0.4.7, 2005-05-26 +;; +;; * Change header line of tumme.el so that it does not wrap and cause +;; evaluation problems for people getting the source from Usenet. +;; +;; * Changed `tumme-write-tag' slightly to get better performance when +;; tagging many files. +;; +;; * Fixed bug in `tumme-create-gallery-lists' that made it puke if +;; there was empty lines in the database. Changed the code so that it +;; does not car about that. Also, fixed `tumme-remove-tag' so that it +;; tries not to add empty lines at the end of the database. +;; +;; * Changed all commands that execute shell commands to be +;; configurable using the `tumme-cmd-x' custom variables. This makes +;; it easier to switch among different image conversion tools which +;; might use different syntax and options. +;; +;; * Added `tumme-toggle-dired-display-properties'. +;; +;; * Added `tumme-thumb-file-name-format' and changed +;; `tumme-thumb-name' to make it possible to configure the format of +;; thumbnail files. Did not make it customizable yet though. It might +;; be a bad idea to be able to switch between formats... +;; +;; * Changed `tumme-display-window' so that it looks for tumme's +;; display window in all frames. Useful if you want to create an own +;; frame for displaying the temporary image. +;; +;; * After changing the call to `get-window-with-predicate' to scan +;; all frames for tumme's special buffers in visible windows, and also +;; changing the way tumme tracks thumbnail movement in the dired +;; buffer (now using `set-buffer' together with `set-window-point'), +;; tumme now works quite happily with all three buffers in different +;; frames. This empowers the user to setup the special buffers the way +;; that best fits his need at the time. Jumping between dired and +;; `tumme-thumbnail-buffer' work independent on in which frames they +;; are. +;; +;; * Renamed `tumme-track-movement-in-dired' to +;; `tumme-toggle-movement-tracking'. +;; +;; * Added `tumme-track-thumbnail' for movement tracking from dired +;; buffer, analoguous to the tracking done in thumbnail buffer. Both +;; uses the same custom variable `tumme-track-movement' which can be +;; toggled on and off with `tumme-toggle-movement-tracking'. This is +;; neat. :) Changed `tumme-setup-dired-keybindings' to make use of +;; this in the best way. Read more about this there. +;; +;; Version 0.4.8, 2005-06-05 +;; +;; * Changed `tumme-display-dired-image' and +;; `tumme-display-thumbnail-original-image' so that when called with a +;; prefix argument, the image is not resized in the display +;; buffer. This will be useful for later additions of image +;; manipulation commands. +;; +;; * Added `tumme-kill-buffer-and-window' to make it easy to kill the +;; tumme buffers. +;; +;; * Renamed `tumme-mode' to `tumme-thumbnail-mode'. +;; +;; * `tumme-tag-thumbnail' and `tumme-tag-thumbnail-remove' now +;; updates the tags property for the thumbnail. +;; +;; * Added `tumme-dired-display-external' to display images in +;; external viewer from dired buffer. +;; +;; * Added support for multiple files in `tumme-remove-tag' to +;; increase performance. +;; +;; * Added `tumme-display-image-mode' so that we can add image +;; manipulation commands there. +;; +;; * Added call to `tumme-display-thumb-properties' in +;; `tumme-track-thumbnail'. +;; +;; * Added command `tumme-display-current-image-in-full-size' to be +;; used in `tumme-display-image-mode'. +;; +;; * Changed `tumme-display-image' to call +;; `tumme-create-display-image-buffer' so that we are sure that +;; `tumme-display-image-buffer' is always available. +;; +;; * Added optional prefix argument to `tumme-dired-folder' that tells +;; it to skip the window splitting and just creates the needed +;; buffers. +;; +;; * Fixed bug somewhere that relied on `tumme-dired-folder' having +;; created the `tumme-display-image-buffer'. Now `tumme-dired-folder' +;; *should* not be necessary to call at all, just convenient. +;; +;; * Added tracking to `tumme-mouse-display-image'. +;; +;; * Added `tumme-mouse-select-thumbnail' and bound mouse-1 to it, so +;; that selecting a thumbnail will track the original file. +;; +;; * Added three new custom variables, `tumme-cmd-ACTION-program' to +;; make the command options cleaner and easier to read. +;; +;; * Added `tumme-display-properties-format' and +;; `tumme-format-properties-string' to make it possible to configure +;; the display format of the image file's properties. +;; +;; * Added missing (require 'format-spec) +;; +;; Version 0.4.9, 2005-09-25 +;; +;; * Fixed bug in `tumme-display-thumbs'. If a thumbnail file could +;; not be created for some reason (bad file for example), even if +;; several other thumbnails was created sucessfully, the code +;; generated an error and never continued doing the line-up. +;; +;; * Made tumme.el pass the M-x checkdoc test, phew! +;; +;; * Added `tumme-rotate-original', `tumme-rotate-original-left' and +;; `tumme-rotate-original-right' to rotate the original image from +;; thumbnail view. By default it uses JpegTRAN to rotate the images +;; non-lossy. Only works on JPEG images. The two new commands were +;; added to thumbnail mode. Thanks to Colin Marquardt who told me +;; about the "-copy all" option to jpegtran. +;; +;; * Added the functions `tumme-get-exif-data' and +;; `tumme-set-exif-data' for reading and writing EXIF data to image files. +;; +;; * Rewrote `tumme-get-exif-file-name': now uses +;; `tumme-get-exif-data'. Slight change to replace spaces with +;; underscores (tt seems not all cameras use the exact same format for +;; DateTimeOriginal). Added code for handling files that has no +;; EXIF-data (use file's timestamp instead). +;; +;; * Changed from using the exif program to exiftool because exiftool +;; also handles writing of EXIF data, which is very useful. +;; +;; * Added the command `tumme-thumbnail-set-image-description' that +;; can be used to set the EXIF tag ImageDescription. Thanks to Colin +;; Marquardt for the suggestion. +;; +;; * Added `tumme-toggle-mark-thumb-original-file' and +;; `tumme-mouse-toggle-mark' and changed +;; `tumme-modify-mark-on-thumb-original-file' to support toggling of +;; mark of original image file in dired, from +;; `tumme-thumbnail-mode'. Bound C-down-mouse-1 +;; `tumme-mouse-toggle-mark' to in `tumme-thumbnail-mode'. +;; +;; * Changed `tumme-mouse-select-thumbnail' to also display properties +;; after the file is selected. +;; +;; Version 0.4.10, 2005-11-07 +;; +;; * Renamed `tumme-dired-folder' to `tumme-dired'. +;; +;; * Changed format of the database file slightly, now the full path +;; and file name is used. Had to change most of the tag functions +;; (writing, reading, searching) slightly to cope with the change. If +;; you are an old tumme user, you have to update your database +;; manually, probably you only need to prefix all rows with a +;; directory name to get the full path and file name. +;; +;; * Removed `tumme-thumb-file-name-format'. Added +;; `tumme-thumbnail-storage' and changed `tumme-thumb-name' to provide +;; two different thumbnail storage schemes. It is no longer necessary +;; to have unique image file names to use tumme fully. +;; +;; * As a consequence of the above, gallery generation is currently +;; not supported if per-directory thumbnail file storage is used. +;; +;; * Changed parameters to `tumme-create-thumb'. +;; +;; * To be included in Emacs 22. +;; +;; +;; +;; TODO +;; ==== +;; +;; * Support gallery creation when using per-directory thumbnail +;; storage. +;; +;; * Some sort of auto-rotate function based on rotate info in the +;; EXIF data. +;; +;; * Check if exiftool exist before trying to call it to give a better +;; error message. +;; +;; * Investigate if it is possible to also write the tags to the image +;; files. +;; +;; * From thumbs.el: Add an option for clean-up/max-size functionality +;; for thumbnail directory. +;; +;; * From thumbs.el: Add setroot function. +;; +;; * Asynchronous creation of thumbnails. +;; +;; * Add `tumme-display-thumbs-ring' and functions to cycle that. Find +;; out which is best, saving old batch just before inserting new, or +;; saving the current batch in the ring when inserting it. Adding it +;; probably needs rewriting `tumme-display-thumbs' to be more general. +;; +;; * Find some way of toggling on and off really nice keybindings in +;; dired (for example, using C-n or <down> instead of C-S-n). Richard +;; suggested that we could keep C-t as prefix for tumme commands as it +;; is currently not used in dired. He also suggested that +;; `dired-next-line' and `dired-previous-line' figure out if tumme is +;; enabled in the current buffer and, if it is, call +;; `tumme-dired-next-line' and `tumme-dired-previous-line', +;; respectively. +;; +;; * Enhanced gallery creation with basic CSS-support and pagination +;; of tag pages with many pictures. +;; +;; * Rewrite `tumme-modify-mark-on-thumb-original-file' to be less +;; ugly. +;; +;; * In some way keep track of buffers and windows and stuff so that +;; it works as the user expects. +;; +;; * More/better documentation +;; +;; +;;; Code: + +(require 'dired) +(require 'format-spec) + +(defgroup tumme nil + "Use dired to browse your images as thumbnails, and more." + :prefix "tumme-" + :group 'files) + +(defcustom tumme-dir "~/.tumme/" + "*Directory where thumbnail images for are stored." + :type 'string + :group 'tumme) + +(defcustom tumme-thumbnail-storage 'use-tumme-dir + "*How to store tumme's thumbnail files. +Tumme can store thumbnail files in one of two ways and this is +controlled by this variable. \"Use tumme dir\" means that the +thumbnails are stored in a central directory. \"Per directory\" +means that each thumbnail is stored in a subdirectory called +\".tumme\" in the same directory where the image file is." + :type '(choice :tag "How to store thumbnail files" + (const :tag "Use tumme-dir" use-tumme-dir) + (const :tag "Per-directory" per-directory)) + :group 'tumme) + +(defcustom tumme-db-file "~/.tumme/.tumme_db" + "*Database file where file names and their associated tags are stored." + :type 'string + :group 'tumme) + +(defcustom tumme-temp-image-file "~/.tumme/.tumme_temp" + "*Name of temporary image file used by various commands." + :type 'string + :group 'tumme) + +(defcustom tumme-gallery-dir "~/.tumme/.tumme_gallery" + "*Directory to store generated gallery html pages. +This path needs to be \"shared\" to the public so that it can access +the index.html page that tumme creates." + :type 'string + :group 'tumme) + +(defcustom tumme-gallery-image-root-url +"http://your.own.server/tummepics" + "*URL where the full size images are to be found. +Note that this path has to be configured in your web server. Tumme +expects to find pictures in this directory." + :type 'string + :group 'tumme) + +(defcustom tumme-gallery-thumb-image-root-url +"http://your.own.server/tummethumbs" + "*URL where the thumbnail images are to be found. +Note that this path has to be configured in your web server. Tumme +expects to find pictures in this directory." + :type 'string + :group 'tumme) + +(defcustom tumme-cmd-create-thumbnail-program + "convert" + "*Executable used to create thumbnail. +Used together with `tumme-cmd-create-thumbnail-options'." + :type 'string + :group 'tumme) + +(defcustom tumme-cmd-create-thumbnail-options + "%p -size %sx%s \"%f\" -resize %sx%s +profile \"*\" jpeg:\"%t\"" + "*Format of command used to create thumbnail image. +Available options are %p which is replaced by +`tumme-cmd-create-thumbnail-program', %s which is replaced by +`tumme-thumb-size', %f which is replaced by the file name of the +original image and %t which is replaced by the file name of the +thumbnail file." + :type 'string + :group 'tumme) + +(defcustom tumme-cmd-create-temp-image-program + "convert" + "*Executable used to create temporary image. +Used together with `tumme-cmd-create-temp-image-options'." + :type 'string + :group 'tumme) + +(defcustom tumme-cmd-create-temp-image-options + "%p -size %xx%y \"%f\" -resize %xx%y +profile \"*\" jpeg:\"%t\"" + "*Format of command used to create temporary image for display window. +Available options are %p which is replaced by +`tumme-cmd-create-temp-image-program', %x and %y which is replaced by +the calculated max size for x and y in the image display window, %f +which is replaced by the file name of the original image and %t which +is replaced by the file name of the temporary file." + :type 'string + :group 'tumme) + +(defcustom tumme-cmd-rotate-thumbnail-program + "mogrify" + "*Executable used to rotate thumbnail. +Used together with `tumme-cmd-rotate-thumbnail-options'." + :type 'string + :group 'tumme) + +(defcustom tumme-cmd-rotate-thumbnail-options + "%p -rotate %d \"%t\"" + "*Format of command used to rotate thumbnail image. +Available options are %p which is replaced by +`tumme-cmd-rotate-thumbnail-program', %d which is replaced by the +number of (positive) degrees to rotate the image, normally 90 or 270 +\(for 90 degrees right and left), %t which is replaced by the file name +of the thumbnail file." + :type 'string + :group 'tumme) + +(defcustom tumme-cmd-rotate-original-program + "jpegtran" + "*Executable used to rotate original image. +Used together with `tumme-cmd-rotate-original-options'." + :type 'string + :group 'tumme) + +(defcustom tumme-cmd-rotate-original-options + "%p -rotate %d -copy all \"%o\" > %t" + "*Format of command used to rotate original image. +Available options are %p which is replaced by +`tumme-cmd-rotate-original-program', %d which is replaced by the +number of (positive) degrees to rotate the image, normally 90 or +270 \(for 90 degrees right and left), %o which is replaced by the +original image file name and %t which is replaced by +`tumme-temp-image-file'" + :type 'string + :group 'tumme) + +(defcustom tumme-temp-rotate-image-file + "~/.tumme/.tumme_rotate_temp" + "*Temporary file for rotate operations." + :type 'string + :group 'tumme) + +(defcustom tumme-rotate-original-ask-before-overwrite t + "Confirm overwrite of original file after rotate operation. +If non-nil, ask user for confirmation before overwriting the +original file with `tumme-temp-rotate-image-file'." + :type 'boolean + :group 'tumme) + +(defcustom tumme-cmd-write-exif-data-program + "exiftool" + "*Program used to write EXIF data to image. +Used together with `tumme-cmd-write-exif-data-options'." + :type 'string + :group 'tumme) + +(defcustom tumme-cmd-write-exif-data-options + "%p -%t=\"%v\" \"%f\"" + "*Format of command used to write EXIF data. +Available options are %p which is replaced by +`tumme-cmd-write-exif-data-program', %f which is replaced by the +image file name, %t which is replaced by the tag name and %v +which is replaced by the tag value." + :type 'string + :group 'tumme) + +(defcustom tumme-cmd-read-exif-data-program + "exiftool" + "*Program used to read EXIF data to image. +Used together with `tumme-cmd-read-exif-data-program-options'." + :type 'string + :group 'tumme) + +(defcustom tumme-cmd-read-exif-data-options + "%p -s -s -s -%t \"%f\"" + "*Format of command used to read EXIF data. +Available options are %p which is replaced by +`tumme-cmd-write-exif-data-options', %f which is replaced +by the image file name and %t which is replaced by the tag name." + :type 'string + :group 'tumme) + +(defcustom tumme-gallery-hidden-tags + (list "private" "hidden" "pending") + "*List of \"hidden\" tags. +Used by `tumme-gallery-generate' to leave out \"hidden\" images." + :type '(repeat string) + :group 'tumme) + +(defcustom tumme-thumb-size 100 + "Size of thumbnails, in pixels." + :type 'integer + :group 'tumme) + +(defcustom tumme-thumb-relief 2 + "*Size of button-like border around thumbnails." + :type 'integer + :group 'tumme) + +(defcustom tumme-thumb-margin 2 + "*Size of the margin around thumbnails. +This is where you see the cursor." + :type 'integer + :group 'tumme) + +(defcustom tumme-line-up-method 'dynamic + "*Default method for line-up of thumbnails in thumbnail buffer. +Used by `tumme-display-thumbs' and other functions that needs to +line-up thumbnails. Dynamic means to use the available width of the +window containing the thumbnail buffer, Fixed means to use +`tumme-thumbs-per-row', Interactive is for asking the user, and No +line-up means that no automatic line-up will be done." + :type '(choice :tag "Default line-up method" + (const :tag "Dynamic" dynamic) + (const :tag "Fixed" fixed) + (const :tag "Interactive" interactive) + (const :tag "No line-up" none)) + :group 'tumme) + +(defcustom tumme-thumbs-per-row 3 + "*Number of thumbnails to display per row in thumb buffer." + :type 'integer + :group 'tumme) + +(defcustom tumme-display-window-width-correction 1 + "*Number to be used to correct image display window height. +Change if the default (1) does not work (i.e. if the image does not +completely fit)." + :type 'integer + :group 'tumme) + +(defcustom tumme-display-window-height-correction 0 + "*Number to be used to correct image display window height. +Use if the default (0) does not work (i.e. if the image does not +completely fit)." + :type 'integer + :group 'tumme) + +(defcustom tumme-track-movement nil + "The current state of the tracking and mirroring. +For more information, see the documentation for +`tumme-toggle-movement-tracking'." + :type 'boolean + :group 'tumme) + +(defcustom tumme-append-when-browsing nil + "Append thumbnails in thumbnail buffer when browsing. +If non-nil, using `tumme-next-line-and-display' and +`tumme-previous-line-and-display' will leave a trail of thumbnail +images in the thumbnail buffer. If you enable this and want to clean +the thumbnail buffer because it is filled with too many thumbmnails, +just call `tumme-display-thumb' to display only the image at point. +This value can be toggled using `tumme-toggle-append-browsing'." + :type 'boolean + :group 'tumme) + +(defcustom tumme-dired-disp-props t + "If non-nil, display properties for dired file when browsing. +Used by `tumme-next-line-and-display', +`tumme-previous-line-and-display' and `tumme-mark-and-display-next'. +If the database file is large, this can slow down image browsing in +dired and you might want to turn it off." + :type 'boolean + :group 'tumme) + +(defcustom tumme-display-properties-format "%b: %f (%t): %c" + "* Display format for thumbnail properties. +%b is replaced with associated dired buffer name, %f with file name +\(without path) of original image file, %t with the list of tags and %c +with the comment." + :type 'string + :group 'tumme) + +(defcustom tumme-external-viewer "qiv -t" + "*Name of external viewer. +Including parameters. Used when displaying original image from +`tumme-thumbnail-mode'." + :type 'string + :group 'tumme) + +(defcustom tumme-main-image-directory "~/pics/" + "*Name of main image directory, if any. +Used by `tumme-copy-with-exif-file-name'." + :type 'string + :group 'tumme) + +(defun tumme-insert-image (file type relief margin) + "Insert image FILE of image TYPE, using RELIEF and MARGIN, at point." + + (let ((i `(image :type ,type + :file ,file + :relief ,relief + :margin ,margin))) + (insert-image i))) + +(defun tumme-insert-thumbnail (file original-file-name + associated-dired-buffer) + "Insert thumbnail image FILE. +Add text properties ORIGINAL-FILE-NAME and ASSOCIATED-DIRED-BUFFER." + (let (beg end) + (setq beg (point)) + (tumme-insert-image file + 'jpeg + tumme-thumb-relief + tumme-thumb-margin) + (setq end (point)) + (add-text-properties + beg end + (list 'tumme-thumbnail t + 'original-file-name original-file-name + 'associated-dired-buffer associated-dired-buffer + 'tags (tumme-list-tags original-file-name) + 'mouse-face 'highlight + 'comment (tumme-get-comment original-file-name))))) + +(defun tumme-thumb-name (file) + "Return thumbnail file name for FILE. +Depending on the value of `tumme-thumbnail-storage', the file +name will vary. For central thumbnail file storage, make a +MD5-hash of the image file's directory name and add that to make +the thumbnail file name unique. For per-directory storage, just +add a subdirectory." + (let ((f (expand-file-name file)) + md5-hash) + (format "%s%s%s.thumb.%s" + (cond ((eq 'use-tumme-dir tumme-thumbnail-storage) + ;; Is MD5 hashes fast enough? The checksum of a + ;; thumbnail file name need not be that + ;; "cryptographically" good so a faster one could + ;; be used here. + (setq md5-hash (md5 (file-name-as-directory + (file-name-directory file)))) + (file-name-as-directory (expand-file-name tumme-dir))) + ((eq 'per-directory tumme-thumbnail-storage) + (format "%s.tumme/" + (file-name-directory f)))) + (file-name-sans-extension + (file-name-nondirectory f)) + (if md5-hash + (concat "_" md5-hash) + "") + (file-name-extension f)))) + +(defun tumme-create-thumb (original-file thumbnail-file) + "For ORIGINAL-FILE, create thumbnail image named THUMBNAIL-FILE." + (let* ((size (int-to-string tumme-thumb-size)) + (command + (format-spec + tumme-cmd-create-thumbnail-options + (list + (cons ?p tumme-cmd-create-thumbnail-program) + (cons ?s size) + (cons ?f original-file) + (cons ?t thumbnail-file)))) + thumbnail-dir) + (when (not (file-exists-p + (setq thumbnail-dir (file-name-directory thumbnail-file)))) + (message "Creating thumbnail directory.") + (make-directory thumbnail-dir)) + (shell-command command nil))) + +(defun tumme-next-line-and-display () + "Move to next dired line and display thumbnail image." + (interactive) + (dired-next-line 1) + (tumme-display-thumbs + t (or tumme-append-when-browsing nil)) + (if tumme-dired-disp-props + (tumme-dired-display-properties))) + +(defun tumme-previous-line-and-display () + "Move to previous dired line and display thumbnail image." + (interactive) + (dired-previous-line 1) + (tumme-display-thumbs + t (or tumme-append-when-browsing nil)) + (if tumme-dired-disp-props + (tumme-dired-display-properties))) + +(defun tumme-toggle-append-browsing () + "Toggle `tumme-append-when-browsing'." + (interactive) + (setq tumme-append-when-browsing + (not tumme-append-when-browsing)) + (message "Append browsing %s." + (if tumme-append-when-browsing + "on" + "off"))) + +(defun tumme-mark-and-display-next () + "Mark current file in dired and display next thumbnail image." + (interactive) + (dired-mark 1) + (tumme-display-thumbs + t (or tumme-append-when-browsing nil)) + (if tumme-dired-disp-props + (tumme-dired-display-properties))) + +(defun tumme-toggle-dired-display-properties () + "Toggle `tumme-dired-disp-props'." + (interactive) + (setq tumme-dired-disp-props + (not tumme-dired-disp-props)) + (message "Dired display properties %s." + (if tumme-dired-disp-props + "on" + "off"))) + +(defvar tumme-thumbnail-buffer "*tumme*" + "Tumme's thumbnail buffer.") + +(defun tumme-create-thumbnail-buffer () + "Create thumb buffer and set `tumme-thumbnail-mode'." + (let ((buf (get-buffer-create tumme-thumbnail-buffer))) + (save-excursion + (set-buffer buf) + (setq buffer-read-only t) + (if (not (eq major-mode 'tumme-thumbnail-mode)) + (tumme-thumbnail-mode))) + buf)) + +(defvar tumme-display-image-buffer "*tumme-display-image*" + "Where larger versions of the images are display.") + +(defun tumme-create-display-image-buffer () + "Create image display buffer and set `tumme-display-image-mode'." + (let ((buf (get-buffer-create tumme-display-image-buffer))) + (save-excursion + (set-buffer buf) + (setq buffer-read-only t) + (if (not (eq major-mode 'tumme-display-image-mode)) + (tumme-display-image-mode))) + buf)) + +(defun tumme-dired (dir &optional arg) + "Open directory DIR and create a default window configuration. + +Convenience command that: + + - Opens dired in folder DIR + - Splits windows in most useful (?) way + - Set `truncate-lines' to t + +If called with prefix argument ARG, skip splitting of windows." + (interactive "DDirectory: \nP") + (let ((buf (tumme-create-thumbnail-buffer)) + (buf2 (tumme-create-display-image-buffer))) + (dired dir) + (when (not arg) + (split-window-horizontally) + (setq truncate-lines t) + (save-excursion + (other-window 1) + (switch-to-buffer buf) + (split-window-vertically) + (other-window 1) + (switch-to-buffer buf2) + (other-window -2))))) + +(defun tumme-display-thumbs (&optional arg append) + "Display thumbnails of all marked files, in `tumme-thumbnail-buffer'. +If a thumbnail image does not exist for a file, it is created on the +fly. With prefix argument ARG, display only thumbnail for file at +point (this is useful if you have marked some files but want to show +another one). + +Recommended usage is to split the current frame horizontally so that +you have the dired buffer in the left window and the +`tumme-thumbnail-buffer' buffer in the right window. + +With optional argument APPEND, append thumbnail to thumbnail buffer +instead of erasing it first." + (interactive "P") + (let ((buf (tumme-create-thumbnail-buffer)) + curr-file thumb-name files count dired-buf beg) + (if arg + (setq files (list (dired-get-filename))) + (setq files (dired-get-marked-files))) + (setq dired-buf (current-buffer)) + (save-excursion + (set-buffer buf) + (let ((inhibit-read-only t)) + (if (not append) + (erase-buffer) + (goto-char (point-max))) + (mapcar + (lambda (curr-file) + (setq thumb-name (tumme-thumb-name curr-file)) + (if (and (not (file-exists-p thumb-name)) + (not (= 0 (tumme-create-thumb curr-file thumb-name)))) + (message "Thumb could not be created for file %s" curr-file) + (tumme-insert-thumbnail thumb-name curr-file dired-buf))) + files)) + (cond ((eq 'dynamic tumme-line-up-method) + (tumme-line-up-dynamic)) + ((eq 'fixed tumme-line-up-method) + (tumme-line-up)) + ((eq 'interactive tumme-line-up-method) + (tumme-line-up-interactive)) + ((eq 'none tumme-line-up-method) + nil) + (t + (tumme-line-up-dynamic)))))) + +(defun tumme-write-tag (files tag) + "For all FILES, writes TAG to the image database." + (save-excursion + (let (end buf) + (setq buf (find-file tumme-db-file)) + (if (not (listp files)) + (if (stringp files) + (setq files (list files)) + (error "Files must be a string or a list of strings!"))) + (mapcar + (lambda (file) + (goto-char (point-min)) + (if (search-forward-regexp + (format "^%s" file) nil t) + (progn + (end-of-line) + (setq end (point)) + (beginning-of-line) + (if (not (search-forward (format ";%s" tag) end t)) + (progn + (end-of-line) + (insert (format ";%s" tag))))) + (goto-char (point-max)) + (insert (format "\n%s;%s" file tag)))) + files) + (save-buffer) + (kill-buffer buf)))) + +(defun tumme-remove-tag (files tag) + "For all FILES, remove TAG from the image database." + (save-excursion + (let (end buf start) + (setq buf (find-file tumme-db-file)) + (if (not (listp files)) + (if (stringp files) + (setq files (list files)) + (error "Files must be a string or a list of strings!"))) + (mapcar + (lambda (file) + (goto-char (point-min)) + (if (search-forward-regexp + (format "^%s" file) nil t) + (progn + (end-of-line) + (setq end (point)) + (beginning-of-line) + (if (search-forward-regexp (format "\\(;%s\\)" tag) end t) + (progn + (delete-region (match-beginning 1) (match-end 1)) + ;; Check if file should still be in the database. If + ;; it has no tags or comments, it will be removed. + (end-of-line) + (setq end (point)) + (beginning-of-line) + (if (not (search-forward ";" end t)) + (progn + (kill-line 1) + ;; If on empty line at end of buffer + (if (and (eobp) + (looking-at "^$")) + (delete-backward-char 1))))))))) + files) + (save-buffer) + (kill-buffer buf)))) + +(defun tumme-list-tags (file) + "Read all tags for image FILE from the image database." + (save-excursion + (let (end buf (tags "")) + (setq buf (find-file tumme-db-file)) + (goto-char (point-min)) + (if (search-forward-regexp + (format "^%s" file) nil t) + (progn + (end-of-line) + (setq end (point)) + (beginning-of-line) + (if (search-forward ";" end t) + (if (search-forward "comment:" end t) + (if (search-forward ";" end t) + (setq tags (buffer-substring (point) end))) + (setq tags (buffer-substring (point) end)))))) + (kill-buffer buf) + (split-string tags ";")))) + +(defun tumme-tag-files (arg) + "Tag marked file(s) in dired. With prefix ARG, tag file at point." + (interactive "P") + (let ((tag (read-string "Tag to add: ")) + curr-file files) + (if arg + (setq files (dired-get-filename)) + (setq files (dired-get-marked-files))) + (tumme-write-tag files tag))) + +(defun tumme-tag-thumbnail () + "Tag current thumbnail." + (interactive) + (let ((tag (read-string "Tag to add: "))) + (tumme-write-tag (tumme-original-file-name) tag)) + (tumme-update-property + 'tags (tumme-list-tags (tumme-original-file-name)))) + +(defun tumme-tag-remove (arg) + "Remove tag for selected file(s). +With prefix argument ARG, remove tag from file at point." + (interactive "P") + (let ((tag (read-string "Tag to remove: ")) + files) + (if arg + (setq files (list (dired-get-filename))) + (setq files (dired-get-marked-files))) + (tumme-remove-tag files tag))) + +(defun tumme-tag-thumbnail-remove () + "Remove tag from thumbnail." + (interactive) + (let ((tag (read-string "Tag to remove: "))) + (tumme-remove-tag (tumme-original-file-name) tag)) + (tumme-update-property + 'tags (tumme-list-tags (tumme-original-file-name)))) + +(defun tumme-original-file-name () + "Get original file name for thumbnail or display image at point." + (get-text-property (point) 'original-file-name)) + +(defun tumme-associated-dired-buffer () + "Get associated dired buffer at point." + (get-text-property (point) 'associated-dired-buffer)) + +(defun tumme-get-buffer-window (buf) + "Return window where buffer BUF is." + (get-window-with-predicate + (lambda (window) + (equal (window-buffer window) buf)) + nil t)) + +(defun tumme-track-original-file () + "Track the original file in the associated dired buffer. +See documentation for `tumme-toggle-movement-tracking'. Interactive +use only useful if `tumme-track-movement' is nil." + (interactive) + (let ((old-buf (current-buffer)) + (dired-buf (tumme-associated-dired-buffer)) + (file-name (tumme-original-file-name))) + (if (and dired-buf file-name) + (progn + (setq file-name (file-name-nondirectory file-name)) + (set-buffer dired-buf) + (goto-char (point-min)) + (if (not (search-forward file-name nil t)) + (message "Could not track file") + (dired-move-to-filename) + (set-window-point + (tumme-get-buffer-window dired-buf) (point))) + (set-buffer old-buf))))) + +(defun tumme-toggle-movement-tracking () + "Turn on and off `tumme-track-movement'. +Tracking of the movements between thumbnail and dired buffer so that +they are \"mirrored\" in the dired buffer. When this is on, moving +around in the thumbnail or dired buffer will find the matching +position in the other buffer." + (interactive) + (setq tumme-track-movement (not tumme-track-movement)) + (message "Tracking %s" (if tumme-track-movement "on" "off"))) + +(defun tumme-track-thumbnail () + "Track current dired file's thumb in `tumme-thumbnail-buffer'. +This is almost the same as what `tumme-track-original-file' does, but +the other way around." + (let ((file (dired-get-filename)) + (old-buf (current-buffer)) + prop-val found) + (if (get-buffer tumme-thumbnail-buffer) + (progn + (set-buffer tumme-thumbnail-buffer) + (goto-char (point-min)) + (while (and (not (eobp)) + (not found)) + (if (and (setq prop-val + (get-text-property (point) 'original-file-name)) + (string= prop-val file)) + (setq found t)) + (if (not found) + (forward-char 1))) + (if found + (progn + (set-window-point + (tumme-thumbnail-window) (point)) + (tumme-display-thumb-properties))) + (set-buffer old-buf))))) + +(defun tumme-dired-next-line (&optional arg) + "Call `dired-next-line', then track thumbnail. +This can safely replace `dired-next-line'. With prefix argument, move +ARG lines." + (interactive "P") + (dired-next-line (or arg 1)) + (if tumme-track-movement + (tumme-track-thumbnail))) + +(defun tumme-dired-previous-line (&optional arg) + "Call `dired-previous-line', then track thumbnail. +This can safely replace `dired-previous-line'. With prefix argument, +move ARG lines." + (interactive "P") + (dired-previous-line (or arg 1)) + (if tumme-track-movement + (tumme-track-thumbnail))) + +(defun tumme-forward-char () + "Move to next image and display properties." + (interactive) + ;; Before we move, make sure that there is an image two positions + ;; forward. + (if (save-excursion + (forward-char 2) + (tumme-image-at-point-p)) + (progn + (forward-char) + (while (and (not (eobp)) + (not (tumme-image-at-point-p))) + (forward-char)) + (if tumme-track-movement + (tumme-track-original-file)))) + (tumme-display-thumb-properties)) + +(defun tumme-backward-char () + "Move to previous image and display properties." + (interactive) + (if (not (bobp)) + (progn + (backward-char) + (while (and (not (bobp)) + (not (tumme-image-at-point-p))) + (backward-char)) + (if tumme-track-movement + (tumme-track-original-file)))) + (tumme-display-thumb-properties)) + +(defun tumme-next-line () + "Move to next line and display properties." + (interactive) + (next-line 1) + ;; If we end up in an empty spot, back up to the next thumbnail. + (if (not (tumme-image-at-point-p)) + (tumme-backward-char)) + (if tumme-track-movement + (tumme-track-original-file)) + (tumme-display-thumb-properties)) + + +(defun tumme-previous-line () + "Move to previous line and display properties." + (interactive) + (previous-line 1) + ;; If we end up in an empty spot, back up to the next + ;; thumbnail. This should only happen if the user deleted a + ;; thumbnail and did not refresh, so it is not very common. But we + ;; can handle it in a good manner, so why not? + (if (not (tumme-image-at-point-p)) + (tumme-backward-char)) + (if tumme-track-movement + (tumme-track-original-file)) + (tumme-display-thumb-properties)) + +(defun tumme-format-properties-string (buf file props comment) + "Format display properties. +BUF is the associated dired buffer, FILE is the original image file +name, PROPS is a list of tags and COMMENT is the images files's +comment." + (format-spec + tumme-display-properties-format + (list + (cons ?b buf) + (cons ?f file) + (cons ?t (or (princ props) "")) + (cons ?c (or comment ""))))) + +(defun tumme-display-thumb-properties () + "Display thumbnail properties in the echo area." + (if (not (eobp)) + (let ((file-name (file-name-nondirectory (tumme-original-file-name))) + (dired-buf (buffer-name (tumme-associated-dired-buffer))) + (props (mapconcat + 'princ + (get-text-property (point) 'tags) + ", ")) + (comment (get-text-property (point) 'comment))) + (if file-name + (message + (tumme-format-properties-string + dired-buf + file-name + props + comment)))))) + +(defun tumme-dired-file-marked-p () + "Check whether file on current line is marked or not." + (save-excursion + (beginning-of-line) + (not (looking-at "^ .*$")))) + +(defun tumme-modify-mark-on-thumb-original-file (command) + "Modify mark in dired buffer. +This is quite ugly but I don't know how to implemented in a better +way. COMMAND is one of 'mark for marking file in dired, 'unmark for +unmarking file in dired or 'flag for flagging file for delete in +dired." + (let ((file-name (tumme-original-file-name)) + (dired-buf (tumme-associated-dired-buffer))) + (if (not (and dired-buf file-name)) + (message "No image, or image with correct properties, at point.") + (save-excursion + (message file-name) + (setq file-name (file-name-nondirectory file-name)) + (set-buffer dired-buf) + (goto-char (point-min)) + (if (search-forward file-name nil t) + (cond ((eq command 'mark) (dired-mark 1)) + ((eq command 'unmark) (dired-unmark 1)) + ((eq command 'toggle) + (if (tumme-dired-file-marked-p) + (dired-unmark 1) + (dired-mark 1))) + ((eq command 'flag) (dired-flag-file-deletion 1)))))))) + +(defun tumme-mark-thumb-original-file () + "Mark original image file in associated dired buffer." + (interactive) + (tumme-modify-mark-on-thumb-original-file 'mark) + (tumme-forward-char)) + +(defun tumme-unmark-thumb-original-file () + "Unmark original image file in associated dired buffer." + (interactive) + (tumme-modify-mark-on-thumb-original-file 'unmark) + (tumme-forward-char)) + +(defun tumme-flag-thumb-original-file () + "Flag original image file for deletion in associated dired buffer." + (interactive) + (tumme-modify-mark-on-thumb-original-file 'flag) + (tumme-forward-char)) + +(defun tumme-toggle-mark-thumb-original-file () + "Toggle mark on original image file in associated dired buffer." + (interactive) + (tumme-modify-mark-on-thumb-original-file 'toggle)) + +(defun tumme-jump-original-dired-buffer () + "Jump to the dired buffer associated with the current image file. +You probably want to use this together with +`tumme-track-original-file'." + (interactive) + (let ((buf (tumme-associated-dired-buffer)) + window frame) + (setq window (tumme-get-buffer-window buf)) + (if window + (progn + (if (not (equal (selected-frame) (setq frame (window-frame window)))) + (select-frame-set-input-focus frame)) + (select-window window)) + (message "Associated dired buffer not visible")))) + +(defun tumme-jump-thumbnail-buffer () + "Jump to thumbnail buffer." + (interactive) + (let ((window (tumme-thumbnail-window)) + frame) + (if window + (progn + (if (not (equal (selected-frame) (setq frame (window-frame window)))) + (select-frame-set-input-focus frame)) + (select-window window)) + (message "Thumbnail buffer not visible")))) + +(defvar tumme-thumbnail-mode-map (make-sparse-keymap) + "Keymap for `tumme-thumbnail-mode'.") + +(defvar tumme-thumbnail-mode-line-up-map (make-sparse-keymap) + "Keymap for line-up commands in `tumme-thumbnail-mode'.") + +(defvar tumme-thumbnail-mode-tag-map (make-sparse-keymap) + "Keymap for tag commands in `tumme-thumbnail-mode'.") + +(defun tumme-define-thumbnail-mode-keymap () + "Define keymap for `tumme-thumbnail-mode'." + + ;; Keys + (define-key tumme-thumbnail-mode-map [right] 'tumme-forward-char) + (define-key tumme-thumbnail-mode-map [left] 'tumme-backward-char) + (define-key tumme-thumbnail-mode-map [up] 'tumme-previous-line) + (define-key tumme-thumbnail-mode-map [down] 'tumme-next-line) + (define-key tumme-thumbnail-mode-map "\C-f" 'tumme-forward-char) + (define-key tumme-thumbnail-mode-map "\C-b" 'tumme-backward-char) + (define-key tumme-thumbnail-mode-map "\C-p" 'tumme-previous-line) + (define-key tumme-thumbnail-mode-map "\C-n" 'tumme-next-line) + + (define-key tumme-thumbnail-mode-map "d" 'tumme-flag-thumb-original-file) + (define-key tumme-thumbnail-mode-map [delete] + 'tumme-flag-thumb-original-file) + (define-key tumme-thumbnail-mode-map "m" 'tumme-mark-thumb-original-file) + (define-key tumme-thumbnail-mode-map "u" 'tumme-unmark-thumb-original-file) + (define-key tumme-thumbnail-mode-map "." 'tumme-track-original-file) + (define-key tumme-thumbnail-mode-map [tab] 'tumme-jump-original-dired-buffer) + + ;; add line-up map + (define-key tumme-thumbnail-mode-map "g" tumme-thumbnail-mode-line-up-map) + + ;; map it to "g" so that the user can press it more quickly + (define-key tumme-thumbnail-mode-line-up-map "g" 'tumme-line-up-dynamic) + ;; "f" for "fixed" number of thumbs per row + (define-key tumme-thumbnail-mode-line-up-map "f" 'tumme-line-up) + ;; "i" for "interactive" + (define-key tumme-thumbnail-mode-line-up-map "i" 'tumme-line-up-interactive) + + ;; add tag map + (define-key tumme-thumbnail-mode-map "t" tumme-thumbnail-mode-tag-map) + + ;; map it to "t" so that the user can press it more quickly + (define-key tumme-thumbnail-mode-tag-map "t" 'tumme-tag-thumbnail) + ;; "r" for "remove" + (define-key tumme-thumbnail-mode-tag-map "r" 'tumme-tag-thumbnail-remove) + + (define-key tumme-thumbnail-mode-map "\C-m" + 'tumme-display-thumbnail-original-image) + (define-key tumme-thumbnail-mode-map [C-return] + 'tumme-thumbnail-display-external) + + (define-key tumme-thumbnail-mode-map "l" 'tumme-rotate-thumbnail-left) + (define-key tumme-thumbnail-mode-map "r" 'tumme-rotate-thumbnail-right) + + (define-key tumme-thumbnail-mode-map "L" 'tumme-rotate-original-left) + (define-key tumme-thumbnail-mode-map "R" 'tumme-rotate-original-right) + + (define-key tumme-thumbnail-mode-map "D" 'tumme-thumbnail-set-image-description) + + (define-key tumme-thumbnail-mode-map "\C-d" 'tumme-delete-char) + (define-key tumme-thumbnail-mode-map " " + 'tumme-display-next-thumbnail-original) + (define-key tumme-thumbnail-mode-map + (kbd "DEL") 'tumme-display-previous-thumbnail-original) + (define-key tumme-thumbnail-mode-map "c" 'tumme-comment-thumbnail) + (define-key tumme-thumbnail-mode-map "q" 'tumme-kill-buffer-and-window) + + ;; Mouse + (define-key tumme-thumbnail-mode-map [mouse-2] 'tumme-mouse-display-image) + (define-key tumme-thumbnail-mode-map [mouse-1] 'tumme-mouse-select-thumbnail) + + ;; Seems I must first set C-down-mouse-1 to undefined, or else it + ;; will trigger the buffer menu. If I try to instead bind + ;; C-down-mouse-1 to `tumme-mouse-toggle-mark', I get a message + ;; about C-mouse-1 not being defined afterwards. Annoying, but I + ;; probably do not completely understand mouse events. + + (define-key tumme-thumbnail-mode-map [C-down-mouse-1] 'undefined) + (define-key tumme-thumbnail-mode-map [C-mouse-1] 'tumme-mouse-toggle-mark) + + ;; Menu + (define-key tumme-thumbnail-mode-map [menu-bar tumme] + (cons "Tumme" (make-sparse-keymap "Tumme"))) + + (define-key tumme-thumbnail-mode-map + [menu-bar tumme tumme-kill-buffer-and-window] + '("Quit" . tumme-kill-buffer-and-window)) + + (define-key tumme-thumbnail-mode-map + [menu-bar tumme tumme-delete-char] + '("Delete thumbnail from buffer" . tumme-delete-char)) + + (define-key tumme-thumbnail-mode-map + [menu-bar tumme tumme-tag-thumbnail-remove] + '("Remove tag from thumbnail" . tumme-tag-thumbnail-remove)) + + (define-key tumme-thumbnail-mode-map + [menu-bar tumme tumme-tag-thumbnail] + '("Tag thumbnail" . tumme-tag-thumbnail)) + + (define-key tumme-thumbnail-mode-map + [menu-bar tumme tumme-comment-thumbnail] + '("Comment thumbnail" . tumme-comment-thumbnail)) + + (define-key tumme-thumbnail-mode-map + [menu-bar tumme tumme-refresh-thumb] + '("Refresh thumb" . tumme-refresh-thumb)) + (define-key tumme-thumbnail-mode-map + [menu-bar tumme tumme-line-up-dynamic] + '("Dynamic line up" . tumme-line-up-dynamic)) + (define-key tumme-thumbnail-mode-map + [menu-bar tumme tumme-line-up] + '("Line up thumbnails" . tumme-line-up)) + + (define-key tumme-thumbnail-mode-map + [menu-bar tumme tumme-rotate-thumbnail-left] + '("Rotate thumbnail left" . tumme-rotate-thumbnail-left)) + (define-key tumme-thumbnail-mode-map + [menu-bar tumme tumme-rotate-thumbnail-right] + '("Rotate thumbnail right" . tumme-rotate-thumbnail-right)) + + (define-key tumme-thumbnail-mode-map + [menu-bar tumme tumme-rotate-original-left] + '("Rotate original left" . tumme-rotate-original-left)) + (define-key tumme-thumbnail-mode-map + [menu-bar tumme tumme-rotate-original-right] + '("Rotate original right" . tumme-rotate-original-right)) + + (define-key tumme-thumbnail-mode-map + [menu-bar tumme tumme-toggle-movement-tracking] + '("Toggle movement tracking on/off" . tumme-toggle-movement-tracking)) + + (define-key tumme-thumbnail-mode-map + [menu-bar tumme tumme-jump-original-dired-buffer] + '("Jump to dired buffer" . tumme-jump-original-dired-buffer)) + (define-key tumme-thumbnail-mode-map + [menu-bar tumme tumme-track-original-file] + '("Track original" . tumme-track-original-file)) + + (define-key tumme-thumbnail-mode-map + [menu-bar tumme tumme-flag-thumb-original-file] + '("Flag original for deletion" . tumme-flag-thumb-original-file)) + (define-key tumme-thumbnail-mode-map + [menu-bar tumme tumme-unmark-thumb-original-file] + '("Unmark original" . tumme-unmark-thumb-original-file)) + (define-key tumme-thumbnail-mode-map + [menu-bar tumme tumme-mark-thumb-original-file] + '("Mark original" . tumme-mark-thumb-original-file)) + + (define-key tumme-thumbnail-mode-map + [menu-bar tumme tumme-thumbnail-display-external] + '("Display in external viewer" . tumme-thumbnail-display-external)) + (define-key tumme-thumbnail-mode-map + [menu-bar tumme tumme-display-thumbnail-original-image] + '("Display image" . tumme-display-thumbnail-original-image))) + +(defvar tumme-display-image-mode-map (make-sparse-keymap) + "Keymap for `tumme-display-image-mode'.") + +(defun tumme-define-display-image-mode-keymap () + "Define keymap for `tumme-display-image-mode'." + + ;; Keys + (define-key tumme-display-image-mode-map "q" 'tumme-kill-buffer-and-window) + + (define-key tumme-display-image-mode-map "f" + 'tumme-display-current-image-full) + + (define-key tumme-display-image-mode-map "s" + 'tumme-display-current-image-sized) + + ;; Menu + (define-key tumme-display-image-mode-map [menu-bar tumme] + (cons "Tumme" (make-sparse-keymap "Tumme"))) + + (define-key tumme-display-image-mode-map + [menu-bar tumme tumme-kill-buffer-and-window] + '("Quit" . tumme-kill-buffer-and-window)) + + (define-key tumme-display-image-mode-map + [menu-bar tumme tumme-display-current-image-sized] + '("Display original, sized to fit" . tumme-display-current-image-sized)) + + (define-key tumme-display-image-mode-map + [menu-bar tumme tumme-display-current-image-full] + '("Display original, full size" . tumme-display-current-image-full)) + + ) + +(defun tumme-display-current-image-full () + "Display current image in full size." + (interactive) + (let ((file (tumme-original-file-name))) + (if file + (progn + (tumme-display-image file t) + (message "Full size image displayed")) + (error "No original file name at point")))) + +(defun tumme-display-current-image-sized () + "Display current image in sized to fit window dimensions." + (interactive) + (let ((file (tumme-original-file-name))) + (if file + (progn + (tumme-display-image file) + (message "Full size image displayed")) + (error "No original file name at point")))) + +(define-derived-mode tumme-thumbnail-mode + fundamental-mode "tumme-thumbnail" + "Browse and manipulate thumbnail images using dired. +Use `tumme-dired' and `tumme-setup-dired-keybindings' to get a +nice setup to start with." + (tumme-define-thumbnail-mode-keymap) + (message "tumme-thumbnail-mode enabled")) + +(define-derived-mode tumme-display-image-mode + fundamental-mode "tumme-image-display" + "Mode for displaying and manipulating original image. +Resized or in full-size." + (tumme-define-display-image-mode-keymap) + (message "tumme-display-image-mode enabled")) + +(defun tumme-setup-dired-keybindings () + "Setup easy-to-use keybindings for the commands to be used in dired mode. +Note that n, p and <down> and <up> will be hijacked and bound to +`tumme-dired-x-line'." + (interactive) + + ;; Hijack previous and next line movement. Let C-p and C-b be + ;; though... + + (define-key dired-mode-map "p" 'tumme-dired-previous-line) + (define-key dired-mode-map "n" 'tumme-dired-next-line) + (define-key dired-mode-map [up] 'tumme-dired-previous-line) + (define-key dired-mode-map [down] 'tumme-dired-next-line) + + (define-key dired-mode-map (kbd "C-S-n") 'tumme-next-line-and-display) + (define-key dired-mode-map (kbd "C-S-p") 'tumme-previous-line-and-display) + (define-key dired-mode-map (kbd "C-S-m") 'tumme-mark-and-display-next) + + (define-key dired-mode-map "\C-td" 'tumme-display-thumbs) + (define-key dired-mode-map "\C-tt" 'tumme-tag-files) + (define-key dired-mode-map "\C-tr" 'tumme-tag-remove) + (define-key dired-mode-map [tab] 'tumme-jump-thumbnail-buffer) + (define-key dired-mode-map "\C-ti" 'tumme-display-dired-image) + (define-key dired-mode-map "\C-tx" 'tumme-dired-display-external) + (define-key dired-mode-map "\C-ta" 'tumme-display-thumbs-append) + (define-key dired-mode-map "\C-t." 'tumme-display-thumb) + (define-key dired-mode-map "\C-tc" 'tumme-dired-comment-files) + (define-key dired-mode-map "\C-tf" 'tumme-mark-tagged-files) + + ;; Menu for dired + (define-key dired-mode-map [menu-bar tumme] + (cons "Tumme" (make-sparse-keymap "Tumme"))) + + (define-key dired-mode-map [menu-bar tumme tumme-copy-with-exif-file-name] + '("Copy with EXIF file name" . tumme-copy-with-exif-file-name)) + + (define-key dired-mode-map [menu-bar tumme tumme-dired-comment-files] + '("Comment files" . tumme-dired-comment-files)) + + (define-key dired-mode-map [menu-bar tumme tumme-mark-tagged-files] + '("Mark tagged files" . tumme-mark-tagged-files)) + + (define-key dired-mode-map [menu-bar tumme tumme-tag-remove] + '("Remove tag from files" . tumme-tag-remove)) + + (define-key dired-mode-map [menu-bar tumme tumme-tag-files] + '("Tag files" . tumme-tag-files)) + + (define-key dired-mode-map [menu-bar tumme tumme-jump-thumbnail-buffer] + '("Jump to thumbnail buffer" . tumme-jump-thumbnail-buffer)) + + (define-key dired-mode-map [menu-bar tumme tumme-toggle-movement-tracking] + '("Toggle movement tracking" . tumme-toggle-movement-tracking)) + + (define-key dired-mode-map + [menu-bar tumme tumme-toggle-append-browsing] + '("Toggle append browsing" . tumme-toggle-append-browsing)) + + (define-key dired-mode-map + [menu-bar tumme tumme-toggle-disp-props] + '("Toggle display properties" . tumme-toggle-dired-display-properties)) + + (define-key dired-mode-map + [menu-bar tumme tumme-dired-display-external] + '("Display in external viewer" . tumme-dired-display-external)) + (define-key dired-mode-map + [menu-bar tumme tumme-display-dired-image] + '("Display image" . tumme-display-dired-image)) + (define-key dired-mode-map + [menu-bar tumme tumme-display-thumb] + '("Display this thumbnail" . tumme-display-thumb)) + (define-key dired-mode-map + [menu-bar tumme tumme-display-thumbs-append] + '("Display thumbnails append" . tumme-display-thumbs-append)) + (define-key dired-mode-map + [menu-bar tumme tumme-display-thumbs] + '("Display thumbnails" . tumme-display-thumbs)) + + (define-key dired-mode-map + [menu-bar tumme tumme-create-thumbs] + '("Create thumbnails for marked files" . tumme-create-thumbs)) + + (define-key dired-mode-map + [menu-bar tumme tumme-mark-and-display-next] + '("Mark and display next" . tumme-mark-and-display-next)) + (define-key dired-mode-map + [menu-bar tumme tumme-previous-line-and-display] + '("Display thumb for previous file" . tumme-previous-line-and-display)) + (define-key dired-mode-map + [menu-bar tumme tumme-next-line-and-display] + '("Display thumb for next file" . tumme-next-line-and-display))) + +(defun tumme-create-thumbs (&optional arg) + "Create thumbnail images for all marked files in dired. +With prefix argument ARG, create thumbnails even if they already exist +\(i.e. use this to refresh your thumbnails)." + (interactive "P") + (let (curr-file thumb-name files count) + (setq files (dired-get-marked-files)) + (mapcar + (lambda (curr-file) + (setq thumb-name (tumme-thumb-name curr-file)) + ;; If the user overrides the exist check, we must clear the + ;; image cache so that if the user wants to display the + ;; thumnail, it is not fetched from cache. + (if arg + (clear-image-cache)) + (if (or (not (file-exists-p thumb-name)) + arg) + (if (not (= 0 (tumme-create-thumb curr-file + (tumme-thumb-name curr-file)))) + (error "Thumb could not be created")))) + files))) + +(defvar tumme-slideshow-timer nil + "Slideshow timer.") + +(defvar tumme-slideshow-count 0 + "Keeping track on number of images in slideshow.") + +(defvar tumme-slideshow-times 0 + "Number of pictures to display in slideshow.") + +(defun tumme-slideshow-step () + "Step to next file, if `tumme-slideshow-times' has not been reached." + (if (< tumme-slideshow-count tumme-slideshow-times) + (progn + (message "%s" (1+ tumme-slideshow-count)) + (setq tumme-slideshow-count (1+ tumme-slideshow-count)) + (tumme-next-line-and-display)) + (tumme-slideshow-stop))) + +(defun tumme-slideshow-start () + "Start slideshow. +Ask user for number of images to show and the delay in between." + (interactive) + (setq tumme-slideshow-count 0) + (setq tumme-slideshow-times (string-to-number (read-string "How many: "))) + (let ((repeat (string-to-number + (read-string + "Delay, in seconds. Decimals are accepted : " "1")))) + (setq tumme-slideshow-timer + (run-with-timer + 0 repeat + 'tumme-slideshow-step)))) + +(defun tumme-slideshow-stop () + "Cancel slideshow." + (interactive) + (cancel-timer tumme-slideshow-timer)) + +(defun tumme-delete-char () + "Remove current thumbnail from thumbnail buffer and line up." + (interactive) + (let ((inhibit-read-only t)) + (delete-char 1) + (if (looking-at " ") + (delete-char 1)))) + +(defun tumme-display-thumbs-append () + "Append thumbnails to `tumme-thumbnail-buffer'." + (interactive) + (tumme-display-thumbs nil t)) + +(defun tumme-display-thumb () + "Shorthard for `tumme-display-thumbs' with prefix argument." + (interactive) + (tumme-display-thumbs t)) + +(defun tumme-line-up () + "Line up thumbnails according to `tumme-thumbs-per-row'. +See also `tumme-line-up-dynamic'." + (interactive) + (let ((inhibit-read-only t)) + (goto-char (point-min)) + (while (and (not (tumme-image-at-point-p)) + (not (eobp))) + (delete-char 1)) + (while (not (eobp)) + (forward-char) + (while (and (not (tumme-image-at-point-p)) + (not (eobp))) + (delete-char 1))) + (goto-char (point-min)) + (let ((count 0)) + (while (not (eobp)) + (forward-char) + (if (= tumme-thumbs-per-row 1) + (insert "\n") + (insert " ") + (setq count (1+ count)) + (if (= count (- tumme-thumbs-per-row 1)) + (progn + (forward-char) + (insert "\n") + (setq count 0)))))) + (goto-char (point-min)))) + +(defun tumme-line-up-dynamic () + "Line up thumbnails images dynamically. +Calculate how many thumbnails that fits." + (interactive) + (let* ((char-width (frame-char-width)) + (width (tumme-window-width-pixels (tumme-thumbnail-window))) + (tumme-thumbs-per-row + (/ width + (+ (* 2 tumme-thumb-relief) + (* 2 tumme-thumb-margin) + tumme-thumb-size char-width)))) + (tumme-line-up))) + +(defun tumme-line-up-interactive () + "Line up thumbnails interactively. +Ask user how many thumbnails that should be displayed per row." + (interactive) + (let ((tumme-thumbs-per-row + (string-to-number (read-string "How many thumbs per row: ")))) + (if (not (> tumme-thumbs-per-row 0)) + (message "Number must be greater than 0") + (tumme-line-up)))) + +(defun tumme-thumbnail-display-external () + "Display original image for thumbnail at point using external viewer." + + (interactive) + (let ((file (tumme-original-file-name))) + (if (not (tumme-image-at-point-p)) + (message "No thumbnail at point") + (if (not file) + (message "No original file name found") + (shell-command (format "%s \"%s\"" + tumme-external-viewer + file)))))) + +(defun tumme-dired-display-external () + "Display file at point using an external viewer." + (interactive) + (let ((file (dired-get-filename))) + (shell-command (format "%s \"%s\"" + tumme-external-viewer + file)))) + +(defun tumme-window-width-pixels (window) + "Calculate WINDOW width in pixels." + (* (window-width window) (frame-char-width))) + +(defun tumme-window-height-pixels (window) + "Calculate WINDOW height in pixels." + ;; Note: The mode-line consumes one line + (* (- (window-height window) 1) (frame-char-height))) + +(defun tumme-display-window () + "Return window where `tumme-display-image-buffer' is visible." + (get-window-with-predicate + (lambda (window) + (equal (buffer-name (window-buffer window)) tumme-display-image-buffer)) + nil t)) + +(defun tumme-thumbnail-window () + "Return window where `tumme-thumbnail-buffer' is visible." + (get-window-with-predicate + (lambda (window) + (equal (buffer-name (window-buffer window)) tumme-thumbnail-buffer)) + nil t)) + +(defun tumme-associated-dired-buffer-window () + "Return window where associated dired buffer is visible." + (let (buf) + (if (tumme-image-at-point-p) + (progn + (setq buf (tumme-associated-dired-buffer)) + (get-window-with-predicate + (lambda (window) + (equal (window-buffer window) buf)))) + (error "No thumbnail image at point")))) + +(defun tumme-display-window-width () + "Return width, in pixels, of tumme's image display window." + (- (tumme-window-width-pixels (tumme-display-window)) + tumme-display-window-width-correction)) + +(defun tumme-display-window-height () + "Return height, in pixels, of tumme's image display window." + (- (tumme-window-height-pixels (tumme-display-window)) + tumme-display-window-height-correction)) + +(defun tumme-display-image (file &optional original-size) + "Display image FILE in image buffer. +Use this when you want to display the image, semi sized, in a window +next to the thumbnail window - typically a three-window configuration +with dired to the left, thumbnail window to the upper right and image +window to the lower right. The image is sized to fit the display +window (using a temporary file, don't worry). Because of this, it +will not be as quick as opening it directly, but on most modern +systems it should feel snappy enough. + +If optional argument ORIGINAL-SIZE is non-nil, display image in its +original size." + (let ((new-file (expand-file-name tumme-temp-image-file)) + size-x size-y command ret) + (setq file (expand-file-name file)) + (if (not original-size) + (progn + (setq size-x (tumme-display-window-width)) + (setq size-y (tumme-display-window-height)) + (setq command + (format-spec + tumme-cmd-create-temp-image-options + (list + (cons ?p tumme-cmd-create-temp-image-program) + (cons ?x size-x) + (cons ?y size-y) + (cons ?f file) + (cons ?t new-file)))) + (setq ret (shell-command command nil)) + (if (not (= 0 ret)) + (error "Could not resize image"))) + (copy-file file new-file t)) + (save-excursion + (set-buffer (tumme-create-display-image-buffer)) + (let ((inhibit-read-only t)) + (erase-buffer) + (clear-image-cache) + (tumme-insert-image tumme-temp-image-file 'jpeg 0 0) + (goto-char (point-min)) + (tumme-update-property 'original-file-name file))))) + +(defun tumme-display-thumbnail-original-image (&optional arg) + "Display current thumbnail's original image in display buffer. +See documentation for `tumme-display-image' for more information. +With prefix argument ARG, display image in its original size." + (interactive "P") + (let ((file (tumme-original-file-name))) + (if (not (string-equal major-mode "tumme-thumbnail-mode")) + (message "Not in tumme-thumbnail-mode") + (if (not (tumme-image-at-point-p)) + (message "No thumbnail at point") + (if (not file) + (message "No original file name found") + (tumme-display-image file arg)))))) + +(defun tumme-display-dired-image (&optional arg) + "Display current image file. +See documentation for `tumme-display-image' for more information. +With prefix argument ARG, display image in its original size." + (interactive "P") + (tumme-display-image (dired-get-filename) arg)) + +(defun tumme-image-at-point-p () + "Return true if there is a tumme thumbnail at point." + (get-text-property (point) 'tumme-thumbnail)) + +(defun tumme-rotate-thumbnail (degrees) + "Rotate thumbnail DEGREES degrees." + (if (not (tumme-image-at-point-p)) + (message "No thumbnail at point") + (let ((file (tumme-thumb-name (tumme-original-file-name))) + command) + (setq command (format-spec + tumme-cmd-rotate-thumbnail-options + (list + (cons ?p tumme-cmd-rotate-thumbnail-program) + (cons ?d degrees) + (cons ?t (expand-file-name file))))) + (shell-command command nil) + ;; Clear the cache to refresh image. I wish I could just refresh + ;; the current file but I do not know how to do that. Yet... + (clear-image-cache)))) + +(defun tumme-rotate-thumbnail-left () + "Rotate thumbnail left (counter clockwise) 90 degrees. +The result of the rotation is displayed in the image display area +and a confirmation is needed before the original image files is +overwritten. This confirmation can be turned off using +`tumme-rotate-original-ask-before-overwrite'." + (interactive) + (tumme-rotate-thumbnail "270")) + +(defun tumme-rotate-thumbnail-right () + "Rotate thumbnail counter right (clockwise) 90 degrees. +The result of the rotation is displayed in the image display area +and a confirmation is needed before the original image files is +overwritten. This confirmation can be turned off using +`tumme-rotate-original-ask-before-overwrite'." + (interactive) + (tumme-rotate-thumbnail "90")) + +(defun tumme-refresh-thumb () + "Force creation of new image for current thumbnail." + (interactive) + (let ((file (tumme-original-file-name))) + (clear-image-cache) + (tumme-create-thumb file (tumme-thumb-name file)))) + +(defun tumme-rotate-original (degrees) + "Rotate original image DEGREES degrees." + (if (not (tumme-image-at-point-p)) + (message "No image at point") + (let ((file (tumme-original-file-name)) + command temp-file) + (if (not (string-match "\.[jJ][pP[eE]?[gG]$" file)) + (error "Only JPEG images can be rotated!")) + (setq command (format-spec + tumme-cmd-rotate-original-options + (list + (cons ?p tumme-cmd-rotate-original-program) + (cons ?d degrees) + (cons ?o (expand-file-name file)) + (cons ?t tumme-temp-rotate-image-file)))) + (if (not (= 0 (shell-command command nil))) + (error "Could not rotate image") + (tumme-display-image tumme-temp-rotate-image-file) + (if (or (and tumme-rotate-original-ask-before-overwrite + (y-or-n-p "Rotate to temp file OK. Overwrite original image? ")) + (not tumme-rotate-original-ask-before-overwrite)) + (progn + (copy-file tumme-temp-rotate-image-file file t) + (tumme-refresh-thumb)) + (tumme-display-image file)))))) + +(defun tumme-rotate-original-left () + "Rotate original image left (counter clockwise) 90 degrees." + (interactive) + (tumme-rotate-original "270")) + +(defun tumme-rotate-original-right () + "Rotate original image right (clockwise) 90 degrees." + (interactive) + (tumme-rotate-original "90")) + +(defun tumme-get-exif-file-name (file) + "Use the image's EXIF information to return a unique file name. +The file name should be unique as long as you do not take more than +one picture per second. The original file name is suffixed at the end +for traceability. The format of the returned file name is +YYYY_MM_DD_HH_MM_DD_ORIG_FILE_NAME.jpg. Used from +`tumme-copy-with-exif-file-name'." + (let (data no-exif-data-found) + (if (not (string-match "\.[Jj][Pp][Ee]?[Gg]$" (expand-file-name file))) + (progn + (setq no-exif-data-found t) + (setq data + (format-time-string + "%Y:%m:%d %H:%M:%S" + (nth 5 (file-attributes (expand-file-name file)))))) + (setq data (tumme-get-exif-data (expand-file-name file) "DateTimeOriginal"))) + (while (string-match "[ :]" data) + (setq data (replace-match "_" nil nil data))) + (format "%s%s%s" data + (if no-exif-data-found + "_noexif_" + "_") + (file-name-nondirectory file)))) + +(defun tumme-thumbnail-set-image-description () + "Set the ImageDescription EXIF tag for the original image. +If the image already has a value for this tag, it is used as the +default value at the prompt." + (interactive) + (if (not (tumme-image-at-point-p)) + (message "No thumbnail at point") + (let* ((file (tumme-original-file-name)) + (old-value (tumme-get-exif-data file "ImageDescription"))) + (if (eq 0 + (tumme-set-exif-data file "ImageDescription" + (read-string "Value of ImageDescription: " old-value))) + (message "Successfully wrote ImageDescription tag.") + (error "Could not write ImageDescription tag"))))) + +(defun tumme-set-exif-data (file tag-name tag-value) + "In FILE, set EXIF tag TAG-NAME to value TAG-VALUE." + (let (command) + (setq command (format-spec + tumme-cmd-write-exif-data-options + (list + (cons ?p tumme-cmd-write-exif-data-program) + (cons ?f (expand-file-name file)) + (cons ?t tag-name) + (cons ?v tag-value)))) + (shell-command command nil))) + +(defun tumme-get-exif-data (file tag-name) + "From FILE, return EXIF tag TAG-NAME." + (let ((buf (get-buffer-create "*tumme-get-exif-data*")) + command tag-value) + (setq command (format-spec + tumme-cmd-read-exif-data-options + (list + (cons ?p tumme-cmd-read-exif-data-program) + (cons ?f file) + (cons ?t tag-name)))) + (save-excursion + (set-buffer buf) + (delete-region (point-min) (point-max)) + (if (not (eq (shell-command command buf) 0)) + (error "Could not get EXIF tag") + (goto-char (point-min)) + ;; Clean buffer from newlines and carriage returns before + ;; getting final info + (while (search-forward-regexp "[\n\r]" nil t) + (replace-match "" nil t)) + (setq tag-value (buffer-substring (point-min) (point-max))))) + tag-value)) + +(defun tumme-copy-with-exif-file-name () + "Copy file with unique name to main image directory. +Copy current or all marked files in dired to a new file in your main +image directory, using a file name generated by +`tumme-get-exif-file-name'. This might or might not be useful for +other people, but I use it each time I fetch images from my digital +camera, for copying the images into my main image directory. + +Typically I open up the folder where I store my incoming digital +images, with file names like dscn0319.jpg, dscn0320.jpg etc., mark the +files I want to copy into my main image directory, and execute this +function. The result is a couple of new files in +`tumme-main-image-directory' called 2005_05_08_12_52_00_dscn0319.jpg, +2005_05_08_14_27_45_dscn0320.jpg etc. + +When the images are safely in my main image directory I start to +browse and tag them using rest of the functionality in `tumme'." + (interactive) + (let (new-name + (files (dired-get-marked-files))) + (mapcar + (lambda (curr-file) + (setq new-name + (format "%s/%s" + (file-name-as-directory + (expand-file-name tumme-main-image-directory)) + (tumme-get-exif-file-name curr-file))) + (message "Copying %s to %s" curr-file new-name) + (copy-file curr-file new-name)) + files))) + +(defun tumme-display-next-thumbnail-original () + "In thubnail buffer, move to next thumbnail and display the image." + (interactive) + (tumme-forward-char) + (tumme-display-thumbnail-original-image)) + +(defun tumme-display-previous-thumbnail-original () + "Move to previous thumbnail and display image." + + (interactive) + (tumme-backward-char) + (tumme-display-thumbnail-original-image)) + +(defun tumme-write-comment (file comment) + "For FILE, write comment COMMENT in database." + (save-excursion + (let (end buf comment-beg + (base-name (file-name-nondirectory file))) + (setq buf (find-file tumme-db-file)) + (goto-char (point-min)) + (if (search-forward-regexp + (format "^%s" base-name) nil t) + (progn + (end-of-line) + (setq end (point)) + (beginning-of-line) + ;; Delete old comment, if any + (cond ((search-forward ";comment:" end t) + (setq comment-beg (match-beginning 0)) + ;; Any tags after the comment? + (if (search-forward ";" end t) + (setq comment-end (- (point) 1)) + (setq comment-end end)) + ;; Delete comment tag and comment + (delete-region comment-beg comment-end))) + ;; Insert new comment + (beginning-of-line) + (if (not (search-forward ";" end t)) + (progn + (end-of-line) + (insert ";"))) + (insert (format "comment:%s;" comment))) + ;; File does not exist in databse - add it. + (goto-char (point-max)) + (insert (format "\n%s;comment:%s" base-name comment))) + (save-buffer) + (kill-buffer buf)))) + +(defun tumme-update-property (prop value) + "Update text property PROP with value VALUE at point." + (let ((inhibit-read-only t)) + (put-text-property + (point) (1+ (point)) + prop + value))) + +(defun tumme-dired-comment-files () + "Add comment to current or marked files in dired." + (interactive) + (let ((files (dired-get-marked-files)) + (comment (tumme-read-comment))) + (mapcar + (lambda (curr-file) + (tumme-write-comment curr-file comment)) + files))) + +(defun tumme-comment-thumbnail () + "Add comment to current thumbnail in thumbnail buffer." + (interactive) + (let* ((file (tumme-original-file-name)) + (comment (tumme-read-comment file))) + (tumme-write-comment file comment) + (tumme-update-property 'comment comment)) + (tumme-display-thumb-properties)) + +(defun tumme-read-comment (&optional file) + "Read comment, optionally using old comment from FILE as initial value." + + (let ((comment + (read-string + "Comment: " + (if file (tumme-get-comment file))))) + comment)) + +(defun tumme-get-comment (file) + "Get comment for file FILE." + (save-excursion + (let (end buf comment-beg comment (base-name (file-name-nondirectory file))) + (setq buf (find-file tumme-db-file)) + (goto-char (point-min)) + (if (search-forward-regexp + (format "^%s" base-name) nil t) + (progn + (end-of-line) + (setq end (point)) + (beginning-of-line) + (cond ((search-forward ";comment:" end t) + (setq comment-beg (point)) + (if (search-forward ";" end t) + (setq comment-end (- (point) 1)) + (setq comment-end end)) + (setq comment (buffer-substring + comment-beg comment-end)))))) + (kill-buffer buf) + comment))) + +(defun tumme-mark-tagged-files () + "Use regexp to mark files with matching tag." + (interactive) + (let ((tag (read-string "Mark tagged files (regexp): ")) + (hits 0) + files buf) + (save-excursion + (setq buf (find-file tumme-db-file)) + (goto-char (point-min)) + ;; Collect matches + (while (search-forward-regexp + (concat "\\(^[^;]+\\);.*" tag ".*$") nil t) + (setq files (append (list (match-string 1)) files))) + (kill-buffer buf) + ;; Mark files + (mapcar + ;; I tried using `dired-mark-files-regexp' but it was + ;; waaaay to slow. + (lambda (curr-file) + ;; Don't bother about hits found in other directories than + ;; the current one. + (when (string= (file-name-as-directory + (expand-file-name default-directory)) + (file-name-as-directory + (file-name-directory curr-file))) + (setq curr-file (file-name-nondirectory curr-file)) + (goto-char (point-min)) + (when (search-forward-regexp (format "\\s %s$" curr-file) nil t) + (setq hits (+ hits 1)) + (dired-mark 1)))) + files)) + (message "%d files with matching tag marked." hits))) + +(defun tumme-mouse-display-image (event) + "Use mouse EVENT, call `tumme-display-image' to display image. +Track this in associated dired buffer if `tumme-track-movement' is +non-nil." + (interactive "e") + (let (file) + (mouse-set-point event) + (goto-char (posn-point (event-end event))) + (setq file (tumme-original-file-name)) + (if tumme-track-movement + (tumme-track-original-file)) + (tumme-display-image file))) + +(defun tumme-mouse-select-thumbnail (event) + "Use mouse EVENT to select thumbnail image. +Track this in associated dired buffer if `tumme-track-movement' is +non-nil." + (interactive "e") + (let (file) + (mouse-set-point event) + (goto-char (posn-point (event-end event))) + (if tumme-track-movement + (tumme-track-original-file))) + (tumme-display-thumb-properties)) + +(defun tumme-mouse-toggle-mark (event) + "Use mouse EVENT to toggle dired mark for thumbnail. +Track this in associated dired buffer if `tumme-track-movement' is +non-nil." + (interactive "e") + (let (file) + (mouse-set-point event) + (goto-char (posn-point (event-end event))) + (if tumme-track-movement + (tumme-track-original-file))) + (tumme-toggle-mark-thumb-original-file)) + +(defun tumme-dired-display-properties () + "Display properties for dired file in the echo area." + (interactive) + (let* ((file (dired-get-filename)) + (file-name (file-name-nondirectory file)) + (dired-buf (buffer-name (current-buffer))) + (props (mapconcat + 'princ + (tumme-list-tags file) + ", ")) + (comment (tumme-get-comment file))) + (if file-name + (message + (tumme-format-properties-string + dired-buf + file-name + props + comment))))) + +(defvar tumme-tag-file-list nil + "List to store tag-file structure.") + +(defvar tumme-file-tag-list nil + "List to store file-tag structure.") + +(defvar tumme-file-comment-list nil + "List to store file comments.") + +(defun tumme-add-to-tag-file-list (tag file) + "Add relation between TAG and FILE." + (let (curr) + (if tumme-tag-file-list + (if (setq curr (assoc tag tumme-tag-file-list)) + (if (not (member file curr)) + (setcdr curr (cons file (cdr curr)))) + (setcdr tumme-tag-file-list + (cons (list tag file) (cdr tumme-tag-file-list)))) + (setq tumme-tag-file-list (list (list tag file)))))) + +(defun tumme-add-to-tag-file-lists (tag file) + "Helper function used from `tumme-create-gallery-lists'. + +Add TAG to FILE in one list and FILE to TAG in the other. + +Lisp structures look like the following: + +tumme-file-tag-list: + + ((\"filename1\" \"tag1\" \"tag2\" \"tag3\" ...) + (\"filename2\" \"tag1\" \"tag2\" \"tag3\" ...) + ...) + +tumme-tag-file-list: + + ((\"tag1\" \"filename1\" \"filename2\" \"filename3\" ...) + (\"tag2\" \"filename1\" \"filename2\" \"filename3\" ...) + ...)" + ;; Add tag to file list + (let (curr) + (if tumme-file-tag-list + (if (setq curr (assoc file tumme-file-tag-list)) + (setcdr curr (cons tag (cdr curr))) + (setcdr tumme-file-tag-list + (cons (list file tag) (cdr tumme-file-tag-list)))) + (setq tumme-file-tag-list (list (list file tag)))) + ;; Add file to tag list + (if tumme-tag-file-list + (if (setq curr (assoc tag tumme-tag-file-list)) + (if (not (member file curr)) + (setcdr curr (cons file (cdr curr)))) + (setcdr tumme-tag-file-list + (cons (list tag file) (cdr tumme-tag-file-list)))) + (setq tumme-tag-file-list (list (list tag file)))))) + +(defun tumme-add-to-file-comment-list (file comment) + "Helper function used from `tumme-create-gallery-lists'. + +For FILE, add COMMENT to list. + +Lisp structure looks like the following: + +tumme-file-comment-list: + + ((\"filename1\" . \"comment1\") + (\"filename2\" . \"comment2\") + ...)" + (if tumme-file-comment-list + (if (not (assoc file tumme-file-comment-list)) + (setcdr tumme-file-comment-list + (cons (cons file comment) + (cdr tumme-file-comment-list)))) + (setq tumme-file-comment-list (list (cons file comment))))) + +(defun tumme-create-gallery-lists () + "Create temporary lists used by `tumme-gallery-generate'." + (let ((buf (find-file tumme-db-file)) + end beg file row-tags) + (setq tumme-tag-file-list nil) + (setq tumme-file-tag-list nil) + (setq tumme-file-comment-list nil) + (goto-char (point-min)) + (while (search-forward-regexp "^." nil t) + (end-of-line) + (setq end (point)) + (beginning-of-line) + (setq beg (point)) + (if (not (search-forward ";" end nil)) + (error "Something is really wrong, check format of database")) + (setq row-tags (split-string + (buffer-substring beg end) ";")) + (setq file (car row-tags)) + (mapc + (lambda (x) + (if (not (string-match "^comment:\\(.*\\)" x)) + (tumme-add-to-tag-file-lists x file) + (tumme-add-to-file-comment-list file (match-string 1 x)))) + (cdr row-tags))) + (kill-buffer buf)) + ;; Sort tag-file list + (setq tumme-tag-file-list + (sort tumme-tag-file-list + (lambda (x y) + (string< (car x) (car y)))))) + +(defun tumme-hidden-p (file) + "Return t if image FILE has a \"hidden\" tag." + (let (hidden) + (mapc + (lambda (tag) + (if (member tag tumme-gallery-hidden-tags) + (setq hidden t))) + (cdr (assoc file tumme-file-tag-list))) + hidden)) + +(defun tumme-gallery-generate () + "Generate gallery pages. +First we create a couple of Lisp structures from the database to make +it easier to generate, then HTML-files are created in +`tumme-gallery-dir'" + (interactive) + (if (eq 'per-directory tumme-thumbnail-storage) + (error "Currently, gallery generation is not supported \ +when using per-directory thumbnail file storage")) + (tumme-create-gallery-lists) + (let ((tags tumme-tag-file-list) + count curr tag index-buf tag-buf + comment file-tags tag-link tag-link-list) + ;; Make sure gallery root exist + (if (file-exists-p tumme-gallery-dir) + (if (not (file-directory-p tumme-gallery-dir)) + (error "Tumme-gallery-dir is not a directory")) + (make-directory tumme-gallery-dir)) + ;; Open index file + (setq index-buf (find-file + (format "%s/index.html" tumme-gallery-dir))) + (erase-buffer) + (insert "<html>\n") + (insert " <body>\n") + (insert " <h2>Tumme Gallery</h2>\n") + (insert (format "<p>\n Gallery generated %s\n <p>\n" + (current-time-string))) + (insert " <h3>Tag index</h3>\n") + (setq count 1) + ;; Pre-generate list of all tag links + (mapc + (lambda (curr) + (setq tag (car curr)) + (when (not (member tag tumme-gallery-hidden-tags)) + (setq tag-link (format "<a href=\"%d.html\">%s</a>" count tag)) + (if tag-link-list + (setq tag-link-list + (append tag-link-list (list (cons tag tag-link)))) + (setq tag-link-list (list (cons tag tag-link)))) + (setq count (1+ count)))) + tags) + (setq count 1) + ;; Main loop where we generated thumbnail pages per tag + (mapc + (lambda (curr) + (setq tag (car curr)) + ;; Don't display hidden tags + (when (not (member tag tumme-gallery-hidden-tags)) + ;; Insert link to tag page in index + (insert (format " %s<br>\n" (cdr (assoc tag tag-link-list)))) + ;; Open per-tag file + (setq tag-buf (find-file + (format "%s/%s.html" tumme-gallery-dir count))) + (erase-buffer) + (insert "<html>\n") + (insert " <body>\n") + (insert " <p><a href=\"index.html\">Index</a></p>\n") + (insert (format " <h2>Images with tag "%s"</h2>" tag)) + ;; Main loop for files per tag page + (mapc + (lambda (file) + (when (not (tumme-hidden-p file)) + ;; Insert thumbnail with link to full image + (insert + (format "<a href=\"%s/%s\"><img src=\"%s/%s\"%s></a>\n" + tumme-gallery-image-root-url file + tumme-gallery-thumb-image-root-url + (file-name-nondirectory (tumme-thumb-name file)) file)) + ;; Insert comment, if any + (if (setq comment (cdr (assoc file tumme-file-comment-list))) + (insert (format "<br>\n%s<br>\n" comment)) + (insert "<br>\n")) + ;; Insert links to other tags, if any + (when (> (length + (setq file-tags (assoc file tumme-file-tag-list))) 2) + (insert "[ ") + (mapc + (lambda (extra-tag) + ;; Only insert if not file name or the main tag + (if (and (not (equal extra-tag tag)) + (not (equal extra-tag file))) + (insert + (format "%s " (cdr (assoc extra-tag tag-link-list)))))) + file-tags) + (insert "]<br>\n")))) + (cdr curr)) + (insert " <p><a href=\"index.html\">Index</a></p>\n") + (insert " </body>\n") + (insert "</html>\n") + (save-buffer) + (kill-buffer tag-buf) + (setq count (1+ count)))) + tags) + (insert " </body>\n") + (insert "</html>") + (save-buffer) + (kill-buffer index-buf))) + +(defun tumme-kill-buffer-and-window () + "Kill the current buffer and, if possible, also the window." + (interactive) + (let ((buffer (current-buffer))) + (condition-case nil + (delete-window (selected-window)) + (error nil)) + (kill-buffer buffer))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;; TEST-SECTION ;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +(setq tumme-dir-max-size 12300000) + +(defun tumme-test () + "Clean `tumme-dir' from old thumbnail files. +\"Oldness\" measured using last access time. If the total size of all +thumbnail files in `tumme-dir' is larger than 'tumme-dir-max-size', +old files are deleted until the max size is reached." + (let* ((files + (sort + (mapcar + (lambda (f) + (let ((fattribs (file-attributes f))) + ;; Get last access time and file size + `(,(nth 4 fattribs) ,(nth 7 fattribs) ,f))) + (directory-files tumme-dir t ".+\.thumb\..+$")) + ;; Sort function. Compare time between two files. + '(lambda (l1 l2) + (time-less-p (car l1) (car l2))))) + (dirsize (apply '+ (mapcar (lambda (x) (cadr x)) files)))) + (while (> dirsize tumme-dir-max-size) + (y-or-n-p + (format "Size of thumbnail directory: %d, delete old file %s? " + dirsize (cadr (cdar files)))) + (delete-file (cadr (cdar files))) + (setq dirsize (- dirsize (car (cdar files)))) + (setq files (cdr files))))) + +(provide 'tumme) + +;; arch-tag: 9d11411d-331f-4380-8b44-8adfe3a0343e +;;; tumme.el ends here
--- a/lisp/url/ChangeLog Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/url/ChangeLog Sat Dec 10 21:18:28 2005 +0000 @@ -1,3 +1,26 @@ +2005-12-07 Klaus Straubinger <KSNetz@Arcor.DE> (tiny change) + + * url-cookie.el (url-cookie-save-interval): Simplify. + (url-cookie-setup-save-timer): Simplify. + +2005-12-04 Klaus Straubinger <KSNetz@Arcor.DE> (tiny change) + + * url-history.el (url-history-list): Var deleted. + (url-history-save-interval): Simplify. + (url-history-setup-save-timer): Simplify. + +2005-12-01 Kim F. Storm <storm@cua.dk> + + * url-history.el (url-history-track): Fix last change. + +2005-12-01 Klaus Straubinger <KSNetz@Arcor.DE> (tiny change) + + * url-history.el (url-history-track): + Call url-history-setup-save-timer in :set function. + :type allows three alternatives. + (url-history-setup-save-timer): Test url-history-track. + * url.el (url-retrieve): Test url-history-track. + 2005-11-18 Stefan Monnier <monnier@iro.umontreal.ca> * url-http.el: Use with-current-buffer.
--- a/lisp/url/url-cookie.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/url/url-cookie.el Sat Dec 10 21:18:28 2005 +0000 @@ -449,11 +449,10 @@ Default is 1 hour. Note that if you change this variable outside of the `customize' interface after `url-do-setup' has been run, you need to run the `url-cookie-setup-save-timer' function manually." - :set (function (lambda (var val) - (set-default var val) - (and (featurep 'url) - (fboundp 'url-cookie-setup-save-timer) - (url-cookie-setup-save-timer)))) + :set #'(lambda (var val) + (set-default var val) + (if (bound-and-true-p url-setup-done) + (url-cookie-setup-save-timer))) :type 'integer :group 'url) @@ -461,21 +460,12 @@ (defun url-cookie-setup-save-timer () "Reset the cookie saver timer." (interactive) - (ignore-errors - (cond ((fboundp 'cancel-timer) (cancel-timer url-cookie-timer)) - ((fboundp 'delete-itimer) (delete-itimer url-cookie-timer)))) + (ignore-errors (cancel-timer url-cookie-timer)) (setq url-cookie-timer nil) (if url-cookie-save-interval - (setq url-cookie-timer - (cond - ((fboundp 'run-at-time) - (run-at-time url-cookie-save-interval - url-cookie-save-interval - 'url-cookie-write-file)) - ((fboundp 'start-itimer) - (start-itimer "url-cookie-saver" 'url-cookie-write-file - url-cookie-save-interval - url-cookie-save-interval)))))) + (setq url-cookie-timer (run-at-time url-cookie-save-interval + url-cookie-save-interval + #'url-cookie-write-file)))) (provide 'url-cookie)
--- a/lisp/url/url-history.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/url/url-history.el Sat Dec 10 21:18:28 2005 +0000 @@ -38,11 +38,17 @@ :group 'url) (defcustom url-history-track nil - "*Controls whether to keep a list of all the URLS being visited. -If non-nil, url will keep track of all the URLS visited. + "*Controls whether to keep a list of all the URLs being visited. +If non-nil, the URL package will keep track of all the URLs visited. If set to t, then the list is saved to disk at the end of each Emacs session." - :type 'boolean + :set #'(lambda (var val) + (set-default var val) + (and (bound-and-true-p url-setup-done) + (url-history-setup-save-timer))) + :type '(choice (const :tag "off" nil) + (const :tag "on" t) + (const :tag "within session" 'session)) :group 'url-history) (defcustom url-history-file nil @@ -57,22 +63,15 @@ Default is 1 hour. Note that if you change this variable outside of the `customize' interface after `url-do-setup' has been run, you need to run the `url-history-setup-save-timer' function manually." - :set (function (lambda (var val) - (set-default var val) - (and (featurep 'url) - (fboundp 'url-history-setup-save-timer) - (let ((def (symbol-function - 'url-history-setup-save-timer))) - (not (and (listp def) (eq 'autoload (car def))))) - (url-history-setup-save-timer)))) + :set #'(lambda (var val) + (set-default var val) + (if (bound-and-true-p url-setup-done) + (url-history-setup-save-timer))) :type 'integer :group 'url-history) (defvar url-history-timer nil) -(defvar url-history-list nil - "List of urls visited this session.") - (defvar url-history-changed-since-last-save nil "Whether the history list has changed since the last save operation.") @@ -86,20 +85,12 @@ "Reset the history list timer." (interactive) (ignore-errors - (cond ((fboundp 'cancel-timer) (cancel-timer url-history-timer)) - ((fboundp 'delete-itimer) (delete-itimer url-history-timer)))) + (cancel-timer url-history-timer)) (setq url-history-timer nil) - (if url-history-save-interval - (setq url-history-timer - (cond - ((fboundp 'run-at-time) - (run-at-time url-history-save-interval - url-history-save-interval - 'url-history-save-history)) - ((fboundp 'start-itimer) - (start-itimer "url-history-saver" 'url-history-save-history - url-history-save-interval - url-history-save-interval)))))) + (if (and (eq url-history-track t) url-history-save-interval) + (setq url-history-timer (run-at-time url-history-save-interval + url-history-save-interval + 'url-history-save-history)))) ;;;###autoload (defun url-history-parse-history (&optional fname)
--- a/lisp/url/url.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/url/url.el Sat Dec 10 21:18:28 2005 +0000 @@ -148,7 +148,8 @@ (if buffer (with-current-buffer buffer (apply callback cbargs)))) - (url-history-update-url url (current-time)) + (if url-history-track + (url-history-update-url url (current-time))) buffer)) (defun url-retrieve-synchronously (url)
--- a/lisp/view.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/view.el Sat Dec 10 21:18:28 2005 +0000 @@ -439,12 +439,14 @@ \\[View-kill-and-leave] quit View mode, kill current buffer and go back to other buffer. The effect of \\[View-leave] , \\[View-quit] and \\[View-kill-and-leave] depends on how view-mode was entered. If it was -entered by view-file, view-file-other-window or view-file-other-frame -\(\\[view-file], \\[view-file-other-window], \\[view-file-other-frame] or the dired mode v command), then \\[View-quit] will -try to kill the current buffer. If view-mode was entered from another buffer -as is done by View-buffer, View-buffer-other-window, View-buffer-other frame, -View-file, View-file-other-window or View-file-other-frame then \\[View-leave] , \\[View-quit] and \\[View-kill-and-leave] -will return to that buffer. +entered by view-file, view-file-other-window, view-file-other-frame, or +\\[dired-view-file] \(\\[view-file], \\[view-file-other-window], +\\[view-file-other-frame], or the Dired mode v command), +then \\[View-quit] will try to kill the current buffer. +If view-mode was entered from another buffer, by \\[view-buffer], +\\[view-buffer-other-window], \\[view-buffer-other frame], \\[view-file], +\\[view-file-other-window], or \\[view-file-other-frame], +then \\[View-leave] , \\[View-quit] and \\[View-kill-and-leave] will return to that buffer. Entry to view-mode runs the normal hook `view-mode-hook'." (interactive "P")
--- a/lisp/window.el Sat Dec 10 21:12:12 2005 +0000 +++ b/lisp/window.el Sat Dec 10 21:18:28 2005 +0000 @@ -293,7 +293,7 @@ (when newsize (enlarge-window (- newsize (window-height)) - nil t) + nil) (unless (= (window-height) newsize) (setq done nil)))))) 'nomini))))))
--- a/lispref/ChangeLog Sat Dec 10 21:12:12 2005 +0000 +++ b/lispref/ChangeLog Sat Dec 10 21:18:28 2005 +0000 @@ -1,3 +1,17 @@ +2005-12-05 Richard M. Stallman <rms@gnu.org> + + * windows.texi (Resizing Windows): Delete preserve-before args. + +2005-12-05 Stefan Monnier <monnier@iro.umontreal.ca> + + * keymaps.texi (Format of Keymaps): Remove mention of a quirk + in full keymaps, since the quirk has been fixed. + +2005-12-03 Eli Zaretskii <eliz@gnu.org> + + * hooks.texi (Standard Hooks): Add index entries. Mention + `compilation-finish-functions'. + 2005-11-27 Richard M. Stallman <rms@gnu.org> * windows.texi (Resizing Windows): Add adjust-window-trailing-edge.
--- a/lispref/hooks.texi Sat Dec 10 21:12:12 2005 +0000 +++ b/lispref/hooks.texi Sat Dec 10 21:18:28 2005 +0000 @@ -6,6 +6,8 @@ @setfilename ../info/hooks @node Standard Hooks, Index, Standard Keymaps, Top @appendix Standard Hooks +@cindex standard hooks +@cindex hook variables, list of The following is a list of hook variables that let you provide functions to be called from within Emacs on suitable occasions. @@ -102,6 +104,9 @@ @xref{Options for Comments,, Options Controlling Comments, emacs, the GNU Emacs Manual}. +@item compilation-finish-functions +Functions to call when a compilation process finishes. + @item custom-define-hook Hook called after defining each customize option.
--- a/lispref/keymaps.texi Sat Dec 10 21:12:12 2005 +0000 +++ b/lispref/keymaps.texi Sat Dec 10 21:18:28 2005 +0000 @@ -158,17 +158,6 @@ bindings. A keymap with such a char-table is called a @dfn{full keymap}. Other keymaps are called @dfn{sparse keymaps}. -When a keymap contains a char-table vector, it always defines a -binding for each character without modifiers. However, if the binding -is @code{nil}, it doesn't constitute a definition. @code{nil} takes -precedence over a default binding or a binding in the parent keymap. -So in a full keymap, default bindings are not meaningful for -characters without modifiers. They can still apply to characters with -modifier bits and to non-character events. A binding of @code{nil} -does @emph{not} override lower-precedence keymaps; thus, if the local -map gives a binding of @code{nil}, Emacs uses the binding from the -global map. - @item @var{string} @cindex keymap prompt string @cindex overall prompt string @@ -178,6 +167,13 @@ use the keymap as a menu. @xref{Defining Menus}. @end table +When the binding is @code{nil}, it doesn't constitute a definition +but it does take precedence over a default binding or a binding in the +parent keymap. On the other hand, a binding of @code{nil} does +@emph{not} override lower-precedence keymaps; thus, if the local map +gives a binding of @code{nil}, Emacs uses the binding from the +global map. + @cindex meta characters lookup Keymaps do not directly record bindings for the meta characters. Instead, meta characters are regarded for purposes of key lookup as
--- a/lispref/windows.texi Sat Dec 10 21:12:12 2005 +0000 +++ b/lispref/windows.texi Sat Dec 10 21:18:28 2005 +0000 @@ -1966,7 +1966,7 @@ window size. Emacs does not permit overlapping windows or gaps between windows, so resizing one window affects other windows. -@deffn Command enlarge-window size &optional horizontal preserve-before +@deffn Command enlarge-window size &optional horizontal This function makes the selected window @var{size} lines taller, stealing lines from neighboring windows. It takes the lines from one window at a time until that window is used up, then takes from another. @@ -1989,11 +1989,6 @@ size of a fixed-size window, @code{enlarge-window} gets an error instead. -If @var{preserve-before} is non-@code{nil}, this function does not -change the size of the siblings above or to the left of the selected -window. Only the size of the siblings below or to the right of the -selected window are changed. - If @var{size} is negative, this function shrinks the window by @minus{}@var{size} lines or columns. If that makes the window smaller than the minimum size (@code{window-min-height} and @@ -2015,7 +2010,7 @@ @end example @end deffn -@deffn Command shrink-window size &optional horizontal preserve-before +@deffn Command shrink-window size &optional horizontal This function is like @code{enlarge-window} but negates the argument @var{size}, making the selected window smaller by giving lines (or columns) to the other windows. If the window shrinks below
--- a/man/ChangeLog Sat Dec 10 21:12:12 2005 +0000 +++ b/man/ChangeLog Sat Dec 10 21:18:28 2005 +0000 @@ -1,3 +1,20 @@ +2005-12-08 Nick Roberts <nickrob@snap.net.nz> + + * building.texi (GDB Graphical Interface): Explain screen size + setting. + (Other GDB User Interface Buffers): Describe features specific to + GDB 6.4. + +2005-12-06 Luc Teirlinck <teirllm@auburn.edu> + + * org.texi (Internal Links): Fix Texinfo usage. + +2005-12-06 Carsten Dominik <dominik@science.uva.nl> + + * org.texi (TODO basics): Document the global todo list. + (TODO items): Documents sparse tree for specific TODO + keywords. + 2005-12-01 Nick Roberts <nickrob@snap.net.nz> * building.texi (GDB User Interface Layout): Describe how to
--- a/man/building.texi Sat Dec 10 21:12:12 2005 +0000 +++ b/man/building.texi Sat Dec 10 21:18:28 2005 +0000 @@ -768,6 +768,10 @@ at some point in the fringe of this buffer and execution will advance to there. +This mode requires that GDB think that the screen size is unlimited, +and sets the height and width accordingly. For correct operation it +is important that you don't change these values during the session. + @vindex gud-gdb-command-name @findex gdba You can also run GDB in text command mode, which creates a buffer @@ -956,17 +960,20 @@ current frame for simple data types (@pxref{Frame Info, Frame Info, Information on a frame, gdb, The GNU debugger}). -Arrays and structures display their type only. Move point to their -type description ([struct/union] or [array]) and press @key{RET}, or -alternatively click @kbd{Mouse-2} there, to examine their values. -@xref{Watch Expressions}. +Arrays and structures display their type only. With GDB 6.4 or later, +move point to their name and press @key{RET}, or alternatively click +@kbd{Mouse-2} there, to examine their values. With earlier versions +of GDB, move point to their type description ([struct/union] or +[array]). @xref{Watch Expressions}. @item Registers Buffer @findex toggle-gdb-all-registers The registers buffer displays the values held by the registers (@pxref{Registers,,, gdb, The GNU debugger}). Press @key{RET} or click @kbd{Mouse-2} on a register if you want to change its value. -Press @key{SPC} to toggle the display of floating point registers +With GDB 6.4 or later, recently changed register values display with +font-lock-warning-face. With earlier versions of GDB, you can press +@key{SPC} to toggle the display of floating point registers (@code{toggle-gdb-all-registers}). @item Assembler Buffer
--- a/man/cc-mode.texi Sat Dec 10 21:12:12 2005 +0000 +++ b/man/cc-mode.texi Sat Dec 10 21:18:28 2005 +0000 @@ -1,5 +1,4 @@ \input texinfo - @c Notes to self regarding line handling: @c @c Empty lines are often significant before @end directives; avoid them. @@ -27,6 +26,58 @@ @comment %**start of header (This is for running Texinfo on a region) @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@comment How to make the various output formats: +@comment (Thanks to Robert Chassell for supplying this information.) +@comment Note that Texinfo 4.7 (or later) is needed. +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@ignore +In each of the following pairs of commands, the first generates a +version with cross references pointing to the GNU Emacs manuals, +the second with them pointing to the XEmacs manuals. + ## Info output + makeinfo cc-mode.texi + makeinfo -DXEMACS cc-mode.texi + + ## DVI output + ## You may need to set up the environment variable TEXINPUTS so + ## that tex can find the file texinfo.tex - See the tex + ## manpage. + texi2dvi cc-mode.texi + texi2dvi -t "@set XEMACS " cc-mode.texi + + ## HTML output. (The --no-split parameter is optional) + makeinfo --html --no-split cc-mode.texi + makeinfo --html --no-split -DXEMACS cc-mode.texi + + ## Plain text output + makeinfo --fill-column=70 --no-split --paragraph-indent=0 \ + --no-headers --output=cc-mode.txt cc-mode.texi + makeinfo --fill-column=70 --no-split --paragraph-indent=0 \ + --no-headers --output=cc-mode.txt -DXEMACS cc-mode.texi + + ## DocBook output + makeinfo --docbook --no-split --paragraph-indent=0 \ + cc-mode.texi + makeinfo --docbook --no-split --paragraph-indent=0 \ + -DXEMACS cc-mode.texi + + ## XML output + makeinfo --xml --no-split --paragraph-indent=0 \ + cc-mode.texi + makeinfo --xml --no-split --paragraph-indent=0 \ + -DXEMACS cc-mode.texi + + #### (You must be in the same directory as the viewed file.) + + ## View DVI output + xdvi cc-mode.dvi & + + ## View HTML output + mozilla cc-mode.html +@end ignore + @comment No overfull hbox marks in the dvi file. @finalout @@ -34,6 +85,46 @@ @settitle CC Mode Manual @footnotestyle end +@c The following four macros generate the filenames and titles of the +@c main (X)Emacs manual and the Elisp/Lispref manual. Leave the +@c Texinfo variable `XEMACS' unset to generate a GNU Emacs version, set it +@c to generate an XEmacs version, e.g. with +@c "makeinfo -DXEMACS cc-mode.texi". +@ifset XEMACS +@macro emacsman +xemacs +@end macro +@macro emacsmantitle +XEmacs User's Manual +@end macro +@macro lispref +lispref +@end macro +@macro lispreftitle +XEmacs Lisp Reference Manual +@end macro +@end ifset + +@ifclear XEMACS +@macro emacsman +emacs +@end macro +@macro emacsmantitle +GNU Emacs Manual +@end macro +@macro lispref +elisp +@end macro +@macro lispreftitle +GNU Emacs Lisp Reference Manual +@end macro +@end ifclear + + +@macro ccmode +CC Mode +@end macro + @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @comment @setchapternewpage odd !! we don't want blank pages !! @comment %**end of header (This is for running Texinfo on a region) @@ -49,13 +140,15 @@ @comment Authors: @comment Barry A. Warsaw @comment Martin Stjernholm +@comment Alan Mackenzie @comment -@comment Maintained by Martin Stjernholm <bug-cc-mode@gnu.org> +@comment Maintained by Martin Stjernholm and Alan Mackenzie <bug-cc-mode@gnu.org> @comment @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @comment Define an index for syntactic symbols. -@ifnottex +@ifnottex @c In texi2dvi, the @defindex would create an empty cc-mode.ss + @c For Info, unlike tex, @syncodeindex needs a matching @defindex. @defindex ss @end ifnottex @@ -105,15 +198,19 @@ @titlepage @sp 10 -@center @titlefont{CC Mode 5.30} +@center @titlefont{CC Mode 5.31} @sp 2 @center @subtitlefont{A GNU Emacs mode for editing C and C-like languages} @sp 2 -@center Barry A. Warsaw, Martin Stjernholm, Alan Mackenzie (AWK support) +@center Barry A. Warsaw, Martin Stjernholm, Alan Mackenzie @page @vskip 0pt plus 1filll @insertcopying + +This manual was generated from $Revision: 1.32 $ of $RCSfile: cc-mode.texi,v $, which can be +downloaded from +@url{http://cvs.sf.net/viewcvs.py/cc-mode/cc-mode/cc-mode.texi}. @end titlepage @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -124,139 +221,161 @@ @node Top, Introduction, (dir), (dir) @comment node-name, next, previous, up -@macro ccmode -CC Mode -@end macro - @ifinfo @top @ccmode{} @ccmode{} is a GNU Emacs mode for editing files containing C, C++, Objective-C, Java, CORBA IDL (and the variants PSDL and CIDL), Pike -code and to a certain extent, AWK code @xref{AWK Mode}. It provides -syntax-based indentation, font locking, and has several handy commands -and some minor modes to make the editing easier. It does not provide -tools to look up and navigate between functions, classes etc - there are -other packages for that. +and AWK code. It provides syntax-based indentation, font locking, and +has several handy commands and some minor modes to make the editing +easier. It does not provide tools to look up and navigate between +functions, classes etc - there are other packages for that. @end ifinfo @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @menu -* Introduction:: -* Getting Connected:: -* Indentation Engine:: -* Minor Modes:: -* Text Filling and Line Breaking:: -* Macro Handling:: -* Font Locking:: -* Commands:: -* Customizing Indentation:: -* Syntactic Symbols:: -* Indentation Functions:: -* AWK Mode:: -* Odds and Ends:: -* Performance Issues:: -* Limitations and Known Bugs:: -* Frequently Asked Questions:: -* Getting the Latest CC Mode Release:: -* Mailing Lists and Submitting Bug Reports:: -* Sample .emacs File:: - - --- Indices --- - -* Command and Function Index:: -* Variable Index:: -* Concept Index:: +* Introduction:: +* Overview:: +* Getting Started:: +* Commands:: +* Font Locking:: +* Config Basics:: +* Custom Filling and Breaking:: +* Custom Auto-newlines:: +* Clean-ups:: +* Indentation Engine Basics:: +* Customizing Indentation:: +* Custom Macros:: +* Odds and Ends:: +* Sample .emacs File:: +* Performance Issues:: +* Limitations and Known Bugs:: +* FAQ:: +* Updating CC Mode:: +* Mailing Lists and Bug Reports:: +* Command and Function Index:: +* Variable Index:: +* Concept and Key Index:: @detailmenu --- The Detailed Node Listing --- -Indentation Engine - -* Syntactic Analysis:: -* Indentation Calculation:: - -Minor Modes - -* Auto-newline Insertion:: -* Hungry-deletion of Whitespace:: +Commands + +* Indentation Commands:: +* Comment Commands:: +* Movement Commands:: +* Filling and Breaking:: +* Minor Modes:: +* Electric Keys:: +* Auto-newlines:: +* Hungry WS Deletion:: +* Subword Movement:: +* Other Commands:: Font Locking -* Font Locking Preliminaries:: -* Faces:: -* Documentation Comments:: - -Auto-newline Insertion - -* Hanging Braces:: -* Hanging Colons:: -* Hanging Semicolons and Commas:: -* Other Electric Commands:: -* Clean-ups:: - -Commands - -* Indentation Commands:: -* Movement Commands:: -* Other Commands:: +* Font Locking Preliminaries:: +* Faces:: +* Doc Comments:: +* AWK Mode Font Locking:: + +Configuration Basics + +* CC Hooks:: +* Style Variables:: +* Styles:: + +Styles + +* Built-in Styles:: +* Choosing a Style:: +* Adding Styles:: +* File Styles:: + +Customizing Auto-newlines + +* Hanging Braces:: +* Hanging Colons:: +* Hanging Semicolons and Commas:: + +Hanging Braces + +* Custom Braces:: + +Indentation Engine Basics + +* Syntactic Analysis:: +* Syntactic Symbols:: +* Indentation Calculation:: + +Syntactic Symbols + +* Function Symbols:: +* Class Symbols:: +* Conditional Construct Symbols:: +* Switch Statement Symbols:: +* Brace List Symbols:: +* External Scope Symbols:: +* Paren List Symbols:: +* Literal Symbols:: +* Multiline Macro Symbols:: +* Objective-C Method Symbols:: +* Anonymous Class Symbol:: +* Statement Block Symbols:: +* K&R Symbols:: Customizing Indentation -* Interactive Customization:: -* Permanent Customization:: -* Hooks:: -* Styles:: -* Advanced Customizations:: - -Styles - -* Built-in Styles:: -* Choosing a Style:: -* Adding Styles:: -* File Styles:: - -Advanced Customizations - -* Custom Indentation Functions:: -* Custom Brace and Colon Hanging:: -* Customizing Semicolons and Commas:: -* Other Special Indentations:: - -AWK Mode - -* Initialising AWK Mode:: -* AWK Mode Font Locking:: -* AWK Mode Defuns:: +* c-offsets-alist:: +* Interactive Customization:: +* Line-Up Functions:: +* Custom Line-Up:: +* Other Indentation:: + +Line-Up Functions + +* Brace/Paren Line-Up:: +* List Line-Up:: +* Operator Line-Up:: +* Comment Line-Up:: +* Misc Line-Up:: + @end detailmenu @end menu - @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Introduction, Getting Connected, Top, Top +@node Introduction, Overview, Top, Top @comment node-name, next, previous, up @chapter Introduction @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @cindex BOCM +@cindex history +@cindex awk-mode.el +@cindex c-mode.el +@cindex c++-mode.el Welcome to @ccmode{}, a GNU Emacs mode for editing files containing C, C++, Objective-C, Java, CORBA IDL (and the variants CORBA PSDL and -CIDL), Pike and to a certain extent, AWK code (@pxref{AWK Mode}). This -incarnation of the mode is descended from @file{c-mode.el} (also called -``Boring Old C Mode'' or BOCM @t{:-)}, and @file{c++-mode.el} version 2, -which Barry has been maintaining since 1992. Late in 1997, Martin -joined the @ccmode{} Maintainers Team, and implemented the Pike support. -As of 2000 Martin has taken over as the sole maintainer. @ccmode{} did -not originally contain the font lock support for its languages --- that -was added in version 5.30. AWK support was also added in 5.30 by Alan -Mackenzie. +CIDL), Pike and AWK code. This incarnation of the mode is descended +from @file{c-mode.el} (also called ``Boring Old C Mode'' or BOCM +@t{:-)}, @file{c++-mode.el} version 2, which Barry Warsaw had been +maintaining since 1992, and @file{awk-mode.el}, a long neglected mode +in the (X)Emacs base. + +Late in 1997, Martin Stjernholm joined Barry on the @ccmode{} +Maintainers Team, and implemented the Pike support. In 2000 Martin +took over as the sole maintainer. In 2001 Alan Mackenzie joined the +team, implementing AWK support in version 5.30. @ccmode{} did not +originally contain the font lock support for its languages --- that +was added in version 5.30. This manual describes @ccmode{} -@comment The following line must appear on its own, so that the automated -version 5.30. +@comment The following line must appear on its own, so that the +version 5.31. @comment Release.py script can update the version number automatically @ccmode{} supports the editing of K&R and ANSI C, C++, Objective-C, @@ -274,7 +393,7 @@ @findex idl-mode @findex pike-mode @findex awk-mode -Note that the name of this package is ``@ccmode{},'' but there is no top +Note that the name of this package is ``@ccmode{}'', but there is no top level @code{cc-mode} entry point. All of the variables, commands, and functions in @ccmode{} are prefixed with @code{c-@var{thing}}, and @code{c-mode}, @code{c++-mode}, @code{objc-mode}, @code{java-mode}, @@ -282,38 +401,177 @@ provided. This package is intended to be a replacement for @file{c-mode.el}, @file{c++-mode.el} and @file{awk-mode.el}. -@c @cindex @file{cc-compat.el} file -@c This distribution also contains a file -@c called @file{cc-compat.el} which should ease your transition from BOCM -@c to @ccmode{}. If you have a BOCM configuration you are really happy -@c with, and want to postpone learning how to configure @ccmode{}, take a -@c look at that file. It maps BOCM configuration variables to @ccmode{}'s -@c indentation model. It is not actively supported so for the long run, -@c you should learn how to customize @ccmode{} to support your coding -@c style. - A special word of thanks goes to Krishna Padmasola for his work in -converting the original @file{README} file to Texinfo format. I'd also -like to thank all the @ccmode{} victims who help enormously during the -early beta stages of @ccmode{}'s development. - +converting the original @file{README} file to Texinfo format. I'd +also like to thank all the @ccmode{} victims who help enormously +during the early beta stages of @ccmode{}'s development. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Overview, Getting Started, Introduction, Top +@comment node-name, next, previous, up@cindex organization of the manual +@chapter Overview of the Manual +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@noindent +The manual starts with several introductory chapters (including this +one). + +@noindent +The next chunk of the manual describes the day to day @emph{use} of +@ccmode{} (as contrasted with how to customize it). + +@itemize @bullet +@item +The chapter ``Commands'' describes in detail how to use (nearly) all +of @ccmode{}'s features. There are extensive cross-references from +here to the corresponding sections later in the manual which tell you +how to customize these features. + +@item +``Font Locking'' describes how ``syntax highlighting'' is applied to +your buffers. It is mainly background information and can be skipped +over at a first reading. +@end itemize + +@noindent +The next chunk of the manual describes how to @emph{customize} +@ccmode{}. Typically, an overview of a topic is given at the chapter +level, then the sections and subsections describe the material in +increasing detail. + +@itemize @bullet +@item +The chapter ``Configuration Basics'' tells you @emph{how} to write +customizations - whether in hooks, in styles, in both, or in neither, +depending on your needs. It describes the @ccmode{} style system and +lists the standard styles that @ccmode{} supplies. + +@item +The next few chapters, describe in detail how to customize the various +features of @ccmode{}. + +@item +Finally, there is a sample @file{.emacs} fragment, which might help you +in creating your own customization. +@end itemize + +@noindent +The manual ends with ``this and that'', things that don't fit cleanly +into any of the previous chunks. + +@itemize @bullet +@item +Two chapters discuss the performance of @ccmode{} and known +bugs/limitations. + +@item +The FAQ contains a list of common problems and questions. + +@item +The next two chapters tell you how to get in touch with the @ccmode{} +project - whether for updating @ccmode{} or submitting bug reports. +@end itemize + +@noindent +Finally, there are the customary indices. @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Getting Connected, Indentation Engine, Introduction, Top +@node Getting Started, Commands, Overview, Top @comment node-name, next, previous, up -@chapter Getting Connected +@chapter Getting Started @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! If you got this version of @ccmode{} with Emacs or XEmacs, it should -work just fine right out of the box. Note however that you may not have -the latest @ccmode{} release and may want to upgrade your copy. - -If you are upgrading an existing @ccmode{} installation, please see the -@file{README} file for installation details. @ccmode{} may not work -with older versions of Emacs or XEmacs. See the @ccmode{} release notes -at @uref{http://cc-mode.sourceforge.net} for the latest information on -Emacs version and package compatibility (@pxref{Getting the Latest CC -Mode Release}). +work just fine right out of the box. Note however that you might not +have the latest @ccmode{} release and might want to upgrade your copy +(see below). + +You should probably start by reading the entire chapter +@ref{Commands} to get an overview of @ccmode{}'s capabilities. + +After trying out some commands, you may dislike some aspects of +@ccmode{}'s default configuration. Here is an outline of how to +change some of the settings that newcomers to @ccmode{} most often +want to change: + +@table @asis +@item c-basic-offset +This Lisp variable holds an integer, the number of columns @ccmode{} +indents nested code. To set this value to 6, customize +@code{c-basic-offset} or put this into your @file{.emacs}: + +@example +(setq c-basic-offset 6) +@end example + +@item The (indentation) style +The basic ``shape'' of indentation created by @ccmode{}---by default, +this is @code{gnu} style (except for Java and AWK buffers). A list of +the availables styles and their descriptions can be found in +@ref{Built-in Styles}. A complete specification of the @ccmode{} +style system, including how to create your own style, can be found in +the chapter @ref{Styles}. To set your style to @code{linux}, either +customize @code{c-default-style} or put this into your @file{.emacs}: + +@example +(setq c-default-style '((java-mode . "java") + (awk-mode . "awk") + (other . "linux"))) +@end example + +@item Electric Indentation +Normally, when you type ``punctuation'' characters such as @samp{;} or +@samp{@{}, @ccmode{} instantly reindents the current line. This can +be disconcerting until you get used to it. To disable @dfn{electric +indentation} in the current buffer, type @kbd{C-c C-l}. Type the same +thing to enable it again. To have electric indentation disabled by +default, put the following into your @file{.emacs} mode@footnote{There +is no ``easy customization'' facility for making this change.}: + +@example +(setq-default c-electric-flag nil) +@end example + +@noindent +Details of of this and other similar ``Minor Modes'' appear in the +section @ref{Minor Modes}. + +@item Making the @key{RET} key indent the new line +The standard Emacs binding for @key{RET} just adds a new line. If you +want it to reindent the new line as well, rebind the key. Note that +the action of rebinding will fail if the pertinent keymap doesn't yet +exist---we thus need to delay the action until after @ccmode{} has +been loaded. Put the following code into your @file{.emacs}: + +@example +(defun my-make-CR-do-indent () + (define-key c-mode-base-map "\C-m" 'c-context-line-break)) +(add-hook 'c-initialization-hook 'my-make-CR-do-indent) +@end example + +@noindent +This example demonstrates the use of a very powerful @ccmode{} (and +Emacs) facility, the hook. The use of @ccmode{}'s hooks is described +in @ref{CC Hooks}. +@end table + +All these settings should occur in your @file{.emacs} @emph{before} +any @ccmode{} buffers get loaded---in particular, before any call of +@code{desktop-read}. + +As you get to know the mode better, you may want to make more +ambitious changes to your configuration. For this, you should start +reading the chapter @ref{Config Basics}. + +If you are upgrading an existing @ccmode{} installation, please see +the @file{README} file for installation details. In particular, if +you are going to be editing AWK files, @file{README} describes how to +configure your (X)Emacs so that @ccmode{} will supersede the obsolete +@code{awk-mode.el} which might have been supplied with your (X)Emacs. +@ccmode{} might not work with older versions of Emacs or XEmacs. See +the @ccmode{} release notes at @uref{http://cc-mode.sourceforge.net} +for the latest information on Emacs version and package compatibility +(@pxref{Updating CC Mode}). @deffn Command c-version @findex version (c-) @@ -329,531 +587,655 @@ where @samp{XX} is the minor release number. @end deffn - @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Indentation Engine, Minor Modes, Getting Connected, Top +@node Commands, Font Locking, Getting Started, Top @comment node-name, next, previous, up -@chapter Indentation Engine +@chapter Commands @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@ccmode{} has an indentation engine that provides a flexible and general -mechanism for customizing indentation. It separates indentation -calculation into two steps: first, @ccmode{} analyzes the line of code -being indented to determine the kind of language construct it's looking -at, then it applies user defined offsets to the current line based on -this analysis. - -This section will briefly cover how indentation is calculated in -@ccmode{}. It is important to understand the indentation model being -used so that you will know how to customize @ccmode{} for your personal -coding style. All the details are in @ref{Customizing Indentation}, and -later chapters. - -@defopt c-syntactic-indentation -@vindex syntactic-indentation (c-) -Syntactic analysis for indentation is done when this is non-@code{nil} -(which is the default). When it's @code{nil} every line is just -indented to the same level as the previous one, and @kbd{TAB} -(@code{c-indent-command}) adjusts the indentation in steps of -@code{c-basic-offset}. The indentation style has no effect, nor any of -the indentation associated variables, e.g., @code{c-special-indent-hook}. -@end defopt +This chapter specifies all of CC Mode's commands, and thus contains +nearly everything you need to know to @emph{use} @ccmode{} (as +contrasted with configuring it). @dfn{Commands} here means both +control key sequences and @dfn{electric keys}, these being characters +such as @samp{;} which, as well as inserting themselves into the +buffer, also do other things. + +You might well want to review +@ifset XEMACS +@ref{Lists,,,@emacsman{}, @emacsmantitle{}}, +@end ifset +@ifclear XEMACS +@ref{Moving by Parens,,,@emacsman{}, @emacsmantitle{}}, +@end ifclear +which describes commands for moving around brace and parenthesis +structures. + @menu -* Syntactic Analysis:: -* Indentation Calculation:: +* Indentation Commands:: +* Comment Commands:: +* Movement Commands:: +* Filling and Breaking:: +* Minor Modes:: +* Electric Keys:: +* Auto-newlines:: +* Hungry WS Deletion:: +* Subword Movement:: +* Other Commands:: @end menu - @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Syntactic Analysis, Indentation Calculation, , Indentation Engine -@comment node-name, next, previous, up -@section Syntactic Analysis -@cindex syntactic analysis +@node Indentation Commands, Comment Commands, Commands, Commands +@comment node-name, next, previous,up +@section Indentation Commands +@cindex indentation @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@cindex relative buffer position -@cindex syntactic symbols -@cindex syntactic component -@cindex syntactic component list -The first thing @ccmode{} does when indenting a line of code, is to -analyze the line, determining the @dfn{syntactic component list} of the -construct on that line. A syntactic component consists of a pair of -elements (in lisp parlance, a @emph{cons cell}), the first being -a @dfn{syntactic symbol}, the second being a @dfn{relative -buffer position}. Syntactic symbols describe elements of C code -@footnote{Unless otherwise noted, the term ``C code'' refers to all -the C-like languages.}, e.g., @code{statement}, @code{substatement}, -@code{class-open}, @code{class-close}, etc. @xref{Syntactic Symbols}, -for a complete list of currently recognized syntactic symbols and their -semantics. The style variable @code{c-offsets-alist} also contains the -list of currently supported syntactic symbols. - -Conceptually, a line of C code is always indented relative to the -indentation of some line higher up in the buffer. This is represented -by the relative buffer position in the syntactic component. - -Here is an example. Suppose we had the following code as the only thing -in a C++ buffer @footnote{The line numbers in this and future examples -don't actually appear in the buffer, of course!}: - -@example - 1: void swap( int& a, int& b ) - 2: @{ - 3: int tmp = a; - 4: a = b; - 5: b = tmp; - 6: @} -@end example - -@kindex C-c C-s -@findex c-show-syntactic-information -@findex show-syntactic-information (c-) -We can use the command @kbd{C-c C-s} (bound to -@code{c-show-syntactic-information}) to simply report what the -syntactic analysis is for the current line. Running this command on -line 4 of this example, we'd see in the echo area@footnote{With a -universal argument (i.e., @kbd{C-u C-c C-s}) the analysis is inserted -into the buffer as a comment on the current line.}: - -@example -((statement 35)) -@end example - -This tells us that the line is a statement and it is indented relative -to buffer position 35, which happens to be the @samp{i} in @code{int} on -line 3. If you were to move point to line 3 and hit @kbd{C-c C-s}, you -would see: - -@example -((defun-block-intro 29)) -@end example - -This indicates that the @samp{int} line is the first statement in a top -level function block, and is indented relative to buffer position 29, -which is the brace just after the function header. - -Here's another example: - -@example - 1: int add( int val, int incr, int doit ) - 2: @{ - 3: if( doit ) - 4: @{ - 5: return( val + incr ); - 6: @} - 7: return( val ); - 8: @} -@end example +The following commands reindent C constructs. Note that when you +change your coding style, either interactively or through some other +means, your file does @emph{not} automatically get reindented. You +will need to execute one of the following commands to see the effects +of your changes. + +@cindex GNU indent program +Also, variables like @code{c-hanging-*} and @code{c-cleanup-list} +(@pxref{Custom Auto-newlines}) only affect how on-the-fly code is +formatted. Changing the ``hanginess'' of a brace and then +reindenting, will not move the brace to a different line. For this, +you're better off getting an external program like GNU @code{indent}, +which will rearrange brace location, amongst other things. + +Preprocessor directives are handled as syntactic whitespace from other +code, i.e. they can be interspersed anywhere without affecting the +indentation of the surrounding code, just like comments. + +The code inside macro definitions is, by default, still analyzed +syntactically so that you get relative indentation there just as you'd +get if the same code was outside a macro. However, since there is no +hint about the syntactic context, i.e. whether the macro expands to an +expression, to some statements, or perhaps to whole functions, the +syntactic recognition can be wrong. @ccmode{} manages to figure it +out correctly most of the time, though. + +Reindenting large sections of code can take a long time. When +@ccmode{} reindents a region of code, it is essentially equivalent to +hitting @key{TAB} on every line of the region. + +These commands indent code: + +@table @asis +@item @kbd{@key{TAB}} (@code{c-indent-command}) +@kindex TAB +@findex c-indent-command +@findex indent-command (c-) +This command indents the current line. That is all you need to know +about it for normal use. + +@code{c-indent-command} does different things, depending on the +settting of @code{c-syntactic-indentation} (@pxref{Indentation Engine +Basics}): + +@itemize @bullet +@item +When it's non-@code{nil} (which it normally is), the command indents +the line according to its syntactic context. With a prefix argument +(@kbd{C-u @key{TAB}}), it will re-indent the entire +expression@footnote{this is only useful for a line starting with a +comment opener or an opening brace, parenthesis, or string quote.} +that begins at the line's left margin. + +@item +When it's @code{nil}, the command indents the line by an extra +@code{c-basic-offset} columns. A prefix argument acts as a +multiplier. A bare prefix (@kbd{C-u @key{TAB}} is equivalent to -1, +removing @code{c-basic-offset} columns from the indentation. +@end itemize + +The precise behavior is modified by several variables: With +@code{c-tab-always-indent}, you can make @key{TAB} insert whitespace +in some circumstances---@code{c-insert-tab-function} then defines +precisely what sort of ``whitespace'' this will be. Set the standard +Emacs variable @code{indent-tabs-mode} to @code{t} if you want real +@samp{tab} characters to be used in the indentation, to @code{nil} if +you want only spaces. @xref{Just Spaces,,, @emacsman{}, +@emacsmantitle{}}. + +@defopt c-tab-always-indent +@vindex tab-always-indent (c-) +@cindex literal +This variable modifies how @key{TAB} operates. +@itemize @bullet +@item +When it is @code{t} (the default), @key{TAB} simply indents the +current line. +@item +When it is @code{nil}, @key{TAB} (re)indents the line only if point is +to the left of the first non-whitespace character on the line. +Otherwise it inserts some whitespace (a tab or an equivalent number of +spaces - see below) at point. +@item +With some other value, the line is reindented. Additionally, if point +is within a string or comment, some whitespace is inserted. +@end itemize +@end defopt + +@defopt c-insert-tab-function +@vindex insert-tab-function (c-) +@findex tab-to-tab-stop +When ``some whitespace'' is inserted as described above, what actually +happens is that the function stored in @code{c-insert-tab-function} is +called. Normally, this is @code{insert-tab}, which inserts a real tab +character or the equivalent number of spaces (depending on +@code{indent-tabs-mode}). Some people, however, set +@code{c-insert-tab-function} to @code{tab-to-tab-stop} so as to get +hard tab stops when indenting. +@end defopt +@end table @noindent -Hitting @kbd{C-c C-s} on line 4 gives us: - -@example -((substatement-open 46)) -@end example - -@cindex substatement -@cindex substatement block -@noindent -which tells us that this is a brace that @emph{opens} a substatement -block. @footnote{A @dfn{substatement} is the line after a -conditional statement, such as @code{if}, @code{else}, @code{while}, -@code{do}, @code{switch}, etc. A @dfn{substatement -block} is a brace block following one of these conditional statements.} - -@cindex comment-only line -Syntactic component lists can contain more than one component, and -individual syntactic components need not have relative buffer positions. -The most common example of this is a line that contains a @dfn{comment -only line}. - -@example - 1: void draw_list( List<Drawables>& drawables ) - 2: @{ - 3: // call the virtual draw() method on each element in list - 4: for( int i=0; i < drawables.count(), ++i ) - 5: @{ - 6: drawables[i].draw(); - 7: @} - 8: @} -@end example - -@noindent -Hitting @kbd{C-c C-s} on line 3 of this example gives: - -@example -((comment-intro) (defun-block-intro 46)) -@end example - -@noindent -and you can see that the syntactic component list contains two syntactic -components. Also notice that the first component, -@samp{(comment-intro)} has no relative buffer position. - +The kind of indentation the next five commands do depends on the +setting of @code{c-syntactic-indentation} (@pxref{Indentation Engine +Basics}): +@itemize @bullet +@item +when it is non-@code{nil} (the default), the commands indent lines +according to their syntactic context; +@item +when it is @code{nil}, they just indent each line the same amount as +the previous non-blank line. The commands that indent a region aren't +very useful in this case. +@end itemize + +@table @asis +@item @kbd{C-j} (@code{newline-and-indent}) +@kindex C-j +@findex newline-and-indent +Inserts a linefeed and indents the new blank line, ready to start +typing. This is a standard (X)Emacs command. + +@item @kbd{C-M-q} (@code{c-indent-exp}) +@kindex C-M-q +@findex c-indent-exp +@findex indent-exp (c-) +Indents an entire balanced brace or parenthesis expression. Note that +point must be on the opening brace or parenthesis of the expression +you want to indent. + +@item @kbd{C-c C-q} (@code{c-indent-defun}) +@kindex C-c C-q +@findex c-indent-defun +@findex indent-defun (c-) +Indents the entire top-level function, class or macro definition +encompassing point. It leaves point unchanged. This function can't be +used to reindent a nested brace construct, such as a nested class or +function, or a Java method. The top-level construct being reindented +must be complete, i.e. it must have both a beginning brace and an ending +brace. + +@item @kbd{C-M-\} (@code{indent-region}) +@kindex C-M-\ +@findex indent-region +Indents an arbitrary region of code. This is a standard Emacs command, +tailored for C code in a @ccmode{} buffer. Note, of course, that point +and mark must delineate the region you want to indent. + +@item @kbd{C-M-h} (@code{c-mark-function}) +@kindex C-M-h +@findex c-mark-function +@findex mark-function (c-) +While not strictly an indentation command, this is useful for marking +the current top-level function or class definition as the current +region. As with @code{c-indent-defun}, this command operates on +top-level constructs, and can't be used to mark say, a Java method. +@end table + +These variables are also useful when indenting code: + +@defopt indent-tabs-mode +This is a standard Emacs variable that controls how line indentation +is composed. When it's non-@code{nil}, tabs can be used in a line's +indentation, otherwise only spaces are used. +@end defopt + +@defopt c-progress-interval +@vindex progress-interval (c-) +When indenting large regions of code, this variable controls how often a +progress message is displayed. Set this variable to @code{nil} to +inhibit the progress messages, or set it to an integer which is how +often (in seconds) progress messages are to be displayed. +@end defopt + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Comment Commands, Movement Commands, Indentation Commands, Commands +@comment node-name, next, previous, up +@section Comment Commands +@cindex comments (insertion of) +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@table @asis +@item @kbd{C-c C-c} (@code{comment-region}) +@kindex C-c C-c +@findex comment-region +This command comments out the lines that start in the region. With a +negative argument, it does the opposite - it deletes the comment +delimiters from these lines. @xref{Multi-Line Comments,,, emacs, GNU +Emacs Manual}, for fuller details. @code{comment-region} isn't +actually part of @ccmode{} - it is given a @ccmode{} binding for +convenience. + +@item @kbd{M-;} (@code{comment-dwim} or @code{indent-for-comment} @footnote{The name of this command varies between (X)Emacs versions.}) +@kindex M-; +@findex comment-dwim +@findex indent-for-comment +Insert a comment at the end of the current line, if none is there +already. Then reindent the comment according to @code{comment-column} +@ifclear XEMACS +(@pxref{Options for Comments,,, emacs, GNU Emacs Manual}) +@end ifclear +@ifset XEMACS +(@pxref{Comments,,, xemacs, XEmacs User's Manual}) +@end ifset +and the variables below. Finally, position the point after the +comment starter. This is a standard Emacs command, but @ccmode{} +enhances it a bit with two variables: + +@defopt c-indent-comment-alist +@vindex indent-comment-alist (c-) +@vindex comment-column +This style variable allows you to vary the column that @kbd{M-;} puts +the comment at, depending on what sort of code is on the line, and +possibly the indentation of any similar comment on the preceding line. +It is an association list that maps different types of lines to +actions describing how they should be handled. If a certain line type +isn't present on the list then the line is indented to the column +specified by @code{comment-column}. + +See the documentation string for for a full description of this +variable (use @kbd{C-h v c-indent-comment-alist}). +@end defopt + +@defopt c-indent-comments-syntactically-p +@vindex indent-comments-syntactically-p (c-) +Normally, when this style variable is @code{nil}, @kbd{M-;} will +indent comment-only lines according to @code{c-indent-comment-alist}, +just as it does with lines where other code precede the comments. +However, if you want it to act just like @key{TAB} for comment-only +lines you can get that by setting +@code{c-indent-comments-syntactically-p} to non-@code{nil}. + +If @code{c-indent-comments-syntactically-p} is non-@code{nil} then +@code{c-indent-comment-alist} won't be consulted at all for comment-only +lines. +@end defopt +@end table @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Indentation Calculation, , Syntactic Analysis, Indentation Engine +@node Movement Commands, Filling and Breaking, Comment Commands, Commands @comment node-name, next, previous, up -@section Indentation Calculation -@cindex indentation +@section Movement Commands +@cindex movement @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -Indentation for a line is calculated using the syntactic -component list derived in step 1 above (@pxref{Syntactic Analysis}). -Each component contributes to the final total indentation of the line in -two ways. - -First, the syntactic symbols are looked up in the @code{c-offsets-alist} -style variable, which is an association list of syntactic symbols and -the offsets to apply for those symbols. These offsets are added to a -running total. - -Second, if the component has a relative buffer position, @ccmode{} -adds the column number of that position to the running total. By adding -up the offsets and columns for every syntactic component on the list, -the final total indentation for the current line is computed. - -Let's use our two code examples above to see how this works. Here is -our first example again: - -@example - 1: void swap( int& a, int& b ) - 2: @{ - 3: int tmp = a; - 4: a = b; - 5: b = tmp; - 6: @} -@end example - -Let's say point is on line 3 and we hit the @kbd{TAB} key to reindent -the line. Remember that the syntactic component list for that -line is: - -@example -((defun-block-intro 29)) -@end example - -@noindent -@ccmode{} looks up @code{defun-block-intro} in the -@code{c-offsets-alist} style variable. Let's say it finds the value -@samp{4}; it adds this to the running total (initialized to zero), -yielding a running total indentation of 4 spaces. - -Next @ccmode{} goes to buffer position 29 and asks for the current -column. This brace is in column zero, so @ccmode{} -adds @samp{0} to the running total. Since there is only one syntactic -component on the list for this line, indentation calculation is -complete, and the total indentation for the line -is 4 spaces. - -Here's another example: - -@example - 1: int add( int val, int incr, int doit ) - 2: @{ - 3: if( doit ) - 4: @{ - 5: return( val + incr ); - 6: @} - 7: return( val ); - 8: @} -@end example - -If we were to hit @kbd{TAB} on line 4 in the above example, the same -basic process is performed, despite the differences in the syntactic -component list. Remember that the list for this line is: - -@example -((substatement-open 46)) -@end example - -Here, @ccmode{} first looks up the @code{substatement-open} symbol -in @code{c-offsets-alist}. Let's say it finds the value @samp{4}. This -yields a running total of 4. @ccmode{} then goes to -buffer position 46, which is the @samp{i} in @code{if} on line 3. This -character is in the fourth column on that line so adding this to the -running total yields an indentation for the line of 8 spaces. - -Simple, huh? - -Actually, the mode usually just does The Right Thing without you having -to think about it in this much detail. But when customizing -indentation, it's helpful to understand the general indentation model -being used. - -As you configure @ccmode{}, you might want to set the variable -@code{c-echo-syntactic-information-p} to non-@code{nil} so that the -syntactic component list and calculated offset will always be echoed in -the minibuffer when you hit @kbd{TAB}. +@ccmode{} contains some useful commands for moving around in C code. + +@table @asis +@item @kbd{M-x c-beginning-of-defun} +@itemx @kbd{M-x c-end-of-defun} +@findex c-beginning-of-defun +@findex c-end-of-defun +@findex beginning-of-defun (c-) +@findex end-of-defun (c-) +@findex beginning-of-defun +@findex end-of-defun +Move to the start or end of the current top-level definition, this +being the outermost brace pair which encloses point. These functions +are analogous to the Emacs built-in commands @code{beginning-of-defun} +and @code{end-of-defun}, except they eliminate the constraint that the +top-level opening brace of the defun must be in column zero. See +@ref{Defuns,,,@emacsman{}, @emacsmantitle{}}, for more information. + +Depending on the coding style you're using, you might prefer these two +commands to the standard Emacs ones. If so, consider binding them to +@kbd{C-M-a} and @kbd{C-M-e}. @xref{Sample .emacs File}. This +customization won't affect the special bindings for these key +sequences in force in AWK Mode. For backwards compatibility reasons, +the default bindings for @kbd{C-M-a} and @kbd{C-M-e} remain in effect. + +@item @kbd{C-M-a} (AWK Mode) (@code{c-awk-beginning-of-defun}) +@itemx @kbd{C-M-e} (AWK Mode) (@code{c-awk-end-of-defun}) +@kindex C-M-a (AWK Mode) +@kindex C-M-e (AWK Mode) +@findex c-awk-beginning-of-defun +@findex awk-beginning-of-defun (c-) +@findex c-awk-end-of-defun +@findex awk-end-of-defun (c-) +Move back to the beginning or forward to the end of the current AWK +defun. These functions are bound to @kbd{C-M-a} and @kbd{C-M-e} by +default in AWK Mode. They can take prefix-arguments, their +functionality being entirely equivalent to @code{beginning-of-defun} +and @code{end-of-defun}. + +AWK Mode @dfn{defuns} are either pattern/action pairs (either of which +might be implicit) or user defined functions. Having the @samp{@{} and +@samp{@}} (if there are any) in column zero, as is suggested for some +modes, is neither necessary nor helpful in AWK mode. + +@item @kbd{M-a} (@code{c-beginning-of-statement}) +@itemx @kbd{M-e} (@code{c-end-of-statement}) +@kindex M-a +@kindex M-e +@findex c-beginning-of-statement +@findex c-end-of-statement +@findex beginning-of-statement (c-) +@findex end-of-statement (c-) +Move to the beginning or end of the innermost C statement. If point +is already there, move to the next beginning or end of a statement, +even if that means moving into a block. (Use @kbd{C-M-b} or +@kbd{C-M-f} to move over a balanced block.) A prefix argument @var{n} +means move over @var{n} statements. + +If point is within or next to a comment or a string which spans more +than one line, these commands move by sentences instead of statements. + +When called from a program, these functions take three optional +arguments: the repetition count, a buffer position limit which is the +farthest back to search for the syntactic context, and a flag saying +whether to do sentence motion in or near comments and multiline +strings. + +@item @kbd{C-c C-u} (@code{c-up-conditional}) +@kindex C-c C-u +@findex c-up-conditional +@findex up-conditional (c-) +Move back to the containing preprocessor conditional, leaving the mark +behind. A prefix argument acts as a repeat count. With a negative +argument, move forward to the end of the containing preprocessor +conditional. + +@samp{#elif} is treated like @samp{#else} followed by @samp{#if}, so the +function stops at them when going backward, but not when going +forward. + +This key sequence is not bound in AWK Mode, which doesn't have +preprocessor statements. + +@item @kbd{M-x c-up-conditional-with-else} +@findex c-up-conditional-with-else +@findex up-conditional-with-else (c-) +A variety of @code{c-up-conditional} that also stops at @samp{#else} +lines. Normally those lines are ignored. + +@item @kbd{M-x c-down-conditional} +@findex c-down-conditional +@findex down-conditional (c-) +Move forward into the next nested preprocessor conditional, leaving +the mark behind. A prefix argument acts as a repeat count. With a +negative argument, move backward into the previous nested preprocessor +conditional. + +@samp{#elif} is treated like @samp{#else} followed by @samp{#if}, so the +function stops at them when going forward, but not when going backward. + +@item @kbd{M-x c-down-conditional-with-else} +@findex c-down-conditional-with-else +@findex down-conditional-with-else (c-) +A variety of @code{c-down-conditional} that also stops at @samp{#else} +lines. Normally those lines are ignored. + +@item @kbd{C-c C-p} (@code{c-backward-conditional}) +@itemx @kbd{C-c C-n} (@code{c-forward-conditional}) +@kindex C-c C-p +@kindex C-c C-n +@findex c-backward-conditional +@findex c-forward-conditional +@findex backward-conditional (c-) +@findex forward-conditional (c-) +Move backward or forward across a preprocessor conditional, leaving +the mark behind. A prefix argument acts as a repeat count. With a +negative argument, move in the opposite direction. + +These key sequences are not bound in AWK Mode, which doesn't have +preprocessor statements. + +@item @kbd{M-x c-backward-into-nomenclature} +@itemx @kbd{M-x c-forward-into-nomenclature} +@findex c-backward-into-nomenclature +@findex c-forward-into-nomenclature +@findex backward-into-nomenclature (c-) +@findex forward-into-nomenclature (c-) +A popular programming style, especially for object-oriented languages +such as C++ is to write symbols in a mixed case format, where the +first letter of each word is capitalized, and not separated by +underscores. E.g. @samp{SymbolsWithMixedCaseAndNoUnderlines}. + +These commands move backward or forward to the beginning of the next +capitalized word. With prefix argument @var{n}, move @var{n} times. +If @var{n} is negative, move in the opposite direction. + +Note that these two commands have been superseded by +@code{c-subword-mode}, which you should use instead. @xref{Subword +Movement}. They might be removed from a future release of @ccmode{}. +@end table + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Filling and Breaking, Minor Modes, Movement Commands, Commands +@comment node-name, next, previous, up +@section Filling and Line Breaking Commands +@cindex text filling +@cindex line breaking +@cindex comment handling +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Since there's a lot of normal text in comments and string literals, +@ccmode{} provides features to edit these like in text mode. The goal +is to do it seamlessly, i.e. you can use auto fill mode, sentence and +paragraph movement, paragraph filling, adaptive filling etc. wherever +there's a piece of normal text without having to think much about it. +@ccmode{} keeps the indentation, fixes suitable comment line prefixes, +and so on. + +You can configure the exact way comments get filled and broken, and +where Emacs does auto-filling (see @pxref{Custom Filling and +Breaking}). Typically, the style system (@pxref{Styles}) will have +set this up for you, so you probably won't have to bother. + +@findex auto-fill-mode +@cindex Auto Fill mode +@cindex paragraph filling +Line breaks are by default handled (almost) the same regardless of +whether they are made by auto fill mode (@pxref{Auto Fill,,, +@emacsman{}, @emacsmantitle{}}), by paragraph filling (e.g. with +@kbd{M-q}), or explicitly with @kbd{M-j} or similar methods. In +string literals, the new line gets the same indentation as the +previous nonempty line.@footnote{You can change this default by +setting the @code{string} syntactic symbol (@pxref{Syntactic Symbols} +and @pxref{Customizing Indentation})}. + +@table @asis +@item @kbd{M-q} (@code{c-fill-paragraph}) +@kindex M-q +@findex c-fill-paragraph +@findex fill-paragraph (c-) +@cindex Javadoc markup +@cindex Pike autodoc markup +This command fills multiline string literals and both block +and line style comments. In Java buffers, the Javadoc markup words +are recognized as paragraph starters. The line oriented Pike autodoc +markup words are recognized in the same way in Pike mode. + +The formatting of the starters (@code{/*}) and enders (@code{*/}) of +block comments are kept as they were before the filling. I.e., if +either the starter or ender were on a line of its own, then it stays +on its own line; conversely, if the delimiter has comment text on its +line, it keeps at least one word of that text with it on the line. + +This command is the replacement for @code{fill-paragraph} in @ccmode{} +buffers. + +@item @kbd{M-j} (@code{c-indent-new-comment-line}) +@kindex M-j +@findex c-indent-new-comment-line +@findex indent-new-comment-line (c-) +This breaks the current line at point and indents the new line. If +point was in a comment, the new line gets the proper comment line +prefix. If point was inside a macro, a backslash is inserted before +the line break. It is the replacement for +@code{indent-new-comment-line}. + +@item @kbd{M-x c-context-line-break} +@findex c-context-line-break +@findex context-line-break (c-) +Insert a line break suitable to the context: If the point is inside a +comment, the new line gets the suitable indentation and comment line +prefix like @code{c-indent-new-comment-line}. In normal code it's +indented like @code{newline-and-indent} would do. In macros it acts +like @code{newline-and-indent} but additionally inserts and optionally +aligns the line ending backslash so that the macro remains unbroken. +@xref{Custom Macros}, for details about the backslash alignment. + +This function is not bound to a key by default, but it's intended to be +used on the @kbd{RET} key. If you like the behavior of +@code{newline-and-indent} on @kbd{RET}, you should consider switching to +this function. @xref{Sample .emacs File}. + +@item @kbd{M-x c-context-open-line} +@findex c-context-open-line +@findex context-open-line (c-) +This is to @kbd{C-o} (@kbd{M-x open-line}) as +@code{c-context-line-break} is to @kbd{RET}. I.e. it works just like +@code{c-context-line-break} but leaves the point before the inserted +line break. +@end table @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Minor Modes, Text Filling and Line Breaking, Indentation Engine, Top +@node Minor Modes, Electric Keys, Filling and Breaking, Commands @comment node-name, next, previous, up -@chapter Minor Modes +@section Minor Modes +@cindex Minor Modes @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@ccmode{} contains two minor-mode-like features that you should -find useful while entering new C code. The first is called -@dfn{auto-newline} mode, and the second is called @dfn{hungry-delete} -mode. These minor modes can be toggled on and off independently, and -@ccmode{} can be configured so that it starts up with any -combination of these minor modes. By default, both of these minor modes -are turned off. - -The state of the minor modes is always reflected in the minor mode list -on the modeline of the @ccmode{} buffer. When auto-newline mode is -enabled, you will see @samp{C/a} on the mode line@footnote{The @samp{C} -would be replaced with the name of the language in question for the -other languages @ccmode{} supports.}. When hungry delete mode is -enabled you will see @samp{C/h} and if both modes were enabled, you'd -see @samp{C/ah}. - +@ccmode{} contains several minor-mode-like features that you might +find useful while writing new code or editing old code: + +@table @asis +@item electric mode +When this is enabled, certain visible characters cause reformatting as +they are typed. This is normally helpful, but can be a nuisance when +editing chaotically formatted code. It can also be disconcerting, +especially for users who are new to @ccmode{}. +@item auto-newline mode +This automatically inserts newlines where you'd probably want to type +them yourself, e.g. after typing @samp{@}}s. Its action is suppressed +when electric mode is disabled. +@item hungry-delete mode +This lets you delete a contiguous block of whitespace with a single +key - for example, the newline and indentation just inserted by +auto-newline when you want to back up and write a comment after the +last statement. +@item subword mode +This mode makes basic word movement commands like @kbd{M-f} +(@code{forward-word}) and @kbd{M-b} (@code{backward-word}) treat the +parts of sillycapsed symbols as different words. +E.g. @samp{NSGraphicsContext} is treated as three words @samp{NS}, +@samp{Graphics}, and @samp{Context}. +@item syntactic-indentation mode +When this is enabled (which it normally is), indentation commands such +as @kbd{C-j} indent lines of code according to their syntactic +structure. Otherwise, a line is simply indented to the same level as +the previous one and @kbd{@key{TAB}} adjusts the indentation in steps +of `c-basic-offset'. +@end table + +Full details on how these minor modes work are at @ref{Electric Keys}, +@ref{Auto-newlines}, @ref{Hungry WS Deletion}, @ref{Subword Movement}, +and @ref{Indentation Engine Basics}. + +You can toggle each of these minor modes on and off, and you can +configure @ccmode{} so that it starts up with your favourite +combination of them (@pxref{Sample .emacs File}). By default, when +you initialize a buffer, electric mode and syntactic-indentation mode +are enabled but the other two modes are disabled. + +@ccmode{} displays the current state of the first four of these minor +modes on the modeline by appending letters to the major mode's name, +one letter for each enabled minor mode - @samp{l} for electric mode, +@samp{a} for auto-newline mode, @samp{h} for hungry delete mode, and +@samp{w} for subword mode. If all these modes were enabled, you'd see +@samp{C/lahw}@footnote{The @samp{C} would be replaced with the name of +the language in question for the other languages @ccmode{} supports.}. + +Here are the commands to toggle these modes: + +@table @asis +@item @kbd{C-c C-l} (@code{c-toggle-electric-state}) +@kindex C-c C-l +@findex c-toggle-electric-state +@findex toggle-electric-state (c-) +Toggle electric minor mode. When the command turns the mode off, it +also suppresses auto-newline mode. + +@item @kbd{C-c C-a} (@code{c-toggle-auto-newline}) @kindex C-c C-a -@kindex C-c C-d -@kindex C-c C-t +@findex c-toggle-auto-newline +@findex toggle-auto-newline (c-) +Toggle auto-newline minor mode. When the command turns the mode on, +it also enables electric minor mode. + +@item @kbd{M-x c-toggle-hungry-state}@footnote{Prior to @ccmode{} 5.31, this command was bound to @kbd{C-c C-d}.} @findex c-toggle-hungry-state -@findex c-toggle-auto-state +@findex toggle-hungry-state (c-) +Toggle hungry-delete minor mode. + +@item @kbd{M-x c-toggle-auto-hungry-state}@footnote{Prior to @ccmode{} 5.31, this command was bound to @kbd{C-c C-t}.} @findex c-toggle-auto-hungry-state -@findex toggle-hungry-state (c-) -@findex toggle-auto-state (c-) @findex toggle-auto-hungry-state (c-) -@ccmode{} provides key bindings which allow you to toggle the minor -modes on the fly while editing code. To toggle just the auto-newline -state, hit @kbd{C-c C-a} (bound to @code{c-toggle-auto-state}). When -you do this, you should see the @samp{a} indicator either appear or -disappear on the modeline. Similarly, to toggle just the -hungry-delete state, use @kbd{C-c C-d} (@code{c-toggle-hungry-state}), -and to toggle both states, use @kbd{C-c C-t} -(@code{c-toggle-auto-hungry-state}). - -To set up the auto-newline and hungry-delete states to your preferred -values, you would need to add some lisp to your @file{.emacs} file that -called one of the @code{c-toggle-*-state} functions directly. When -called programmatically, each function takes a numeric value, where -a positive number enables the minor mode, a negative number disables the -mode, and zero toggles the current state of the mode. - -So for example, if you wanted to enable both auto-newline and -hungry-delete for all your C file editing, you could add the following -to your @file{.emacs} file: - -@example -(add-hook 'c-mode-common-hook - (lambda () (c-toggle-auto-hungry-state 1))) -@end example - -@menu -* Auto-newline Insertion:: -* Hungry-deletion of Whitespace:: -@end menu - - -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Auto-newline Insertion, Hungry-deletion of Whitespace, , Minor Modes -@comment node-name, next, previous, up -@section Auto-newline Insertion -@cindex auto-newline -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -@cindex electric characters -Auto-newline minor mode works by enabling certain @dfn{electric -characters}. Special characters such as the left and right braces, -colons, semicolons, etc., have been made electric to perform some -magic formatting in addition to inserting the typed character. As a -general rule, electric characters are only electric when the following -conditions apply: - -@itemize @bullet -@item -Auto-newline minor mode is enabled, as evidenced by a @samp{C/a} or -@samp{C/ah} indicator on the modeline. - -@item -@cindex literal -@cindex syntactic whitespace -The character was not typed inside of a literal @footnote{A -@dfn{literal} is defined as any comment, string, or preprocessor macro -definition. These constructs are also known as @dfn{syntactic -whitespace} since they are usually ignored when scanning C code.}. - -@item -No numeric argument was supplied to the command (i.e., it was typed as -normal, with no @kbd{C-u} prefix). -@end itemize - -@menu -* Hanging Braces:: -* Hanging Colons:: -* Hanging Semicolons and Commas:: -* Other Electric Commands:: -* Clean-ups:: -@end menu +Toggle both auto-newline and hungry delete minor modes. + +@item @kbd{C-c C-w} (@code{M-x c-subword-mode}) +@kindex C-c C-w +@findex c-subword-mode +@findex subword-mode (c-) +Toggle subword mode. + +@item @kbd{M-x c-toggle-syntactic-indentation} +@findex c-toggle-syntactic-indentation +@findex toggle-syntactic-indentation (c-) +Toggle syntactic-indentation mode. +@end table + +Common to all the toggle functions above is that if they are called +programmatically, they take an optional numerical argument. A +positive value will turn on the minor mode (or both of them in the +case of @code{c-toggle-auto-hungry-state}) and a negative value will +turn it (or them) off. @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Hanging Braces, Hanging Colons, , Auto-newline Insertion +@node Electric Keys, Auto-newlines, Minor Modes, Commands @comment node-name, next, previous, up -@subsection Hanging Braces -@cindex hanging braces +@section Electric Keys and Keywords +@cindex electric characters @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@findex c-electric-brace -@findex electric-brace (c-) -@kindex @{ -@kindex @} - -When you type either an open or close brace (i.e., @kbd{@{} or @kbd{@}}), -the electric command @code{c-electric-brace} gets run. This command has -two electric formatting behaviors. First, it will perform some -reindentation of the line the brace was typed on, and second, it will -add various newlines before and/or after the typed brace. -Reindentation occurs automatically whenever the electric behavior is -enabled. If the brace ends up on a line other than the one it was typed -on, then that line is also reindented. - -The default in auto-newline mode is to insert newlines both before and -after a brace, but that can be controlled by the -@code{c-hanging-braces-alist} style variable. - -@defopt c-hanging-braces-alist -@vindex hanging-braces-alist (c-) - -This variable contains a mapping between syntactic symbols related to -braces, and a list of places to insert a newline. The syntactic symbols -that are useful for this list are @code{brace-list-intro}, -@code{statement-cont}, @code{inexpr-class-open}, -@code{inexpr-class-close}, and all the @code{*-open} and @code{*-close} -symbols. @xref{Syntactic Symbols}, for a more detailed description of -these syntactic symbols, except for @code{inexpr-class-open} and -@code{inexpr-class-close}, which aren't actual syntactic symbols. - -The braces of anonymous inner classes in Java are given the special -symbols @code{inexpr-class-open} and @code{inexpr-class-close}, so that -they can be distinguished from the braces of normal classes@footnote{The -braces of anonymous classes produce a combination of -@code{inexpr-class}, and @code{class-open} or @code{class-close} in -normal indentation analysis.}. - -Note that the aggregate constructs in Pike mode, @samp{(@{}, @samp{@})}, -@samp{([}, @samp{])}, and @samp{(<}, @samp{>)}, do not count as brace -lists in this regard, even though they do for normal indentation -purposes. It's currently not possible to set automatic newlines on -these constructs. - -The value associated with each syntactic symbol in this association list -is called an @var{action}, which can be either a function or a list. -@xref{Custom Brace and Colon Hanging}, for a more detailed discussion of -using a function as a brace hanging @var{action}. - -When the @var{action} is a list, it can contain any combination of the -symbols @code{before} and @code{after}, directing @ccmode{} where to -put newlines in relationship to the brace being inserted. Thus, if the -list contains only the symbol @code{after}, then the brace is said to -@dfn{hang} on the right side of the line, as in: - -@example -// here, open braces always `hang' -void spam( int i ) @{ - if( i == 7 ) @{ - dosomething(i); - @} -@} -@end example - -When the list contains both @code{after} and @code{before}, the braces -will appear on a line by themselves, as shown by the close braces in the -above example. The list can also be empty, in which case no newlines -are added either before or after the brace. - -If a syntactic symbol is missing entirely from -@code{c-hanging-braces-alist}, it's treated in the same way as an -@var{action} with a list containing @code{before} and @code{after}, so -that braces by default end up on their own line. - -For example, the default value of @code{c-hanging-braces-alist} is: - -@example -((brace-list-open) - (brace-entry-open) - (statement-cont) - (substatement-open after) - (block-close . c-snug-do-while) - (extern-lang-open after) - (inexpr-class-open after) - (inexpr-class-close before)) -@end example - -@noindent which says that @code{brace-list-open}, -@code{brace-entry-open} and @code{statement-cont}@footnote{Brace lists -inside statements, such as initializers for static array variables -inside functions in C, are recognized as @code{statement-cont}. All -normal substatement blocks are recognized with other symbols.} braces -should both hang on the right side and allow subsequent text to follow -on the same line as the brace. Also, @code{substatement-open}, -@code{extern-lang-open}, and @code{inexpr-class-open} braces should hang -on the right side, but subsequent text should follow on the next line. -The opposite holds for @code{inexpr-class-close} braces; they won't -hang, but the following text continues on the same line. Here, in the -@code{block-close} entry, you also see an example of using a function as -an @var{action}. In all other cases, braces are put on a line by -themselves. -@end defopt - - -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Hanging Colons, Hanging Semicolons and Commas, Hanging Braces, Auto-newline Insertion -@comment node-name, next, previous, up -@subsection Hanging Colons -@cindex hanging colons -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -Using a mechanism similar to brace hanging (@pxref{Hanging Braces}), -colons can also be made to hang using the style variable -@code{c-hanging-colons-alist}. - -@defopt c-hanging-colons-alist -@vindex hanging-colons-alist (c-) - -The syntactic symbols appropriate for this association list are: -@code{case-label}, @code{label}, @code{access-label}, -@code{member-init-intro}, and @code{inher-intro}. Note however that for -@code{c-hanging-colons-alist}, @var{action}s as functions are not -supported. See also @ref{Custom Brace and Colon Hanging} for details. - -In C++, double-colons are used as a scope operator but because these -colons always appear right next to each other, newlines before and after -them are controlled by a different mechanism, called @dfn{clean-ups} in -@ccmode{}. @xref{Clean-ups}, for details. -@end defopt - - -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Hanging Semicolons and Commas, Other Electric Commands, Hanging Colons, Auto-newline Insertion -@comment node-name, next, previous, up -@subsection Hanging Semicolons and Commas -@cindex hanging semicolons -@cindex hanging commas -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -Semicolons and commas are also electric in @ccmode{}, but since -these characters do not correspond directly to syntactic symbols, a -different mechanism is used to determine whether newlines should be -automatically inserted after these characters. @xref{Customizing -Semicolons and Commas}, for details. - - -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Other Electric Commands, Clean-ups, Hanging Semicolons and Commas, Auto-newline Insertion -@comment node-name, next, previous, up -@subsection Other Electric Commands -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -A few other keys also provide electric behavior, often only to reindent -the line. Common to all of them is that they only reindent if used in -normal code (as opposed to in a string literal or comment), and -@code{c-syntactic-indentation} isn't @code{nil}. They are: +Most punctuation keys provide @dfn{electric} behavior - as well as +inserting themselves they perform some other action, such as +reindenting the line. A few keywords, such as @code{else}, also +trigger electric action. + +You can inhibit the electric behaviour described here by disabling +electric minor mode (@pxref{Minor Modes}.) + +Common to all of them is that they only behave electrically when used +in normal code (as contrasted with getting typed in a string literal +or comment). Those which cause re-indentation do so only when +@code{c-syntactic-indentation} has a non-@code{nil} value (which it +does by default). + +These keys and keywords are: +@c ACM, 2004/8/24: c-electric-pound doesn't check c-s-i: this is more +@c like a bug in the code than a bug in this document. It'll get +@c fixed in the code sometime. @table @kbd @item # @@ -873,6 +1255,8 @@ Pound is not electric in AWK buffers, where @samp{#} starts a comment, and is bound to @code{self-insert-command} like any typical printable character. +@c ACM, 2004/8/24: Change this (and the code) to do AWK comment +@c reindentation. @item * @kindex * @@ -882,32 +1266,20 @@ @findex electric-star (c-) @findex c-electric-slash @findex electric-slash (c-) -Stars and slashes (bound to @code{c-electric-star} and -@code{c-electric-slash} respectively) are also electric under certain -circumstances. If a @samp{*} is inserted as the second character of a C -style block comment on a comment-only line, then the comment delimiter -is indented as defined by @code{c-offsets-alist}. A comment-only line -is defined as a line which contains only a comment, as in: - -@example -@group -void spam( int i ) -@{ - // this is a comment-only line... - if( i == 7 ) // but this is not - @{ - dosomething(i); - @} -@} -@end group -@end example - -Likewise, if a @samp{/} is inserted as the second slash in a C++ style -line comment (also only on a comment-only line), then the line is -indented as defined by @code{c-offsets-alist}. - -In AWK mode, @samp{*} and @samp{/} do not delimit comments and are -bound to @code{self-insert-command}. +A star (bound to @code{c-electric-star}) or a slash +(@code{c-electric-slash}) causes reindentation when you type it as the +second component of a C style block comment opener (@samp{/*}) or a +C++ line comment opener (@samp{//}) respectively, but only if the +comment opener is the first thing on the line (i.e. there's only +whitespace before it). + +Additionally, you can configure @ccmode{} so that typing a slash at +the start of a line within a block comment will terminate the +comment. You don't need to have electric minor mode enabled to get +this behaviour. @xref{Clean-ups}. + +In AWK mode, @samp{*} and @samp{/} do not delimit comments and are not +electric. @item < @kindex < @@ -915,9 +1287,13 @@ @kindex > @findex c-electric-lt-gt @findex electric-lt-gt (c-) -Less-than and greater-than signs (bound to @code{c-electric-lt-gt}) are -electric, but only in C++ mode. Hitting the second of two @kbd{<} or -@kbd{>} keys reindents the line if it is a C++ style stream operator. +A less-than or greater-than sign (bound to @code{c-electric-lt-gt}) is +electric in two circumstances: when it is an angle bracket in a C++ +@samp{template} declaration (and similar constructs in other +languages) and when it is the second of two @kbd{<} or @kbd{>} +characters in a C++ style stream operator. In either case, the line +is reindented. Angle brackets in C @samp{#include} directives are not +electric. @item ( @kindex ( @@ -925,19 +1301,68 @@ @kindex ) @findex c-electric-paren @findex electric-paren (c-) -The normal parenthesis characters @samp{(} and @samp{)} reindent the -current line. This is useful for getting the closing parenthesis of an -argument list aligned automatically. +The normal parenthesis characters @samp{(} and @samp{)} (bound to +@code{c-electric-paren}) reindent the current line. This is useful +for getting the closing parenthesis of an argument list aligned +automatically. + +You can also configure @ccmode{} to insert a space automatically +between a function name and the @samp{(} you've just typed, and to +remove it automatically after typing @samp{)}, should the argument +list be empty. You don't need to have electric minor mode enabled to +get these actions. @xref{Clean-ups}. + +@item @{ +@kindex @{ +@itemx @} +@kindex @} +@findex c-electric-brace +@findex electric-brace (c-) +Typing a brace (bound to @code{c-electric-brace}) reindents the +current line. Also, one or more newlines might be inserted if +auto-newline minor mode is enabled. @xref{Auto-newlines}. +Additionally, you can configure @ccmode{} to compact excess whitespace +inserted by auto-newline mode in certain circumstances. +@xref{Clean-ups}. + +@item : +@kindex : +@findex c-electric-colon +@findex electric-colon (c-) +Typing a colon (bound to @code{c-electric-colon}) reindents the +current line. Additionally, one or more newlines might be inserted if +auto-newline minor mode is enabled. @xref{Auto-newlines}. If you +type a second colon immediately after such an auto-newline, by default +the whitespace between the two colons is removed, leaving a C++ scope +operator. @xref{Clean-ups}. + +If you prefer, you can insert @samp{::} in a single operation, +avoiding all these spurious reindentations, newlines, and clean-ups. +@xref{Other Commands}. + +@item ; +@kindex ; +@itemx , +@kindex , +@findex c-electric-semi&comma +@findex electric-semi&comma (c-) +Typing a semicolon or comma (bound to @code{c-electric-semi&comma}) +reindents the current line. Also, a newline might be inserted if +auto-newline minor mode is enabled. @xref{Auto-newlines}. +Additionally, you can configure @ccmode{} so that when auto-newline +has inserted whitespace after a @samp{@}}, it will be removed again +when you type a semicolon or comma just after it. @xref{Clean-ups}. + @end table @deffn Command c-electric-continued-statement @findex electric-continued-statement (c-) -Certain keywords, depending on language, are electric to cause -reindentation when they are preceded only by whitespace on the line. -The keywords are those that continue an earlier statement instead of -starting a new one: @code{else}, @code{while}, @code{catch} (only in C++ -and Java) and @code{finally} (only in Java). +Certain keywords are electric, causing reindentation when they are +preceded only by whitespace on the line. The keywords are those that +continue an earlier statement instead of starting a new one: +@code{else}, @code{while}, @code{catch} (only in C++ and Java) and +@code{finally} (only in Java). An example: @@ -951,280 +1376,197 @@ @end example Here, the @code{else} should be indented like the preceding @code{if}, -since it continues that statement. @ccmode{} will automatically reindent -it after the @code{else} has been typed in full, since it's not until -then it's possible to decide whether it's a new statement or a +since it continues that statement. @ccmode{} will automatically +reindent it after the @code{else} has been typed in full, since only +then is it possible to decide whether it's a new statement or a continuation of the preceding @code{if}. @vindex abbrev-mode @findex abbrev-mode @cindex Abbrev mode -@ccmode{} uses Abbrev mode (@pxref{Abbrevs,,, emacs, The Emacs Editor}) +@ccmode{} uses Abbrev mode (@pxref{Abbrevs,,, @emacsman{}, @emacsmantitle{}}) to accomplish this. It's therefore turned on by default in all language modes except IDL mode, since CORBA IDL doesn't have any statements. @end deffn @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Clean-ups, , Other Electric Commands, Auto-newline Insertion +@node Auto-newlines, Hungry WS Deletion, Electric Keys, Commands @comment node-name, next, previous, up -@subsection Clean-ups -@cindex clean-ups +@section Auto-newline Insertion +@cindex auto-newline @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@dfn{Clean-ups} are mechanisms complementary to colon and brace hanging. -On the surface, it would seem that clean-ups overlap the functionality -provided by the @code{c-hanging-*-alist} variables. Clean-ups are -however used to adjust code ``after-the-fact,'' i.e., to adjust the -whitespace in constructs after they are typed. - -Most of the clean-ups are only applicable to counteract automatically -inserted newlines, and will therefore only have any effect if the -auto-newline minor mode is turned on. Others will work all the time. - -@defopt c-cleanup-list -@vindex cleanup-list (c-) +When you have @dfn{Auto-newline minor mode} enabled (@pxref{Minor +Modes}), @ccmode{} inserts newlines for you automatically (in certain +syntactic contexts) when you type a left or right brace, a colon, a +semicolon, or a comma. Sometimes a newline appears before the +character you type, sometimes after it, sometimes both. + +Auto-newline only triggers when the following conditions hold: + +@itemize @bullet +@item +Auto-newline minor mode is enabled, as evidenced by the indicator +@samp{a} after the mode name on the modeline (e.g. @samp{C/a} or +@samp{C/la}). + +@item +The character was typed at the end of a line, or with only whitespace +after it, and possibly a @samp{\} escaping the newline. + +@item +The character is not on its own line already. (This applies only to +insertion of a newline @emph{before} the character.) + +@item @cindex literal - -You can configure @ccmode{}'s clean-ups by setting the style variable -@code{c-cleanup-list}, which is a list of clean-up symbols. By default, -@ccmode{} cleans up only the @code{scope-operator} construct, which is -necessary for proper C++ support. Note that clean-ups are only -performed when the construct does not occur within a literal -(@pxref{Auto-newline Insertion}), and when there is nothing but -whitespace appearing between the individual components of the construct. -@end defopt - -These are the clean-ups that are only active in the auto-newline minor -mode: - -@c TBD: Would like to use some sort of @deffoo here; @table indents a -@c bit too much in dvi output. -@table @code -@item brace-else-brace -Clean up @samp{@} else @{} constructs by placing the entire construct on -a single line. Clean-up occurs when the open brace after the -@samp{else} is typed. So for example, this: - -@example -@group -void spam(int i) -@{ - if( i==7 ) @{ - dosomething(); - @} - else - @{ -@end group -@end example - -@noindent -appears like this after the last open brace is typed: - -@example -@group -void spam(int i) -@{ - if( i==7 ) @{ - dosomething(); - @} else @{ -@end group -@end example - -@item brace-elseif-brace -Similar to the @code{brace-else-brace} clean-up, but this cleans up -@samp{@} else if (...) @{} constructs. For example: - -@example -@group -void spam(int i) -@{ - if( i==7 ) @{ - dosomething(); - @} - else if( i==3 ) - @{ -@end group -@end example - -@noindent -appears like this after the last open parenthesis is typed: - -@example -@group -void spam(int i) -@{ - if( i==7 ) @{ - dosomething(); - @} else if( i==3 ) - @{ -@end group -@end example - -@noindent -and like this after the last open brace is typed: - -@example -@group -void spam(int i) -@{ - if( i==7 ) @{ - dosomething(); - @} else if( i==3 ) @{ -@end group -@end example - -@item brace-catch-brace -Analogous to @code{brace-elseif-brace}, but cleans up @samp{@} catch -(...) @{} in C++ and Java mode. - -@item empty-defun-braces -Clean up braces following a top-level function or class definition that -contains no body. Clean up occurs when the closing brace is typed. -Thus the following: - -@example -@group -class Spam -@{ -@} -@end group -@end example - -@noindent -is transformed into this when the close brace is typed: - -@example -@group -class Spam -@{@} -@end group -@end example - -@item defun-close-semi -Clean up the terminating semicolon on top-level function or class -definitions when they follow a close brace. Clean up occurs when the -semicolon is typed. So for example, the following: - -@example -@group -class Spam -@{ -@} -; -@end group -@end example - -@noindent -is transformed into this when the semicolon is typed: - -@example -@group -class Spam -@{ -@}; -@end group -@end example - -@item list-close-comma -Clean up commas following braces in array and aggregate initializers. -Clean up occurs when the comma is typed. - -@item scope-operator -Clean up double colons which may designate a C++ scope operator split -across multiple lines@footnote{Certain C++ constructs introduce -ambiguous situations, so @code{scope-operator} clean-ups may not always -be correct. This usually only occurs when scoped identifiers appear in -switch label tags.}. Clean up occurs when the second colon is typed. -You will always want @code{scope-operator} in the @code{c-cleanup-list} -when you are editing C++ code. -@end table - -The following clean-ups are always active when they occur on -@code{c-cleanup-list}, and are thus not affected by the auto-newline -minor mode: - -@table @code -@item space-before-funcall -Insert a space between the function name and the opening parenthesis of -a function call. This produces function calls in the style mandated by -the GNU coding standards, e.g., @samp{signal (SIGINT, SIG_IGN)} and -@samp{abort ()}. Clean up occurs when the opening parenthesis is typed. - -@item compact-empty-funcall -Clean up any space between the function name and the opening parenthesis -of a function call that has no arguments. This is typically used -together with @code{space-before-funcall} if you prefer the GNU function -call style for functions with arguments but think it looks ugly when -it's only an empty parenthesis pair. I.e., you will get @samp{signal -(SIGINT, SIG_IGN)}, but @samp{abort()}. Clean up occurs when the -closing parenthesis is typed. -@end table +@cindex syntactic whitespace +The character was not typed inside of a literal @footnote{A +@dfn{literal} is defined as any comment, string, or preprocessor macro +definition. These constructs are also known as @dfn{syntactic +whitespace} since they are usually ignored when scanning C code.}. + +@item +No numeric argument was supplied to the command (i.e. it was typed as +normal, with no @kbd{C-u} prefix). +@end itemize + +You can configure the precise circumstances in which newlines get +inserted (see @pxref{Custom Auto-newlines}). Typically, the style +system (@pxref{Styles}) will have set this up for you, so you probably +won't have to bother. + +Sometimes @ccmode{} inserts an auto-newline where you don't want one, +such as after a @samp{@}} when you're about to type a @samp{;}. +Hungry deletion can help here (@pxref{Hungry WS Deletion}), or you can +activate an appropriate @dfn{clean-up}, which will remove the excess +whitespace after you've typed the @samp{;}. See @ref{Clean-ups} for a +full description. See also @ref{Electric Keys} for a summary of +clean-ups listed by key. @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Hungry-deletion of Whitespace, , Auto-newline Insertion, Minor Modes +@node Hungry WS Deletion, Subword Movement, Auto-newlines, Commands @comment node-name, next, previous, up -@section Hungry-deletion of Whitespace +@section Hungry Deletion of Whitespace @cindex hungry-deletion @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -Hungry deletion of whitespace, or as it more commonly called, -@dfn{hungry-delete mode}, is a simple feature that some people find -extremely useful. In fact, you might find yourself wanting -hungry-delete in @strong{all} your editing modes! - +@kindex C-d + +If you want to delete an entire block of whitespace at point, you can +use @dfn{hungry deletion}. This deletes all the contiguous whitespace +either before point or after point in a single operation. +``Whitespace'' here includes tabs and newlines, but not comments or +preprocessor commands. Hungry deletion can markedly cut down on the +number of times you have to hit deletion keys when, for example, +you've made a mistake on the preceding line and have already pressed +@kbd{C-j}. + +Hungry deletion is a simple feature that some people find extremely +useful. In fact, you might find yourself wanting it in @strong{all} +your editing modes! + +There are two different ways you can use hungry deletion: + +@table @asis +@item Using @dfn{Hungry Delete Mode} with @kbd{@key{DEL}} and @kbd{C-d} +Here you toggle Hungry Delete minor mode with @kbd{M-x +c-toggle-hungry-state}@footnote{Prior to @ccmode{} 5.31, this command +was bound to @kbd{C-c C-d}. @kbd{C-c C-d} is now the default binding +for @code{c-hungry-delete-forward}.} (@pxref{Minor Modes}.) This +makes @kbd{@key{DEL}} and @kbd{C-d} do forward and backwards hungry +deletion. + +@table @asis +@item @kbd{@key{DEL}} (@code{c-electric-backspace}) @kindex DEL -@kindex C-d - -In a nutshell, when hungry-delete mode is enabled, hitting the @kbd{DEL} -or @kbd{C-d} keys will consume all preceding or following whitespace, -including newlines and tabs. This can really cut down on the number of -times you have to hit these keys if, for example, you made a mistake on -the preceding line. - -@deffn Command c-electric-backspace +@findex c-electric-backspace @findex electric-backspace (c-) -This command is run by default when you hit the @kbd{DEL} key. It -deletes any amount of whitespace in the backwards direction if -hungry-delete mode is enabled. When it's disabled, or when used with -a prefix argument or in a literal (@pxref{Auto-newline Insertion}), -the function contained in the @code{c-backspace-function} variable is -called with the prefix argument. -@end deffn - -@defvar c-backspace-function +This command is run by default when you hit the @kbd{DEL} key. When +hungry delete mode is enabled, it deletes any amount of whitespace in +the backwards direction. Otherwise, or when used with a prefix +argument or in a literal (@pxref{Auto-newlines}), the command just +deletes backwards in the usual way. (More precisely, it calls the +function contained in the variable @code{c-backspace-function}, +passing it the prefix argument, if any.) + +@item @code{c-backspace-function} +@vindex c-backspace-function @vindex backspace-function (c-) @findex backward-delete-char-untabify Hook that gets called by @code{c-electric-backspace} when it doesn't do an ``electric'' deletion of the preceding whitespace. The default -value is @code{backward-delete-char-untabify}. -@end defvar - -@deffn Command c-electric-delete-forward +value is @code{backward-delete-char-untabify} +(@pxref{Deletion,,,@lispref{}, @lispreftitle{}}, the function which +deletes a single character. + +@item @kbd{C-d} (@code{c-electric-delete-forward}) +@kindex C-d +@findex c-electric-delete-forward @findex electric-delete-forward (c-) This function, which is bound to @kbd{C-d} by default, works just like @code{c-electric-backspace} but in the forward direction. When it doesn't do an ``electric'' deletion of the following whitespace, it -calls the function in @code{c-delete-function} with its prefix -argument. -@end deffn - -@defvar c-delete-function +just does @code{delete-char}, more or less. (Strictly speaking, it +calls the function in @code{c-delete-function} with the prefix +argument.) + +@item @code{c-delete-function} +@vindex c-delete-function @vindex delete-function (c-) @findex delete-char Hook that gets called by @code{c-electric-delete-forward} when it doesn't do an ``electric'' deletion of the following whitespace. The default value is @code{delete-char}. -@end defvar - -Above we have only talked about the @kbd{DEL} and @kbd{C-d} key events, -without connecting them to the physical keys commonly known as -@key{Backspace} and @key{Delete}. The default behavior of those two -depends on the flavor of (X)Emacs you are using. +@end table + +@item Using Distinct Bindings +The other (newer and recommended) way to use hungry deletion is to +perform @code{c-hungry-backspace} and @code{c-hungry-delete-forward} +directly through their key sequences rather than using the minor mode +toggling. + +@table @asis +@item @kbd{C-c C-@key{Backspace}}, @kbd{C-c DEL}, or @kbd{C-c @key{Backspace}} (@code{c-hungry-backspace}) +@kindex C-c C-<backspace> +@kindex C-c DEL +@kindex C-c <backspace> +@findex c-hungry-backspace +@findex hungry-backspace (c-) +Delete any amount of whitespace in the backwards direction (regardless +whether hungry-delete mode is enabled or not). This command is bound +to both @kbd{C-c C-@key{Backspace}} and @kbd{C-c @key{Backspace}}, +since the more natural one, @kbd{C-c C-@key{Backspace}}, is sometimes +difficult to type at a character terminal. + +@item @kbd{C-c C-@key{Delete}}, @kbd{C-c C-d}, or @kbd{C-c @key{Delete}} (@code{c-hungry-delete-forward}) +@kindex C-c C-<delete> +@kindex C-c C-d +@kindex C-c <delete> +@findex c-hungry-delete-forward +@findex hungry-delete-forward (c-) +Delete any amount of whitespace in the forward direction (regardless +whether hungry-delete mode is enabled or not). This command is bound +to both @kbd{C-c C-@key{Delete}} and @kbd{C-c @key{Delete}} for the +same reason as for @key{Backspace} above. +@end table +@end table + +@kindex <delete> +@kindex <backspace> + +When we talk about @kbd{DEL}, @kbd{C-d}, @key{Backspace} and +@key{Delete} above, we actually do so without connecting them to the +physical keys commonly known as @key{Backspace} and @key{Delete}. The +default bindings to those two keys depends on the flavor of (X)Emacs +you are using. @findex c-electric-delete @findex electric-delete (c-) +@findex c-hungry-delete +@findex hungry-delete (c-) @vindex delete-key-deletes-forward In XEmacs 20.3 and beyond, the @key{Backspace} key is bound to @@ -1234,361 +1576,132 @@ XEmacs variable. When this variable is non-@code{nil}, @code{c-electric-delete} will do forward deletion with @code{c-electric-delete-forward}, otherwise it does backward deletion -with @code{c-electric-backspace}. - -In other Emacs versions, @ccmode{} doesn't bind either @key{Backspace} -or @key{Delete}. In XEmacs 19 and Emacs prior to 21 that means that -it's up to you to fix them. Emacs 21 automatically binds them as -appropriate to @kbd{DEL} and @kbd{C-d}. - -Another way to use hungry deletion is to bind -@code{c-hungry-backspace} and @code{c-hungry-delete-forward} directly -to keys, and not use the mode toggling. For example @kbd{C-c C-d} and -@kbd{C-c DEL} to match plain @kbd{C-d} and @kbd{DEL}, - -@example -(add-hook - 'c-mode-common-hook - (lambda () - (define-key c-mode-base-map - [?\C-c ?\d] 'c-hungry-backspace) - (define-key c-mode-base-map - [?\C-c ?\C-d] 'c-hungry-delete-forward))) -@end example - -@deffn Command c-hungry-backspace -@findex hungry-backspace (c-) -Delete any amount of whitespace in the backwards direction (regardless -whether hungry-delete mode is enabled or not). -@end deffn - -@deffn Command c-hungry-delete-forward -@findex hungry-delete-forward (c-) -Delete any amount of whitespace in the forward direction (regardless -whether hungry-delete mode is enabled or not). -@end deffn +with @code{c-electric-backspace}. Similarly, @kbd{C-c @key{Delete}} +and @kbd{C-c C-@key{Delete}} are bound to @code{c-hungry-delete} which +is controlled in the same way by @code{delete-key-deletes-forward}. + +@findex normal-erase-is-backspace-mode + +Emacs 21 and later automatically binds @key{Backspace} and +@key{Delete} to @kbd{DEL} and @kbd{C-d} according to your environment, +and @ccmode{} extends those bindings to @kbd{C-c C-@key{Backspace}} +etc. If you need to change the bindings through +@code{normal-erase-is-backspace-mode} then @ccmode{} will also adapt +its extended bindings accordingly. + +In earlier (X)Emacs versions, @ccmode{} doesn't bind either +@key{Backspace} or @key{Delete} directly. Only the key codes +@kbd{DEL} and @kbd{C-d} are bound, and it's up to the default bindings +to map the physical keys to them. You might need to modify this +yourself if the defaults are unsuitable. + +Getting your @key{Backspace} and @key{Delete} keys properly set up can +sometimes be tricky. The information in @ref{DEL Does Not +Delete,,,emacs, GNU Emacs Manual}, might be helpful if you're having +trouble with this in GNU Emacs. @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Text Filling and Line Breaking, Macro Handling, Minor Modes, Top +@node Subword Movement, Other Commands, Hungry WS Deletion, Commands @comment node-name, next, previous, up -@chapter Text Filling and Line Breaking -@cindex text filling -@cindex line breaking -@cindex comment handling +@section Subword Movement and Editing @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -Since there's a lot of normal text in comments and string literals, -@ccmode{} provides features to edit these like in text mode. The goal -is to do it as seamlessly as possible, i.e., you can use auto fill mode, -sentence and paragraph movement, paragraph filling, adaptive filling etc -wherever there's a piece of normal text without having to think much -about it. @ccmode{} should keep the indentation, fix the comment line -decorations, and so on, for you. It does that by hooking in on the -different line breaking functions and tuning relevant variables as -necessary. - -@vindex c-comment-prefix-regexp -@vindex comment-prefix-regexp (c-) -@cindex comment line prefix -@vindex comment-start -@vindex comment-end -@vindex comment-start-skip -@vindex paragraph-start -@vindex paragraph-separate -@vindex paragraph-ignore-fill-prefix -@vindex adaptive-fill-mode -@vindex adaptive-fill-regexp -@vindex adaptive-fill-first-line-regexp -To make Emacs recognize comments and treat text in them as normal -paragraphs, @ccmode{} makes several standard -variables@footnote{@code{comment-start}, @code{comment-end}, -@code{comment-start-skip}, @code{paragraph-start}, -@code{paragraph-separate}, @code{paragraph-ignore-fill-prefix}, -@code{adaptive-fill-mode}, @code{adaptive-fill-regexp}, and -@code{adaptive-fill-first-line-regexp}.} buffer local and modifies them -according to the language syntax and the comment line prefix. - -@defopt c-comment-prefix-regexp -@vindex comment-prefix-regexp (c-) -This style variable contains the regexp used to recognize the -@dfn{comment line prefix}, which is the line decoration that starts -every line in a comment. The default is @samp{//+\\|\\**}, which -matches C++ style line comments like - -@example -// blah blah -@end example - -@noindent -with two or more slashes in front of them, and C style block comments -like - -@example -@group -/* - * blah blah - */ -@end group -@end example - -@noindent -with zero or more stars at the beginning of every line. If you change -this variable, please make sure it still matches the comment starter -(i.e., @code{//}) of line comments @emph{and} the line prefix inside -block comments. - -@findex c-setup-paragraph-variables -@findex setup-paragraph-variables (c-) -Also note that since @ccmode{} uses the value of -@code{c-comment-prefix-regexp} to set up several other variables at mode -initialization, there won't be any effect if you just change it inside a -@ccmode{} buffer. You need to call the command -@code{c-setup-paragraph-variables} too, to update those other variables with -the new value. That's also the case if you modify this variable in a -mode hook, since @ccmode{} sets up all variables before calling them. -@end defopt - -@findex auto-fill-mode -@cindex Auto Fill mode -@cindex paragraph filling -Line breaks are by default handled (almost) the same regardless whether -they are made by auto fill mode (@pxref{Auto Fill,,, emacs, The Emacs -Editor}), paragraph filling (e.g., with @kbd{M-q}), or explicitly with -@kbd{M-j} or similar methods. In string literals, the new line gets the -same indentation as the previous nonempty line (may be changed with the -@code{string} syntactic symbol). In comments, @ccmode{} uses -@code{c-comment-prefix-regexp} to adapt the line prefix from the other -lines in the comment. - -@vindex adaptive-fill-mode -@cindex Adaptive Fill mode -@ccmode{} uses adaptive fill mode (@pxref{Adaptive Fill,,, emacs, The -Emacs Editor}) to make Emacs correctly keep the line prefix when filling -paragraphs. That also makes Emacs preserve the text indentation -@emph{inside} the comment line prefix. e.g., in the following comment, -both paragraphs will be filled with the left margins of the texts kept -intact: - -@example -@group -/* Make a balanced b-tree of the nodes in the incoming - * stream. But, to quote the famous words of Donald E. - * Knuth, - * - * Beware of bugs in the above code; I have only - * proved it correct, not tried it. - */ -@end group -@end example - -@findex c-setup-filladapt -@findex setup-filladapt (c-) -@findex filladapt-mode -@vindex filladapt-mode -@cindex Filladapt mode -It's also possible to use other adaptive filling packages, notably Kyle -E. Jones' Filladapt package@footnote{It's available from -@uref{http://www.wonderworks.com/}. As of version 2.12, it does however -lack a feature that makes it work suboptimally when -@code{c-comment-prefix-regexp} matches the empty string (which it does -by default). A patch for that is available from -@uref{http://cc-mode.sourceforge.net/,, the CC Mode web site}.}, -which handles things like bulleted lists nicely. There's a convenience -function @code{c-setup-filladapt} that tunes the relevant variables in -Filladapt for use in @ccmode{}. Call it from a mode hook, e.g., with -something like this in your @file{.emacs}: - -@example -(defun my-c-mode-common-hook () - (c-setup-filladapt) - (filladapt-mode 1)) -(add-hook 'c-mode-common-hook 'my-c-mode-common-hook) -@end example - -@defopt c-block-comment-prefix -@vindex block-comment-prefix (c-) -@vindex c-comment-continuation-stars -@vindex comment-continuation-stars (c-) -Normally the comment line prefix inserted for a new line inside a -comment is deduced from other lines in it. However there's one -situation when there's no hint about what the prefix should look like, -namely when a block comment is broken for the first time. This style -variable@footnote{In versions before 5.26, this variable was called -@code{c-comment-continuation-stars}. As a compatibility measure, -@ccmode{} still uses the value on that variable if it's set.} is used -then as the comment prefix. It defaults to @samp{* -}@footnote{Actually, this default setting of -@code{c-block-comment-prefix} typically gets overriden by the default -style @code{gnu}, which sets it to blank. You can see the line -splitting effect described here by setting a different style, -e.g. @code{k&r} @xref{Choosing a Style}.}, which makes a comment +@cindex nomenclature +@cindex subword +In spite of the GNU Coding Standards, it is popular to name a symbol +by mixing uppercase and lowercase letters, e.g. @samp{GtkWidget}, +@samp{EmacsFrameClass}, or @samp{NSGraphicsContext}. Here we call +these mixed case symbols @dfn{nomenclatures}. Also, each capitalized +(or completely uppercase) part of a nomenclature is called a +@dfn{subword}. Here are some examples: + +@multitable {@samp{NSGraphicsContext}} {@samp{NS}, @samp{Graphics}, and @samp{Context}} +@headitem Nomenclature + @tab Subwords +@item @samp{GtkWindow} + @tab @samp{Gtk} and @samp{Window} +@item @samp{EmacsFrameClass} + @tab @samp{Emacs}, @samp{Frame}, and @samp{Class} +@item @samp{NSGraphicsContext} + @tab @samp{NS}, @samp{Graphics}, and @samp{Context} +@end multitable + +The subword minor mode replaces the basic word oriented movement and +editing commands with variants that recognize subwords in a +nomenclature and treat them as separate words: + +@findex c-forward-subword +@findex forward-subword (c-) +@findex c-backward-subword +@findex backward-subword (c-) +@findex c-mark-subword +@findex mark-subword (c-) +@findex c-kill-subword +@findex kill-subword (c-) +@findex c-backward-kill-subword +@findex backward-kill-subword (c-) +@findex c-transpose-subwords +@findex transpose-subwords (c-) +@findex c-capitalize-subword +@findex capitalize-subword (c-) +@findex c-upcase-subword +@findex upcase-subword (c-) +@findex c-downcase-subword +@findex downcase-subword (c-) +@multitable @columnfractions .20 .40 .40 +@headitem Key @tab Word oriented command @tab Subword oriented command +@item @kbd{M-f} @tab @code{forward-word} @tab @code{c-forward-subword} +@item @kbd{M-b} @tab @code{backward-word} @tab @code{c-backward-subword} +@item @kbd{M-@@} @tab @code{mark-word} @tab @code{c-mark-subword} +@item @kbd{M-d} @tab @code{kill-word} @tab @code{c-kill-subword} +@item @kbd{M-DEL} @tab @code{backward-kill-word} @tab @code{c-backward-kill-subword} +@item @kbd{M-t} @tab @code{transpose-words} @tab @code{c-transpose-subwords} +@item @kbd{M-c} @tab @code{capitalize-word} @tab @code{c-capitalize-subword} +@item @kbd{M-u} @tab @code{upcase-word} @tab @code{c-upcase-subword} +@item @kbd{M-l} @tab @code{downcase-word} @tab @code{c-downcase-subword} +@end multitable + +Note that if you have changed the key bindings for the word oriented +commands in your @file{.emacs} or a similar place, the keys you have +configured are also used for the corresponding subword oriented +commands. + +Type @kbd{C-c C-w} to toggle subword mode on and off. To make the +mode turn on automatically, put the following code in your +@file{.emacs}: @example -/* Got O(n^2) here, which is a Bad Thing. */ -@end example - -@noindent -break into - -@example -@group -/* Got O(n^2) here, - * which is a Bad Thing. */ -@end group +(add-hook 'c-mode-common-hook + (lambda () (c-subword-mode 1))) @end example -Note that it won't work to adjust the indentation by putting leading -spaces in @code{c-block-comment-prefix}, since @ccmode{} still uses the -normal indentation engine to indent the line. Thus, the right way to -fix the indentation is by customizing the @code{c} syntactic symbol. It -defaults to @code{c-lineup-C-comments}, which handles the indentation of -most common comment styles, see @ref{Indentation Functions}. -@end defopt - -@defopt c-ignore-auto-fill -@vindex ignore-auto-fill (c-) -When auto fill mode is enabled, @ccmode{} can selectively ignore it -depending on the context the line break would occur in, e.g., to never -break a line automatically inside a string literal. This variable -takes a list of symbols for the different contexts where auto-filling -never should occur: - -@table @code -@item string -Inside a string or character literal. -@item c -Inside a C style block comment. -@item c++ -Inside a C++ style line comment. -@item cpp -Inside a preprocessor directive. -@item code -Anywhere else, i.e., in normal code. -@end table - -By default, @code{c-ignore-auto-fill} is set to @code{'(string cpp -code)}, which means that auto-filling only occurs in comments when -auto-fill mode is activated. In literals, it's often desirable to have -explicit control over newlines. In preprocessor directives, the -necessary @samp{\} escape character before the newline is not -automatically inserted, so an automatic line break would produce invalid -code. In normal code, line breaks are normally dictated by some logical -structure in the code rather than the last whitespace character, so -automatic line breaks there will produce poor results in the current -implementation. -@end defopt - -The commands that do the actual work follow. +As a bonus, you can also use @code{c-subword-mode} in non-@ccmode{} +buffers by typing @kbd{M-x c-subword-mode}. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Other Commands, , Subword Movement, Commands +@comment node-name, next, previous, up +@section Other Commands +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Here are the various other commands that didn't fit anywhere else: @table @asis -@item @kbd{M-q} (@code{c-fill-paragraph}) -@kindex M-q -@findex c-fill-paragraph -@findex fill-paragraph (c-) -@cindex Javadoc markup -@cindex Pike autodoc markup -This is the replacement for @code{fill-paragraph} in @ccmode{} -buffers. It's used to fill multiline string literals and both block and -line style comments. In Java buffers, the Javadoc markup words are -recognized as paragraph starters. The line oriented Pike autodoc markup -words are recognized in the same way in Pike mode. - -The function keeps the comment starters and enders of block comments as -they were before the filling. This means that a comment ender on the -same line as the paragraph being filled will be filled with the -paragraph, and one on a line by itself will stay as it is. The comment -starter is handled similarly@footnote{This means that the variables -@code{c-hanging-comment-starter-p} and @code{c-hanging-comment-ender-p}, -which controlled this behavior in earlier versions of @ccmode{}, are now -obsolete.}. - -@item @kbd{M-j} (@code{c-indent-new-comment-line}) -@kindex M-j -@findex c-indent-new-comment-line -@findex indent-new-comment-line (c-) -This is the replacement for @code{indent-new-comment-line}. It breaks -the line at point and indents the new line like the current one. - -@vindex comment-multi-line -If inside a comment and @code{comment-multi-line} is non-@code{nil}, the -indentation and line prefix are preserved. If inside a comment and -@code{comment-multi-line} is @code{nil}, a new comment of the same type -is started on the next line and indented as appropriate for comments. - -Note that @ccmode{} sets @code{comment-multi-line} to @code{t} at -startup. The reason is that @kbd{M-j} could otherwise produce sequences -of single line block comments for texts that should logically be treated -as one comment, and the rest of the paragraph handling code -(e.g., @kbd{M-q} and @kbd{M-a}) can't cope with that, which would lead to -inconsistent behavior. - -@item @kbd{M-x c-context-line-break} -@findex c-context-line-break -@findex context-line-break (c-) -This is a function that works like @code{indent-new-comment-line} in -comments and @code{newline-and-indent} elsewhere, thus combining those -two in a way that uses each one in the context it's best suited for. -I.e., in comments the comment line prefix and indentation is kept for -the new line, and in normal code it's indented according to context by -the indentation engine. - -In macros it acts like @code{newline-and-indent} but additionally -inserts and optionally aligns the line ending backslash so that the -macro remains unbroken. @xref{Macro Handling}, for details about the -backslash alignment. - -It's not bound to a key by default, but it's intended to be used on the -@kbd{RET} key. If you like the behavior of @code{newline-and-indent} on -@kbd{RET}, you should consider switching to this function. - -@item @kbd{M-x c-context-open-line} -@findex c-context-open-line -@findex context-open-line (c-) -This is to @kbd{C-o} (@kbd{M-x open-line}) as -@code{c-context-line-break} is to @kbd{RET}. I.e., it works just like -@code{c-context-line-break} but leaves the point before the inserted -line break. -@end table - - -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Macro Handling, Font Locking, Text Filling and Line Breaking, Top -@comment node-name, next, previous, up -@chapter Macro Handling -@cindex macros -@cindex preprocessor directives -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -Preprocessor directives are handled as syntactic whitespace from other -code, i.e., they can be interspersed anywhere without affecting the -syntactic analysis, just like comments. - -The code inside macro definitions is still analyzed syntactically so -that you get relative indentation there just as you'd get if the same -code was outside a macro. However, since there is no hint about the -syntactic context, i.e., whether the macro expands to an expression, to some -statements, or perhaps to whole functions, the syntactic recognition can be -wrong. @ccmode{} manages to figure it out correctly most of the time, -though. @xref{Syntactic Symbols}, for details about the indentation. - -@defopt c-syntactic-indentation-in-macros -@vindex syntactic-indentation-in-macros (c-) -Enable syntactic analysis inside macros, which is the default. If this -is @code{nil}, all lines inside macro definitions are analyzed as -@code{cpp-macro-cont}. -@end defopt - -@ccmode{} provides some tools to help keep the line continuation -backslashes in macros neat and tidy: - -@table @asis +@item @kbd{C-c :} (@code{c-scope-operator}) +@kindex C-c : +@findex c-scope-operator +@findex scope-operator (c-) +In C++, it is also sometimes desirable to insert the double-colon scope +operator without performing the electric behavior of colon insertion. +@kbd{C-c :} does just this. + @item @kbd{C-c C-\} (@code{c-backslash-region}) @kindex C-c C-\ @findex c-backslash-region @findex backslash-region (c-) -This function inserts and aligns or deletes the end-of-line backslashes -in the current region. +This function inserts and aligns or deletes end-of-line backslashes in +the current region. These are typically used in multi-line macros. With no prefix argument, it inserts any missing backslashes and aligns them according to the @code{c-backslash-column} and @@ -1598,75 +1711,72 @@ The function does not modify blank lines at the start of the region. If the region ends at the start of a line, it always deletes the backslash (if any) at the end of the previous line. + +To customize the precise workings of this command, @ref{Custom Macros}. @end table -@defopt c-backslash-column -@vindex backslash-column (c-) -@defoptx c-backslash-max-column -@vindex backslash-max-column (c-) -These variables control the alignment columns for line continuation -backslashes in multiline macros. They are used by the functions that -automatically insert or align such backslashes, -e.g., @code{c-backslash-region} and @code{c-context-line-break}. - -@code{c-backslash-column} specifies the minimum column for the -backslashes. If any line in the macro exceeds it then the next tab -stop from that line is used as the alignment column for all the -backslashes, so that they remain in a single column. However, if some -lines exceed @code{c-backslash-max-column} then the backslashes in the -rest of the macro will be kept at that column, so that the -lines which are too long ``stick out'' instead. -@end defopt - -@defopt c-auto-align-backslashes -@vindex auto-align-backslashes (c-) -Align automatically inserted line continuation backslashes if -non-@code{nil}. When line continuation backslashes are inserted -automatically for line breaks in multiline macros, e.g., by -@code{c-context-line-break}, they are aligned with the other backslashes -in the same macro if this flag is set. Otherwise the inserted -backslashes are preceded by a single space. -@end defopt - +@noindent The recommended line breaking function, @code{c-context-line-break} -(@pxref{Text Filling and Line Breaking}), is especially nice if you edit -multiline macros frequently. When used inside a macro, it automatically -inserts and adjusts the mandatory backslash at the end of the line to -keep the macro together, and it leaves the point at the right -indentation column for the code. Thus you can write code inside macros -almost exactly as you can elsewhere, without having to bother with the -trailing backslashes. - +(@pxref{Filling and Breaking}), is especially nice if you edit +multiline macros frequently. When used inside a macro, it +automatically inserts and adjusts the mandatory backslash at the end +of the line to keep the macro together, and it leaves the point at the +right indentation column for the code. Thus you can write code inside +macros almost exactly as you can elsewhere, without having to bother +with the trailing backslashes. + +@table @asis +@item @kbd{C-c C-e} (@code{c-macro-expand}) +@kindex C-c C-e +@findex c-macro-expand +@findex macro-expand (c-) +This command expands C, C++, Objective C or Pike macros in the region, +using an appropriate external preprocessor program. Normally it +displays its output in a temporary buffer, but if you give it a prefix +arg (with @kbd{C-u C-c C-e}) it will overwrite the original region +with the expansion. + +The command does not work in any of the other modes, and the key +sequence is not bound in these other modes. + +@code{c-macro-expand} isn't actually part of @ccmode{}, even though it +is bound to a @ccmode{} key sequence. If you need help setting it up +or have other problems with it, you can either read its source code or +ask for help in the standard (X)Emacs forums. +@end table @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Font Locking, Commands, Macro Handling, Top +@node Font Locking, Config Basics, Commands, Top @comment node-name, next, previous, up @chapter Font Locking @cindex font locking @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@strong{Please note:} The font locking in AWK mode is currently not integrated -with the rest of @ccmode{}, so this section does not apply there. -@xref{AWK Mode Font Locking}, instead. - @cindex Font Lock mode -@ccmode{} provides font locking for its supported languages by supplying -patterns for use with Font Lock mode. This means that you get distinct -faces on the various syntactic parts such as comments, strings, keywords -and types, which is very helpful in telling them apart at a glance and -discovering syntactic errors. @xref{Font Lock,,, emacs, The Emacs -Editor}, for ways to enable font locking in @ccmode{} buffers. +@ccmode{} provides font locking for its supported languages by +supplying patterns for use with Font Lock mode. This means that you +get distinct faces on the various syntactic parts such as comments, +strings, keywords and types, which is very helpful in telling them +apart at a glance and discovering syntactic errors. @xref{Font +Lock,,, emacs, GNU Emacs Manual}, for ways to enable font locking in +@ccmode{} buffers. + +@strong{Please note:} The font locking in AWK mode is currently not +integrated with the rest of @ccmode{}. Only the last section of this +chapter, @ref{AWK Mode Font Locking}, applies to AWK. The other +sections apply to the other languages. @menu -* Font Locking Preliminaries:: -* Faces:: -* Documentation Comments:: +* Font Locking Preliminaries:: +* Faces:: +* Doc Comments:: +* AWK Mode Font Locking:: @end menu @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Font Locking Preliminaries, Faces, , Font Locking +@node Font Locking Preliminaries, Faces, Font Locking, Font Locking @comment node-name, next, previous, up @section Font Locking Preliminaries @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -1676,19 +1786,20 @@ In the transition to @ccmode{} the patterns have been reworked completely and are applied uniformly across all the languages except AWK mode, just like the indentation rules (although each language still has -some pecularities of its own, of course). Since the languages +some peculiarities of its own, of course). Since the languages previously had completely separate font locking patterns, this means that it's a bit different in most languages now. The main goal for the font locking in @ccmode{} is accuracy, to provide a dependable aid in recognizing the various constructs. Some, like -strings and comments, are easy to recognize while others like -declarations and types can be very tricky. @ccmode{} can go to great +strings and comments, are easy to recognize while others, like +declarations and types, can be very tricky. @ccmode{} can go to great lengths to recognize declarations and casts correctly, especially when the types aren't recognized by standard patterns. This is a fairly demanding analysis which can be slow on older hardware, and it can therefore be disabled by choosing a lower decoration level with the -variable @code{font-lock-maximum-decoration}. +variable @code{font-lock-maximum-decoration} (@pxref{Font Lock,,, +emacs, GNU Emacs Manual}). @vindex font-lock-maximum-decoration @@ -1702,20 +1813,20 @@ @comment 2 @item -Fast normal font locking: In addition to level 1, fontify keywords, -simple types and declarations that are easy to recognize. The variables +Fast font locking: In addition to level 1, fontify keywords, simple +types and declarations that are easy to recognize. The variables @code{*-font-lock-extra-types} (where @samp{*} is the name of the language) are used to recognize types (see below). Documentation comments like Javadoc are fontified according to -@code{c-doc-comment-style} (@pxref{Documentation Comments}). +@code{c-doc-comment-style} (@pxref{Doc Comments}). Use this if you think the font locking is too slow. It's the closest corresponding level to level 3 in the old font lock patterns. @comment 3 @item -Accurate normal font locking: Like level 2 but uses a different approach -that can recognize types and declarations much more accurately. The +Accurate font locking: Like level 2 but uses a different approach that +can recognize types and declarations much more accurately. The @code{*-font-lock-extra-types} variables are still used, but user defined types are recognized correctly anyway in most cases. Therefore those variables should be fairly restrictive and not contain patterns @@ -1726,7 +1837,13 @@ This level is designed for fairly modern hardware and a font lock support mode like Lazy Lock or Just-in-time Lock mode that only -fontifies the parts that are actually shown. +fontifies the parts that are actually shown. Fontifying the whole +buffer at once can easily get bothersomely slow even on contemporary +hardware. +@c ACM, 2005/8/28: There should be a page in the (X)Emacs manual +@c describing these support modes. There wasn't in the +@c fourteenth edition of the Emacs manual (released with Emacs 21.3). +@c There might be one in the Emacs CVS for 22.1. @end enumerate @cindex user defined types @@ -1744,7 +1861,7 @@ For each language there's a variable @code{*-font-lock-extra-types}, where @samp{*} stands for the language in question. It contains a list of regexps that matches identifiers that should be recognized as types, -e.g., @samp{\\sw+_t} to recognize all identifiers ending with @samp{_t} +e.g. @samp{\\sw+_t} to recognize all identifiers ending with @samp{_t} as is customary in C code. Each regexp should not match more than a single identifier. @@ -1761,7 +1878,7 @@ @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Faces, Documentation Comments, Font Locking Preliminaries, Font Locking +@node Faces, Doc Comments, Font Locking Preliminaries, Font Locking @comment node-name, next, previous, up @section Faces @cindex faces @@ -1782,10 +1899,10 @@ @vindex font-lock-doc-face @vindex font-lock-doc-string-face @vindex font-lock-comment-face -Comments that are recognized as documentation (@pxref{Documentation -Comments}) get @code{font-lock-doc-face} (Emacs) or -@code{font-lock-doc-string-face} (XEmacs) if those faces exist. If they -don't then @code{font-lock-comment-face} is used. +Comments that are recognized as documentation (@pxref{Doc Comments}) +get @code{font-lock-doc-face} (Emacs) or +@code{font-lock-doc-string-face} (XEmacs) if those faces exist. If +they don't then @code{font-lock-comment-face} is used. @item @vindex font-lock-string-face @@ -1841,7 +1958,7 @@ @vindex font-lock-builtin-face @vindex font-lock-reference-face Preprocessor directives get @code{font-lock-preprocessor-face} if it -exists (i.e., XEmacs). In Emacs they get @code{font-lock-builtin-face} +exists (i.e. XEmacs). In Emacs they get @code{font-lock-builtin-face} or @code{font-lock-reference-face}, for lack of a closer equivalent. @item @@ -1860,21 +1977,21 @@ @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Documentation Comments, , Faces, Font Locking +@node Doc Comments, AWK Mode Font Locking, Faces, Font Locking @comment node-name, next, previous, up @section Documentation Comments @cindex documentation comments @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! There are various tools to supply documentation in the source as -specially structured comments, e.g., the standard Javadoc tool in Java. +specially structured comments, e.g. the standard Javadoc tool in Java. @ccmode{} provides an extensible mechanism to fontify such comments and the special markup inside them. @defopt c-doc-comment-style @vindex doc-comment-style (c-) This is a style variable that specifies which documentation comment -style to recognize, e.g., @code{javadoc} for Javadoc comments. +style to recognize, e.g. @code{javadoc} for Javadoc comments. The value may also be a list of styles, in which case all of them are recognized simultaneously (presumably with markup cues that don't @@ -1886,10 +2003,13 @@ above if found. If it isn't found then the symbol `other' is looked up and its value is used instead. +The default value for @code{c-doc-comment-style} is +@w{@code{((java-mode . javadoc) (pike-mode . autodoc) (c-mode . gtkdoc))}}. + Note that @ccmode{} uses this variable to set other variables that handle fontification etc. That's done at mode initialization or when you switch to a style which sets this variable. Thus, if you change it -in some other way, e.g., interactively in a CC Mode buffer, you will need +in some other way, e.g. interactively in a CC Mode buffer, you will need to do @kbd{M-x java-mode} (or whatever mode you're currently using) to reinitialize. @@ -1897,7 +2017,7 @@ @findex setup-doc-comment-style (c-) Note also that when @ccmode{} starts up, the other variables are modified before the mode hooks are run. If you change this variable in -a mode hook, you have to call @code{c-setup-doc-comment-style} +a mode hook, you'll have to call @code{c-setup-doc-comment-style} afterwards to redo that work. @end defopt @@ -1912,11 +2032,15 @@ @item autodoc @cindex Pike autodoc markup For Pike autodoc markup, the standard in Pike. + +@item gtkdoc +@cindex GtkDoc markup +For GtkDoc markup, widely used in the Gnome community. @end table The above is by no means complete. If you'd like to see support for other doc comment styles, please let us know (@pxref{Mailing Lists and -Submitting Bug Reports}). +Bug Reports}). You can also write your own doc comment fontification support to use with @code{c-doc-comment-style}: Supply a variable or function @@ -1927,688 +2051,276 @@ @code{javadoc-font-lock-keywords} in @file{cc-fonts.el}. If you add support for another doc comment style, please consider -contributing it --- send a note to @email{bug-cc-mode@@gnu.org}. - - -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Commands, Customizing Indentation, Font Locking, Top -@comment node-name, next, previous, up -@chapter Commands -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -@menu -* Indentation Commands:: -* Movement Commands:: -* Other Commands:: -@end menu - -See also @ref{Text Filling and Line Breaking} and @ref{Macro Handling}, -for commands concerning those bits. - - -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Indentation Commands, Movement Commands, , Commands -@comment node-name, next, previous,up -@section Indentation Commands -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -The following list of commands reindent C constructs. Note that when -you change your coding style, either interactively or through some other -means, your file does @emph{not} automatically get reindented. You -will need to execute one of the following commands to see the effects of -your changes. - -@cindex GNU indent program -Also, variables like @code{c-hanging-*} and @code{c-cleanup-list} -only affect how on-the-fly code is formatted. Changing the -``hanginess'' of a brace and then reindenting, will not move the brace -to a different line. For this, you're better off getting an external -program like GNU @code{indent}, which will rearrange brace location, -among other things. - -Reindenting large sections of code can take a long time. When -@ccmode{} reindents a region of code, it is essentially equivalent to -hitting @kbd{TAB} on every line of the region. - -These commands are useful when indenting code: - -@table @asis -@item @kbd{TAB} (@code{c-indent-command}) -@kindex TAB -@findex c-indent-command -@findex indent-command (c-) -Indents the current line. The actual behavior is controlled by several -variables, described below. See @code{c-tab-always-indent}, -@code{c-insert-tab-function}, and @code{indent-tabs-mode}. With a -numeric argument, this command rigidly indents the region, preserving -the relative indentation among the lines. - -@item @kbd{C-M-q} (@code{c-indent-exp}) -@kindex C-M-q -@findex c-indent-exp -@findex indent-exp (c-) -Indent an entire balanced brace or parenthesis expression. Note that -point must be on the opening brace or parenthesis of the expression you -want to indent. - -@item @kbd{C-c C-q} (@code{c-indent-defun}) -@kindex C-c C-q -@findex c-indent-defun -@findex indent-defun (c-) -Indents the entire top-level function, class or macro definition -encompassing point. It leaves point unchanged. This function can't be -used to reindent a nested brace construct, such as a nested class or -function, or a Java method. The top-level construct being reindented -must be complete, i.e., it must have both a beginning brace and an ending -brace. - -@item @kbd{C-M-\} (@code{indent-region}) -@kindex C-M-\ -@findex indent-region -Indents an arbitrary region of code. This is a standard Emacs command, -tailored for C code in a @ccmode{} buffer. Note, of course, that point -and mark must delineate the region you want to indent. - -@item @kbd{M-;} (@code{indent-for-comment}) -@kindex M-; -@findex indent-for-comment -Insert a comment at the end of the current line, if none is there already. -Then reindent the comment according to the variables -@code{c-indent-comment-alist}, @code{c-indent-comments-syntactically-p} -and @code{comment-column}. Then position the point after the comment -starter. This is a standard Emacs command, but @ccmode{} enhances it a -bit with two variables: - -@defopt c-indent-comment-alist -@vindex indent-comment-alist (c-) -@vindex comment-column -This style variable allows you to control which column @kbd{M-;} -indents the comment to, depending on the preceding code and the -indentation of a similar comment on the preceding line, if there is -any. It is an association list that maps different types of lines to -actions describing how they should be handled. If a certain line type -isn't present on the list then the line is indented to the column -specified by @code{comment-column}. See the documentation string for -@code{c-indent-comment-alist} for a full description of the available -line types and actions (use @kbd{C-h v c-indent-comment-alist}). -@end defopt - -@defopt c-indent-comments-syntactically-p -@vindex indent-comments-syntactically-p (c-) -Normally, when this variable is @code{nil}, @kbd{M-;} will indent -comment-only lines according to @code{c-indent-comment-alist}, just as -it does with lines where other code precede the comments. However, if -you want it to act just like @kbd{TAB} for comment-only lines you can -get that by setting @code{c-indent-comments-syntactically-p} to -non-@code{nil}. - -If @code{c-indent-comments-syntactically-p} is non-@code{nil} then -@code{c-indent-comment-alist} won't be consulted at all for comment-only -lines. -@end defopt - -@item @kbd{C-M-h} (@code{c-mark-function}) -@kindex C-M-h -@findex c-mark-function -@findex mark-function (c-) -While not strictly an indentation command, this is useful for marking -the current top-level function or class definition as the current -region. As with @code{c-indent-defun}, this command operates on -top-level constructs, and can't be used to mark say, a Java method. -@end table - -These variables are also useful when indenting code: - -@defopt c-tab-always-indent -@vindex tab-always-indent (c-) -@kindex TAB -@cindex literal -This variable controls how @kbd{TAB} (@code{c-indent-command}) -operates. When it is @code{t}, @kbd{TAB} always indents the current -line. When it is @code{nil}, the line is indented only if point is at -the left margin, or on or before the first non-whitespace character on -the line, otherwise some whitespace is inserted. If this variable is -some other value (not @code{nil} or @code{t}), then some whitespace is -inserted only within strings and comments (literals), but the line is -always reindented. -@end defopt - -@defopt c-insert-tab-function -@vindex insert-tab-function (c-) -@findex tab-to-tab-stop -When ``some whitespace'' is inserted as described above, what actually -happens is that the function stored in @code{c-insert-tab-function} is -called. Normally, this just inserts a real tab character, or the -equivalent number of spaces, depending on @code{indent-tabs-mode}. -Some people, however, set @code{c-insert-tab-function} to -@code{tab-to-tab-stop} so as to get hard tab stops when indenting. -@end defopt - -@defopt indent-tabs-mode -This is a standard Emacs variable that controls how line indentation -is composed. When it's non-@code{nil}, tabs can be used in a line's -indentation, otherwise only spaces can be used. -@end defopt - -@defopt c-progress-interval -@vindex progress-interval (c-) -When indenting large regions of code, this variable controls how often a -progress message is displayed. Set this variable to @code{nil} to -inhibit the progress messages, or set it to an integer which is how -often (in seconds) progress messages are to be displayed. -@end defopt - - -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Movement Commands, Other Commands, Indentation Commands, Commands -@comment node-name, next, previous, up -@section Movement Commands -@cindex movement -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -@ccmode{} contains some useful commands for moving around in C -code. +contributing it - send a note to @email{bug-cc-mode@@gnu.org}. + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node AWK Mode Font Locking, , Doc Comments, Font Locking +@comment node-name, next, previous, up +@section AWK Mode Font Locking +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +The general appearance of font-locking in AWK mode is much like in any +other programming mode. @xref{Faces For Font Lock,,,elisp, GNU Emacs +Lisp Reference Manual}. + +The following faces are, however, used in a non-standard fashion in +AWK mode: @table @asis -@item @kbd{M-x c-beginning-of-defun} -@findex c-beginning-of-defun -@findex beginning-of-defun (c-) -@findex beginning-of-defun -Move point back to the least-enclosing brace. This function is -analogous to the Emacs built-in command @code{beginning-of-defun}, -except it eliminates the constraint that the top-level opening brace -must be in column zero. See @code{beginning-of-defun} for more -information. - -Depending on the coding style being used, you might prefer -@code{c-beginning-of-defun} to @code{beginning-of-defun}. If so, -consider binding @kbd{C-M-a} to the former instead. For backwards -compatibility reasons, the default binding remains in effect. - -In AWK mode, a defun doesn't necessarily have braces at all. AWK Mode -therefore has its own version of this function which is bound by -default to @kbd{C-M-a}. You can thus chose freely which function to -bind to @kbd{C-M-a} for the other modes without worrying about AWK -buffers. @xref{AWK Mode Defuns}. - -@item @kbd{M-x c-end-of-defun} -@findex c-end-of-defun -@findex end-of-defun (c-) -@findex end-of-defun -Moves point to the end of the current top-level definition. This -function is analogous to the Emacs built-in command @code{end-of-defun}, -except it eliminates the constraint that the top-level opening brace of -the defun must be in column zero. See @code{end-of-defun} for more -information. - -Depending on the coding style being used, you might prefer -@code{c-end-of-defun} to @code{end-of-defun}. If so, -consider binding @kbd{C-M-e} to the former instead. For backwards -compatibility reasons, the default binding remains in effect. - -In AWK Mode, a defun doesn't necessarily have braces at all. AWK Mode -therefore has its own version of this function which is bound by -default to @kbd{C-M-e}. You can thus chose freely which function to -bind to @kbd{C-M-e} for the other modes without worrying about AWK -buffers. @ref{AWK Mode Defuns}. - -@item @kbd{C-c C-u} (@code{c-up-conditional}) -@kindex C-c C-u -@findex c-up-conditional -@findex up-conditional (c-) -Move point back to the containing preprocessor conditional, leaving the -mark behind. A prefix argument acts as a repeat count. With a negative -argument, move point forward to the end of the containing -preprocessor conditional. - -@samp{#elif} is treated like @samp{#else} followed by @samp{#if}, so the -function stops at them when going backward, but not when going forward. - -@item @kbd{M-x c-up-conditional-with-else} -@findex c-up-conditional-with-else -@findex up-conditional-with-else (c-) -A variety of @code{c-up-conditional} that also stops at @samp{#else} -lines. Normally those lines are ignored. - -@item @kbd{M-x c-down-conditional} -@findex c-down-conditional -@findex down-conditional (c-) -Move point forward into the next nested preprocessor conditional, -leaving the mark behind. A prefix argument acts as a repeat count. -With a negative argument, move point backward into the previous -nested preprocessor conditional. - -@samp{#elif} is treated like @samp{#else} followed by @samp{#if}, so the -function stops at them when going forward, but not when going backward. - -@item @kbd{M-x c-down-conditional-with-else} -@findex c-down-conditional-with-else -@findex down-conditional-with-else (c-) -A variety of @code{c-down-conditional} that also stops at @samp{#else} -lines. Normally those lines are ignored. - -@item @kbd{C-c C-p} (@code{c-backward-conditional}) -@kindex C-c C-p -@findex c-backward-conditional -@findex backward-conditional (c-) -Move point back over a preprocessor conditional, leaving the mark -behind. A prefix argument acts as a repeat count. With a negative -argument, move forward. - -@item @kbd{C-c C-n} (@code{c-forward-conditional}) -@kindex C-c C-n -@findex c-forward-conditional -@findex forward-conditional (c-) -Move point forward across a preprocessor conditional, leaving the mark -behind. A prefix argument acts as a repeat count. With a negative -argument, move backward. - -@item @kbd{M-a} (@code{c-beginning-of-statement}) -@kindex M-a -@findex c-beginning-of-statement -@findex beginning-of-statement (c-) -Move point to the beginning of the innermost C statement. If point is -already at the beginning of a statement, move to the beginning of the -closest preceding statement, even if that means moving into a block (you -can use @kbd{C-M-b} to move over a balanced block). With prefix -argument @var{n}, move back @var{n} @minus{} 1 statements. - -If point is within or next to a comment or a string which spans more -than one line, this command moves by sentences instead of statements. - -When called from a program, this function takes three optional -arguments: the repetition count, a buffer position limit which is the -farthest back to search for the syntactic context, and a flag saying -whether to do sentence motion in or near comments and multiline strings. - -@item @kbd{M-e} (@code{c-end-of-statement}) -@kindex M-e -@findex c-end-of-statement -@findex end-of-statement (c-) -Move point to the end of the innermost C statement. If point is at the -end of a statement, move to the end of the next statement, even if it's -inside a nested block (use @kbd{C-M-f} to move to the other side of the -block). With prefix argument @var{n}, move forward @var{n} @minus{} 1 -statements. - -If point is within or next to a comment or a string which spans more -than one line, this command moves by sentences instead of statements. - -When called from a program, this function takes three optional -arguments: the repetition count, a buffer position limit which is the -farthest back to search for the syntactic context, and a flag saying -whether to do sentence motion in or near comments and multiline strings. - -@item @kbd{M-x c-forward-into-nomenclature} -@findex c-forward-into-nomenclature -@findex forward-into-nomenclature (c-) -A popular programming style, especially for object-oriented languages -such as C++ is to write symbols in a mixed case format, where the first -letter of each word is capitalized, and not separated by underscores. -e.g., @samp{SymbolsWithMixedCaseAndNoUnderlines}. - -This command moves point forward to next capitalized word. With prefix -argument @var{n}, move @var{n} times. - -@item @kbd{M-x c-backward-into-nomenclature} -@findex c-backward-into-nomenclature -@findex backward-into-nomenclature (c-) -Move point backward to beginning of the next capitalized -word. With prefix argument @var{n}, move @var{n} times. If -@var{n} is negative, move forward. +@item @code{font-lock-variable-name-face} +This face was intended for variable declarations. Since variables are +not declared in AWK, this face is used instead for AWK system +variables (such as @code{NF}) and ``Special File Names'' (such as +@code{"/dev/stderr"}). + +@item @code{font-lock-builtin-face} (Emacs)/@code{font-lock-preprocessor-face} (XEmacs) +This face is normally used for preprocessor directives in @ccmode{}. +There are no such things in AWK, so this face is used instead for +standard functions (such as @code{match}). + +@item @code{font-lock-string-face} +As well as being used for strings, including localizable strings, +(delimited by @samp{"} and @samp{_"}), this face is also used for AWK +regular expressions (delimited by @samp{/}). + +@item @code{font-lock-warning-face} (Emacs)/@code{c-invalid-face} (XEmacs) +This face highlights the following syntactically invalid AWK +constructs: + +@itemize @bullet +@item +An unterminated string or regular expression. Here the opening +delimiter (@samp{"} or @samp{/} or @samp{_"}) is displayed in +@code{font-lock-warning-face}. This is most noticeable when typing in a +new string/regular expression into a buffer, when the warning-face +serves as a continual reminder to terminate the construct. + +AWK mode fontifies unterminated strings/regular expressions +differently from other modes: Only the text up to the end of the line +is fontified as a string (escaped newlines being handled correctly), +rather than the text up to the next string quote. + +@item +A space between the function name and opening parenthesis when calling +a user function. The last character of the function name and the +opening parenthesis are highlighted. This font-locking rule will +spuriously highlight a valid concatenation expression where an +identifier precedes a parenthesised expression. Unfortunately. + +@item +Whitespace following the @samp{\} in what otherwise looks like an +escaped newline. The @samp{\} is highlighted. +@end itemize @end table +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Config Basics, Custom Filling and Breaking, Font Locking, Top +@comment node-name, next, previous, up +@chapter Configuration Basics @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Other Commands, , Movement Commands, Commands -@comment node-name, next, previous, up -@section Other Commands -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -Here are the various other commands that didn't fit anywhere else: + +@cindex Emacs Initiliazation File +@cindex Configuration +You configure @ccmode{} by setting Lisp variables and calling (and +perhaps writing) Lisp functions@footnote{DON'T PANIC!!! This isn't +difficult.}, which is usually done by adding code to an Emacs +initialization file. This file might be @file{site-start.el} or +@file{.emacs} or @file{init.el} or @file{default.el} or perhaps some +other file. @xref{Init File,,,@emacsman{}, @emacsmantitle{}}. For +the sake of conciseness, we just call this file ``your @file{.emacs}'' +throughout the rest of the manual. + +Several of these variables (currently 16), are known collectively as +@dfn{style variables}. @ccmode{} provides a special mechanism, known +as @dfn{styles} to make it easier to set these variables as a group, +to ``inherit'' settings from one style into another, and so on. Style +variables remain ordinary Lisp variables, whose values can be read and +changed independently of the style system. @xref{Style Variables}. + +There are several ways you can write the code, depending on the +precise effect you want---they are described further down on this page. +If you are new to @ccmode{}, we suggest you begin with the simplest +method, ``Top-level commands or the customization interface''. + +If you make conflicting settings in several of these ways, the way +that takes precedence is the one that appears latest in this list: +@itemize @asis +@item +@table @asis +@item Style +@itemx Top-level command or ``customization interface'' +@itemx Hook +@itemx File Style +@end table +@end itemize + +Here is a summary of the different ways of writing your configuration +settings: @table @asis -@item @kbd{C-c :} (@code{c-scope-operator}) -@kindex C-c : -@findex c-scope-operator -@findex scope-operator (c-) -In C++, it is also sometimes desirable to insert the double-colon scope -operator without performing the electric behavior of colon insertion. -@kbd{C-c :} does just this. -@end table - -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Customizing Indentation, Syntactic Symbols, Commands, Top -@comment node-name, next, previous, up -@chapter Customizing Indentation -@cindex customization, indentation -@cindex indentation -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -The context sensitive indentation is mainly controlled by the variable -@code{c-offsets-alist}: - -@defopt c-offsets-alist -@vindex offsets-alist (c-) -This special style variable contains the mappings between syntactic -symbols and the offsets to apply for those symbols. It's set at mode -initialization from a @emph{style} you may specify. Styles are -groupings of syntactic symbol offsets and other style variable values. -Most likely, you'll find that one of the predefined styles will suit -your needs. @xref{Styles}, for an explanation of how to set up named -styles. - -Only syntactic symbols not already bound on @code{c-offsets-alist} will -be set from styles. This means that any association you set on it, be -it before or after mode initialization, will not be changed. The -@code{c-offsets-alist} variable may therefore be used from e.g., the -Customization interface@footnote{Available in Emacs 20 and later, and -XEmacs 19.15 and later.} to easily change indentation offsets without -having to bother about styles. Initially @code{c-offsets-alist} is -empty, so that all syntactic symbols are set by the style system. - -The offset associated with any particular syntactic symbol can be an -integer, a function or lambda expression, a variable name, a vector, a -list, or one of the following special symbols: @code{+}, @code{-}, -@code{++}, @code{--}, @code{*}, or @code{/}. The meaning of these -values are described in detail below. -@end defopt - -The special symbols describe an offset in multiples of the value of -@code{c-basic-offset}: - -@defopt c-basic-offset -@vindex basic-offset (c-) -Style variable that holds the basic offset between indentation levels. -@end defopt - -By defining a style's indentation in terms of @code{c-basic-offset}, -you can change the amount of whitespace given to an indentation level -while maintaining the same basic shape of your code. Here are the -values that the special symbols correspond to: - -@table @code -@item + -@code{c-basic-offset} times 1 -@item - -@code{c-basic-offset} times -1 -@item ++ -@code{c-basic-offset} times 2 -@item -- -@code{c-basic-offset} times -2 -@item * -@code{c-basic-offset} times 0.5 -@item / -@code{c-basic-offset} times -0.5 -@end table - -@cindex indentation functions - -When a function is used as offset, it's called an @dfn{indentation -function}. Such functions are useful when more context than just the -syntactic symbol is needed to get the desired indentation. -@xref{Indentation Functions}, and @ref{Custom Indentation Functions}, -for details about them. - -If the offset is a vector, its first element sets the absolute -indentation column, which will override any previous relative -indentation. It won't override additional relative indentation for -nested constructs, though. - -@vindex c-strict-syntax-p -@vindex strict-syntax-p (c-) -The offset can also be a list, in which case it is evaluated recursively -using the semantics described above. The first element of the list that -returns a non-@code{nil} value succeeds and the evaluation stops. If -none of the list elements return a non-@code{nil} value, then an offset -of 0 (zero) is used@footnote{There is however a variable -@code{c-strict-syntax-p} that, when set to non-@code{nil}, will cause an -error to be signaled in that case. It's now considered obsolete since -it doesn't work well with some of the alignment functions that now -returns @code{nil} instead of zero to be more usable in lists. You -should therefore leave @code{c-strict-syntax-p} set to @code{nil}.}. - -So, for example, because most of the default offsets are defined in -terms of @code{+}, @code{-}, and @code{0}, if you like the general -indentation style, but you use 4 spaces instead of 2 spaces per level, -you can probably achieve your style just by changing -@code{c-basic-offset} like so@footnote{You can try this interactively in -a C buffer by typing the text that appears in italics.}: +@item Top-level commands or the ``customization interface'' +Most simply, you can write @code{setq} and similar commands at the top +level of your @file{.emacs} file. When you load a @ccmode{} buffer, +it initializes its configuration from these global values (at least, +for those settings you have given values to), so it makes sense to +have these @code{setq} commands run @emph{before} @ccmode{} is first +initialized---in particular, before any call to @code{desktop-read} +(@pxref{Saving Emacs Sessions,,, emacs, GNU Emacs Manual}). For +example, you might set c-basic-offset thus: @example -@emph{M-x set-variable RET} -Set variable: @emph{c-basic-offset RET} -Set c-basic-offset to value: @emph{4 RET} +(setq c-basic-offset 4) @end example -@noindent -This would change +You can use the more user friendly Customization interface instead, +but this manual does not cover in detail how that works. To do this, +start by typing @kbd{M-x customize-group @key{RET} c @key{RET}}. +@xref{Easy Customization,,,@emacsman{}, @emacsmantitle{}}. +@c The following note really belongs in the Emacs manual. +Emacs normally writes the customizations at the end of your +@file{.emacs} file. If you use @code{desktop-read}, you should edit +your @file{.emacs} to place the call to @code{desktop-read} @emph{after} +the customizations. + +The first initialization of @ccmode{} puts a snapshot of the +configuration settings into the special style @code{user}. +@xref{Built-in Styles}. + +For basic use of Emacs, either of these ways of configuring is +adequate. However, the settings are then the same in all @ccmode{} +buffers and it can be clumsy to communicate them between programmers. +For more flexibility, you'll want to use one (or both) of @ccmode{}'s +more sophisticated facilities, hooks and styles. + +@item Hooks +An Emacs @dfn{hook} is a place to put Lisp functions that you want +Emacs to execute later in specific circumstances. +@xref{Hooks,,,@lispref{}, @lispreftitle{}}. @ccmode{} supplies a main +hook and a language-specific hook for each language it supports - any +functions you put onto these hooks get executed as the last part of a +buffer's initialization. Typically you put most of your customization +within the main hook, and use the language-specific hooks to vary the +customization settings between language modes. For example, if you +wanted different (non-standard) values of @code{c-basic-offset} in C +Mode and Java Mode buffers, you could do it like this: @example @group -int add( int val, int incr, int doit ) -@{ - if( doit ) - @{ - return( val + incr ); - @} - return( val ); -@} -@end group -@end example - -@noindent -to - -@example -@group -int add( int val, int incr, int doit ) -@{ - if( doit ) - @{ - return( val + incr ); - @} - return( val ); -@} +(defun my-c-mode-hook () + (setq c-basic-offset 3)) +(add-hook 'c-mode-hook 'my-c-mode-hook) + +(defun my-java-mode-hook () + (setq c-basic-offset 6)) +(add-hook 'java-mode-hook 'my-java-mode-hook) @end group @end example -To change indentation styles more radically, you will want to change the -offsets associated with other syntactic symbols. First, I'll show you -how to do that interactively, then I'll describe how to make changes to -your @file{.emacs} file so that your changes are more permanent. - -@menu -* Interactive Customization:: -* Permanent Customization:: -* Hooks:: -* Styles:: -* Advanced Customizations:: -@end menu - - -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Interactive Customization, Permanent Customization, , Customizing Indentation -@comment node-name, next, previous, up -@section Interactive Customization -@cindex customization, interactive -@cindex interactive customization -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -As an example of how to customize indentation, let's change the -style of this example@footnote{In this and subsequent examples, the -original code is formatted using the @samp{gnu} style unless otherwise -indicated. @xref{Styles}.}: +See @ref{CC Hooks} for more details on the use of @ccmode{} hooks. + +@item Styles +A @ccmode{} @dfn{style} is a coherent collection of customizations +with a name. At any time, exactly one style is active in each +@ccmode{} buffer, either the one you have selected or a default. +@ccmode{} is delivered with several existing styles. Additionally, +you can create your own styles, possibly based on these existing +styles. If you worked in a programming team called the ``Free +Group'', which had its own coding standards, you might well have this +in your @file{.emacs} file: @example -@group - 1: int add( int val, int incr, int doit ) - 2: @{ - 3: if( doit ) - 4: @{ - 5: return( val + incr ); - 6: @} - 7: return( val ); - 8: @} -@end group +(setq c-default-style '((java-mode . "java") + (awk-mode . "awk") + (other . "free-group-style"))) @end example -@noindent -to: +See @ref{Styles} for fuller details on using @ccmode{} styles and how +to create them. + +@item File Styles +A @dfn{file style} is a rarely used variant of the ``style'' mechanism +described above, which applies to an individual source file. To use +it, you set certain Emacs local variables in a special block at the +end of the source file. @xref{File Styles}. + +@item Hooks with Styles +For ultimate flexibility, you can use hooks and styles together. For +example, if your team were developing a product which required a +Linux driver, you'd probably want to use the ``linux'' style for the +driver, and your own team's style for the rest of the code. You +could achieve this with code like this in your @file{.emacs}: @example @group - 1: int add( int val, int incr, int doit ) - 2: @{ - 3: if( doit ) - 4: @{ - 5: return( val + incr ); - 6: @} - 7: return( val ); - 8: @} +(defun my-c-mode-hook () + (c-set-style + (if (and (buffer-file-name) + (string-match "/usr/src/linux" (buffer-file-name))) + "linux" + "free-group-style"))) +(add-hook 'c-mode-hook 'my-c-mode-hook) @end group @end example -In other words, we want to change the indentation of braces that open a -block following a condition so that the braces line up under the -conditional, instead of being indented. Notice that the construct we -want to change starts on line 4. To change the indentation of a line, -we need to see which syntactic components affect the offset calculations -for that line. Hitting @kbd{C-c C-s} on line 4 yields: - -@example -((substatement-open 44)) -@end example - -@noindent -so we know that to change the offset of the open brace, we need to -change the indentation for the @code{substatement-open} syntactic -symbol. - -To do this interactively, just hit @kbd{C-c C-o}. This prompts -you for the syntactic symbol to change, providing a reasonable default. -In this case, the default is @code{substatement-open}, which is just the -syntactic symbol we want to change! - -After you hit return, @ccmode{} will then prompt you for the new -offset value, with the old value as the default. The default in this -case is @samp{+}, but we want no extra indentation so enter -@samp{0} and @kbd{RET}. This will associate the offset 0 with the -syntactic symbol @code{substatement-open}. - -To check your changes quickly, just hit @kbd{C-c C-q} -(@code{c-indent-defun}) to reindent the entire function. The example -should now look like: +In a programming team, a hook is a also a good place for each member +to put his own personal preferences. For example, you might be the +only person in your team who likes Auto-newline minor mode. You could +have it enabled by default by placing the following in your +@file{.emacs}: @example @group - 1: int add( int val, int incr, int doit ) - 2: @{ - 3: if( doit ) - 4: @{ - 5: return( val + incr ); - 6: @} - 7: return( val ); - 8: @} +(defun my-turn-on-auto-newline () + (c-toggle-auto-newline 1)) +(add-hook 'c-mode-common-hook 'my-turn-on-auto-newline) @end group @end example - -Notice how just changing the open brace offset on line 4 is all we -needed to do. Since the other affected lines are indented relative to -line 4, they are automatically indented the way you'd expect. For more -complicated examples, this may not always work. The general approach to -take is to always start adjusting offsets for lines higher up in the -file, then reindent and see if any following lines need further -adjustments. - -@deffn Command c-set-offset symbol offset -@findex set-offset (c-) -@kindex C-c C-o -This is the command bound to @kbd{C-c C-o}. It provides a convenient -way to set offsets on @code{c-offsets-alist} both interactively (see -the example above) and from your mode hook. - -It takes two arguments when used programmatically: @var{symbol} is the -syntactic element symbol to change and @var{offset} is the new offset -for that syntactic element. -@end deffn - +@end table + +@menu +* CC Hooks:: +* Style Variables:: +* Styles:: +@end menu @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Permanent Customization, Hooks, Interactive Customization, Customizing Indentation -@comment node-name, next, previous, up -@section Permanent Customization -@cindex customization, permanent -@cindex permanent customization -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -To make your changes permanent, you need to add some lisp code to your -@file{.emacs} file. @ccmode{} supports many different ways to be -configured, from the straightforward way by setting variables globally -in @file{.emacs} or in the Customization interface, to the complex and -precisely controlled way by using styles and hook functions. - -The simplest way of customizing @ccmode{} permanently is to set the -variables in your @file{.emacs} with @code{setq} and similar commands. -So to make a permanent setting of @code{substatement-open} to 0, add -this to the @file{.emacs} file: - -@example -@group -(setq c-offsets-alist - '((substatement-open . 0))) -@end group -@end example - -When @ccmode{} initializes a buffer, it will fill out -@code{c-offsets-alist} with the remaining syntactic symbols according to -the style system. - -You can also use the more user friendly Customization interface, but -this manual does not cover how that works. - -Variables set like this at the top level in @file{.emacs} take effect in -all @ccmode{} buffers, regardless of language. The indentation style -related variables, e.g., @code{c-offsets-alist}, that you don't set this -way get their value from the style system (@pxref{Styles}), and they -therefore depend on the setting of @code{c-default-style}. Note that if -you use Customize, this means that the greyed-out default values -presented there might not be the ones you actually get, since the actual -values depend on the style, which may very well be different for -different languages. - -If you want to make more advanced configurations, e.g., language-specific -customization, setting global variables isn't enough. For that you can -use the language hooks, see @ref{Hooks}, and/or the style system, see -@ref{Styles}. - -@defopt c-style-variables-are-local-p -@vindex style-variables-are-local-p (c-) -By default, all style variables are buffer local, so that different -buffers can have different style settings. If you only use one style -in all the files you edit you might want to share them between buffers -so that a change take effect in all buffers. That's done by setting -this variable to @code{nil}. The value takes effect when @ccmode{} is -activated in a buffer for the first time in the Emacs session, so you -typically set it in your @file{.emacs} file and then restart Emacs. -@end defopt - - -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Hooks, Styles, Permanent Customization, Customizing Indentation +@node CC Hooks, Style Variables, Config Basics, Config Basics @comment node-name, next, previous, up @section Hooks @cindex mode hooks @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -@ccmode{} provides several hooks that you can use to customize the mode -according to your coding style. Each language mode has its own hook, -adhering to standard Emacs major mode conventions. There is also one -general hook and one package initialization hook: +@c The node name is "CC Hooks" rather than "Hooks" because of a bug in +@c some older versions of Info, e.g. the info.el in GNU Emacs 21.3. +@c If you go to "Config Basics" and hit <CR> on the xref to "CC +@c Hooks" the function Info-follow-reference searches for "*Note: CC +@c Hooks" from the beginning of the page. If this node were instead +@c named "Hooks", that search would spuriously find "*Note: +@c Hooks(elisp)" and go to the wrong node. + +@ccmode{} provides several hooks that you can use to customize the +mode for your coding style. The main hook is +@code{c-mode-common-hook}; typically, you'll put the bulk of your +customizations here. In addition, each language mode has its own +hook, allowing you to fine tune your settings individually for the +different @ccmode{} languages, and there is a package initialization +hook. Finally, there is @code{c-special-indent-hook}, which enables +you to solve anomalous indentation problems. It is described in +@ref{Other Indentation}, not here. All these hooks adhere to the +standard Emacs conventions. + +When you open a buffer, @ccmode{} first initializes it with the +currently active style (@pxref{Styles}). Then it calls +@code{c-mode-common-hook}, and finally it calls the language-specific +hook. Thus, any style settings done in these hooks will override +those set by @code{c-default-style}. @defvar c-initialization-hook @vindex initialization-hook (c-) Hook run only once per Emacs session, when @ccmode{} is initialized. +This is a good place to change key bindings (or add new ones) in any +of the @ccmode{} key maps. @xref{Sample .emacs File}. @end defvar @defvar c-mode-common-hook @@ -2628,12 +2340,10 @@ last thing when you enter that language mode. @end defvar -Note that all the language-specific mode setup that CC Mode does is done -prior to both @code{c-mode-common-hook} and the language specific hook. -That includes installing the indentation style, which can be mode -specific (and also is by default for Java mode). Thus, any style -settings done in @code{c-mode-common-hook} will override whatever -language-specific style is chosen by @code{c-default-style}. +Although these hooks are variables defined in @ccmode{}, you can give +them values before @ccmode{}'s code is loaded - indeed, this is the +only way to use @code{c-initialization-hook}. Their values aren't +overwritten when @ccmode{} gets loaded. Here's a simplified example of what you can add to your @file{.emacs} file to do things whenever any @ccmode{} language is edited. See the @@ -2649,9 +2359,96 @@ (add-hook 'c-mode-common-hook 'my-c-mode-common-hook) @end example +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Style Variables, Styles, CC Hooks, Config Basics +@comment node-name, next, previous, up +@section Style Variables +@cindex styles +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@cindex style variables +The variables that @ccmode{}'s style system control are called +@dfn{style variables}. Note that style variables are ordinary Lisp +variables, which the style system initializes; you can change their +values at any time (e.g. in a hook function). The style system can +also also set other variables, to some extent. @xref{Styles}. + +@dfn{Style variables} are handled specially in several ways: + +@itemize @bullet +@item +Style variables are by default buffer-local variables. However, they +can instead be made global by setting +@code{c-style-variables-are-local-p} to @code{nil} before @ccmode{} is +initialized. + +@item +@vindex c-old-style-variable-behavior +@vindex old-style-variable-behavior (c-) +The default global binding of any style variable (with two exceptions +- see below) is the special symbol @code{set-from-style}. When the +style system initializes a buffer-local copy of a style variable for a +@ccmode{} buffer, if its global binding is still that symbol then it +will be set from the current style. Otherwise it will retain its +global default@footnote{This is a big change from versions of +@ccmode{} earlier than 5.26, where such settings would get overridden +by the style system unless special precautions were taken. That was +changed since it was counterintuitive and confusing, especially to +novice users. If your configuration depends on the old overriding +behavior, you can set the variable +@code{c-old-style-variable-behavior} to non-@code{nil}.}. This +``otherwise'' happens, for example, when you've set the variable with +@code{setq} at the top level of your @file{.emacs} (@pxref{Config +Basics}). + +@item +The style variable @code{c-offsets-alist} (@pxref{c-offsets-alist}) is +an association list with an element for each syntactic symbol. It's +handled a little differently from the other style variables. It's +default global binding is the empty list @code{nil}, rather than +@code{set-from-style}. Before the style system is initialized, you +can add individual elements to @code{c-offsets-alist} by calling +@code{c-set-offset}(@pxref{c-offsets-alist}) just like you would set +other style variables with @code{setq}. Those elements will then +prevail when the style system later initializes a buffer-local copy of +@code{c-offsets-alist}. + +@item +The style variable @code{c-special-indent-hook} is also handled in a +special way. Styles can only add functions to this hook, not remove +them, so any global settings you put on it are always +preserved@footnote{This did not change in version 5.26.}. The value +you give this variable in a style definition can be either a function +or a list of functions. + +@item +The global bindings of the style variables get captured in the special +@code{user} style when the style system is first initialized. +@xref{Built-in Styles}, for details. +@end itemize + +The style variables are:@* +@code{c-indent-comment-alist}, +@code{c-indent-comments-syntactically-p} (@pxref{Indentation +Commands});@* +@code{c-doc-comment-style} (@pxref{Doc Comments});@* +@code{c-block-comment-prefix}, @code{c-comment-prefix-regexp} +(@pxref{Custom Filling and Breaking});@* +@code{c-hanging-braces-alist} (@pxref{Hanging Braces});@* +@code{c-hanging-colons-alist} (@pxref{Hanging Colons});@* +@code{c-hanging-semi&comma-criteria} (@pxref{Hanging Semicolons and +Commas});@* +@code{c-cleanup-list} (@pxref{Clean-ups});@* +@code{c-basic-offset} (@pxref{Customizing Indentation});@* +@code{c-offsets-alist} (@pxref{c-offsets-alist});@* +@code{c-comment-only-line-offset} (@pxref{Comment Line-Up});@* +@code{c-special-indent-hook}, @code{c-label-minimum-indentation} +(@pxref{Other Indentation});@* +@code{c-backslash-column}, @code{c-backslash-max-column} +(@pxref{Custom Macros}). @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Styles, Advanced Customizations, Hooks, Customizing Indentation +@node Styles, , Style Variables, Config Basics @comment node-name, next, previous, up @section Styles @cindex styles @@ -2668,86 +2465,23 @@ for any particular style, and pretty easily start editing new or existing code using these styles. -@cindex style variables -The variables that the style system affect are called @dfn{style -variables}. They are handled specially in several ways: - -@itemize @bullet -@item -Style variables are by default buffer local variables. However, they -can instead be made global by setting -@code{c-style-variables-are-local-p} to @code{nil} before @ccmode{} is -initialized. - -@item -@vindex c-old-style-variable-behavior -@vindex old-style-variable-behavior (c-) -The default value of any style variable (with two exceptions --- see -below) is the special symbol @code{set-from-style}. Variables that are -still set to that symbol when a @ccmode{} buffer is initialized will be -set according to the current style, otherwise they will keep their -current value@footnote{This is a big change from versions of @ccmode{} -earlier than 5.26, where such settings would get overridden by the style -system unless special precautions were taken. That was changed since it -was counterintuitive and confusing, especially to novice users. If your -configuration depends on the old overriding behavior, you can set the -variable @code{c-old-style-variable-behavior} to non-@code{nil}.}. - -Note that when we talk about the ``default value'' for a style variable, -we don't mean the @code{set-from-style} symbol that all style variables -are set to initially, but instead the value it will get at mode -initialization when neither a style nor a global setting has set its -value. - -The style variable @code{c-offsets-alist} is handled a little -differently from the other style variables. It's an association list, -and is thus by default set to the empty list, @code{nil}. When the -style system is initialized, any syntactic symbols already on it are -kept --- only the missing ones are filled in from the chosen style. - -The style variable @code{c-special-indent-hook} is also handled in a -special way. Styles may only add more functions on this hook, so the -global settings on it are always preserved@footnote{This did not change -in version 5.26.}. - -@item -The global settings of style variables get captured in the special -@code{user} style, which is used as the base for all the other styles. -@xref{Built-in Styles}, for details. -@end itemize - -The style variables are: -@code{c-basic-offset}, -@code{c-comment-only-line-offset}, -@code{c-block-comment-prefix}, -@code{c-comment-prefix-regexp}, -@code{c-cleanup-list}, -@code{c-hanging-braces-alist}, -@code{c-hanging-colons-alist}, -@code{c-hanging-semi&comma-criteria}, -@code{c-backslash-column}, -@code{c-backslash-max-column}, -@code{c-special-indent-hook}, -@code{c-label-minimum-indentation}, and -@code{c-offsets-alist}. - @menu -* Built-in Styles:: -* Choosing a Style:: -* Adding Styles:: -* File Styles:: +* Built-in Styles:: +* Choosing a Style:: +* Adding Styles:: +* File Styles:: @end menu @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Built-in Styles, Choosing a Style, , Styles +@node Built-in Styles, Choosing a Style, Styles, Styles @comment node-name, next, previous, up @subsection Built-in Styles @cindex styles, built-in @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! If you're lucky, one of @ccmode{}'s built-in styles might be just -what you're looking for. These include: +what you're looking for. These are: @table @code @item gnu @@ -2779,6 +2513,7 @@ Ellemtel@footnote{This document is available at @uref{http://www.doc.ic.ac.uk/lab/cplus/c++.rules/} among other places.}. +@c N.B. This URL was still valid at 2005/8/28 (ACM). @item linux @cindex Linux style @@ -2796,16 +2531,21 @@ value for @code{c-default-style} installs this style when you enter @code{java-mode}. +@item awk +@cindex AWK style +The style for editing AWK code. Note that the default value for +@code{c-default-style} installs this style when you enter +@code{awk-mode}. + @item user @cindex User style -This is a special style for several reasons. First, the -@ccmode{} customizations you do by using either the Customization -interface, or by writing @code{setq}'s at the top level of your -@file{.emacs} file, will be captured in the @code{user} style. Also, -all other styles implicitly inherit their settings from @code{user} -style. This means that for any styles you add via @code{c-add-style} -(@pxref{Adding Styles}) you need only define the differences between -your new style and @code{user} style. +This is a special style created by you. It consists of the factory +defaults for all the style variables as modified by the customizations +you do either with the Customization interface or by writing +@code{setq}s and @code{c-set-offset}s at the top level of your +@file{.emacs} file (@pxref{Config Basics}). The style system creates +this style as part of its initialization and doesn't modify it +afterwards. @end table @@ -2824,24 +2564,25 @@ interactively like this: @example -@kbd{C-c . @var{style-name} RET} +@kbd{C-c . @var{style-name} @key{RET}} @end example -Note that all style names are case insensitive, even the ones you -define. +You can use the @key{TAB} in the normal way to do completion on the +style name. Note that all style names are case insensitive, even the +ones you define yourself. Setting a style in this way does @emph{not} automatically reindent your file. For commands that you can use to view the effect of your changes, -see @ref{Commands}. +see @ref{Indentation Commands} and @ref{Filling and Breaking}. @end deffn The default style in all newly created buffers is @code{gnu}, except -in Java mode where it's @code{java}. Although the @code{user} style -is not the default style, any style variable settings you do with the -Customization interface or on the top level in your @file{.emacs} file -will by default override the style system, so you don't need to set -@code{c-default-style} to @code{user} to see the effect of such -settings. +in Java and AWK modes where it's @code{java} and @code{awk}. + +Remember that if you set a style variable with the Customization +interface or at the top level of your @file{.emacs} file before the +style system is initialised (@pxref{Config Basics}), this setting will +override the one that the style system would have given the variable. @defopt c-default-style @vindex default-style (c-) @@ -2865,13 +2606,15 @@ @item If @samp{other} is not found then the @samp{gnu} style is used. - -@item +@end enumerate + In all cases, the style described in @code{c-default-style} is installed @emph{before} the language hooks are run, so you can always override this setting by including an explicit call to @code{c-set-style} in your language mode hook, or in @code{c-mode-common-hook}. -@end enumerate + +The standard value of @code{c-default-style} is @w{@code{((java-mode +. "java") (awk-mode . "awk") (other . "gnu"))}}. @end defopt @defvar c-indentation-style @@ -2891,49 +2634,55 @@ create a new @dfn{style definition}, possibly based on an existing style. To do this, put the new style's settings into a list with the following format - the list can then be passed as an argument to the -function @code{c-add-style}: +function @code{c-add-style}. You can see an example of a style +definition in @ref{Sample .emacs File}. @cindex style definition -@defvr {List} style definition +@c @defvr {List} style definition +@table @asis +@item Structure of a Style Definition List ([@var{base-style}] [(@var{variable} . @var{value}) @dots{}]) Optional @var{base-style}, if present, must be a string which is the name of the @dfn{base style} from which this style inherits. At most one @var{base-style} is allowed in a style definition. If -@var{base-style} is not specified, the style inherits from a table of -default values@footnote{This table is stored internally in the -variable c-fallback-style. It is computed during the initialisation -of @ccmode{} from the factory defaults of the style variables and any -global values they may have been given since starting Emacs.} instead. -All styles eventually inherit from this internal table. Style loops -generate errors. The list of pre-existing styles can be seen in -@ref{Built-in Styles}. +@var{base-style} is not specified, the style inherits from the table +of factory default values@footnote{This table is stored internally in +the variable c-fallback-style.} instead. All styles eventually +inherit from this internal table. Style loops generate errors. The +list of pre-existing styles can be seen in @ref{Built-in Styles}. The dotted pairs (@var{variable} . @var{value}) each consist of a variable and the value it is to be set to when the style is later -activated.@footnote{In certain circumstances, this value can get -overridden by another value.} The variable can be either a @ccmode{} -style variable or an arbitrary Emacs variable. In the latter case, it -is @emph{not} made buffer local by the @ccmode{} style system. -@end defvr +activated.@footnote{Note that if the variable has been given a value +by the Customization interface or a @code{setq} at the top level of +your @file{.emacs}, this value will override the one the style system +tries to give it. @xref{Config Basics}.} The variable can be either a +@ccmode{} style variable or an arbitrary Emacs variable. In the +latter case, it is @emph{not} made buffer-local by the @ccmode{} style +system. +@c @end defvr Two variables are treated specially in the dotted pair list: @table @code @item c-offsets-alist -The value is in turn a dotted list on the form - -(@var{syntactic-symbol} . @var{offset}) - -as described in @ref{Customizing Indentation}. These are passed to -@code{c-set-offset} so there is no need to set every syntactic symbol in -your style, only those that are different from the inherited style. +The value is in turn a list of dotted pairs of the form + +@example +(@r{@var{syntactic-symbol}} . @r{@var{offset}}) +@end example + +as described in @ref{c-offsets-alist}. These are passed to +@code{c-set-offset} so there is no need to set every syntactic symbol +in your style, only those that are different from the inherited style. @item c-special-indent-hook The value is added to @code{c-special-indent-hook} using @code{add-hook}, so any functions already on it are kept. If the value is a list, each element of the list is added with @code{add-hook}. @end table +@end table Styles are kept in the @code{c-style-alist} variable, but you should never modify this variable directly. Instead, @ccmode{} @@ -2946,9 +2695,12 @@ above. If @var{stylename} already exists in @code{c-style-alist} then it is replaced by @var{description}. (Note, this replacement is total. The old style is @emph{not} merged into the new one.) -Otherwise, a new style is added. If the optional @var{set-p} is -non-@code{nil} then the new style is applied to the current buffer as -well. +Otherwise, a new style is added. + +If the optional @var{set-p} is non-@code{nil} then the new style is +applied to the current buffer as well. The use of this facility is +deprecated and it might be removed from @ccmode{} in a future release. +You should use @code{c-set-style} instead. The sample @file{.emacs} file provides a concrete example of how a new style can be added and automatically set. @xref{Sample .emacs File}. @@ -2962,7 +2714,7 @@ @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node File Styles, , Adding Styles, Styles +@node File Styles, , Adding Styles, Styles @comment node-name, next, previous, up @subsection File Styles @cindex styles, file local @@ -2970,175 +2722,513 @@ @cindex file local variables -The Emacs manual describes how you can customize certain variables on -a per-file basis by including a @dfn{file local variable} block at the -end of the file. So far, you've only seen a functional interface to -@ccmode{} customization, which can't be used there. @ccmode{} -provides two variables allow customization of the indentation style on -a per-file basis: +The Emacs manual describes how you can customize certain variables on a +per-file basis by including a @dfn{file local variable} block at the end +of the file (@pxref{File Variables,, Local Variables in Files, @emacsman{}, +@emacsmantitle{}}). + +So far, you've only seen a functional interface for setting styles in +@ccmode{}, and this can't be used here. @ccmode{} fills the gap by +providing two variables for use in a file's local variable list. +Don't use them anywhere else! These allow you to customize the style +on a per-file basis: @defvar c-file-style @vindex file-style (c-) -This variable can be set to a style name string. When the file is -visited, @ccmode{} will automatically set the file's style to this -one using @code{c-set-style}. +Set this variable to a style name string in the Local Variables list. +From now on, when you visit the file, @ccmode{} will automatically set +the file's style to this one using @code{c-set-style}. @end defvar @defvar c-file-offsets @vindex file-offsets (c-) -This variable takes an association list similar to what is allowed in -@code{c-offsets-alist}. When the file is visited, @ccmode{} will -automatically institute these offsets using @code{c-set-offset}. +Set this variable (in the Local Variables list) to an association list +of the same format as @code{c-offsets-alist}. From now on, when you +visit the file, @ccmode{} will automatically institute these offsets +using @code{c-set-offset}. @end defvar -Note that file style settings (i.e., @code{c-file-style}) are applied -before file offset settings (i.e., @code{c-file-offsets}). Also, if -either of these are set in a file's local variable section, all the -style variable values are made local to that buffer. - +Note that file style settings (i.e. @code{c-file-style}) are applied +before file offset settings +(i.e. @code{c-file-offsets})@footnote{Also, if either of these are set +in a file's local variable section, all the style variable values are +made local to that buffer, even if +@code{c-style-variables-are-local-p} is @code{nil}. Since this +variable is virtually always non-@code{nil} anyhow, you're unlikely to +notice this effect.}. + +If you set any variables, including style variables, by the file local +variables mechanism, these settings take priority over all other +settings, even those in your mode hooks (@pxref{CC Hooks}). If you +use @code{c-file-style} or @code{c-file-offsets} and also explicitly +set a style variable in a local variable block, the explicit setting +will take priority. @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Advanced Customizations, , Styles, Customizing Indentation +@node Custom Filling and Breaking, Custom Auto-newlines, Config Basics, Top @comment node-name, next, previous, up -@section Advanced Customizations +@chapter Customizing Filling and Line Breaking @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -For most users, @ccmode{} will support their coding styles with very -little need for more advanced customizations. Usually, one of the -standard styles (@pxref{Built-in Styles}) will do the trick. At most, -perhaps one of the syntactic symbol offsets will need to be tweaked -slightly, or maybe @code{c-basic-offset} will need to be changed. -However, some styles require a more flexible framework for -customization, and one of the real strengths of @ccmode{} is that the -syntactic analysis model provides just such a framework. This allows -you to implement custom indentation calculations for situations not -handled by the mode directly. - -@menu -* Custom Indentation Functions:: -* Custom Brace and Colon Hanging:: -* Customizing Semicolons and Commas:: -* Other Special Indentations:: -@end menu - -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Custom Indentation Functions, Custom Brace and Colon Hanging, , Advanced Customizations -@comment node-name, next, previous, up -@subsection Custom Indentation Functions -@cindex customization, indentation functions -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -The most flexible way to customize @ccmode{} is by writing custom -indentation functions, and associating them with specific syntactic -symbols (@pxref{Syntactic Symbols}). @ccmode{} itself uses indentation -functions to provide more sophisticated indentation, for example when -lining up C++ stream operator blocks: +Since there's a lot of normal text in comments and string literals, +@ccmode{} provides features to edit these like in text mode. It does +this by hooking in on the different line breaking functions and tuning +relevant variables as necessary. + +@vindex c-comment-prefix-regexp +@vindex comment-prefix-regexp (c-) +@cindex comment line prefix +@vindex comment-start +@vindex comment-end +@vindex comment-start-skip +@vindex paragraph-start +@vindex paragraph-separate +@vindex paragraph-ignore-fill-prefix +@vindex adaptive-fill-mode +@vindex adaptive-fill-regexp +@vindex adaptive-fill-first-line-regexp +To make Emacs recognize comments and treat text in them as normal +paragraphs, @ccmode{} makes several standard +variables@footnote{@code{comment-start}, @code{comment-end}, +@code{comment-start-skip}, @code{paragraph-start}, +@code{paragraph-separate}, @code{paragraph-ignore-fill-prefix}, +@code{adaptive-fill-mode}, @code{adaptive-fill-regexp}, and +@code{adaptive-fill-first-line-regexp}.} buffer-local and modifies them +according to the language syntax and the comment line prefix. + +@defopt c-comment-prefix-regexp +@vindex comment-prefix-regexp (c-) +This style variable contains the regexp used to recognize the +@dfn{comment line prefix}, which is the line decoration that starts +every line in a comment. The variable is either the comment line +prefix itself, or (more usually) an association list with different +values for different languages. The symbol for the major mode is +looked up in the alist to get the regexp for the language, and if it +isn't found then the special symbol @samp{other} is looked up instead. + +When a comment line gets divided by @kbd{M-j} or the like, @ccmode{} +inserts the comment line prefix from a neighbouring line at the start +of the new line. The default value of c-comment-prefix-regexp is +@samp{//+\\|\\**}, which matches C++ style line comments like + +@example +// blah blah +@end example + +@noindent +with two or more slashes in front of them, and the second and +subsequent lines of C style block comments like + +@example +@group +/* + * blah blah + */ +@end group +@end example + +@noindent +with zero or more stars at the beginning of every line. If you change +this variable, please make sure it still matches the comment starter +(i.e. @code{//}) of line comments @emph{and} the line prefix inside +block comments. + +@findex c-setup-paragraph-variables +@findex setup-paragraph-variables (c-) +Also note that since @ccmode{} uses the value of +@code{c-comment-prefix-regexp} to set up several other variables at +mode initialization, there won't be any effect if you just change it +inside a @ccmode{} buffer. You need to call the command +@code{c-setup-paragraph-variables} too, to update those other +variables. That's also the case if you modify +@code{c-comment-prefix-regexp} in a mode hook, since @ccmode{} will +already have set up these variables before calling the hook. +@end defopt + +In comments, @ccmode{} uses @code{c-comment-prefix-regexp} to adapt +the line prefix from the other lines in the comment. + +@vindex adaptive-fill-mode +@cindex Adaptive Fill mode +@ccmode{} uses adaptive fill mode (@pxref{Adaptive Fill,,, emacs, GNU +Emacs Manual}) to make Emacs correctly keep the line prefix when +filling paragraphs. That also makes Emacs preserve the text +indentation @emph{inside} the comment line prefix. E.g. in the +following comment, both paragraphs will be filled with the left +margins of the texts kept intact: + +@example +@group +/* Make a balanced b-tree of the nodes in the incoming + * stream. But, to quote the famous words of Donald E. + * Knuth, + * + * Beware of bugs in the above code; I have only + * proved it correct, not tried it. + */ +@end group +@end example + +@findex c-setup-filladapt +@findex setup-filladapt (c-) +@findex filladapt-mode +@vindex filladapt-mode +@cindex Filladapt mode +It's also possible to use other adaptive filling packages, notably Kyle +E. Jones' Filladapt package@footnote{It's available from +@uref{http://www.wonderworks.com/}. As of version 2.12, it does however +lack a feature that makes it work suboptimally when +@code{c-comment-prefix-regexp} matches the empty string (which it does +by default). A patch for that is available from +@uref{http://cc-mode.sourceforge.net/,, the CC Mode web site}.}, +@c 2005/11/22: The above is still believed to be the case. +which handles things like bulleted lists nicely. There's a convenience +function @code{c-setup-filladapt} that tunes the relevant variables in +Filladapt for use in @ccmode{}. Call it from a mode hook, e.g. with +something like this in your @file{.emacs}: + +@example +(defun my-c-mode-common-hook () + (c-setup-filladapt) + (filladapt-mode 1)) +(add-hook 'c-mode-common-hook 'my-c-mode-common-hook) +@end example + +@defopt c-block-comment-prefix +@vindex block-comment-prefix (c-) +@vindex c-comment-continuation-stars +@vindex comment-continuation-stars (c-) +Normally the comment line prefix inserted for a new line inside a +comment is deduced from other lines in it. However there's one +situation when there's no hint about what the prefix should look like, +namely when a block comment is broken for the first time. This style +variable@footnote{In versions before 5.26, this variable was called +@code{c-comment-continuation-stars}. As a compatibility measure, +@ccmode{} still uses the value on that variable if it's set.} is used +then as the comment prefix. It defaults to @samp{* +}@footnote{Actually, this default setting of +@code{c-block-comment-prefix} typically gets overriden by the default +style @code{gnu}, which sets it to blank. You can see the line +splitting effect described here by setting a different style, +e.g. @code{k&r} @xref{Choosing a Style}.}, which makes a comment + +@example +/* Got O(n^2) here, which is a Bad Thing. */ +@end example + +@noindent +break into @example @group - 1: void main(int argc, char**) - 2: @{ - 3: cout << "There were " - 4: << argc - 5: << "arguments passed to the program" - 6: << endl; - 7: @} +/* Got O(n^2) here, which + * is a Bad Thing. */ @end group @end example -In this example, lines 4 through 6 are assigned the @code{stream-op} -syntactic symbol. Here, @code{stream-op} has an offset of @code{+}, and -with a @code{c-basic-offset} of 2, you can see that lines 4 through 6 -are simply indented two spaces to the right of line 3. But perhaps we'd -like @ccmode{} to be a little more intelligent so that it aligns -all the @samp{<<} symbols in lines 3 through 6. To do this, we have -to write a custom indentation function which finds the column of the first -stream operator on the first line of the statement. Here is sample -lisp code implementing this: - -@example -(defun c-lineup-streamop (langelem) - (save-excursion - (goto-char (cdr langelem)) - (re-search-forward "<<\\|>>" (c-point 'eol) 'move) - (goto-char (match-beginning 0)) - (vector (current-column)))) -@end example - -Indentation functions take a single argument, which is a syntactic -component cons cell (@pxref{Syntactic Analysis}). The function can -return an integer which is added to the running total indentation for -the line, or a vector containing an integer which is an absolute -column to align to. Usually an absolute column is wanted when -aligning to existing text, as in this example. - -The function should return @code{nil} if it's used in a situation where -it doesn't want to make any decision. If the function is used in a list -expression (@pxref{Customizing Indentation}), that will cause @ccmode{} -to go on and check the next entry in the list. - -Now, to associate the function @code{c-lineup-streamop} with the -@code{stream-op} syntactic symbol, we can add something like the -following to our @code{c++-mode-hook}@footnote{It probably makes more -sense to add this to @code{c++-mode-hook} than @code{c-mode-common-hook} -since stream operators are only relevant for C++.}: - -@example -(c-set-offset 'stream-op 'c-lineup-streamop) -@end example - -Now the function looks like this after reindenting (using @kbd{C-c -C-q}): +Note that it won't work to adjust the indentation by putting leading +spaces in @code{c-block-comment-prefix}, since @ccmode{} still uses the +normal indentation engine to indent the line. Thus, the right way to +fix the indentation is by customizing the @code{c} syntactic symbol. It +defaults to @code{c-lineup-C-comments}, which handles the indentation of +most common comment styles, see @ref{Line-Up Functions}. +@end defopt + +@defopt c-ignore-auto-fill +@vindex ignore-auto-fill (c-) +When auto fill mode is enabled, @ccmode{} can selectively ignore it +depending on the context the line break would occur in, e.g. to never +break a line automatically inside a string literal. This variable +takes a list of symbols for the different contexts where auto-filling +never should occur: + +@table @code +@item string +Inside a string or character literal. +@item c +Inside a C style block comment. +@item c++ +Inside a C++ style line comment. +@item cpp +Inside a preprocessor directive. +@item code +Anywhere else, i.e. in normal code. +@end table + +By default, @code{c-ignore-auto-fill} is set to @code{(string cpp +code)}, which means that when auto-fill mode is activated, +auto-filling only occurs in comments. In literals, it's often +desirable to have explicit control over newlines. In preprocessor +directives, the necessary @samp{\} escape character before the newline +is not automatically inserted, so an automatic line break would +produce invalid code. In normal code, line breaks are normally +dictated by some logical structure in the code rather than the last +whitespace character, so automatic line breaks there will produce poor +results in the current implementation. +@end defopt + +@vindex comment-multi-line +If inside a comment and @code{comment-multi-line} (@pxref{Auto Fill,,, +@emacsman{}, @emacsmantitle{}} is non-@code{nil}, the indentation and +line prefix are preserved. If inside a comment and +@code{comment-multi-line} is @code{nil}, a new comment of the same +type is started on the next line and indented as appropriate for +comments. + +Note that @ccmode{} sets @code{comment-multi-line} to @code{t} at +startup. The reason is that @kbd{M-j} could otherwise produce sequences +of single line block comments for texts that should logically be treated +as one comment, and the rest of the paragraph handling code +(e.g. @kbd{M-q} and @kbd{M-a}) can't cope with that, which would lead to +inconsistent behavior. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Custom Auto-newlines, Clean-ups, Custom Filling and Breaking, Top +@comment node-name, next, previous, up +@chapter Customizing Auto-newlines +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@ccmode{} determines whether to insert auto-newlines in two basically +different ways, depending on the character just typed: + +@table @asis +@item Braces and Colons +@ccmode{} first determines the syntactic context of the brace or colon +(@pxref{Syntactic Symbols}), then looks for a corresponding element in +an alist. This element specifies where to put newlines - this is any +combination of before and after the brace or colon. If no alist +element is found, newlines are inserted both before and after a brace, +but none are inserted around a colon. See @ref{Hanging Braces} and +@ref{Hanging Colons}. + +@item Semicolons and Commas +The variable @code{c-hanging-semi&comma-criteria} contains a list of +functions which determine whether to insert a newline after a newly +typed semicolon or comma. @xref{Hanging Semicolons and Commas}. +@end table + +The names of these configuration variables contain @samp{hanging} +because they let you @dfn{hang} the pertinent characters. A character +which introduces a C construct is said to @dfn{hang on the right} when +it appears at the end of a line after other code, being separated by a +line break from the construct it introduces, like the opening brace in: @example @group - 1: void main(int argc, char**) - 2: @{ - 3: cout << "There were " - 4: << argc - 5: << " arguments passed to the program" - 6: << endl; - 7: @} +while (i < MAX) @{ + total += entry[i]; + entry [i++] = 0; +@} @end group @end example -Custom indentation functions can be as simple or as complex as you like, -and any syntactic symbol that appears in @code{c-offsets-alist} can have -a custom indentation function associated with it. - -@ccmode{} comes with an extensive set of predefined indentation -functions, not all of which are used by the default styles. So there's -a good chance the function you want already exists. @xref{Indentation -Functions}, for a list of them. If you have written an indentation -function that you think is generally useful, you're very welcome to -contribute it; please contact @email{bug-cc-mode@@gnu.org}. +@noindent +A character @dfn{hangs on the left} when it appears at the start of +the line after the construct it closes off, like the above closing +brace. + +The next chapter, ``Clean-ups'', describes how to configure @ccmode{} +to remove these automatically added newlines in certain specific +circumstances. @xref{Clean-ups}. + +@menu +* Hanging Braces:: +* Hanging Colons:: +* Hanging Semicolons and Commas:: +@end menu @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Custom Brace and Colon Hanging, Customizing Semicolons and Commas, Custom Indentation Functions, Advanced Customizations +@node Hanging Braces, Hanging Colons, Custom Auto-newlines, Custom Auto-newlines @comment node-name, next, previous, up -@subsection Custom Brace and Colon Hanging +@section Hanging Braces +@cindex hanging braces +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +To specify which kinds of braces you want auto-newlines put around, +you set the style variable @code{c-hanging-braces-alist}. Its +structure and semantics are described in this section. Details of how +to set it up, and its relationship to CC Mode's style system are given +in @ref{Style Variables}. + +Say you wanted an auto-newline after (but not before) the following +@samp{@{}: + +@example +if (foo < 17) @{ +@end example + +@noindent +First you need to find the @dfn{syntactic context} of the brace---type +a @key{RET} before the brace to get it on a line of its +own@footnote{Also insert a @samp{\} at the end of the previous line if +you're in AWK Mode.}, then type @kbd{C-c C-s}. That will tell you +something like: + +@example +((substatement-open 1061)) +@end example + +@noindent +So here you need to put the entry @code{(substatement-open . (after))} +into @code{c-hanging-braces-alist}. + +If you don't want any auto-newlines for a particular syntactic symbol, +put this into @code{c-hanging-braces-alist}: + +@example +(brace-entry-open) +@end example + +If some brace syntactic symbol is not in @code{c-hanging-brace-alist}, +its entry is taken by default as @code{(before after)}---insert a +newline both before and after the brace. In place of a +``before/after'' list you can specify a function in this alist---this +is useful when the auto newlines depend on the code around the brace. + +@defopt c-hanging-braces-alist +@vindex hanging-braces-alist (c-) + +This variable is an association list which maps syntactic symbols to +lists of places to insert a newline. @xref{Association +Lists,,,@lispref{}, @lispreftitle{}}. The key of each element is the +syntactic symbol, the associated value is either @code{nil}, a list, +or a function. + +@table @asis +@item The Key - the syntactic symbol +The syntactic symbols that are useful as keys in this list are +@code{brace-list-intro}, @code{statement-cont}, +@code{inexpr-class-open}, @code{inexpr-class-close}, and all the +@code{*-open} and @code{*-close} symbols. @xref{Syntactic Symbols}, +for a more detailed description of these syntactic symbols, except for +@code{inexpr-class-open} and @code{inexpr-class-close}, which aren't +actual syntactic symbols. Elements with any other value as a key get +ignored. + +The braces of anonymous inner classes in Java are given the special +symbols @code{inexpr-class-open} and @code{inexpr-class-close}, so that +they can be distinguished from the braces of normal classes@footnote{The +braces of anonymous classes produce a combination of +@code{inexpr-class}, and @code{class-open} or @code{class-close} in +normal indentation analysis.}. + +Note that the aggregate constructs in Pike mode, @samp{(@{}, @samp{@})}, +@samp{([}, @samp{])}, and @samp{(<}, @samp{>)}, do not count as brace +lists in this regard, even though they do for normal indentation +purposes. It's currently not possible to set automatic newlines on +these constructs. + +@item The associated value - the ``ACTION'' list or function +The value associated with each syntactic symbol in this association +list is called an @var{action}, which can be either a list or a +function which returns a list. @xref{Custom Braces}, for how to use +a function as a brace hanging @var{action}. + +The list @var{action} (or the list returned by @var{action} when it's +a function) contains some combination of the symbols @code{before} and +@code{after}, directing @ccmode{} where to put newlines in +relationship to the brace being inserted. Thus, if the list contains +only the symbol @code{after}, then the brace hangs on the right side +of the line, as in: + +@example +// here, open braces always `hang' +void spam( int i ) @{ + if( i == 7 ) @{ + dosomething(i); + @} +@} +@end example + +When the list contains both @code{after} and @code{before}, the braces +will appear on a line by themselves, as shown by the close braces in +the above example. The list can also be empty, in which case newlines +are added neither before nor after the brace. +@end table + +If a syntactic symbol is missing entirely from +@code{c-hanging-braces-alist}, it's treated in the same way as an +@var{action} with a list containing @code{before} and @code{after}, so +that braces by default end up on their own line. + +For example, the default value of @code{c-hanging-braces-alist} is: + +@example +((brace-list-open) + (brace-entry-open) + (statement-cont) + (substatement-open after) + (block-close . c-snug-do-while) + (extern-lang-open after) + (namespace-open after) + (module-open after) + (composition-open after) + (inexpr-class-open after) + (inexpr-class-close before)) +@end example + +@noindent which says that @code{brace-list-open}, +@code{brace-entry-open} and @code{statement-cont}@footnote{Brace lists +inside statements, such as initializers for static array variables +inside functions in C, are recognized as @code{statement-cont}. All +normal substatement blocks are recognized with other symbols.} braces +should both hang on the right side and allow subsequent text to follow +on the same line as the brace. Also, @code{substatement-open}, +@code{extern-lang-open}, and @code{inexpr-class-open} braces should hang +on the right side, but subsequent text should follow on the next line. +The opposite holds for @code{inexpr-class-close} braces; they won't +hang, but the following text continues on the same line. Here, in the +@code{block-close} entry, you also see an example of using a function as +an @var{action}. In all other cases, braces are put on a line by +themselves. +@end defopt + +@menu +* Custom Braces:: +@end menu + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Custom Braces, , Hanging Braces, Hanging Braces +@comment node-name, next, previous, up +@subsection Custom Brace Hanging @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @vindex c-hanging-braces-alist @vindex hanging-braces-alist (c-) +@cindex action functions Syntactic symbols aren't the only place where you can customize -@ccmode{} with the lisp equivalent of callback functions. Brace -``hanginess'' can also be determined by custom functions associated with -syntactic symbols on the @code{c-hanging-braces-alist} style variable. -Remember that @var{action}'s are typically a list containing some -combination of the symbols @code{before} and @code{after} -(@pxref{Hanging Braces}). However, an @var{action} can also be a -function which gets called when a brace matching that syntactic symbol -is entered. +@ccmode{} with the lisp equivalent of callback functions. Remember +that @var{action}s are usually a list containing some combination of +the symbols @code{before} and @code{after} (@pxref{Hanging Braces}). +For more flexibility, you can instead specify brace ``hanginess'' by +giving a synctactic symbol an @dfn{action function} in +@code{c-hanging-braces-alist}; this function determines the +``hanginess'' of a brace, usually by looking at the code near it. @cindex customization, brace hanging -These @var{action} functions are called with two arguments: the -syntactic symbol for the brace, and the buffer position at which the -brace was inserted. The @var{action} function is expected to return a -list containing some combination of @code{before} and @code{after}, -including neither of them (i.e., @code{nil}). This return value has the -normal brace hanging semantics. +An action function is called with two arguments: the syntactic symbol +for the brace (e.g. @code{substatement-open}), and the buffer position +where the brace has been inserted. Point is undefined on entry to an +action function, but the function must preserve it (e.g. by using +@code{save-excursion}). The return value should be a list containing +some combination of @code{before} and @code{after}, including neither +of them (i.e. @code{nil}). + +@defvar c-syntactic-context +@vindex syntactic-context (c-) +During the call to the indentation or brace hanging @var{action} +function, this variable is bound to the full syntactic analysis list. +This might be, for example, @samp{((block-close 73))}. Don't ever +give @code{c-syntactic-context} a value yourself---this would disrupt +the proper functioning of @ccmode{}. + +This variable is also bound in three other circumstances: +(i)@tie{}when calling a c-hanging-semi&comma-criteria function +(@pxref{Hanging Semicolons and Commas}; (ii)@tie{}when calling a +line-up function (@pxref{Custom Line-Up}; (iii)@tie{}when calling a +c-special-indent-hook function (@pxref{Other Indentation}). +@end defvar As an example, @ccmode{} itself uses this feature to dynamically determine the hanginess of braces which close ``do-while'' @@ -3186,54 +3276,92 @@ In all other cases, it returns the list @samp{(before after)} so that the brace appears on a line by itself. -@defvar c-syntactic-context -@vindex syntactic-context (c-) -During the call to the indentation or brace hanging @var{action} -function, this variable is bound to the full syntactic analysis list. -@end defvar +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Hanging Colons, Hanging Semicolons and Commas, Hanging Braces, Custom Auto-newlines +@comment node-name, next, previous, up +@section Hanging Colons +@cindex hanging colons +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @cindex customization, colon hanging @vindex c-hanging-colons-alist @vindex hanging-colons-alist (c-) -Note that for symmetry, colon hanginess should be customizable by -allowing function symbols as @var{action}s on the -@code{c-hanging-colons-alist} style variable. Since no use has actually -been found for this feature, it isn't currently implemented! - + +Using a mechanism similar to brace hanging (@pxref{Hanging Braces}), +colons can also be made to hang using the style variable +@code{c-hanging-colons-alist} - When a colon is typed, @ccmode +determines its syntactic context, looks this up in the alist +@code{c-changing-colons-alist} and inserts up to two newlines +accordingly. Here, however, If @ccmode fails to find an entry for a +syntactic symbol in the alist, no newlines are inserted around the +newly typed colon. + +@defopt c-hanging-colons-alist +@vindex hanging-colons-alist (c-) + +@table @asis +@item The Key - the syntactic symbol +The syntactic symbols appropriate as keys in this association list +are: @code{case-label}, @code{label}, @code{access-label}, +@code{member-init-intro}, and @code{inher-intro}. @xref{Syntactic +Symbols}. Elements with any other value as a key get ignored. + +@item The associate value - the ``ACTION'' list +The @var{action} here is simply a list containing a combination of the +symbols @code{before} and @code{after}. Unlike in +@code{c-hanging-braces-alist}, functions as @var{actions} are not +supported - there doesn't seem to be any need for them. +@end table +@end defopt + +In C++, double-colons are used as a scope operator but because these +colons always appear right next to each other, newlines before and after +them are controlled by a different mechanism, called @dfn{clean-ups} in +@ccmode{}. @xref{Clean-ups}, for details. @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Customizing Semicolons and Commas, Other Special Indentations, Custom Brace and Colon Hanging, Advanced Customizations +@node Hanging Semicolons and Commas, , Hanging Colons, Custom Auto-newlines @comment node-name, next, previous, up -@subsection Customizing Semicolons and Commas +@section Hanging Semicolons and Commas +@cindex hanging semicolons +@cindex hanging commas @cindex customization, semicolon newlines @cindex customization, comma newlines @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -You can also customize the insertion of newlines after semicolons and -commas when the auto-newline minor mode is enabled (@pxref{Minor -Modes}). - @defopt c-hanging-semi&comma-criteria @vindex hanging-semi&comma-criteria (c-) -This style variable takes a list of hooks that get called when a -semicolon or comma is inserted. The hooks are called in order without -arguments, and are expected to return one of the following values: +This style variable takes a list of functions; these get called when +you type a semicolon or comma. The functions are called in order +without arguments. When these functions are entered, point is just +after the newly inserted @samp{;} or @samp{,} and they must preserve +point (e.g., by using @code{save-excursion}). During the call, the +variable @code{c-syntactic-context} is bound to the syntactic context +of the current line@footnote{This was first introduced in @ccmode{} +5.31.} @pxref{Custom Braces}. These functions don't insert newlines +themselves, rather they direct @ccmode{} whether or not to do so. +They should return one of the following values: @table @code @item t -A newline is inserted, and no more functions from the list are called. +A newline is to be inserted after the @samp{;} or @samp{,}, and no +more functions from the list are to be called. @item stop -No more functions from the list are called, but no newline is -inserted. +No more functions from the list are to be called, and no newline is to +be inserted. @item nil -No determination is made, and the next function in the list is called. +No determination has been made, and the next function in the list is +to be called. @end table -If every function in the list is called without a determination being -made, then no newline is added. The default value for this variable is a -list containing a single function which inserts newlines only after -semicolons which do not appear inside parenthesis lists (i.e., those -that separate @code{for}-clause statements). +Note that auto-newlines are never inserted @emph{before} a semicolon +or comma. If every function in the list is called without a +determination being made, then no newline is added. + +In AWK mode, this variable is set by default to @code{nil}. In the +other modes, the default value is a list containing a single function, +@code{c-semi&comma-inside-parenlist}. This inserts newlines after all +semicolons, apart from those separating @code{for}-clause statements. @end defopt @defun c-semi&comma-no-newlines-before-nonblanks @@ -3266,234 +3394,715 @@ @ccmode{} also comes with the criteria function @code{c-semi&comma-no-newlines-for-oneline-inliners}, which suppresses newlines after semicolons inside one-line inline method definitions -(e.g., in C++ or Java). +(e.g. in C++ or Java). @end defun @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Other Special Indentations, , Customizing Semicolons and Commas, Advanced Customizations +@node Clean-ups, Indentation Engine Basics, Custom Auto-newlines, Top @comment node-name, next, previous, up -@subsection Other Special Indentations +@chapter Clean-ups +@cindex clean-ups @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -Here are the remaining odds and ends regarding indentation: - -@defopt c-label-minimum-indentation -@vindex label-minimum-indentation (c-) -In @samp{gnu} style (@pxref{Built-in Styles}), a minimum indentation -is imposed on lines inside top-level constructs. This minimum -indentation is controlled by this style variable. The default value -is 1. +@dfn{Clean-ups} are mechanisms which remove (or exceptionally, add) +whitespace in specific circumstances and are complementary to colon +and brace hanging. You enable a clean-up by adding its symbol into +@code{c-cleanup-list}. + +On the surface, it would seem that clean-ups overlap the functionality +provided by the @code{c-hanging-*-alist} variables. Clean-ups, +however, are used to adjust code ``after-the-fact'', i.e. to adjust +the whitespace in constructs later than when they were typed. + +Most of the clean-ups remove automatically inserted newlines, and are +only active when auto-newline minor mode is turned on. Others will +work all the time. Note that clean-ups are only performed when there +is nothing but whitespace appearing between the individual components +of the construct, and (apart from @code{comment-close-slash}) when the +construct does not occur within a literal (@pxref{Auto-newlines}). + +@defopt c-cleanup-list +@vindex cleanup-list (c-) +@cindex literal + +You configure @ccmode{}'s clean-ups by setting the style variable +@code{c-cleanup-list}, which is a list of clean-up symbols. By +default, @ccmode{} cleans up only the @code{scope-operator} construct, +which is necessary for proper C++ support. @end defopt -@defopt c-special-indent-hook -@vindex special-indent-hook (c-) -This style variable is a standard hook variable that is called after -every line is indented by @ccmode{}. You can use it to do any special -indentation or line adjustments your style dictates, such as adding -extra indentation to constructors or destructor declarations in a -class definition, etc. Note that you should not change point or mark -inside your @code{c-special-indent-hook} functions, i.e., you'll -probably want to wrap your function in a @code{save-excursion}. - -Setting @code{c-special-indent-hook} in your style definition is -handled slightly differently than other variables. In your style -definition, you should set the value for @code{c-special-indent-hook} -to a function or list of functions, which will be appended to -@code{c-special-indent-hook} using @code{add-hook}. That way, the -current setting for the buffer local value of -@code{c-special-indent-hook} won't be overridden. +These are the clean-ups that are only active when electric and +auto-newline minor modes are enabled: + +@c TBD: Would like to use some sort of @deffoo here; @table indents a +@c bit too much in dvi output. +@table @code +@item brace-else-brace +Clean up @samp{@} else @{} constructs by placing the entire construct on +a single line. Clean up occurs when the open brace after the +@samp{else} is typed. So for example, this: + +@example +@group +void spam(int i) +@{ + if( i==7 ) @{ + dosomething(); + @} + else + @{ +@end group +@end example + +@noindent +appears like this after the last open brace is typed: + +@example +@group +void spam(int i) +@{ + if( i==7 ) @{ + dosomething(); + @} else @{ +@end group +@end example + +@item brace-elseif-brace +Similar to the @code{brace-else-brace} clean-up, but this cleans up +@samp{@} else if (...) @{} constructs. For example: + +@example +@group +void spam(int i) +@{ + if( i==7 ) @{ + dosomething(); + @} + else if( i==3 ) + @{ +@end group +@end example + +@noindent +appears like this after the last open parenthesis is typed: + +@example +@group +void spam(int i) +@{ + if( i==7 ) @{ + dosomething(); + @} else if( +@end group +@end example + +@noindent +and like this after the last open brace is typed: + +@example +@group +void spam(int i) +@{ + if( i==7 ) @{ + dosomething(); + @} else if( i==3 ) @{ +@end group +@end example + +@item brace-catch-brace +Analogous to @code{brace-elseif-brace}, but cleans up @samp{@} catch +(...) @{} in C++ and Java mode. + +@item empty-defun-braces +Clean up braces following a top-level function or class definition that +contains no body. Clean up occurs when the closing brace is typed. +Thus the following: + +@example +@group +class Spam +@{ +@} +@end group +@end example + +@noindent +is transformed into this when the close brace is typed: + +@example +@group +class Spam +@{@} +@end group +@end example + +@item defun-close-semi +Clean up the terminating semicolon on top-level function or class +definitions when they follow a close brace. Clean up occurs when the +semicolon is typed. So for example, the following: + +@example +@group +class Spam +@{ +... +@} +; +@end group +@end example + +@noindent +is transformed into this when the semicolon is typed: + +@example +@group +class Spam +@{ +... +@}; +@end group +@end example + +@item list-close-comma +Clean up commas following braces in array and aggregate initializers. +Clean up occurs when the comma is typed. The space before the comma +is zapped just like the space before the semicolon in +@code{defun-close-semi}. + +@item scope-operator +Clean up double colons which might designate a C++ scope operator split +across multiple lines@footnote{Certain C++ constructs introduce +ambiguous situations, so @code{scope-operator} clean-ups might not +always be correct. This usually only occurs when scoped identifiers +appear in switch label tags.}. Clean up occurs when the second colon is +typed. You will always want @code{scope-operator} in the +@code{c-cleanup-list} when you are editing C++ code. + +@item one-liner-defun +Clean up a single line of code enclosed by defun braces by removing +the whitespace before and after the code. The clean-up happens when +the closing brace is typed. If the variable +@code{c-max-one-liner-length} is set, the cleanup is only done if the +resulting line would be no longer than the value of that variable. + +For example, consider this AWK code: + +@example +@group +BEGIN @{ + FS = "\t" # use <TAB> as a field separator +@} +@end group +@end example + +@noindent +It gets compacted to the following when the closing brace is typed: + +@example +@group +BEGIN @{FS = "\t"@} # use <TAB> as a field separator +@end group +@end example + +@defopt c-max-one-liner-length +@vindex max-one-liner-length (c-) +The maximum length of the resulting line for which the clean-up +@code{one-liner-defun} will be triggered. This length is that of the entire +line, including any leading whitespace and any trailing comment. Its +default value is 80. If the value is zero or @code{nil}, no limit +applies. @end defopt +@end table + +The following clean-ups are always active when they occur on +@code{c-cleanup-list}, regardless of whether Electric minor mode or +Auto-newline minor mode are enabled: + +@table @code +@item space-before-funcall +Insert a space between the function name and the opening parenthesis +of a function call. This produces function calls in the style +mandated by the GNU coding standards, e.g. @samp{signal@tie{}(SIGINT, +SIG_IGN)} and @samp{abort@tie{}()}. Clean up occurs when the opening +parenthesis is typed. This clean-up should never be active in AWK +Mode, since such a space is syntactically invalid for user defined +functions. + +@item compact-empty-funcall +Clean up any space between the function name and the opening parenthesis +of a function call that has no arguments. This is typically used +together with @code{space-before-funcall} if you prefer the GNU function +call style for functions with arguments but think it looks ugly when +it's only an empty parenthesis pair. I.e. you will get @samp{signal +(SIGINT, SIG_IGN)}, but @samp{abort()}. Clean up occurs when the +closing parenthesis is typed. + +@item comment-close-slash +When inside a block comment, terminate the comment when you type a +slash at the beginning of a line (i.e. immediately after the comment +prefix). This clean-up removes whitespace preceding the slash and if +needed, inserts a star to complete the token @samp{*/}. +@end table + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Indentation Engine Basics, Customizing Indentation, Clean-ups, Top +@comment node-name, next, previous, up +@chapter Indentation Engine Basics +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +This chapter will briefly cover how @ccmode{} indents lines of code. +It is helpful to understand the indentation model being used so that +you will know how to customize @ccmode{} for your personal coding +style. All the details are in @ref{Customizing Indentation}. + +@ccmode{} has an indentation engine that provides a flexible and +general mechanism for customizing indentation. When @ccmode{} indents +a line of code, it separates its calculations into two steps: + +@enumerate +@item +@cindex syntactic symbol +@cindex anchor position +It analyzes the line to determine its @dfn{syntactic symbol(s)} (the +kind of language construct it's looking at) and its @dfn{anchor +position} (the position earlier in the file that @ccmode{} will indent +the line relative to). The anchor position might be the location of +an opening brace in the previous line, for example. @xref{Syntactic +Analysis}. +@item +@cindex offsets +@cindex indentation offset specifications +It looks up the syntactic symbol(s) in the configuration to get the +corresponding @dfn{offset(s)}. The symbol @code{+}, which means +``indent this line one more level'' is a typical offset. @ccmode{} +then applies these offset(s) to the anchor position, giving the +indentation for the line. The different sorts of offsets are +described in @ref{c-offsets-alist}. +@end enumerate + +In exceptional circumstances, the syntax directed indentation +described here may be a nuisance rather than a help. You can disable +it by setting @code{c-syntactic-indentation} to @code{nil}. (To set +the variable interactively, @ref{Minor Modes}). + +@defopt c-syntactic-indentation +@vindex syntactic-indentation (c-) +When this is non-@code{nil} (which it is by default), the indentation +of code is done according to its syntactic structure. When it's +@code{nil}, every line is just indented to the same level as the +previous one, and @kbd{TAB} (@code{c-indent-command}) adjusts the +indentation in steps of @code{c-basic-offset}. The current style +(@pxref{Config Basics}) then has no effect on indentation, nor do any +of the variables associated with indentation, not even +@code{c-special-indent-hook}. +@end defopt + +@menu +* Syntactic Analysis:: +* Syntactic Symbols:: +* Indentation Calculation:: +@end menu @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Syntactic Symbols, Indentation Functions, Customizing Indentation, Top +@node Syntactic Analysis, Syntactic Symbols, Indentation Engine Basics, Indentation Engine Basics @comment node-name, next, previous, up -@chapter Syntactic Symbols +@section Syntactic Analysis +@cindex syntactic analysis +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@cindex syntactic element +@cindex syntactic context +The first thing @ccmode{} does when indenting a line of code, is to +analyze the line, determining the @dfn{syntactic context} of the +(first) construct on that line. It's a list of @dfn{syntactic +elements}, where each syntactic element in turn is a list@footnote{In +@ccmode 5.28 and earlier, a syntactic element was a dotted pair; the +cons was the syntactic symbol and the cdr was the anchor position. +For compatibility's sake, the parameter passed to a line-up function +still has this dotted pair form (@pxref{Custom Line-Up}).} Here is a +brief and typical example: + +@example +((defun-block-intro 1959)) +@end example + +@cindex syntactic symbol +@noindent +The first thing inside each syntactic element is always a +@dfn{syntactic symbol}. It describes the kind of construct that was +recognized, e.g. @code{statement}, @code{substatement}, +@code{class-open}, @code{class-close}, etc. @xref{Syntactic Symbols}, +for a complete list of currently recognized syntactic symbols and +their semantics. The remaining entries are various data associated +with the recognized construct - there might be zero or more. + +@cindex anchor position +Conceptually, a line of code is always indented relative to some +position higher up in the buffer (typically the indentation of the +previous line). That position is the @dfn{anchor position} in the +syntactic element. If there is an entry after the syntactic symbol in +the syntactic element list then it's either nil or that anchor position. + +Here is an example. Suppose we had the following code as the only thing +in a C++ buffer @footnote{The line numbers in this and future examples +don't actually appear in the buffer, of course!}: + +@example + 1: void swap( int& a, int& b ) + 2: @{ + 3: int tmp = a; + 4: a = b; + 5: b = tmp; + 6: @} +@end example + +@noindent +We can use @kbd{C-c C-s} (@code{c-show-syntactic-information}) to +report what the syntactic analysis is for the current line: + +@table @asis +@item @kbd{C-c C-s} (@code{c-show-syntactic-information}) +@kindex C-c C-s +@findex c-show-syntactic-information +@findex show-syntactic-information (c-) +This command calculates the syntactic analysis of the current line and +displays it in the minibuffer. The command also highlights the anchor +position(s). +@end table + + Running this command on line 4 of this example, we'd see in the echo +area@footnote{With a universal argument (i.e. @kbd{C-u C-c C-s}) the +analysis is inserted into the buffer as a comment on the current +line.}: + +@example +((statement 35)) +@end example + +@noindent +and the @samp{i} of @code{int} on line 3 would be highlighted. This +tells us that the line is a statement and it is indented relative to +buffer position 35, the highlighted position. If you were to move +point to line 3 and hit @kbd{C-c C-s}, you would see: + +@example +((defun-block-intro 29)) +@end example + +@noindent +This indicates that the @samp{int} line is the first statement in a top +level function block, and is indented relative to buffer position 29, +which is the brace just after the function header. + +Here's another example: + +@example + 1: int add( int val, int incr, int doit ) + 2: @{ + 3: if( doit ) + 4: @{ + 5: return( val + incr ); + 6: @} + 7: return( val ); + 8: @} +@end example + +@noindent +Hitting @kbd{C-c C-s} on line 4 gives us: + +@example +((substatement-open 46)) +@end example + +@cindex substatement +@cindex substatement block +@noindent +which tells us that this is a brace that @emph{opens} a substatement +block. @footnote{A @dfn{substatement} is the line after a +conditional statement, such as @code{if}, @code{else}, @code{while}, +@code{do}, @code{switch}, etc. A @dfn{substatement +block} is a brace block following one of these conditional statements.} + +@cindex comment-only line +Syntactic contexts can contain more than one element, and syntactic +elements need not have anchor positions. The most common example of +this is a @dfn{comment-only line}: + +@example + 1: void draw_list( List<Drawables>& drawables ) + 2: @{ + 3: // call the virtual draw() method on each element in list + 4: for( int i=0; i < drawables.count(), ++i ) + 5: @{ + 6: drawables[i].draw(); + 7: @} + 8: @} +@end example + +@noindent +Hitting @kbd{C-c C-s} on line 3 of this example gives: + +@example +((comment-intro) (defun-block-intro 46)) +@end example + +@noindent +and you can see that the syntactic context contains two syntactic +elements. Notice that the first element, @samp{(comment-intro)}, has no +anchor position. + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Syntactic Symbols, Indentation Calculation, Syntactic Analysis, Indentation Engine Basics +@comment node-name, next, previous, up +@section Syntactic Symbols @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @cindex syntactic symbols, brief list @vindex c-offsets-alist @vindex offsets-alist (c-) -Here is a complete list of the recognized syntactic symbols as described -in the @code{c-offsets-alist} style variable, along with a brief -description. More detailed descriptions follow. +This section is a complete list of the syntactic symbols which appear +in the @code{c-offsets-alist} style variable, along with brief +descriptions. The previous section (@pxref{Syntactic Analysis}) +states what syntactic symbols are and how the indentation engine uses +them. + +More detailed descriptions of these symbols, together with snippets of +source code to which they apply, appear in the examples in the +subsections below. Note that, in the interests of brevity, the anchor +position associated with most syntactic symbols is @emph{not} +specified. In cases of doubt, type @kbd{C-c C-s} on a pertinent +line---this highlights the anchor position. + +@ssindex -open symbols +@ssindex -close symbols +@ssindex -block-intro symbols +The syntactic symbols which indicate brace constructs follow a general +naming convention. When a line begins with an open or close brace, +its syntactic symbol will contain the suffix @code{-open} or +@code{-close} respectively. The first line within the brace block +construct will contain the suffix @code{-block-intro}. + +@ssindex -intro symbols +@ssindex -cont symbols +In constructs which can span several lines, a distinction is usually +made between the first line that introduces the construct and the +lines that continue it. The syntactic symbols that indicate these +lines will contain the suffixes @code{-intro} or @code{-cont} +respectively. + +The best way to understand how all this works is by looking at some +examples. Remember that you can see the syntax of any source code +line by using @kbd{C-c C-s}. @table @code @item string -Inside a multiline string. +Inside a multiline string. @ref{Literal Symbols}. @item c -Inside a multiline C style block comment. +Inside a multiline C style block comment. @ref{Literal Symbols}. @item defun-open -Brace that opens a top-level function definition. +Brace that opens a top-level function definition. @ref{Function +Symbols}. @item defun-close -Brace that closes a top-level function definition. +Brace that closes a top-level function definition. @ref{Function +Symbols}. @item defun-block-intro -The first line in a top-level defun. +The first line in a top-level defun. @ref{Function Symbols}. @item class-open -Brace that opens a class definition. +Brace that opens a class definition. @ref{Class Symbols}. @item class-close -Brace that closes a class definition. +Brace that closes a class definition. @ref{Class Symbols}. @item inline-open -Brace that opens an in-class inline method. +Brace that opens an in-class inline method. @ref{Class Symbols}. @item inline-close -Brace that closes an in-class inline method. +Brace that closes an in-class inline method. @ref{Class Symbols}. @item func-decl-cont The region between a function definition's argument list and the -function opening brace (excluding K&R argument declarations). In C, you -cannot put anything but whitespace and comments in this region, however -in C++ and Java, @code{throws} declarations and other things can appear -here. +function opening brace (excluding K&R argument declarations). In C, +you cannot put anything but whitespace and comments in this region, +however in C++ and Java, @code{throws} declarations and other things +can appear here. @ref{Literal Symbols}. @c @emph{FIXME!!! Can it not +@c go somewhere better?} @item knr-argdecl-intro -First line of a K&R C argument declaration. +First line of a K&R C argument declaration. @ref{K&R Symbols}. @item knr-argdecl -Subsequent lines in a K&R C argument declaration. +Subsequent lines in a K&R C argument declaration. @ref{K&R Symbols}. @item topmost-intro -The first line in a ``topmost'' definition. +The first line in a ``topmost'' definition. @ref{Function Symbols}. @item topmost-intro-cont Topmost definition continuation lines. This is only used in the parts that aren't covered by other symbols such as @code{func-decl-cont} and -@code{knr-argdecl}. +@code{knr-argdecl}. @ref{Function Symbols}. @item member-init-intro -First line in a member initialization list. +First line in a member initialization list. @ref{Class Symbols}. @item member-init-cont -Subsequent member initialization list lines. +Subsequent member initialization list lines. @ref{Class Symbols}. @item inher-intro -First line of a multiple inheritance list. +First line of a multiple inheritance list. @ref{Class Symbols}. @item inher-cont -Subsequent multiple inheritance lines. +Subsequent multiple inheritance lines. @ref{Class Symbols}. @item block-open -Statement block open brace. +Statement block open brace. @ref{Literal Symbols}. @item block-close -Statement block close brace. +Statement block close brace. @ref{Conditional Construct Symbols}. @item brace-list-open -Open brace of an enum or static array list. +Open brace of an enum or static array list. @ref{Brace List Symbols}. @item brace-list-close -Close brace of an enum or static array list. +Close brace of an enum or static array list. @ref{Brace List Symbols}. @item brace-list-intro -First line in an enum or static array list. +First line in an enum or static array list. @ref{Brace List Symbols}. @item brace-list-entry -Subsequent lines in an enum or static array list. +Subsequent lines in an enum or static array list. @ref{Brace List +Symbols}. @item brace-entry-open Subsequent lines in an enum or static array list where the line begins -with an open brace. +with an open brace. @ref{Brace List Symbols}. @item statement -A statement. +A statement. @ref{Function Symbols}. @item statement-cont -A continuation of a statement. +A continuation of a statement. @ref{Function Symbols}. @item statement-block-intro -The first line in a new statement block. +The first line in a new statement block. @ref{Conditional Construct +Symbols}. @item statement-case-intro -The first line in a case block. +The first line in a case block. @ref{Switch Statement Symbols}. @item statement-case-open -The first line in a case block that starts with a brace. +The first line in a case block that starts with a brace. @ref{Switch +Statement Symbols}. @item substatement The first line after a conditional or loop construct. +@ref{Conditional Construct Symbols}. @item substatement-open -The brace that opens a substatement block. +The brace that opens a substatement block. @ref{Conditional Construct +Symbols}. @item substatement-label The first line after a conditional or loop construct if it's a label. +@ref{Conditional Construct Symbols}. @item case-label -A label in a @code{switch} block. +A label in a @code{switch} block. @ref{Switch Statement Symbols}. @item access-label -C++ access control label. +C++ access control label. @ref{Class Symbols}. @item label -Any other label. +Any other label. @ref{Literal Symbols}. @item do-while-closure The @code{while} line that ends a @code{do}-@code{while} construct. +@ref{Conditional Construct Symbols}. @item else-clause The @code{else} line of an @code{if}-@code{else} construct. +@ref{Conditional Construct Symbols}. @item catch-clause The @code{catch} or @code{finally} (in Java) line of a -@code{try}-@code{catch} construct. +@code{try}-@code{catch} construct. @ref{Conditional Construct +Symbols}. @item comment-intro -A line containing only a comment introduction. +A line containing only a comment introduction. @ref{Literal Symbols}. @item arglist-intro -The first line in an argument list. +The first line in an argument list. @ref{Paren List Symbols}. @item arglist-cont -Subsequent argument list lines when no arguments follow on the same line -as the arglist opening paren. +Subsequent argument list lines when no arguments follow on the same +line as the arglist opening paren. @ref{Paren List Symbols}. @item arglist-cont-nonempty -Subsequent argument list lines when at least one argument follows on the -same line as the arglist opening paren. +Subsequent argument list lines when at least one argument follows on +the same line as the arglist opening paren. @ref{Paren List Symbols}. @item arglist-close -The solo close paren of an argument list. +The solo close paren of an argument list. @ref{Paren List Symbols}. @item stream-op -Lines continuing a stream operator (C++ only). +Lines continuing a stream operator (C++ only). @ref{Literal +Symbols}. @c @emph{FIXME!!! Can this not be moved somewhere better?} @item inclass -The line is nested inside a class definition. +The line is nested inside a class definition. @ref{Class Symbols}. @item cpp-macro -The start of a preprocessor macro definition. +The start of a preprocessor macro definition. @ref{Literal Symbols}. @item cpp-define-intro The first line inside a multiline preproprocessor macro if -@code{c-syntactic-indentation-in-macros} is set. +@code{c-syntactic-indentation-in-macros} is set. @ref{Multiline Macro +Symbols}. @item cpp-macro-cont All lines inside multiline preprocessor macros if @code{c-syntactic-indentation-in-macros} is @code{nil}. +@ref{Multiline Macro Symbols}. @item friend -A C++ friend declaration. +A C++ friend declaration. @ref{Class Symbols}. @item objc-method-intro -The first line of an Objective-C method definition. +The first line of an Objective-C method definition. @ref{Objective-C +Method Symbols}. @item objc-method-args-cont -Lines continuing an Objective-C method definition. +Lines continuing an Objective-C method definition. @ref{Objective-C +Method Symbols}. @item objc-method-call-cont -Lines continuing an Objective-C method call. +Lines continuing an Objective-C method call. @ref{Objective-C Method +Symbols}. @item extern-lang-open -Brace that opens an @code{extern} block (e.g., @code{extern "C" @{...@}}). +Brace that opens an @code{extern} block (e.g. @code{extern "C" +@{...@}}). @ref{External Scope Symbols}. @item extern-lang-close -Brace that closes an @code{extern} block. +Brace that closes an @code{extern} block. @ref{External Scope +Symbols}. @item inextern-lang Analogous to @code{inclass} syntactic symbol, but used inside -@code{extern} blocks. +@code{extern} blocks. @ref{External Scope Symbols}. @item namespace-open @itemx namespace-close @itemx innamespace These are analogous to the three @code{extern-lang} symbols above, but -are returned for C++ namespace blocks. +are returned for C++ namespace blocks. @ref{External Scope Symbols}. @item module-open @itemx module-close @itemx inmodule Analogous to the above, but for CORBA IDL @code{module} blocks. +@ref{External Scope Symbols}. @item composition-open @itemx composition-close @itemx incomposition Analogous to the above, but for CORBA CIDL @code{composition} blocks. +@ref{External Scope Symbols}. @item template-args-cont -C++ template argument list continuations. +C++ template argument list continuations. @ref{Class Symbols}. @item inlambda Analogous to @code{inclass} syntactic symbol, but used inside lambda -(i.e., anonymous) functions. Only used in Pike mode. +(i.e. anonymous) functions. Only used in Pike mode. @ref{Statement +Block Symbols}. @item lambda-intro-cont -Lines continuing the header of a lambda function, i.e., between the +Lines continuing the header of a lambda function, i.e. between the @code{lambda} keyword and the function body. Only used in Pike mode. +@ref{Statement Block Symbols}. @item inexpr-statement -A statement block inside an expression. The gcc C and C++ extension for -this is recognized. It's also used for the special functions that take -a statement block as an argument in Pike. +A statement block inside an expression. The gcc C and C++ extension +for this is recognized. It's also used for the special functions that +take a statement block as an argument in Pike. @ref{Statement Block +Symbols}. @item inexpr-class A class definition inside an expression. This is used for anonymous classes in Java. It's also used for anonymous array initializers in -Java. +Java. @ref{Anonymous Class Symbol}. @end table -@ssindex -open symbols -@ssindex -close symbols -Most syntactic symbol names follow a general naming convention. When a -line begins with an open or close brace, the syntactic symbol will -contain the suffix @code{-open} or @code{-close} respectively. - -@ssindex -intro symbols -@ssindex -cont symbols -@ssindex -block-intro symbols -Usually, a distinction is made between the first line that introduces a -construct and lines that continue a construct, and the syntactic symbols -that represent these lines will contain the suffix @code{-intro} or -@code{-cont} respectively. As a sub-classification of this scheme, a -line which is the first of a particular brace block construct will -contain the suffix @code{-block-intro}. - -Let's look at some examples to understand how this works. Remember that -you can check the syntax of any line by using @kbd{C-c C-s}. +@menu +* Function Symbols:: +* Class Symbols:: +* Conditional Construct Symbols:: +* Switch Statement Symbols:: +* Brace List Symbols:: +* External Scope Symbols:: +* Paren List Symbols:: +* Literal Symbols:: +* Multiline Macro Symbols:: +* Objective-C Method Symbols:: +* Anonymous Class Symbol:: +* Statement Block Symbols:: +* K&R Symbols:: +@end menu + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Function Symbols, Class Symbols, Syntactic Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection Function Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +This example shows a typical function declaration. @example 1: void @@ -3519,7 +4128,7 @@ the brace that opens a top-level function definition. Line 9 is the corresponding @code{defun-close} since it contains the brace that closes the top-level -function definition. Line 4 is a @code{defun-block-intro}, i.e., it is +function definition. Line 4 is a @code{defun-block-intro}, i.e. it is the first line of a brace-block, enclosed in a top-level function definition. @@ -3530,8 +4139,13 @@ @code{statement-cont} syntax since it continues the statement begun on the previous line. -Here's another example, which illustrates some C++ class syntactic -symbols: +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Class Symbols, Conditional Construct Symbols, Function Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection Class related Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Here's an example which illustrates some C++ class syntactic symbols: @example 1: class Bass @@ -3657,9 +4271,10 @@ ((inclass 58) (topmost-intro 380) (friend)) @end example -The @code{friend} syntactic symbol is a modifier that typically does not -have a relative buffer position. - +The @code{friend} and @code{inline-open} syntactic symbols are +modifiers that do not have anchor positions. + +@ssindex template-args-cont Template definitions introduce yet another syntactic symbol: @example @@ -3671,8 +4286,14 @@ Here, line 1 is analyzed as a @code{topmost-intro}, but lines 2 and 3 are both analyzed as @code{template-args-cont} lines. -Here is another (totally contrived) example which illustrates how syntax -is assigned to various conditional constructs: +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Conditional Construct Symbols, Switch Statement Symbols, Class Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection Conditional Construct Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Here is a (totally contrived) example which illustrates how syntax is +assigned to various conditional constructs: @example 1: void spam( int index ) @@ -3695,14 +4316,16 @@ Only the lines that illustrate new syntactic symbols will be discussed. @ssindex substatement-open -@ssindex substatement-block-intro +@ssindex statement-block-intro @ssindex block-close Line 4 has a brace which opens a conditional's substatement block. It is thus assigned @code{substatement-open} syntax, and since line 5 is the first line in the substatement block, it is assigned -@code{substatement-block-intro} syntax. Line 10 contains the brace that -closes the inner substatement block, and is therefore given the syntax -@code{block-close}. Line 13 is treated the same way. +@code{statement-block-intro} syntax. Line 10 contains the brace +that closes the inner substatement block, and is therefore given the +syntax @code{block-close}@footnote{@code{block-open} is used only for +``free-standing'' blocks, and is somewhat rare (@pxref{Literal +Symbols} for an example.)}. Line 13 is treated the same way. @ssindex substatement Lines 6 and 9 are also substatements of conditionals, but since they @@ -3731,6 +4354,12 @@ the same line as the preceding close brace, that line would still have @code{block-close} syntax. +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Switch Statement Symbols, Brace List Symbols, Conditional Construct Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection Switch Statement Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + Switch statements have their own set of syntactic symbols. Here's an example: @@ -3761,6 +4390,12 @@ is treated slightly differently since it contains a brace that opens a block --- it is given @code{statement-case-open} syntax. +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Brace List Symbols, External Scope Symbols, Switch Statement Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection Brace List Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + @cindex brace lists There are a set of syntactic symbols that are used to recognize constructs inside of brace lists. A brace list is defined as an @@ -3815,6 +4450,12 @@ expect. Once again, line 8 is assigned as @code{brace-entry-open} as is line 10. +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node External Scope Symbols, Paren List Symbols, Brace List Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection External Scope Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + External language definition blocks also have their own syntactic symbols. In this example: @@ -3844,7 +4485,7 @@ There are various other top level blocks like @code{extern}, and they are all treated in the same way except that the symbols are named after -the keyword that introduces the block. e.g., C++ namespace blocks get +the keyword that introduces the block. E.g. C++ namespace blocks get the three symbols @code{namespace-open}, @code{namespace-close} and @code{innamespace}. The currently recognized top level blocks are: @@ -3873,6 +4514,12 @@ @code{composition} blocks in CORBA CIDL. @end table +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Paren List Symbols, Literal Symbols, External Scope Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection Parenthesis (Argument) List Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + A number of syntactic symbols are associated with parenthesis lists, a.k.a argument lists, as found in function declarations and function calls. This example illustrates these: @@ -3916,10 +4563,23 @@ @code{arglist-cont} syntax. This is because the parenthesis that opens their argument lists is the last character on that line. +Syntactic elements with @code{arglist-intro}, +@code{arglist-cont-nonempty}, and @code{arglist-close} contain two +buffer positions: the anchor position (the beginning of the +declaration or statement) and the position of the open parenthesis. +The latter position can be used in a line-up function (@pxref{Line-Up +Functions}). + Note that there is no @code{arglist-open} syntax. This is because any parenthesis that opens an argument list, appearing on a separate line, is assigned the @code{statement-cont} syntax instead. +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Literal Symbols, Multiline Macro Symbols, Paren List Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection Comment String Label and Macro Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + A few miscellaneous syntactic symbols that haven't been previously covered are illustrated by this C++ example: @@ -3955,7 +4615,9 @@ @item @ssindex comment-intro Line 4 is assigned both @code{defun-block-intro} @emph{and} -@code{comment-intro} syntax. +@code{comment-intro} syntax. A syntactic element with +@code{comment-intro} has no anchor point --- It is always accompanied +by another syntactic element which does have one. @item @ssindex c @@ -3980,7 +4642,10 @@ @item @ssindex block-open -Line 11 is assigned @code{block-open} syntax. +Line 11 is assigned @code{block-open} as well as @code{statement} +syntax. A @code{block-open} syntactic element doesn't have an anchor +position, since it always appears with another syntactic element which +does have one. @item @ssindex cpp-macro @@ -3990,20 +4655,28 @@ configured to cancel out the normal syntactic context to make all preprocessor directives stick to the first column, but that's easily changed if you want preprocessor directives to be indented like the rest -of the code. +of the code. Like @code{comment-intro}, a syntactic element with +@code{cpp-macro} doesn't contain an anchor position. @item @ssindex stream-op Line 17 is assigned @code{stream-op} syntax. @end itemize +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Multiline Macro Symbols, Objective-C Method Symbols, Literal Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection Multiline Macro Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + @cindex multiline macros @cindex syntactic whitespace @ssindex cpp-define-intro +@ssindex cpp-macro-cont Multiline preprocessor macro definitions are normally handled just like -other code, i.e., the lines inside them are indented according to the +other code, i.e. the lines inside them are indented according to the syntactic analysis of the preceding lines inside the macro. The first -line inside a macro definition (i.e., the line after the starting line of +line inside a macro definition (i.e. the line after the starting line of the cpp directive itself) gets @code{cpp-define-intro}. In this example: @example @@ -4019,17 +4692,23 @@ of a cpp directive is always given that symbol. Line 2 is given @code{cpp-define-intro}, so that you can give the macro body as a whole some extra indentation. Lines 3 through 5 are then analyzed as normal -code, i.e., @code{substatement} on lines 3 and 4, and @code{else-clause} +code, i.e. @code{substatement} on lines 3 and 4, and @code{else-clause} on line 5. The syntactic analysis inside macros can be turned off with -@code{c-syntactic-indentation-in-macros}. In that case, lines 2 through -5 would all be given @code{cpp-macro-cont} with a relative buffer -position pointing to the @code{#} which starts the cpp +@code{c-syntactic-indentation-in-macros} (@pxref{Custom Macros}). In +that case, lines 2 through 5 would all be given @code{cpp-macro-cont} +with an anchor position pointing to the @code{#} which starts the cpp directive@footnote{This is how @ccmode{} 5.28 and earlier analyzed macros.}. -@xref{Macro Handling}, for more info about the treatment of macros. +@xref{Custom Macros}, for more info about the treatment of macros. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Objective-C Method Symbols, Anonymous Class Symbol, Multiline Macro Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection Objective-C Method Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! In Objective-C buffers, there are three additional syntactic symbols assigned to various message calling constructs. Here's an example @@ -4052,7 +4731,13 @@ assigned @code{objc-method-args-cont} syntax. Lines 5 and 6 are both assigned @code{objc-method-call-cont} syntax. -Java has a concept of anonymous classes, which may look something like +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Anonymous Class Symbol, Statement Block Symbols, Objective-C Method Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection Anonymous Class Symbol (Java) +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Java has a concept of anonymous classes which can look something like this: @example @@ -4070,11 +4755,18 @@ Lines 3 and 6 are assigned the @code{inexpr-class} syntax, besides the @code{inclass} symbol used in normal classes. Thus, the class will be indented just like a normal class, with the added indentation given to -@code{inexpr-class}. - -There are a few occasions where a statement block may be used inside an -expression. One is in C or C++ code using the gcc extension for this, -e.g: +@code{inexpr-class}. An @code{inexpr-class} syntactic element doesn't +have an anchor position. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Statement Block Symbols, K&R Symbols, Anonymous Class Symbol, Syntactic Symbols +@comment node-name, next, previous, up +@subsection Statement Block Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +There are a few occasions where a statement block might be used inside +an expression. One is in C or C++ code using the gcc extension for +this, e.g: @example 1: int res = (@{ @@ -4088,7 +4780,8 @@ Lines 2 and 5 get the @code{inexpr-statement} syntax, besides the symbols they'd get in a normal block. Therefore, the indentation put on @code{inexpr-statement} is added to the normal statement block -indentation. +indentation. An @code{inexpr-statement} syntactic element doesn't +contain an anchor position. In Pike code, there are a few other situations where blocks occur inside statements, as illustrated here: @@ -4129,6 +4822,12 @@ example above. The other similar special function, @code{gauge}, is handled like this too. +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node K&R Symbols, , Statement Block Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection K&R Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + @ssindex knr-argdecl-intro @ssindex knr-argdecl Two other syntactic symbols can appear in old style, non-prototyped C @@ -4146,30 +4845,467 @@ Here, line 2 is the first line in an argument declaration list and so is given the @code{knr-argdecl-intro} syntactic symbol. Subsequent lines -(i.e., lines 3 and 4 in this example), are given @code{knr-argdecl} +(i.e. lines 3 and 4 in this example), are given @code{knr-argdecl} syntax. @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Indentation Functions, AWK Mode, Syntactic Symbols, Top +@node Indentation Calculation, , Syntactic Symbols, Indentation Engine Basics @comment node-name, next, previous, up -@chapter Indentation Functions +@section Indentation Calculation +@cindex indentation +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Indentation for a line is calculated from the syntactic context +(@pxref{Syntactic Analysis}). + +First, a buffer position is found whose column will be the base for the +indentation calculation. It's the anchor position in the first +syntactic element that provides one that is used. If no syntactic +element has an anchor position then column zero is used. + +Second, the syntactic symbols in each syntactic element are looked up +in the @code{c-offsets-alist} style variable +(@pxref{c-offsets-alist}), which is an association list of syntactic +symbols and the offsets to apply for those symbols. These offsets are +added together with the base column to produce the new indentation +column. + +Let's use our two code examples above to see how this works. Here is +our first example again: + +@example + 1: void swap( int& a, int& b ) + 2: @{ + 3: int tmp = a; + 4: a = b; + 5: b = tmp; + 6: @} +@end example + +Let's say point is on line 3 and we hit the @kbd{TAB} key to reindent +the line. The syntactic context for that line is: + +@example +((defun-block-intro 29)) +@end example + +@noindent +Since buffer position 29 is the first and only anchor position in the +list, @ccmode{} goes there and asks for the current column. This brace +is in column zero, so @ccmode{} uses @samp{0} as the base column. + +Next, @ccmode{} looks up @code{defun-block-intro} in the +@code{c-offsets-alist} style variable. Let's say it finds the value +@samp{4}; it adds this to the base column @samp{0}, yielding a running +total indentation of 4 spaces. + +Since there is only one syntactic element on the list for this line, +indentation calculation is complete, and the total indentation for the +line is 4 spaces. + +Here's another example: + +@example + 1: int add( int val, int incr, int doit ) + 2: @{ + 3: if( doit ) + 4: @{ + 5: return( val + incr ); + 6: @} + 7: return( val ); + 8: @} +@end example + +If we were to hit @kbd{TAB} on line 4 in the above example, the same +basic process is performed, despite the differences in the syntactic +context. The context for this line is: + +@example +((substatement-open 46)) +@end example + +Here, @ccmode{} goes to buffer position 46, which is the @samp{i} in +@code{if} on line 3. This character is in the fourth column on that +line so the base column is @samp{4}. Then @ccmode{} looks up the +@code{substatement-open} symbol in @code{c-offsets-alist}. Let's say it +finds the value @samp{4}. It's added with the base column and yields an +indentation for the line of 8 spaces. + +Simple, huh? + +Actually, it's a bit more complicated than that since the entries on +@code{c-offsets-alist} can be much more than plain offsets. +@xref{c-offsets-alist}, for the full story. + +Anyway, the mode usually just does The Right Thing without you having to +think about it in this much detail. But when customizing indentation, +it's helpful to understand the general indentation model being used. + +As you configure @ccmode{}, you might want to set the variable +@code{c-echo-syntactic-information-p} to non-@code{nil} so that the +syntactic context and calculated offset always is echoed in the +minibuffer when you hit @kbd{TAB}. + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Customizing Indentation, Custom Macros, Indentation Engine Basics, Top +@comment node-name, next, previous, up +@chapter Customizing Indentation +@cindex customization, indentation +@cindex indentation +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +The principal variable for customizing indentation is the style +variable @code{c-offsets-alist}, which gives an @dfn{offset} (an +indentation rule) for each syntactic symbol. Its structure and +semantics are completely described in @ref{c-offsets-alist}. The +various ways you can set the variable, including the use of the +@ccmode{} style system, are described in @ref{Config Basics} and its +sections, in particular @ref{Style Variables}. + +The simplest and most used kind of ``offset'' setting in +@code{c-offsets-alist} is in terms of multiples of +@code{c-basic-offset}: + +@defopt c-basic-offset +@vindex basic-offset (c-) +This style variable holds the basic offset between indentation levels. +It's factory default is 4, but all the built-in styles set it +themselves, to some value between 2 (for @code{gnu} style) and 8 (for +@code{bsd}, @code{linux}, and @code{python} styles). +@end defopt + +The most flexible ``offset'' setting you can make in +@code{c-offsets-alist} is a line-up function (or even a list of them), +either one supplied by @ccmode{} (@pxref{Line-Up Functions}) or one +you write yourself (@pxref{Custom Line-Up}). + +Finally, in @ref{Other Indentation} you'll find the tool of last +resort: a hook which is called after a line has been indented. You +can install functions here to make ad-hoc adjustments to any line's +indentation. + +@menu +* c-offsets-alist:: +* Interactive Customization:: +* Line-Up Functions:: +* Custom Line-Up:: +* Other Indentation:: +@end menu + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node c-offsets-alist, Interactive Customization, Customizing Indentation, Customizing Indentation +@comment node-name, next, previous, up +@section c-offsets-alist @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +This section explains the structure and semantics of the style +variable @code{c-offset-alist}, the principal variable for configuring +indentation. Details of how to set it up, and its relationship to +@ccmode{}'s style system are given in @ref{Style Variables}. + +@defopt c-offsets-alist +@vindex offsets-alist (c-) +This is an alist which associates an offset with each syntactic +symbol. This @dfn{offset} is a rule specifying how to indent a line +whose syntactic context matches the symbol. @xref{Syntactic +Analysis}. + +Note that the buffer-local binding of this alist in a @ccmode{} buffer +contains an entry for @emph{every} syntactic symbol. Its global +binding and its settings within style specifications usually contain +only a few entries. @xref{Style Variables}. + +The offset specification associated with any particular syntactic +symbol can be an integer, a variable name, a vector, a function or +lambda expression, a list, or one of the following special symbols: +@code{+}, @code{-}, @code{++}, @code{--}, @code{*}, or @code{/}. The +meanings of these values are described in detail below. + +Here is an example fragment of a @code{c-offsets-alist}, showing some +of these kinds of offsets: + +@example +((statement . 0) + (substatement . +) + (cpp-macro . [0]) + (topmost-intro-cont . c-lineup-topmost-intro-cont) + (statement-block-intro . (add c-lineup-whitesmith-in-block + c-indent-multi-line-block)) + @dots{} +@*) +@end example +@end defopt + +@deffn Command c-set-offset (@kbd{C-c C-o}) +@findex set-offset (c-) +@kindex C-c C-o +This command changes the entry for a syntactic symbol in the current +binding of @code{c-offsets-alist}, or it inserts a new entry if there +isn't already one for that syntactic symbol. + +You can use @code{c-set-offsets} interactively within a @ccmode{} +buffer to make experimental changes to your indentation settings. +@kbd{C-c C-o} prompts you for the syntactic symbol to change +(defaulting to that of the current line) and the new offset +(defaulting to the current offset). + +@code{c-set-offsets} takes two arguments when used programmatically: +@var{symbol}, the syntactic element symbol to change and @var{offset}, +the new offset for that syntactic element. You can call the command +in your @file{.emacs} to change the global binding of +@code{c-offsets-alist} (@pxref{Style Variables}); you can use it in a +hook function to make changes from the current style. @ccmode{} +itself uses this function when initializing styles. +@end deffn + +@cindex offset specification +The ``offset specifications'' in @code{c-offsets-alist} can be any of +the following: + +@table @asis +@item An integer +The integer specifies a relative offset. All relative +offsets@footnote{The syntactic context @code{@w{((defun-block-intro +2724) (comment-intro))}} would likely have two relative offsets.} will +be added together and used to calculate the indentation relative to an +anchor position earlier in the buffer. @xref{Indentation +Calculation}, for details. Most of the time, it's probably better to +use one of the special symbols like @code{+} than an integer (apart +from zero). + +@item One of the symbols @code{+}, @code{-}, @code{++}, @code{--}, @code{*}, or @code{/} +These special symbols describe a relative offset in multiples of +@code{c-basic-offset}: + +By defining a style's indentation in terms of @code{c-basic-offset}, +you can change the amount of whitespace given to an indentation level +while maintaining the same basic shape of your code. Here are the +values that the special symbols correspond to: + +@table @code +@item + +@code{c-basic-offset} times 1 +@item - +@code{c-basic-offset} times -1 +@item ++ +@code{c-basic-offset} times 2 +@item -- +@code{c-basic-offset} times -2 +@item * +@code{c-basic-offset} times 0.5 +@item / +@code{c-basic-offset} times -0.5 +@end table + +@item A vector +The first element of the vector, an integer, sets the absolute +indentation column. This will override any previously calculated +indentation, but won't override relative indentation calculated from +syntactic elements later on in the syntactic context of the line being +indented. @xref{Indentation Calculation}. Any elements in the vector +beyond the first will be ignored. + +@item A function or lambda expression +The function will be called and its return value will in turn be +evaluated as an offset specification. Functions are useful when more +context than just the syntactic symbol is needed to get the desired +indentation. @xref{Line-Up Functions}, and @ref{Custom Line-Up}, for +details about them. + +@item A symbol with a variable binding +If the symbol also has a function binding, the function takes +precedence over the variable. Otherwise the value of the variable is +used. It must be an integer (which is used as relative offset) or a +vector (an absolute offset). + +@item A list +The offset can also be a list containing several offset +specifications; these are evaluated recursively and combined. A list +is typically only useful when some of the offsets are line-up +functions. A common strategy is calling a sequence of functions in +turn until one of them recognizes that it is appropriate for the +source line and returns a non-@code{nil} value. + +@code{nil} values are always ignored when the offsets are combined. +The first element of the list specifies the method of combining the +non-@code{nil} offsets from the remaining elements: + +@table @code +@item first +Use the first offset that doesn't evaluate to @code{nil}. Subsequent +elements of the list don't get evaluated. +@item min +Use the minimum of all the offsets. All must be either relative or +absolute - they can't be mixed. +@item max +Use the maximum of all the offsets. All must be either relative or +absolute - they can't be mixed. +@item add +Add all the evaluated offsets together. Exactly one of them may be +absolute, in which case the result is absolute. Any relative offsets +that preceded the absolute one in the list will be ignored in that case. +@end table + +As a compatibility measure, if the first element is none of the above +then it too will be taken as an offset specification and the whole list +will be combined according to the method @code{first}. +@end table + +@vindex c-strict-syntax-p +@vindex strict-syntax-p (c-) +If an offset specification evaluates to @code{nil}, then a relative +offset of 0 (zero) is used@footnote{There is however a variable +@code{c-strict-syntax-p} that when set to non-@code{nil} will cause an +error to be signaled in that case. It's now considered obsolete since +it doesn't work well with some of the alignment functions that returns +@code{nil} instead of zero. You should therefore leave +@code{c-strict-syntax-p} set to @code{nil}.}. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Interactive Customization, Line-Up Functions, c-offsets-alist, Customizing Indentation +@comment node-name, next, previous, up +@section Interactive Customization +@cindex customization, interactive +@cindex interactive customization +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +As an example of how to customize indentation, let's change the +style of this example@footnote{In this and subsequent examples, the +original code is formatted using the @samp{gnu} style unless otherwise +indicated. @xref{Styles}.}: + +@example +@group + 1: int add( int val, int incr, int doit ) + 2: @{ + 3: if( doit ) + 4: @{ + 5: return( val + incr ); + 6: @} + 7: return( val ); + 8: @} +@end group +@end example + +@noindent +to: + +@example +@group + 1: int add( int val, int incr, int doit ) + 2: @{ + 3: if( doit ) + 4: @{ + 5: return( val + incr ); + 6: @} + 7: return( val ); + 8: @} +@end group +@end example + +In other words, we want to change the indentation of braces that open a +block following a condition so that the braces line up under the +conditional, instead of being indented. Notice that the construct we +want to change starts on line 4. To change the indentation of a line, +we need to see which syntactic symbols affect the offset calculations +for that line. Hitting @kbd{C-c C-s} on line 4 yields: + +@example +((substatement-open 44)) +@end example + +@noindent +so we know that to change the offset of the open brace, we need to +change the indentation for the @code{substatement-open} syntactic +symbol. + +To do this interactively, just hit @kbd{C-c C-o}. This prompts +you for the syntactic symbol to change, providing a reasonable default. +In this case, the default is @code{substatement-open}, which is just the +syntactic symbol we want to change! + +After you hit return, @ccmode{} will then prompt you for the new +offset value, with the old value as the default. The default in this +case is @samp{+}, but we want no extra indentation so enter +@samp{0} and @kbd{RET}. This will associate the offset 0 with the +syntactic symbol @code{substatement-open}. + +To check your changes quickly, just hit @kbd{C-c C-q} +(@code{c-indent-defun}) to reindent the entire function. The example +should now look like: + +@example +@group + 1: int add( int val, int incr, int doit ) + 2: @{ + 3: if( doit ) + 4: @{ + 5: return( val + incr ); + 6: @} + 7: return( val ); + 8: @} +@end group +@end example + +Notice how just changing the open brace offset on line 4 is all we +needed to do. Since the other affected lines are indented relative to +line 4, they are automatically indented the way you'd expect. For more +complicated examples, this might not always work. The general approach +to take is to always start adjusting offsets for lines higher up in the +file, then reindent and see if any following lines need further +adjustments. + +@c Move this bit to "Styles" (2005/10/7) +@deffn Command c-set-offset symbol offset +@findex set-offset (c-) +@kindex C-c C-o +This is the command bound to @kbd{C-c C-o}. It provides a convenient +way to set offsets on @code{c-offsets-alist} both interactively (see +the example above) and from your mode hook. + +It takes two arguments when used programmatically: @var{symbol} is the +syntactic element symbol to change and @var{offset} is the new offset +for that syntactic element. +@end deffn +@c End of MOVE THIS BIT. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Line-Up Functions, Custom Line-Up, Interactive Customization, Customizing Indentation +@comment node-name, next, previous, up +@section Line-Up Functions +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@cindex line-up function @cindex indentation function -@cindex line-up function Often there are cases when a simple offset setting on a syntactic -symbol isn't enough to get the desired indentation. Therefore, it's -also possible to use an @dfn{indentation function} (a.k.a. @dfn{line-up -function}) for a syntactic symbol. - -@ccmode{} comes with many predefined indentation functions for common -situations. If none of these does what you want, you can write your -own, see @ref{Custom Indentation Functions}. If you do, it's probably a -good idea to start working from one of these predefined functions, they -can be found in the file @file{cc-align.el}. - -For every function below there is a ``works with'' list that indicates +symbol isn't enough to get the desired indentation---for example, you +might want to line up a closing parenthesis with the matching opening +one rather than indenting relative to its ``anchor point''. @ccmode{} +provides this flexibility with @dfn{line-up functions}. + +The way you associate a line-up function with a syntactic symbol is +described in @ref{c-offsets-alist}. @ccmode{} comes with many +predefined line-up functions for common situations. If none of these +does what you want, you can write your own. @xref{Custom Line-Up}. +Sometimes, it is easier to tweak the standard indentation by adding a +function to @code{c-special-indent-hook} (@pxref{Other Indentation}). + +The line-up functions haven't been adapted for AWK buffers or tested +with them. Some of them might work serendipitously. There shouldn't be +any problems writing custom line-up functions for AWK mode. + +The calling convention for line-up functions is described fully in +@ref{Custom Line-Up}. Roughly speaking, the return value is either an +offset itself (such as @code{+} or @code{[0]}) or it's @code{nil}, +meaning ``this function is inappropriate in this case - try a +different one''. @xref{c-offsets-alist}. + +The subsections below describe all the standard line-up functions, +categorized by the sort of token the lining-up centres around. For +each of these functions there is a ``works with'' list that indicates which syntactic symbols the function is intended to be used with. @macro workswith @@ -4202,6 +5338,77 @@ @end macro @end iftex +@menu +* Brace/Paren Line-Up:: +* List Line-Up:: +* Operator Line-Up:: +* Comment Line-Up:: +* Misc Line-Up:: +@end menu + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Brace/Paren Line-Up, List Line-Up, Line-Up Functions, Line-Up Functions +@comment node-name, next, previous, up +@subsection Brace and Parenthesis Line-Up Functions +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +The line-up functions here calculate the indentation for braces, +parentheses and statements within brace blocks. + +@defun c-lineup-close-paren +@findex lineup-close-paren (c-) +Line up the closing paren under its corresponding open paren if the +open paren is followed by code. If the open paren ends its line, no +indentation is added. E.g: + +@example +@group +main (int, + char ** + ) @hereFn{c-lineup-close-paren} +@end group +@end example + +@noindent +and + +@example +@group +main ( + int, char ** +) @hereFn{c-lineup-close-paren} +@end group +@end example + +As a special case, if a brace block is opened at the same line as the +open parenthesis of the argument list, the indentation is +@code{c-basic-offset} instead of the open paren column. See +@code{c-lineup-arglist} for further discussion of this ``DWIM'' measure. + +@workswith All @code{*-close} symbols. +@end defun + +@comment ------------------------------------------------------------ + +@anchor{c-lineup-arglist-close-under-paren} +@defun c-lineup-arglist-close-under-paren +@findex lineup-arglist-close-under-paren (c-) +Set your @code{arglist-close} syntactic symbol to this line-up function +so that parentheses that close argument lists will line up under the +parenthesis that opened the argument list. It can also be used with +@code{arglist-cont} and @code{arglist-cont-nonempty} to line up all +lines inside a parenthesis under the open paren. + +As a special case, if a brace block is opened at the same line as the +open parenthesis of the argument list, the indentation is +@code{c-basic-offset} only. See @code{c-lineup-arglist} for further +discussion of this ``DWIM'' measure. + +@workswith Almost all symbols, but are typically most useful on +@code{arglist-close}, @code{brace-list-close}, @code{arglist-cont} and +@code{arglist-cont-nonempty}. +@end defun + @comment ------------------------------------------------------------ @defun c-indent-one-line-block @@ -4274,29 +5481,141 @@ @comment ------------------------------------------------------------ -@defun c-lineup-argcont -@findex lineup-argcont (c-) -Line up a continued argument. E.g: +@defun c-lineup-runin-statements +@findex lineup-runin-statements (c-) +Line up statements for coding standards which place the first statement +in a block on the same line as the block opening brace@footnote{Run-in +style doesn't really work too well. You might need to write your own +custom line-up functions to better support this style.}. E.g: + +@example +@group +int main() +@{ puts ("Hello!"); + return 0; @hereFn{c-lineup-runin-statements} +@} +@end group +@end example + +If there is no statement after the opening brace to align with, +@code{nil} is returned. This makes the function usable in list +expressions. + +@workswith The @code{statement} syntactic symbol. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-inexpr-block +@findex lineup-inexpr-block (c-) +This can be used with the in-expression block symbols to indent the +whole block to the column where the construct is started. E.g. for Java +anonymous classes, this lines up the class under the @samp{new} keyword, +and in Pike it lines up the lambda function body under the @samp{lambda} +keyword. Returns @code{nil} if the block isn't part of such a +construct. + +@workswith @code{inlambda}, @code{inexpr-statement}, +@code{inexpr-class}. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-after-whitesmith-blocks +@findex lineup-after-whitesmith-blocks (c-) +Compensate for Whitesmith style indentation of blocks. Due to the way +@ccmode{} calculates anchor positions for normal lines inside blocks, +this function is necessary for those lines to get correct Whitesmith +style indentation. Consider the following examples: + +@example +@group +int foo() + @{ + a; + x; @hereFn{c-lineup-after-whitesmith-blocks} +@end group +@end example @example @group -foo (xyz, aaa + bbb + ccc - + ddd + eee + fff); @hereFn{c-lineup-argcont} +int foo() + @{ + @{ + a; + @} + x; @hereFn{c-lineup-after-whitesmith-blocks} @end group @end example -Only continuation lines like this are touched, @code{nil} is returned on -lines which are the start of an argument. - -Within a gcc @code{asm} block, @code{:} is recognised as an argument -separator, but of course only between operand specifications, not in the -expressions for the operands. - -@workswith @code{arglist-cont}, @code{arglist-cont-nonempty}. +The fact that the line with @code{x} is preceded by a Whitesmith style +indented block in the latter case and not the first should not affect +its indentation. But since CC Mode in cases like this uses the +indentation of the preceding statement as anchor position, the @code{x} +would in the second case be indented too much if the offset for +@code{statement} was set simply to zero. + +This lineup function corrects for this situation by detecting if the +anchor position is at an open paren character. In that case, it instead +indents relative to the surrounding block just like +@code{c-lineup-whitesmith-in-block}. + +@workswith @code{brace-list-entry}, @code{brace-entry-open}, +@code{statement}, @code{arglist-cont}. @end defun @comment ------------------------------------------------------------ +@defun c-lineup-whitesmith-in-block +@findex lineup-whitesmith-in-block (c-) +Line up lines inside a block in Whitesmith style. It's done in a way +that works both when the opening brace hangs and when it doesn't. E.g: + +@example +@group +something + @{ + foo; @hereFn{c-lineup-whitesmith-in-block} + @} +@end group +@end example + +@noindent +and + +@example +@group +something @{ + foo; @hereFn{c-lineup-whitesmith-in-block} + @} +@sssTBasicOffset{} +@end group +@end example + +In the first case the indentation is kept unchanged, in the second +@code{c-basic-offset} is added. + +@workswith @code{defun-close}, @code{defun-block-intro}, +@code{inline-close}, @code{block-close}, @code{brace-list-close}, +@code{brace-list-intro}, @code{statement-block-intro}, +@code{arglist-intro}, @code{arglist-cont-nonempty}, +@code{arglist-close}, and all @code{in*} symbols, e.g. @code{inclass} +and @code{inextern-lang}. +@end defun + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node List Line-Up, Operator Line-Up, Brace/Paren Line-Up, Line-Up Functions +@comment node-name, next, previous, up +@subsection List Line-Up Functions +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +The line-up functions here calculate the indentation for lines which +form lists of items, usually separated by commas. + +The function @ref{c-lineup-arglist-close-under-paren}, which is mainly +for indenting a close parenthesis, is also useful for the lines +contained within parentheses. + @defun c-lineup-arglist @findex lineup-arglist (c-) Line up the current argument line under the first argument. @@ -4304,7 +5623,7 @@ As a special case, if an argument on the same line as the open parenthesis starts with a brace block opener, the indentation is @code{c-basic-offset} only. This is intended as a ``DWIM'' measure in -cases like macros that contains statement blocks, e.g: +cases like macros that contain statement blocks, e.g: @example @group @@ -4337,147 +5656,16 @@ @comment ------------------------------------------------------------ -@defun c-lineup-arglist-close-under-paren -@findex lineup-arglist-close-under-paren (c-) -Set your @code{arglist-close} syntactic symbol to this line-up function -so that parentheses that close argument lists will line up under the -parenthesis that opened the argument list. It can also be used with -@code{arglist-cont} and @code{arglist-cont-nonempty} to line up all -lines inside a parenthesis under the open paren. - -As a special case, if a brace block is opened at the same line as the -open parenthesis of the argument list, the indentation is -@code{c-basic-offset} only. See @code{c-lineup-arglist} for further -discussion of this ``DWIM'' measure. - -@workswith Almost all symbols, but are typically most useful on -@code{arglist-close}, @code{brace-list-close}, @code{arglist-cont} and -@code{arglist-cont-nonempty}. -@end defun - -@comment ------------------------------------------------------------ - -@defun c-lineup-arglist-operators -@findex lineup-arglist-operators (c-) -Line up lines starting with an infix operator under the open paren. -Return @code{nil} on lines that don't start with an operator, to leave -those cases to other lineup functions. Example: - -@example -@group -if ( x < 10 - || at_limit (x, @hereFn{c-lineup-arglist-operators} - list) @hereFn{c-lineup-arglist-operators@r{ returns nil}} - ) -@end group -@end example - -Since this function doesn't do anything for lines without an infix -operator you typically want to use it together with some other lineup -settings, e.g., as follows (the @code{arglist-close} setting is just a -suggestion to get a consistent style): - -@example -(c-set-offset 'arglist-cont - '(c-lineup-arglist-operators 0)) -(c-set-offset 'arglist-cont-nonempty - '(c-lineup-arglist-operators c-lineup-arglist)) -(c-set-offset 'arglist-close - '(c-lineup-arglist-close-under-paren)) -@end example - -@workswith @code{arglist-cont}, @code{arglist-cont-nonempty}. -@end defun - -@comment ------------------------------------------------------------ - -@defun c-lineup-C-comments -@findex lineup-C-comments (c-) -Line up C block comment continuation lines. Various heuristics are used -to handle most of the common comment styles. Some examples: - -@example -@group -/* /** /* - * text * text text - */ */ */ -@end group -@end example +@defun c-lineup-multi-inher +@findex lineup-multi-inher (c-) +Line up the classes in C++ multiple inheritance clauses and member +initializers under each other. E.g: @example @group -/* text /* /** - text ** text ** text -*/ */ */ -@end group -@end example - -@example -@group -/************************************************** - * text - *************************************************/ -@end group -@end example - -@vindex comment-start-skip -@example -@group -/************************************************** - Free form text comments: - In comments with a long delimiter line at the - start, the indentation is kept unchanged for lines - that start with an empty comment line prefix. The - delimiter line is whatever matches the - @code{comment-start-skip} regexp. -**************************************************/ -@end group -@end example - -The style variable @code{c-comment-prefix-regexp} is used to recognize -the comment line prefix, e.g., the @samp{*} that usually starts every -line inside a comment. - -@workswith The @code{c} syntactic symbol. -@end defun - -@comment ------------------------------------------------------------ - -@defun c-lineup-cascaded-calls -@findex lineup-cascaded-calls (c-) -Line up ``cascaded calls'' under each other. If the line begins with -@code{->} or @code{.} and the preceding line ends with one or more -function calls preceded by the same token, then the arrow is lined up -with the first of those tokens. E.g: - -@example -@group -r = proc->add(17)->add(18) - ->add(19) + @hereFn{c-lineup-cascaded-calls} - offset; @hereFn{c-lineup-cascaded-calls@r{ (inactive)}} -@end group -@end example - -In any other situation @code{nil} is returned to allow use in list -expressions. - -@workswith @code{topmost-intro-cont}, @code{statement-cont}, -@code{arglist-cont}, @code{arglist-cont-nonempty}. -@end defun - -@comment ------------------------------------------------------------ - -@defun c-lineup-close-paren -@findex lineup-close-paren (c-) -Line up the closing paren under its corresponding open paren if the -open paren is followed by code. If the open paren ends its line, no -indentation is added. E.g: - -@example -@group -main (int, - char ** - ) @hereFn{c-lineup-close-paren} +Foo::Foo (int a, int b): + Cyphr (a), + Bar (b) @hereFn{c-lineup-multi-inher} @end group @end example @@ -4486,191 +5674,24 @@ @example @group -main ( - int, char ** -) @hereFn{c-lineup-close-paren} -@end group -@end example - -As a special case, if a brace block is opened at the same line as the -open parenthesis of the argument list, the indentation is -@code{c-basic-offset} instead of the open paren column. See -@code{c-lineup-arglist} for further discussion of this ``DWIM'' measure. - -@workswith All @code{*-close} symbols. -@end defun - -@comment ------------------------------------------------------------ - -@defun c-lineup-comment -@findex lineup-comment (c-) -Line up a comment-only line according to the style variable -@code{c-comment-only-line-offset}. If the comment is lined up with a -comment starter on the previous line, that alignment is preserved. - -@defopt c-comment-only-line-offset -@vindex comment-only-line-offset (c-) -This style variable specifies the extra offset for the line. It can -contain an integer or a cons cell of the form - -@example -(@r{@var{non-anchored-offset}} . @r{@var{anchored-offset}}) -@end example - -@noindent -where @var{non-anchored-offset} is the amount of offset given to -non-column-zero anchored lines, and @var{anchored-offset} is the amount -of offset to give column-zero anchored lines. Just an integer as value -is equivalent to @code{(@r{@var{value}} . -1000)}. -@end defopt - -@workswith @code{comment-intro}. -@end defun - -@comment ------------------------------------------------------------ - -@defun c-lineup-cpp-define -@findex lineup-cpp-define (c-) -Line up macro continuation lines according to the indentation of the -construct preceding the macro. E.g: - -@example -@group -const char msg[] = @hereFn{@r{The beginning of the preceding construct.}} - \"Some text.\"; - -#define X(A, B) \ -do @{ \ @hereFn{c-lineup-cpp-define} - printf (A, B); \ -@} while (0) +class Foo + : public Cyphr, + public Bar @hereFn{c-lineup-multi-inher} @end group @end example @noindent -and: - -@example -@group -int dribble() @{ - if (!running) @hereFn{@r{The beginning of the preceding construct.}} - error(\"Not running!\"); - -#define X(A, B) \ - do @{ \ @hereFn{c-lineup-cpp-define} - printf (A, B); \ - @} while (0) -@end group -@end example - -If @code{c-syntactic-indentation-in-macros} is non-@code{nil}, the -function returns the relative indentation to the macro start line to -allow accumulation with other offsets. e.g., in the following cases, -@code{cpp-define-intro} is combined with the -@code{statement-block-intro} that comes from the @samp{do @{} that hangs -on the @samp{#define} line: - -@example -@group -const char msg[] = - \"Some text.\"; - -#define X(A, B) do @{ \ - printf (A, B); \ @hereFn{c-lineup-cpp-define} - this->refs++; \ -@} while (0) @hereFn{c-lineup-cpp-define} -@end group -@end example - -@noindent -and: +and @example @group -int dribble() @{ - if (!running) - error(\"Not running!\"); - -#define X(A, B) do @{ \ - printf (A, B); \ @hereFn{c-lineup-cpp-define} - this->refs++; \ - @} while (0) @hereFn{c-lineup-cpp-define} +Foo::Foo (int a, int b) + : Cyphr (a) + , Bar (b) @hereFn{c-lineup-multi-inher} @end group @end example -The relative indentation returned by @code{c-lineup-cpp-define} is zero -and two, respectively, on the two lines in each of these examples. They -are then added to the two column indentation that -@code{statement-block-intro} gives in both cases here. - -If the relative indentation is zero, then @code{nil} is returned -instead. That is useful in a list expression to specify the default -indentation on the top level. - -If @code{c-syntactic-indentation-in-macros} is @code{nil} then this -function keeps the current indentation, except for empty lines (ignoring -the ending backslash) where it takes the indentation from the closest -preceding nonempty line in the macro. If there's no such line in the -macro then the indentation is taken from the construct preceding it, as -described above. - -@workswith @code{cpp-define-intro}. -@end defun - -@comment ------------------------------------------------------------ - -@defun c-lineup-dont-change -@findex lineup-dont-change (c-) -This lineup function makes the line stay at whatever indentation it -already has; think of it as an identity function for lineups. - -@workswith Any syntactic symbol. -@end defun - -@comment ------------------------------------------------------------ - -@defun c-lineup-gcc-asm-reg -@findex lineup-gcc-asm-reg (c-) -Line up a gcc asm register under one on a previous line. - -@example -@group - asm ("foo %1, %0\n" - "bar %0, %1" - : "=r" (w), - "=r" (x) - : "0" (y), - "1" (z)); -@end group -@end example - -The @samp{x} line is aligned to the text after the @samp{:} on the -@samp{w} line, and similarly @samp{z} under @samp{y}. - -This is done only in an @samp{asm} or @samp{__asm__} block, and only to -those lines mentioned. Anywhere else @code{nil} is returned. The usual -arrangement is to have this routine as an extra feature at the start of -arglist lineups, e.g. - -@example -(c-lineup-gcc-asm-reg c-lineup-arglist) -@end example - -@workswith @code{arglist-cont}, @code{arglist-cont-nonempty}. -@end defun - -@comment ------------------------------------------------------------ - -@defun c-lineup-inexpr-block -@findex lineup-inexpr-block (c-) -This can be used with the in-expression block symbols to indent the -whole block to the column where the construct is started. e.g., for Java -anonymous classes, this lines up the class under the @samp{new} keyword, -and in Pike it lines up the lambda function body under the @samp{lambda} -keyword. Returns @code{nil} if the block isn't part of such a -construct. - -@workswith @code{inlambda}, @code{inexpr-statement}, -@code{inexpr-class}. +@workswith @code{inher-cont}, @code{member-init-cont}. @end defun @comment ------------------------------------------------------------ @@ -4742,79 +5763,16 @@ @comment ------------------------------------------------------------ -@defun c-lineup-knr-region-comment -@findex lineup-knr-region-comment (c-) -Line up a comment in the ``K&R region'' with the declaration. That is -the region between the function or class header and the beginning of the -block. E.g: - -@example -@group -int main() -/* Called at startup. */ @hereFn{c-lineup-knr-region-comment} -@{ - return 0; -@} -@end group -@end example - -Return @code{nil} if called in any other situation, to be useful in list -expressions. - -@workswith @code{comment-intro}. -@end defun - -@comment ------------------------------------------------------------ - -@defun c-lineup-math -@findex lineup-math (c-) -Line up the current line to after the equal sign on the first line in the -statement. If there isn't any, indent with @code{c-basic-offset}. If -the current line contains an equal sign too, try to align it with the -first one. - -@workswith @code{topmost-intro-cont}, @code{statement-cont}, -@code{arglist-cont}, @code{arglist-cont-nonempty}. -@end defun - -@comment ------------------------------------------------------------ - -@defun c-lineup-multi-inher -@findex lineup-multi-inher (c-) -Line up the classes in C++ multiple inheritance clauses and member -initializers under each other. E.g: - -@example -@group -Foo::Foo (int a, int b): - Cyphr (a), - Bar (b) @hereFn{c-lineup-multi-inher} -@end group -@end example - -@noindent -and - -@example -@group -class Foo - : public Cyphr, - public Bar @hereFn{c-lineup-multi-inher} -@end group -@end example - -@noindent -and - -@example -@group -Foo::Foo (int a, int b) - : Cyphr (a) - , Bar (b) @hereFn{c-lineup-multi-inher} -@end group -@end example - -@workswith @code{inher-cont}, @code{member-init-cont}. +@defun c-lineup-template-args +@findex lineup-template-args (c-) +Line up the arguments of a template argument list under each other, but +only in the case where the first argument is on the same line as the +opening @samp{<}. + +To allow this function to be used in a list expression, @code{nil} is +returned if there's no template argument on the first line. + +@workswith @code{template-args-cont}. @end defun @comment ------------------------------------------------------------ @@ -4851,36 +5809,127 @@ @workswith @code{objc-method-args-cont}. @end defun +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Operator Line-Up, Comment Line-Up, List Line-Up, Line-Up Functions +@comment node-name, next, previous, up +@subsection Operator Line-Up Functions +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +The line-up functions here calculate the indentation for lines which +start with an operator, by lining it up with something on the previous +line. + +@defun c-lineup-argcont +@findex lineup-argcont (c-) +Line up a continued argument. E.g: + +@example +@group +foo (xyz, aaa + bbb + ccc + + ddd + eee + fff); @hereFn{c-lineup-argcont} +@end group +@end example + +Only continuation lines like this are touched, @code{nil} is returned on +lines which are the start of an argument. + +Within a gcc @code{asm} block, @code{:} is recognised as an argument +separator, but of course only between operand specifications, not in the +expressions for the operands. + +@workswith @code{arglist-cont}, @code{arglist-cont-nonempty}. +@end defun + @comment ------------------------------------------------------------ -@defun c-lineup-runin-statements -@findex lineup-runin-statements (c-) -Line up statements for coding standards which place the first statement -in a block on the same line as the block opening brace@footnote{Run-in -style doesn't really work too well. You might need to write your own -custom indentation functions to better support this style.}. E.g: +@defun c-lineup-arglist-operators +@findex lineup-arglist-operators (c-) +Line up lines starting with an infix operator under the open paren. +Return @code{nil} on lines that don't start with an operator, to leave +those cases to other line-up functions. Example: @example @group -int main() -@{ puts ("Hello!"); - return 0; @hereFn{c-lineup-runin-statements} -@} +if ( x < 10 + || at_limit (x, @hereFn{c-lineup-arglist-operators} + list) @hereFn{c-lineup-arglist-operators@r{ returns nil}} + ) @end group @end example -If there is no statement after the opening brace to align with, -@code{nil} is returned. This makes the function usable in list +Since this function doesn't do anything for lines without an infix +operator you typically want to use it together with some other lineup +settings, e.g. as follows (the @code{arglist-close} setting is just a +suggestion to get a consistent style): + +@example +(c-set-offset 'arglist-cont + '(c-lineup-arglist-operators 0)) +(c-set-offset 'arglist-cont-nonempty + '(c-lineup-arglist-operators c-lineup-arglist)) +(c-set-offset 'arglist-close + '(c-lineup-arglist-close-under-paren)) +@end example + +@workswith @code{arglist-cont}, @code{arglist-cont-nonempty}. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-assignments +@findex lineup-assignments (c-) +Line up the current line after the assignment operator on the first line +in the statement. If there isn't any, return nil to allow stacking with +other line-up functions. If the current line contains an assignment +operator too, try to align it with the first one. + +@workswith @code{topmost-intro-cont}, @code{statement-cont}, +@code{arglist-cont}, @code{arglist-cont-nonempty}. + +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-math +@findex lineup-math (c-) +Like @code{c-lineup-assignments} but indent with @code{c-basic-offset} +if no assignment operator was found on the first line. I.e. this +function is the same as specifying a list @code{(c-lineup-assignments ++)}. It's provided for compatibility with old configurations. + +@workswith @code{topmost-intro-cont}, @code{statement-cont}, +@code{arglist-cont}, @code{arglist-cont-nonempty}. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-cascaded-calls +@findex lineup-cascaded-calls (c-) +Line up ``cascaded calls'' under each other. If the line begins with +@code{->} or @code{.} and the preceding line ends with one or more +function calls preceded by the same token, then the arrow is lined up +with the first of those tokens. E.g: + +@example +@group +r = proc->add(17)->add(18) + ->add(19) + @hereFn{c-lineup-cascaded-calls} + offset; @hereFn{c-lineup-cascaded-calls@r{ (inactive)}} +@end group +@end example + +In any other situation @code{nil} is returned to allow use in list expressions. -@workswith The @code{statement} syntactic symbol. +@workswith @code{topmost-intro-cont}, @code{statement-cont}, +@code{arglist-cont}, @code{arglist-cont-nonempty}. @end defun @comment ------------------------------------------------------------ @defun c-lineup-streamop @findex lineup-streamop (c-) -Line up C++ stream operators (i.e., @samp{<<} and @samp{>>}). +Line up C++ stream operators (i.e. @samp{<<} and @samp{>>}). @workswith @code{stream-op}. @end defun @@ -4907,18 +5956,253 @@ @code{arglist-cont}, @code{arglist-cont-nonempty}. @end defun + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Comment Line-Up, Misc Line-Up, Operator Line-Up, Line-Up Functions +@comment node-name, next, previous, up +@subsection Comment Line-Up Functions +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +The lineup functions here calculate the indentation for several types +of comment structure. + +@defun c-lineup-C-comments +@findex lineup-C-comments (c-) +Line up C block comment continuation lines. Various heuristics are used +to handle most of the common comment styles. Some examples: + +@example +@group +/* /** /* + * text * text text + */ */ */ +@end group +@end example + +@example +@group +/* text /* /** + text ** text ** text +*/ */ */ +@end group +@end example + +@example +@group +/************************************************** + * text + *************************************************/ +@end group +@end example + +@vindex comment-start-skip +@example +@group +/************************************************** + Free form text comments: + In comments with a long delimiter line at the + start, the indentation is kept unchanged for lines + that start with an empty comment line prefix. The + delimiter line is whatever matches the + @code{comment-start-skip} regexp. +**************************************************/ +@end group +@end example + +The style variable @code{c-comment-prefix-regexp} is used to recognize +the comment line prefix, e.g. the @samp{*} that usually starts every +line inside a comment. + +@workswith The @code{c} syntactic symbol. +@end defun + @comment ------------------------------------------------------------ -@defun c-lineup-template-args -@findex lineup-template-args (c-) -Line up the arguments of a template argument list under each other, but -only in the case where the first argument is on the same line as the -opening @samp{<}. - -To allow this function to be used in a list expression, @code{nil} is -returned if there's no template argument on the first line. - -@workswith @code{template-args-cont}. +@defun c-lineup-comment +@findex lineup-comment (c-) +Line up a comment-only line according to the style variable +@code{c-comment-only-line-offset}. If the comment is lined up with a +comment starter on the previous line, that alignment is preserved. + +@defopt c-comment-only-line-offset +@vindex comment-only-line-offset (c-) +This style variable specifies the extra offset for the line. It can +contain an integer or a cons cell of the form + +@example +(@r{@var{non-anchored-offset}} . @r{@var{anchored-offset}}) +@end example + +@noindent +where @var{non-anchored-offset} is the amount of offset given to +non-column-zero anchored lines, and @var{anchored-offset} is the amount +of offset to give column-zero anchored lines. Just an integer as value +is equivalent to @code{(@r{@var{value}} . -1000)}. +@end defopt + +@workswith @code{comment-intro}. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-knr-region-comment +@findex lineup-knr-region-comment (c-) +Line up a comment in the ``K&R region'' with the declaration. That is +the region between the function or class header and the beginning of the +block. E.g: + +@example +@group +int main() +/* Called at startup. */ @hereFn{c-lineup-knr-region-comment} +@{ + return 0; +@} +@end group +@end example + +Return @code{nil} if called in any other situation, to be useful in list +expressions. + +@workswith @code{comment-intro}. +@end defun + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Misc Line-Up, , Comment Line-Up, Line-Up Functions +@comment node-name, next, previous, up +@subsection Miscellaneous Line-Up Functions +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +The line-up functions here are the odds and ends which didn't fit into +any earlier category. + +@defun c-lineup-dont-change +@findex lineup-dont-change (c-) +This lineup function makes the line stay at whatever indentation it +already has; think of it as an identity function for lineups. + +@workswith Any syntactic symbol. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-cpp-define +@findex lineup-cpp-define (c-) +Line up macro continuation lines according to the indentation of the +construct preceding the macro. E.g: + +@example +@group +const char msg[] = @hereFn{@r{The beginning of the preceding construct.}} + \"Some text.\"; + +#define X(A, B) \ +do @{ \ @hereFn{c-lineup-cpp-define} + printf (A, B); \ +@} while (0) +@end group +@end example + +@noindent +and: + +@example +@group +int dribble() @{ + if (!running) @hereFn{@r{The beginning of the preceding construct.}} + error(\"Not running!\"); + +#define X(A, B) \ + do @{ \ @hereFn{c-lineup-cpp-define} + printf (A, B); \ + @} while (0) +@end group +@end example + +If @code{c-syntactic-indentation-in-macros} is non-@code{nil}, the +function returns the relative indentation to the macro start line to +allow accumulation with other offsets. E.g. in the following cases, +@code{cpp-define-intro} is combined with the +@code{statement-block-intro} that comes from the @samp{do @{} that hangs +on the @samp{#define} line: + +@example +@group +const char msg[] = + \"Some text.\"; + +#define X(A, B) do @{ \ + printf (A, B); \ @hereFn{c-lineup-cpp-define} + this->refs++; \ +@} while (0) @hereFn{c-lineup-cpp-define} +@end group +@end example + +@noindent +and: + +@example +@group +int dribble() @{ + if (!running) + error(\"Not running!\"); + +#define X(A, B) do @{ \ + printf (A, B); \ @hereFn{c-lineup-cpp-define} + this->refs++; \ + @} while (0) @hereFn{c-lineup-cpp-define} +@end group +@end example + +The relative indentation returned by @code{c-lineup-cpp-define} is zero +and two, respectively, on the two lines in each of these examples. They +are then added to the two column indentation that +@code{statement-block-intro} gives in both cases here. + +If the relative indentation is zero, then @code{nil} is returned +instead. That is useful in a list expression to specify the default +indentation on the top level. + +If @code{c-syntactic-indentation-in-macros} is @code{nil} then this +function keeps the current indentation, except for empty lines (ignoring +the ending backslash) where it takes the indentation from the closest +preceding nonempty line in the macro. If there's no such line in the +macro then the indentation is taken from the construct preceding it, as +described above. + +@workswith @code{cpp-define-intro}. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-gcc-asm-reg +@findex lineup-gcc-asm-reg (c-) +Line up a gcc asm register under one on a previous line. + +@example +@group + asm ("foo %1, %0\n" + "bar %0, %1" + : "=r" (w), + "=r" (x) + : "0" (y), + "1" (z)); +@end group +@end example + +The @samp{x} line is aligned to the text after the @samp{:} on the +@samp{w} line, and similarly @samp{z} under @samp{y}. + +This is done only in an @samp{asm} or @samp{__asm__} block, and only to +those lines mentioned. Anywhere else @code{nil} is returned. The usual +arrangement is to have this routine as an extra feature at the start of +arglist lineups, e.g. + +@example +(c-lineup-gcc-asm-reg c-lineup-arglist) +@end example + +@workswith @code{arglist-cont}, @code{arglist-cont-nonempty}. @end defun @comment ------------------------------------------------------------ @@ -4974,297 +6258,227 @@ @workswith @code{topmost-intro-cont}. @end defun -@comment ------------------------------------------------------------ - -@defun c-lineup-whitesmith-in-block -@findex lineup-whitesmith-in-block (c-) -Line up lines inside a block in Whitesmith style. It's done in a way -that works both when the opening brace hangs and when it doesn't. E.g: +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Custom Line-Up, Other Indentation, Line-Up Functions, Customizing Indentation +@comment node-name, next, previous, up +@section Custom Line-Up Functions +@cindex customization, indentation functions +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +The most flexible way to customize indentation is by writing custom +line-up functions, and associating them with specific syntactic +symbols (@pxref{c-offsets-alist}). Depending on the effect you want, +it might be better to write a @code{c-special-indent-hook} function +rather than a line-up function (@pxref{Other Indentation}). + +@ccmode{} comes with an extensive set of predefined line-up functions, +not all of which are used by the default styles. So there's a good +chance the function you want already exists. @xref{Line-Up +Functions}, for a list of them. If you write your own line-up +function, it's probably a good idea to start working from one of these +predefined functions, which can be found in the file +@file{cc-align.el}. If you have written a line-up function that you +think is generally useful, you're very welcome to contribute it; +please contact @email{bug-cc-mode@@gnu.org}. + + Line-up functions are passed a single argument, the syntactic +element (see below). The return value is a @code{c-offsets-alist} +offset specification: for example, an integer, a symbol such as +@code{+}, a vector, @code{nil}@footnote{Returning @code{nil} is useful +when the offset specification for a syntactic element is a list +containing the line-up function (@pxref{c-offsets-alist}).}, or even +another line-up function. Full details of these are in +@ref{c-offsets-alist}. + +Line-up functions must not move point or change the content of the +buffer (except temporarily). They are however allowed to do +@dfn{hidden buffer changes}, i.e. setting text properties for caching +purposes etc. Buffer undo recording is disabled while they run. + +The syntactic element passed as the parameter to a line-up function is +a cons cell of the form @example -@group -something - @{ - foo; @hereFn{c-lineup-whitesmith-in-block} - @} -@end group +(@r{@var{syntactic-symbol}} . @r{@var{anchor-position}}) @end example @noindent -and - -@example -@group -something @{ - foo; @hereFn{c-lineup-whitesmith-in-block} - @} -@sssTBasicOffset{} -@end group -@end example - -In the first case the indentation is kept unchanged, in the second -@code{c-basic-offset} is added. - -@workswith @code{defun-close}, @code{defun-block-intro}, -@code{block-close}, @code{brace-list-close}, @code{brace-list-intro}, -@code{statement-block-intro} and all @code{in*} symbols, -e.g., @code{inclass} and @code{inextern-lang}. +@c FIXME!!! The following sentence might be better omitted, since the +@c information is in the cross reference "Syntactic Analysis". 2005/10/2. +where @var{syntactic-symbol} is the symbol that the function was +called for, and @var{anchor-position} is the anchor position (if any) +for the construct that triggered the syntactic symbol +(@pxref{Syntactic Analysis}). This cons cell is how the syntactic +element of a line used to be represented in @ccmode{} 5.28 and +earlier. Line-up functions are still passed this cons cell, so as to +preserve compatibility with older configurations. In the future, we +may decide to convert to using the full list format---you can prepare +your setup for this by using the access functions +(@code{c-langelem-sym}, etc.) described below. + +@vindex c-syntactic-element +@vindex syntactic-element (c-) +@vindex c-syntactic-context +@vindex syntactic-context (c-) +Some syntactic symbols, e.g. @code{arglist-cont-nonempty}, have more +info in the syntactic element - typically other positions that can be +interesting besides the anchor position. That info can't be accessed +through the passed argument, which is a cons cell. Instead, you can +get this information from the variable @code{c-syntactic-element}, +which is dynamically bound to the complete syntactic element. The +variable @code{c-syntactic-context} might also be useful - it gets +dynamically bound to the complete syntactic context. @xref{Custom +Braces}. + +@ccmode{} provides a few functions to access parts of syntactic +elements in a more abstract way. Besides making the code easier to +read, they also hide the difference between the old cons cell form +used in the line-up function argument and the new list form used in +@code{c-syntactic-element} and everywhere else. The functions are: + +@defun c-langelem-sym langelem +@findex langelem-sym (c-) +Return the syntactic symbol in @var{langelem}. +@end defun + +@defun c-langelem-pos langelem +@findex langelem-pos (c-) +Return the anchor position in @var{langelem}, or nil if there is none. +@end defun + +@defun c-langelem-col langelem &optional preserve-point +@findex langelem-col (c-) +Return the column of the anchor position in @var{langelem}. Also move +the point to that position unless @var{preserve-point} is +non-@code{nil}. @end defun - -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node AWK Mode, Odds and Ends, Indentation Functions, Top -@comment node-name, next, previous, up -@chapter Status of AWK Mode -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -@dfn{AWK mode} existed until recently in the file @file{awk-mode.el} -as a mode derived from c-mode. It had not been actively maintained to -keep pace with the newer @ccmode{}, and its indentation mechanism no -longer worked satisfactorally. - -The current AWK mode is based around the GNU implementation, -@emph{GAWK version 3.1.0}, though it should work pretty well with any -AWK. It has now been updated and integrated into @ccmode{} to a -substantial extent, though as yet not all the features of @ccmode{} -have been adapted to support it. - -If your (X)Emacs is set up to use the old file @file{awk-mode.elc} -(which will usually be the case if you have obtained this @ccmode{} -independently of (X)Emacs itself), or if you are not sure, insert the -following form into your @file{.emacs} or @file{init.el} so that the new -AWK mode will be used instead: - -@example -(autoload 'awk-mode "cc-mode" nil t) -@end example - -You can check which AWK mode you are running by displaying the mode -documentation string with @kbd{C-h m} from an AWK buffer. The newer -mode's doc string contains @code{To submit a problem report, enter -`C-c C-b'} near the top of the doc string where the older mode has -@code{This is much like C mode except ....}. - -Since this newer AWK mode makes essential use of a relatively new -Emacs Lisp feature@footnote{Specifically, the @code{syntax-table} text -property.}, you need either GNU Emacs 20.1 (or later) or XEmacs 21.4 -(or later) to use it. If your Emacs version is earlier than one of -these, the older @file{awk-mode.el} will get loaded and run in place -of the AWK mode described here, even when you have put the above -@code{autoload} form into your @file{.emacs} or @file{init.el}. -Upgrading your (X)Emacs is strongly recommended if this is the case. - -Here is an overview of which @ccmode{} features currently work with -AWK mode and which don't: - -@table @asis -@item Indentation Engine -The @ccmode{} indentation engine fully supports AWK mode. -@xref{Indentation Engine}. - -AWK mode handles code formatted in the conventional AWK fashion: -@samp{@{}s which start actions, user-defined functions, or compound -statements are placed on the same line as the associated construct; the -matching @samp{@}}s are normally placed under the start of the -respective pattern, function definition, or structured statement. -@c Add in a bit about the @samp{@}} being on the same line when the -@c contents are short. - -The predefined indentation functions (@pxref{Indentation Functions}) -haven't yet been adapted for AWK mode, though some of them may work -serendipitously. There shouldn't be any problems writing custom -indentation functions for AWK mode. - -The command @kbd{C-c C-q} (@code{c-indent-defun}) hasn't yet been -adapted for AWK, though in practice it works properly nearly all the -time. Should it fail, explicitly set the region around the function -(using @kbd{C-u C-SPC}: @kbd{C-M-h} probably won't work either) then do -@kbd{C-M-\} (@code{indent-region}). - -@item Font Locking -There is a single level of font locking in AWK mode, rather than the -three distinct levels the other modes have. There are several -idiosyncrasies in AWK mode's font-locking due to the peculiarities of -the AWK language itself. @xref{AWK Mode Font Locking}. - -@item Comment Commands -@kbd{M-;} (@code{indent-for-comment}) works fine. None of the other -@ccmode{} comment formatting commands have yet been adapted for AWK -mode. @xref{Text Filling and Line Breaking}. - -@item Movement Commands -Most of the movement commands work in AWK mode. The most important -exceptions are @kbd{M-a} (@code{c-beginning-of-statement}) and -@kbd{M-e} (@code{c-end-of-statement}) which haven't yet been adapted. - -The notion of @dfn{defun} has been augmented to include pattern-action -pairs. See @ref{AWK Mode Defuns} for a description of commands which -work on AWK ``defuns''. - -Since there is no preprocessor in AWK, the commands which move to -preprocessor directives (e.g., @code{c-up-conditional}) are meaningless -in AWK mode and are not bound in the AWK mode keymap. - -@item Auto-newline Insertion and Clean-ups -Auto-newline insertion hasn't yet been adapted for AWK. Some of the -clean-ups can actually convert good AWK code into syntactically -invalid code. - -If auto-newline or its associated clean-ups are enabled generally for -the modes in @ccmode{}, you are strongly recommended to disable them -in the AWK Mode hook. @xref{Initialising AWK Mode}. - -The clean-up @code{space-before-funcall}, which is independent of -auto-newline, should never be active in AWK mode (since inserting a -space between a user function's name and its opening @samp{(} makes -the call syntactically invalid). If necessary, this should be -disabled in the AWK Mode hook. @xref{Initialising AWK Mode}. - -@end table - -@menu -* Initialising AWK Mode:: -* AWK Mode Font Locking:: -* AWK Mode Defuns:: -@end menu - - -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Initialising AWK Mode, AWK Mode Font Locking, , AWK Mode -@comment node-name, next, previous, up -@section AWK mode - What to put in your @file{.emacs} or @file{init.el} -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -Much of the AWK mode initialization can, of course, be done by the -@ccmode{} general initialization procedure. You may want to use certain -@ccmode{} features such as @code{auto-newline} and @code{clean-ups} in -the other modes, and you might thus have enabled them in a -@code{c-mode-common-hook} function, as described in @ref{Sample .emacs File}. -These features have not yet been amended for AWK mode, and far from -being useful, can be irritating in AWK mode or actually make AWK code -syntactically invalid. Adding the following code to your -@file{.emacs} or @file{init.el} file will disable them for AWK mode. - -@example -(defun my-awk-mode-hook () - "Disable certain @ccmode{} features which could impair AWK mode." - (c-toggle-auto-state -1) ; disable automatic insertions of newlines - (if (memq 'space-before-funcall c-cleanup-list) - (setq c-cleanup-list ; don't automatically insert a space into "foo(" - (remove 'space-before-funcall c-cleanup-list)))) -(add-hook 'awk-mode-hook 'my-awk-mode-hook) -@end example - -Naturally you can add your own AWK-specific customizations to this -function. @xref{Hooks}. - - -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node AWK Mode Font Locking, AWK Mode Defuns, Initialising AWK Mode, AWK Mode -@comment node-name, next, previous, up -@section AWK Mode Font Locking -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -The general appearance of font-locking in AWK mode is much like in any -other programming mode. @xref{Faces For Font Lock,,,elisp}. - -The following faces are, however, used in a non-standard fashion in -AWK mode: - -@table @asis -@item @code{font-lock-variable-name-face} -This face was intended for variable declarations. Since variables are -not declared in AWK, this face is used instead for AWK system -variables (such as @code{NF}) and ``Special File Names'' (such as -@code{"/dev/stderr"}). - -@item @code{font-lock-builtin-face} (Emacs)/@code{font-lock-preprocessor-face} (XEmacs) -This face is normally used for preprocessor directives in @ccmode{}. -There are no such things in AWK, so this face is used instead for -standard functions (such as @code{match}). - -@item @code{font-lock-string-face} -As well as being used for strings, including localizable strings, -(delimited by @samp{"} and @samp{_"}), this face is also used for AWK -regular expressions (delimited by @samp{/}). - -@item @code{font-lock-warning-face} (Emacs)/@code{c-invalid-face} (XEmacs) -This face highlights the following syntactically invalid AWK -constructs: - -@itemize @bullet -@item -An unterminated string or regular expression. Here the opening -delimiter (@samp{"} or @samp{/} or @samp{_"}) is displayed in -@code{font-lock-warning-face}. This is most noticeable when typing in a -new string/regular expression into a buffer, when the warning-face -serves as a continual reminder to terminate the construct. - -AWK mode fontifies unterminated strings/regular expressions -differently from other modes: Only the text up to the end of the line -is fontified as a string (escaped newlines being handled correctly), -rather than the text up to the next string quote. - -@item -A space between the function name and opening parenthesis when calling -a user function. The last character of the function name and the -opening parenthesis are highlighted. This font-locking rule will -spuriously highlight a valid concatenation expression where an -identifier precedes a parenthesised expression. Unfortunately. - -@item -Whitespace following the @samp{\} in what otherwise looks like an -escaped newline. The @samp{\} is highlighted. -@end itemize -@end table - - -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node AWK Mode Defuns, , AWK Mode Font Locking, AWK Mode -@comment node-name, next, previous, up -@section AWK Mode Defuns -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -In AWK mode, @dfn{defun} means either a user-defined function or a -pattern-action pair. Either the pattern or the action may be -implicit. - -The beginning of a defun is recognised heuristically as, more or less, -code which begins in column zero. Having the @samp{@{} in column zero, -as is suggested for some modes, is neither necessary nor helpful in AWK -mode. - -More precisely, the beginning of a defun is code which begins in -column zero, and which isn't a closing brace, a comment, or a -continuation of the previous line. Code is the @dfn{continuation of -the previous line} when that line is syntactically incomplete, for -example when it ends with @samp{@{} or an escaped newline. - -The end of a defun is the @samp{@}} which matches the @samp{@{} (if -any) at the beginning of the action or function body, or the EOL or -@samp{;} which marks an implicit action. Although this @samp{@}} is -usually placed in column zero, AWK mode doesn't need it to be placed -there. - -@table @asis -@item @kbd{C-M-a} @code{c-awk-beginning-of-defun} -@itemx @kbd{C-M-e} @code{c-awk-end-of-defun} -@findex c-awk-beginning-of-defun -@findex awk-beginning-of-defun (c-) -@findex c-awk-end-of-defun -@findex awk-end-of-defun (c-) -Move point back to the beginning or forward to the end of the current -AWK defun. These functions can take prefix-arguments, their -functionality being entirely equivalent to @code{beginning-of-defun} -and @code{end-of-defun}. @xref{Moving by Defuns,,,emacs}. - -@item @kbd{C-M-h} @code{c-mark-function} -This works fine with AWK defuns. @xref{Indentation Commands}. -@end table +@defun c-langelem-2nd-pos langelem +@findex langelem-2nd-pos (c-) +Return the secondary position in @var{langelem}, or @code{nil} if there +is none. + +Note that the return value of this function is always @code{nil} if +@var{langelem} is in the old cons cell form. Thus this function is +only meaningful when used on syntactic elements taken from +@code{c-syntactic-element} or @code{c-syntactic-context}. +@end defun + +Custom line-up functions can be as simple or as complex as you like, and +any syntactic symbol that appears in @code{c-offsets-alist} can have a +custom line-up function associated with it. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Other Indentation, , Custom Line-Up, Customizing Indentation +@comment node-name, next, previous, up +@section Other Special Indentations +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Here are the remaining odds and ends regarding indentation: + +@defopt c-label-minimum-indentation +@vindex label-minimum-indentation (c-) +In @samp{gnu} style (@pxref{Built-in Styles}), a minimum indentation is +imposed on lines inside code blocks. This minimum indentation is +controlled by this style variable. The default value is 1. + +@findex c-gnu-impose-minimum +@findex gnu-impose-minimum (c-) +It's the function @code{c-gnu-impose-minimum} that enforces this minimum +indentation. It must be present on @code{c-special-indent-hook} to +work. +@end defopt + +@defopt c-special-indent-hook +@vindex special-indent-hook (c-) +This style variable is a standard hook variable that is called after +every line is indented by @ccmode{}. It is called only if +@code{c-syntactic-indentation} is non-@code{nil} (which it is by +default (@pxref{Indentation Engine Basics})). You can put a function +on this hook to do any special indentation or ad hoc line adjustments +your style dictates, such as adding extra indentation to constructors +or destructor declarations in a class definition, etc. Sometimes it +is better to write a custom Line-up Function instead (@pxref{Custom +Line-Up}). + +When the indentation engine calls this hook, the variable +@code{c-syntactic-context} is bound to the current syntactic context +(i.e. what you would get by typing @kbd{C-c C-s} on the source line. +@xref{Custom Braces}.). Note that you should not change point or mark +inside a @code{c-special-indent-hook} function, i.e. you'll probably +want to wrap your function in a @code{save-excursion}@footnote{The +numerical value returned by @code{point} will change if you change the +indentation of the line within a @code{save-excursion} form, but point +itself will still be over the same piece of text.}. + +Setting @code{c-special-indent-hook} in style definitions is handled +slightly differently from other variables---A style can only add +functions to this hook, not remove them. @xref{Style Variables}. +@end defopt @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Odds and Ends, Performance Issues, AWK Mode, Top +@node Custom Macros, Odds and Ends, Customizing Indentation, Top +@comment node-name, next, previous, up +@chapter Customizing Macros +@cindex macros +@cindex preprocessor directives +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Normally, the lines in a multi-line macro are indented relative to +eachother as though they were code. You can suppress this behaviour +by setting the following user option: + +@defopt c-syntactic-indentation-in-macros +@vindex syntactic-indentation-in-macros (c-) +Enable syntactic analysis inside macros, which is the default. If this +is @code{nil}, all lines inside macro definitions are analyzed as +@code{cpp-macro-cont}. +@end defopt + +@ccmode{} provides some tools to help keep the line continuation +backslashes in macros neat and tidy. Their precise action is +customized with these variables: + +@defopt c-backslash-column +@vindex backslash-column (c-) +@defoptx c-backslash-max-column +@vindex backslash-max-column (c-) +These variables control the alignment columns for line continuation +backslashes in multiline macros. They are used by the functions that +automatically insert or align such backslashes, +e.g. @code{c-backslash-region} and @code{c-context-line-break}. + +@code{c-backslash-column} specifies the minimum column for the +backslashes. If any line in the macro goes past this column, then the +next tab stop (i.e. next multiple of @code{tab-width}) in that line is +used as the alignment column for all the backslashes, so that they +remain in a single column. However, if any lines go past +@code{c-backslash-max-column} then the backslashes in the rest of the +macro will be kept at that column, so that the lines which are too +long ``stick out'' instead. + +Don't ever set these variables to @code{nil}. If you want to disable +the automatic alignment of backslashes, use +@code{c-auto-align-backslashes}. +@end defopt + +@defopt c-auto-align-backslashes +@vindex auto-align-backslashes (c-) +Align automatically inserted line continuation backslashes if +non-@code{nil}. When line continuation backslashes are inserted +automatically for line breaks in multiline macros, e.g. by +@code{c-context-line-break}, they are aligned with the other +backslashes in the same macro if this flag is set. + +If @code{c-auto-align-backslashes} is @code{nil}, automatically +inserted backslashes are preceded by a single space, and backslashes +get aligned only when you explicitly invoke the command +@code{c-backslash-region} (@kbd{C-c C-\}). +@end defopt + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Odds and Ends, Sample .emacs File, Custom Macros, Top @comment node-name, next, previous, up @chapter Odds and Ends @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -5273,16 +6487,16 @@ @defopt c-require-final-newline @vindex require-final-newline (c-) -Controls whether a final newline is ensured when the file is saved. The -value is an association list that for each language mode specifies the -value to give to @code{require-final-newline} at mode initialization; -see that variable for details about the value. If a language isn't -present on the association list, CC Mode won't touch +Controls whether a final newline is enforced when the file is saved. +The value is an association list that for each language mode specifies +the value to give to @code{require-final-newline} (@pxref{Saving +Buffers,,, @lispref{}, @lispreftitle{}}) at mode initialization. If a +language isn't present on the association list, CC Mode won't touch @code{require-final-newline} in buffers for that language. The default is to set @code{require-final-newline} to @code{t} in the -languages that mandates that source files should end with newlines, -i.e., C, C++ and Objective-C. +languages that mandate that source files should end with newlines. +These are C, C++ and Objective-C. @end defopt @defopt c-echo-syntactic-information-p @@ -5308,7 +6522,68 @@ @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Performance Issues, Limitations and Known Bugs, Odds and Ends, Top +@node Sample .emacs File, Performance Issues, Odds and Ends, Top +@comment node-name, next, previous, up +@appendix Sample .emacs File +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@verbatim +;; Here's a sample .emacs file fragment that might help you along the +;; way. Just copy this region and paste it into your .emacs file. +;; You might want to change some of the actual values. + +;; Make some non-standard key bindings. We can put these in +;; c-mode-base-map because c-mode-map, c++-mode-map, and so on, +;; inherit from it. +(defun my-c-initialization-hook () + (define-key c-mode-base-map "\C-m" 'c-context-line-break) + (define-key c-mode-base-map [?\C-\M-a] 'c-beginning-of-defun) + (define-key c-mode-base-map [?\C-\M-e] 'c-end-of-defun) +(add-hook 'c-initialization-hook 'my-c-initialization-hook) + +;; offset customizations not in my-c-style +;; This will take precedence over any setting of the syntactic symbol +;; made by a style. +(setq c-offsets-alist '((member-init-intro . ++))) + +;; Create my personal style. +(defconst my-c-style + '((c-tab-always-indent . t) + (c-comment-only-line-offset . 4) + (c-hanging-braces-alist . ((substatement-open after) + (brace-list-open))) + (c-hanging-colons-alist . ((member-init-intro before) + (inher-intro) + (case-label after) + (label after) + (access-label after))) + (c-cleanup-list . (scope-operator + empty-defun-braces + defun-close-semi)) + (c-offsets-alist . ((arglist-close . c-lineup-arglist) + (substatement-open . 0) + (case-label . 4) + (block-open . 0) + (knr-argdecl-intro . -))) + (c-echo-syntactic-information-p . t)) + "My C Programming Style") +(c-add-style "PERSONAL" my-c-style) + +;; Customizations for all modes in CC Mode. +(defun my-c-mode-common-hook () + ;; set my personal style for the current buffer + (c-set-style "PERSONAL") + ;; other customizations + (setq tab-width 8 + ;; this will make sure spaces are used instead of tabs + indent-tabs-mode nil) + ;; we like auto-newline, but not hungry-delete + (c-toggle-auto-newline 1)) +(add-hook 'c-mode-common-hook 'my-c-mode-common-hook) +@end verbatim + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Performance Issues, Limitations and Known Bugs, Sample .emacs File, Top @comment node-name, next, previous, up @chapter Performance Issues @cindex performance @@ -5323,10 +6598,10 @@ section gives some insight in how @ccmode{} operates, how that interacts with some coding styles, and what you can use to improve performance. -The overall goal is that @ccmode{} shouldn't be overly slow (i.e., take +The overall goal is that @ccmode{} shouldn't be overly slow (i.e. take more than a fraction of a second) in any interactive operation. -i.e., it's tuned to limit the maximum response time in single operations, -which sometimes is at the expense of batch-like operations like +I.e. it's tuned to limit the maximum response time in single operations, +which is sometimes at the expense of batch-like operations like reindenting whole blocks. If you find that @ccmode{} gradually gets slower and slower in certain situations, perhaps as the file grows in size or as the macro or comment you're editing gets bigger, then chances @@ -5337,28 +6612,30 @@ insertion point, and because C's syntax is fairly difficult to parse in the backwards direction, @ccmode{} often tries to find the nearest position higher up in the buffer from which to begin a forward scan -(it's typically an opening or closing parethesis of some kind). The +(it's typically an opening or closing parenthesis of some kind). The farther this position is from the current insertion point, the slower it gets. @findex beginning-of-defun +In earlier versions of @ccmode{}, we used to recommend putting the +opening brace of a top-level construct@footnote{E.g. a function in C, +or outermost class definition in C++ or Java.} into the leftmost +column. Earlier still, this used to be a rigid Emacs constraint, as +embodied in the @code{beginning-of-defun} function. @ccmode now +caches syntactic information much better, so that the delay caused by +searching for such a brace when it's not in column 0 is minimal, +except perhaps when you've just moved a long way inside the file. +Don't forget to rebind @kbd{C-M-a} and @kbd{C-M-e} to the @ccmode{} +functions @code{beginning-of-defun} and @code{end-of-defun} if you're +going to be hanging your braces! @xref{Sample .emacs File}. + @findex defun-prompt-regexp -One of the simplest things you can do to reduce scan time, is make sure -any brace that opens a top-level construct@footnote{e.g., a function in -C, or outermost class definition in C++ or Java.} always appears in the -leftmost column. This is actually an Emacs constraint, as embodied in -the @code{beginning-of-defun} function which @ccmode{} uses heavily. If -you hang top-level open braces on the right side of the line, then you -might want to set the variable @code{defun-prompt-regexp} to something -reasonable, however that ``something reasonable'' is difficult to -define, so @ccmode{} doesn't do it for you. - @vindex c-Java-defun-prompt-regexp @vindex Java-defun-prompt-regexp (c-) A special note about @code{defun-prompt-regexp} in Java mode: The common style is to hang the opening braces of functions and classes on the right side of the line, and that doesn't work well with the Emacs -approach. @ccmode{} comes with a variable +approach. @ccmode{} comes with a constant @code{c-Java-defun-prompt-regexp} which tries to define a regular expression usable for this style, but there are problems with it. In some cases it can cause @code{beginning-of-defun} to hang@footnote{This @@ -5386,7 +6663,7 @@ tells @ccmode{} to use XEmacs-specific built-in functions which, in some circumstances, can locate the top-most opening brace much more quickly than @code{beginning-of-defun}. Preliminary testing has shown that for -styles where these braces are hung (e.g., most JDK-derived Java styles), +styles where these braces are hung (e.g. most JDK-derived Java styles), this hack can improve performance of the core syntax parsing routines from 3 to 60 times. However, for styles which @emph{do} conform to Emacs' recommended style of putting top-level braces in column zero, @@ -5397,7 +6674,7 @@ 21.3 as of this writing in May 2003). Text properties are used to speed up skipping over syntactic whitespace, -i.e., comments and preprocessor directives. Indenting a line after a +i.e. comments and preprocessor directives. Indenting a line after a huge macro definition can be slow the first time, but after that the text properties are in place and it should be fast (even after you've edited other parts of the file and then moved back). @@ -5405,7 +6682,7 @@ Font locking can be a CPU hog, especially the font locking done on decoration level 3 which tries to be very accurate. Note that that level is designed to be used with a font lock support mode that only -fontifies the text that's actually shown, i.e., Lazy Lock or Just-in-time +fontifies the text that's actually shown, i.e. Lazy Lock or Just-in-time Lock mode, so make sure you use one of them. Fontification of a whole buffer with some thousand lines can often take over a minute. That is a known weakness; the idea is that it never should happen. @@ -5418,7 +6695,7 @@ @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Limitations and Known Bugs, Frequently Asked Questions, Performance Issues, Top +@node Limitations and Known Bugs, FAQ, Performance Issues, Top @comment node-name, next, previous, up @chapter Limitations and Known Bugs @cindex limitations @@ -5427,9 +6704,9 @@ @itemize @bullet @item -There is no way to apply auto newline settings (@pxref{Auto-newline -Insertion}) on already typed lines. That's only a feature to ease -interactive editing. +There is no way to apply auto newline settings (@pxref{Auto-newlines}) +on already typed lines. That's only a feature to ease interactive +editing. To generalize this issue a bit: @ccmode{} is not intended to be used as a reformatter for old code in some more or less batch-like way. With @@ -5438,47 +6715,29 @@ intention to change this goal. If you want to reformat old code, you're probably better off using some -other tool instead, e.g., @ref{Top, , GNU indent, indent, The `indent' +other tool instead, e.g. @ref{Top, , GNU indent, indent, The `indent' Manual}, which has more powerful reformatting capabilities than @ccmode{}. @item -@vindex signal-error-on-buffer-boundary -XEmacs has a variable called @code{signal-error-on-buffer-boundary}. -It's used as a solution to user interface problems associated with -buffer movement and the @code{zmacs-region} deactivation on errors. -However, setting this variable to a non-default value in XEmacs 19 and -20 had the deleterious side effect of breaking many built-in primitive -functions. @strong{Do not set this variable to @code{nil} in XEmacs -19 and 20}; you will cause serious problems in @ccmode{} and probably -other XEmacs packages! In XEmacs 21 the effects of the variable is -limited to some functions that are only used interactively, so it's -not a problem there. +The support for C++ templates (in angle brackets) is not yet complete. +When a non-nested template is used in a declaration, @ccmode{} indents +it and font-locks it OK. Templates used in expressions, and nested +templates do not fare so well. Sometimes a workaround is to refontify +the expression after typing the closing @samp{>}. @end itemize - @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Frequently Asked Questions, Getting the Latest CC Mode Release, Limitations and Known Bugs, Top +@node FAQ, Updating CC Mode, Limitations and Known Bugs, Top @comment node-name, next, previous, up @appendix Frequently Asked Questions @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @itemize @bullet @item -@kindex C-x h -@kindex C-M-\ -@emph{How do I reindent the whole file?} - -Visit the file and hit @kbd{C-x h} to mark the whole buffer. Then hit -@kbd{C-M-\}. - -@item -@kindex C-M-q -@kindex C-M-u -@emph{How do I reindent the current block?} - -First move to the brace which opens the block with @kbd{C-M-u}, then -reindent that expression with @kbd{C-M-q}. +@emph{How can I change the indent level from 4 spaces to 2 spaces?} + +Set the variable @code{c-basic-offset}. @xref{Getting Started}. @item @kindex RET @@ -5487,57 +6746,55 @@ Emacs' convention is that @kbd{RET} just adds a newline, and that @kbd{C-j} adds a newline and indents it. You can make @kbd{RET} do this -too by adding this to your @code{c-mode-common-hook}: +too by adding this to your @code{c-initialization-hook}: @example (define-key c-mode-base-map "\C-m" 'c-context-line-break) @end example -This is a very common question. If you want this to be the default -behavior, don't lobby me, lobby RMS! @t{:-)} +@xref{Getting Started}. This is a very common question. If you want +this to be the default behavior, don't lobby us, lobby RMS! @t{:-)} + +@item +@emph{How do I stop my code jumping all over the place when I type?} + +Deactivate ``electric minor mode'' with @kbd{C-c C-l}. @xref{Getting +Started}. + +@item +@kindex C-x h +@kindex C-M-\ +@emph{How do I reindent the whole file?} + +Visit the file and hit @kbd{C-x h} to mark the whole buffer. Then hit +@kbd{C-M-\}. @xref{Indentation Commands}. + +@item +@kindex C-M-q +@kindex C-M-u +@emph{How do I reindent the current block?} + +First move to the brace which opens the block with @kbd{C-M-u}, then +reindent that expression with @kbd{C-M-q}. @xref{Indentation +Commands}. @item @emph{I put @code{(c-set-offset 'substatement-open 0)} in my @file{.emacs} file but I get an error saying that @code{c-set-offset}'s function definition is void. What's wrong?} -This means that @ccmode{} wasn't loaded into your Emacs session by the -time the @code{c-set-offset} call was reached, most likely because -@ccmode{} is being autoloaded. Instead of putting the -@code{c-set-offset} line in your top-level @file{.emacs} file, put it in -your @code{c-mode-common-hook}, or simply modify @code{c-offsets-alist} -directly: +This means that @ccmode{} hasn't yet been loaded into your Emacs +session by the time the @code{c-set-offset} call is reached, most +likely because @ccmode{} is being autoloaded. Instead of putting the +@code{c-set-offset} line in your top-level @file{.emacs} file, put it +in your @code{c-initialization-hook} (@pxref{CC Hooks}), or simply +modify @code{c-offsets-alist} directly: @example (setq c-offsets-alist '((substatement-open . 0))) @end example @item -@kindex M-a -@kindex M-e -@emph{@kbd{M-a} and @kbd{M-e} used to move over entire balanced brace -lists, but now they move into blocks. How do I get the old behavior -back?} - -Use @kbd{C-M-f} and @kbd{C-M-b} to move over balanced brace blocks. Use -@kbd{M-a} and @kbd{M-e} to move by statements, which will also move into -blocks. - -@item -@emph{Whenever I try to indent a line or type an ``electric'' key such -as @kbd{;}, @kbd{@{}, or @kbd{@}}, I get an error that look like this: -@code{Invalid function: (macro . #[...}. What gives?} - -This is a common error when @ccmode{} hasn't been compiled correctly, -especially under Emacs 19.34@footnote{Technically, it's because some -macro wasn't defined during the compilation, so the byte compiler put -in function calls instead of the macro expansions. Later, when the -interpreter tries to call the macro as a function, it shows this -(somewhat cryptic) error message.}. If you are using the standalone -@ccmode{} distribution, try recompiling it according to the instructions -in the @file{README} file. - -@item @cindex open paren in column zero @emph{I have an open paren character at column zero inside a comment or multiline string literal, and it causes the fontification and/or @@ -5546,20 +6803,25 @@ It's due to the ad-hoc rule in (X)Emacs that such open parens always start defuns (which translates to functions, classes, namespaces or any other top-level block constructs in the @ccmode{} languages). -@xref{Left Margin Paren,,, emacs, The Emacs Editor}, for details -(@xref{Defuns,,, emacs, The Emacs Editor}, in the Emacs 20 manual). +@ifset XEMACS +@xref{Defuns,,, xemacs, XEmacs User's Manual}, for details. +@end ifset +@ifclear XEMACS +@xref{Left Margin Paren,,, emacs, GNU Emacs Manual}, for details +(@xref{Defuns,,, emacs, GNU Emacs Manual}, in the Emacs 20 manual). +@end ifclear This heuristic is built into the core syntax analysis routines in -(X)Emacs, so it's not really a @ccmode{} issue. However, in Emacs 22.1 -it has become possible to turn it off@footnote{Using the variable +(X)Emacs, so it's not really a @ccmode{} issue. However, in Emacs +21.1 it became possible to turn it off@footnote{Using the variable @code{open-paren-in-column-0-is-defun-start}.} and @ccmode{} does so -there since it got its own system to keep track of blocks. +there since it's got its own system to keep track of blocks. @end itemize @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Getting the Latest CC Mode Release, Mailing Lists and Submitting Bug Reports, Frequently Asked Questions, Top +@node Updating CC Mode, Mailing Lists and Bug Reports, FAQ, Top @comment node-name, next, previous, up @appendix Getting the Latest CC Mode Release @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -5579,7 +6841,7 @@ @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Mailing Lists and Submitting Bug Reports, Sample .emacs File, Getting the Latest CC Mode Release, Top +@node Mailing Lists and Bug Reports, Command and Function Index, Updating CC Mode, Top @comment node-name, next, previous, up @appendix Mailing Lists and Submitting Bug Reports @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -5597,83 +6859,33 @@ you think it might affect our ability to reproduce it. Please try to produce the problem in an Emacs instance without any -customizations loaded (i.e., start it with the @samp{-q --no-site-file} -arguments). If it works correctly there, the problem might be caused by -faulty customizations in either your own or your site configuration. In -that case, we'd appreciate if you isolate the Emacs Lisp code that trigs -the bug and include it in your report. +customizations loaded (i.e. start it with the @samp{-q -no-site-file} +arguments). If it works correctly there, the problem might be caused +by faulty customizations in either your own or your site +configuration. In that case, we'd appreciate if you isolate the Emacs +Lisp code that triggers the bug and include it in your report. @cindex bug report mailing list -Bug reports are sent to @email{bug-cc-mode@@gnu.org}. You can also send -other questions and suggestions (kudos? @t{;-)} to that address. It's a -mailing list which you can join or browse an archive of; see the web -site at @uref{http://cc-mode.sourceforge.net/} for further details. +Bug reports should be sent to @email{bug-cc-mode@@gnu.org}. You can +also send other questions and suggestions (kudos? @t{;-)} to that +address. It's a mailing list which you can join or browse an archive +of; see the web site at @uref{http://cc-mode.sourceforge.net/} for +further details. @cindex announcement mailing list If you want to get announcements of new @ccmode{} releases, send the word @emph{subscribe} in the body of a message to @email{cc-mode-announce-request@@lists.sourceforge.net}. It's possible to subscribe from the web site too. Announcements will also be posted -to the Usenet newsgroups @code{gnu.emacs.sources}, @code{comp.emacs} and -@code{comp.emacs.xemacs}. - - -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Sample .emacs File, Command and Function Index, Mailing Lists and Submitting Bug Reports, Top -@comment node-name, next, previous, up -@appendix Sample .emacs file +to the Usenet newsgroups @code{gnu.emacs.sources}, @code{comp.emacs}, +@code{comp.emacs.xemacs}, @code{comp.lang.c}, @code{comp.lang.c++}, +@code{comp.lang.objective-c}, @code{comp.lang.java.softwaretools}, +@code{comp.lang.idl}, and @code{comp.lang.awk}. +@c There is no newsgroup for Pike. :-( + +@c Removed the tentative node "Mode Initialization" from here, 2005/8/27. @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -@example -;; Here's a sample .emacs file that might help you along the way. -;; Just copy this region and paste it into your .emacs file. You may -;; want to change some of the actual values. - -(defconst my-c-style - '((c-tab-always-indent . t) - (c-comment-only-line-offset . 4) - (c-hanging-braces-alist . ((substatement-open after) - (brace-list-open))) - (c-hanging-colons-alist . ((member-init-intro before) - (inher-intro) - (case-label after) - (label after) - (access-label after))) - (c-cleanup-list . (scope-operator - empty-defun-braces - defun-close-semi)) - (c-offsets-alist . ((arglist-close . c-lineup-arglist) - (substatement-open . 0) - (case-label . 4) - (block-open . 0) - (knr-argdecl-intro . -))) - (c-echo-syntactic-information-p . t)) - "My C Programming Style") - -;; offset customizations not in my-c-style -(setq c-offsets-alist '((member-init-intro . ++))) - -;; Customizations for all modes in CC Mode. -(defun my-c-mode-common-hook () - ;; add my personal style and set it for the current buffer - (c-add-style "PERSONAL" my-c-style t) - ;; other customizations - (setq tab-width 8 - ;; this will make sure spaces are used instead of tabs - indent-tabs-mode nil) - ;; we like auto-newline and hungry-delete - (c-toggle-auto-hungry-state 1) - ;; key bindings for all supported languages. We can put these in - ;; c-mode-base-map because c-mode-map, c++-mode-map, objc-mode-map, - ;; java-mode-map, idl-mode-map, and pike-mode-map inherit from it. - (define-key c-mode-base-map "\C-m" 'c-context-line-break)) - -(add-hook 'c-mode-common-hook 'my-c-mode-common-hook) -@end example - - -@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Command and Function Index, Variable Index, Sample .emacs File, Top +@node Command and Function Index, Variable Index, Mailing Lists and Bug Reports, Top @comment node-name, next, previous, up @unnumbered Command and Function Index @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -5688,7 +6900,7 @@ @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Variable Index, Concept Index, Command and Function Index, Top +@node Variable Index, Concept and Key Index, Command and Function Index, Top @comment node-name, next, previous, up @unnumbered Variable Index @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -5703,9 +6915,9 @@ @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -@node Concept Index, , Variable Index, Top +@node Concept and Key Index, , Variable Index, Top @comment node-name, next, previous, up -@unnumbered Concept Index +@unnumbered Concept and Key Index @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @printindex cp
--- a/man/org.texi Sat Dec 10 21:12:12 2005 +0000 +++ b/man/org.texi Sat Dec 10 21:18:28 2005 +0000 @@ -4,7 +4,7 @@ @setfilename ../info/org @settitle Org Mode Manual -@set VERSION 3.21 +@set VERSION 3.22 @set DATE December 2005 @dircategory Emacs @@ -125,7 +125,10 @@ Hyperlinks -* Links:: URL-like links to the world +* Internal Links:: CamelCaseWords as internal links +* External Links:: URL-like links to the world +* Managing links:: Creating, inserting and following +* Search Options:: Linking to a specific location * Remember:: Org-trees store quick notes TODO items @@ -247,15 +250,16 @@ If Org-mode is part of the Emacs distribution or an XEmacs package, you only need to copy the following lines to your @file{.emacs} file. -The last two lines define @emph{global} keys for the commands -@command{org-store-link} and @command{org-agenda} - please choose -suitable keys yourself. +The last three lines define @emph{global} keys for the commands +@command{org-store-link}, @command{org-agenda}, and +@code{org-todo-list} - please choose suitable keys yourself. @lisp ;; The following lines are always needed. Choose your own keys. (add-to-list 'auto-mode-alist '("\\.org$" . org-mode)) (define-key global-map "\C-cl" 'org-store-link) (define-key global-map "\C-ca" 'org-agenda) +(define-key global-map "\C-ct" 'org-todo-list) @end lisp If you have downloaded Org-mode from the Web, you must byte-compile @@ -268,6 +272,7 @@ (autoload 'org-mode "org" "Org mode" t) (autoload 'org-diary "org" "Diary entries from Org mode") (autoload 'org-agenda "org" "Multi-file agenda from Org mode" t) +(autoload 'org-todo-list "org" "Global TODO list from Org mode" t) (autoload 'org-store-link "org" "Store a link to the current location" t) (autoload 'orgtbl-mode "org" "Org tables as a minor mode" t) (autoload 'turn-on-orgtbl "org" "Org tables as a minor mode") @@ -561,7 +566,8 @@ match is in the body of an entry, headline and body are made visible. In order to provide minimal context, also the full hierarchy of headlines above the match is shown, as well as the headline following -the match. +the match. Each match is also highlighted, the highlights disappear +when the buffer is changed with an editing command. @end table Other commands are using this feature as well. For example @kbd{C-c @@ -583,9 +589,9 @@ @cindex plain lists @cindex lists, plain -Headlines define the entire structure of the Org-mode file, and also -lists (for example TODO items (@pxref{TODO items}) should be created -using headline levels. However, when taking notes, the plain text is +Headlines define the structure of the Org-mode file, and also lists +(for example TODO items (@pxref{TODO items}) should be created using +headline levels. However, when taking notes, the plain text is sometimes easier to read with hand-formatted lists. Org-mode supports editing such lists, and the HTML exporter (@pxref{Exporting}) does parse and format them. @@ -604,12 +610,12 @@ @example ** Lord of the Rings My favorite scenes are (in this order) -1. Eowyns fight with the witch-king +1. Eowyns fight with the witch king + this was already my favorite scene in the book + I really like Miranda Otto. 2. The attack of the Rohirrim 3. Peter Jackson being shot by Legolas - - on DVD only + - on DVD only He makes a really funny face when it happens. @end example @@ -619,6 +625,13 @@ with the bullet or number). @table @kbd +@kindex @key{TAB} +@item @key{TAB} +Items can be folded just like headline levels if you set the variable +@code{org-cycle-include-plain-lists}. The level of an item is then +given by the indentation of the bullet/number. However, items are +always subortinate to real headlines, the hierarchies remain +completely separated. @kindex M-S-@key{up} @kindex M-S-@key{down} @item M-S-@key{up} @@ -771,7 +784,7 @@ Sort the table lines in the region. Point and mark must be in the first and last line to be included, and must be in the column that should be used for sorting. The command prompts for numerical versus -alphnumerical sorting. +alphanumerical sorting. @tsubheading{Regions} @kindex C-c C-x M-w @@ -1053,7 +1066,7 @@ associated with them. @item _ Similar to @samp{^}, but defines names for the fields in the row -@emph{below}. +@emph{below}. @item $ Fields in this row can define @emph{parameters} for formulas. For example, if a field in a @samp{$} row contains @samp{max=50}, then @@ -1070,7 +1083,7 @@ Selects this line for global recalculation with @kbd{C-u C-c *}, but not for automatic recalculation. Use this when automatic recalculation slows down editing too much. -@item +@item Unmarked lines are exempted from recalculation with @kbd{C-u C-c *}. All lines that should be recalculated should be marked with @samp{#} or @samp{*}. @@ -1104,7 +1117,7 @@ @kindex C-c C-c You may edit the @samp{#+TBLFM} directly and re-apply the changed equations with @kbd{C-c C-c} in that line, or with the -normal recalculation commands in the table. +normal recalculation commands in the table. @kindex C-c ' @kindex C-c C-c @@ -1197,17 +1210,67 @@ @chapter Hyperlinks @cindex hyperlinks -Just like HMTL, Org-mode provides links to other files, Usenet -articles, emails and much more. +Just like HMTL, Org-mode provides links inside a file, and external +links to other files, Usenet articles, emails and much more. @menu -* Links:: URL-like links to the world +* Internal Links:: CamelCaseWords as internal links +* External Links:: URL-like links to the world +* Managing links:: Creating, inserting and following +* Search Options:: Linking to a specific location * Remember:: Org-trees store quick notes @end menu -@node Links, Remember, Hyperlinks, Hyperlinks -@section Links +@node Internal Links, External Links, Hyperlinks, Hyperlinks +@section Internal Links +@cindex internal links +@cindex links, internal +@cindex CamelCase links + +Similar to Wiki implementations, Org-mode interprets words spelled in +CamelCase (i.e. mixed case with at least one capital letter following +on a small letter inside the word) as links. While in Wiki +implementations these links usually point to another file, in Org-mode +they point to a target in the current file. Targets are CamelCased +words in double angular brackets, and may be located anywhere, also in +a comment line. For example +@example +# <<MyTarget>> +@end example + +Each occurence of @samp{MyTarget} in the file is an active link that +can be followed with @kbd{C-c C-o} or with a mouse click +(@pxref{Managing links}). If no dedicated target exists, org-mode will +search for the words in the link separated by white space, in the +above example for @samp{my target}. If the link starts with a star +like @samp{*MyTarget}, the search is restricted to headlines. +Org-mode will first try an exact match of a full headline, but then +move on to more and more lenient searches. The link @samp{*MyTargets} +will find any of the following +@example +** My targets +** TODO my targets are bright +** my 20 targets are +@end example +@cindex completion, of CamelCase links +@cindex CamelCase links, completion of +It is therefore often not even necessary to set a dedicated target. +The link will automatically find a target. If you want to see what +lines in the current buffer are matched by a given CamelCase link, +open the link with @kbd{C-u C-c C-o}. Even if there are several +matches, org-mode will usually find the right one since it tries +targets and exact matches first. To insert links targeting a +headline, in-buffer completion can be used. Just type a star followed +by a few optional letters into the buffer and press @kbd{M-@key{TAB}}. +CamelCased versions of all headlines in the current buffer will be +offered as completions. @xref{Managing links}, for more commands +creating links. + +@node External Links, Managing links, Internal Links, Hyperlinks +@section External Links @cindex links +@cindex external links +@cindex links, external @cindex GNUS links @cindex BBDB links @cindex URL links @@ -1227,7 +1290,6 @@ <http://www.astro.uva.nl/~dominik> @r{on the web} <file:/home/dominik/images/jupiter.jpg> @r{file, absolute path} <file:papers/last.pdf> @r{file, relative path} -<file:~/code/main.c:255> @r{file, with line number} <news:comp.emacs> @r{Usenet link} <mailto:adent@@galaxy.net> @r{Mail link} <vm:folder> @r{VM folder link} @@ -1249,18 +1311,29 @@ recommended to avoid problems with punctuation and other text following the link. See also the variable @code{org-allow-space-in-links}. -@cindex storing links + +@node Managing links, Search Options, External Links, Hyperlinks +@section Managing links + +Org-mode provides methods to create a link in the correct syntax, to +insert it into an org-mode file, and to follow the link. + @table @kbd @kindex C-c l +@cindex storing links @item C-c l Store a link to the current location. This is a @emph{global} command which can be used in any buffer to create a link. The link will be -stored for later insertion into an Org-mode buffer (see below). For VM, -RMAIL, WANDERLUST, GNUS and BBDB buffers, the link will point to the -current article/entry. For W3 and W3M buffer, the link goes to the -current URL. For any other files, the link will just point to the file. -The key binding @kbd{C-c l} is only a suggestion - see -@ref{Installation and Activation}. +stored for later insertion into an Org-mode buffer (see below). For +VM, RMAIL, WANDERLUST, GNUS and BBDB buffers, the link will point to +the current article/entry. For W3 and W3M buffer, the link goes to +the current URL. For Org-mode files, the current headline is +targeted. For any other files, the link will point to the file, with +a CamelCase (@pxref{Search Options}) search string pointing to the +contents of the current line. If there is an active region, the +selected words will form the basis of the search string. The key +binding @kbd{C-c l} is only a suggestion - see @ref{Installation and +Activation}. @kindex C-c C-l @cindex completion, of links @@ -1301,7 +1374,47 @@ Like @kbd{mouse-2}, but force file links to be opened with Emacs. @end table -@node Remember, , Links, Hyperlinks + +@node Search Options, Remember, Managing links, Hyperlinks +@section Search options in file links + +File links can contain additional information to make Emacs jump to a +particular location in the file when following a link. This can be a +line number or a search option after a double@footnote{For backward +compatibility, line numbers can also follow a single colon.} colon. +For example: +@example +<file:~/code/main.c::255> +<file:~/xx.org::MyTarget> +<file:~/xx.org::find me> +<file:~/xx.org::/regexp/> +@end example +@noindent Here is what these options do. + +@table @code +@item 255 +Jump to line 255. +@item MyGoal +Search for a link target with name MyGoal, or do a text search for +@samp{my target}, similar to the CamelCase search in internal links, +see @ref{Internal Links}. +@item find me +Do a normal text search for the text @samp{find me}. +@item /regexp/ +Do a regular expression search for @code{regexp}. This uses the Emacs +command @code{occur} to list all matches in a separate window. If the +target file is in Org-mode, @code{org-occur} is used to create a +sparse tree with the matches. +@c If the target file is a directory, +@c @code{grep} will be used to search all files in the directory. +@end table + +To use the search options also for a search in the current file, a +file link with an empty file name can be used. For example, +@code{<file:::find me>} does a search for @samp{find me} in the +current file. + +@node Remember, , Search Options, Hyperlinks @section Remember @cindex @file{remember.el} @@ -1314,7 +1427,7 @@ to file away notes either to a default file, or directly to the correct location in your Org-mode outline tree. The following customization@footnote{The two autoload forms are only necessary if -@file{org.el} is not part of the Emacs distribution or and XEmacs +@file{org.el} is not part of the Emacs distribution or an XEmacs package.} will tell @emph{Remember} to use org files as target, and to create annotations compatible with Org-mode links. @@ -1410,10 +1523,29 @@ @item C-c C-v View TODO items in a @emph{sparse tree} (@pxref{Sparse trees}). Folds the entire buffer, but shows all TODO items and the headings hierarchy -above them. With prefix arg, show also the DONE entries. +above them. With prefix arg, show also the DONE entries. With +numerical prefix N, show the tree for the Nth keyword in the variable +@code{org-todo-keywords}. +@kindex C-c t +@item C-c t +Show the global TODO list. This collects the TODO items from all +agenda files (@pxref{Agenda}) into a single buffer. The buffer is in +@code{agenda-mode}, so there are commands to examine and manipulate +the TODO entries directly from that buffer (@pxref{Agenda commands}). +A prefix argument can be used to collect only TODO entries of a +particular type. With a C-u prefix you are prompted for a keyword. +With a numeric prefix, the Nth keyword in @code{org-todo-keywords} is +selected. +@kindex r +The @kbd{r} key in the agenda +buffer regenerates it, and you can give a prefix argument to this +command to change the selected TODO keyword, for example @kbd{3 r}. +The key binding @kbd{C-c t} is only a suggestion - see +@ref{Installation and Activation}. +@kindex C-u C-c a @item C-u C-c a A @kbd{C-u} argument to the @code{org-agenda command} (@pxref{Agenda}) -collects all unfinished TODO items into a single place. +includes all unfinished TODO items at the beginning of todays agenda. @end table @node TODO extensions, Priorities, TODO basics, TODO items @@ -1463,10 +1595,12 @@ The second possibility is to use TODO keywords to indicate different types of action items. For example, you might want to indicate that -items are for ``work'' or ``home''. Or, when you work with several -people on a single project, you might want to assign action items -directly to persons, by using their names as TODO keywords. This -would be set up like this: +items are for ``work'' or ``home''. If you are into David Allen's +@emph{Getting Things DONE}, you might want to use todo types +@samp{NEXTACTION}, @samp{WAITING}, @samp{MAYBE}. Or, when you work +with several people on a single project, you might want to assign +action items directly to persons, by using their names as TODO +keywords. This would be set up like this: @lisp (setq org-todo-keywords '("Fred" "Sara" "Lucy" "Mike" "DONE") @@ -1479,10 +1613,15 @@ command @kbd{C-c C-t} is changed slightly@footnote{This is also true for the @kbd{t} command in the timeline and agenda buffers.}. When used several times in succession, it will still cycle through all -names. But when you return to the item after some time and -execute @kbd{C-c C-t} again, it will switch from each name directly to -DONE. Use prefix arguments or completion to quickly select a specific -name. +names. But when you return to the item after some time and execute +@kbd{C-c C-t} again, it will switch from each name directly to DONE. +Use prefix arguments or completion to quickly select a specific name. +You can also review the items of a specific TODO type in a sparse tree +by using a numeric prefix to @kbd{C-c C-v}. For example, to see all +things Lucy has to do, you would use @kbd{C-3 C-c C-v}. To collect +collect Lucy's items from all agenda files into a single buffer, you +would use the prefix arg as well when creating the global todo list: +@kbd{C-3 C-c t}. @node Per file keywords, , TODO types, TODO extensions @subsection Setting up TODO keywords for individual files @@ -1566,8 +1705,6 @@ (@pxref{Interaction}). @end table - - @node Timestamps, Timeline and Agenda, TODO items, Top @chapter Timestamps @@ -1659,7 +1796,7 @@ @kindex C-c ! @item C-c ! Like @kbd{C-c .}, but insert an inactive time stamp not triggering the -agenda. +agenda. @kindex C-c < @item C-c < @@ -1879,14 +2016,9 @@ @example #+CATEGORY: Thesis @end example -@noindent -After changing this line, press @kbd{C-c C-c} with the cursor still in -the line, to make the changes known to org-mode. Otherwise, the -change will only be active the next time you visit this file with -Emacs. - -The display in the agenda buffer looks best if the category is not -longer than 10 characters. +If there are several such lines in a file, each specifies the category +for the text below it. The display in the agenda buffer looks best if +the category is not longer than 10 characters. @subsection Time-of-Day Specifications @@ -2028,7 +2160,9 @@ @item r Recreate the agenda buffer, for example to reflect the changes after modification of the time stamps of items with S-@key{left} and -S-@key{right}. +S-@key{right}. When the buffer is the global todo list, a prefix +argument is interpreted to create a selective list for a specific TODO +keyword. @kindex @key{right} @item @key{right} @@ -2275,7 +2409,7 @@ @end example @noindent creates only top level headlines and does the rest as items. Lines -starting with @samp{#} and subtree starting with the word @samp{COMMENT} +starting with @samp{#} and subtrees starting with the word @samp{COMMENT} will not be exported. @node HTML export, iCalendar export, ASCII export, Exporting @@ -2436,7 +2570,7 @@ @example * COMMENT HTML style specifications -# Local Variables: +# Local Variables: # org-export-html-style: " <style type=\"text/css\"> p @{font-weight: normal; color: gray; @} h1 @{color: black; @} @@ -2491,10 +2625,10 @@ @code{org-combined-agenda-icalendar-file}. @end table -How this calendar is best read and updated, depends on the on the -application you are using. For example, when using iCal under Apple -MacOS X, you could create a new calendar @samp{OrgMode} (the default -name for the calendar created by @kbd{C-c C-x c}, see the variables +How this calendar is best read and updated, depends on the application +you are using. For example, when using iCal under Apple MacOS X, you +could create a new calendar @samp{OrgMode} (the default name for the +calendar created by @kbd{C-c C-x c}, see the variables @code{org-icalendar-combined-name} and @code{org-combined-agenda-icalendar-file}). Then set Org-mode to overwrite the corresponding file @@ -2530,6 +2664,7 @@ @cindex completion, of TODO keywords @cindex completion, of dictionary words @cindex completion, of option keywords +@cindex completion, of CamelCase links Org-mode supports in-buffer completion. This type of completion does not make use of the minibuffer. You simply type a few letters into @@ -2545,6 +2680,9 @@ @item After @samp{\}, complete @TeX{} symbols supported by the exporter. @item +After @samp{*}, complete CamelCase versions of all headlines in the +buffer. +@item After @samp{#+}, complete the special keywords like @samp{TYP_TODO} or @samp{OPTIONS} which set file-specific options for Org-mode. When the option keyword is already complete, pressing @kbd{M-@key{TAB}} again @@ -2854,9 +2992,14 @@ @item Kai Grossjohann pointed out that a number of key bindings in Org-mode conflict with other packages. -@item +@item Roland Winkler pointed out that additional keybindings are needed to use Org-mode on a tty. +@item +Tim O'Callaghan suggested in-file links, and search options for +general file links. +@c @item +@c Nic Ferrier and Christian Egli implemented XML export. @end itemize @node Index, Key Index, Miscellaneous, Top
--- a/src/ChangeLog Sat Dec 10 21:12:12 2005 +0000 +++ b/src/ChangeLog Sat Dec 10 21:18:28 2005 +0000 @@ -1,3 +1,66 @@ +2005-12-07 L$,1 q(Brentey K,Aa(Broly <lorentey@elte.hu> + + * xfns.c (Fx_create_frame): Initialize Vdefault_minibuffer_frame, + when needed. + +2005-12-06 Stefan Monnier <monnier@iro.umontreal.ca> + + * minibuf.c (keys_of_minibuf): Just unbind SPC in + Vminibuffer_local_filename_completion_map rather than forcing it + explicitly to the same binding as the global map. + +2005-12-06 Ken Raeburn <raeburn@gnu.org> + + * buffer.c (Fkill_buffer): Avoid dangerous side effects in NILP + argument. + * bytecode.c (Fbyte_code): Likewise. + * fileio.c (internal_delete_file, Fread_file_name_internal): + Likewise. + * minibuf.c (Fminibuffer_complete_and_exit): Likewise. + * undo.c (truncate_undo_list): Likewise. + +2005-12-05 Richard M. Stallman <rms@gnu.org> + + * window.c (enlarge_window): Eliminate arg preserve_before. + Assume it is 0. All callers changed. + (Fenlarge_window, Fshrink_window): Likewise. + +2005-12-02 Eli Zaretskii <eliz@gnu.org> + + * w32fns.c (compute_tip_xy): Put tip above pointer if it doesn't + fit below. + +2005-12-02 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> + + * xterm.h: Add prototype for xg_set_icon_from_xpm_data. + + * xfns.c (x_real_positions): int ign => unsigned int. + (xg_set_icon_from_xpm_data): Remove unused variable err. + (x_set_name_internal, Fx_create_frame, xg_set_icon): Add cast + to remove compiler warning. + (compute_tip_xy): Put tip above pointer if it doesn't fit below. + +2005-12-02 David Reitter <david.reitter@gmail.com> + + * minibuf.c (Fcompleting_read): If Vminibuffer_completing_file_name is + non-nil, use the new keymaps Vminibuffer_local_filename_completion_map + and Vminibuffer_local_must_match_filename_map keymaps. + (keys_of_minibuf): Bind SPC in the new file-name completion keymaps. + + * keymap.c (Vminibuffer_local_filename_completion_map) + (Vminibuffer_local_must_match_filename_map): New variables. + (syms_of_keymap): DEFVAR_LISP them, initialize them, and set their + parent to be Vminibuffer_local_completion_map and + Vminibuffer_local_must_match_map, respectively. + + * commands.h (Vminibuffer_local_filename_completion_map) + (Vminibuffer_local_must_match_filename_map): Declare the new keymaps. + +2005-12-01 Stefan Monnier <monnier@iro.umontreal.ca> + + * window.c (Fset_window_configuration): Don't accidentally copy the + window-point of one window to another. + 2005-11-30 L$,1 q(Brentey K,Aa(Broly <lorentey@elte.hu> * buffer.c (Fpop_to_buffer): Remove superfluous call to record_buffer. @@ -55,7 +118,7 @@ * macterm.h (cfstring_to_lisp_nodecode) [TARGET_API_MAC_CARBON]: Add prototype. -2005-11-21 Ken Raeburn <raeburn@mit.edu> +2005-11-21 Ken Raeburn <raeburn@gnu.org> * keymap.c (shadow_lookup): Use make_number to pass a number to Fsubstring. @@ -16289,7 +16352,7 @@ * xdisp.c (forward_to_next_line_start): Return 0 when reaching the end of the buffer. -2002-08-08 Ken Raeburn <raeburn@mit.edu> +2002-08-08 Ken Raeburn <raeburn@gnu.org> * coding.c (Ffind_operation_coding_system): Fix Lisp_Object/int mixup.
--- a/src/buffer.c Sat Dec 10 21:12:12 2005 +0000 +++ b/src/buffer.c Sat Dec 10 21:18:28 2005 +0000 @@ -1359,7 +1359,8 @@ /* First run the query functions; if any query is answered no, don't kill the buffer. */ arglist[0] = Qkill_buffer_query_functions; - if (NILP (Frun_hook_with_args_until_failure (1, arglist))) + tem = Frun_hook_with_args_until_failure (1, arglist); + if (NILP (tem)) return unbind_to (count, Qnil); /* Then run the hooks. */
--- a/src/bytecode.c Sat Dec 10 21:12:12 2005 +0000 +++ b/src/bytecode.c Sat Dec 10 21:18:28 2005 +0000 @@ -524,15 +524,19 @@ } case Bgotoifnil: - MAYBE_GC (); - op = FETCH2; - if (NILP (POP)) - { - BYTE_CODE_QUIT; - CHECK_RANGE (op); - stack.pc = stack.byte_string_start + op; - } - break; + { + Lisp_Object v1; + MAYBE_GC (); + op = FETCH2; + v1 = POP; + if (NILP (v1)) + { + BYTE_CODE_QUIT; + CHECK_RANGE (op); + stack.pc = stack.byte_string_start + op; + } + break; + } case Bcar: { @@ -730,15 +734,19 @@ break; case Bgotoifnonnil: - MAYBE_GC (); - op = FETCH2; - if (!NILP (POP)) - { - BYTE_CODE_QUIT; - CHECK_RANGE (op); - stack.pc = stack.byte_string_start + op; - } - break; + { + Lisp_Object v1; + MAYBE_GC (); + op = FETCH2; + v1 = POP; + if (!NILP (v1)) + { + BYTE_CODE_QUIT; + CHECK_RANGE (op); + stack.pc = stack.byte_string_start + op; + } + break; + } case Bgotoifnilelsepop: MAYBE_GC (); @@ -771,24 +779,32 @@ break; case BRgotoifnil: - MAYBE_GC (); - if (NILP (POP)) - { - BYTE_CODE_QUIT; - stack.pc += (int) *stack.pc - 128; - } - stack.pc++; - break; + { + Lisp_Object v1; + MAYBE_GC (); + v1 = POP; + if (NILP (v1)) + { + BYTE_CODE_QUIT; + stack.pc += (int) *stack.pc - 128; + } + stack.pc++; + break; + } case BRgotoifnonnil: - MAYBE_GC (); - if (!NILP (POP)) - { - BYTE_CODE_QUIT; - stack.pc += (int) *stack.pc - 128; - } - stack.pc++; - break; + { + Lisp_Object v1; + MAYBE_GC (); + v1 = POP; + if (!NILP (v1)) + { + BYTE_CODE_QUIT; + stack.pc += (int) *stack.pc - 128; + } + stack.pc++; + break; + } case BRgotoifnilelsepop: MAYBE_GC ();
--- a/src/commands.h Sat Dec 10 21:12:12 2005 +0000 +++ b/src/commands.h Sat Dec 10 21:18:28 2005 +0000 @@ -37,9 +37,16 @@ /* keymap used for minibuffers when doing completion */ extern Lisp_Object Vminibuffer_local_completion_map; +/* keymap used for minibuffers when doing completion in filenames*/ +extern Lisp_Object Vminibuffer_local_filename_completion_map; + /* keymap used for minibuffers when doing completion and require a match */ extern Lisp_Object Vminibuffer_local_must_match_map; +/* keymap used for minibuffers when doing completion in filenames + and require a match */ +extern Lisp_Object Vminibuffer_local_must_match_filename_map; + /* Last character of last key sequence. */ extern Lisp_Object last_command_char;
--- a/src/fileio.c Sat Dec 10 21:12:12 2005 +0000 +++ b/src/fileio.c Sat Dec 10 21:18:28 2005 +0000 @@ -2732,8 +2732,10 @@ internal_delete_file (filename) Lisp_Object filename; { - return NILP (internal_condition_case_1 (Fdelete_file, filename, - Qt, internal_delete_file_1)); + Lisp_Object tem; + tem = internal_condition_case_1 (Fdelete_file, filename, + Qt, internal_delete_file_1); + return NILP (tem); } DEFUN ("rename-file", Frename_file, Srename_file, 2, 3, @@ -6236,13 +6238,17 @@ #endif { /* Must do it the hard (and slow) way. */ + Lisp_Object tem; GCPRO3 (all, comp, specdir); count = SPECPDL_INDEX (); record_unwind_protect (read_file_name_cleanup, current_buffer->directory); current_buffer->directory = realdir; for (comp = Qnil; CONSP (all); all = XCDR (all)) - if (!NILP (call1 (Vread_file_name_predicate, XCAR (all)))) - comp = Fcons (XCAR (all), comp); + { + tem = call1 (Vread_file_name_predicate, XCAR (all)); + if (!NILP (tem)) + comp = Fcons (XCAR (all), comp); + } unbind_to (count, Qnil); UNGCPRO; }
--- a/src/keymap.c Sat Dec 10 21:12:12 2005 +0000 +++ b/src/keymap.c Sat Dec 10 21:18:28 2005 +0000 @@ -66,6 +66,13 @@ /* was MinibufLocalCompletionMap */ Lisp_Object Vminibuffer_local_completion_map; +/* keymap used for minibuffers when doing completion in filenames */ +Lisp_Object Vminibuffer_local_filename_completion_map; + +/* keymap used for minibuffers when doing completion in filenames + with require-match*/ +Lisp_Object Vminibuffer_local_must_match_filename_map; + /* keymap used for minibuffers when doing completion and require a match */ /* was MinibufLocalMustMatchMap */ Lisp_Object Vminibuffer_local_must_match_map; @@ -3775,12 +3782,27 @@ Vminibuffer_local_completion_map = Fmake_sparse_keymap (Qnil); Fset_keymap_parent (Vminibuffer_local_completion_map, Vminibuffer_local_map); + DEFVAR_LISP ("minibuffer-local-filename-completion-map", + &Vminibuffer_local_filename_completion_map, + doc: /* Local keymap for minibuffer input with completion for filenames. */); + Vminibuffer_local_filename_completion_map = Fmake_sparse_keymap (Qnil); + Fset_keymap_parent (Vminibuffer_local_filename_completion_map, + Vminibuffer_local_completion_map); + + DEFVAR_LISP ("minibuffer-local-must-match-map", &Vminibuffer_local_must_match_map, doc: /* Local keymap for minibuffer input with completion, for exact match. */); Vminibuffer_local_must_match_map = Fmake_sparse_keymap (Qnil); Fset_keymap_parent (Vminibuffer_local_must_match_map, Vminibuffer_local_completion_map); + DEFVAR_LISP ("minibuffer-local-must-match-filename-map", + &Vminibuffer_local_must_match_filename_map, + doc: /* Local keymap for minibuffer input with completion for filenames with exact match. */); + Vminibuffer_local_must_match_filename_map = Fmake_sparse_keymap (Qnil); + Fset_keymap_parent (Vminibuffer_local_must_match_filename_map, + Vminibuffer_local_must_match_map); + DEFVAR_LISP ("minor-mode-map-alist", &Vminor_mode_map_alist, doc: /* Alist of keymaps to use for minor modes. Each element looks like (VARIABLE . KEYMAP); KEYMAP is used to read
--- a/src/minibuf.c Sat Dec 10 21:12:12 2005 +0000 +++ b/src/minibuf.c Sat Dec 10 21:18:28 2005 +0000 @@ -1753,8 +1753,12 @@ XSETFASTINT (histpos, 0); val = read_minibuf (NILP (require_match) - ? Vminibuffer_local_completion_map - : Vminibuffer_local_must_match_map, + ? (NILP (Vminibuffer_completing_file_name) + ? Vminibuffer_local_completion_map + : Vminibuffer_local_filename_completion_map) + : (NILP (Vminibuffer_completing_file_name) + ? Vminibuffer_local_must_match_map + : Vminibuffer_local_must_match_filename_map), init, prompt, make_number (pos), 0, histvar, histpos, def, 0, !NILP (inherit_input_method), 0); @@ -2118,16 +2122,17 @@ () { register int i; - Lisp_Object val; + Lisp_Object val, tem; /* Allow user to specify null string */ if (XINT (Fminibuffer_prompt_end ()) == ZV) goto exit; val = Fminibuffer_contents (); - if (!NILP (Ftest_completion (val, - Vminibuffer_completion_table, - Vminibuffer_completion_predicate))) + tem = Ftest_completion (val, + Vminibuffer_completion_table, + Vminibuffer_completion_predicate); + if (!NILP (tem)) { if (completion_ignore_case) { /* Fixup case of the field, if necessary. */ @@ -2927,10 +2932,16 @@ initial_define_key (Vminibuffer_local_completion_map, '?', "minibuffer-completion-help"); + Fdefine_key (Vminibuffer_local_filename_completion_map, + build_string (" "), Qnil); + initial_define_key (Vminibuffer_local_must_match_map, Ctl ('m'), "minibuffer-complete-and-exit"); initial_define_key (Vminibuffer_local_must_match_map, Ctl ('j'), "minibuffer-complete-and-exit"); + + initial_define_key (Vminibuffer_local_must_match_filename_map, ' ', + "self-insert-command"); } /* arch-tag: 8f69b601-fba3-484c-a6dd-ceaee54a7a73
--- a/src/undo.c Sat Dec 10 21:12:12 2005 +0000 +++ b/src/undo.c Sat Dec 10 21:18:28 2005 +0000 @@ -378,11 +378,11 @@ && size_so_far > XINT (Vundo_outer_limit) && !NILP (Vundo_outer_limit_function)) { - Lisp_Object temp = last_undo_buffer; + Lisp_Object temp = last_undo_buffer, tem; /* Normally the function this calls is undo-outer-limit-truncate. */ - if (! NILP (call1 (Vundo_outer_limit_function, - make_number (size_so_far)))) + tem = call1 (Vundo_outer_limit_function, make_number (size_so_far)); + if (! NILP (tem)) { /* The function is responsible for making any desired changes in buffer-undo-list. */
--- a/src/w32fns.c Sat Dec 10 21:12:12 2005 +0000 +++ b/src/w32fns.c Sat Dec 10 21:18:28 2005 +0000 @@ -7413,6 +7413,9 @@ *root_y = XINT (top); else if (*root_y + XINT (dy) - height < 0) *root_y -= XINT (dy); + /* If there's not enough place below the pointer, put tip above it. */ + else if (*root_y + XINT (dy) >= FRAME_W32_DISPLAY_INFO (f)->height) + *root_y -= XINT (dy); else { *root_y -= height;
--- a/src/window.c Sat Dec 10 21:12:12 2005 +0000 +++ b/src/window.c Sat Dec 10 21:18:28 2005 +0000 @@ -67,7 +67,7 @@ static void size_window P_ ((Lisp_Object, int, int, int)); static int freeze_window_start P_ ((struct window *, void *)); static int window_fixed_size_p P_ ((struct window *, int, int)); -static void enlarge_window P_ ((Lisp_Object, int, int, int)); +static void enlarge_window P_ ((Lisp_Object, int, int)); static Lisp_Object window_list P_ ((void)); static int add_window_to_list P_ ((struct window *, void *)); static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object, @@ -1971,7 +1971,7 @@ GCPRO1 (windows); best_window = Qnil; - for (; CONSP (windows); windows = CDR (windows)) + for (; CONSP (windows); windows = XCDR (windows)) { struct window *w; @@ -3592,7 +3592,7 @@ + XFASTINT (XWINDOW (window)->total_lines)); enlarge_window (upper, total / 2 - XFASTINT (XWINDOW (upper)->total_lines), - 0, 0); + 0); } } } @@ -3669,7 +3669,7 @@ #endif set_buffer_internal (old); - if (!EQ (Vtemp_buffer_show_function, Qnil)) + if (!NILP (Vtemp_buffer_show_function)) call1 (Vtemp_buffer_show_function, buf); else { @@ -3883,21 +3883,18 @@ return new; } -DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 3, "p", +DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p", doc: /* Make current window ARG lines bigger. From program, optional second arg non-nil means grow sideways ARG columns. Interactively, if an argument is not given, make the window one line bigger. If HORIZONTAL is non-nil, enlarge horizontally instead of vertically. - -Optional third arg PRESERVE-BEFORE, if non-nil, means do not change the size -of the siblings above or to the left of the selected window. Only -siblings to the right or below are changed. */) - (arg, horizontal, preserve_before) - register Lisp_Object arg, horizontal, preserve_before; +This function can delete windows, even the second window, if they get +too small. */) + (arg, horizontal) + Lisp_Object arg, horizontal; { CHECK_NUMBER (arg); - enlarge_window (selected_window, XINT (arg), !NILP (horizontal), - !NILP (preserve_before)); + enlarge_window (selected_window, XINT (arg), !NILP (horizontal)); if (! NILP (Vwindow_configuration_change_hook)) call1 (Vrun_hooks, Qwindow_configuration_change_hook); @@ -3905,20 +3902,16 @@ return Qnil; } -DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 3, "p", +DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p", doc: /* Make current window ARG lines smaller. From program, optional second arg non-nil means shrink sideways arg columns. -Interactively, if an argument is not given, make the window one line smaller. - -Optional third arg PRESERVE-BEFORE, if non-nil, means do not change the size -of the siblings above or to the left of the selected window. Only +Interactively, if an argument is not given, make the window one line smaller. Only siblings to the right or below are changed. */) - (arg, side, preserve_before) - register Lisp_Object arg, side, preserve_before; + (arg, side) + Lisp_Object arg, side; { CHECK_NUMBER (arg); - enlarge_window (selected_window, -XINT (arg), !NILP (side), - !NILP (preserve_before)); + enlarge_window (selected_window, -XINT (arg), !NILP (side)); if (! NILP (Vwindow_configuration_change_hook)) call1 (Vrun_hooks, Qwindow_configuration_change_hook); @@ -3956,15 +3949,12 @@ Siblings of the selected window are resized to fulfill the size request. If they become too small in the process, they will be - deleted. - - If PRESERVE_BEFORE is nonzero, that means don't alter - the siblings to the left or above WINDOW. */ + deleted. */ static void -enlarge_window (window, delta, horiz_flag, preserve_before) +enlarge_window (window, delta, horiz_flag) Lisp_Object window; - int delta, horiz_flag, preserve_before; + int delta, horiz_flag; { Lisp_Object parent, next, prev; struct window *p; @@ -4011,33 +4001,18 @@ /* Compute the maximum size increment this window can have. */ - if (preserve_before) - { - if (!NILP (parent)) - { - maxdelta = (*sizefun) (parent) - XINT (*sizep); - /* Subtract size of siblings before, since we can't take that. */ - maxdelta -= XINT (CURBEG (window)) - XINT (CURBEG (parent)); - } - else - maxdelta = (!NILP (p->next) ? ((*sizefun) (p->next) - - window_min_size (XWINDOW (p->next), - horiz_flag, 0, 0)) - : (delta = 0)); - } - else - maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep) - /* This is a main window followed by a minibuffer. */ - : !NILP (p->next) ? ((*sizefun) (p->next) - - window_min_size (XWINDOW (p->next), - horiz_flag, 0, 0)) - /* This is a minibuffer following a main window. */ - : !NILP (p->prev) ? ((*sizefun) (p->prev) - - window_min_size (XWINDOW (p->prev), - horiz_flag, 0, 0)) - /* This is a frame with only one window, a minibuffer-only - or a minibufferless frame. */ - : (delta = 0)); + maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep) + /* This is a main window followed by a minibuffer. */ + : !NILP (p->next) ? ((*sizefun) (p->next) + - window_min_size (XWINDOW (p->next), + horiz_flag, 0, 0)) + /* This is a minibuffer following a main window. */ + : !NILP (p->prev) ? ((*sizefun) (p->prev) + - window_min_size (XWINDOW (p->prev), + horiz_flag, 0, 0)) + /* This is a frame with only one window, a minibuffer-only + or a minibufferless frame. */ + : (delta = 0)); if (delta > maxdelta) /* This case traps trying to make the minibuffer @@ -4060,10 +4035,9 @@ for (next = p->next; ! NILP (next); next = XWINDOW (next)->next) maximum += (*sizefun) (next) - window_min_size (XWINDOW (next), horiz_flag, 0, 0); - if (! preserve_before) - for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev) - maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev), - horiz_flag, 0, 0); + for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev) + maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev), + horiz_flag, 0, 0); /* If we can get it all from them without deleting them, do so. */ if (delta <= maximum) @@ -4079,7 +4053,7 @@ moving away from this window in both directions alternately, and take as much as we can get without deleting that sibling. */ while (delta != 0 - && (!NILP (next) || (!preserve_before && !NILP (prev)))) + && (!NILP (next) || !NILP (prev))) { if (! NILP (next)) { @@ -4103,7 +4077,7 @@ if (delta == 0) break; - if (!preserve_before && ! NILP (prev)) + if (! NILP (prev)) { int this_one = ((*sizefun) (prev) - window_min_size (XWINDOW (prev), @@ -4352,7 +4326,7 @@ DEFUN ("adjust-window-trailing-edge", Fadjust_window_trailing_edge, Sadjust_window_trailing_edge, 3, 3, 0, doc: /* Adjust the bottom or right edge of WINDOW by DELTA. -If HORIZ_FLAG is t, that means adjust the width, moving the right edge. +If HORIZONTAL is non-nil, that means adjust the width, moving the right edge. Otherwise, adjust the height, moving the bottom edge. Following siblings of the selected window are resized to fulfill @@ -4604,7 +4578,7 @@ among the other windows. */ Lisp_Object window; XSETWINDOW (window, w); - enlarge_window (window, 1 - XFASTINT (w->total_lines), 0, 0); + enlarge_window (window, 1 - XFASTINT (w->total_lines), 0); } } @@ -5833,7 +5807,23 @@ else { if (XBUFFER (new_current_buffer) == current_buffer) - old_point = PT; + /* The code further down "preserves point" by saving here PT in + old_point and then setting it later back into PT. When the + current-selected-window and the final-selected-window both show + the current buffer, this suffers from the problem that the + current PT is the window-point of the current-selected-window, + while the final PT is the point of the final-selected-window, so + this copy from one PT to the other would end up moving the + window-point of the final-selected-window to the window-point of + the current-selected-window. So we have to be careful which + point of the current-buffer we copy into old_point. */ + if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer) + && WINDOWP (selected_window) + && EQ (XWINDOW (selected_window)->buffer, new_current_buffer) + && !EQ (selected_window, data->current_window)) + old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos; + else + old_point = PT; else /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of point in new_current_buffer as of the last time this buffer was
--- a/src/xfns.c Sat Dec 10 21:12:12 2005 +0000 +++ b/src/xfns.c Sat Dec 10 21:18:28 2005 +0000 @@ -619,7 +619,7 @@ if (! had_errors) { - int ign; + unsigned int ign; Window child, rootw; /* Get the real coordinates for the WM window upper left corner */ @@ -805,9 +805,7 @@ { GdkPixbuf *pixbuf; GError *err = NULL; - char *filename; - - filename = SDATA (found); + char *filename = (char *) SDATA (found); BLOCK_INPUT; pixbuf = gdk_pixbuf_new_from_file (filename, &err); @@ -836,17 +834,12 @@ char **data; { int result = 0; - GError *err = NULL; - GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data (data); + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **) data); if (!pixbuf) - { - g_error_free (err); - return 0; - } - - gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - pixbuf); + return 0; + + gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf); g_object_unref (pixbuf); return 1; } @@ -1658,7 +1651,7 @@ #ifdef USE_GTK gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - SDATA (ENCODE_UTF_8 (name))); + (char *) SDATA (ENCODE_UTF_8 (name))); #else /* not USE_GTK */ XSetWMName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text); #endif /* not USE_GTK */ @@ -3393,10 +3386,17 @@ FRAME_OUTER_WINDOW (f), dpyinfo->Xatom_wm_client_leader, XA_WINDOW, 32, PropModeReplace, - (char *) &dpyinfo->client_leader_window, 1); + (unsigned char *) &dpyinfo->client_leader_window, 1); UNBLOCK_INPUT; } + /* Initialize `default-minibuffer-frame' in case this is the first + frame on this display device. */ + if (FRAME_HAS_MINIBUF_P (f) + && (!FRAMEP (kb->Vdefault_minibuffer_frame) + || !FRAME_LIVE_P (XFRAME (kb->Vdefault_minibuffer_frame)))) + kb->Vdefault_minibuffer_frame = frame; + UNGCPRO; /* Make sure windows on this frame appear in calls to next-window @@ -4944,6 +4944,9 @@ *root_y = XINT (top); else if (*root_y + XINT (dy) - height < 0) *root_y -= XINT (dy); + else if (*root_y + XINT (dy) >= FRAME_X_DISPLAY_INFO (f)->height) + /* Put tip above the pointer. */ + *root_y -= XINT (dy); else { *root_y -= height;
--- a/src/xterm.h Sat Dec 10 21:12:12 2005 +0000 +++ b/src/xterm.h Sat Dec 10 21:18:28 2005 +0000 @@ -1036,6 +1036,7 @@ #ifdef USE_GTK extern int xg_set_icon P_ ((struct frame *, Lisp_Object)); +extern int xg_set_icon_from_xpm_data P_ ((struct frame *, char**)); #endif /* USE_GTK */ extern void x_real_positions P_ ((struct frame *, int *, int *));