Changes for GNU Emacs 19.12, from 19.11 Changes in files you can reconstruct with yacc, makeinfo, TeX or the byte compiler have been omitted. Remember to recompile the changed .el files with M-x byte-recompile RET emac-19.12/lisp RET before building and dumping Emacs. Note that you must load the old version of cl.elc in order to compile the new cl.el successfully. diff -crP -x *.elc -x *.info* emacs-19.11/ChangeLog emacs-19.12/ChangeLog *** emacs-19.11/ChangeLog Tue Jun 1 04:29:55 1993 --- emacs-19.12/ChangeLog Wed Jun 2 01:16:16 1993 *************** *** 1,5 **** --- 1,11 ---- Tue Jun 1 00:08:05 1993 Richard Stallman (rms@mole.gnu.ai.mit.edu) + * Version 19.12 released. + + * Makefile.in (do-install): Correct previous etc-copying change. + Partially rewrite using `if'. + (src/Makefile): Insert --x-libraries option into LD_SWITCH_X_SITE. + * Version 19.11 released. * configure.in: Handle 386bsd. *************** *** 1362,1373 **** * Makefile: Changed LIBDIR and BINDIR back to /usr/local/{emacs,bin} to match build-install and paths.h. - - - Local Variables: - mode: indented-text - left-margin: 8 - fill-column: 74 - fill-prefix: "\t" - version-control: never - End: --- 1368,1370 ---- diff -crP -x *.elc -x *.info* emacs-19.11/INSTALL emacs-19.12/INSTALL *** emacs-19.11/INSTALL Fri May 28 00:47:23 1993 --- emacs-19.12/INSTALL Tue Jun 1 13:03:54 1993 *************** *** 217,223 **** /usr/local/info) to make sure that it has a menu entry for the Emacs info files. ! 9) You are done! MAKE VARIABLES --- 217,227 ---- /usr/local/info) to make sure that it has a menu entry for the Emacs info files. ! 9) If your system uses lock files to interlock access to mailer inbox files, ! then you might need to make the program arch-lib/movemail setuid or setgid ! to enable it to write the lock files. We believe this is safe. ! ! 10) You are done! MAKE VARIABLES diff -crP -x *.elc -x *.info* emacs-19.11/Makefile.in emacs-19.12/Makefile.in *** emacs-19.11/Makefile.in Mon May 31 16:56:32 1993 --- emacs-19.12/Makefile.in Wed Jun 2 01:15:56 1993 *************** *** 278,283 **** --- 278,284 ---- -e 's|^CC *=.*$$|CC='"${CC}"'|' \ -e 's|^LN_S *=.*$$|LN_S='"${LN_S}"'|' \ -e 's|^CFLAGS *=.*$$|CFLAGS='"${CFLAGS}"'|' \ + -e 's|^\(LD_SWITCH_X_SITE *=\).*$$|\1'"${LD_SWITCH_X_SITE}"'|' \ -e '/^# DIST: /d') > src/Makefile.tmp @${srcdir}/move-if-change src/Makefile.tmp src/Makefile chmod -w src/Makefile *************** *** 348,364 **** rm -f $${subdir}/*~ ; \ done) ; \ done ! [ `(cd etc; /bin/pwd)` != `(cd ${srcdir}/etc; /bin/pwd)` ] \ ! && (echo "Copying etc/DOC* ..." ; \ ! (cd etc; tar -cf - DOC*)|(cd ${etcdir}; umask 0; tar -xvf - )) ! -[ `(cd ${srcdir}/info && /bin/pwd)` != `(cd ${infodir} && /bin/pwd)` ] \ ! && (cd ${srcdir}/info ; \ if [ ! -f ${infodir}/dir ] && [ -f dir ]; then \ ${INSTALL_DATA} dir ${infodir}/dir ; \ fi ; \ for f in cl* emacs* forms* info* vip* ; do \ ${INSTALL_DATA} $$f ${infodir}/$$f ; \ ! done) cd ${srcdir}/etc; for page in emacs etags ctags ; do \ ${INSTALL_DATA} $${page}.1 ${mandir}/$${page}${manext} ; \ done --- 349,368 ---- rm -f $${subdir}/*~ ; \ done) ; \ done ! if [ `(cd ./etc; /bin/pwd)` != `(cd ${srcdir}/etc; /bin/pwd)` ]; \ ! then \ ! echo "Copying etc/DOC* ..." ; \ ! (cd etc; tar -cf - DOC*)|(cd ${etcdir}; umask 0; tar -xvf - ); \ ! else true; fi ! if [ `(cd ${srcdir}/info && /bin/pwd)` != `(cd ${infodir} && /bin/pwd)` ]; \ ! then (cd ${srcdir}/info ; \ if [ ! -f ${infodir}/dir ] && [ -f dir ]; then \ ${INSTALL_DATA} dir ${infodir}/dir ; \ fi ; \ for f in cl* emacs* forms* info* vip* ; do \ ${INSTALL_DATA} $$f ${infodir}/$$f ; \ ! done); \ ! else true; fi cd ${srcdir}/etc; for page in emacs etags ctags ; do \ ${INSTALL_DATA} $${page}.1 ${mandir}/$${page}${manext} ; \ done diff -crP -x *.elc -x *.info* emacs-19.11/README emacs-19.12/README *** emacs-19.11/README Tue Jun 1 04:32:32 1993 --- emacs-19.12/README Wed Jun 2 03:33:06 1993 *************** *** 1,4 **** ! This directory tree holds version 19.11 of GNU Emacs, the extensible, customizable, self-documenting real-time display editor. See the files `etc/NEWS' and `etc/news.texi' for information on new --- 1,4 ---- ! This directory tree holds version 19.12 of GNU Emacs, the extensible, customizable, self-documenting real-time display editor. See the files `etc/NEWS' and `etc/news.texi' for information on new diff -crP -x *.elc -x *.info* emacs-19.11/README-c++ emacs-19.12/README-c++ *** emacs-19.11/README-c++ --- emacs-19.12/README-c++ Wed Jun 2 03:46:59 1993 *************** *** 0 **** --- 1,585 ---- + These untested patches in src/syntax.c might fix a bug + in forward-comment that would show up if you use lisp/c++-mode1.el. + + *************** + *** 564,575 **** + } + + DEFUN ("forward-comment", Fforward_comment, Sforward_comment, 1, 1, 0, + "Move forward across up to N comments. If N is negative, move backward.\n\ + Stop scanning if we find something other than a comment or whitespace.\n\ + - Set point to where scanning stops.\n\ + If N comments are found as expected, with nothing except whitespace\n\ + ! between them, return t; otherwise return nil.") + ! (count) + ! Lisp_Object count; + { + register int from; + --- 653,831 ---- + } + + + static int + + find_start_of_comment (from, stop, mask) + + int from, stop, mask; + + { + + int c; + + enum syntaxcode code; + + + + /* Look back, counting the parity of string-quotes, + + and recording the comment-starters seen. + + When we reach a safe place, assume that's not in a string; + + then step the main scan to the earliest comment-starter seen + + an even number of string quotes away from the safe place. + + + + OFROM[I] is position of the earliest comment-starter seen + + which is I+2X quotes from the comment-end. + + PARITY is current parity of quotes from the comment end. */ + + int parity = 0; + + char my_stringend = 0; + + int string_lossage = 0; + + int comment_end = from; + + int comstart_pos = 0; + + int comstart_parity = 0; + + int styles_match_p = 0; + + + + /* At beginning of range to scan, we're outside of strings; + + that determines quote parity to the comment-end. */ + + while (from != stop) + + { + + /* Move back and examine a character. */ + + from--; + + + + c = FETCH_CHAR (from); + + code = SYNTAX (c); + + + + /* is this a 1-char comment end sequence? if so, try + + to see if style matches previously extracted mask */ + + if (code == Sendcomment) + + { + + styles_match_p = SYNTAX_STYLES_MATCH_1CHAR_P (c, mask); + + } + + + + /* otherwise, is this a 2-char comment end sequence? + + if so, back up, and see if style matches previously + + extracted mask */ + + else if (from > stop + + && SYNTAX_END_P (FETCH_CHAR (from-1), c)) + + { + + code = Sendcomment; + + styles_match_p = + + SYNTAX_STYLES_MATCH_END_P (FETCH_CHAR (from-1), c, mask); + + + + from--; + + } + + + + /* or are we looking at a 1-char comment start sequence + + of the style matching mask? */ + + else if (code == Scomment + + && SYNTAX_STYLES_MATCH_1CHAR_P (c, mask)) + + { + + styles_match_p = 1; + + } + + + + /* or possibly, a 2-char comment start sequence */ + + else if (from > stop + + && SYNTAX_STYLES_MATCH_START_P (FETCH_CHAR (from-1), c, mask)) + + { + + code = Scomment; + + from--; + + styles_match_p = 1; + + } + + + + /* Ignore escaped characters. */ + + if (char_quoted (from)) + + continue; + + + + /* Track parity of quotes. */ + + if (code == Sstring) + + { + + parity ^= 1; + + if (my_stringend == 0) + + my_stringend = c; + + /* If we have two kinds of string delimiters. + + There's no way to grok this scanning backwards. */ + + else if (my_stringend != c) + + string_lossage = 1; + + } + + + + /* Record comment-starters according to that + + quote-parity to the comment-end. */ + + if (code == Scomment && styles_match_p) + + { + + comstart_parity = parity; + + comstart_pos = from; + + } + + + + /* If we find another earlier comment-ender, + + any comment-starts earier than that don't count + + (because they go with the earlier comment-ender). */ + + if (code == Sendcomment && styles_match_p) + + break; + + + + /* Assume a defun-start point is outside of strings. */ + + if (code == Sopen + + && (from == stop || FETCH_CHAR (from - 1) == '\n')) + + break; + + } + + + + if (comstart_pos == 0) + + from = comment_end; + + /* If the earliest comment starter + + is followed by uniform paired string quotes or none, + + we know it can't be inside a string + + since if it were then the comment ender would be inside one. + + So it does start a comment. Skip back to it. */ + + else if (comstart_parity == 0 && !string_lossage) + + from = comstart_pos; + + else + + { + + /* We had two kinds of string delimiters mixed up + + together. Decode this going forwards. + + Scan fwd from the previous comment ender + + to the one in question; this records where we + + last passed a comment starter. */ + + struct lisp_parse_state state; + + scan_sexps_forward (&state, find_defun_start (comment_end), + + comment_end - 1, -10000, 0, Qnil); + + if (state.incomment) + + from = state.comstart; + + else + + /* We can't grok this as a comment; scan it normally. */ + + from = comment_end; + + } + + return from; + + } + + + + static int + + find_end_of_comment (from, stop, mask) + + int from, stop, mask; + + { + + int c; + + + + while (1) + + { + + if (from == stop) + + { + + return -1; + + } + + c = FETCH_CHAR (from); + + if (SYNTAX (c) == Sendcomment + + && SYNTAX_STYLES_MATCH_1CHAR_P (c, mask)) + + /* we have encountered a comment end of the same style + + as the comment sequence which began this comment + + section */ + + break; + + + + from++; + + if (from < stop + + && SYNTAX_STYLES_MATCH_END_P (c, FETCH_CHAR (from), mask)) + + /* we have encountered a comment end of the same style + + as the comment sequence which began this comment + + section */ + + { from++; break; } + + } + + return from; + + } + + + + + DEFUN ("forward-comment", Fforward_comment, Sforward_comment, 1, 1, 0, + "Move forward across up to N comments. If N is negative, move backward.\n\ + + Set point to the far end of the last comment found.\n\ + Stop scanning if we find something other than a comment or whitespace.\n\ + If N comments are found as expected, with nothing except whitespace\n\ + ! between them, return t; otherwise return nil. Point is set in either case.") + ! (cntarg) + ! Lisp_Object cntarg; + { + register int from; + *************** + *** 577,586 **** + register int c; + register enum syntaxcode code; + ! int comstyle = 0; /* style of comment encountered */ + ! int found; + ! int count1; + + ! CHECK_NUMBER (count, 0); + ! count1 = XINT (count); + + immediate_quit = 1; + --- 833,841 ---- + register int c; + register enum syntaxcode code; + ! int count; + ! int mask = 0x0; /* mask for matching comments */ + + ! CHECK_NUMBER (cntarg, 0); + ! count = XINT (cntarg); + + immediate_quit = 1; + *************** + *** 589,593 **** + from = PT; + + ! while (count1 > 0) + { + stop = ZV; + --- 844,848 ---- + from = PT; + + ! while (count > 0) + { + stop = ZV; + *************** + *** 594,605 **** + while (from < stop) + { + c = FETCH_CHAR (from); + code = SYNTAX (c); + ! from++; + ! comstyle = 0; + ! if (from < stop && SYNTAX_COMSTART_FIRST (c) + ! && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from))) + { + ! /* we have encountered a comment start sequence and we + are ignoring all text inside comments. we must record + the comment style this sequence begins so that later, + --- 849,872 ---- + while (from < stop) + { + + if (char_quoted (from)) + + { from++; continue; } + + + c = FETCH_CHAR (from); + code = SYNTAX (c); + ! mask = 0x0; + ! + ! if (code == Scomment) + { + ! /* we have encountered a single character comment start + ! sequence, and we are ignoring all text inside comments. + ! we must record the comment style this character begins + ! so that later, only a comment end of the same style actually + ! ends the comment section */ + ! mask = SYNTAX_COMMENT_1CHAR_MASK (c); + ! } + ! + ! else if (from < stop && SYNTAX_START_P (c, FETCH_CHAR (from+1))) + ! { + ! /* we have encountered a 2char comment start sequence and we + are ignoring all text inside comments. we must record + the comment style this sequence begins so that later, + *************** + *** 607,611 **** + the comment section */ + code = Scomment; + ! comstyle = SYNTAX_COMMENT_STYLE (FETCH_CHAR (from)); + from++; + } + --- 874,878 ---- + the comment section */ + code = Scomment; + ! mask = SYNTAX_COMMENT_MASK_START (c, FETCH_CHAR (from+1)); + from++; + } + *************** + *** 613,656 **** + if (code == Scomment) + { + ! while (1) + { + ! if (from == stop) + ! { + ! immediate_quit = 0; + ! SET_PT (from); + ! return Qnil; + ! } + ! c = FETCH_CHAR (from); + ! if (SYNTAX (c) == Sendcomment + ! && SYNTAX_COMMENT_STYLE (c) == comstyle) + ! /* we have encountered a comment end of the same style + ! as the comment sequence which began this comment + ! section */ + ! break; + ! from++; + ! if (from < stop && SYNTAX_COMEND_FIRST (c) + ! && SYNTAX_COMEND_SECOND (FETCH_CHAR (from)) + ! && SYNTAX_COMMENT_STYLE (c) == comstyle) + ! /* we have encountered a comment end of the same style + ! as the comment sequence which began this comment + ! section */ + ! { from++; break; } + } + /* We have skipped one comment. */ + break; + } + ! else if (code != Swhitespace && code != Sendcomment) + { + immediate_quit = 0; + ! SET_PT (from - 1); + return Qnil; + } + } + + /* End of comment reached */ + ! count1--; + } + + ! while (count1 < 0) + { + stop = BEGV; + --- 880,914 ---- + if (code == Scomment) + { + ! int newfrom; + ! + ! newfrom = find_end_of_comment (from, stop, mask); + ! if (newfrom < 0) + { + ! /* we stopped because from==stop */ + ! immediate_quit = 0; + ! SET_PT (stop); + ! return Qnil; + } + + from = newfrom; + + + /* We have skipped one comment. */ + break; + } + ! else if (code != Swhitespace && + ! code != Sendcomment && + ! code != Scomment ) + { + immediate_quit = 0; + ! SET_PT (from); + return Qnil; + } + + from++; + } + + /* End of comment reached */ + ! count--; + } + + ! while (count < 0) + { + stop = BEGV; + *************** + *** 660,672 **** + + from--; + ! quoted = char_quoted (from); + ! if (quoted) + ! from--; + c = FETCH_CHAR (from); + code = SYNTAX (c); + ! comstyle = 0; + ! if (from > stop && SYNTAX_COMEND_SECOND (c) + ! && SYNTAX_COMEND_FIRST (FETCH_CHAR (from - 1)) + ! && !char_quoted (from - 1)) + { + /* we must record the comment style encountered so that + --- 918,939 ---- + + from--; + ! if (char_quoted (from)) + ! { from--; continue; } + ! + c = FETCH_CHAR (from); + code = SYNTAX (c); + ! mask = 0x0; + ! + ! if (code == Sendcomment) + ! { + ! /* we have found a single char end comment. we must record + ! the comment style encountered so that later, we can match + ! only the proper comment begin sequence of the same style */ + ! mask = SYNTAX_COMMENT_1CHAR_MASK (c); + ! } + ! + ! else if (from > stop + ! && SYNTAX_END_P (FETCH_CHAR (from-1), c) + ! && !char_quoted (from - 1)) + { + /* we must record the comment style encountered so that + *************** + *** 674,821 **** + sequence of the same style */ + code = Sendcomment; + ! comstyle = SYNTAX_COMMENT_STYLE (FETCH_CHAR (from - 1)); + from--; + } + + ! if (code == Sendcomment && !quoted) + ! { + ! if (code != SYNTAX (c)) + ! /* For a two-char comment ender, we can assume + ! it does end a comment. So scan back in a simple way. */ + ! { + ! if (from != stop) from--; + ! while (1) + ! { + ! if (SYNTAX (c = FETCH_CHAR (from)) == Scomment + ! && SYNTAX_COMMENT_STYLE (c) == comstyle) + ! break; + ! if (from == stop) + ! { + ! immediate_quit = 0; + ! SET_PT (from); + ! return Qnil; + ! } + ! from--; + ! if (SYNTAX_COMSTART_SECOND (c) + ! && SYNTAX_COMSTART_FIRST (FETCH_CHAR (from)) + ! && SYNTAX_COMMENT_STYLE (c) == comstyle + ! && !char_quoted (from)) + ! break; + ! } + ! break; + ! } + ! + ! /* Look back, counting the parity of string-quotes, + ! and recording the comment-starters seen. + ! When we reach a safe place, assume that's not in a string; + ! then step the main scan to the earliest comment-starter seen + ! an even number of string quotes away from the safe place. + ! + ! OFROM[I] is position of the earliest comment-starter seen + ! which is I+2X quotes from the comment-end. + ! PARITY is current parity of quotes from the comment end. */ + ! { + ! int parity = 0; + ! char my_stringend = 0; + ! int string_lossage = 0; + ! int comment_end = from; + ! int comstart_pos = 0; + ! int comstart_parity = 0; + ! + ! /* At beginning of range to scan, we're outside of strings; + ! that determines quote parity to the comment-end. */ + ! while (from != stop) + ! { + ! /* Move back and examine a character. */ + ! from--; + ! + ! c = FETCH_CHAR (from); + ! code = SYNTAX (c); + ! + ! /* If this char is the second of a 2-char comment sequence, + ! back up and give the pair the appropriate syntax. */ + ! if (from > stop && SYNTAX_COMEND_SECOND (c) + ! && SYNTAX_COMEND_FIRST (FETCH_CHAR (from - 1))) + ! { + ! code = Sendcomment; + ! from--; + ! } + ! + ! else if (from > stop && SYNTAX_COMSTART_SECOND (c) + ! && SYNTAX_COMSTART_FIRST (FETCH_CHAR (from - 1)) + ! && comstyle == SYNTAX_COMMENT_STYLE (c)) + ! { + ! code = Scomment; + ! from--; + ! } + ! + ! /* Ignore escaped characters. */ + ! if (char_quoted (from)) + ! continue; + ! + ! /* Track parity of quotes. */ + ! if (code == Sstring) + ! { + ! parity ^= 1; + ! if (my_stringend == 0) + ! my_stringend = c; + ! /* If we have two kinds of string delimiters. + ! There's no way to grok this scanning backwards. */ + ! else if (my_stringend != c) + ! string_lossage = 1; + ! } + ! + ! /* Record comment-starters according to that + ! quote-parity to the comment-end. */ + ! if (code == Scomment) + ! { + ! comstart_parity = parity; + ! comstart_pos = from; + ! } + ! + ! /* If we find another earlier comment-ender, + ! any comment-starts earier than that don't count + ! (because they go with the earlier comment-ender). */ + ! if (code == Sendcomment + ! && SYNTAX_COMMENT_STYLE (FETCH_CHAR (from)) == comstyle) + ! break; + ! + ! /* Assume a defun-start point is outside of strings. */ + ! if (code == Sopen + ! && (from == stop || FETCH_CHAR (from - 1) == '\n')) + ! break; + ! } + + ! if (comstart_pos == 0) + ! from = comment_end; + ! /* If the earliest comment starter + ! is followed by uniform paired string quotes or none, + ! we know it can't be inside a string + ! since if it were then the comment ender would be inside one. + ! So it does start a comment. Skip back to it. */ + ! else if (comstart_parity == 0 && !string_lossage) + ! from = comstart_pos; + ! else + ! { + ! /* We had two kinds of string delimiters mixed up + ! together. Decode this going forwards. + ! Scan fwd from the previous comment ender + ! to the one in question; this records where we + ! last passed a comment starter. */ + ! struct lisp_parse_state state; + ! scan_sexps_forward (&state, find_defun_start (comment_end), + ! comment_end - 1, -10000, 0, Qnil); + ! if (state.incomment) + ! from = state.comstart; + ! else + ! /* We can't grok this as a comment; scan it normally. */ + ! from = comment_end; + ! } + ! } + ! } + ! else if ((code != Swhitespace && code != Scomment) || quoted) + { + immediate_quit = 0; + ! SET_PT (from + 1); + return Qnil; + } + --- 941,957 ---- + sequence of the same style */ + code = Sendcomment; + ! mask = SYNTAX_COMMENT_MASK_END (FETCH_CHAR (from-1), c); + from--; + } + + ! if (code == Sendcomment) + ! from = find_start_of_comment (from, stop, mask); + + ! else if (code != Swhitespace && + ! SYNTAX (c) != Scomment && + ! SYNTAX (c) != Sendcomment) + { + immediate_quit = 0; + ! SET_PT (from); + return Qnil; + } + *************** + *** 822,826 **** + } + + ! count1++; + } + + --- 958,962 ---- + } + + ! count++; + } + diff -crP -x *.elc -x *.info* emacs-19.11/README-sol2 emacs-19.12/README-sol2 *** emacs-19.11/README-sol2 --- emacs-19.12/README-sol2 Wed Jun 2 03:43:53 1993 *************** *** 0 **** --- 1,120 ---- + This untested alternative version of x_new_font in xterm.c + might solve the problem of access to scalable fonts + in Open Windows on Solaris. + + + Lisp_Object + x_new_font (f, fontname) + struct frame *f; + register char *fontname; + { + int already_loaded; + int n_matching_fonts; + XFontStruct *font_info; + char **font_names; + + /* Get a list of all the fonts that match this name. Once we + have a list of matching fonts, we compare them against the fonts + we already have by comparing font ids. */ + font_names = (char **) XListFontsWithInfo (x_current_display, fontname, + 1024, &n_matching_fonts, + &font_info); + /* Don't just give up if n_matching_fonts is 0. + Apparently there's a bug on Suns: XListFontsWithInfo can + fail to find a font, but XLoadQueryFont may still find it. */ + + /* See if we've already loaded a matching font. */ + already_loaded = -1; + if (n_matching_fonts != 0) + { + int i, j; + + for (i = 0; i < n_fonts; i++) + for (j = 0; j < n_matching_fonts; j++) + if (x_font_table[i]->fid == font_info[j].fid) + { + already_loaded = i; + fontname = font_names[j]; + goto found_font; + } + } + found_font: + + /* If we have, just return it from the table. */ + if (already_loaded > 0) + f->display.x->font = x_font_table[already_loaded]; + + /* Otherwise, load the font and add it to the table. */ + else + { + int i; + XFontStruct *font; + + /* Try to find a character-cell font in the list. */ + #if 0 + /* A laudable goal, but this isn't how to do it. */ + for (i = 0; i < n_matching_fonts; i++) + if (! font_info[i].per_char) + break; + #else + i = 0; + #endif + + /* See comment above. */ + if (n_matching_fonts != 0) + fontname = font_names[i]; + + font = (XFontStruct *) XLoadQueryFont (x_current_display, fontname); + if (! font) + { + /* Free the information from XListFontsWithInfo. */ + if (n_matching_fonts) + XFreeFontInfo (font_names, font_info, n_matching_fonts); + return Qnil; + } + + /* Do we need to create the table? */ + if (x_font_table_size == 0) + { + x_font_table_size = 16; + x_font_table + = (XFontStruct **) xmalloc (x_font_table_size + * sizeof (x_font_table[0])); + } + /* Do we need to grow the table? */ + else if (n_fonts >= x_font_table_size) + { + x_font_table_size *= 2; + x_font_table + = (XFontStruct **) xrealloc (x_font_table, + (x_font_table_size + * sizeof (x_font_table[0]))); + } + + f->display.x->font = x_font_table[n_fonts++] = font; + } + + /* Now make the frame display the given font. */ + if (FRAME_X_WINDOW (f) != 0) + { + XSetFont (x_current_display, f->display.x->normal_gc, + f->display.x->font->fid); + XSetFont (x_current_display, f->display.x->reverse_gc, + f->display.x->font->fid); + XSetFont (x_current_display, f->display.x->cursor_gc, + f->display.x->font->fid); + + x_set_window_size (f, f->width, f->height); + } + + { + Lisp_Object lispy_name = build_string (fontname); + + + /* Free the information from XListFontsWithInfo. The data + we actually retain comes from XLoadQueryFont. */ + XFreeFontInfo (font_names, font_info, n_matching_fonts); + + return lispy_name; + } + } diff -crP -x *.elc -x *.info* emacs-19.11/etc/FTP emacs-19.12/etc/FTP *** emacs-19.11/etc/FTP Sat May 29 01:13:15 1993 --- emacs-19.12/etc/FTP Tue Jun 1 18:20:30 1993 *************** *** 142,156 **** scam.berkeley.edu, jaguar.utah.edu, gatekeeper.dec.com:/pub/gnu, archive.cis.ohio-state.edu, and ftp.uu.net:/archive/systems/gnu). And these foreign sites: archie.oz.au:/gnu (Australia (archie.oz or ! archie.oz.au for ACSnet)), ! ftp-admin@ftp.technion.al.il:/pub/unsupported/gnu (Israel, automatic ! update daily), ftp.informatik.tu-muenchen.de or ! ftp.informatik.rwth-aachen.de (Germany), isy.liu.se, ! ftp.stacken.kth.se or ftp.luth.se:/pub/unix/gnu (Sweden), ! hp4nl.nluug.nl (Netherlands), ftp.win.tue.nl (Netherlands Internet ! Address 131.155.70.100), funic.funet.fi:/pub/gnu (Finland ! 128.214.6.100), ftp.denet.dk (Denmark), ugle.unit.no (Norway ! 129.241.1.97), ftp.eunet.ch or nic.switch.ch:/mirror/gnu (Switzerland), irisa.irisa.fr:/pub/gnu or grasp1.univ-lyon1.fr:pub/gnu (France), archive.eu.net (Europe, 192.16.202.1), cair.kaist.ac.kr:/pub/gnu (Korea 143.248.11.170), --- 142,155 ---- scam.berkeley.edu, jaguar.utah.edu, gatekeeper.dec.com:/pub/gnu, archive.cis.ohio-state.edu, and ftp.uu.net:/archive/systems/gnu). And these foreign sites: archie.oz.au:/gnu (Australia (archie.oz or ! archie.oz.au for ACSnet)), ftp.technion.al.il:/pub/unsupported/gnu ! (Israel, automatic update daily, ran by ftp-admin), ! ftp.informatik.tu-muenchen.de or ftp.informatik.rwth-aachen.de ! (Germany), isy.liu.se, ftp.stacken.kth.se or ftp.luth.se:/pub/unix/gnu ! (Sweden), hp4nl.nluug.nl (Netherlands), ftp.win.tue.nl (Netherlands, ! Internet Address 131.155.70.100), nic.funet.fi:/pub/gnu (Finland ! 128.214.6.100, ran by gnu-adm), ftp.denet.dk (Denmark), ugle.unit.no ! (Norway 129.241.1.97), ftp.eunet.ch or nic.switch.ch:/mirror/gnu (Switzerland), irisa.irisa.fr:/pub/gnu or grasp1.univ-lyon1.fr:pub/gnu (France), archive.eu.net (Europe, 192.16.202.1), cair.kaist.ac.kr:/pub/gnu (Korea 143.248.11.170), diff -crP -x *.elc -x *.info* emacs-19.11/etc/MACHINES emacs-19.12/etc/MACHINES *** emacs-19.11/etc/MACHINES Tue Jun 1 02:28:49 1993 --- emacs-19.12/etc/MACHINES Wed Jun 2 02:58:03 1993 *************** *** 344,356 **** corrupted; if you have a fix, please send it to us. Reports are that the IBM supplied X libraries don't work with Emacs, ! but the IBM X libraries and include files do work. Compiling with -O using the IBM compiler has been known to make Emacs work incorrectly. ! GCC 2.3.3 and 2.4.1 have a bug that miscompiles Emacs. IBM RT/PC (romp-ibm-bsd or romp-ibm-aix) 18.52 worked on both operating systems. --- 344,359 ---- corrupted; if you have a fix, please send it to us. Reports are that the IBM supplied X libraries don't work with Emacs, ! but the MIT X libraries and include files do work. Compiling with -O using the IBM compiler has been known to make Emacs work incorrectly. ! As of 19.11, if you strip the Emacs executable, it ceases to work. + If anyone can fix the above problems, or confirm that they don't happen + with certain versions of various programs, we would appreciate it. + IBM RT/PC (romp-ibm-bsd or romp-ibm-aix) 18.52 worked on both operating systems. *************** *** 559,565 **** Emacs 19 has not been tested extensively yet, but it seems to work in a NeXTStep 3.0 terminal window with the almost unchanged system ! dependent code from version 18. Multiple frames (new with Emacs 19) might work with X, but this has not not been tested yet. A NeXTStep implementation of multiple --- 562,569 ---- Emacs 19 has not been tested extensively yet, but it seems to work in a NeXTStep 3.0 terminal window with the almost unchanged system ! dependent code from version 18. You may need to specify -traditional ! when src/Makefile builds xmakefile. Multiple frames (new with Emacs 19) might work with X, but this has not not been tested yet. A NeXTStep implementation of multiple *************** *** 650,656 **** It may be possible to run on their V.1 system but changes in the s- file would be needed. ! Sun 1, 2 and 3 (m68k-sun-sunos, sparc-sun-sunos, i386-sun-sunos) Emacs runs on Sparcs and Sun 3's, as of version 19.7. --- 654,660 ---- It may be possible to run on their V.1 system but changes in the s- file would be needed. ! Sun 3, Sun 4 (sparc), Sun 386 (m68k-sun-sunos, sparc-sun-sunos, i386-sun-sunos) Emacs runs on Sparcs and Sun 3's, as of version 19.7. *************** *** 663,668 **** --- 667,680 ---- Use `m68k' for the 68000-based Sun boxes, `sparc' for Sparcstations, and `i386' for Sun Roadrunners. + On Solaris 2, you need to install patch 100947-02 to fix a system bug. + Presumably this patch comes from Sun. You must alter the definition of + LD_SWITCH_SYSTEM if your X11 libraries are not in /usr/openwin/lib. + + On Solaris 2, Emacs 19.12 currently expects certain optional packages + to be installed. You need libucb; you need termcap (which may be + part of libucb). This may be changed in the future. + There are three machine files for the different versions of SunOS that run on the Motorola 68000 processors. All are derived from Berkeley 4.2. Emacs 17 has run on all of them. *************** *** 875,880 **** --- 887,895 ---- think that POSIX requires this feature to fail. This is untrue; ptys are an extension, and POSIX says that extensions *when used* may change the action of standard facilities in any fashion. + + If you get compilation errors about wrong number of + arguments to getpgrp, define GETPGRP_NO_ARG. The standard C preprocessor may generate xmakefile incorrectly. However, /lib/cpp will work, so use `make CPP=/lib/cpp'. Standard cpp diff -crP -x *.elc -x *.info* emacs-19.11/etc/NEWS emacs-19.12/etc/NEWS *** emacs-19.11/etc/NEWS Tue Jun 1 00:36:55 1993 --- emacs-19.12/etc/NEWS Tue Jun 1 16:36:33 1993 *************** *** 1,10 **** ! GNU Emacs NEWS -- history of user-visible changes. 28 May 1993 Copyright (C) 1993 Free Software Foundation, Inc. See the end for copying conditions. Please send Emacs bug reports to bug-gnu-emacs@prep.ai.mit.edu. For older news, see the file ONEWS. For Lisp changes in Emacs 19, see the file LNEWS. Changes in version 19.11. --- 1,15 ---- ! GNU Emacs NEWS -- history of user-visible changes. 1 Jun 1993 Copyright (C) 1993 Free Software Foundation, Inc. See the end for copying conditions. Please send Emacs bug reports to bug-gnu-emacs@prep.ai.mit.edu. For older news, see the file ONEWS. For Lisp changes in Emacs 19, see the file LNEWS. + + Changes in version 19.12. + + * You can now make many of the sort commands ignore case by setting + `sort-fold-case' to a non-nil value. Changes in version 19.11. diff -crP -x *.elc -x *.info* emacs-19.11/lib-src/ChangeLog emacs-19.12/lib-src/ChangeLog *** emacs-19.11/lib-src/ChangeLog Tue Jun 1 04:29:30 1993 --- emacs-19.12/lib-src/ChangeLog Wed Jun 2 02:52:28 1993 *************** *** 1,3 **** --- 1,9 ---- + Wed Jun 2 02:50:10 1993 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * Version 19.12 released. + + * Makefile.in (all): Exclude INSTALLABLE_SCRIPTS and SCRIPTS from deps. + Tue Jun 1 04:07:00 1993 Richard Stallman (rms@mole.gnu.ai.mit.edu) * Version 19.11 released. diff -crP -x *.elc -x *.info* emacs-19.11/lib-src/Makefile.in emacs-19.12/lib-src/Makefile.in *** emacs-19.11/lib-src/Makefile.in Sun May 30 15:39:16 1993 --- emacs-19.12/lib-src/Makefile.in Wed Jun 2 02:51:56 1993 *************** *** 108,114 **** .c.o: ${CC} -c ${CPPFLAGS} ${ALL_CFLAGS} $< ! all: ${EXECUTABLES} ### Install the internal utilities. Until they are installed, we can ### just run them directly from lib-src. --- 108,114 ---- .c.o: ${CC} -c ${CPPFLAGS} ${ALL_CFLAGS} $< ! all: ${UTILITIES} ${INSTALLABLES} ### Install the internal utilities. Until they are installed, we can ### just run them directly from lib-src. diff -crP -x *.elc -x *.info* emacs-19.11/lisp/ChangeLog emacs-19.12/lisp/ChangeLog *** emacs-19.11/lisp/ChangeLog Tue Jun 1 04:29:05 1993 --- emacs-19.12/lisp/ChangeLog Tue Jun 1 18:26:55 1993 *************** *** 1,4 **** --- 1,67 ---- + Tue Jun 1 16:09:26 1993 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * Version 19.12 released. + + * reporter.el: New file. + + * mouse.el (mouse-buffer-menu): Don't select the event's window, + if event has frame instead. + + * tar-mode.el: Typo in autoload cookie. + + * shell.el (shell-prompt-pattern): Use defvar. + + * ange-ftp.el (ange-ftp-make-backup-files): Doc fix. + + * sendmail.el (mail-signature): Do not insert a line with `--'. + + * menu-bar.el (mouse-menu-bar-buffers): Renamed from mouse-buffer-menu. + + * subr.el (posn-timestamp): Doc fix. + + * sort.el (sort-fold-case): New variable. + (sort-subr): Bind case-fold-search from sort-fold-case. + + * simple.el (undo): + Pass proper arg to delete-auto-save-file-if-necessary. + + * desktop.el: New file. + + * c++-mode-1.el: New file. + + Tue Jun 1 16:03:30 1993 Ken Manheimer (klm@coil.nist.gov) + + * allout.el (move-to-column): Pass zero instead of negative arg. + Added some free variables defvars, so byte-comple doesn't complain. + Included some stub code, eventually will be proper use of Emacs 19 + minor-mode-sensitive keymaps. + + Tue Jun 1 14:01:25 1993 Stephen A. Wood (saw@cebaf.gov) + + * fortran.el (fortran-mode): Replace comment-indent-hook with + comment-indent-function. + + * fortran.el (fortran-is-in-string-p): Replaced with new version + that uses the syntax table. + + * fortran.el (calculate-fortran-indent): Lines that have a # after + whitespace are interpreted as cpp directives and outdented back to + column zero. + Tue Jun 1 00:27:03 1993 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * lucid.el (map-keymap): Doc fix. + + * dired-aux.el (dired-compress-file): Use gzip when proper/possible. + + * sc.el: Fix installation instructions. + (sc-cite-original): Add autoload cookie. + + * sendmail.el (mail-yank-hooks): New hook variable. + (mail-yank-original): Run the hook. + (mail-indent-citation): New function. + + * cl.el (cl-mod): Renamed from mod. * Version 19.11 released. diff -crP -x *.elc -x *.info* emacs-19.11/lisp/allout.el emacs-19.12/lisp/allout.el *** emacs-19.11/lisp/allout.el Thu May 27 23:00:58 1993 --- emacs-19.12/lisp/allout.el Tue Jun 1 17:10:53 1993 *************** *** 11,17 **** ;;;_ - Author: Ken Manheimer ;;;_ - Maintainer: Ken Manheimer ;;;_ - Created: Dec 1991 - first release to usenet ! ;;;_ - Version: $Id: allout.el,v 3.4 1993/05/27 19:24:19 klm Exp $|| ;;;_ - Keywords: outline mode ;;;_ - LCD Archive Entry --- 11,17 ---- ;;;_ - Author: Ken Manheimer ;;;_ - Maintainer: Ken Manheimer ;;;_ - Created: Dec 1991 - first release to usenet ! ;;;_ - Version: $Id: allout.el,v 3.5 1993/06/01 19:55:25 klm Exp $|| ;;;_ - Keywords: outline mode ;;;_ - LCD Archive Entry *************** *** 333,338 **** --- 333,385 ---- ;;;_ : Key bindings ;;;_ = Generic minor keybindings control + ;;;_ ; Stallmans suggestion + (defvar outline-mode-map nil "") + + (if outline-mode-map + nil + (setq outline-mode-map (nconc (make-sparse-keymap) text-mode-map)) + (define-key outline-mode-map "\C-c\C-n" 'outline-next-visible-heading) + (define-key outline-mode-map "\C-c\C-p" 'outline-previous-visible-heading) + (define-key outline-mode-map "\C-c\C-i" 'show-children) + (define-key outline-mode-map "\C-c\C-s" 'show-subtree) + (define-key outline-mode-map "\C-c\C-h" 'hide-subtree) + (define-key outline-mode-map "\C-c\C-u" 'outline-up-heading) + (define-key outline-mode-map "\C-c\C-f" 'outline-forward-same-level) + (define-key outline-mode-map "\C-c\C-b" 'outline-backward-same-level)) + + (defvar outline-minor-mode nil + "Non-nil if using Outline mode as a minor mode of some other mode.") + (make-variable-buffer-local 'outline-minor-mode) + (put 'outline-minor-mode 'permanent-local t) + (setq minor-mode-alist (append minor-mode-alist + (list '(outline-minor-mode " Outl")))) + + (defvar outline-minor-mode-map nil) + (if outline-minor-mode-map + nil + (setq outline-minor-mode-map (make-sparse-keymap)) + (define-key outline-minor-mode-map "\C-c" + (lookup-key outline-mode-map "\C-c"))) + + (or (assq 'outline-minor-mode minor-mode-map-alist) + (setq minor-mode-map-alist + (cons (cons 'outline-minor-mode outline-minor-mode-map) + minor-mode-map-alist))) + + (defun outline-minor-mode (&optional arg) + "Toggle Outline minor mode. + With arg, turn Outline minor mode on if arg is positive, off otherwise. + See the command `outline-mode' for more information on this mode." + (interactive "P") + (setq outline-minor-mode + (if (null arg) (not outline-minor-mode) + (> (prefix-numeric-value arg) 0))) + (if outline-minor-mode + (progn + (setq selective-display t) + (run-hooks 'outline-minor-mode-hook)) + (setq selective-display nil))) ;;;_ ; minor-bind-keys (keys-assoc) (defun minor-bind-keys (keys-assoc) " Establish BINDINGS assoc list in current buffer, returning a list *************** *** 413,419 **** (minor-relinquish-keys outline-minor-prior-keys) ) ! ;;;_ : Variables ;;;_ = outline-mode-prior-settings (defvar outline-mode-prior-settings nil "For internal use by outline mode, registers settings to be resumed --- 460,466 ---- (minor-relinquish-keys outline-minor-prior-keys) ) ! ;;;_ : Mode-Specific Variables Maintenance ;;;_ = outline-mode-prior-settings (defvar outline-mode-prior-settings nil "For internal use by outline mode, registers settings to be resumed *************** *** 678,684 **** ) ; defun ! ;;;_ #2 Internal State-Tracking Variables ;;; All basic outline functions which directly do string matches to ;;; evaluate heading prefix location set the variables ;;; outline-recent-prefix-beginning and outline-recent-prefix-end when --- 725,731 ---- ) ; defun ! ;;;_ #2 Internal Position State-Tracking Variables ;;; All basic outline functions which directly do string matches to ;;; evaluate heading prefix location set the variables ;;; outline-recent-prefix-beginning and outline-recent-prefix-end when *************** *** 1334,1339 **** --- 1381,1392 ---- match was concealed outside of search. The value is the location of the match, if it was concealed, regular if the entire topic was concealed, in a list if the entry was concealed.") + ;;;_ = outline-search-quitting + (defconst outline-search-quitting nil + "Variable used by isearch-terminate/outline-provisions and + isearch-done/outline-provisions to distinguish between a conclusion + and cancellation of a search.") + ;;;_ > outline-enwrap-isearch () (defun outline-enwrap-isearch () " Impose isearch-mode wrappers so isearch progressively exposes and *************** *** 1885,1890 **** --- 1938,1947 ---- ) ) ;;;_ > outline-rebullet-heading (&optional solicit ...) + (defvar current-bullet nil + "Variable local to outline-rebullet-heading,but referenced by + outline-make-topic-prefix, also. Should be resolved with explicitly + parameterized communication between the two, if suitable.") (defun outline-rebullet-heading (&optional solicit new-depth number-control *************** *** 1995,2001 **** (error "Attempt to shift topic below level 1")) (outline-rebullet-topic-grunt arg) (if (not (zerop arg)) (message "Shifting... done."))) ! (move-to-column (+ start-col arg))) ) ;;;_ > outline-rebullet-topic-grunt (&optional relative-depth ...) (defun outline-rebullet-topic-grunt (&optional relative-depth --- 2052,2058 ---- (error "Attempt to shift topic below level 1")) (outline-rebullet-topic-grunt arg) (if (not (zerop arg)) (message "Shifting... done."))) ! (move-to-column (max 0 (+ start-col arg)))) ) ;;;_ > outline-rebullet-topic-grunt (&optional relative-depth ...) (defun outline-rebullet-topic-grunt (&optional relative-depth *************** *** 2369,2379 **** ) ) ) ! ;;;_ ; Bizarreness - ignore this! ;------------------------------------------------------------------- ; Something added solely for use by a "smart menu" package someone got ; off the net. I have no idea whether this is appropriate code. (defun outline-to-entry-end (&optional include-sub-entries curr-entry-level) " Go to end of whole entry if optional INCLUDE-SUB-ENTRIES is non-nil. CURR-ENTRY-LEVEL is an integer representing the length of the current level --- 2426,2437 ---- ) ) ) ! ;;;_ > outline-to-entry-end - Unmaintained compatability - ignore this! ;------------------------------------------------------------------- ; Something added solely for use by a "smart menu" package someone got ; off the net. I have no idea whether this is appropriate code. + (defvar next-entry-exists nil "Used by outline-to-entry-end, dunno why.") (defun outline-to-entry-end (&optional include-sub-entries curr-entry-level) " Go to end of whole entry if optional INCLUDE-SUB-ENTRIES is non-nil. CURR-ENTRY-LEVEL is an integer representing the length of the current level diff -crP -x *.elc -x *.info* emacs-19.11/lisp/ange-ftp.el emacs-19.12/lisp/ange-ftp.el *** emacs-19.11/lisp/ange-ftp.el Sat May 29 00:30:18 1993 --- emacs-19.12/lisp/ange-ftp.el Tue Jun 1 17:20:44 1993 *************** *** 1,7 **** ;;; ange-ftp.el --- transparent FTP support for GNU Emacs ;;; Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. - ;;; ??? Waiting for papers from several people. ;;; ;; Author: Andy Norman (ange@hplb.hpl.hp.com) ;; Keywords: comm --- 1,6 ---- *************** *** 781,789 **** "*If non-NIL then a string naming nslookup program." ) (defvar ange-ftp-make-backup-files () ! "*A list of operating systems for which ange-ftp will make Emacs backup ! files files on the remote host. For example, '\(unix\) makes sense, but ! '\(unix vms\) or '\(vms\) would be silly, since vms makes its own backups.") (defvar ange-ftp-retry-time 5 "*Number of seconds to wait before retrying if a file or listing --- 780,786 ---- "*If non-NIL then a string naming nslookup program." ) (defvar ange-ftp-make-backup-files () ! "*Non-nil means make backup files for \"magic\" remote files.") (defvar ange-ftp-retry-time 5 "*Number of seconds to wait before retrying if a file or listing *************** *** 859,865 **** ;;;; Internal variables. ;;;; ------------------------------------------------------------ ! (defconst ange-ftp-version "$Revision: 1.19 $") (defvar ange-ftp-data-buffer-name " *ftp data*" "Buffer name to hold directory listing data received from ftp process.") --- 856,862 ---- ;;;; Internal variables. ;;;; ------------------------------------------------------------ ! (defconst ange-ftp-version "$Revision: 1.21 $") (defvar ange-ftp-data-buffer-name " *ftp data*" "Buffer name to hold directory listing data received from ftp process.") diff -crP -x *.elc -x *.info* emacs-19.11/lisp/c++-mode-1.el emacs-19.12/lisp/c++-mode-1.el *** emacs-19.11/lisp/c++-mode-1.el --- emacs-19.12/lisp/c++-mode-1.el Tue Jun 1 16:11:14 1993 *************** *** 0 **** --- 1,2736 ---- + ;;; c++-mode.el --- major mode for editing C++ (and C) code + + ;; Author: 1992 Barry A. Warsaw, Century Computing Inc. + ;; 1987 Dave Detlefs and Stewart Clamen + ;; 1985 Richard M. Stallman + ;; Maintainer: c++-mode-help@anthem.nlm.nih.gov + ;; Created: a long, long, time ago. adapted from the original c-mode.el + ;; Version: 2.334 + ;; Last Modified: 1993/06/01 14:58:00 + ;; Keywords: C++ C editing major-mode + + ;; Copyright (C) 1992, 1993 Free Software Foundation, Inc. + + ;; 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, 675 Mass Ave, Cambridge, MA 02139, USA. + + ;; Introduction + ;; ============ + ;; Do a "C-h m" in a c++-mode buffer for more information on + ;; customizing c++-mode. To submit bug reports hit "C-c C-b" in a + ;; c++-mode buffer. This runs the command c++-submit-bug-report and + ;; automatically sets up the mail buffer with all the necessary + ;; information. If you have other questions contact me at the + ;; following address: c++-mode-help@anthem.nlm.nih.gov. Please don't + ;; send bug reports to my personal account, I may not get it for a + ;; long time. + + ;; Notes for Novice Users + ;; ====================== + ;; c++-mode facilitates editing of C++ code by automatically handling + ;; the indentation of lines of code in a manner very similar to c-mode + ;; as distributed with GNU emacs. Refer to the GNU Emacs manual, + ;; chapter 21 for more information on "Editing Programs". In fact, + ;; c++-mode (through its companion mode entry point c++-c-mode) can + ;; also be used to edit both K&R and ANSI C code! + ;; + ;; To use c++-mode, add the following to your .emacs file. This + ;; assumes you will use .cc or .C extensions for your C++ source: + ;; + ;; (autoload 'c++-mode "c++-mode" "C++ Editing Mode" t) + ;; (autoload 'c++-c-mode "c++-mode" "C Editing Mode" t) + ;; (setq auto-mode-alist + ;; (append '(("\\.C$" . c++-mode) + ;; ("\\.cc$" . c++-mode) + ;; ("\\.c$" . c++-c-mode) ; to edit C code + ;; ("\\.h$" . c++-c-mode) ; to edit C code + ;; ) auto-mode-alist)) + ;; + ;; If you want to use the default c-mode for editing C code, then just + ;; omit the lines marked "to edit C code". + ;; + ;; Finally, you may want to customize certain c++-mode variables. The + ;; best place to do this is in the mode hook variable called + ;; c++-mode-hook. Again, see the Emacs manual, chapter 21 for more + ;; information. + + ;; Important Note about Escapes in Comments, and Performance + ;; ========================================================= + ;; You may notice that certain characters, when typed in comment + ;; regions, get escaped with a backslash. This is a workaround for + ;; bugs in emacs' syntax parsing algorithms. In brief, syntax parsing + ;; in emacs 18 and derivatives is broken because syntax tables are not + ;; rich enough to support more than 1 comment style per mode (as C++ + ;; requires). The result is that emacs will sometimes choke on + ;; unbalanced parentheses and single quotes in comments. Please do a + ;; "C-h v c++-untame-characters" for more information. + ;; + ;; This problem affect both the accuracy and performance of c++-mode + ;; because some parsing must be performed in elisp instead of relying + ;; on the C primitives. In general, I've chosen accuracy over + ;; performance, but have worked hard to give moderately acceptable + ;; speed in all but the most uncommon situations. You will most likely + ;; notice c++-mode slowing when you're editing a file of preprocessor + ;; commands, or inside long functions or class definitions. + ;; Optimization is an ongoing concern, but the real solution is to fix + ;; emacs. + ;; + ;; As of release 19.4, Lucid Emacs is distributed with the fixes in + ;; place, and c++-mode will automatically take advantage of them so + ;; none of the above applies to you. Similar patches will be part of + ;; GNU Emacs 19. Some patches for GNU emacs 18 have been released on + ;; the beta site, but they are unsupported. Email for more + ;; information. + + ;; Beta Testers Mailing List + ;; ========================= + ;; Want to be a c++-mode victim, er, beta-tester? Send add/drop + ;; requests to c++-mode-victims-request@anthem.nlm.nih.gov. + ;; Discussions go to c++-mode-victims@anthem.nlm.nih.gov, but bug + ;; reports and such should still be sent to c++-mode-help only. + ;; + ;; Many, many thanks go out to all the folks on the beta test list. + ;; Without their patience, testing, insight, and code contribution, + ;; c++-mode.el would be a far inferior package. + + ;; Getting c++-mode.el + ;; =================== + ;; The latest public release version of this file should always be + ;; available for anonymous ftp on the elisp archive machine. The path + ;; to the file is: + ;; + ;; archive.cis.ohio-state.edu:pub/gnu/emacs/elisp-archive/modes/c++-mode.el.Z + ;; + ;; For those of you without anon-ftp access, you can use the DEC's + ;; ftpmail'er at the address ftpmail@decwrl.dec.com. Send the + ;; following message in the body of your mail to that address to get + ;; c++-mode: + ;; + ;; reply + ;; connect archive.cis.ohio-state.edu + ;; binary + ;; uuencode + ;; chdir pub/gnu/emacs/elisp-archive/modes + ;; get c++-mode.el.Z + ;; + ;; or just send the message "help" for more information on ftpmail. + ;; Response times will vary with the number of requests in the queue. + + ;; LCD Archive Entry: + ;; c++-mode|Barry A. Warsaw|c++-mode-help@anthem.nlm.nih.gov + ;; |Mode for editing C++, and ANSI/K&R C code (was Detlefs' c++-mode.el) + ;; |1993/06/01 14:58:00|2.334| + + ;;; Code: + + ;; some people may not have c-mode loaded in by default. c++-mode.el + ;; unfortunately still depends on distrib c-mode. c-mode doesn't + ;; provide itself so this hack is best known way to ensure its loaded + (or (fboundp 'c-mode) + (load "c-mode" nil t)) + + + ;; ====================================================================== + ;; user definable variables + ;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + + (defconst c++-emacs-features + (let ((mse-spec 'no-dual-comments) + (scanner 'v18)) + ;; vanilla GNU18/Epoch 4 uses default values + (if (= 8 (length (parse-partial-sexp (point) (point)))) + ;; we know we're using v19 style dual-comment specifications. + ;; All Lemacsen use 8-bit modify-syntax-entry flags, as do all + ;; patched GNU19, GNU18, Epoch4's. Only vanilla GNU19.7-8 + ;; uses 1-bit flag. Lets be as smart as we can about figuring + ;; this out. + (let ((table (copy-syntax-table))) + (modify-syntax-entry ?a ". 12345678" table) + (if (= (logand (lsh (aref table ?a) -16) 255) 255) + (setq mse-spec '8-bit) + (setq mse-spec '1-bit)) + ;; we also know we're using a quicker, built-in comment + ;; scanner, but we don't know if its old-style or new. + ;; Fortunately we can ask emacs directly + (if (fboundp 'forward-comment) + (setq scanner 'v19) + (setq scanner 'old-v19)))) + ;; now cobble up the necessary list + (list mse-spec scanner)) + "A list of needed features extant in the emacs you are using. + There are many flavors of emacs out on the net, each with different + features supporting those needed by c++-mode. Here's the current + known list, along with the values for this variable: + + Vanilla GNU 18/Epoch 4: (no-dual-comments v18) + GNU 18/Epoch 4 (patch1): (8-bit old-v19) + GNU 18/Epoch 4 (patch2): (8-bit v19) + Lemacs 19.4 - 19.6: (8-bit old-v19) + Lemacs 19.7 and over: (8-bit v19) + GNU 19: (1-bit v19) + GNU 19 (patched): (8-bit v19)") + + (defvar c++-mode-abbrev-table nil + "Abbrev table in use in C++-mode buffers.") + (define-abbrev-table 'c++-mode-abbrev-table ()) + + (defvar c++-mode-map () + "Keymap used in C++ mode.") + (if c++-mode-map + () + (setq c++-mode-map (make-sparse-keymap)) + (define-key c++-mode-map "\C-j" 'reindent-then-newline-and-indent) + (define-key c++-mode-map "{" 'c++-electric-brace) + (define-key c++-mode-map "}" 'c++-electric-brace) + (define-key c++-mode-map ";" 'c++-electric-semi) + (define-key c++-mode-map "#" 'c++-electric-pound) + (define-key c++-mode-map "\e\C-h" 'mark-c-function) + (define-key c++-mode-map "\e\C-q" 'c++-indent-exp) + (define-key c++-mode-map "\t" 'c++-indent-command) + (define-key c++-mode-map "\C-c\C-i" 'c++-insert-header) + (define-key c++-mode-map "\C-c\C-\\" 'c++-macroize-region) + (define-key c++-mode-map "\C-c\C-c" 'c++-comment-region) + (define-key c++-mode-map "\C-c\C-u" 'c++-uncomment-region) + (define-key c++-mode-map "\C-c\C-x" 'c++-match-paren) + (define-key c++-mode-map "\e\C-a" 'c++-beginning-of-defun) + (define-key c++-mode-map "\e\C-e" 'c++-end-of-defun) + (define-key c++-mode-map "\e\C-x" 'c++-indent-defun) + (define-key c++-mode-map "/" 'c++-electric-slash) + (define-key c++-mode-map "*" 'c++-electric-star) + (define-key c++-mode-map ":" 'c++-electric-colon) + (define-key c++-mode-map "\177" 'c++-electric-delete) + (define-key c++-mode-map "\C-c\C-t" 'c++-toggle-auto-hungry-state) + (define-key c++-mode-map "\C-c\C-h" 'c++-toggle-hungry-state) + (define-key c++-mode-map "\C-c\C-a" 'c++-toggle-auto-state) + (if (memq 'v18 c++-emacs-features) + (progn + (define-key c++-mode-map "\C-c'" 'c++-tame-comments) + (define-key c++-mode-map "'" 'c++-tame-insert) + (define-key c++-mode-map "[" 'c++-tame-insert) + (define-key c++-mode-map "]" 'c++-tame-insert) + (define-key c++-mode-map "(" 'c++-tame-insert) + (define-key c++-mode-map ")" 'c++-tame-insert))) + (define-key c++-mode-map "\C-c\C-b" 'c++-submit-bug-report) + (define-key c++-mode-map "\C-c\C-v" 'c++-version) + ;; these are necessary because default forward-sexp and + ;; backward-sexp don't automatically let-bind + ;; parse-sexp-ignore-comments, which is needed for them to work + ;; properly in a C++ buffer. + (define-key c++-mode-map "\e\C-f" 'c++-forward-sexp) + (define-key c++-mode-map "\e\C-b" 'c++-backward-sexp) + ) + + (defvar c++-mode-syntax-table nil + "Syntax table used in c++-mode buffers.") + (defvar c++-c-mode-syntax-table nil + "Syntax table used in c++-c-mode buffers.") + + (if c++-mode-syntax-table + () + (setq c++-mode-syntax-table (make-syntax-table)) + (modify-syntax-entry ?\\ "\\" c++-mode-syntax-table) + (modify-syntax-entry ?+ "." c++-mode-syntax-table) + (modify-syntax-entry ?- "." c++-mode-syntax-table) + (modify-syntax-entry ?= "." c++-mode-syntax-table) + (modify-syntax-entry ?% "." c++-mode-syntax-table) + (modify-syntax-entry ?< "." c++-mode-syntax-table) + (modify-syntax-entry ?> "." c++-mode-syntax-table) + (modify-syntax-entry ?& "." c++-mode-syntax-table) + (modify-syntax-entry ?| "." c++-mode-syntax-table) + (modify-syntax-entry ?\' "\"" c++-mode-syntax-table) + ;; comment syntax + (cond + ((memq '8-bit c++-emacs-features) + ;; Lucid emacs has the best implementation + (modify-syntax-entry ?/ ". 1456" c++-mode-syntax-table) + (modify-syntax-entry ?* ". 23" c++-mode-syntax-table) + (modify-syntax-entry ?\n "> b" c++-mode-syntax-table)) + ((memq '1-bit c++-emacs-features) + ;; GNU19 has sub-optimal, but workable implementation + ;; Some strange behavior may be encountered. LOBBY FSF! + (modify-syntax-entry ?/ ". 124" c++-mode-syntax-table) + (modify-syntax-entry ?* ". 23b" c++-mode-syntax-table) + (modify-syntax-entry ?\n ">" c++-mode-syntax-table)) + (t + ;; Vanilla GNU18 is just plain busted. We'll do the best we can, + ;; but some strange behavior may be encountered. PATCH or UPGRADE! + (modify-syntax-entry ?/ ". 124" c++-mode-syntax-table) + (modify-syntax-entry ?* ". 23" c++-mode-syntax-table) + (modify-syntax-entry ?\n ">" c++-mode-syntax-table)) + )) + + (if c++-c-mode-syntax-table + () + (setq c++-c-mode-syntax-table (make-syntax-table)) + (modify-syntax-entry ?\\ "\\" c++-c-mode-syntax-table) + (modify-syntax-entry ?+ "." c++-c-mode-syntax-table) + (modify-syntax-entry ?- "." c++-c-mode-syntax-table) + (modify-syntax-entry ?= "." c++-c-mode-syntax-table) + (modify-syntax-entry ?% "." c++-c-mode-syntax-table) + (modify-syntax-entry ?< "." c++-c-mode-syntax-table) + (modify-syntax-entry ?> "." c++-c-mode-syntax-table) + (modify-syntax-entry ?& "." c++-c-mode-syntax-table) + (modify-syntax-entry ?| "." c++-c-mode-syntax-table) + (modify-syntax-entry ?\' "\"" c++-c-mode-syntax-table) + (modify-syntax-entry ?/ ". 14" c++-c-mode-syntax-table) + (modify-syntax-entry ?* ". 23" c++-c-mode-syntax-table) + ) + + (defvar c++-tab-always-indent + (if (boundp 'c-tab-always-indent) c-tab-always-indent t) + "*Controls the operation of the TAB key. + If t (the default), always just indent the current line. If nil, + indent the current line only if point is at the left margin or in the + line's indentation; otherwise insert a tab. If not-nil-or-t, then tab + is inserted only within literals (comments and strings) and inside + preprocessor directives, but line is always reindented.") + (defvar c++-always-arglist-indent-p nil + "*Control indentation of continued arglists. + When non-nil, arglists continued on subsequent lines will always + indent c++-empty-arglist-indent spaces, otherwise, they will indent to + just under previous line's argument indentation.") + (defvar c++-block-close-brace-offset 0 + "*Extra indentation given to close braces which close a block. This + does not affect braces which close a top-level construct (e.g. function).") + (defvar c++-paren-as-block-close-p nil + "*Treat a parenthesis which is the first non-whitespace on a line as + a paren which closes a block. When non-nil, c-indent-level is + subtracted, and c++-block-close-brace-offset is added to the line's + offset.") + (defvar c++-continued-member-init-offset nil + "*Extra indent for continuation lines of member inits; nil means to align + with previous initializations rather than with the colon on the first line.") + (defvar c++-member-init-indent 0 + "*Indentation level of member initializations in function declarations.") + (defvar c++-friend-offset -4 + "*Offset of C++ friend class declarations relative to member declarations.") + (defvar c++-access-specifier-offset c-label-offset + "*Extra indentation given to public, protected, and private labels.") + (defvar c++-empty-arglist-indent nil + "*Indicates how far to indent a line following an empty argument list. + Nil means indent to just after the paren.") + (defvar c++-comment-only-line-offset 0 + "*Indentation offset for line which contains only C or C++ style comments. + This variable can take either a single integer or a list of integers. + If a single integer this is the extra indentation offset to apply to + all comment-only lines, except those which start in column zero. If a + list is used, the first integer is for all non-column-zero + comment-only lines and the second integer is for all column-zero + lines. You can also use a list containing only 1 integer, in which + case, this value is used for all comment-only lines. For example: + + value meaning + ===== ======= + 0 comment-only lines do not indent + 4 non-col0 lines indent 4 spaces, col0 lines don't indent + '(4) all comment-only lines indent 4 spaces + '(4 1) non-col0 lines indent 4 spaces, col0 lines indent 1 space") + + (defvar c++-C-block-comments-indent-p nil + "*4 styles of C block comments are supported. If this variable is nil, + then styles 1-3 are supported. If this variable is non-nil, style 4 is + supported. + style 1: style 2: style 3: style 4: + /* /* /* /* + blah * blah ** blah blah + blah * blah ** blah blah + */ */ */ */ + ") + (defvar c++-cleanup-list nil + "*List of various C++ constructs to \"clean up\". + These cleanups only take place when the auto-newline feature is turned + on, as evidenced by the `/a' or `/ah' appearing next to the mode name. + + Current legal values are: + brace-else-brace -- clean up \"} else {\" constructs by placing entire + construct on a single line. This cleanup only + takes place when there is nothing but white + space between the braces and the else. + empty-defun-braces -- cleans up empty C++ function braces by + placing them on the same line. + defun-close-semi -- cleans up the terminating semi-colon on class + definitions and functions by placing the semi + on the same line as the closing brace.") + (defvar c++-hanging-braces t + "*Controls the insertion of newlines before open (left) braces. + This variable only has effect when auto-newline is on, as evidenced by + the `/a' or `/ah' appearing next to the mode name. If nil, open + braces do not hang (i.e. a newline is inserted before all open + braces). If t, all open braces hang -- no newline is inserted before + open braces. If not nil or t, newlines are only inserted before + top-level open braces; all other braces hang.") + (defvar c++-hanging-member-init-colon 'before + "*Defines how colons which introduce member initializations are formatted. + Legal values are: + t -- no newlines inserted before or after colon + nil -- newlines inserted before and after colon + 'after -- newlines inserted only after colon + 'before -- newlines inserted only before colon") + (defvar c++-auto-hungry-initial-state 'none + "*Initial state of auto/hungry features when buffer is first visited. + Legal values are: + 'none -- no auto-newline and no hungry-delete-key. + 'auto-only -- auto-newline, but no hungry-delete-key. + 'hungry-only -- no auto-newline, but hungry-delete-key. + 'auto-hungry -- both auto-newline and hungry-delete-key enabled. + Nil is synonymous for 'none and t is synonymous for 'auto-hungry.") + + (defvar c++-auto-hungry-toggle t + "*Enable/disable toggling of auto/hungry features. + Legal values are: + 'none -- auto-newline and hungry-delete-key cannot be enabled. + 'auto-only -- only auto-newline feature can be toggled. + 'hungry-only -- only hungry-delete-key feature can be toggled. + 'auto-hungry -- both auto-newline and hungry-delete-key can be toggled. + Nil is synonymous for 'none and t is synonymous for 'auto-hungry.") + + (defvar c++-relative-offset-p t + "*Control the calculation for indentation. + When non-nil (the default), indentation is calculated relative to the + first statement in the block. When nil, the indentation is calculated + without regard to how the first statement is indented.") + + (defvar c++-untame-characters (and (memq 'v18 c++-emacs-features) '(?\')) + "*Utilize a backslashing workaround of an emacs syntax parsing bug. + If non-nil, this variable should contain a list of characters which + will be prepended by a backslash in comment regions. By default, the + list contains only the most troublesome character, the single quote. + To be completely safe, set this variable to: + + '(?\( ?\) ?\' ?\{ ?\} ?\[ ?\]) + + This is the full list of characters which can potentially cause + problems if they exist unbalanced within comments. Setting this + variable to nil will defeat this feature, but be forewarned! Such + un-escaped characters in comment regions can potentially break many + things such as some indenting and blinking of parenthesis. + + Note further that only the default set of characters will be escaped + automatically as they are typed. But, executing c++-tame-comments + (\\[c++-tame-comments]) will escape all characters which are members + of this set, and which are found in comments throughout the file. + + Finally, c++-mode can tell if you're running a patched emacs. If so, + taming characters isn't necessary and this variable is automatically + set to nil.") + + (defvar c++-default-macroize-column 78 + "*Column to insert backslashes.") + (defvar c++-special-indent-hook nil + "*Hook for user defined special indentation adjustments. + This hook gets called after a line is indented by the mode. By + supplying a hook, you can make adjustments to the line's standard + indentation. If you do use this hook, you will likely need to also + set c++-relative-offset-p to nil. The call to this hook is wrapped in + a save-excursion so you don't need to worry about restoring point and + mark inside the hook function.") + (defvar c++-delete-function 'backward-delete-char-untabify + "*Function called by c++-electric-delete when deleting a single char.") + (defvar c++-electric-pound-behavior nil + "*List of behaviors for electric pound insertion. + Only currently supported behavior is '(alignleft).") + (defvar c++-backscan-limit 2000 + "*Limit in characters for looking back while skipping syntactic ws. + If you typically write really big methods, and start noticing + incorrect indentations, try cranking this value up. The larger this + value is, though, the slower parts of c++-mode can become. Setting + this variable to nil defeats backscan limits.") + + ;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ;; NO USER DEFINABLE VARIABLES BEYOND THIS POINT + ;; + (defvar c++-hungry-delete-key nil + "Internal state of hungry delete key feature.") + (defvar c++-auto-newline nil + "Internal state of auto newline feature.") + + (make-variable-buffer-local 'c++-auto-newline) + (make-variable-buffer-local 'c++-hungry-delete-key) + + (defconst c++-access-key "\\<\\(public\\|protected\\|private\\)\\>:" + "Regexp which describes access specification keywords.") + (defconst c++-class-key + (concat + "\\(\\(extern\\|typedef\\)\\s +\\)?" + "\\(template\\s *<[^>]*>\\s *\\)?" + "\\<\\(class\\|struct\\|union\\)\\>") + "Regexp which describes a class declaration, including templates.") + (defconst c++-inher-key + (concat "\\(\\\\s +\\)?" + c++-class-key + "[ \t]+\\(\\(\\w\\|_\\)+[ \t]*:[ \t]*\\)?") + "Regexp which describes a class inheritance declaration.") + + + ;; ====================================================================== + ;; c++-mode main entry point + ;; ====================================================================== + (defun c++-mode () + "Major mode for editing C++ code. 2.334 + To submit a bug report, enter \"\\[c++-submit-bug-report]\" + from a c++-mode buffer. + + 1. Very much like editing C code, + 2. Expression and list commands understand all C++ brackets, + 3. Tab at left margin indents for C++ code, + 4. Both C++ and C style block comments are recognized, + 5. Paragraphs are separated by blank lines only, + 6. Hungry delete key and auto newline features are optional. + + IMPORTANT NOTE: You may notice that some characters (by default, only + single quote) will get escaped with a backslash when typed in a + comment region. This is a necessary workaround of a bug present in + GNU emacs 18 and derivatives. Enter \"\\[describe-variable] c++-untame-characters RET\" + for more information. If you are running a patched emacs, no + characters will be escaped in comment regions, and many functions will + run much faster. + + Key bindings: + \\{c++-mode-map} + + These variables control indentation style. Those with names like + c- are inherited from c-mode. Those with names like + c++- are unique for this mode, or have extended functionality + from their c-mode cousins. + + c-argdecl-indent + Indentation level of declarations of C function arguments. + c-brace-imaginary-offset + An open brace following other text is treated as if it were + this far to the right of the start of its line. + c-brace-offset + Extra indentation for line if it starts with an open brace. + c-continued-brace-offset + Extra indentation given to a brace that starts a substatement. + This is in addition to c-continued-statement-offset. + c-continued-statement-offset + Extra indentation given to a substatement, such as the + then-clause of an if or body of a while. + c-indent-level + Indentation of C statements within surrounding block. + The surrounding block's indentation is the indentation + of the line on which the open-brace appears. + c-label-offset + Extra indentation for line that is a label, or case or ``default:'' + + c++-C-block-comments-indent-p + Style of C block comments to support. + c++-access-specifier-offset + Extra indentation given to public, protected, and private keyword lines. + c++-always-arglist-indent-p + Control indentation of continued arglists. When non-nil, arglists + continued on subsequent lines will always indent + c++-empty-arglist-indent spaces, otherwise, they will indent to + just under previous line's argument indentation. + c++-auto-hungry-initial-state + Initial state of auto/hungry feature when a C++ buffer is first visited. + c++-auto-hungry-toggle + Enable/disable toggling of auto/hungry features. + c++-backscan-limit + Limit in characters for looking back while skipping syntactic + whitespace. This variable is only used in an un-patched emacs to + help improve performance at the expense of some accuracy. Patched + emacses are both fast and accurate. + c++-block-close-brace-offset + Extra indentation give to braces which close a block. This does + not affect braces which close top-level constructs (e.g. functions). + c++-cleanup-list + A list of construct \"clean ups\" which c++-mode will perform when + auto-newline feature is on. Current legal values are: + brace-else-brace, empty-defun-braces, defun-close-semi. + c++-comment-only-line-offset + Extra indentation for a line containing only a C or C++ style + comment. Can be an integer or list, specifying the various styles + of comment-only line special indentations. + c++-continued-member-init-offset + Extra indentation for continuation lines of member initializations; nil + means to align with previous initializations rather than with the colon. + c++-default-macroize-column + Column to insert backslashes when macroizing a region. + c++-delete-function + Function called by c++-electric-delete when deleting a single char. + c++-electric-pound-behavior + List of behaviors for electric pound insertion. + c++-empty-arglist-indent + Extra indentation to apply to a line following an empty argument + list. nil means to line it up with the left paren. + c++-friend-offset + Offset of C++ friend class declarations relative to member declarations. + c++-hanging-braces + Controls open brace hanging behavior when using auto-newline feature. + nil says no braces hang, t says all open braces hang. non-nil-or-t + means top-level open braces don't hang, all others do. + c++-hanging-member-init-colon + Defines how colons which introduce member initialization lists are + formatted. t means no newlines are inserted either before or after + the colon. nil means newlines are inserted both before and after + the colon. 'before inserts newlines only before the colon, and + 'after inserts newlines only after colon. + c++-member-init-indent + Indentation level of member initializations in function declarations, + if they are on a separate line beginning with a colon. + c++-paren-as-block-close-p + If non-nil, treat a parenthesis which is the first non-whitespace + on a line as a paren whcih closes a block (i.e. treat it similar + to right curly brace) + c++-relative-offset-p + Control the calculation for indentation. When non-nil (the + default), indentation is calculated relative to the first + statement in the block. When nil, the indentation is calculated + without regard to how the first statement is indented. Useful when + using a c++-special-indent-hook. + c++-special-indent-hook + Hook for user defined special indentation adjustments. You can use + this hook, which gets called after a line is indented by the mode, + to customize indentations of the line. + c++-tab-always-indent + Controls the operation of the TAB key. t means always just indent + the current line. nil means indent the current line only if point + is at the left margin or in the line's indentation; otherwise + insert a tab. If not-nil-or-t, then tab is inserted only within + literals (comments and strings) and inside preprocessor + directives, but the line is always reindented. Default is value + for c-tab-always-indent. + c++-untame-characters + When non-nil, inserts backslash escapes before certain untamed + characters in comment regions. It is recommended that you keep the + default setting to workaround a nasty emacs bug, unless you are + running a patched emacs. + + Auto-newlining is no longer an all or nothing proposition. In my + opinion, I don't believe it is possible to implement a perfect + auto-newline algorithm. Sometimes you want it and sometimes you don't. + So now auto-newline (and its companion feature, hungry-delete-key) can + be toggled on and off on the fly. Hungry-delete-key is the optional + behavior of the delete key so that, when enabled, hitting the delete + key once consumes all preceeding whitespace, unless point is within a + literal (defined as a C or C++ comment, or string). Inside literals, + and with hungry-delete-key disabled, the delete key just calls the + function in variable c++-delete-function. + + Selection and toggling of these features is controlled by the + variables c++-auto-hungry-initial-state and c++-auto-hungry-toggle. + Legal values for both variables are: + + 'none (or nil) -- no auto-newline or hungry-delete-key. + 'auto-only -- function affects only auto-newline feature. + 'hungry-only -- function affects only hungry-delete-key feature. + 'auto-hungry (or t) -- function affects both features. + + Thus if c++-auto-hungry-initial-state is 'hungry-only, then only + hungry-delete-key feature is turned on when the buffer is first + visited. If c++-auto-hungry-toggle is 'auto-hungry, and both + auto-newline and hungry-delete-key features are on, then hitting + \"\\[c++-toggle-auto-hungry-state]\" will toggle both features. + Hitting \"\\[c++-toggle-hungry-state]\" will always toggle + hungry-delete-key feature and hitting \"\\[c++-toggle-auto-state]\" + will always toggle auto-newline feature, regardless of the value of + c++-auto-hungry-toggle. + + Settings for K&R, BSD, and Stroustrup indentation styles are + c-indent-level 5 8 4 + c-continued-statement-offset 5 8 4 + c-continued-brace-offset 0 + c-brace-offset -5 -8 0 + c-brace-imaginary-offset 0 + c-argdecl-indent 0 8 4 + c-label-offset -5 -8 -4 + c++-access-specifier-offset -5 -8 -4 + c++-empty-arglist-indent 4 + c++-friend-offset 0 + + Turning on C++ mode calls the value of the variable c++-mode-hook with + no args, if that value is non-nil. + + Report bugs by entering \"\\[c++-submit-bug-report]\". This + automatically sets up a mail buffer with version information already + added. You just need to add a description of the problem and send the + message." + (interactive) + (kill-all-local-variables) + (use-local-map c++-mode-map) + (set-syntax-table c++-mode-syntax-table) + (setq major-mode 'c++-mode + mode-name "C++" + local-abbrev-table c++-mode-abbrev-table) + (set (make-local-variable 'paragraph-start) (concat "^$\\|" page-delimiter)) + (set (make-local-variable 'paragraph-separate) paragraph-start) + (set (make-local-variable 'paragraph-ignore-fill-prefix) t) + (set (make-local-variable 'require-final-newline) t) + (set (make-local-variable 'parse-sexp-ignore-comments) nil) + ;; + (set (make-local-variable 'indent-line-function) 'c++-indent-line) + (set (make-local-variable 'comment-start) "// ") + (set (make-local-variable 'comment-end) "") + (set (make-local-variable 'comment-column) 32) + (set (make-local-variable 'comment-start-skip) "/\\*+ *\\|// *") + (set (make-local-variable 'comment-indent-hook) 'c++-comment-indent) + ;; hack auto-hungry designators into mode-line-format + (if (listp mode-line-format) + (setq mode-line-format + (let ((modeline nil)) + (mapcar + (function + (lambda (element) + (setq modeline + (append modeline + (if (eq element 'mode-name) + '(mode-name (c++-hungry-delete-key + (c++-auto-newline "/ah" "/h") + (c++-auto-newline "/a"))) + (list element)))))) + mode-line-format) + modeline))) + (run-hooks 'c++-mode-hook) + (c++-set-auto-hungry-state + (memq c++-auto-hungry-initial-state '(auto-only auto-hungry t)) + (memq c++-auto-hungry-initial-state '(hungry-only auto-hungry t)))) + + (defun c++-c-mode () + "Major mode for editing K&R and ANSI C code. 2.334 + This mode is based on c++-mode. Documentation for this mode is + available by doing a \"\\[describe-function] c++-mode\"." + (interactive) + (c++-mode) + (setq major-mode 'c++-c-mode + mode-name "C" + local-abbrev-table c-mode-abbrev-table) + (setq comment-start "/* " + comment-end " */") + ;; some syntax differences are necessary for C vs. C++ + (set-syntax-table c++-c-mode-syntax-table) + (run-hooks 'c++-c-mode-hook)) + + (defun c++-comment-indent () + "Used by indent-for-comment to decide how much to indent a comment + in C++ code based on its context." + (if (looking-at "^\\(/\\*\\|//\\)") + 0 ; Existing comment at bol stays there. + (save-excursion + (skip-chars-backward " \t") + (max + ;; leave at least one space on non-empty lines. + (if (zerop (current-column)) + 0 + (1+ (current-column))) + ;; use comment-column if previous line is comment only line + ;; indented to the left of comment-column + (save-excursion + (beginning-of-line) + (if (not (bobp)) (forward-line -1)) + (skip-chars-forward " \t") + (if (looking-at "/\\*\\|//") + (if (< (current-column) comment-column) + comment-column + (current-column)) + 0)) + (let ((cur-pt (point))) + (beginning-of-line 0) + ;; If previous line had a comment, use it's indent + (if (re-search-forward comment-start-skip cur-pt t) + (progn + (goto-char (match-beginning 0)) + (current-column)) + comment-column)))))) ; otherwise indent at comment column. + + + ;; ====================================================================== + ;; most command level (interactive) and related + ;; ====================================================================== + (defun c++-set-auto-hungry-state (auto-p hungry-p) + "Set auto/hungry to state indicated by AUTO-P and HUNGRY-P. + Update mode line to indicate state to user." + (setq c++-auto-newline auto-p + c++-hungry-delete-key hungry-p) + (set-buffer-modified-p (buffer-modified-p))) + + (defun c++-toggle-auto-state (arg) + "Toggle auto-newline feature. + This function ignores c++-auto-hungry-toggle variable. Optional + numeric ARG, if supplied turns on auto-newline when positive, turns + off auto-newline when negative and toggles when zero." + (interactive "P") + (let ((auto (cond + ((not arg) + (not c++-auto-newline)) + ((zerop (setq arg (prefix-numeric-value arg))) + (not c++-auto-newline)) + ((< arg 0) nil) + (t t)))) + (c++-set-auto-hungry-state auto c++-hungry-delete-key))) + + (defun c++-toggle-hungry-state (arg) + "Toggle hungry-delete-key feature. + This function ignores c++-auto-hungry-toggle variable. Optional + numeric ARG, if supplied turns on hungry-delete-key when positive, + turns off hungry-delete-key when negative and toggles when zero." + (interactive "P") + (let ((hungry (cond + ((not arg) + (not c++-hungry-delete-key)) + ((zerop (setq arg (prefix-numeric-value arg))) + (not c++-hungry-delete-key)) + ((< arg 0) nil) + (t t)))) + (c++-set-auto-hungry-state c++-auto-newline hungry))) + + (defun c++-toggle-auto-hungry-state (arg) + "Toggle auto-newline and hungry-delete-key features. + Actual toggling of these features is controlled by + c++-auto-hungry-toggle variable. + + Optional argument has the following meanings when supplied: + Universal argument \\[universal-argument] + resets features to c++-auto-hungry-initial-state. + negative number + turn off both auto-newline and hungry-delete-key features. + positive number + turn on both auto-newline and hungry-delete-key features. + zero + toggle both features regardless of c++-auto-hungry-toggle-p." + (interactive "P") + (let* ((numarg (prefix-numeric-value arg)) + (apl (list 'auto-only 'auto-hungry t)) + (hpl (list 'hungry-only 'auto-hungry t)) + (auto (cond + ((not arg) + (if (memq c++-auto-hungry-toggle apl) + (not c++-auto-newline) + c++-auto-newline)) + ((listp arg) + (memq c++-auto-hungry-initial-state apl)) + ((zerop numarg) + (not c++-auto-newline)) + ((< arg 0) nil) + (t t))) + (hungry (cond + ((not arg) + (if (memq c++-auto-hungry-toggle hpl) + (not c++-hungry-delete-key) + c++-hungry-delete-key)) + ((listp arg) + (memq c++-auto-hungry-initial-state hpl)) + ((zerop numarg) + (not c++-hungry-delete-key)) + ((< arg 0) nil) + (t t)))) + (c++-set-auto-hungry-state auto hungry))) + + (defun c++-tame-insert (arg) + "Safely inserts certain troublesome characters in comment regions. + Because of syntax bugs in emacs, characters with string or parenthesis + syntax must be escaped with a backslash or lots of things get messed + up. Unfortunately, setting parse-sexp-ignore-comments to non-nil does + not fix the problem, but this function is unnecessary if you are + running a patched emacs. + + See also the variable c++-untame-characters." + (interactive "p") + (if (and (memq last-command-char c++-untame-characters) + (memq (c++-in-literal) '(c c++))) + (insert "\\")) + (self-insert-command arg)) + + (defun c++-electric-delete (arg) + "If c++-hungry-delete-key is non-nil, consumes all preceding + whitespace unless ARG is supplied, or point is inside a C or C++ style + comment or string. If ARG is supplied, this just calls + backward-delete-char-untabify passing along ARG. + + If c++-hungry-delete-key is nil, just call + backward-delete-char-untabify." + (interactive "P") + (cond + ((or (not c++-hungry-delete-key) arg) + (funcall c++-delete-function (prefix-numeric-value arg))) + ((let ((bod (c++-point 'bod))) + (not (or (memq (c++-in-literal bod) '(c c++ string)) + (save-excursion + (skip-chars-backward " \t") + (= (preceding-char) ?#))))) + (let ((here (point))) + (skip-chars-backward " \t\n") + (if (/= (point) here) + (delete-region (point) here) + (funcall c++-delete-function 1)))) + (t (funcall c++-delete-function 1)))) + + (defun c++-electric-pound (arg) + (interactive "p") + (if (memq (c++-in-literal) '(c c++ string)) + (self-insert-command arg) + (let ((here (point-marker)) + (bobp (bobp)) + (bolp (bolp))) + (if (memq 'alignleft c++-electric-pound-behavior) + (progn (beginning-of-line) + (delete-horizontal-space))) + (if bobp + (insert (make-string arg last-command-char)) + (insert-before-markers (make-string arg last-command-char))) + (if (not bolp) + (goto-char here)) + (set-marker here nil)))) + + (defun c++-electric-brace (arg) + "Insert character and correct line's indentation." + (interactive "P") + (let (insertpos + (last-command-char last-command-char) + (bod (c++-point 'bod))) + (if (and (not arg) + (save-excursion + (skip-chars-forward " \t") + (eolp)) + (or (save-excursion + (skip-chars-backward " \t") + (bolp)) + (let ((c++-auto-newline c++-auto-newline) + (open-brace-p (= last-command-char ?{))) + (if (and open-brace-p + (or (eq c++-hanging-braces t) + (and c++-hanging-braces + (not (c++-at-top-level-p t bod))))) + (setq c++-auto-newline nil)) + (if (c++-auto-newline) + ;; this may have auto-filled so we need to + ;; indent the previous line. we also need to + ;; indent the currently line, or + ;; c++-beginning-of-defun will not be able to + ;; correctly find the bod when + ;; c++-match-headers-strongly is nil. + (progn (c++-indent-line) + (save-excursion + (forward-line -1) + (c++-indent-line)))) + t))) + (progn + (if (and (memq last-command-char c++-untame-characters) + (memq (c++-in-literal bod) '(c c++))) + (insert "\\")) + ;; we need to work around a bogus feature of emacs where an + ;; open brace at bolp means a beginning-of-defun. but it + ;; really might not. + (and (= last-command-char ?{) + (bolp) + (c++-indent-line)) + (insert last-command-char) + ;; try to clean up empty defun braces if conditions apply + (let ((here (point-marker))) + (and (memq 'empty-defun-braces c++-cleanup-list) + (c++-at-top-level-p t bod) + c++-auto-newline + (= last-command-char ?\}) + (progn (forward-char -1) + (skip-chars-backward " \t\n") + (= (preceding-char) ?\{)) + (not (memq (c++-in-literal) '(c c++ string))) + (delete-region (point) (1- here))) + (goto-char here) + (set-marker here nil)) + (let ((here (point-marker)) + mbeg mend) + (if (and (memq 'brace-else-brace c++-cleanup-list) + (= last-command-char ?\{) + (let ((status + (re-search-backward "}[ \t\n]*else[ \t\n]*{" + nil t))) + (setq mbeg (match-beginning 0) + mend (match-end 0)) + status) + (= mend here) + (not (memq (c++-in-literal bod) '(c c++ string)))) + (progn + ;; we should clean up brace-else-brace syntax + (delete-region mbeg mend) + (insert-before-markers "} else {") + (goto-char here) + (set-marker here nil)) + (goto-char here) + (set-marker here nil))) + (c++-indent-line) + (if (c++-auto-newline) + (progn + ;; c++-auto-newline may have done an auto-fill + (save-excursion + (let ((here (point-marker))) + (goto-char (- (point) 2)) + (c++-indent-line) + (setq insertpos (- (goto-char here) 2)) + (set-marker here nil))) + (c++-indent-line))) + (save-excursion + (if insertpos (goto-char (1+ insertpos))) + (delete-char -1)))) + (if insertpos + (save-excursion + (goto-char insertpos) + (self-insert-command (prefix-numeric-value arg))) + (self-insert-command (prefix-numeric-value arg))))) + + (defun c++-electric-slash (arg) + "Insert slash, and if slash is second of a double-slash comment + introducing construct, indent line as comment. This only indents if + we're on a comment-only line, otherwise use indent-for-comment (\\[indent-for-comment])." + (interactive "P") + (let ((here (point)) char) + (self-insert-command (prefix-numeric-value arg)) + (and (setq char (char-after (1- here))) + (= char ?/) + (save-excursion + (goto-char here) + (c++-indent-line))))) + + (defun c++-electric-star (arg) + "Works with c++-electric-slash to auto indent C style comment lines." + (interactive "P") + (let ((here (point)) char) + (self-insert-command (prefix-numeric-value arg)) + (if (and (setq char (char-after (1- here))) + (memq (c++-in-literal) '(c)) + (memq char '(?/ ?* ?\t 32 ?\n)) + (save-excursion + (skip-chars-backward "* \t") + (if (= (preceding-char) ?/) + (progn + (forward-char -1) + (skip-chars-backward " \t"))) + (bolp))) + (save-excursion + (goto-char here) + (c++-indent-line))))) + + (defun c++-electric-semi (arg) + "Insert character and correct line's indentation." + (interactive "P") + (if (c++-in-literal) + (self-insert-command (prefix-numeric-value arg)) + (let ((here (point-marker))) + (if (and (memq 'defun-close-semi c++-cleanup-list) + c++-auto-newline + (progn + (skip-chars-backward " \t\n") + (= (preceding-char) ?}))) + (delete-region here (point))) + (goto-char here) + (set-marker here nil)) + (c++-electric-terminator arg))) + + (defun c++-electric-colon (arg) + "Electrify colon. De-auto-newline double colons. No auto-new-lines + for member initialization list." + (interactive "P") + (if (c++-in-literal) + (self-insert-command (prefix-numeric-value arg)) + (let ((c++-auto-newline c++-auto-newline) + (insertion-point (point)) + (bod (c++-point 'bod))) + (save-excursion + (cond + ;; check for double-colon where the first colon is not in a + ;; comment or literal region + ((progn (skip-chars-backward " \t\n") + (and (= (preceding-char) ?:) + (not (memq (c++-in-literal bod) '(c c++ string))))) + (progn (delete-region insertion-point (point)) + (setq c++-auto-newline nil + insertion-point (point)))) + ;; check for ?: construct which may be at any level + ((progn (goto-char insertion-point) + (condition-case premature-end + (backward-sexp 1) + (error nil)) + ;; is possible that the sexp we just skipped was a + ;; negative number. in that case the minus won't be + ;; gobbled + (skip-chars-backward "-") + (c++-backward-syntactic-ws bod) + (= (preceding-char) ?\?)) + (setq c++-auto-newline nil)) + ;; check for being at top level or top with respect to the + ;; class. if not, process as normal + ((progn (goto-char insertion-point) + (not (c++-at-top-level-p t bod)))) + ;; if at top level, check to see if we are introducing a member + ;; init list. if not, continue + ((progn (c++-backward-syntactic-ws bod) + (= (preceding-char) ?\))) + (goto-char insertion-point) + ;; at a member init list, figure out about auto newlining. if + ;; nil or before then put a newline before the colon and + ;; adjust the insertion point, but *only* if there is no + ;; newline already before the insertion point + (if (and (memq c++-hanging-member-init-colon '(nil before)) + c++-auto-newline) + (if (not (save-excursion (skip-chars-backward " \t") + (bolp))) + (let ((c++-auto-newline t)) + (c++-auto-newline) + (setq insertion-point (point))))) + ;; if hanging colon is after or nil, then newline is inserted + ;; after colon. set up variable so c++-electric-terminator + ;; places the newline correctly + (setq c++-auto-newline + (and c++-auto-newline + (memq c++-hanging-member-init-colon '(nil after))))) + ;; last condition is always put newline after colon + (t (setq c++-auto-newline nil)) + )) ; end-cond, end-save-excursion + (goto-char insertion-point) + (c++-electric-terminator arg)))) + + (defun c++-electric-terminator (arg) + "Insert character and correct line's indentation." + (interactive "P") + (let (insertpos (end (point))) + (if (and (not arg) + (save-excursion + (skip-chars-forward " \t") + (eolp)) + (not (save-excursion + (beginning-of-line) + (skip-chars-forward " \t") + (or (= (following-char) ?#) + ;; Colon is special only after a label, or + ;; case, or another colon. + ;; So quickly rule out most other uses of colon + ;; and do no indentation for them. + (and (eq last-command-char ?:) + (not (looking-at "case[ \t]")) + (save-excursion + (forward-word 1) + (skip-chars-forward " \t") + (< (point) end)) + ;; Do re-indent double colons + (save-excursion + (end-of-line 1) + (looking-at ":"))) + (progn + (c++-beginning-of-defun) + (let* ((parse-sexp-ignore-comments t) + (pps (parse-partial-sexp (point) end))) + (or (nth 3 pps) (nth 4 pps) (nth 5 pps)))))))) + (progn + (insert last-command-char) + (c++-indent-line) + (and c++-auto-newline + (not (c++-in-parens-p)) + (progn + ;; the new marker object, used to be just an integer + (setq insertpos (make-marker)) + ;; changed setq to set-marker + (set-marker insertpos (1- (point))) + ;; do this before the newline, since in auto fill can break + (newline) + (c++-indent-line))) + (save-excursion + (if insertpos (goto-char (1+ insertpos))) + (delete-char -1)))) + (if insertpos + (save-excursion + (goto-char insertpos) + (self-insert-command (prefix-numeric-value arg))) + (self-insert-command (prefix-numeric-value arg))))) + + (defun c++-indent-command (&optional whole-exp) + "Indent current line as C++ code, or in some cases insert a tab character. + + If c++-tab-always-indent is t, always just indent the current line. + If nil, indent the current line only if point is at the left margin or + in the line's indentation; otherwise insert a tab. If not-nil-or-t, + then tab is inserted only within literals (comments and strings) and + inside preprocessor directives, but line is always reindented. + + A numeric argument, regardless of its value, means indent rigidly all + the lines of the expression starting after point so that this line + becomes properly indented. The relative indentation among the lines + of the expression are preserved." + (interactive "P") + (let ((bod (c++-point 'bod))) + (if whole-exp + ;; If arg, always indent this line as C + ;; and shift remaining lines of expression the same amount. + (let ((shift-amt (c++-indent-line bod)) + beg end) + (save-excursion + (if (eq c++-tab-always-indent t) + (beginning-of-line)) + (setq beg (point)) + (forward-sexp 1) + (setq end (point)) + (goto-char beg) + (forward-line 1) + (setq beg (point))) + (if (> end beg) + (indent-code-rigidly beg end shift-amt "#"))) + (cond + ;; CASE 1: indent when at column zero or in lines indentation, + ;; otherwise insert a tab + ((not c++-tab-always-indent) + (if (and (save-excursion + (skip-chars-backward " \t") + (bolp)) + (or (looking-at "[ \t]*$") + (/= (point) (c++-point 'boi)) + (bolp))) + (c++-indent-line bod) + (insert-tab))) + ;; CASE 2: just indent the line + ((eq c++-tab-always-indent t) + (c++-indent-line bod)) + ;; CASE 3: if in a literal, insert a tab, but always indent the line + ((or (memq (c++-in-literal bod) '(c c++ string)) + (save-excursion + (skip-chars-backward " \t") + (= (preceding-char) ?#))) + (let ((here (point)) + (boi (save-excursion (back-to-indentation) (point))) + (indent-p nil)) + (c++-indent-line bod) + (save-excursion + (back-to-indentation) + (setq indent-p (and (> here boi) (= (point) boi)))) + (if indent-p (insert-tab)))) + ;; CASE 4: bogus, just indent the line + (t (c++-indent-line bod)))))) + + (defun c++-indent-exp () + "Indent each line of the C++ grouping following point." + (interactive) + (let ((indent-stack (list nil)) + (contain-stack (list (point))) + (case-fold-search nil) + restart outer-loop-done inner-loop-done state ostate + this-indent last-sexp last-depth + at-else at-brace + (parse-sexp-ignore-comments t) + (opoint (point)) + (next-depth 0)) + (save-excursion + (forward-sexp 1)) + (save-excursion + (setq outer-loop-done nil) + (while (and (not (eobp)) (not outer-loop-done)) + (setq last-depth next-depth) + ;; Compute how depth changes over this line + ;; plus enough other lines to get to one that + ;; does not end inside a comment or string. + ;; Meanwhile, do appropriate indentation on comment lines. + (setq inner-loop-done nil) + (while (and (not inner-loop-done) + (not (and (eobp) (setq outer-loop-done t)))) + (setq ostate state) + ;; fix by reed@adapt.net.com + ;; must pass in the return past the end of line, so that + ;; parse-partial-sexp finds it, and recognizes that a "//" + ;; comment is over. otherwise, state is set that we're in a + ;; comment, and never gets unset, causing outer-loop to only + ;; terminate in (eobp). old: + ;;(setq state (parse-partial-sexp (point) + ;;(progn (end-of-line) (point)) + ;;nil nil state)) + (let ((start (point)) + (line-end + (progn (end-of-line) + (while (eq (c++-in-literal) 'c) + (forward-line 1) + (c++-indent-line) + (end-of-line)) + (skip-chars-backward " \t") + (end-of-line) + (point))) + (end (progn (if (not (eobp)) (forward-char)) (point)))) + (setq state (parse-partial-sexp start end nil nil state)) + (goto-char line-end)) + (setq next-depth (car state)) + (if (and (car (cdr (cdr state))) + (>= (car (cdr (cdr state))) 0)) + (setq last-sexp (car (cdr (cdr state))))) + (if (or (nth 4 ostate)) + (c++-indent-line)) + (if (or (nth 3 state)) + (forward-line 1) + (setq inner-loop-done t))) + (if (<= next-depth 0) + (setq outer-loop-done t)) + (if outer-loop-done + nil + ;; If this line had ..))) (((.. in it, pop out of the levels + ;; that ended anywhere in this line, even if the final depth + ;; doesn't indicate that they ended. + (while (> last-depth (nth 6 state)) + (setq indent-stack (cdr indent-stack) + contain-stack (cdr contain-stack) + last-depth (1- last-depth))) + (if (/= last-depth next-depth) + (setq last-sexp nil)) + ;; Add levels for any parens that were started in this line. + (while (< last-depth next-depth) + (setq indent-stack (cons nil indent-stack) + contain-stack (cons nil contain-stack) + last-depth (1+ last-depth))) + (if (null (car contain-stack)) + (setcar contain-stack (or (car (cdr state)) + (save-excursion (forward-sexp -1) + (point))))) + (forward-line 1) + (skip-chars-forward " \t") + ;; check for C comment block + (if (memq (c++-in-literal) '(c)) + (let ((eoc (save-excursion + (re-search-forward "\\*/" (point-max) 'move) + (point)))) + (while (< (point) eoc) + (c++-indent-line) + (forward-line 1)))) + (if (eolp) + nil + (if (and (car indent-stack) + (>= (car indent-stack) 0)) + ;; Line is on an existing nesting level. + ;; Lines inside parens are handled specially. + (if (or (/= (char-after (car contain-stack)) ?{) + ;;(c++-at-top-level-p t)) + ;; baw hack for continued statement offsets + ;; repercussions??? + t) + (setq this-indent (car indent-stack)) + ;; Line is at statement level. + ;; Is it a new statement? Is it an else? + ;; Find last non-comment character before this line + (save-excursion + (setq at-else (looking-at "else\\W")) + (setq at-brace (= (following-char) ?{)) + (c++-backward-syntactic-ws opoint) + (if (not (memq (preceding-char) '(nil ?\, ?\; ?} ?: ?{))) + ;; Preceding line did not end in comma or semi; + ;; indent this line c-continued-statement-offset + ;; more than previous. + (progn + (c-backward-to-start-of-continued-exp + (car contain-stack)) + (setq this-indent + (+ c-continued-statement-offset + (current-column) + (if at-brace c-continued-brace-offset 0)))) + ;; Preceding line ended in comma or semi; + ;; use the standard indent for this level. + (if at-else + (progn (c++-backward-to-start-of-if opoint) + (back-to-indentation) + (skip-chars-forward "{ \t") + (setq this-indent (current-column))) + (setq this-indent (car indent-stack)))))) + ;; Just started a new nesting level. + ;; Compute the standard indent for this level. + (let ((val (c++-calculate-indent + (if (car indent-stack) + (- (car indent-stack)))))) + (setcar indent-stack + (setq this-indent val)))) + ;; Adjust line indentation according to its contents + (cond + ;; looking at public, protected, private line + ((looking-at c++-access-key) + (setq this-indent (+ this-indent c++-access-specifier-offset))) + ;; looking at a case, default, or other label + ((or (looking-at "\\(case[ \t]+.*\\|default[ \t]*\\):") + (and (looking-at "[A-Za-z]") + (save-excursion + (forward-sexp 1) + (looking-at ":[^:]")))) + (setq this-indent (max 0 (+ this-indent c-label-offset)))) + ;; looking at a comment only line? + ((looking-at comment-start-skip) + ;; different indentation base on whether this is a col0 + ;; comment only line or not. also, if comment is in, or + ;; to the right of comment-column, the comment doesn't + ;; move + (progn + (skip-chars-forward " \t") + (setq this-indent + (if (>= (current-column) comment-column) + (current-column) + (c++-comment-offset (bolp) this-indent))))) + ;; looking at a friend declaration + ((looking-at "friend[ \t]") + (setq this-indent (+ this-indent c++-friend-offset))) + ;; looking at a close brace + ((= (following-char) ?}) + (setq this-indent (- this-indent c-indent-level))) + ;; looking at an open brace + ((= (following-char) ?{) + (setq this-indent (+ this-indent c-brace-offset))) + ;; check for continued statements + ((save-excursion + (c++-backward-syntactic-ws (car contain-stack)) + (and (not (c++-in-parens-p)) + (not (memq (preceding-char) + '(nil ?\000 ?\, ?\; ?\} ?\: ?\{))) + (progn + (beginning-of-line) + (skip-chars-forward " \t") + (not (looking-at c++-class-key))))) + (setq this-indent (+ this-indent c-continued-statement-offset))) + ;; check for stream operator + ((looking-at "\\(<<\\|>>\\)") + (setq this-indent (c++-calculate-indent))) + ) ;; end-cond + ;; Put chosen indentation into effect. + (or (= (current-column) this-indent) + (= (following-char) ?\#) + (progn + (delete-region (point) (progn (beginning-of-line) (point))) + (indent-to this-indent))) + ;; Indent any comment following the text. + (or (looking-at comment-start-skip) + (if (re-search-forward + comment-start-skip + (c++-point 'eol) t) + (progn (indent-for-comment) + (beginning-of-line)))) + )))))) + + (defun c++-insert-header () + "Insert header denoting C++ code at top of buffer." + (interactive) + (save-excursion + (goto-char (point-min)) + (insert "// " + "This may look like C code, but it is really " + "-*- C++ -*-" + "\n\n"))) + + (defun c++-tame-comments () + "Backslashifies all untamed in comment regions found in the buffer. + This is a workaround for emacs syntax bugs. This function is + unnecessary (and un-used automatically) if you are running a patched + emacs. Untamed characters to escape are defined in the variable + c++-untame-characters." + (interactive) + ;; make the list into a valid charset, escaping where necessary + (let ((charset (concat "^" (mapconcat + (function + (lambda (char) + (if (memq char '(?\\ ?^ ?-)) + (concat "\\" (char-to-string char)) + (char-to-string char)))) + c++-untame-characters "")))) + (save-excursion + (beginning-of-buffer) + (while (not (eobp)) + (skip-chars-forward charset) + (if (and (not (zerop (following-char))) + (memq (c++-in-literal) '(c c++)) + (/= (preceding-char) ?\\ )) + (insert "\\")) + (if (not (eobp)) + (forward-char 1)))))) + + ;; taken from match-paren.el. Author: unknown + (defun c++-match-paren () + "Jumps to the paren matching the one under point, if there is one." + (interactive) + (let ((parse-sexp-ignore-comments (memq 'v19 c++-emacs-features))) + (cond + ((looking-at "[\(\[{]") + (forward-sexp 1) + (backward-char)) + ((looking-at "[])}]") + (forward-char) + (backward-sexp 1)) + (t (message "Could not find matching paren."))))) + + (defun c++-forward-sexp (&optional arg) + (interactive "p") + (let ((parse-sexp-ignore-comments (memq 'v19 c++-emacs-features))) + (forward-sexp arg))) + + (defun c++-backward-sexp (&optional arg) + (interactive "p") + (let ((parse-sexp-ignore-comments (memq 'v19 c++-emacs-features))) + (backward-sexp arg))) + + + ;; ====================================================================== + ;; compatibility between emacsen + ;; ====================================================================== + + ;; This is the best we can do in vanilla GNU 18 emacsen. Note that the + ;; following problems exist: + ;; 1. We only look back to LIM, and that could place us inside a + ;; literal if we are scanning backwards over lots of comments + ;; 2. This can potentially get slower the larger LIM is + ;; If anybody has a better solution, I'll all ears + (defun c++-backward-syntactic-ws (&optional lim) + "Skip backwards over syntactic whitespace. + Syntactic whitespace is defined as lexical whitespace, C and C++ style + comments, and preprocessor directives. Search no farther back than + optional LIM. If LIM is ommitted, beginning-of-defun is used." + (let ((lim (or lim (c++-point 'bod))) + literal stop) + (if (and c++-backscan-limit + (> (- (point) lim) c++-backscan-limit)) + (setq lim (- (point) c++-backscan-limit))) + (while (not stop) + (skip-chars-backward " \t\n\r\f" lim) + ;; c++ comment + (if (eq (setq literal (c++-in-literal lim)) 'c++) + (progn + (skip-chars-backward "^/" lim) + (skip-chars-backward "/" lim) + (while (not (or (and (= (following-char) ?/) + (= (char-after (1+ (point))) ?/)) + (<= (point) lim))) + (skip-chars-backward "^/" lim) + (skip-chars-backward "/" lim))) + ;; c comment + (if (eq literal 'c) + (progn + (skip-chars-backward "^*" lim) + (skip-chars-backward "*" lim) + (while (not (or (and (= (following-char) ?*) + (= (preceding-char) ?/)) + (<= (point) lim))) + (skip-chars-backward "^*" lim) + (skip-chars-backward "*" lim)) + (or (bobp) (forward-char -1))) + ;; preprocessor directive + (if (eq literal 'pound) + (progn + (beginning-of-line) + (setq stop (<= (point) lim))) + ;; just outside of c block + (if (and (= (preceding-char) ?/) + (= (char-after (- (point) 2)) ?*)) + (progn + (skip-chars-backward "^*" lim) + (skip-chars-backward "*" lim) + (while (not (or (and (= (following-char) ?*) + (= (preceding-char) ?/)) + (<= (point) lim))) + (skip-chars-backward "^*" lim) + (skip-chars-backward "*" lim)) + (or (bobp) (forward-char -1))) + ;; none of the above + (setq stop t)))))))) + + ;; This defun works well for Lemacs 19.4 through 19.6, which + ;; implemented a first shot at doing this via a C built-in + ;; backward-syntactic-ws. This has been obsoleted in future Lemacsen + ;; and in GNU19 + (defun c++-fast-backward-syntactic-ws-1 (&optional lim) + "Skip backwards over syntactic whitespace. + Syntactic whitespace is defined as lexical whitespace, C and C++ style + comments, and preprocessor directives. Search no farther back than + optional LIM. If LIM is ommitted, beginning-of-defun is used." + (save-restriction + (let ((parse-sexp-ignore-comments t) + donep boi char + (lim (or lim (c++-point 'bod)))) + (if (< lim (point)) + (unwind-protect + (progn + (narrow-to-region lim (point)) + (modify-syntax-entry ?# "< b" c++-mode-syntax-table) + (while (not donep) + ;; if you're not running a patched lemacs, the new byte + ;; compiler will complain about this function. ignore that + (backward-syntactic-ws) + (if (not (looking-at "#\\|/\\*\\|//\\|\n")) + (forward-char 1)) + (setq boi (c++-point 'boi) + char (char-after boi)) + (if (and char (= char ?#)) + (progn (goto-char boi) + (setq donep (<= (point) lim))) + (setq donep t)) + )) + (modify-syntax-entry ?# "." c++-mode-syntax-table))) + ))) + + ;; This is the way it should be done for all post 19.6 Lemacsen and + ;; for all GNU19 implementations + (defun c++-fast-backward-syntactic-ws-2 (&optional lim) + "Skip backwards over syntactic whitespace. + Syntactic whitespace is defined as lexical whitespace, C and C++ style + comments, and preprocessor directives. Search no farther back than + optional LIM. If LIM is ommitted, beginning-of-defun is used." + (save-restriction + (let ((lim (or lim (c++-point 'bod))) + donep boi char) + (if (< lim (point)) + (unwind-protect + (progn + (narrow-to-region lim (point)) + (modify-syntax-entry ?# "< b" c++-mode-syntax-table) + (while (not donep) + (forward-comment -1) + (if (not (looking-at "#\\|/\\*\\|//\\|\n")) + (forward-char 1)) + (setq boi (c++-point 'boi) + char (char-after boi)) + (if (and char (= char ?#)) + (progn (goto-char boi) + (setq donep (<= (point) lim))) + (setq donep t)) + )) + (modify-syntax-entry ?# "." c++-mode-syntax-table))) + ))) + + ;; This is the slow and ugly way, but its the best we can do in + ;; vanilla GNU18 emacsen + (defun c++-in-literal (&optional lim) + "Determine if point is in a C++ `literal'. + Return 'c if in a C-style comment, 'c++ if in a C++ style comment, + 'string if in a string literal, 'pound if on a preprocessor line, or + nil if not in a comment at all. Optional LIM is used as the backward + limit of the search. If omitted, or nil, c++-beginning-of-defun is + used." + (save-excursion + (let* ((here (point)) + (state nil) + (match nil) + (backlim (or lim (c++-point 'bod)))) + (goto-char backlim) + (while (< (point) here) + (setq match + (and (re-search-forward "\\(/[/*]\\)\\|[\"']\\|\\(^[ \t]*#\\)" + here 'move) + (buffer-substring (match-beginning 0) (match-end 0)))) + (setq state + (cond + ;; no match + ((null match) nil) + ;; looking at the opening of a C++ style comment + ((string= "//" match) + (if (<= here (progn (end-of-line) (point))) 'c++)) + ;; looking at the opening of a C block comment + ((string= "/*" match) + (if (not (re-search-forward "*/" here 'move)) 'c)) + ;; looking at the opening of a double quote string + ((string= "\"" match) + (if (not (save-restriction + ;; this seems to be necessary since the + ;; re-search-forward will not work without it + (narrow-to-region (point) here) + (re-search-forward + ;; this regexp matches a double quote + ;; which is preceeded by an even number + ;; of backslashes, including zero + "\\([^\\]\\|^\\)\\(\\\\\\\\\\)*\"" here 'move))) + 'string)) + ;; looking at the opening of a single quote string + ((string= "'" match) + (if (not (save-restriction + ;; see comments from above + (narrow-to-region (point) here) + (re-search-forward + ;; this matches a single quote which is + ;; preceeded by zero or two backslashes. + "\\([^\\]\\|^\\)\\(\\\\\\\\\\)?'" + here 'move))) + 'string)) + ((string-match "[ \t]*#" match) + (if (<= here (progn (end-of-line) (point))) 'pound)) + (t nil))) + ) ; end-while + state))) + + ;; This is for all 8-bit emacsen (Lucid 19, patched GNU18) + (defun c++-in-literal-8-bit (&optional lim) + "Determine if point is in a C++ `literal'. + Return 'c if in a C-style comment, 'c++ if in a C++ style comment, + 'string if in a string literal, 'pound if on a preprocessor line, or + nil if not in a comment at all. Optional LIM is used as the backward + limit of the search. If omitted, or nil, c++-beginning-of-defun is + used." + (save-excursion + (let* ((backlim (or lim (c++-point 'bod))) + (here (point)) + (parse-sexp-ignore-comments t) ; may not be necessary + (state (parse-partial-sexp backlim (point)))) + (cond + ((nth 3 state) 'string) + ((nth 4 state) (if (nth 7 state) 'c++ 'c)) + ((progn + (goto-char here) + (beginning-of-line) + (looking-at "[ \t]*#")) + 'pound) + (t nil))))) + + ;; This is for all 1-bit emacsen (GNU19) + (defun c++-in-literal-1-bit (&optional lim) + "Determine if point is in a C++ `literal'. + Return 'c if in a C-style comment, 'c++ if in a C++ style comment, + 'string if in a string literal, 'pound if on a preprocessor line, or + nil if not in a comment at all. Optional LIM is used as the backward + limit of the search. If omitted, or nil, c++-beginning-of-defun is + used." + (save-excursion + (let* ((backlim (or lim (c++-point 'bod))) + (here (point)) + (parse-sexp-ignore-comments t) ; may not be necessary + (state (parse-partial-sexp backlim (point)))) + (cond + ((nth 3 state) 'string) + ((nth 4 state) (if (nth 7 state) 'c 'c++)) + ((progn + (goto-char here) + (beginning-of-line) + (looking-at "[ \t]*#")) + 'pound) + (t nil))))) + + (cond + ((memq 'old-v19 c++-emacs-features) + (fset 'c++-backward-syntactic-ws 'c++-fast-backward-syntactic-ws-1)) + ((memq 'v19 c++-emacs-features) + (fset 'c++-backward-syntactic-ws 'c++-fast-backward-syntactic-ws-2)) + ) + (cond + ((memq '8-bit c++-emacs-features) + (fset 'c++-in-literal 'c++-in-literal-8-bit)) + ((memq '1-bit c++-emacs-features) + (fset 'c++-in-literal 'c++-in-literal-1-bit)) + ) + + + ;; ====================================================================== + ;; defuns for parsing syntactic elements + ;; ====================================================================== + (defun c++-parse-state (&optional limit) + "Determinate the syntactic state of the code at point. + Iteratively uses parse-partial-sexp from point to LIMIT and returns + the result of parse-partial-sexp at point. LIMIT is optional and + defaults to point-max." + (let ((limit (or limit (point-max))) + (parse-sexp-ignore-comments t) + state) + (while (< (point) limit) + (setq state (parse-partial-sexp (point) limit 0))) + state)) + + (defun c++-at-top-level-p (wrt &optional bod) + "Return t if point is not inside a containing C++ expression, nil + if it is embedded in an expression. When WRT is non-nil, returns nil + if not at the top level with respect to an enclosing class, or the + depth of class nesting at point. With WRT nil, returns nil if not at + the \"real\" top level. Optional BOD is the beginning of defun." + (save-excursion + (let ((indent-point (point)) + (case-fold-search nil) + state containing-sexp paren-depth + (bod (or bod (c++-point 'bod))) + foundp) + (goto-char bod) + (setq state (c++-parse-state indent-point) + containing-sexp (nth 1 state) + paren-depth (nth 0 state)) + (cond + ((eq major-mode 'c++-c-mode) + (and (null containing-sexp) 0)) + ((not wrt) + (null containing-sexp)) + ((null containing-sexp) 0) + ((c++-in-parens-p) nil) + (t + ;; calculate depth wrt containing (possibly nested) classes + (goto-char containing-sexp) + (while (and (setq foundp (re-search-backward + (concat "[;}]\\|" c++-class-key) + (point-min) t)) + (let ((bod (c++-point 'bod))) + (or (c++-in-literal bod) + (c++-in-parens-p bod) + ;; see if class key is inside a template spec + (and (looking-at c++-class-key) + (progn (skip-chars-backward " \t\n") + (memq (preceding-char) '(?, ?<)))))))) + (if (memq (following-char) '(?} ?\;)) + nil + (setq state (c++-parse-state containing-sexp)) + (and foundp + (not (nth 1 state)) + (nth 2 state) + paren-depth)) + ))))) + + (defun c++-in-parens-p (&optional lim) + "Return t if inside a paren expression. + Optional LIM is used as the backward limit of the search." + (let ((lim (or lim (c++-point 'bod)))) + (condition-case var + (save-excursion + (save-restriction + (narrow-to-region (point) lim) + (goto-char (point-max)) + (= (char-after (or (scan-lists (point) -1 1) + (point-min))) + ?\())) + (error nil) + ))) + + (defun c++-in-function-p (&optional containing) + "Return t if inside a C++ function definition. + Optional CONTAINING is position of containing s-exp open brace. If not + supplied, point is used as search start." + (save-excursion + (let ((here (if (not containing) + (point) + (goto-char containing) + (c++-backward-syntactic-ws) + (point)))) + (if (and (= (preceding-char) ?t) + (forward-word -1) + (looking-at "\\")) + (c++-backward-syntactic-ws) + (goto-char here)) + (= (preceding-char) ?\))))) + + + ;; ====================================================================== + ;; defuns for calculating indentation + ;; ====================================================================== + (defun c++-indent-line (&optional bod) + "Indent current line as C++ code. + Return the amount the indentation changed by. Optional BOD is the + point of the beginning of the C++ definition." + (let* ((bod (or bod (c++-point 'bod))) + (indent (c++-calculate-indent nil bod)) + beg shift-amt + (case-fold-search nil) + (pos (- (point-max) (point)))) + (beginning-of-line) + (setq beg (point)) + (cond + ((eq indent nil) + (setq indent (current-indentation))) + ((eq indent t) + (setq indent (c++-calculate-c-indent-within-comment))) + ((looking-at "[ \t]*#") + (setq indent 0)) + ((save-excursion + (back-to-indentation) + (looking-at "//\\|/\\*")) + ;; we've found a comment-only line. we now must try to determine + ;; if the line is a continuation from a comment on the previous + ;; line. we check to see if the comment starts in or to the + ;; right of comment-column and if so, we don't change its + ;; indentation. + (skip-chars-forward " \t") + (if (>= (current-column) comment-column) + (setq indent (current-column)) + (setq indent (c++-comment-offset (bolp) indent)))) + (t + (skip-chars-forward " \t") + (if (listp indent) (setq indent (car indent))) + (cond + ((looking-at c++-access-key) + (setq indent (+ indent c++-access-specifier-offset))) + ((looking-at "default[ \t]*:") + (setq indent (+ indent c-label-offset))) + ((or (looking-at "case[ \t]+.*:") + (and (looking-at "[A-Za-z]") + (save-excursion + (forward-sexp 1) + (looking-at ":[^:]")))) + (setq indent (max 1 (+ indent c-label-offset)))) + ((and (looking-at "else\\b") + (not (looking-at "else\\s_"))) + (setq indent (save-excursion + (c++-backward-to-start-of-if) + (back-to-indentation) + (skip-chars-forward "{ \t") + (current-column)))) + ((looking-at "\\") + (setq indent (+ indent c++-friend-offset))) + ((and (= (following-char) ?\)) + c++-paren-as-block-close-p) + (setq indent (+ (- indent c-indent-level) + (if (save-excursion + (forward-char 1) + (c++-at-top-level-p nil bod)) + (- c++-block-close-brace-offset) + c++-block-close-brace-offset)))) + ((= (following-char) ?}) + (setq indent (+ (- indent c-indent-level) + (if (save-excursion + (forward-char 1) + (c++-at-top-level-p nil bod)) + (- c++-block-close-brace-offset) + c++-block-close-brace-offset)))) + ((= (following-char) ?{) + (setq indent (+ indent c-brace-offset)))))) + (skip-chars-forward " \t") + (setq shift-amt (- indent (current-column))) + (if (zerop shift-amt) + (if (> (- (point-max) pos) (point)) + (goto-char (- (point-max) pos))) + (delete-region beg (point)) + (indent-to indent) + ;; If initial point was within line's indentation, + ;; position after the indentation. Else stay at same point in text. + (if (> (- (point-max) pos) (point)) + (goto-char (- (point-max) pos)))) + ;; save-excursion is necessary because things break if the hook + ;; changes point or mark + (save-excursion + (run-hooks 'c++-special-indent-hook)) + shift-amt)) + + (defun c++-cont-indent (ipnt char lim) + "Calculate the indentation for a continued statement. + IPNT is the indentation point; CHAR is the character before the + indentation point, excluding any intervenine whitespace; LIM is the + minimum point to search backwards to" + (let ((charlist '(nil ?\000 ?\, ?\; ?\} ?\: ?\{)) + streamop-pos here) + (goto-char ipnt) + (c++-backward-syntactic-ws lim) + (if (not (memq char charlist)) + ;; This line is continuation of preceding line's statement + (progn + (c-backward-to-start-of-continued-exp lim) + ;; take care of << and >> while in streams + (setq here (point)) + (if (save-excursion + (and (progn (goto-char ipnt) + (looking-at "[ \t]*\\(<<\\|>>\\)")) + (progn (goto-char here) + (skip-chars-forward "^><\n") + (setq streamop-pos (current-column)) + (looking-at "\\(<<\\|>>\\)")))) + streamop-pos + (+ (current-column) + ;; prevent repeated continued indentation + (if (save-excursion + (beginning-of-line 1) + (c++-backward-syntactic-ws lim) + (memq (preceding-char) charlist)) + c-continued-statement-offset + ;; the following statements *do* indent even + ;; for single statements (are there others?) + (if (looking-at "\\(do\\|else\\|for\\|if\\|while\\)\\b") + c-continued-statement-offset + ;; else may be a continued statement inside + ;; a simple for/else/while/if/do loop + (beginning-of-line 1) + (forward-char -1) + (c++-backward-syntactic-ws lim) + (c-backward-to-start-of-continued-exp lim) + (if (looking-at "\\(do\\|else\\|for\\|if\\|while\\)\\b") + c-continued-statement-offset + 0))) + (save-excursion + (goto-char ipnt) + (skip-chars-forward " \t") + (cond + ((= (following-char) ?\{) + c-continued-brace-offset) + ((and (= (following-char) ?\}) + (progn (forward-char 1) + (c++-at-top-level-p nil lim))) + (- c-continued-statement-offset)) + (t 0)))))) + nil))) + + (defun c++-calculate-indent (&optional parse-start bod) + "Return appropriate indentation for current line as C++ code. + In usual case returns an integer: the column to indent to. + Returns nil if line starts inside a string, t if in a comment. + Optional PARSE-START is the location to start parsing, and optional + BOD is the beginning of the C++ definition." + (save-excursion + (beginning-of-line) + (let ((indent-point (point)) + (case-fold-search nil) + state do-indentation literal + containing-sexp streamop-pos char-before-ip + (inclass-shift 0) inclass-depth inclass-unshift + (bod (or bod (c++-point 'bod)))) + (if parse-start + (goto-char parse-start) + (goto-char bod)) + (setq parse-start (point) + state (c++-parse-state indent-point) + containing-sexp (nth 1 state)) + ;; it is possible that c++-defun-header-weak could not find the + ;; beginning of the C++ definition. The following code attempts + ;; to work around this. It is probably better to just use + ;; c++-match-header-strongly, but there are performance questions + (if (null state) + (let* ((c++-match-header-strongly t) + (bod (c++-point 'bod))) + (goto-char bod) + (setq state (c++-parse-state indent-point) + containing-sexp (nth 1 state) + parse-start (point)))) + (setq literal (c++-in-literal bod)) + ;; cache char before indent point + (save-excursion + (goto-char indent-point) + (c++-backward-syntactic-ws bod) + (setq char-before-ip (preceding-char))) + (cond + ;; CASE 1: in a string. + ((memq literal '(string)) nil) + ;; CASE 2: in a C or C++ style comment. + ((memq literal '(c c++)) t) + ;; CASE 3: Line is at top level. May be comment-only line, + ;; data or function definition, or may be function argument + ;; declaration or member initialization. Indent like the + ;; previous top level line unless: + ;; + ;; 1. the previous line ends in a closeparen without + ;; semicolon, in which case this line is the first + ;; argument declaration or member initialization, or + ;; + ;; 2. the previous line ends with a closeparen + ;; (closebrace), optional spaces, and a semicolon, in + ;; which case this line follows a multiline function + ;; declaration (class definition), or + ;; + ;; 3. the previous line begins with a colon, in which + ;; case this is the second line of member inits. It is + ;; assumed that arg decls and member inits are not mixed. + ;; + ((setq inclass-depth (c++-at-top-level-p t bod)) + (+ + ;; add an offset if we are inside a class defun body, + ;; i.e. we are at the top level, but only wrt a + ;; containing class + (let ((shift/level (+ c-indent-level c-brace-imaginary-offset))) + (setq inclass-shift (* shift/level inclass-depth) + inclass-unshift (* shift/level (max 0 (1- inclass-depth)))) + inclass-shift) + (progn + (goto-char indent-point) + (skip-chars-forward " \t") + (if (or (= (following-char) ?{) + (progn + (c++-backward-syntactic-ws parse-start) + (bobp))) + 0 + (if (c++-in-function-p) + (progn ; first arg decl or member init + (goto-char indent-point) + (skip-chars-forward " \t") + (if (= (following-char) ?:) + c++-member-init-indent + c-argdecl-indent)) + (if (= (preceding-char) ?\;) + (progn + (backward-char 1) + (skip-chars-backward " \t"))) + ;; may be first line after a hanging member init + ;; colon. check to be sure its not a scope + ;; operator meaning we are inside a member def + (if (or (= (preceding-char) ?:) + (save-excursion + (forward-line 1) + (skip-chars-forward " \t") + (or (eobp) (forward-char 1)) + (and (= (preceding-char) ?:) + (/= (following-char) ?:))) + (save-excursion + (and (= (preceding-char) ?,) + (let ((bol (c++-point 'bol))) + (skip-chars-backward "^:" bol) + (= (preceding-char) ?:)) + (not (c++-in-parens-p)) + (progn + (forward-char -1) + (skip-chars-backward " \t") + (not (bolp))) + ;; make sure its not a multiple inheritance + ;; continuation line + (progn + (beginning-of-line) + (not (looking-at c++-inher-key))) + ))) + ;; check to see if we're looking at a member + ;; init, or access specifier + (if (progn + (beginning-of-line) + (skip-chars-forward " \t") + (looking-at c++-access-key)) + ;; access specifier. class defun opening brace + ;; may not be in col zero + (progn (goto-char (or containing-sexp bod)) + (- (current-indentation) + ;; remove some nested inclass indentation + inclass-unshift)) + ;; member init, so add offset. add additional + ;; offset if looking at line with just a member + ;; init colon + (+ c++-member-init-indent + (if (looking-at ":[ \t]*$") + (or c++-continued-member-init-offset 0) 0))) + (if (or (= (preceding-char) ?}) + (= (preceding-char) ?\)) + (save-excursion + (beginning-of-line) + (looking-at "[ \t]*\\"))) + ;; indentation of class defun opening brace + ;; may not be zero + (progn (goto-char (or containing-sexp bod)) + (- (current-indentation) + ;; remove some nested inclass indentation + inclass-unshift)) + ;; cont arg decls or member inits + (beginning-of-line) + ;; we might be inside a K&R C arg decl + (if (save-excursion + (c++-backward-syntactic-ws bod) + (and (eq major-mode 'c++-c-mode) + (= (preceding-char) ?\)))) + c-argdecl-indent + (skip-chars-forward " \t") + (if (or (memq (c++-in-literal bod) '(c c++)) + (looking-at "/[/*]")) + 0 + (if (= (following-char) ?:) + (if c++-continued-member-init-offset + (+ (current-indentation) + c++-continued-member-init-offset) + (progn + (forward-char 1) + (skip-chars-forward " \t") + (- (current-column) + inclass-shift))) + ;; else first check to see if its a + ;; multiple inheritance continuation line, + ;; but not a K&R C arg decl + (if (and (not (eq major-mode 'c++-c-mode)) + (looking-at c++-inher-key)) + (if (= char-before-ip ?,) + (progn (goto-char (match-end 0)) + (current-column)) + ;; nope, its probably a nested class + 0) + ;; we might be looking at the opening + ;; brace of a class defun + (if (= (following-char) ?\{) + ;; indentation of opening brace may not + ;; be zero + (- (current-indentation) + ;; remove some nested inclass indentation + inclass-unshift) + (if (eolp) + ;; looking at a blank line, indent + ;; next line to zero + 0 + (if (save-excursion + (goto-char indent-point) + (beginning-of-line) + (bobp)) + ;; at beginning of buffer, if + ;; nothing else, indent to zero + 0 + (if (c++-in-parens-p) + ;; we are perhaps inside a + ;; member init call + (while (and (c++-in-parens-p) + (< bod (point))) + (forward-line -1) + (skip-chars-forward " \t"))) + ;; check to be sure that we're + ;; not on the first line of the + ;; member init list + (if (= (following-char) ?:) + (progn + (forward-char 1) + (skip-chars-forward " \t"))) + ;; subtract inclass-shift since + ;; its already incorporated by + ;; default in current-column + (- (cond + ;;((save-excursion + ;;(c++-cont-indent + ;;indent-point char-before-ip + ;;(or containing-sexp bod)))) + ;;((= char-before-ip ?\;) + ;;(goto-char (or containing-sexp bod)) + ;;(+ (current-indentation) + ;;inclass-shift)) + (t (current-column))) + inclass-shift) + ))))))))) + ))))) + ;; CASE 4: line is expression, not statement. indent to just + ;; after the surrounding open -- unless empty arg list, in + ;; which case we do what c++-empty-arglist-indent says to do. + ((/= (char-after containing-sexp) ?{) + (if (and c++-empty-arglist-indent + (or c++-always-arglist-indent-p + (null (nth 2 state)) + ;; indicates empty arg list. Use a heuristic: if + ;; the first non-whitespace following left paren + ;; on same line is not a comment, is not an empty + ;; arglist. + (save-excursion + (goto-char (1+ containing-sexp)) + (looking-at "[ \t]*[/\n]")))) + (progn + (goto-char containing-sexp) + (beginning-of-line) + (skip-chars-forward " \t") + (goto-char (min (+ (point) c++-empty-arglist-indent) + (1+ containing-sexp))) + (current-column)) + ;; In C-mode, we would always indent to one after the + ;; left paren. Here, though, we may have an + ;; empty-arglist, so we'll indent to the min of that + ;; and the beginning of the first argument. + (goto-char (1+ containing-sexp)) + ;; we want to skip any whitespace b/w open paren and + ;; first argurment. this handles while (thing) style + ;; and while( thing ) style + (skip-chars-forward " \t") + (current-column))) + ;; CASE 5: Statement. Find previous non-comment character. + (t + (or (c++-cont-indent indent-point char-before-ip containing-sexp) + ;; This line may start a new statement, or it could + ;; represent the while closure of a do/while construct + (if (save-excursion + (and (progn (goto-char indent-point) + (skip-chars-forward " \t\n") + (looking-at "while\\b")) + (progn + (c++-backward-to-start-of-do containing-sexp) + (looking-at "do\\b")) + (setq do-indentation (current-column)))) + do-indentation + ;; this could be a case statement. if so we want to + ;; indent it like the first case statement after a switch + (if (save-excursion + (goto-char indent-point) + (skip-chars-forward " \t\n") + (looking-at "\\(case[ \t]+.*\\|default[ \t]*\\):")) + (progn + (goto-char containing-sexp) + (back-to-indentation) + (+ (current-column) c-indent-level)) + ;; else, this is the start of a new statement + ;; Position following last unclosed open. + (goto-char containing-sexp) + ;; Is line first statement after an open-brace? + (or + (and c++-relative-offset-p + ;; If no, find that first statement and + ;; indent like it. + (save-excursion + (forward-char 1) + (while + (progn + (skip-chars-forward " \t\n") + (looking-at + (concat + "#\\|/\\*\\|//" + "\\|\\(case[ \t]+.*\\|default[ \t]*\\)" + "\\|[a-zA-Z0-9_$]*:[^:]" + "\\|friend[ \t]" + c++-class-key + "[ \t]"))) + ;; Skip over comments and labels + ;; following openbrace. + (cond + ((= (following-char) ?\#) + (forward-line 1)) + ((looking-at "/\\*") + (search-forward "*/" nil 'move)) + ((looking-at + (concat "//\\|friend[ \t]" c++-class-key + "[ \t]")) + (forward-line 1)) + ((looking-at "\\(case[ \t]+.*\\|default[ \t]*\\):") + (forward-line 1)) + (t + (re-search-forward ":[^:]" nil 'move)))) + ;; The first following code counts + ;; if it is before the line we want to indent. + (and (< (point) indent-point) + (+ (current-column) + ;; check if this is a true + ;; statement continuation, not a + ;; list of enums or static arrays elems + (if (and + (= char-before-ip ?,) + (c++-in-function-p containing-sexp)) + c-indent-level 0))))) + ;; If no previous statement, indent it relative to + ;; line brace is on. For open brace in column + ;; zero, don't let statement start there too. If + ;; c-indent-offset is zero, use c-brace-offset + + ;; c-continued-statement-offset instead. For + ;; open-braces not the first thing in a line, add + ;; in c-brace-imaginary-offset. + (+ (if (and (bolp) (zerop c-indent-level)) + (+ c-brace-offset c-continued-statement-offset) + c-indent-level) + ;; Move back over whitespace before the openbrace. + ;; If openbrace is not first nonwhite thing on the line, + ;; add the c-brace-imaginary-offset. + (progn (skip-chars-backward " \t") + (if (bolp) 0 c-brace-imaginary-offset)) + ;; If the openbrace is preceded by a parenthesized exp, + ;; move to the beginning of that; + ;; possibly a different line + (progn + (if (eq (preceding-char) ?\)) + (forward-sexp -1)) + ;; Get initial indentation of the line we are on. + (current-indentation)))))))) ; end t outer cond + )))) + + (defun c++-calculate-c-indent-within-comment () + "Return the indentation amount for line, assuming that + the current line is to be regarded as part of a block comment." + (let (end stars indent) + (save-excursion + (beginning-of-line) + (skip-chars-forward " \t") + (setq stars (if (looking-at "\\*\\*?") + (- (match-end 0) (match-beginning 0)) + 0)) + (skip-chars-backward " \t\n") + (setq end (point)) + (beginning-of-line) + (skip-chars-forward " \t") + (if (re-search-forward "/\\*[ \t]*" end t) + (goto-char (+ (match-beginning 0) + (cond + (c++-C-block-comments-indent-p 0) + ((= stars 1) 1) + ((= stars 2) 0) + (t (- (match-end 0) (match-beginning 0))))))) + (current-column)))) + + (defun c++-comment-offset (col0-line-p indent) + "Calculates and returns the comment-only line offset. + Offset is based on the value of c++-comment-only-line-offset, the + argument COL0-LINE-P, and the current indentation INDENT." + (let ((offset 0)) + (if col0-line-p + ;; col0 means we need to look at the second member of the var's + ;; list value. if value is not a list, then zero is used + (if (listp c++-comment-only-line-offset) + ;; it is a list, so second element must be nil or a number + (setq offset + (+ indent + (or (car (cdr c++-comment-only-line-offset)) + (car c++-comment-only-line-offset))))) + ;; not in column zero so indentation is car or value of variable + (setq offset + (+ indent + (if (listp c++-comment-only-line-offset) + (car c++-comment-only-line-offset) + c++-comment-only-line-offset)))) + offset)) + + + ;; ====================================================================== + ;; defuns to look backwards for things + ;; ====================================================================== + + (defun c++-backward-to-start-of-do (&optional limit) + "Move to the start of the last ``unbalanced'' do." + (let ((do-level 1) + (case-fold-search nil) + (limit (or limit (c++-point 'bod)))) + (while (not (zerop do-level)) + ;; we protect this call because trying to execute this when the + ;; while is not associated with a do will throw an error + (condition-case err + (progn + (backward-sexp 1) + (cond + ((memq (c++-in-literal limit) '(c c++))) + ((looking-at "while\\b") + (setq do-level (1+ do-level))) + ((looking-at "do\\b") + (setq do-level (1- do-level))) + ((< (point) limit) + (setq do-level 0) + (goto-char limit)))) + (error + (goto-char limit) + (setq do-level 0)))))) + + (defun c++-backward-to-start-of-if (&optional limit) + "Move to the start of the last ``unbalanced'' if." + (let ((if-level 1) + (case-fold-search nil) + (limit (or limit (c++-point 'bod)))) + (while (and (not (bobp)) + (not (zerop if-level))) + (c++-backward-syntactic-ws) + (c++-backward-sexp 1) + (cond ((looking-at "else\\b") + (setq if-level (1+ if-level))) + ((looking-at "if\\b") + (setq if-level (1- if-level))) + ((< (point) limit) + (setq if-level 0) + (goto-char limit)))))) + + (defun c++-auto-newline () + "Insert a newline iff we're not in a literal. + Literals are defined as being inside a C or C++ style comment or open + string according to mode's syntax." + (let ((bod (c++-point 'bod))) + (and c++-auto-newline + (not (c++-in-literal bod)) + (not (newline))))) + + (defun c++-point (position) + "Returns the value of point at certain commonly referenced POSITIONs. + POSITION can be one of the following symbols: + bol -- beginning of line + eol -- end of line + bod -- beginning of defun + boi -- back to indentation + This function does not modify point or mark." + (let ((here (point)) bufpos) + (cond + ((eq position 'bol) (beginning-of-line)) + ((eq position 'eol) (end-of-line)) + ((eq position 'bod) (c++-beginning-of-defun)) + ((eq position 'boi) (back-to-indentation)) + ) + (setq bufpos (point)) + (goto-char here) + bufpos)) + + + ;; ====================================================================== + ;; defuns for "macroizations" -- making C++ parameterized types via macros + ;; ====================================================================== + (defun c++-macroize-region (from to arg) + "Insert backslashes at end of every line in region. + Useful for defining cpp macros. If called with a prefix argument, + it will remove trailing backslashes." + (interactive "r\nP") + (save-excursion + (goto-char from) + (beginning-of-line 1) + (let ((line (count-lines (point-min) (point))) + (to-line (save-excursion (goto-char to) + (count-lines (point-min) (point))))) + (while (< line to-line) + (c++-backslashify-current-line (null arg)) + (forward-line 1) (setq line (1+ line)))))) + + (defun c++-backslashify-current-line (doit) + "Backslashifies current line." + (end-of-line 1) + (cond + (doit + ;; Note that "\\\\" is needed to get one backslash. + (if (not (save-excursion (forward-char -1) (looking-at "\\\\"))) + (progn + (if (>= (current-column) c++-default-macroize-column) + (insert " \\") + (while (<= (current-column) c++-default-macroize-column) + (insert "\t") (end-of-line)) + (delete-char -1) + (while (< (current-column) c++-default-macroize-column) + (insert " ") (end-of-line)) + (insert "\\"))))) + (t + (forward-char -1) + (if (looking-at "\\\\") + (progn (skip-chars-backward " \t") + (kill-line)))))) + + + ;; ====================================================================== + ;; defuns for commenting out multiple lines. + ;; ====================================================================== + (defun c++-comment-region (beg end) + "Comment out all lines in a region between mark and current point by + inserting comment-start in front of each line." + (interactive "*r") + (save-excursion + (save-restriction + (narrow-to-region + (progn (goto-char beg) (beginning-of-line) (point)) + (progn (goto-char end) (or (bolp) (forward-line 1)) (point))) + (goto-char (point-min)) + (while (not (eobp)) + (insert comment-start) + (forward-line 1)) + (if (eq major-mode 'c++-c-mode) + (insert comment-end))))) + + (defun c++-uncomment-region (beg end) + "Uncomment all lines in region between mark and current point by deleting + the leading \"// \" from each line, if any." + (interactive "*r") + (save-excursion + (save-restriction + (narrow-to-region + (progn (goto-char beg) (beginning-of-line) (point)) + (progn (goto-char end) (forward-line 1) (point))) + (goto-char (point-min)) + (let ((comment-regexp + (if (eq major-mode 'c++-c-mode) + (concat "\\s *\\(" (regexp-quote comment-start) + "\\|" (regexp-quote comment-end) + "\\)") + (concat "\\s *" (regexp-quote comment-start))))) + (while (not (eobp)) + (if (looking-at comment-regexp) + (delete-region (match-beginning 0) (match-end 0))) + (forward-line 1)))))) + + + ;; ====================================================================== + ;; grammar parsing + ;; ====================================================================== + + ;;; Below are two regular expressions that attempt to match defuns + ;;; "strongly" and "weakly." The strong one almost reconstructs the + ;;; grammar of C++; the weak one just figures anything id or curly on + ;;; the left begins a defun. The constant "c++-match-header-strongly" + ;;; determines which to use; the default is the weak one. + + (defvar c++-match-header-strongly nil + "*If NIL, use c++-defun-header-weak to identify beginning of definitions, + if nonNIL, use c++-defun-header-strong") + + (defvar c++-defun-header-strong-struct-equivs + "\\(class\\|struct\\|union\\|enum\\)" + "Regexp to match names of structure declaration blocks in C++") + + (defconst c++-defun-header-strong + (let* + (; valid identifiers + ;; There's a real wierdness here -- if I switch the below + (id "\\(\\w\\|_\\)+") + ;; to be + ;; (id "\\(_\\|\\w\\)+") + ;; things no longer work right. Try it and see! + + ; overloadable operators + (op-sym1 + "[---+*/%^&|~!=<>]\\|[---+*/%^&|<>=!]=\\|<<=?\\|>>=?") + (op-sym2 + "&&\\|||\\|\\+\\+\\|--\\|()\\|\\[\\]") + (op-sym (concat "\\(" op-sym1 "\\|" op-sym2 "\\)")) + ; whitespace + (middle "[^\\*]*\\(\\*+[^/\\*][^\\*]*\\)*") + (c-comment (concat "/\\*" middle "\\*+/")) + (wh (concat "\\(\\s \\|\n\\|//.*$\\|" c-comment "\\)")) + (wh-opt (concat wh "*")) + (wh-nec (concat wh "+")) + (oper (concat "\\(" "operator" "\\(" + wh-opt op-sym "\\|" wh-nec id "\\)" "\\)")) + (dcl-list "([^():]*)") + (func-name (concat "\\(" oper "\\|" id "::" id "\\|" id "\\)")) + (inits + (concat "\\(:" + "\\(" wh-opt id "(.*\\()" wh-opt "," "\\)\\)*" + wh-opt id "(.*)" wh-opt "{" + "\\|" wh-opt "{\\)")) + (type-name (concat + "\\(" c++-defun-header-strong-struct-equivs wh-nec "\\)?" + id)) + (type (concat "\\(const" wh-nec "\\)?" + "\\(" type-name "\\|" type-name wh-opt "\\*+" "\\|" + type-name wh-opt "&" "\\)")) + (modifier "\\(inline\\|virtual\\|overload\\|auto\\|static\\)") + (modifiers (concat "\\(" modifier wh-nec "\\)*")) + (func-header + ;; type arg-dcl + (concat modifiers type wh-nec func-name wh-opt dcl-list wh-opt inits)) + (inherit (concat "\\(:" wh-opt "\\(public\\|protected\\|private\\)?" + wh-nec id "\\)")) + (cs-header (concat + c++-defun-header-strong-struct-equivs + wh-nec id wh-opt inherit "?" wh-opt "{"))) + (concat "^\\(" func-header "\\|" cs-header "\\)")) + "Strongly-defined regexp to match beginning of structure or + function definition.") + + + ;; This part has to do with recognizing defuns. + + ;; The weak convention we will use is that a defun begins any time + ;; there is a left curly brace, or some identifier on the left margin, + ;; followed by a left curly somewhere on the line. (This will also + ;; incorrectly match some continued strings, but this is after all + ;; just a weak heuristic.) Suggestions for improvement (short of the + ;; strong scheme shown above) are welcomed. + + (defconst c++-defun-header-weak "^{\\|^[_a-zA-Z].*{" + "Weakly-defined regexp to match beginning of structure or function definition.") + + + (defun c++-beginning-of-defun (&optional arg) + (interactive "p") + (if (not arg) (setq arg 1)) + (let ((c++-defun-header (if c++-match-header-strongly + c++-defun-header-strong + c++-defun-header-weak))) + (cond + ((or (= arg 0) (and (> arg 0) (bobp))) nil) + ((and (not (looking-at c++-defun-header)) + (let ((curr-pos (point)) + (open-pos (if (search-forward "{" nil 'move) + (point))) + (beg-pos + (if (re-search-backward c++-defun-header nil 'move) + (match-beginning 0)))) + (if (and open-pos beg-pos + (< beg-pos curr-pos) + (> open-pos curr-pos)) + (progn + (goto-char beg-pos) + (if (= arg 1) t nil));; Are we done? + (goto-char curr-pos) + nil)))) + (t + (if (and (looking-at c++-defun-header) (not (bobp))) + (forward-char (if (< arg 0) 1 -1))) + (and (re-search-backward c++-defun-header nil 'move (or arg 1)) + (goto-char (match-beginning 0))))))) + + + (defun c++-end-of-defun (arg) + (interactive "p") + (let ((c++-defun-header (if c++-match-header-strongly + c++-defun-header-strong + c++-defun-header-weak)) + (parse-sexp-ignore-comments t)) + (if (and (eobp) (> arg 0)) + nil + (if (and (> arg 0) (looking-at c++-defun-header)) (forward-char 1)) + (let ((pos (point))) + (c++-beginning-of-defun + (if (< arg 0) + (- (- arg (if (eobp) 0 1))) + arg)) + (if (and (< arg 0) (bobp)) + t + (if (re-search-forward c++-defun-header nil 'move) + (progn (forward-char -1) + (forward-sexp) + (beginning-of-line 2))) + (if (and (= pos (point)) + (re-search-forward c++-defun-header nil 'move)) + (c++-end-of-defun 1)))) + t))) + + (defun c++-indent-defun () + "Indents the current function def, struct or class decl." + (interactive) + (let ((restore (point))) + (c++-end-of-defun 1) + (beginning-of-line 1) + (let ((end (point-marker))) + (c++-beginning-of-defun) + (while (and (< (point) end)) + (c++-indent-line) + (forward-line 1) + (beginning-of-line 1)) + (set-marker end nil)) + (goto-char restore))) + + + ;; ====================================================================== + ;; defuns for submitting bug reports + ;; ====================================================================== + (defconst c++-version "2.334" + "c++-mode version number.") + (defconst c++-mode-help-address "c++-mode-help@anthem.nlm.nih.gov" + "Address accepting submission of bug reports.") + + (defun c++-version () + "Echo the current version of c++-mode." + (interactive) + (message "Using c++-mode.el %s" c++-version)) + + (defun c++-submit-bug-report () + "Submit via mail a bug report on c++-mode." + (interactive) + (require 'reporter) + (and + (y-or-n-p "Do you want to submit a report on c++-mode? ") + (reporter-submit-bug-report + c++-mode-help-address + (concat "c++-mode.el " c++-version " (editing " + (if (eq major-mode 'c++-mode) "C++" "C") + " code)") + (list + 'c++-emacs-features + 'c++-C-block-comments-indent-p + 'c++-access-specifier-offset + 'c++-always-arglist-indent-p + 'c++-auto-hungry-initial-state + 'c++-auto-hungry-toggle + 'c++-auto-newline + 'c++-backscan-limit + 'c++-block-close-brace-offset + 'c++-cleanup-list + 'c++-comment-only-line-offset + 'c++-continued-member-init-offset + 'c++-default-macroize-column + 'c++-defun-header-strong-struct-equivs + 'c++-delete-function + 'c++-electric-pound-behavior + 'c++-empty-arglist-indent + 'c++-friend-offset + 'c++-hanging-braces + 'c++-hanging-member-init-colon + 'c++-hungry-delete-key + 'c++-match-header-strongly + 'c++-member-init-indent + 'c++-paren-as-block-close-p + 'c++-relative-offset-p + 'c++-tab-always-indent + 'c++-untame-characters + 'c-argdecl-indent + 'c-brace-imaginary-offset + 'c-brace-offset + 'c-continued-brace-offset + 'c-continued-statement-offset + 'c-indent-level + 'c-label-offset + 'tab-width + ) + (function + (lambda () + (insert + (if c++-special-indent-hook + (concat "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" + "c++-special-indent-hook is set to '" + (format "%s" c++-special-indent-hook) + ".\nPerhaps this is your problem?\n" + "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n\n") + "\n") + ))) + ))) + + + ;; this is sometimes useful + (provide 'c++-mode) + + ;;; c++-mode.el ends here + diff -crP -x *.elc -x *.info* emacs-19.11/lisp/cl.el emacs-19.12/lisp/cl.el *** emacs-19.11/lisp/cl.el Mon May 31 20:10:36 1993 --- emacs-19.12/lisp/cl.el Tue Jun 1 12:30:22 1993 *************** *** 1804,1810 **** ;;; These two functions access the implementation-dependent representation of ;;; the multiple value returns. ! (defun mod (number divisor) "Return remainder of X by Y (rounding quotient toward minus infinity). That is, the remainder goes with the quotient produced by `cl-floor'. Emacs Lisp hint: --- 1804,1810 ---- ;;; These two functions access the implementation-dependent representation of ;;; the multiple value returns. ! (defun cl-mod (number divisor) "Return remainder of X by Y (rounding quotient toward minus infinity). That is, the remainder goes with the quotient produced by `cl-floor'. Emacs Lisp hint: diff -crP -x *.elc -x *.info* emacs-19.11/lisp/desktop.el emacs-19.12/lisp/desktop.el *** emacs-19.11/lisp/desktop.el --- emacs-19.12/lisp/desktop.el Tue Jun 1 16:11:54 1993 *************** *** 0 **** --- 1,344 ---- + ;;; desktop.el --- save partial status of Emacs when killed + + ;; Copyright (C) 1993 Free Software Foundation, Inc. + + ;; Author: Morten Welinder + ;; Version: 2.01 + + ;; 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, 675 Mass Ave, Cambridge, MA 02139, USA. + + ;;; Commentary: + + ; Save the Desktop, i.e., + ; - some global variables + ; - the list of buffers with associated files. For each buffer also + ; - the major mode + ; - the default directory + ; - the point + ; - the mark + ; - buffer-read-only + ; - truncate-lines + ; - case-fold-search + ; - case-replace + ; - fill-column + + ; To use this, first put these three lines in the bottom of your .emacs + ; file (the later the better): + ; + ; (load "desktop") + ; (desktop-load-default) + ; (desktop-read) + ; + + ; Start Emacs in the root directory of your "project". The desktop saver + ; is inactive by default. You activate it by M-X desktop-save RET. When + ; you exit the next time the above data will be saved. This ensures that + ; all the files you were editing will be reloaded the next time you start + ; Emacs from the same directory and that points will be set where you + ; left them. + ; + ; PLEASE NOTE: When the kill ring is saved as specified by the variable + ; `desktop-globals-to-save' (by default it isn't). This may result in saving + ; things you did not mean to keep. Use M-X desktop-clear RET. + ; + ; Thanks to hetrick@phys.uva.nl (Jim Hetrick) for useful ideas. + ; --------------------------------------------------------------------------- + ; HISTORY: + ; + ; Dec , 1992: Version 1.0 written; never released. + ; Jan , 1993: Minor modes now saved: auto-fill-mode, overwrite-mode. + ; Apr 26, 1993: Version 1.1 released. + ; Apr 29, 1993: Now supports RMAIL, Info, and dired modes. + ; Will now search home directory for desktop file. + ; desktop-save asks for directory to save in. + ; May 31, 1993: Version 1.3 + ; Now works with Emacs 19. + ; Jun 1, 1993: Minor bug fix. + ; + ; TODO: + ; + ; Save window configuration. + ; Recognize more minor modes. + ; Save mark rings. + ; Start-up with buffer-menu??? + + ;;; Code: + + ; USER OPTIONS -- settings you might want to play with. + ; ----------------------------------------------------------------------------- + (defconst desktop-basefilename + (if (equal system-type 'ms-dos) + "emacs.dsk" ; Ms-Dos does not support multiple dots in file name + ".emacs.desktop") + "File for Emacs desktop. A directory name will be prepended to this name.") + + (defvar desktop-missing-file-warning t + "*If non-nil then issue warning if a file no longer exists. + Otherwise simply ignore the file.") + + (defvar desktop-globals-to-save + (list 'desktop-missing-file-warning + ; 'kill-ring ; Feature: Also saves kill-ring-yank-pointer + 'desktop-globals-to-save) ; Itself! + "List of global variables to save when killing Emacs.") + + (defvar desktop-buffers-not-to-save + "\\(\\.log\\|(ftp)\\)$" + "Regexp identifying buffers that are to be excluded from saving.") + + (defvar desktop-buffer-handlers + '(desktop-buffer-dired + desktop-buffer-rmail + desktop-buffer-info + desktop-buffer-file) + "*List of functions to call in order to create a buffer. + The functions are called without parameters + but may access the the major mode as `mam', + the file name as `fn', the buffer name as `bn', the default directory as + `dd'. If some function returns non-nil no further functions are called. + If the function returns t then the buffer is considered created.") + ; --------------------------------------------------------------------------- + (defvar desktop-dirname nil + "The directory in which the current desktop file resides.") + + (defconst desktop-header + "; --------------------------------------------------------------------------- + ; Desktop File for Emacs + ; --------------------------------------------------------------------------- + " "*Header to place in Desktop file.") + ; --------------------------------------------------------------------------- + (defconst postv18 + (string-lessp "19" emacs-version) + "t is Emacs version 19 or later.") + + (defun desktop-clear () "Empty the Desktop." + (interactive) + (setq kill-ring nil) + (setq kill-ring-yank-pointer nil) + (mapcar (function kill-buffer) (buffer-list))) + ; --------------------------------------------------------------------------- + (if (not (boundp 'desktop-kill)) + (if postv18 + (add-hook 'kill-emacs-hook 'desktop-kill) + (setq old-kill-emacs kill-emacs-hook) + (setq kill-emacs-hook + (function (lambda () (progn (desktop-kill) + (run-hooks old-kill-emacs))))))) + ; --------------------------------------------------------------------------- + (defun desktop-kill () + (if desktop-dirname + (progn + (desktop-save desktop-dirname)))) + + ;(defun kill-emacs (&optional query) + ; "End this Emacs session. + ;Prefix ARG or optional first ARG non-nil means exit with no questions asked, + ;even if there are unsaved buffers. If Emacs is running non-interactively + ;and ARG is an integer, then Emacs exits with ARG as its exit code. + ; + ;If the variable `desktop-dirname' is non-nil, + ;the function desktop-save will be called first." + ; (interactive "P") + ; (if desktop-dirname (desktop-save desktop-dirname)) + ; (original-kill-emacs query)) + ; --------------------------------------------------------------------------- + (defun desktop-outvar (VAR) + "Output a setq statement for VAR to the desktop file." + (if (boundp VAR) + (progn + (insert "(setq ") + (prin1 VAR (current-buffer)) + (insert " '") + (prin1 (symbol-value VAR) (current-buffer)) + (insert ")\n")))) + ; --------------------------------------------------------------------------- + (defun desktop-save-buffer-p (filename bufname mode) + "Return t if should record a particular buffer for next startup. + FILENAME is the visited file name, BUFNAME is the buffer name, and + MODE is the major mode." + + (or (and filename + (not (string-match desktop-buffers-not-to-save bufname))) + (and (null filename) + (memq mode '(Info-mode dired-mode rmail-mode))))) + ; --------------------------------------------------------------------------- + (defun desktop-save (dirname) + "Save the Desktop file. Parameter DIRNAME specifies where to save desktop." + (interactive "DDirectory to save desktop file in: ") + (save-excursion + (let ((filename (expand-file-name + (concat dirname desktop-basefilename))) + (info (nreverse + (mapcar + (function (lambda (b) + (set-buffer b) + (list + (buffer-file-name) + (buffer-name) + (list 'quote major-mode) + (list 'quote + (list overwrite-mode + (not (null + (if postv18 + auto-fill-function + auto-fill-hook))))) + (point) + (if postv18 + (mark t) + (mark)) + buffer-read-only + truncate-lines + fill-column + case-fold-search + case-replace + (list + 'quote + (cond ((equal major-mode 'Info-mode) + (list Info-current-file + Info-current-node)) + ((equal major-mode 'dired-mode) + (list default-directory)) + )) + ))) + (buffer-list)))) + (buf (get-buffer-create "*desktop*"))) + (set-buffer buf) + (erase-buffer) + + (insert desktop-header + "; Created " (current-time-string) "\n" + "; Emacs version " emacs-version "\n\n" + "; Global section:\n") + (mapcar (function desktop-outvar) desktop-globals-to-save) + (if (memq 'kill-ring desktop-globals-to-save) + (insert "(setq kill-ring-yank-pointer (nthcdr " + (int-to-string + (- (length kill-ring) (length kill-ring-yank-pointer))) + " kill-ring))\n")) + + (insert "\n; Buffer section:\n") + (mapcar + (function (lambda (l) + (if (desktop-save-buffer-p + (car l) + (nth 1 l) + (nth 1 (nth 2 l))) + (progn + (insert "(desktop-buffer") + (mapcar + (function (lambda (e) + (insert "\n ") + (prin1 e (current-buffer)))) + l) + (insert ")\n\n"))))) + info) + (setq default-directory dirname) + (if (file-exists-p filename) (delete-file filename)) + (write-region (point-min) (point-max) filename nil 'nomessage))) + (setq desktop-dirname dirname)) + ; --------------------------------------------------------------------------- + (defun desktop-remove () + "Delete the Desktop file and inactivate the desktop system." + (interactive) + (if desktop-dirname + (let ((filename (concat desktop-dirname desktop-basefilename))) + (if (file-exists-p filename) (delete-file filename)) + (setq desktop-dirname nil)))) + ; --------------------------------------------------------------------------- + (defun desktop-read () + "Read the Desktop file and the files it specifies." + (interactive) + (let ((filename)) + (if (file-exists-p (concat "./" desktop-basefilename)) + (setq desktop-dirname (expand-file-name "./")) + (if (file-exists-p (concat "~/" desktop-basefilename)) + (setq desktop-dirname (expand-file-name "~/")) + (setq desktop-dirname nil))) + (if desktop-dirname + (progn + (load (concat desktop-dirname desktop-basefilename) t t t) + (message "Desktop loaded.")) + (desktop-clear)))) + ; --------------------------------------------------------------------------- + (defun desktop-load-default () + "Load the `default' start-up library manually. + Also inhibit further loading of it. + Call this from your `.emacs' file + provide correct modes for autoloaded files." + (if (not inhibit-default-init) + (progn + (load "default" t t) + (setq inhibit-default-init t)))) + ; --------------------------------------------------------------------------- + (defun desktop-buffer-info () "Load an info file." + (if (equal 'Info-mode mam) + (progn + (require 'info) + (Info-find-node (nth 0 misc) (nth 1 misc)) + t))) + ; --------------------------------------------------------------------------- + (defun desktop-buffer-rmail () "Load a RMAIL file." + (if (equal 'rmail-mode mam) + (progn (rmail-input fn) t))) + ; --------------------------------------------------------------------------- + (defun desktop-buffer-dired () "Load a directory using dired." + (if (equal 'dired-mode mam) + (progn (dired (nth 0 misc)) t))) + ; --------------------------------------------------------------------------- + (defun desktop-buffer-file () "Load a file." + (if fn + (if (or (file-exists-p fn) + (and desktop-missing-file-warning + (y-or-n-p (format + "File \"%s\" no longer exists. Re-create? " + fn)))) + (progn (find-file fn) t) + 'ignored))) + ; --------------------------------------------------------------------------- + ;;Create a buffer, load its file, set is mode, ...; called from Desktop file + ;; only. + (defun desktop-buffer (fn bn mam mim pt mk ro tl fc cfs cr misc) + (let ((hlist desktop-buffer-handlers) + (result) + (handler)) + (while (and (not result) hlist) + (setq handler (car hlist)) + (setq result (funcall handler)) + (setq hlist (cdr hlist))) + (if (equal result t) + (progn + (if (not (equal (buffer-name) bn)) + (rename-buffer bn)) + (if (nth 0 mim) + (overwrite-mode 1) + (overwrite-mode 0)) + (if (nth 1 mim) + (auto-fill-mode 1) + (overwrite-mode 0)) + (goto-char pt) + (set-mark mk) + (setq buffer-read-only ro) + (setq truncate-lines tl) + (setq fill-column fc) + (setq case-fold-search cfs) + (setq case-replace cr) + )))) + ; --------------------------------------------------------------------------- + + (provide 'desktop) + + ;; desktop.el ends here. diff -crP -x *.elc -x *.info* emacs-19.11/lisp/dired-aux.el emacs-19.12/lisp/dired-aux.el *** emacs-19.11/lisp/dired-aux.el Wed May 26 18:10:50 1993 --- emacs-19.12/lisp/dired-aux.el Tue Jun 1 14:01:38 1993 *************** *** 486,499 **** (funcall handler 'dired-compress-file file)) ((file-symlink-p file) nil) ! ((string-match "\\.Z$" file) (if (not (dired-check-process (concat "Uncompressing " file) "uncompress" file)) (substring file 0 -2))) (t ! (if (not (dired-check-process (concat "Compressing " file) ! "compress" "-f" file)) ! (concat file ".Z")))))) (defun dired-mark-confirm (op-symbol arg) ;; Request confirmation from the user that the operation described --- 486,511 ---- (funcall handler 'dired-compress-file file)) ((file-symlink-p file) nil) ! ((let (case-fold-search) ! (string-match "\\.Z$" file)) (if (not (dired-check-process (concat "Uncompressing " file) "uncompress" file)) (substring file 0 -2))) + ((let (case-fold-search) + (string-match "\\.gz$" file)) + (if (not (dired-check-process (concat "Uncompressing " file) + "gunzip" file)) + (substring file 0 -3))) (t ! ;;; Try gzip; if we don't have that, use compress. ! (condition-case nil ! (if (not (dired-check-process (concat "Compressing " file) ! "gzip" "-f" file)) ! (concat file ".gz")) ! (file-error ! (if (not (dired-check-process (concat "Compressing " file) ! "compress" "-f" file)) ! (concat file ".Z")))))))) (defun dired-mark-confirm (op-symbol arg) ;; Request confirmation from the user that the operation described diff -crP -x *.elc -x *.info* emacs-19.11/lisp/fortran.el emacs-19.12/lisp/fortran.el *** emacs-19.11/lisp/fortran.el Mon Mar 22 09:41:41 1993 --- emacs-19.12/lisp/fortran.el Tue Jun 1 15:02:57 1993 *************** *** 1,10 **** ;;; fortran.el --- Fortran mode for GNU Emacs ! ;;; Copyright (c) 1986, 1992 Free Software Foundation, Inc. ;; Author: Michael D. Prange ;; Maintainer: bug-fortran-mode@erl.mit.edu ! ;; Version 1.30 (February 2, 1993) ;; Keywords: languages ;; This file is part of GNU Emacs. --- 1,10 ---- ;;; fortran.el --- Fortran mode for GNU Emacs ! ;;; Copyright (c) 1986, 1993 Free Software Foundation, Inc. ;; Author: Michael D. Prange ;; Maintainer: bug-fortran-mode@erl.mit.edu ! ;; Version 1.30.2 (June 1, 1993) ;; Keywords: languages ;; This file is part of GNU Emacs. *************** *** 41,51 **** ;;; Replace: ;;; frame-width with screen-width ;;; auto-fill-function with auto-fill-hook ;;; (setq unread-command-events (list c)) with (setq unread-command-char c) ;;; Bugs to bug-fortran-mode@erl.mit.edu ! (defconst fortran-mode-version "version 1.30") ;;; Code: --- 41,52 ---- ;;; Replace: ;;; frame-width with screen-width ;;; auto-fill-function with auto-fill-hook + ;;; comment-indent-function with comment-indent-hook ;;; (setq unread-command-events (list c)) with (setq unread-command-char c) ;;; Bugs to bug-fortran-mode@erl.mit.edu ! (defconst fortran-mode-version "version 1.30.2") ;;; Code: *************** *** 551,557 **** (fortran-indent-line)) ;when the cont string is C, c or *. (defun fortran-numerical-continuation-char () ! "Return a digit for tab-digit style of continution lines. If, previous line is a tab-digit continuation line, returns that digit plus one. Otherwise return 1. Zero not allowed." (save-excursion --- 552,558 ---- (fortran-indent-line)) ;when the cont string is C, c or *. (defun fortran-numerical-continuation-char () ! "Return a digit for tab-digit style of continuation lines. If, previous line is a tab-digit continuation line, returns that digit plus one. Otherwise return 1. Zero not allowed." (save-excursion *************** *** 832,837 **** --- 833,840 ---- (looking-at " [^ 0\n]") (looking-at "\t[1-9]")) (setq icol (+ icol fortran-continuation-indent))) + ((looking-at "[ \t]*#") ; Check for cpp directive. + (setq fortran-minimum-statement-indent 0 icol 0)) (first-statement) ((and fortran-check-all-num-for-matching-do (looking-at "[ \t]*[0-9]+") *************** *** 1013,1046 **** t)) nil))) ! (defun fortran-is-in-string-p (pos) ! "Return t if POS (a buffer position) is inside a standard Fortran string. ! Fortran strings are delimeted by apostrophes (\'). Quote-Escape-sequences ! (\\'), strings delimited by \" and detection of syntax-errors ! (unbalanced quotes) are NOT supported." ! ;;; The algorithm is simple: start at point with value nil ! ;;; and toggle value at each quote found until end of line. ! ;;; The quote skip is hard-coded, maybe it's possible to change this ! ;;; and use something like 'string-constant-delimiter' (which ! ;;; doesn't exist yet) so this function can be used by other modes, ! ;;; but then one must pay attention to escape sequences, multi-line-constants ! ;;; and such things. ! (let ((is-in-fortran-string nil)) ! (save-excursion ! (goto-char pos) ! (if (not (fortran-previous-statement)) ! (fortran-next-statement)) ! (while (< (point) pos) ! ;; Make sure we don't count quotes in continuation column. ! (if (looking-at "^ ") ! (goto-char (+ 1 (match-end 0))) ! (if (and (not is-in-fortran-string) ! (looking-at comment-start-skip)) ! (beginning-of-line 2) ! (if (looking-at "'") ! (setq is-in-fortran-string (not is-in-fortran-string))) ! (forward-char 1))))) ! is-in-fortran-string)) (defun fortran-auto-fill-mode (arg) "Toggle fortran-auto-fill mode. --- 1016,1084 ---- t)) nil))) ! ;;;From: ralf@up3aud1.gwdg.de (Ralf Fassel) ! ;;; Test if TAB format continuation lines work. ! (defun fortran-is-in-string-p (where) ! "Return non-nil if POS (a buffer position) is inside a Fortran string, ! nil else." ! (save-excursion ! (goto-char where) ! (cond ! ((bolp) nil) ; bol is never inside a string ! ((save-excursion ; comment lines too ! (beginning-of-line)(looking-at comment-line-start-skip)) nil) ! (t (let (;; ok, serious now. Init some local vars: ! (parse-state '(0 nil nil nil nil nil 0)) ! (quoted-comment-start (if comment-start ! (regexp-quote comment-start))) ! (not-done t) ! parse-limit ! end-of-line ! ) ! ;; move to start of current statement ! (fortran-next-statement) ! (fortran-previous-statement) ! ;; now parse up to WHERE ! (while not-done ! (if (or ;; skip to next line if: ! ;; - comment line? ! (looking-at comment-line-start-skip) ! ;; - at end of line? ! (eolp) ! ;; - not in a string and after comment-start? ! (and (not (nth 3 parse-state)) ! comment-start ! (equal comment-start ! (char-to-string (preceding-char))))) ! ;; get around a bug in forward-line in versions <= 18.57 ! (if (or (> (forward-line 1) 0) (eobp)) ! (setq not-done nil)) ! ;; else: ! ;; if we are at beginning of code line, skip any ! ;; whitespace, labels and tab continuation markers. ! (if (bolp) (skip-chars-forward " \t0-9")) ! ;; if we are in column <= 5 now, check for continuation char ! (cond ((= 5 (current-column)) (forward-char 1)) ! ((and (< (current-column) 5) ! (equal fortran-continuation-string ! (char-to-string (following-char))) ! (forward-char 1)))) ! ;; find out parse-limit from here ! (setq end-of-line (save-excursion (end-of-line)(point))) ! (setq parse-limit (min where end-of-line)) ! ;; parse max up to comment-start, if non-nil and in current line ! (if comment-start ! (save-excursion ! (if (re-search-forward quoted-comment-start end-of-line t) ! (setq parse-limit (min (point) parse-limit))))) ! ;; now parse if still in limits ! (if (< (point) where) ! (setq parse-state (parse-partial-sexp ! (point) parse-limit nil nil parse-state)) ! (setq not-done nil)) ! )) ! ;; result is ! (nth 3 parse-state)))))) (defun fortran-auto-fill-mode (arg) "Toggle fortran-auto-fill mode. *************** *** 1093,1098 **** --- 1131,1137 ---- (if (<= (point) (1+ bos)) (progn (move-to-column (1+ fill-column)) + ;;;what is this doing??? (if (not (re-search-forward "[\t\n,'+-/*)=]" eol t)) (goto-char bol)))) (if (bolp) *************** *** 1195,1197 **** --- 1234,1237 ---- (provide 'fortran) ;;; fortran.el ends here + diff -crP -x *.elc -x *.info* emacs-19.11/lisp/loaddefs.el emacs-19.12/lisp/loaddefs.el *** emacs-19.11/lisp/loaddefs.el Mon May 31 17:54:09 1993 --- emacs-19.12/lisp/loaddefs.el Tue Jun 1 19:19:03 1993 *************** *** 4475,4480 **** --- 4475,4500 ---- ;;;*** + ;;;### (autoloads (tar-mode) "tar-mode" "/home/fsf/rms/e19/lisp/tar-mode.el" (11275 52507)) + ;;; Generated autoloads from /home/fsf/rms/e19/lisp/tar-mode.el + + (autoload (quote tar-mode) "tar-mode" "\ + Major mode for viewing a tar file as a dired-like listing of its contents. + You can move around using the usual cursor motion commands. + Letters no longer insert themselves. + Type 'e' to pull a file out of the tar file and into its own buffer. + Type 'c' to copy an entry from the tar file into another file on disk. + + If you edit a sub-file of this archive (as with the 'e' command) and + save it with Control-X Control-S, the contents of that buffer will be + saved back into the tar-file buffer; in this way you can edit a file + inside of a tar archive without extracting it and re-archiving it. + + See also: variables tar-update-datestamp and tar-anal-blocksize. + \\{tar-mode-map}" nil nil) + + ;;;*** + ;;;### (autoloads (rsh telnet) "telnet" "telnet.el" (11223 20968)) ;;; Generated autoloads from telnet.el diff -crP -x *.elc -x *.info* emacs-19.11/lisp/lucid.el emacs-19.12/lisp/lucid.el *** emacs-19.11/lisp/lucid.el Tue Jun 1 02:00:53 1993 --- emacs-19.12/lisp/lucid.el Tue Jun 1 14:23:43 1993 *************** *** 70,76 **** This includes bindings inherited from a parent keymap. FUNCTION receives two arguments each time it is called: the character (more generally, the event type) that is bound, ! and the binding it has." (if sort-first (let (list) (map-keymap (function (lambda (a b) --- 70,81 ---- This includes bindings inherited from a parent keymap. FUNCTION receives two arguments each time it is called: the character (more generally, the event type) that is bound, ! and the binding it has. ! ! Note that passing the event type directly to `define-key' does not work ! in Emacs 19. We do not emulate that particular feature of Lucid Emacs. ! If your code does that, modify it to make a vector containing the event ! type that you get. That will work in both versions of Emacs." (if sort-first (let (list) (map-keymap (function (lambda (a b) diff -crP -x *.elc -x *.info* emacs-19.11/lisp/menu-bar.el emacs-19.12/lisp/menu-bar.el *** emacs-19.11/lisp/menu-bar.el Mon May 24 01:05:54 1993 --- emacs-19.12/lisp/menu-bar.el Tue Jun 1 16:54:01 1993 *************** *** 105,111 **** pending-undo-list) buffer-undo-list))) ! (define-key global-map [menu-bar buffer] '("Buffers" . mouse-buffer-menu)) (defvar complex-buffers-menu-p nil "*Non-nil says, offer a choice of actions after you pick a buffer. --- 105,111 ---- pending-undo-list) buffer-undo-list))) ! (define-key global-map [menu-bar buffer] '("Buffers" . mouse-menu-bar-buffers)) (defvar complex-buffers-menu-p nil "*Non-nil says, offer a choice of actions after you pick a buffer. *************** *** 117,123 **** If this is nil, then all buffers are shown. A large number or nil slows down menu responsiveness.") ! (defun mouse-buffer-menu (event) "Pop up a menu of buffers for selection with the mouse. This switches buffers in the window that you clicked on, and selects that window." --- 117,123 ---- If this is nil, then all buffers are shown. A large number or nil slows down menu responsiveness.") ! (defun mouse-menu-bar-buffers (event) "Pop up a menu of buffers for selection with the mouse. This switches buffers in the window that you clicked on, and selects that window." diff -crP -x *.elc -x *.info* emacs-19.11/lisp/mouse.el emacs-19.12/lisp/mouse.el *** emacs-19.11/lisp/mouse.el Sat May 29 00:33:37 1993 --- emacs-19.12/lisp/mouse.el Tue Jun 1 18:18:39 1993 *************** *** 258,264 **** (window (posn-window (event-start event)))) (if buf (progn ! (select-window window) (switch-to-buffer buf)))))) ;;; These need to be rewritten for the new scroll bar implementation. --- 258,264 ---- (window (posn-window (event-start event)))) (if buf (progn ! (or (framep window) (select-window window)) (switch-to-buffer buf)))))) ;;; These need to be rewritten for the new scroll bar implementation. diff -crP -x *.elc -x *.info* emacs-19.11/lisp/reporter.el emacs-19.12/lisp/reporter.el *** emacs-19.11/lisp/reporter.el --- emacs-19.12/lisp/reporter.el Tue Jun 1 18:26:20 1993 *************** *** 0 **** --- 1,194 ---- + ;;; reporter.el --- customizable bug reporting of lisp programs + + ;; Author: 1993 Barry A. Warsaw, Century Computing Inc. + ;; Maintainer: bwarsaw@cen.com + ;; Created: 19-Apr-1993 + ;; Version: 1.18 + ;; Last Modified: 1993/05/22 00:29:49 + ;; Keywords: bug reports lisp + + ;; Copyright (C) 1993 Free Software Foundation, Inc. + + ;; This file is not yet part of GNU Emacs. + ;; + ;; 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 of the License, 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; if not, write to the Free Software + ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + ;; Introduction + ;; ============ + ;; This program is for lisp package authors and is used to ease + ;; reporting of bugs. When invoked, reporter-submit-bug-report will + ;; set up a mail buffer with the appropriate bug report address, + ;; including a lisp expression the maintainer of the package can use + ;; to completely reproduce the environment in which the bug was + ;; observed (e.g. by using eval-last-sexp). This package is especially + ;; useful for my development of c++-mode.el, which is highly dependent + ;; on its configuration variables. + ;; + ;; Do a "C-h f reporter-submit-bug-report" for more information. + ;; Here's an example usage: + ;; + ;; (defconst mypkg-version "9.801") + ;; (defconst mypkg-maintainer-address "mypkg-help@foo.com") + ;; (defun mypkg-submit-bug-report () + ;; "Submit via mail a bug report on mypkg" + ;; (interactive) + ;; (require 'reporter) + ;; (and (y-or-n-p "Do you really want to submit a report on mypkg? ") + ;; (reporter-submit-bug-report + ;; mypkg-maintainer-address + ;; (concat "mypkg.el " mypkg-version) + ;; (list 'mypkg-variable-1 + ;; 'mypkg-variable-2 + ;; ;; ... + ;; 'mypkg-variable-last)))) + + ;; Mailing List + ;; ============ + ;; I've set up a mailing list to report bugs or suggest enhancements, + ;; etc. This list's intended audience is elisp package authors who are + ;; using reporter and want to stay current with releases. Here are the + ;; relevent addresses: + ;; + ;; Administrivia: reporter-request@anthem.nlm.nih.gov + ;; Submissions: reporter@anthem.nlm.nih.gov + + ;; LCD Archive Entry: + ;; reporter|Barry A. Warsaw|warsaw@cen.com| + ;; Customizable bug reporting of lisp programs.| + ;; 1993/05/22 00:29:49|1.18|~/misc/reporter.el.Z| + + ;;; Code: + + + ;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + ;; user defined variables + + (defvar reporter-mailer 'mail + "*Mail package to use to generate bug report buffer.") + + ;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ;; end of user defined variables + + + (defun reporter-dump-variable (varsym) + "Pretty-print the value of the variable in symbol VARSYM." + (let ((val (eval varsym)) + (sym (symbol-name varsym)) + (print-escape-newlines t)) + (insert " " sym " " + (cond + ((memq val '(t nil)) "") + ((listp val) "'") + ((symbolp val) "'") + (t "")) + (prin1-to-string val) + "\n"))) + + (defun reporter-dump-state (pkgname varlist pre-hooks post-hooks) + "Dump the state of the mode specific variables. + PKGNAME contains the name of the mode as it will appear in the bug + report (you must explicitly concat any version numbers). + + VARLIST is the list of variables to dump. Each element in VARLIST can + be a variable symbol, or a cons cell. If a symbol, this will be + passed to `reporter-dump-variable' for insertion into the mail buffer. + If a cons cell, the car must be a variable symbol and the cdr must be + a function which will be `funcall'd with the symbol. Use this to write + your own custom variable value printers for specific variables. + + PRE-HOOKS is run after the emacs-version and PKGNAME are inserted, but + before the VARLIST is dumped. POST-HOOKS is run after the VARLIST is + dumped." + (let ((buffer (current-buffer))) + (set-buffer buffer) + (insert "Emacs : " (emacs-version) "\nPackage: " pkgname "\n") + (run-hooks 'pre-hooks) + (insert "\ncurrent state:\n==============\n(setq\n") + (mapcar + (function + (lambda (varsym-or-cons-cell) + (let ((varsym (or (car-safe varsym-or-cons-cell) + varsym-or-cons-cell)) + (printer (or (cdr-safe varsym-or-cons-cell) + 'reporter-dump-variable))) + (funcall printer varsym) + ))) + varlist) + (insert " )\n") + (run-hooks 'post-hooks) + )) + + (defun reporter-submit-bug-report + (address pkgname varlist &optional pre-hooks post-hooks salutation) + "Submit a bug report via mail. + + ADDRESS is the email address for the package's maintainer. PKGNAME is + the name of the mode (you must explicitly concat any version numbers). + VARLIST is the list of variables to dump (do a `\\[describe-function] reporter-dump-state' + for details). Optional PRE-HOOKS and POST-HOOKS are passed to + `reporter-dump-state'. Optional SALUTATION is inserted at the top of the + mail buffer, and point is left after the saluation. + + The mailer used is described in the variable `reporter-mailer'." + + (let ((curbuf (current-buffer)) + (mailbuf (progn (call-interactively reporter-mailer) + (current-buffer)))) + (require 'sendmail) + (pop-to-buffer curbuf) + (pop-to-buffer mailbuf) + (goto-char (point-min)) + ;; different mailers use different separators, some may not even + ;; use m-h-s, but sendmail.el stuff must have m-h-s bound. + (let ((mail-header-separator + (save-excursion + (re-search-forward + (concat + "^\\(" ;beginning of line + (mapconcat + 'identity + (list "[\t ]*" ;simple SMTP form + "-+" ;mh-e form + (regexp-quote + mail-header-separator)) ;sendmail.el form + "\\|") ;or them together + "\\)$") ;end of line + nil + 'move) ;search for and move + (buffer-substring (match-beginning 0) (match-end 0))))) + (mail-position-on-field "to") + (insert address) + (mail-position-on-field "subject") + (insert "Report on package " pkgname) + (re-search-forward mail-header-separator (point-max) 'move) + (forward-line 1) + (and salutation (insert "\n" salutation "\n\n")) + (set-mark (point)) ;user should see mark change + (insert "\n\n") + (reporter-dump-state pkgname varlist pre-hooks post-hooks) + (exchange-point-and-mark)) + (let* ((sendkey "C-c C-c") ;can this be generalized like below? + (killkey-whereis (where-is-internal 'kill-buffer nil t)) + (killkey (if killkey-whereis + (key-description killkey-whereis) + "M-x kill-buffer"))) + (message "Please type in your report. Hit %s to send, %s to abort." + sendkey killkey)) + )) + + ;; this is useful + (provide 'reporter) + + ;;; reporter.el ends here diff -crP -x *.elc -x *.info* emacs-19.11/lisp/sc.el emacs-19.12/lisp/sc.el *** emacs-19.11/lisp/sc.el Fri Jan 8 10:30:08 1993 --- emacs-19.12/lisp/sc.el Tue Jun 1 13:50:34 1993 *************** *** 96,102 **** ;; First, to connect supercite to any mail/news reading subsystem, put ;; this in your .emacs file: ;; ! ;; (setq mail-yank-hooks 'sc-cite-original) ; for all but MH-E ;; (setq mh-yank-hooks 'sc-cite-original) ; for MH-E only ;; ;; If supercite is not pre-loaded into your emacs session, you should --- 96,102 ---- ;; First, to connect supercite to any mail/news reading subsystem, put ;; this in your .emacs file: ;; ! ;; (add-hooks 'mail-yank-hooks 'sc-cite-original) ; for all but MH-E ;; (setq mh-yank-hooks 'sc-cite-original) ; for MH-E only ;; ;; If supercite is not pre-loaded into your emacs session, you should *************** *** 1512,1517 **** --- 1512,1518 ---- ;; ====================================================================== ;; this section contains default hooks and hook support for execution + ;;;###autoload (defun sc-cite-original () "Hook version of sc-cite. This is callable from the various mail and news readers' reply diff -crP -x *.elc -x *.info* emacs-19.11/lisp/sendmail.el emacs-19.12/lisp/sendmail.el *** emacs-19.11/lisp/sendmail.el Mon May 31 00:20:06 1993 --- emacs-19.12/lisp/sendmail.el Tue Jun 1 19:17:31 1993 *************** *** 76,82 **** --- 76,92 ---- (defvar mail-yank-prefix nil "*Prefix insert on lines of yanked message being replied to. nil means use indentation.") + (defvar mail-indentation-spaces 3 + "*Number of spaces to insert at the beginning of each cited line. + Used by `mail-yank-original' via `mail-yank-cite'.") + (defvar mail-yank-hooks '(mail-indent-citation) + "*Hook for modifying a citation just inserted in the mail buffer. + Each hook function can find the citation between (point) and (mark t). + And each hook function should leave point and mark around the citation + text as modified. + This is a normal hook, currently misnamed for historical reasons.") + (defvar mail-abbrevs-loaded nil) (defvar mail-mode-map nil) *************** *** 538,544 **** (end-of-line) (or atpoint (delete-region (point) (point-max))) ! (insert "\n\n--\n") (insert-file-contents (expand-file-name "~/.signature")))) (defun mail-fill-yanked-message (&optional justifyp) --- 548,554 ---- (end-of-line) (or atpoint (delete-region (point) (point-max))) ! (insert "\n\n") (insert-file-contents (expand-file-name "~/.signature")))) (defun mail-fill-yanked-message (&optional justifyp) *************** *** 553,558 **** --- 563,585 ---- justifyp t))) + (defun mail-indent-citation () + "Modify text just inserted from a message to be cited. + The inserted text should be the region. + When this function returns, the region is again around the modified text. + + Normally, indent each nonblank line `mail-indentation-spaces' spaces. + However, if `mail-yank-prefix' is non-nil, insert that prefix on each line." + (let ((start (point))) + (mail-yank-clear-headers start (mark t)) + (if (null mail-yank-prefix) + (indent-rigidly start (mark t) mail-indentation-spaces) + (save-excursion + (goto-char start) + (while (< (point) (mark t)) + (insert mail-yank-prefix) + (forward-line 1)))))) + (defun mail-yank-original (arg) "Insert the message being replied to, if any (in rmail). Puts point before the text and mark after. *************** *** 568,582 **** (insert-buffer mail-reply-buffer) (if (consp arg) nil ! (mail-yank-clear-headers start (mark t)) ! (if (null mail-yank-prefix) ! (indent-rigidly start (mark t) ! (if arg (prefix-numeric-value arg) 3)) ! (save-excursion ! (goto-char start) ! (while (< (point) (mark t)) ! (insert mail-yank-prefix) ! (forward-line 1))))) ;; This is like exchange-point-and-mark, but doesn't activate the mark. ;; It is cleaner to avoid activation, even though the command ;; loop would deactivate the mark because we inserted text. --- 595,604 ---- (insert-buffer mail-reply-buffer) (if (consp arg) nil ! (goto-char start) ! (let ((mail-indentation-spaces (if arg (prefix-numeric-value arg) ! mail-indentation-spaces))) ! (run-hooks 'mail-yank-hooks))) ;; This is like exchange-point-and-mark, but doesn't activate the mark. ;; It is cleaner to avoid activation, even though the command ;; loop would deactivate the mark because we inserted text. diff -crP -x *.elc -x *.info* emacs-19.11/lisp/shell.el emacs-19.12/lisp/shell.el *** emacs-19.11/lisp/shell.el Thu Apr 29 10:23:06 1993 --- emacs-19.12/lisp/shell.el Tue Jun 1 17:40:54 1993 *************** *** 144,150 **** (require 'comint) ;;;###autoload ! (defconst shell-prompt-pattern "^[^#$%>]*[#$%>] *" "Regexp to match prompts in the inferior shell. Defaults to \"^[^#$%>]*[#$%>] *\", which works pretty well. This variable is used to initialise `comint-prompt-regexp' in the --- 144,150 ---- (require 'comint) ;;;###autoload ! (defvar shell-prompt-pattern "^[^#$%>]*[#$%>] *" "Regexp to match prompts in the inferior shell. Defaults to \"^[^#$%>]*[#$%>] *\", which works pretty well. This variable is used to initialise `comint-prompt-regexp' in the diff -crP -x *.elc -x *.info* emacs-19.11/lisp/simple.el emacs-19.12/lisp/simple.el *** emacs-19.11/lisp/simple.el Mon May 24 17:18:57 1993 --- emacs-19.12/lisp/simple.el Tue Jun 1 16:31:13 1993 *************** *** 597,603 **** Repeat this command to undo more changes. A numeric argument serves as a repeat count." (interactive "*p") ! (let ((modified (buffer-modified-p))) (or (eq (selected-window) (minibuffer-window)) (message "Undo!")) (or (eq last-command 'undo) --- 597,604 ---- Repeat this command to undo more changes. A numeric argument serves as a repeat count." (interactive "*p") ! (let ((modified (buffer-modified-p)) ! (recent-save (recent-auto-save-p))) (or (eq (selected-window) (minibuffer-window)) (message "Undo!")) (or (eq last-command 'undo) *************** *** 606,612 **** (setq this-command 'undo) (undo-more (or arg 1)) (and modified (not (buffer-modified-p)) ! (delete-auto-save-file-if-necessary)))) (defvar pending-undo-list nil "Within a run of consecutive undo commands, list remaining to be undone.") --- 607,613 ---- (setq this-command 'undo) (undo-more (or arg 1)) (and modified (not (buffer-modified-p)) ! (delete-auto-save-file-if-necessary recent-save)))) (defvar pending-undo-list nil "Within a run of consecutive undo commands, list remaining to be undone.") diff -crP -x *.elc -x *.info* emacs-19.11/lisp/sort.el emacs-19.12/lisp/sort.el *** emacs-19.11/lisp/sort.el Sat Mar 27 15:38:47 1993 --- emacs-19.12/lisp/sort.el Tue Jun 1 16:35:26 1993 *************** *** 29,34 **** --- 29,37 ---- ;;; Code: + (defvar sort-fold-case nil + "*Non-nil if the buffer sort functions should ignore case.") + (defun sort-subr (reverse nextrecfun endrecfun &optional startkeyfun endkeyfun) "General text sorting routine to divide buffer into records and sort them. Arguments are REVERSE NEXTRECFUN ENDRECFUN &optional STARTKEYFUN ENDKEYFUN. *************** *** 69,75 **** (if messages (message "Finding sort keys...")) (let* ((sort-lists (sort-build-lists nextrecfun endrecfun startkeyfun endkeyfun)) ! (old (reverse sort-lists))) (if (null sort-lists) () (or reverse (setq sort-lists (nreverse sort-lists))) --- 72,79 ---- (if messages (message "Finding sort keys...")) (let* ((sort-lists (sort-build-lists nextrecfun endrecfun startkeyfun endkeyfun)) ! (old (reverse sort-lists)) ! (case-fold-search sort-fold-case)) (if (null sort-lists) () (or reverse (setq sort-lists (nreverse sort-lists))) diff -crP -x *.elc -x *.info* emacs-19.11/lisp/subr.el emacs-19.12/lisp/subr.el *** emacs-19.11/lisp/subr.el Fri May 28 12:40:08 1993 --- emacs-19.12/lisp/subr.el Tue Jun 1 16:51:58 1993 *************** *** 338,344 **** "Return the timestamp of POSITION. POSITION should be a list of the form (WINDOW BUFFER-POSITION (COL . ROW) TIMESTAMP) ! nas returned by the `event-start' and `event-end' functions." (nth 3 position)) --- 338,344 ---- "Return the timestamp of POSITION. POSITION should be a list of the form (WINDOW BUFFER-POSITION (COL . ROW) TIMESTAMP) ! as returned by the `event-start' and `event-end' functions." (nth 3 position)) diff -crP -x *.elc -x *.info* emacs-19.11/lisp/tar-mode.el emacs-19.12/lisp/tar-mode.el *** emacs-19.11/lisp/tar-mode.el Mon May 31 17:45:11 1993 --- emacs-19.12/lisp/tar-mode.el Tue Jun 1 17:41:47 1993 *************** *** 470,476 **** (put 'tar-mode 'mode-class 'special) (put 'tar-subfile-mode 'mode-class 'special) ! ;;;##autoload (defun tar-mode () "Major mode for viewing a tar file as a dired-like listing of its contents. You can move around using the usual cursor motion commands. --- 470,476 ---- (put 'tar-mode 'mode-class 'special) (put 'tar-subfile-mode 'mode-class 'special) ! ;;;###autoload (defun tar-mode () "Major mode for viewing a tar file as a dired-like listing of its contents. You can move around using the usual cursor motion commands. diff -crP -x *.elc -x *.info* emacs-19.11/lisp/version.el emacs-19.12/lisp/version.el *** emacs-19.11/lisp/version.el Tue Jun 1 04:28:07 1993 --- emacs-19.12/lisp/version.el Wed Jun 2 03:41:22 1993 *************** *** 25,31 **** ;; The following line is modified automatically ;; by loading inc-version.el, each time a new Emacs is dumped. ! (defconst emacs-version "19.11.0" "\ Version numbers of this version of Emacs.") (defconst emacs-build-time (current-time-string) "\ --- 25,31 ---- ;; The following line is modified automatically ;; by loading inc-version.el, each time a new Emacs is dumped. ! (defconst emacs-version "19.12.0" "\ Version numbers of this version of Emacs.") (defconst emacs-build-time (current-time-string) "\ diff -crP -x *.elc -x *.info* emacs-19.11/make-dist emacs-19.12/make-dist *** emacs-19.11/make-dist Mon May 31 20:50:39 1993 --- emacs-19.12/make-dist Tue Jun 1 18:37:32 1993 *************** *** 73,79 **** true else echo "You must update the version number in \`./man/emacs.texi'" ! exit 1 fi ### Make sure the subdirectory is available. --- 73,79 ---- true else echo "You must update the version number in \`./man/emacs.texi'" ! sleep 5 fi ### Make sure the subdirectory is available. diff -crP -x *.elc -x *.info* emacs-19.11/man/cmdargs.texi emacs-19.12/man/cmdargs.texi *** emacs-19.11/man/cmdargs.texi Tue Jun 1 02:37:44 1993 --- emacs-19.12/man/cmdargs.texi Tue Jun 1 16:17:30 1993 *************** *** 66,72 **** @itemx -funcall @var{function} Call Lisp function @var{function} with no arguments. ! @itemx -insert @var{file} Insert the contents of @var{file} into the current buffer. This is like what @kbd{M-x insert-buffer} does; @xref{Misc File Ops}. --- 66,72 ---- @itemx -funcall @var{function} Call Lisp function @var{function} with no arguments. ! @item -insert @var{file} Insert the contents of @var{file} into the current buffer. This is like what @kbd{M-x insert-buffer} does; @xref{Misc File Ops}. diff -crP -x *.elc -x *.info* emacs-19.11/man/emacs.texi emacs-19.12/man/emacs.texi *** emacs-19.11/man/emacs.texi Tue Jun 1 04:30:48 1993 --- emacs-19.12/man/emacs.texi Tue Jun 1 19:24:13 1993 *************** *** 75,81 **** Emacs is the extensible, customizable, self-documenting real-time display editor. This Info file describes how to edit with Emacs and some of how to customize it, but not how to extend it. It ! corresponds to GNU Emacs version 19.11. @end ifinfo @menu --- 75,81 ---- Emacs is the extensible, customizable, self-documenting real-time display editor. This Info file describes how to edit with Emacs and some of how to customize it, but not how to extend it. It ! corresponds to GNU Emacs version 19.12. @end ifinfo @menu diff -crP -x *.elc -x *.info* emacs-19.11/src/ChangeLog emacs-19.12/src/ChangeLog *** emacs-19.11/src/ChangeLog Tue Jun 1 04:28:52 1993 --- emacs-19.12/src/ChangeLog Wed Jun 2 03:02:59 1993 *************** *** 1,4 **** --- 1,56 ---- + Wed Jun 2 02:06:21 1993 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * Version 19.12 released. + + * term.c (term_get_fkeys): Use correct names for F10 and up. + Use the key sequence, not the termcap cap name, in Fdefine_key. + + * intervals.c (copy_intervals): Don't adjust total_length at the end. + Set lengths of subintervals properly. + (balance_intervals): Balance left as well as right. + + Tue Jun 1 22:07:46 1993 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * keymap.c (syms_of_keymap): Add missing 2nd arg to Fcons. + Tue Jun 1 00:27:03 1993 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * x/esix5-4.h: Redone by Joe Kelsey. + + * xterm.c (x_new_font): Take out last change. + + * s/386bsd.h (BSD4_2): Defined. + + * fileio.c (Fwrite_region): Don't fsync if autosaving. + + * s/irix4-0.h (GETPGRP_NO_ARG): Defined. + * emacs.c (shut_down_emacs): Handle GETPGRP_NO_ARG. + * sysdep.c (sys_suspend): Handle GETPGRP_NO_ARG. + + * fileio.c [HPUX9]: Don't include errnet.h. + + * hftctl.c (hft_alrm): Don't return a value. + Always declare to return void. + + * floatfns.c [!FLOAT_CHECK_ERRNO] (IN_FLOAT): New definition. + (Flog): Fix argument of `log'. + + * m/pmax.h (KERNEL_FILE): New override definition. + + * keyboard.c (read_key_sequence) [!USE_TEXT_PROPERTIES]: Fix typo. + (menu_bar_items) [!USE_TEXT_PROPERTIES]: Likewise. + + * s/isc3-0.h: #undef C_SWITCH_SYSTEM. + + * xselect.c (Fx_store_cut_buffer_internal): Handle empty string right. + + * xfaces.c (init_frame_faces): Don't look at selected_frame + unless it is an X frame. + + * xfns.c (x_window): Use Vxrdb_name for res_name field. + Delete the shortname stuff. + + * m/pmax.h (LIBS_MACHINE): Defined. * Version 19.11 released. diff -crP -x *.elc -x *.info* emacs-19.11/src/emacs.c emacs-19.12/src/emacs.c *** emacs-19.11/src/emacs.c Mon May 31 20:05:59 1993 --- emacs-19.12/src/emacs.c Tue Jun 1 17:04:49 1993 *************** *** 680,686 **** --- 680,690 ---- { int tpgrp; if (EMACS_GET_TTY_PGRP (0, &tpgrp) != -1 + #ifdef GETPGRP_NO_ARG + && tpgrp == getpgrp ()) + #else && tpgrp == getpgrp (0)) + #endif { fflush (stdout); reset_sys_modes (); diff -crP -x *.elc -x *.info* emacs-19.11/src/fileio.c emacs-19.12/src/fileio.c *** emacs-19.11/src/fileio.c Fri May 28 03:31:36 1993 --- emacs-19.12/src/fileio.c Tue Jun 1 17:15:23 1993 *************** *** 76,84 **** --- 76,86 ---- #ifdef HPUX #include #ifndef HPUX8 + #ifndef HPUX9 #include #endif #endif + #endif #ifndef O_WRONLY #define O_WRONLY 1 *************** *** 2712,2718 **** #ifdef HAVE_FSYNC /* Note fsync appears to change the modtime on BSD4.2 (both vax and sun). Disk full in NFS may be reported here. */ ! if (fsync (desc) < 0) failure = 1, save_errno = errno; #endif --- 2714,2722 ---- #ifdef HAVE_FSYNC /* Note fsync appears to change the modtime on BSD4.2 (both vax and sun). Disk full in NFS may be reported here. */ ! /* mib says that closing the file will try to write as fast as NFS can do ! it, and that means the fsync here is not crucial for autosave files. */ ! if (!auto_saving && fsync (desc) < 0) failure = 1, save_errno = errno; #endif diff -crP -x *.elc -x *.info* emacs-19.11/src/floatfns.c emacs-19.12/src/floatfns.c *** emacs-19.11/src/floatfns.c Tue May 25 16:41:05 1993 --- emacs-19.12/src/floatfns.c Tue Jun 1 16:29:42 1993 *************** *** 154,159 **** --- 154,160 ---- } \ } while (0) #else + #define IN_FLOAT(d, name, num) (in_float = 1, (d), in_float = 0) #define IN_FLOAT2(d, name, num, num2) (in_float = 1, (d), in_float = 0) #endif *************** *** 471,477 **** if (b == 10.0) IN_FLOAT2 (d = log10 (d), "log", arg, base); else ! IN_FLOAT2 (d = log (arg) / log (b), "log", arg, base); } return make_float (d); } --- 472,478 ---- if (b == 10.0) IN_FLOAT2 (d = log10 (d), "log", arg, base); else ! IN_FLOAT2 (d = log (d) / log (b), "log", arg, base); } return make_float (d); } diff -crP -x *.elc -x *.info* emacs-19.11/src/hftctl.c emacs-19.12/src/hftctl.c *** emacs-19.11/src/hftctl.c Sun May 30 16:15:02 1993 --- emacs-19.12/src/hftctl.c Tue Jun 1 16:46:55 1993 *************** *** 114,120 **** #else static GT_ACK (); static WR_REQ (); ! static hft_alrm (); #endif /*************** HFTCTL FUNCTION *******************************/ --- 114,120 ---- #else static GT_ACK (); static WR_REQ (); ! static void hft_alrm (); #endif /*************** HFTCTL FUNCTION *******************************/ *************** *** 282,288 **** signal (SIGALRM, sav_alrm); /* reset to previous */ if (is_ack_vtd) /* has ack vtd arrived ? */ ! return(0); /* yes, then continue */ else /* no, then return with error */ longjmp (hftenv, -1); --- 282,288 ---- signal (SIGALRM, sav_alrm); /* reset to previous */ if (is_ack_vtd) /* has ack vtd arrived ? */ ! return; /* yes, then continue */ else /* no, then return with error */ longjmp (hftenv, -1); diff -crP -x *.elc -x *.info* emacs-19.11/src/intervals.c emacs-19.12/src/intervals.c *** emacs-19.11/src/intervals.c Sun May 30 20:08:08 1993 --- emacs-19.12/src/intervals.c Wed Jun 2 03:31:17 1993 *************** *** 1555,1577 **** register int threshold = (XFASTINT (interval_balance_threshold) * (total_children_size / 100)); ! if (LEFT_TOTAL_LENGTH (i) > RIGHT_TOTAL_LENGTH (i) ! && (LEFT_TOTAL_LENGTH (i) - RIGHT_TOTAL_LENGTH (i)) > threshold) ! return rotate_right (i); if (LEFT_TOTAL_LENGTH (i) > RIGHT_TOTAL_LENGTH (i) && (LEFT_TOTAL_LENGTH (i) - RIGHT_TOTAL_LENGTH (i)) > threshold) ! return rotate_right (i); ! #if 0 ! if (LEFT_TOTAL_LENGTH (i) > ! (RIGHT_TOTAL_LENGTH (i) + XINT (interval_balance_threshold))) ! return rotate_right (i); ! ! if (RIGHT_TOTAL_LENGTH (i) > ! (LEFT_TOTAL_LENGTH (i) + XINT (interval_balance_threshold))) ! return rotate_left (i); ! #endif return i; } --- 1555,1584 ---- register int threshold = (XFASTINT (interval_balance_threshold) * (total_children_size / 100)); ! /* Balance within each side. */ ! balance_intervals (i->left); ! balance_intervals (i->right); if (LEFT_TOTAL_LENGTH (i) > RIGHT_TOTAL_LENGTH (i) && (LEFT_TOTAL_LENGTH (i) - RIGHT_TOTAL_LENGTH (i)) > threshold) ! { ! i = rotate_right (i); ! /* If that made it unbalanced the other way, take it back. */ ! if (RIGHT_TOTAL_LENGTH (i) > LEFT_TOTAL_LENGTH (i) ! && (RIGHT_TOTAL_LENGTH (i) - LEFT_TOTAL_LENGTH (i)) > threshold) ! return rotate_left (i); ! return i; ! } ! if (RIGHT_TOTAL_LENGTH (i) > LEFT_TOTAL_LENGTH (i) ! && (RIGHT_TOTAL_LENGTH (i) - LEFT_TOTAL_LENGTH (i)) > threshold) ! { ! i = rotate_left (i); ! if (LEFT_TOTAL_LENGTH (i) > RIGHT_TOTAL_LENGTH (i) ! && (LEFT_TOTAL_LENGTH (i) - RIGHT_TOTAL_LENGTH (i)) > threshold) ! return rotate_right (i); ! return i; ! } return i; } *************** *** 1608,1614 **** int start, length; { register INTERVAL i, new, t; ! register int got; if (NULL_INTERVAL_P (tree) || length <= 0) return NULL_INTERVAL; --- 1615,1621 ---- int start, length; { register INTERVAL i, new, t; ! register int got, prevlen; if (NULL_INTERVAL_P (tree) || length <= 0) return NULL_INTERVAL; *************** *** 1629,1644 **** copy_properties (i, new); t = new; while (got < length) { i = next_interval (i); ! t = split_interval_right (t, got + 1); copy_properties (i, t); ! got += LENGTH (i); } - - if (got > length) - t->total_length -= (got - length); return balance_intervals (new); } --- 1636,1650 ---- copy_properties (i, new); t = new; + prevlen = got; while (got < length) { i = next_interval (i); ! t = split_interval_right (t, prevlen + 1); copy_properties (i, t); ! prevlen = LENGTH (i); ! got += prevlen; } return balance_intervals (new); } diff -crP -x *.elc -x *.info* emacs-19.11/src/keyboard.c emacs-19.12/src/keyboard.c *** emacs-19.11/src/keyboard.c Mon May 31 14:13:12 1993 --- emacs-19.12/src/keyboard.c Tue Jun 1 16:19:56 1993 *************** *** 3097,3103 **** #ifdef USE_TEXT_PROPERTIES maps[nmaps-2] = get_local_map (PT, current_buffer); #else ! maps[nmaps-2] = current_buffer->local_map; #endif maps[nmaps-1] = global_map; } --- 3097,3103 ---- #ifdef USE_TEXT_PROPERTIES maps[nmaps-2] = get_local_map (PT, current_buffer); #else ! maps[nmaps-2] = current_buffer->keymap; #endif maps[nmaps-1] = global_map; } *************** *** 3665,3671 **** #ifdef USE_TEXT_PROPERTIES submaps[nmaps-2] = get_local_map (PT, current_buffer); #else ! submaps[nmaps-2] = current_buffer->local_map; #endif submaps[nmaps-1] = global_map; } --- 3665,3671 ---- #ifdef USE_TEXT_PROPERTIES submaps[nmaps-2] = get_local_map (PT, current_buffer); #else ! submaps[nmaps-2] = current_buffer->keymap; #endif submaps[nmaps-1] = global_map; } diff -crP -x *.elc -x *.info* emacs-19.11/src/keymap.c emacs-19.12/src/keymap.c *** emacs-19.11/src/keymap.c Fri May 28 18:31:29 1993 --- emacs-19.12/src/keymap.c Tue Jun 1 22:07:22 1993 *************** *** 2013,2019 **** pointed to by a C variable */ global_map = Fcons (Qkeymap, ! Fcons (Fmake_vector (make_number (0400), Qnil))); Fset (intern ("global-map"), global_map); meta_map = Fmake_keymap (Qnil); --- 2013,2019 ---- pointed to by a C variable */ global_map = Fcons (Qkeymap, ! Fcons (Fmake_vector (make_number (0400), Qnil), Qnil)); Fset (intern ("global-map"), global_map); meta_map = Fmake_keymap (Qnil); diff -crP -x *.elc -x *.info* emacs-19.11/src/m/pmax.h emacs-19.12/src/m/pmax.h *** emacs-19.11/src/m/pmax.h Sun Nov 15 18:43:10 1992 --- emacs-19.12/src/m/pmax.h Tue Jun 1 16:25:11 1993 *************** *** 49,51 **** --- 49,60 ---- #undef C_ALLOCA #define HAVE_ALLOCA #endif + + /* mcc@timessqr.gc.cuny.edu says this makes Emacs work with DECnet. + If you don't have DECnet and this causes trouble, + just delete the definition. */ + #define LIBS_MACHINE -ldnet + + /* mcc@timessqr.gc.cuny.edu says it is /vmunix on Ultrix 4.2a. */ + #undef KERNEL_FILE + #define KERNEL_FILE "/vmunix" diff -crP -x *.elc -x *.info* emacs-19.11/src/s/386bsd.h emacs-19.12/src/s/386bsd.h *** emacs-19.11/src/s/386bsd.h Tue Jun 1 00:07:25 1993 --- emacs-19.12/src/s/386bsd.h Tue Jun 1 17:25:47 1993 *************** *** 13,15 **** --- 13,18 ---- /* Need to use GNU make, as system make has problems */ #define MAKE_COMMAND gmake #define LIBS_DEBUG + + /* For mem-limits.h. */ + #define BSD4_2 diff -crP -x *.elc -x *.info* emacs-19.11/src/s/esix5r4.h emacs-19.12/src/s/esix5r4.h *** emacs-19.11/src/s/esix5r4.h Sun Oct 18 04:08:52 1992 --- emacs-19.12/src/s/esix5r4.h Tue Jun 1 19:02:50 1993 *************** *** 1,13 **** /* Definitions for ESIX System V 4.0.4, a variant of V.4 for the 386. */ #include "usg5-4.h" ! #define LIB_X11_LIB -lsocket -lc -lX11 ! #undef LIB_STANDARD ! #define LIB_STANDARD -lnsl -lns -lelf /usr/ucblib/libucb.a /usr/ccs/lib/crtn.o /* Resolve BSD string functions in X Window library from libucb.a. */ ! #define BSTRING ! /* kelsey@mdd.comm.mot.com says this makes X windows work. */ ! #define BROKEN_FIONREAD --- 1,24 ---- /* Definitions for ESIX System V 4.0.4, a variant of V.4 for the 386. */ + /* Redone by zircon!joe@uunet.uu.net (Joe Kelsey). */ #include "usg5-4.h" ! #define SYSTEM_MALLOC 1 ! #if defined (HAVE_XFREE386) ! # undef LIB_STANDARD ! # define LIB_STANDARD -lc ! #else ! # define LIB_X11_LIB -lsocket -lc -lX11 ! # undef LIB_STANDARD ! # ifdef ORDINARY_LINK ! # define LIB_STANDARD -lnsl -lns -lelf /usr/ucblib/libucb.a ! # else ! # define LIB_STANDARD -lnsl -lns -lelf /usr/ucblib/libucb.a /usr/ccs/lib/crtn.o ! # endif /* Resolve BSD string functions in X Window library from libucb.a. */ ! # define BSTRING ! /* zircon!joe says this makes X windows work. */ ! # define BROKEN_FIONREAD ! #endif diff -crP -x *.elc -x *.info* emacs-19.11/src/s/irix4-0.h emacs-19.12/src/s/irix4-0.h *** emacs-19.11/src/s/irix4-0.h Sun May 30 15:11:01 1993 --- emacs-19.12/src/s/irix4-0.h Tue Jun 1 17:07:02 1993 *************** *** 53,55 **** --- 53,58 ---- /* jpff@maths.bath.ac.uk reports `struct exception' is not defined on this system, so inhibit use of matherr. */ #define NO_MATHERR + + /* Info from simon@lia.di.epfl.ch (Simon Leinen) suggests this is needed. */ + #define GETPGRP_NO_ARG diff -crP -x *.elc -x *.info* emacs-19.11/src/s/isc3-0.h emacs-19.12/src/s/isc3-0.h *** emacs-19.11/src/s/isc3-0.h Tue Mar 2 17:22:13 1993 --- emacs-19.12/src/s/isc3-0.h Tue Jun 1 15:56:35 1993 *************** *** 11,13 **** --- 11,17 ---- /* mt00@etherm.co.uk says this is needed for process.c. */ #define HAVE_TIMEVAL + + /* People say that using -traditional causes lossage with `const', + so we might as well try getting rid of -traditional. */ + #undef C_SWITCH_SYSTEM diff -crP -x *.elc -x *.info* emacs-19.11/src/s/sol2.h emacs-19.12/src/s/sol2.h *** emacs-19.11/src/s/sol2.h Wed May 26 23:04:48 1993 --- emacs-19.12/src/s/sol2.h Tue Jun 1 16:57:12 1993 *************** *** 26,30 **** /* Well, we released Emacs with this change, and fixed a typo, but people keep saying that it doesn't work, and that the patch is easy ! to install. */ #undef SOLARIS_BROKEN_ACCESS --- 26,30 ---- /* Well, we released Emacs with this change, and fixed a typo, but people keep saying that it doesn't work, and that the patch is easy ! to install. Patch number is 100947-02. */ #undef SOLARIS_BROKEN_ACCESS diff -crP -x *.elc -x *.info* emacs-19.11/src/sysdep.c emacs-19.12/src/sysdep.c *** emacs-19.11/src/sysdep.c Sun May 30 21:11:52 1993 --- emacs-19.12/src/sysdep.c Tue Jun 1 17:05:41 1993 *************** *** 567,573 **** --- 567,577 ---- #else #ifdef SIGTSTP + #ifdef GETPGRP_NO_ARG + EMACS_KILLPG (getpgrp (), SIGTSTP); + #else EMACS_KILLPG (getpgrp (0), SIGTSTP); + #endif #else /* No SIGTSTP */ #ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */ diff -crP -x *.elc -x *.info* emacs-19.11/src/term.c emacs-19.12/src/term.c *** emacs-19.11/src/term.c Mon May 31 16:18:20 1993 --- emacs-19.12/src/term.c Wed Jun 2 03:01:04 1993 *************** *** 1281,1287 **** { char fcap[3], fkey[4]; ! fcap[0] = 'k'; fcap[2] = '\0'; for (i = 11; i < 64; i++) { if (i <= 19) --- 1281,1287 ---- { char fcap[3], fkey[4]; ! fcap[0] = 'F'; fcap[2] = '\0'; for (i = 11; i < 64; i++) { if (i <= 19) *************** *** 1291,1303 **** else fcap[1] = 'a' + i - 11; ! if (tgetstr (fcap, address)) ! { ! (void) sprintf (fkey, "f%d", i); ! Fdefine_key (Vfunction_key_map, ! build_string (fcap), ! Fmake_vector (make_number (1), intern (fkey))); ! } } } --- 1291,1306 ---- else fcap[1] = 'a' + i - 11; ! { ! char *sequence = tgetstr (fcap, address); ! if (sequence) ! { ! (void) sprintf (fkey, "f%d", i); ! Fdefine_key (Vfunction_key_map, ! build_string (sequence), ! Fmake_vector (make_number (1), intern (fkey))); ! } ! } } } *************** *** 1305,1315 **** * Various mappings to try and get a better fit. */ { ! #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \ ! if (!tgetstr (cap1, address) && tgetstr (cap2, address)) \ ! Fdefine_key (Vfunction_key_map, \ ! build_string (cap2), \ ! Fmake_vector (make_number (1), intern (sym))) /* if there's no key_next keycap, map key_npage to `next' keysym */ CONDITIONAL_REASSIGN ("%5", "kN", "next"); --- 1308,1322 ---- * Various mappings to try and get a better fit. */ { ! #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \ ! if (!tgetstr (cap1, address)) \ ! { \ ! char *sequence = tgetstr (cap2, address); \ ! if (sequence) \ ! Fdefine_key (Vfunction_key_map, \ ! build_string (sequence), \ ! Fmake_vector (make_number (1), intern (sym))); \ ! } /* if there's no key_next keycap, map key_npage to `next' keysym */ CONDITIONAL_REASSIGN ("%5", "kN", "next"); diff -crP -x *.elc -x *.info* emacs-19.11/src/terminfo.c emacs-19.12/src/terminfo.c *** emacs-19.11/src/terminfo.c Tue Aug 4 17:46:29 1992 --- emacs-19.12/src/terminfo.c Wed Jun 2 01:19:03 1993 *************** *** 5,11 **** 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 1, or (at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, --- 5,11 ---- 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, diff -crP -x *.elc -x *.info* emacs-19.11/src/xfaces.c emacs-19.12/src/xfaces.c *** emacs-19.11/src/xfaces.c Sun May 30 16:33:16 1993 --- emacs-19.12/src/xfaces.c Tue Jun 1 14:44:01 1993 *************** *** 471,485 **** /* Make sure that all faces valid on the selected frame are also valid on this new frame. */ ! { ! int i; ! int n_faces = selected_frame->display.x->n_faces; ! struct face **faces = selected_frame->display.x->faces; ! for (i = 2; i < n_faces; i++) ! if (faces[i]) ! ensure_face_ready (f, i); ! } } --- 471,486 ---- /* Make sure that all faces valid on the selected frame are also valid on this new frame. */ ! if (FRAME_X_P (selected_frame)) ! { ! int i; ! int n_faces = selected_frame->display.x->n_faces; ! struct face **faces = selected_frame->display.x->faces; ! for (i = 2; i < n_faces; i++) ! if (faces[i]) ! ensure_face_ready (f, i); ! } } diff -crP -x *.elc -x *.info* emacs-19.11/src/xfns.c emacs-19.12/src/xfns.c *** emacs-19.11/src/xfns.c Tue Jun 1 03:55:02 1993 --- emacs-19.12/src/xfns.c Tue Jun 1 14:03:10 1993 *************** *** 1484,1491 **** XSetWindowAttributes attributes; unsigned long attribute_mask; XClassHint class_hints; - char *shortname; - char *p; attributes.background_pixel = f->display.x->background_pixel; attributes.border_pixel = f->display.x->border_pixel; --- 1484,1489 ---- *************** *** 1511,1525 **** screen_visual, /* set in Fx_open_connection */ attribute_mask, &attributes); ! /* X resource names should not have periods in them. ! So copy the frame name, discarding from the first period onward. */ ! shortname = (char *) alloca (XSTRING (f->name)->size + 1); ! bcopy (XSTRING (f->name)->data, shortname, XSTRING (f->name)->size + 1); ! for (p = shortname; *p; p++) ! if (*p == '.') ! *p = 0; ! ! class_hints.res_name = shortname; class_hints.res_class = EMACS_CLASS; XSetClassHint (x_current_display, FRAME_X_WINDOW (f), &class_hints); --- 1509,1515 ---- screen_visual, /* set in Fx_open_connection */ attribute_mask, &attributes); ! class_hints.res_name = (char *) XSTRING (Vxrdb_name)->data; class_hints.res_class = EMACS_CLASS; XSetClassHint (x_current_display, FRAME_X_WINDOW (f), &class_hints); diff -crP -x *.elc -x *.info* emacs-19.11/src/xselect.c emacs-19.12/src/xselect.c *** emacs-19.11/src/xselect.c Mon May 31 13:02:30 1993 --- emacs-19.12/src/xselect.c Tue Jun 1 15:57:34 1993 *************** *** 1795,1800 **** --- 1795,1806 ---- if (! cut_buffers_initialized) initialize_cut_buffers (display, window); BLOCK_INPUT; + + /* Don't mess up with an empty value. */ + if (!bytes_remaining) + XChangeProperty (display, window, buffer_atom, XA_STRING, 8, + PropModeReplace, data, 0); + while (bytes_remaining) { int chunk = (bytes_remaining < max_bytes diff -crP -x *.elc -x *.info* emacs-19.11/src/xterm.c emacs-19.12/src/xterm.c *** emacs-19.11/src/xterm.c Tue Jun 1 03:54:58 1993 --- emacs-19.12/src/xterm.c Tue Jun 1 19:49:31 1993 *************** *** 3916,3940 **** font_names = (char **) XListFontsWithInfo (x_current_display, fontname, 1024, &n_matching_fonts, &font_info); - /* Don't just give up if n_matching_fonts is 0. - Apparently there's a bug on Suns: XListFontsWithInfo can - fail to find a font, but XLoadQueryFont may still find it. */ /* See if we've already loaded a matching font. */ ! if (n_matching_fonts != 0) ! { ! int i, j; ! already_loaded = 0; ! for (i = 0; i < n_fonts; i++) ! for (j = 0; j < n_matching_fonts; j++) ! if (x_font_table[i]->fid == font_info[j].fid) ! { ! already_loaded = i; ! fontname = font_names[j]; ! goto found_font; ! } ! } found_font: /* If we have, just return it from the table. */ --- 3916,3941 ---- font_names = (char **) XListFontsWithInfo (x_current_display, fontname, 1024, &n_matching_fonts, &font_info); + /* If the server couldn't find any fonts whose named matched fontname, + return an error code. */ + if (n_matching_fonts == 0) + return Qnil; + /* See if we've already loaded a matching font. */ ! { ! int i, j; ! already_loaded = 0; ! for (i = 0; i < n_fonts; i++) ! for (j = 0; j < n_matching_fonts; j++) ! if (x_font_table[i]->fid == font_info[j].fid) ! { ! already_loaded = i; ! fontname = font_names[j]; ! goto found_font; ! } ! } found_font: /* If we have, just return it from the table. */ *************** *** 3957,3974 **** i = 0; #endif ! /* See comment above. */ ! if (n_matching_fonts == 0) fontname = font_names[i]; font = (XFontStruct *) XLoadQueryFont (x_current_display, fontname); if (! font) ! { ! /* Free the information from XListFontsWithInfo. */ ! if (n_matching_fonts) ! XFreeFontInfo (font_names, font_info, n_matching_fonts); ! return Qnil; ! } /* Do we need to create the table? */ if (x_font_table_size == 0) --- 3958,3971 ---- i = 0; #endif ! if (i >= n_matching_fonts) ! return Qt; ! else fontname = font_names[i]; font = (XFontStruct *) XLoadQueryFont (x_current_display, fontname); if (! font) ! return Qnil; /* Do we need to create the table? */ if (x_font_table_size == 0) *************** *** 4096,4105 **** BLOCK_INPUT; check_frame_size (f, &rows, &cols); ! f->display.x->vertical_scroll_bar_extra ! = (FRAME_HAS_VERTICAL_SCROLL_BARS (f) ! ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f) ! : 0); pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols); pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows); --- 4093,4102 ---- BLOCK_INPUT; check_frame_size (f, &rows, &cols); ! f->display.x->vertical_scroll_bar_extra = ! (FRAME_HAS_VERTICAL_SCROLL_BARS (f) ! ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f) ! : 0); pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols); pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);