Now on revision 105479. ------------------------------------------------------------ revno: 105479 fixes bug(s): http://debbugs.gnu.org/9311 committer: Eli Zaretskii branch nick: trunk timestamp: Wed 2011-08-17 11:50:08 +0300 message: Fix bug #9311 with loading on MS-Windows .elc files in root directories. src/lread.c (Fload) [DOS_NT]: If `openp' returns -2, but the file has no `load' handler, try opening the file locally. diff: === modified file 'src/ChangeLog' --- src/ChangeLog 2011-08-16 20:31:32 +0000 +++ src/ChangeLog 2011-08-17 08:50:08 +0000 @@ -1,3 +1,8 @@ +2011-08-17 Eli Zaretskii + + * lread.c (Fload) [DOS_NT]: If `openp' returns -2, but the file + has no `load' handler, try opening the file locally. (Bug#9311) + 2011-08-16 Ken Brown * gmalloc.c: Expand comment. === modified file 'src/lread.c' --- src/lread.c 2011-07-28 20:23:19 +0000 +++ src/lread.c 2011-08-17 08:50:08 +0000 @@ -1124,6 +1124,22 @@ handler = Ffind_file_name_handler (found, Qload); if (! NILP (handler)) return call5 (handler, Qload, found, noerror, nomessage, Qt); +#ifdef DOS_NT + /* Tramp has to deal with semi-broken packages that prepend + drive letters to remote files. For that reason, Tramp + catches file operations that test for file existence, which + makes openp think X:/foo.elc files are remote. However, + Tramp does not catch `load' operations for such files, so we + end up with a nil as the `load' handler above. If we would + continue with fd = -2, we will behave wrongly, and in + particular try reading a .elc file in the "rt" mode instead + of "rb". See bug #9311 for the results. To work around + this, we try to open the file locally, and go with that if it + succeeds. */ + fd = emacs_open (SSDATA (ENCODE_FILE (found)), O_RDONLY, 0); + if (fd == -1) + fd = -2; +#endif } /* Check if we're stuck in a recursive load cycle. @@ -1247,9 +1263,17 @@ GCPRO3 (file, found, hist_file_name); #ifdef WINDOWSNT - emacs_close (fd); efound = ENCODE_FILE (found); - stream = fopen (SSDATA (efound), fmode); + /* If we somehow got here with fd == -2, meaning the file is deemed + to be remote, don't even try to reopen the file locally; just + force a failure instead. */ + if (fd >= 0) + { + emacs_close (fd); + stream = fopen (SSDATA (efound), fmode); + } + else + stream = NULL; #else /* not WINDOWSNT */ stream = fdopen (fd, fmode); #endif /* not WINDOWSNT */ ------------------------------------------------------------ revno: 105478 committer: martin rudalics branch nick: trunk timestamp: Wed 2011-08-17 08:50:31 +0200 message: In display-buffer-pop-up-frame make frame with buffer to display current. * window.el (display-buffer-pop-up-frame): Run frame creation function with BUFFER current (as special-display-popup-frame does). Reported by Drew Adams. diff: === modified file 'lisp/ChangeLog' --- lisp/ChangeLog 2011-08-17 01:31:05 +0000 +++ lisp/ChangeLog 2011-08-17 06:50:31 +0000 @@ -1,3 +1,9 @@ +2011-08-17 Martin Rudalics + + * window.el (display-buffer-pop-up-frame): Run frame creation + function with BUFFER current (as special-display-popup-frame + does). Reported by Drew Adams. + 2011-08-17 Daiki Ueno * epa-mail.el: Simplify GnuPG group expansion using === modified file 'lisp/window.el' --- lisp/window.el 2011-08-14 05:11:36 +0000 +++ lisp/window.el 2011-08-17 06:50:31 +0000 @@ -5087,9 +5087,10 @@ (when (symbolp function) (cdr (assq 'pop-up-frame-alist specifiers)))) (frame - (if (symbolp function) - (funcall function parameters) - (funcall function)))) + (with-current-buffer buffer + (if (symbolp function) + (funcall function parameters) + (funcall function))))) (when frame (let ((window (frame-selected-window frame))) (set-window-parameter ------------------------------------------------------------ revno: 105477 committer: Daiki Ueno branch nick: trunk timestamp: Wed 2011-08-17 10:31:05 +0900 message: Simplify GnuPG group expansion using epg-expand-group. * epa-mail.el: Simplify GnuPG group expansion using epg-expand-group. (epa-mail-group-alist, epa-mail-group-modtime) (epa-mail-gnupg-conf-file, epa-mail-parse-groups) (epa-mail-sync-groups, epa-mail-expand-recipient-1) (epa-mail-expand-recipients-2, epa-mail-expand-recipients): Remove. diff: === modified file 'lisp/ChangeLog' --- lisp/ChangeLog 2011-08-16 22:33:57 +0000 +++ lisp/ChangeLog 2011-08-17 01:31:05 +0000 @@ -1,3 +1,13 @@ +2011-08-17 Daiki Ueno + + * epa-mail.el: Simplify GnuPG group expansion using + epg-expand-group. + (epa-mail-group-alist, epa-mail-group-modtime) + (epa-mail-gnupg-conf-file, epa-mail-parse-groups) + (epa-mail-sync-groups, epa-mail-expand-recipient-1) + (epa-mail-expand-recipients-2, epa-mail-expand-recipients): + Remove. + 2011-08-16 Feng Li (tiny change) * calc/calc-ext.el (math-defintegral-2): Remove nested backquote. === modified file 'lisp/epa-mail.el' --- lisp/epa-mail.el 2011-08-16 04:04:27 +0000 +++ lisp/epa-mail.el 2011-08-17 01:31:05 +0000 @@ -50,11 +50,9 @@ "A minor-mode for composing encrypted/clearsigned mails." nil " epa-mail" epa-mail-mode-map) -;;; ??? Could someone please clarify this doc string? -;;; In particular, what does USAGE look like -;;; and what does it mean? -- rms (defun epa-mail--find-usable-key (keys usage) - "Find a usable key from KEYS for USAGE." + "Find a usable key from KEYS for USAGE. +USAGE would be `sign' or `encrypt'." (catch 'found (while keys (let ((pointer (epg-key-sub-key-list (car keys)))) @@ -66,71 +64,6 @@ (setq pointer (cdr pointer)))) (setq keys (cdr keys))))) -(defvar epa-mail-group-alist nil - "Alist of GnuPG mail groups (`group' commands in `.gnupg/gpg.conf'). -Each element has the form (GROUPNAME ADDRESSES...). -t means the list is not yet read in.") - -(defvar epa-mail-group-modtime nil - "The modification time of `~/.gnupg/gpg.conf' file when last examined.") - -(defvar epa-mail-gnupg-conf-file "~/.gnupg/gpg.conf" - "File name of GnuPG configuration file that specifies recipient groups.") - -(defun epa-mail-parse-groups () - "Parse `~/.gnupg/gpg.conf' and set `epa-mail-group-alist' from it." - (let (aliases) - (with-temp-buffer - (insert-file-contents-literally epa-mail-gnupg-conf-file) - - (while (re-search-forward "^[ \t]*group[ \t]*" nil t) - (if (looking-at "\\([^= \t]+\\)[ \t]*=[ \t]*\\([^ \t\n]+\\)") - (push (cons (match-string-no-properties 1) - (split-string (match-string-no-properties 2))) - aliases)))) - (setq epa-mail-group-alist aliases))) - -(defun epa-mail-sync-groups () - "Update GnuPG groups from file if necessary." - (if (file-exists-p epa-mail-gnupg-conf-file) - (let ((modtime (nth 5 (file-attributes epa-mail-gnupg-conf-file)))) - (if (not (equal epa-mail-group-modtime modtime)) - (progn - (setq epa-mail-group-modtime modtime) - (epa-mail-parse-groups)))) - (setq epa-mail-group-alist nil))) - -(defun epa-mail-expand-recipient-1 (recipient) - "Expand RECIPIENT once thru `epa-mail-group-alist'. -Returns the list of names it stands for, or nil if it isn't a group." - ;; Load the alias list if not loaded before. - (let (alist-elt) - (setq alist-elt (assoc recipient epa-mail-group-alist)) - (cdr alist-elt))) - -(defun epa-mail-expand-recipients-2 (recipients) - "Expand list RECIPIENTS once thru `epa-mail-group-alist'. -Returns the list of names they stand for." - ;; Load the alias list if not loaded before. - (let (output) - (dolist (r recipients) - (let ((expanded (epa-mail-expand-recipient-1 r))) - (if expanded - (dolist (xr expanded) - (unless (member xr output) - (push xr output))) - (unless (member r output) - (push r output))))) - (nreverse output))) - -(defun epa-mail-expand-recipients (recipients) - "Expand RECIPIENTS thru `epa-mail-group-alist' until it stops changing." - (epa-mail-sync-groups) - (while (not (equal recipients - (setq recipients - (epa-mail-expand-recipients-2 recipients))))) - recipients) - ;;;###autoload (defun epa-mail-decrypt () "Decrypt OpenPGP armors in the current buffer. @@ -184,6 +117,7 @@ (interactive (save-excursion (let ((verbose current-prefix-arg) + (config (epg-configuration)) (context (epg-make-context epa-protocol)) recipients-string recipients recipient-key sign) (goto-char (point-min)) @@ -211,9 +145,13 @@ ;; Process all the recipients thru the list of GnuPG groups. ;; Expand GnuPG group names to what they stand for. - ;; The code below, and elsewhere, that checks that names have keys - ;; does not know about these group names. - (setq recipients (epa-mail-expand-recipients recipients)) + (setq recipients + (apply #'nconc + (mapcar + (lambda (recipient) + (or (epg-expand-group config recipient) + (list recipient))) + recipients))) (goto-char (point-min)) (if (search-forward mail-header-separator nil t) ------------------------------------------------------------ revno: 105476 committer: Katsumi Yamaoka branch nick: trunk timestamp: Wed 2011-08-17 00:10:46 +0000 message: nndraft.el (nndraft-update-unread-articles): Don't send delayed articles. diff: === modified file 'lisp/gnus/ChangeLog' --- lisp/gnus/ChangeLog 2011-08-14 05:11:36 +0000 +++ lisp/gnus/ChangeLog 2011-08-17 00:10:46 +0000 @@ -1,3 +1,8 @@ +2011-08-17 Katsumi Yamaoka + + * nndraft.el (nndraft-update-unread-articles): Don't send delayed + articles. + 2011-08-13 Andreas Schwab * gnus-score.el (gnus-all-score-files): Use copy-sequence instead of === modified file 'lisp/gnus/nndraft.el' --- lisp/gnus/nndraft.el 2011-07-04 06:40:46 +0000 +++ lisp/gnus/nndraft.el 2011-08-17 00:10:46 +0000 @@ -177,6 +177,8 @@ (list 'nndraft ""))) (nnmail-get-active))) (gnus-group-marked (copy-sequence groups)) + ;; Don't send delayed articles. + (gnus-get-new-news-hook nil) (inhibit-read-only t)) (gnus-group-get-new-news-this-group nil t) (dolist (group groups) ------------------------------------------------------------ revno: 105475 author: Feng Li committer: Jay Belanger branch nick: trunk timestamp: Tue 2011-08-16 17:33:57 -0500 message: * calc/calc-ext.el (math-defintegral-2): Remove nested backquote. diff: === modified file 'lisp/ChangeLog' --- lisp/ChangeLog 2011-08-16 20:10:40 +0000 +++ lisp/ChangeLog 2011-08-16 22:33:57 +0000 @@ -1,3 +1,7 @@ +2011-08-16 Feng Li (tiny change) + + * calc/calc-ext.el (math-defintegral-2): Remove nested backquote. + 2011-08-16 Alan Mackenzie * progmodes/cc-engine.el (c-state-cache-non-literal-place): === modified file 'lisp/calc/calc-ext.el' --- lisp/calc/calc-ext.el 2011-05-23 17:57:17 +0000 +++ lisp/calc/calc-ext.el 2011-08-16 22:33:57 +0000 @@ -2887,7 +2887,7 @@ (cons 'progn (mapcar #'(lambda (func) `(put ',func 'math-integral-2 - `(nconc + (nconc (get ',func 'math-integral-2) (list #'(lambda (u v) ,@code))))) (if (symbolp funcs) (list funcs) funcs)))) ------------------------------------------------------------ revno: 105474 committer: Ken Brown branch nick: trunk timestamp: Tue 2011-08-16 16:31:32 -0400 message: * src/gmalloc.c: Expand comment. diff: === modified file 'src/ChangeLog' --- src/ChangeLog 2011-08-16 14:28:19 +0000 +++ src/ChangeLog 2011-08-16 20:31:32 +0000 @@ -1,3 +1,7 @@ +2011-08-16 Ken Brown + + * gmalloc.c: Expand comment. + 2011-08-16 Eli Zaretskii * xdisp.c (set_cursor_from_row): Don't accept a previous candidate === modified file 'src/gmalloc.c' --- src/gmalloc.c 2011-08-16 13:27:12 +0000 +++ src/gmalloc.c 2011-08-16 20:31:32 +0000 @@ -356,7 +356,11 @@ emacs uses the Cygwin heap (managed with sbrk). When emacs starts on Cygwin, it reinitializes malloc, and we save the old info for use by free and realloc if they're called with a pointer into the - static heap. */ + static heap. + + Currently (2011-08-16) the Cygwin build doesn't use ralloc.c; if + this is changed in the future, we'll have to similarly deal with + reinitializing ralloc. */ #ifdef CYGWIN extern __ptr_t bss_sbrk PP ((ptrdiff_t __size)); extern int bss_sbrk_did_unexec; ------------------------------------------------------------ revno: 105473 committer: Alan Mackenzie branch nick: trunk timestamp: Tue 2011-08-16 20:10:40 +0000 message: progmodes/cc-engine.el (c-state-cache-non-literal-place): Correct to avoid the insides of macros. diff: === modified file 'lisp/ChangeLog' --- lisp/ChangeLog 2011-08-16 04:04:27 +0000 +++ lisp/ChangeLog 2011-08-16 20:10:40 +0000 @@ -1,3 +1,8 @@ +2011-08-16 Alan Mackenzie + + * progmodes/cc-engine.el (c-state-cache-non-literal-place): + Correct, to avoid the inside of macros. + 2011-08-16 Richard Stallman * epa-mail.el: Handle GnuPG group definitions. === modified file 'lisp/progmodes/cc-engine.el' --- lisp/progmodes/cc-engine.el 2011-07-26 19:18:40 +0000 +++ lisp/progmodes/cc-engine.el 2011-08-16 20:10:40 +0000 @@ -2130,13 +2130,17 @@ pos)) (defsubst c-state-cache-non-literal-place (pos state) - ;; Return a position outside of a string/comment at or before POS. + ;; Return a position outside of a string/comment/macro at or before POS. ;; STATE is the parse-partial-sexp state at POS. - (if (or (nth 3 state) ; in a string? - (nth 4 state)) ; in a comment? - (nth 8 state) - pos)) - + (let ((res (if (or (nth 3 state) ; in a string? + (nth 4 state)) ; in a comment? + (nth 8 state) + pos))) + (save-excursion + (goto-char res) + (if (c-beginning-of-macro) + (point) + res)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Stuff to do with point-min, and coping with any literal there. ------------------------------------------------------------ revno: 105472 committer: Eli Zaretskii branch nick: trunk timestamp: Tue 2011-08-16 17:28:19 +0300 message: Fix cursor positioning at end of buffer under bidi display. src/xdisp.c (set_cursor_from_row): Don't accept a previous candidate if it fails the cursor_row_p test. Fixes cursor positioning at ZV. diff: === modified file 'src/ChangeLog' --- src/ChangeLog 2011-08-16 13:27:12 +0000 +++ src/ChangeLog 2011-08-16 14:28:19 +0000 @@ -1,3 +1,8 @@ +2011-08-16 Eli Zaretskii + + * xdisp.c (set_cursor_from_row): Don't accept a previous candidate + if it fails the cursor_row_p test. Fixes cursor positioning at ZV. + 2011-08-16 Ken Brown Fix memory allocation problems in Cygwin build (Bug#9273). === modified file 'src/xdisp.c' --- src/xdisp.c 2011-08-15 06:44:48 +0000 +++ src/xdisp.c 2011-08-16 14:28:19 +0000 @@ -13751,11 +13751,13 @@ /* that candidate is not the row we are processing */ && MATRIX_ROW (matrix, w->cursor.vpos) != row /* Make sure cursor.vpos specifies a row whose start and end - charpos occlude point. This is because some callers of this - function leave cursor.vpos at the row where the cursor was - displayed during the last redisplay cycle. */ + charpos occlude point, and it is valid candidate for being a + cursor-row. This is because some callers of this function + leave cursor.vpos at the row where the cursor was displayed + during the last redisplay cycle. */ && MATRIX_ROW_START_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos)) <= pt_old - && pt_old <= MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))) + && pt_old <= MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos)) + && cursor_row_p (MATRIX_ROW (matrix, w->cursor.vpos))) { struct glyph *g1 = MATRIX_ROW_GLYPH_START (matrix, w->cursor.vpos) + w->cursor.hpos; ------------------------------------------------------------ revno: 105471 committer: Ken Brown branch nick: trunk timestamp: Tue 2011-08-16 09:27:12 -0400 message: Fix memory allocation problems in Cygwin build (Bug#9273). * src/gmalloc.c [CYGWIN] (bss_sbrk_heapbase, bss_sbrk_heapinfo): New variables. (malloc_initialize_1) [CYGWIN]: Prepare for reinitializing the dumped emacs. (_free_internal_nolock) [CYGWIN]: Ignore requests to free storage in the static heap. [CYGWIN] (special_realloc): New function. (_realloc_internal_nolock) [CYGWIN]: Use the new function on requests to realloc storage in the static heap. * src/unexcw.c ( __malloc_initialized): Declare external variable. (fixup_executable): Force the dumped emacs to reinitialize malloc. diff: === modified file 'src/ChangeLog' --- src/ChangeLog 2011-08-15 18:54:18 +0000 +++ src/ChangeLog 2011-08-16 13:27:12 +0000 @@ -1,3 +1,20 @@ +2011-08-16 Ken Brown + + Fix memory allocation problems in Cygwin build (Bug#9273). + + * unexcw.c ( __malloc_initialized): Declare external variable. + (fixup_executable): Force the dumped emacs to reinitialize malloc. + + * gmalloc.c [CYGWIN] (bss_sbrk_heapbase, bss_sbrk_heapinfo): New + variables. + (malloc_initialize_1) [CYGWIN]: Prepare for reinitializing the + dumped emacs. + (_free_internal_nolock) [CYGWIN]: Ignore requests to free storage + in the static heap. + [CYGWIN] (special_realloc): New function. + (_realloc_internal_nolock) [CYGWIN]: Use the new function on + requests to realloc storage in the static heap. + 2011-08-15 Paul Eggert * bidi.c (bidi_initialize): Remove unused local. === modified file 'src/gmalloc.c' --- src/gmalloc.c 2011-08-04 17:04:39 +0000 +++ src/gmalloc.c 2011-08-16 13:27:12 +0000 @@ -351,10 +351,17 @@ #endif #include -/* How to really get more memory. */ -#if defined(CYGWIN) +/* On Cygwin there are two heaps. temacs uses the static heap + (defined in sheap.c and managed with bss_sbrk), and the dumped + emacs uses the Cygwin heap (managed with sbrk). When emacs starts + on Cygwin, it reinitializes malloc, and we save the old info for + use by free and realloc if they're called with a pointer into the + static heap. */ +#ifdef CYGWIN extern __ptr_t bss_sbrk PP ((ptrdiff_t __size)); extern int bss_sbrk_did_unexec; +char *bss_sbrk_heapbase; /* _heapbase for static heap */ +malloc_info *bss_sbrk_heapinfo; /* _heapinfo for static heap */ #endif __ptr_t (*__morecore) PP ((__malloc_ptrdiff_t __size)) = __default_morecore; @@ -584,6 +591,16 @@ mcheck (NULL); #endif +#ifdef CYGWIN + if (bss_sbrk_did_unexec) + /* we're reinitializing the dumped emacs */ + { + bss_sbrk_heapbase = _heapbase; + bss_sbrk_heapinfo = _heapinfo; + memset (_fraghead, 0, BLOCKLOG * sizeof (struct list)); + } +#endif + if (__malloc_initialize_hook) (*__malloc_initialize_hook) (); @@ -1054,6 +1071,12 @@ if (ptr == NULL) return; +#ifdef CYGWIN + if (ptr < _heapbase) + /* We're being asked to free something in the static heap. */ + return; +#endif + PROTECT_MALLOC_STATE (0); LOCK_ALIGNED_BLOCKS (); @@ -1349,6 +1372,31 @@ #define min(A, B) ((A) < (B) ? (A) : (B)) +/* On Cygwin the dumped emacs may try to realloc storage allocated in + the static heap. We just malloc space in the new heap and copy the + data. */ +#ifdef CYGWIN +__ptr_t +special_realloc (ptr, size) + __ptr_t ptr; + __malloc_size_t size; +{ + __ptr_t result; + int type; + __malloc_size_t block, oldsize; + + block = ((char *) ptr - bss_sbrk_heapbase) / BLOCKSIZE + 1; + type = bss_sbrk_heapinfo[block].busy.type; + oldsize = + type == 0 ? bss_sbrk_heapinfo[block].busy.info.size * BLOCKSIZE + : (__malloc_size_t) 1 << type; + result = _malloc_internal_nolock (size); + if (result != NULL) + memcpy (result, ptr, min (oldsize, size)); + return result; +} +#endif + /* Debugging hook for realloc. */ __ptr_t (*__realloc_hook) PP ((__ptr_t __ptr, __malloc_size_t __size)); @@ -1375,6 +1423,12 @@ else if (ptr == NULL) return _malloc_internal_nolock (size); +#ifdef CYGWIN + if (ptr < _heapbase) + /* ptr points into the static heap */ + return special_realloc (ptr, size); +#endif + block = BLOCK (ptr); PROTECT_MALLOC_STATE (0); === modified file 'src/unexcw.c' --- src/unexcw.c 2011-03-17 20:18:59 +0000 +++ src/unexcw.c 2011-08-16 13:27:12 +0000 @@ -33,6 +33,8 @@ extern int bss_sbrk_did_unexec; +extern int __malloc_initialized; + /* emacs symbols that indicate where bss and data end for emacs internals */ extern char my_endbss[]; extern char my_edata[]; @@ -210,9 +212,12 @@ lseek (fd, (long) (exe_header->section_header[i].s_scnptr), SEEK_SET); assert (ret != -1); + /* force the dumped emacs to reinitialize malloc */ + __malloc_initialized = 0; ret = write (fd, (char *) start_address, my_endbss - (char *) start_address); + __malloc_initialized = 1; assert (ret == (my_endbss - (char *) start_address)); if (debug_unexcw) printf (" .bss, mem start 0x%08x mem length %d\n", ------------------------------------------------------------ revno: 105470 committer: Eli Zaretskii branch nick: trunk timestamp: Tue 2011-08-16 11:40:31 +0300 message: Improve documentation of `special' modes. doc/lispref/modes.texi (Major Mode Conventions): Improve the documentation of `mode-class' `special' modes. diff: === modified file 'doc/lispref/ChangeLog' --- doc/lispref/ChangeLog 2011-08-16 08:26:46 +0000 +++ doc/lispref/ChangeLog 2011-08-16 08:40:31 +0000 @@ -1,5 +1,8 @@ 2011-08-16 Eli Zaretskii + * modes.texi (Major Mode Conventions): Improve the documentation + of `mode-class' `special' modes. + * nonascii.texi (Character Properties): Document the `mirroring' property. Add index entries. === modified file 'doc/lispref/modes.texi' --- doc/lispref/modes.texi 2011-07-13 21:42:54 +0000 +++ doc/lispref/modes.texi 2011-08-16 08:40:31 +0000 @@ -505,21 +505,26 @@ value for @code{change-major-mode-hook} (@pxref{Creating Buffer-Local}). @item -If this mode is appropriate only for specially-prepared text, then the -major mode command symbol should have a property named @code{mode-class} -with value @code{special}, put on as follows: +If this mode is appropriate only for specially-prepared text produced by +the mode itself (rather than by the user typing at the keyboard or by an +external file), then the major mode command symbol should have a +property named @code{mode-class} with value @code{special}, put on as +follows: @kindex mode-class @r{(property)} -@cindex @code{special} +@cindex @code{special} modes @example (put 'funny-mode 'mode-class 'special) @end example @noindent -This tells Emacs that new buffers created while the current buffer is -in Funny mode should not inherit Funny mode, in case the default value -of @code{major-mode} is @code{nil}. Modes such as Dired, Rmail, -and Buffer List use this feature. +This tells Emacs that new buffers created while the current buffer is in +Funny mode should not be put in Funny mode, even though the default +value of @code{major-mode} is @code{nil}. By default, the value of +@code{nil} for @code{major-mode} means to use the current buffer's major +mode when creating new buffers (@pxref{Auto Major Mode}), but with such +@code{special} modes, Fundamental mode is used instead. Modes such as +Dired, Rmail, and Buffer List use this feature. The @code{define-derived-mode} macro automatically marks the derived mode as special if the parent mode is special. The special mode