From: Chong Yidong Date: Sat, 10 Jul 2010 18:52:53 +0000 (-0400) Subject: Merge changes from emacs-23 branch. X-Git-Tag: emacs-pretest-24.0.90~104^2~275^2~438^2~51^2~78^2~17^2 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=2ec1b5ee3464999a18b8197101e8bf08a3c564a8;p=emacs.git Merge changes from emacs-23 branch. --- 2ec1b5ee3464999a18b8197101e8bf08a3c564a8 diff --cc ChangeLog index 13b2fff124a,c51dced40ef..758ba0f29a2 --- a/ChangeLog +++ b/ChangeLog @@@ -1,61 -1,8 +1,65 @@@ +2010-07-08 Dan Nicolaescu + + * configure.in: Use -Wold-style-definition if available. + This helps with the transition to standard C code, it can be + removed when done. + + * configure.in (PRE_EDIT_LDFLAGS, POST_EDIT_LDFLAGS): Remove. + + * configure.in (UNEXEC_OBJ): Add comment about values for MSDOS + and MSWindows. + +2010-07-07 Andreas Schwab + + * configure.in: Don't check for bcopy, bcmp, bzero. Don't include + and don't define bcopy, bzero, BCMP in config.h. + +2010-07-07 Dan Nicolaescu + + * configure.in (getenv): Remove K&R declaration. + +2010-07-02 Jan Djärv + + * configure.in: Remove define __P. + +2010-07-02 Dan Nicolaescu + + * configure.in (--enable-use-lisp-union-type): New flag. + +2010-06-30 Dan Nicolaescu + + Fix CFLAGS for non-GCC compilers. + * configure.in (CFLAGS): Always use -g like it was done before the + 2010-03-30 change. + (REAL_CFLAGS): Use CFLAGS for non-GCC to get optimization flags. (Bug#6538) + +2010-06-30 Glenn Morris + + * configure.in (HAVE_SOUND, HAVE_X_I18N, HAVE_X11R6_XIM): + Set with AC_DEFINE rather than AH_BOTTOM. + + * configure.in (C_OPTIMIZE_SWITCH, CANNOT_DUMP, SYSTEM_MALLOC): + (USE_MMAP_FOR_BUFFERS, C_WARNING_SWITCH, CFLAGS, REAL_CFLAGS): + Set with shell, not cpp. + (LIBX): Remove, just use -lX11 in the one place this was used. + (cannot_dump): Replace with CANNOT_DUMP. + +2010-06-28 Jan Djärv + + * configure.in: Add --with-x-toolkit=gtk3. Remove HAVE_GTK_MULTIDISPLAY, + check for gtk_file_chooser_dialog_new, and HAVE_GTK_FILE_BOTH (implied + by minimum required Gtk+ 2.6). Add checks for functions introduced + in Gtk+ 2.14 or newer (bug#6505). + +2010-06-26 Eli Zaretskii + + * config.bat: Remove white space around "+" in COPY commands. + + 2010-06-23 Glenn Morris + + * info/dir: Start descriptions in column 32, per Texinfo convention. + -2010-06-12 Chong Yidong +2010-06-16 Chong Yidong * INSTALL: Update font information (Bug#6389). diff --cc doc/emacs/xresources.texi index bc60ff946af,2965bec3bd2..2a543eeee08 --- a/doc/emacs/xresources.texi +++ b/doc/emacs/xresources.texi @@@ -432,16 -431,12 +432,17 @@@ Emacs.pane.menubar.faceName: Courier-1 @end example @noindent -Resources for @emph{non-menubar} toolkit pop-up menus have -@samp{menu*} instead of @samp{pane.menubar}. For example, to specify -the font @samp{8x16} for the pop-up menu items, write this: +To specify a font, use fontconfig font names as values to the @code{faceName} +resource. + - If Emacs is not built with the Xft library, Lucid menus and dialogs can only - display old style fonts. If Emacs is built with Xft and you prefer the old - fonts, you have to specify @samp{none} to @code{faceName}: ++If Emacs is not built with the Xft library, Lucid menus and dialogs ++can only display old style fonts. If Emacs is built with Xft and you ++prefer the old fonts, you have to specify @samp{none} to ++@code{faceName}: @example - Emacs.pane.menubar.faceName: none - Emacs.pane.dialog.faceName: none -Emacs.menu*.font: 8x16 ++Emacs.pane.menubar.faceName: none ++Emacs.pane.dialog.faceName: none @end example @noindent @@@ -466,22 -461,6 +467,22 @@@ for both the popup and menu bar menus, Emacs*menu*fontSet: -*-helvetica-medium-r-*--*-120-*-*-*-*-*-*,* @end example +@noindent +Resources for @emph{non-menubar} toolkit pop-up menus have +@samp{menu*} instead of @samp{pane.menubar}. For example, to specify +the font @samp{8x16} for the pop-up menu items, write this: + +@example - Emacs.menu*.font: 8x16 ++Emacs.menu*.font: 8x16 +@end example + +@noindent +For dialog boxes, use @samp{dialog*}: + +@example +Emacs.dialog*.faceName: Sans-12 +@end example + @noindent The @samp{*menu*} as a wildcard matches @samp{pane.menubar} and @samp{menu@dots{}}. diff --cc doc/lispref/ChangeLog index 9f032af4a0d,b92f4aea234..ee6ba8ed50b --- a/doc/lispref/ChangeLog +++ b/doc/lispref/ChangeLog @@@ -1,8 -1,28 +1,33 @@@ +2010-07-09 Eli Zaretskii + + * internals.texi (Writing Emacs Primitives): Adapt to ANSI C + calling sequences, which are now the standard. + + 2010-06-24 Chong Yidong + + * text.texi (Undo): Clarify command loop behavior (Bug#2433). + + * commands.texi (Command Overview): Mention undo-boundary call. + + 2010-06-23 Glenn Morris + + * abbrevs.texi, commands.texi, compile.texi, debugging.texi: + * display.texi, edebug.texi, elisp.texi, eval.texi, files.texi: + * frames.texi, functions.texi, internals.texi, keymaps.texi: + * loading.texi, minibuf.texi, numbers.texi, os.texi, processes.texi: + * searching.texi, sequences.texi, strings.texi, syntax.texi: + * text.texi, tips.texi, vol1.texi, vol2.texi, windows.texi: + Untabify Texinfo files. + + 2010-06-20 Chong Yidong + + * modes.texi (Minor Mode Conventions): Fix typo (Bug#6477). + + 2010-06-19 Chong Yidong + + * errors.texi (Standard Errors): Remove unnecessary markup + (Bug#6461). + 2010-06-02 Chong Yidong * searching.texi (Regexp Special): Remove obsolete information diff --cc doc/misc/ChangeLog index e24363285f5,d913326f2c6..2f8a89d4b3c --- a/doc/misc/ChangeLog +++ b/doc/misc/ChangeLog @@@ -1,21 -1,28 +1,46 @@@ +2010-07-10 Michael Albinus + + * tramp.texi (Inline methods): Remove "kludgy" phrase. + (Filename Syntax): Describe port numbers. + +2010-07-09 Michael Albinus + + * dbus.texi (Top): Introduce Index. Emphasize "nil" whereever + forgotten. + (Type Conversion): Precise conversion of natural numbers. + (Errors and Events): Add "debugging" to concept index. Add variable + `dbus-debug'. + +2010-07-04 Michael Albinus + + * dbus.texi (Receiving Method Calls): Add optional argument + EMITS-SIGNAL to `dbus-register-property'. + + 2010-06-27 Alex Schroeder + + * nxml-mode.texi (Commands for locating a schema): Fix typo. + + 2010-06-24 Glenn Morris + + * ada-mode.texi, auth.texi, autotype.texi, calc.texi, cc-mode.texi: + * dired-x.texi, ebrowse.texi, ede.texi, edt.texi, eieio.texi: + * emacs-mime.texi, epa.texi, erc.texi, eshell.texi, eudc.texi: + * flymake.texi, gnus.texi, info.texi, mairix-el.texi, message.texi: + * newsticker.texi, org.texi, pgg.texi, rcirc.texi, reftex.texi: + * remember.texi, sasl.texi, semantic.texi, ses.texi, smtpmail.texi: + * speedbar.texi, tramp.texi, url.texi, viper.texi, widget.texi: + * woman.texi: Start direntry descriptions in column 32, per Texinfo + convention. Make them end with a period. + + 2010-06-23 Glenn Morris + + * autotype.texi, cl.texi, dired-x.texi, ebrowse.texi, ede.texi: + * eieio.texi, epa.texi, faq.texi, flymake.texi, forms.texi: + * gnus-faq.texi, idlwave.texi, mh-e.texi, nxml-mode.texi, org.texi: + * pcl-cvs.texi, pgg.texi, reftex.texi, sasl.texi, sc.texi, + * sem-user.texi, semantic.texi, sieve.texi, smtpmail.texi, + * speedbar.texi, vip.texi, viper.texi, widget.texi: Untabify. + 2010-06-10 Glenn Morris * idlwave.texi (Load-Path Shadows): diff --cc lisp/ChangeLog index f793f91a932,eb8f0785b26..01ecaab86b6 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@@ -1,345 -1,150 +1,482 @@@ +2010-07-08 Daiki Ueno + + * epa-file.el (epa-file-error, epa-file--find-file-not-found-function) + (epa-file-insert-file-contents): Hack to prevent + find-file from opening empty buffer when decryptin failed + (bug#6568). + +2010-07-07 Agustín Martín + + * ispell.el (ispell-alternate-dictionary): Use file-readable-p. + Return nil if no word-list is found at default locations. + (ispell-complete-word-dict): Default to nil. + (ispell-command-loop): Use 'word-list' when using lookup-words. + (lookup-words): Use ispell-complete-word-dict or + ispell-alternate-dictionary. Check for word-list availability + and handle errors if needed with better messages (Bug#6539). + (ispell-complete-word): Use ispell-complete-word-dict or + ispell-alternate-dictionary. + + 2010-07-07 Christoph Scholtes + + * progmodes/python.el (python-font-lock-keywords): Add Python 2.7 + builtins (BufferError, BytesWarning, WindowsError; callables + bin, bytearray, bytes, format, memoryview, next, print; __package__). + 2010-07-07 Glenn Morris + * play/zone.el (top-level): Do not require timer, tabify, or cl. + (zone-shift-left): Ignore intangibility, and any errors from + forward-char. + (zone-shift-right): Remove no-op end-of-line. Ignore intangibility. + (zone-pgm-putz-with-case): Use upcase-region rather than inserting, + deleting, and copying text properties. + (zone-line-specs, zone-pgm-stress): Check forward-line exit status. + (zone-pgm-rotate): Handle odd buffers like that of gomoku, where getting + to point-max is hard. + (zone-fret, zone-fill-out-screen): Replace cl's do with dotimes. + (zone-fill-out-screen): Ignore intangibility. + +2010-07-05 Chong Yidong + + * menu-bar.el (menu-bar-mode): + * tool-bar.el (tool-bar-mode): Replace default-frame-alist element + if it has been set. + + * mouse.el (mouse-drag-track): Call mouse-start-end to handle + word/line selection (Bug#6565). + +2010-07-04 Juanma Barranquero + + * net/dbus.el (dbus-send-signal): Declare function. + +2010-07-04 Michael Albinus + + * net/dbus.el: Implement signal "PropertiesChanged" (from D-Bus 1.3.1). + (dbus-register-property): New optional argument EMITS-SIGNAL. + (dbus-property-handler): Send signal "PropertiesChanged" if requested. + +2010-07-03 Chong Yidong + + * mouse.el (mouse-drag-overlay): Variable deleted. + (mouse-move-drag-overlay, mouse-show-mark): Functions deleted. + (mouse--remap-link-click-p): New function. + (mouse-drag-track): Handle dragging by using temporary Transient + Mark mode, instead of a special overlay. + (mouse-kill-ring-save, mouse-save-then-kill): Don't call + mouse-show-mark. + + * mouse-sel.el (mouse-sel-selection-alist): mouse-drag-overlay + deleted. + +2010-07-02 Juri Linkov + + * autoinsert.el (auto-insert-alist): Fix readability + by using dotted pair notation for lambda. + +2010-07-02 Juri Linkov + + * faces.el (read-face-name): Rename arg `string-describing-default' + to `default'. Doc fix. Display the default value in quotes + in the prompt. With empty input, return the `default' arg, + unless the default value is a string (in which case return nil). + (describe-face): Replace the string `default' arg of `read-face-name' + with the symbol `default'. + +2010-07-02 Chong Yidong + + * emulation/viper-cmd.el (viper-delete-backward-char) + (viper-del-backward-char-in-insert) + (viper-del-backward-char-in-replace, viper-change) + (viper-backward-indent): Replace delete-backward-char with + delete-char (Bug#6552). + +2010-07-01 Chong Yidong + + * ruler-mode.el (ruler--save-header-line-format): Fix typos. + +2010-06-30 Chong Yidong + + * frame.el (make-frame): Add default-frame-alist to the PARAMETERS + argument passed to frame-creation-function (Bug#5378). + + * faces.el (x-handle-named-frame-geometry) + (x-handle-reverse-video, x-create-frame-with-faces) + (face-set-after-frame-default, tty-create-frame-with-faces): Don't + separately consult default-frame-alist. It is now passed as the + PARAMETER argument. + +2010-06-30 Andreas Schwab + + * startup.el (command-line): Don't call tool-bar-setup in a + tty-only build. + +2010-06-30 Chong Yidong + + * ruler-mode.el (ruler--save-header-line-format): New fun. + (ruler-mode): Use it as a setter function, so as not to overwrite + ruler-mode-header-line-format-old if Ruler mode is on (Bug#5370). + +2010-06-29 Chong Yidong + + * vc/vc.el (vc-deduce-backend): New fun. Handle diff buffers. + (vc-root-diff, vc-print-root-log, vc-log-incoming) + (vc-log-outgoing): Use it. + (vc-diff-internal): Set diff-vc-backend. + + * vc/diff-mode.el (diff-vc-backend): New var. + +2010-06-28 Jan Djärv + + * dynamic-setting.el (font-setting-change-default-font): Remove + call to message. + +2010-06-28 Kenichi Handa + + * international/quail.el (quail-insert-kbd-layout): Fix the + showing of untranslated characters. + +2010-06-28 Chong Yidong + + * simple.el (delete-active-region): New option. + (delete-backward-char): Implement in Lisp. + (delete-forward-char): New command. + + * mouse.el (mouse-region-delete-keys): Deleted. + (mouse-show-mark): Simplify. + + * bindings.el (global-map): Bind delete and DEL, the former to + delete-forward-char. + +2010-01-16 Lennart Borgman + + * progmodes/ruby-mode.el (ruby-mode-map): Don't bind TAB. + (ruby-mode): Bind indent-line-function (Bug#5119). + +2010-06-27 Chong Yidong + + * startup.el (command-line): Recognize "0" X resource value. + +2010-06-27 Chong Yidong + + * startup.el (command-line): Use X resources to set the value of + menu-bar-mode and tool-bar-mode, before calling frame-initialize. + + * menu-bar.el (menu-bar-mode): + * tool-bar.el (tool-bar-mode): Don't change default-frame-alist. + Set init-value to t. + + * frame.el (frame-notice-user-settings): Don't change + default-frame-alist based on menu-bar-mode and tool-bar-mode, or + vice versa (Bug#2249). + +2010-06-26 Eli Zaretskii + + * w32-fns.el (w32-convert-standard-filename): Doc fix. + +2010-06-25 Agustín Martín + + * flyspell.el (flyspell-check-previous-highlighted-word): Make + sure `flyspell-word' re-checks word after function run (Bug#6504). + + * ispell.el (ispell-init-process): Make sure ispell and default + directories are expanded. (Bug#6143). + +2010-06-24 Juri Linkov + + * minibuffer.el (completions-format): Change default from nil to + `horizontal'. Remove `nil' value from :type. Doc fix. (Bug#6459) + +2010-06-24 Juri Linkov + + * vc/vc.el (vc-diff-internal): Set `revert-buffer-function' + buffer-locally to lambda that re-runs the vc diff command. + (Bug#6447) + +2010-06-24 Chong Yidong + + * kmacro.el (kmacro-call-macro): Don't issue hint message if the + echo area is in use (Bug#3412). + +2010-06-22 Glenn Morris + + * textmodes/texinfmt.el (texinfo-format-region) + (texinfo-raise-lower-sections, texinfo-format-separate-node) + (texinfo-itemize-item, texinfo-multitable-item, texinfo-alias) + (texinfo-format-option, texinfo-noindent): + Use line-beginning-position and line-end-position. + + * calc/calc-aent.el, calc/calc-ext.el, calc/calc-lang.el: + * calc/calc-store.el, calc/calc-units.el, calc/calc.el: + * calc/calccomp.el: Add explicit utf-8 coding cookies to files with + utf-8 characters. + +2010-06-21 Karl Fogel + + * play/zone.el (zone-fall-through-ws): Fix next-line -> + forward-line fallout. + + 2010-07-06 Chong Yidong + + * mouse.el (mouse-appearance-menu): Add docstring. + + * help.el (describe-key): Print up-event using key-description. + + 2010-07-03 Michael Albinus + + * net/zeroconf.el (zeroconf-resolve-service) + (zeroconf-service-resolver-handler): Use + `dbus-byte-array-to-string'. + (zeroconf-publish-service): Use `dbus-string-to-byte-array'. + + 2010-07-03 Jan Moringen + + * net/zeroconf.el (zeroconf-service-remove-hook): New defun. + + 2010-06-30 Dan Nicolaescu + + Avoid displaying files with a nil state in vc-dir. + * vc-dir.el (vc-dir-update): Obey the noinsert argument in all + cases that cause insertion. + (vc-dir-resynch-file): Tell vc-dir-update to avoid inserting files + with a nil state. + + 2010-06-30 Chong Yidong + + * xml.el (xml-parse-region): Avoid infloop (Bug#5281). + + 2010-06-29 Leo + + * emacs-lisp/rx.el (rx): Doc fix. (Bug#6537) + + 2010-06-27 Oleksandr Gavenko (tiny change) + + * generic-x.el (bat-generic-mode): Fix regexp for command line + switches (Bug#5719). + + 2010-06-27 Masatake YAMATO + + * htmlfontify.el (hfy-face-attr-for-class): Use append instead + of nconc to avoid pure storage error (Bug#6239). + + 2010-06-27 Christoph (tiny change) + + * bookmark.el (bookmark-bmenu-2-window, bookmark-bmenu-other-window) + (bookmark-bmenu-other-window-with-mouse): Remove unnecessary + bindings of bookmark-automatically-show-annotations (Bug#6515). + + 2010-06-25 Eli Zaretskii + + * arc-mode.el (archive-zip-extract): Don't quote the file name on + MS-Windows and MS-DOS. (Bug#6467, Bug#6144) + + 2010-06-24 Štěpán Němec (tiny change) + + * comint.el (make-comint, make-comint-in-buffer): Mention return + value in the docstrings. (Bug#6498) + + 2010-06-24 Yoni Rabkin + + * bs.el (bs-mode-font-lock-keywords): Remove "by" from Dired pattern, + since it is not present when using some non-default switches. + + 2010-06-23 Karl Fogel + * simple.el (compose-mail): Fix doc string to refer to `compose-mail-user-agent-warnings', instead of to the nonexistent `compose-mail-check-user-agent'. +2010-06-21 Alan Mackenzie + + Fix an indentation bug: + + * progmodes/cc-mode.el (c-common-init): Initialise c-new-BEG/END. + (c-neutralize-syntax-in-and-mark-CPP): c-new-BEG/END: Take account + of existing values. + + * progmodes/cc-engine.el (c-clear-<-pair-props-if-match-after) + (c-clear->-pair-props-if-match-before): now return t when they've + cleared properties, nil otherwise. + (c-before-change-check-<>-operators): Set c-new-beg/end correctly + by taking account of the existing value. + + * progmodes/cc-defs.el + (c-clear-char-property-with-value-function): Fix this to clear the + property rather than overwriting it with nil. + +2010-06-20 Chong Yidong + + * emacs-lisp/package.el (package-print-package): Add link to + package description via describe-package. + (describe-package-1): List package requirements. Add button to + perform installation. + (package-menu-describe-package): New command. + + * help-mode.el (help-package): New button type. + +2010-06-19 Chong Yidong + + * emacs-lisp/package.el: Move package-list-packages binding to + menu-bar.el. + (describe-package, describe-package-1, package--dir): New funs. + (package-activate-1): Use package--dir. + + * emacs-lisp/package-x.el (gnus-article-buffer): Require package. + + * help-mode.el (help-package-def): New button type. + + * menu-bar.el: Move package-list-packages binding here from + package.el. + +2010-06-19 Gustav Hållberg (tiny change) + + * descr-text.el (describe-char): Avoid trailing whitespace. (Bug#6423) + +2010-06-18 Stefan Monnier + + * emacs-lisp/edebug.el (edebug-read-list): + Phase out old-style backquotes. + +2010-06-17 Juri Linkov + + * help-mode.el (help-mode): Set buffer-local variable + revert-buffer-function to help-mode-revert-buffer. + (help-mode-revert-buffer): New function. + + * info.el (Info-revert-find-node): Check for major-mode Info-mode + before popping to "*info*" (like in other Info functions). + Keep buffer-name in old-buffer-name. Keep Info-history-forward in + old-history-forward. Pop to old-buffer-name or "*info*" to + recreate the killed buffer. Set Info-history-forward from + old-history-forward. + (Info-breadcrumbs-depth): Add :group and :version. + +2010-06-17 Dan Nicolaescu + + * emacs-lisp/package.el (package-menu-mode-map): Add a menu. + +2010-06-17 Agustín Martín + + * ispell.el (ispell-aspell-find-dictionary): Fix regexp for + languages like Portuguese with pt_{BR,PT} and no plain pt. + +2010-06-17 Juanma Barranquero + + * emacs-lisp/package.el (package-menu-mode-map): + Move initialization into declaration. + + * menu-bar.el (menu-bar-options-menu): Fix typo in menu entry. + +2010-06-17 Chong Yidong + + * emacs-lisp/package.el (package-archive-base): Point to + elpa.gnu.org. + (package-enable, package-load-list): New defcustoms. + (package-user-dir, package-directory-list): Turn into defcustoms. + Don't include package-user-dir in package-directory-list. + (package--builtins-base): Don't include Emacs as a "package". + (package-subdirectory-regexp): New var. + (package-load-all-descriptors, package-compute-transaction) + (package-download-transaction): Obey package-load-list. + (package-activate-1): Rename from package-do-activate. + (package-list-packages-internal): Check package-load-list. + (package-load-descriptor, package-generate-autoloads) + (package-unpack, package-unpack-single) + (package--read-archive-file, package-delete): Use + expand-file-name. + + * emacs-lisp/package-x.el: New file. Package uploading + functionality split out from package.el. + + * startup.el (command-line): Load packages after reading init + file. + +2010-06-17 Tom Tromey + + * emacs-lisp/package.el: New file. + + 2010-06-22 Dan Nicolaescu + + Fix vc-annotate for renamed files when using Git. + * vc-git.el (vc-git-find-revision): Deal with empty results from + ls-files. Doe not pass the object as a file name to cat-file, it + is not a file name. + (vc-git-annotate-command): Pass the file name using -- to avoid + ambiguity with the revision. + (vc-git-previous-revision): Pass a relative file name. + + 2010-06-22 Glenn Morris + + * progmodes/js.el (js-mode-map): Use standard capitalization and + ellipses for menu entries. + + * wid-edit.el (widget-complete): Doc fix. + + 2010-06-22 Jürgen Hötzel (tiny change) + + * wid-edit.el (widget-complete): Fix typo in 2009-12-02 change. + + 2010-06-22 Dan Nicolaescu + + Fix annotating other revisions for renamed files in vc-annotate. + * vc-annotate.el (vc-annotate): Add an optional argument for the + VC backend. Use it when non-nil. + (vc-annotate-warp-revision): Pass the VC backend to vc-annotate. (Bug#6487) + + Fix vc-annotate-show-changeset-diff-revision-at-line for git. + * vc-annotate.el (vc-annotate-show-diff-revision-at-line-internal): + Do not pass the file name to the 'previous-revision call when we + don't want a file diff. (Bug#6489) + + 2010-06-21 Dan Nicolaescu + + Fix finding revisions for renamed files in vc-annotate. + * vc.el (vc-find-revision): Add an optional argument for + the VC backend. Use it when non-nil. + * vc-annotate.el (vc-annotate-find-revision-at-line): Pass the VC + backend to vc-find-revision. (Bug#6487) + + 2010-06-21 Dan Nicolaescu + + Fix reading file names in Git annotate buffers. + * vc-git.el (vc-git-annotate-extract-revision-at-line): Remove + trailing whitespace. Suggested by Eric Hanchrow. (Bug#6481) + + 2010-06-20 Alan Mackenzie + + * progmodes/cc-mode.el (c-before-hack-hook): When the mode is set + in file local variables, set it first. + + 2010-06-19 Glenn Morris + + * descr-text.el (describe-char-unicode-data): Insert separating + space when needed. (Bug#6422) + + * progmodes/idlwave.el (idlwave-action-and-binding): + Fix typo in 2009-12-03 change. (Bug#6450) + 2010-06-17 Stefan Monnier + * emacs-lisp/macroexp.el (macroexpand-all-1): Put back special + handling for `lambda' (misunderstanding). + +2010-06-16 Jay Belanger + + * calc/calc-poly.el: (math-accum-factors): Make sure that + constants aren't distributed after they are factored out. + +2010-06-16 Juri Linkov + + * facemenu.el (list-colors-display): Call `pop-to-buffer' before + `list-colors-print'. (Bug#6332) + + * subr.el (read-quoted-char): Fix up last change (bug#6290). + 2010-06-16 Stefan Monnier + * emacs-lisp/macroexp.el (macroexpand-all-1): Don't handle `lambda' + specially, since it's a macro. Fix up wrong hint passed to maybe-cons. + * font-lock.el (font-lock-major-mode): Rename from font-lock-mode-major-mode to distinguish it from global-font-lock-mode's own font-lock-mode-major-mode (bug#6135). diff --cc lisp/arc-mode.el index fb6155dfd41,1cb3ade9a2d..6dda7b2e40b --- a/lisp/arc-mode.el +++ b/lisp/arc-mode.el @@@ -1802,22 -1787,20 +1802,25 @@@ This doesn't recover lost files, it jus (apply 'vector (nreverse files)))) (defun archive-zip-extract (archive name) - (if (member-ignore-case (car archive-zip-extract) '("pkunzip" "pkzip")) - (archive-*-extract archive name archive-zip-extract) + (cond + ((member-ignore-case (car archive-zip-extract) '("pkunzip" "pkzip")) + (archive-*-extract archive name archive-zip-extract)) + ((equal (car archive-zip-extract) "7z") + (let ((archive-7z-extract archive-zip-extract)) + (archive-7z-extract archive name))) + (t (archive-extract-by-stdout archive - ;; unzip expands wildcards in NAME, so we need to quote it. + ;; unzip expands wildcards in NAME, so we need to quote it. But + ;; not on DOS/Windows, since that fails extraction on those + ;; systems, and file names with wildcards in zip archives don't + ;; work there anyway. ;; FIXME: Does pkunzip need similar treatment? - ;; (7z doesn't need to quote wildcards) - (if (equal (car archive-zip-extract) "unzip") + (if (and (not (memq system-type '(windows-nt ms-dos))) + (equal (car archive-zip-extract) "unzip")) (shell-quote-argument name) name) - archive-zip-extract))) + archive-zip-extract)))) (defun archive-zip-write-file-member (archive descr) (archive-*-write-file-member diff --cc lisp/vc/vc-annotate.el index d0951bdd404,00000000000..c95fe54d04a mode 100644,000000..100644 --- a/lisp/vc/vc-annotate.el +++ b/lisp/vc/vc-annotate.el @@@ -1,676 -1,0 +1,679 @@@ +;;; vc-annotate.el --- VC Annotate Support + +;; Copyright (C) 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006, +;; 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + +;; Author: Martin Lorentzson +;; Maintainer: FSF +;; Keywords: vc tools + +;; 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 3 of the License, 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. If not, see . + +;;; Commentary: +;; + +(require 'vc-hooks) +(require 'vc) + +;;; Code: +(eval-when-compile + (require 'cl)) + +(defcustom vc-annotate-display-mode 'fullscale + "Which mode to color the output of \\[vc-annotate] with by default." + :type '(choice (const :tag "By Color Map Range" nil) + (const :tag "Scale to Oldest" scale) + (const :tag "Scale Oldest->Newest" fullscale) + (number :tag "Specify Fractional Number of Days" + :value "20.5")) + :group 'vc) + +(defcustom vc-annotate-color-map + (if (and (tty-display-color-p) (<= (display-color-cells) 8)) + ;; A custom sorted TTY colormap + (let* ((colors + (sort + (delq nil + (mapcar (lambda (x) + (if (not (or + (string-equal (car x) "white") + (string-equal (car x) "black") )) + (car x))) + (tty-color-alist))) + (lambda (a b) + (cond + ((or (string-equal a "red") (string-equal b "blue")) t) + ((or (string-equal b "red") (string-equal a "blue")) nil) + ((string-equal a "yellow") t) + ((string-equal b "yellow") nil) + ((string-equal a "cyan") t) + ((string-equal b "cyan") nil) + ((string-equal a "green") t) + ((string-equal b "green") nil) + ((string-equal a "magenta") t) + ((string-equal b "magenta") nil) + (t (string< a b)))))) + (date 20.) + (delta (/ (- 360. date) (1- (length colors))))) + (mapcar (lambda (x) + (prog1 + (cons date x) + (setq date (+ date delta)))) colors)) + ;; Normal colormap: hue stepped from 0-240deg, value=1., saturation=0.75 + '(( 20. . "#FF3F3F") + ( 40. . "#FF6C3F") + ( 60. . "#FF993F") + ( 80. . "#FFC63F") + (100. . "#FFF33F") + (120. . "#DDFF3F") + (140. . "#B0FF3F") + (160. . "#83FF3F") + (180. . "#56FF3F") + (200. . "#3FFF56") + (220. . "#3FFF83") + (240. . "#3FFFB0") + (260. . "#3FFFDD") + (280. . "#3FF3FF") + (300. . "#3FC6FF") + (320. . "#3F99FF") + (340. . "#3F6CFF") + (360. . "#3F3FFF"))) + "Association list of age versus color, for \\[vc-annotate]. +Ages are given in units of fractional days. Default is eighteen +steps using a twenty day increment, from red to blue. For TTY +displays with 8 or fewer colors, the default is red to blue with +all other colors between (excluding black and white)." + :type 'alist + :group 'vc) + +(defcustom vc-annotate-very-old-color "#3F3FFF" + "Color for lines older than the current color range in \\[vc-annotate]." + :type 'string + :group 'vc) + +(defcustom vc-annotate-background "black" + "Background color for \\[vc-annotate]. +Default color is used if nil." + :type '(choice (const :tag "Default background" nil) (color)) + :group 'vc) + +(defcustom vc-annotate-menu-elements '(2 0.5 0.1 0.01) + "Menu elements for the mode-specific menu of VC-Annotate mode. +List of factors, used to expand/compress the time scale. See `vc-annotate'." + :type '(repeat number) + :group 'vc) + +(defvar vc-annotate-mode-map + (let ((m (make-sparse-keymap))) + (define-key m "a" 'vc-annotate-revision-previous-to-line) + (define-key m "d" 'vc-annotate-show-diff-revision-at-line) + (define-key m "D" 'vc-annotate-show-changeset-diff-revision-at-line) + (define-key m "f" 'vc-annotate-find-revision-at-line) + (define-key m "j" 'vc-annotate-revision-at-line) + (define-key m "l" 'vc-annotate-show-log-revision-at-line) + (define-key m "n" 'vc-annotate-next-revision) + (define-key m "p" 'vc-annotate-prev-revision) + (define-key m "w" 'vc-annotate-working-revision) + (define-key m "v" 'vc-annotate-toggle-annotation-visibility) + m) + "Local keymap used for VC-Annotate mode.") + +;;; Annotate functionality + +;; Declare globally instead of additional parameter to +;; temp-buffer-show-function (not possible to pass more than one +;; parameter). The use of annotate-ratio is deprecated in favor of +;; annotate-mode, which replaces it with the more sensible "span-to +;; days", along with autoscaling support. +(defvar vc-annotate-ratio nil "Global variable.") + +;; internal buffer-local variables +(defvar vc-annotate-backend nil) +(defvar vc-annotate-parent-file nil) +(defvar vc-annotate-parent-rev nil) +(defvar vc-annotate-parent-display-mode nil) + +(defconst vc-annotate-font-lock-keywords + ;; The fontification is done by vc-annotate-lines instead of font-lock. + '((vc-annotate-lines))) + +(define-derived-mode vc-annotate-mode special-mode "Annotate" + "Major mode for output buffers of the `vc-annotate' command. + +You can use the mode-specific menu to alter the time-span of the used +colors. See variable `vc-annotate-menu-elements' for customizing the +menu items." + ;; Frob buffer-invisibility-spec so that if it is originally a naked t, + ;; it will become a list, to avoid initial annotations being invisible. + (add-to-invisibility-spec 'foo) + (remove-from-invisibility-spec 'foo) + (set (make-local-variable 'truncate-lines) t) + (set (make-local-variable 'font-lock-defaults) + '(vc-annotate-font-lock-keywords t)) + (hack-dir-local-variables-non-file-buffer)) + +(defun vc-annotate-toggle-annotation-visibility () + "Toggle whether or not the annotation is visible." + (interactive) + (funcall (if (memq 'vc-annotate-annotation buffer-invisibility-spec) + 'remove-from-invisibility-spec + 'add-to-invisibility-spec) + 'vc-annotate-annotation) + (force-window-update (current-buffer))) + +(defun vc-annotate-display-default (ratio) + "Display the output of \\[vc-annotate] using the default color range. +The color range is given by `vc-annotate-color-map', scaled by RATIO. +The current time is used as the offset." + (interactive (progn (kill-local-variable 'vc-annotate-color-map) '(1.0))) + (message "Redisplaying annotation...") + (vc-annotate-display ratio) + (message "Redisplaying annotation...done")) + +(defun vc-annotate-oldest-in-map (color-map) + "Return the oldest time in the COLOR-MAP." + ;; Since entries should be sorted, we can just use the last one. + (caar (last color-map))) + +(defun vc-annotate-get-time-set-line-props () + (let ((bol (point)) + (date (vc-call-backend vc-annotate-backend 'annotate-time)) + (inhibit-read-only t)) + (assert (>= (point) bol)) + (put-text-property bol (point) 'invisible 'vc-annotate-annotation) + date)) + +(defun vc-annotate-display-autoscale (&optional full) + "Highlight the output of \\[vc-annotate] using an autoscaled color map. +Autoscaling means that the map is scaled from the current time to the +oldest annotation in the buffer, or, with prefix argument FULL, to +cover the range from the oldest annotation to the newest." + (interactive "P") + (let ((newest 0.0) + (oldest 999999.) ;Any CVS users at the founding of Rome? + (current (vc-annotate-convert-time (current-time))) + date) + (message "Redisplaying annotation...") + ;; Run through this file and find the oldest and newest dates annotated. + (save-excursion + (goto-char (point-min)) + (while (not (eobp)) + (when (setq date (vc-annotate-get-time-set-line-props)) + (when (> date newest) + (setq newest date)) + (when (< date oldest) + (setq oldest date))) + (forward-line 1))) + (vc-annotate-display + (/ (- (if full newest current) oldest) + (vc-annotate-oldest-in-map vc-annotate-color-map)) + (if full newest)) + (message "Redisplaying annotation...done \(%s\)" + (if full + (format "Spanned from %.1f to %.1f days old" + (- current oldest) + (- current newest)) + (format "Spanned to %.1f days old" (- current oldest)))))) + +;; Menu -- Using easymenu.el +(easy-menu-define vc-annotate-mode-menu vc-annotate-mode-map + "VC Annotate Display Menu" + `("VC-Annotate" + ["By Color Map Range" (unless (null vc-annotate-display-mode) + (setq vc-annotate-display-mode nil) + (vc-annotate-display-select)) + :style toggle :selected (null vc-annotate-display-mode)] + ,@(let ((oldest-in-map (vc-annotate-oldest-in-map vc-annotate-color-map))) + (mapcar (lambda (element) + (let ((days (* element oldest-in-map))) + `[,(format "Span %.1f days" days) + (vc-annotate-display-select nil ,days) + :style toggle :selected + (eql vc-annotate-display-mode ,days) ])) + vc-annotate-menu-elements)) + ["Span ..." + (vc-annotate-display-select + nil (float (string-to-number (read-string "Span how many days? "))))] + "--" + ["Span to Oldest" + (unless (eq vc-annotate-display-mode 'scale) + (vc-annotate-display-select nil 'scale)) + :help + "Use an autoscaled color map from the oldest annotation to the current time" + :style toggle :selected + (eq vc-annotate-display-mode 'scale)] + ["Span Oldest->Newest" + (unless (eq vc-annotate-display-mode 'fullscale) + (vc-annotate-display-select nil 'fullscale)) + :help + "Use an autoscaled color map from the oldest to the newest annotation" + :style toggle :selected + (eq vc-annotate-display-mode 'fullscale)] + "--" + ["Toggle annotation visibility" vc-annotate-toggle-annotation-visibility + :help + "Toggle whether the annotation is visible or not"] + ["Annotate previous revision" vc-annotate-prev-revision + :help "Visit the annotation of the revision previous to this one"] + ["Annotate next revision" vc-annotate-next-revision + :help "Visit the annotation of the revision after this one"] + ["Annotate revision at line" vc-annotate-revision-at-line + :help + "Visit the annotation of the revision identified in the current line"] + ["Annotate revision previous to line" vc-annotate-revision-previous-to-line + :help "Visit the annotation of the revision before the revision at line"] + ["Annotate latest revision" vc-annotate-working-revision + :help "Visit the annotation of the working revision of this file"] + "--" + ["Show log of revision at line" vc-annotate-show-log-revision-at-line + :help "Visit the log of the revision at line"] + ["Show diff of revision at line" vc-annotate-show-diff-revision-at-line + :help "Visit the diff of the revision at line from its previous revision"] + ["Show changeset diff of revision at line" + vc-annotate-show-changeset-diff-revision-at-line + :enable + (eq 'repository (vc-call-backend ,vc-annotate-backend 'revision-granularity)) + :help "Visit the diff of the revision at line from its previous revision"] + ["Visit revision at line" vc-annotate-find-revision-at-line + :help "Visit the revision identified in the current line"])) + +(defun vc-annotate-display-select (&optional buffer mode) + "Highlight the output of \\[vc-annotate]. +By default, the current buffer is highlighted, unless overridden by +BUFFER. `vc-annotate-display-mode' specifies the highlighting mode to +use; you may override this using the second optional arg MODE." + (interactive) + (when mode (setq vc-annotate-display-mode mode)) + (pop-to-buffer (or buffer (current-buffer))) + (cond ((null vc-annotate-display-mode) + ;; The ratio is global, thus relative to the global color-map. + (kill-local-variable 'vc-annotate-color-map) + (vc-annotate-display-default (or vc-annotate-ratio 1.0))) + ;; One of the auto-scaling modes + ((eq vc-annotate-display-mode 'scale) + (vc-exec-after `(vc-annotate-display-autoscale))) + ((eq vc-annotate-display-mode 'fullscale) + (vc-exec-after `(vc-annotate-display-autoscale t))) + ((numberp vc-annotate-display-mode) ; A fixed number of days lookback + (vc-annotate-display-default + (/ vc-annotate-display-mode + (vc-annotate-oldest-in-map vc-annotate-color-map)))) + (t (error "No such display mode: %s" + vc-annotate-display-mode)))) + +;;;###autoload - (defun vc-annotate (file rev &optional display-mode buf move-point-to) ++(defun vc-annotate (file rev &optional display-mode buf move-point-to vc-bk) + "Display the edit history of the current FILE using colors. + +This command creates a buffer that shows, for each line of the current +file, when it was last edited and by whom. Additionally, colors are +used to show the age of each line--blue means oldest, red means +youngest, and intermediate colors indicate intermediate ages. By +default, the time scale stretches back one year into the past; +everything that is older than that is shown in blue. + +With a prefix argument, this command asks two questions in the +minibuffer. First, you may enter a revision number REV; then the buffer +displays and annotates that revision instead of the working revision +\(type RET in the minibuffer to leave that default unchanged). Then, +you are prompted for the time span in days which the color range +should cover. For example, a time span of 20 days means that changes +over the past 20 days are shown in red to blue, according to their +age, and everything that is older than that is shown in blue. + +If MOVE-POINT-TO is given, move the point to that line. + ++If VC-BK is given used that VC backend. ++ +Customization variables: + +`vc-annotate-menu-elements' customizes the menu elements of the +mode-specific menu. `vc-annotate-color-map' and +`vc-annotate-very-old-color' define the mapping of time to colors. +`vc-annotate-background' specifies the background color." + (interactive + (save-current-buffer + (vc-ensure-vc-buffer) + (list buffer-file-name + (let ((def (vc-working-revision buffer-file-name))) + (if (null current-prefix-arg) def + (vc-read-revision + (format "Annotate from revision (default %s): " def) + (list buffer-file-name) nil def))) + (if (null current-prefix-arg) + vc-annotate-display-mode + (float (string-to-number + (read-string "Annotate span days (default 20): " + nil nil "20"))))))) + (vc-ensure-vc-buffer) + (setq vc-annotate-display-mode display-mode) ;Not sure why. --Stef + (let* ((temp-buffer-name (format "*Annotate %s (rev %s)*" (buffer-name) rev)) + (temp-buffer-show-function 'vc-annotate-display-select) + ;; If BUF is specified, we presume the caller maintains current line, + ;; so we don't need to do it here. This implementation may give + ;; strange results occasionally in the case of REV != WORKFILE-REV. + (current-line (or move-point-to (unless buf + (save-restriction + (widen) + (line-number-at-pos)))))) + (message "Annotating...") + ;; If BUF is specified it tells in which buffer we should put the + ;; annotations. This is used when switching annotations to another + ;; revision, so we should update the buffer's name. + (when buf (with-current-buffer buf + (rename-buffer temp-buffer-name t) + ;; In case it had to be uniquified. + (setq temp-buffer-name (buffer-name)))) + (with-output-to-temp-buffer temp-buffer-name - (let ((backend (vc-backend file)) ++ (let ((backend (or vc-bk (vc-backend file))) + (coding-system-for-read buffer-file-coding-system)) + (vc-call-backend backend 'annotate-command file + (get-buffer temp-buffer-name) rev) + ;; we must setup the mode first, and then set our local + ;; variables before the show-function is called at the exit of + ;; with-output-to-temp-buffer + (with-current-buffer temp-buffer-name + (unless (equal major-mode 'vc-annotate-mode) + (vc-annotate-mode)) + (set (make-local-variable 'vc-annotate-backend) backend) + (set (make-local-variable 'vc-annotate-parent-file) file) + (set (make-local-variable 'vc-annotate-parent-rev) rev) + (set (make-local-variable 'vc-annotate-parent-display-mode) + display-mode)))) + + (with-current-buffer temp-buffer-name + (vc-exec-after + `(progn + ;; Ideally, we'd rather not move point if the user has already + ;; moved it elsewhere, but really point here is not the position + ;; of the user's cursor :-( + (when ,current-line ;(and (bobp)) + (goto-line ,current-line) + (setq vc-sentinel-movepoint (point))) + (unless (active-minibuffer-window) + (message "Annotating... done"))))))) + +(defun vc-annotate-prev-revision (prefix) + "Visit the annotation of the revision previous to this one. + +With a numeric prefix argument, annotate the revision that many +revisions previous." + (interactive "p") + (vc-annotate-warp-revision (- 0 prefix))) + +(defun vc-annotate-next-revision (prefix) + "Visit the annotation of the revision after this one. + +With a numeric prefix argument, annotate the revision that many +revisions after." + (interactive "p") + (vc-annotate-warp-revision prefix)) + +(defun vc-annotate-working-revision () + "Visit the annotation of the working revision of this file." + (interactive) + (if (not (equal major-mode 'vc-annotate-mode)) + (message "Cannot be invoked outside of a vc annotate buffer") + (let ((warp-rev (vc-working-revision vc-annotate-parent-file))) + (if (equal warp-rev vc-annotate-parent-rev) + (message "Already at revision %s" warp-rev) + (vc-annotate-warp-revision warp-rev))))) + +(defun vc-annotate-extract-revision-at-line () + "Extract the revision number of the current line. +Return a cons (REV . FILENAME)." + ;; This function must be invoked from a buffer in vc-annotate-mode + (let ((rev (vc-call-backend vc-annotate-backend + 'annotate-extract-revision-at-line))) + (if (or (null rev) (consp rev)) + rev + (cons rev vc-annotate-parent-file)))) + +(defun vc-annotate-revision-at-line () + "Visit the annotation of the revision identified in the current line." + (interactive) + (if (not (equal major-mode 'vc-annotate-mode)) + (message "Cannot be invoked outside of a vc annotate buffer") + (let ((rev-at-line (vc-annotate-extract-revision-at-line))) + (if (not rev-at-line) + (message "Cannot extract revision number from the current line") + (if (and (equal (car rev-at-line) vc-annotate-parent-rev) + (string= (cdr rev-at-line) vc-annotate-parent-file)) + (message "Already at revision %s" rev-at-line) + (vc-annotate-warp-revision (car rev-at-line) (cdr rev-at-line))))))) + +(defun vc-annotate-find-revision-at-line () + "Visit the revision identified in the current line." + (interactive) + (if (not (equal major-mode 'vc-annotate-mode)) + (message "Cannot be invoked outside of a vc annotate buffer") + (let ((rev-at-line (vc-annotate-extract-revision-at-line))) + (if (not rev-at-line) + (message "Cannot extract revision number from the current line") + (switch-to-buffer-other-window - (vc-find-revision (cdr rev-at-line) (car rev-at-line))))))) ++ (vc-find-revision (cdr rev-at-line) (car rev-at-line) vc-annotate-backend)))))) + +(defun vc-annotate-revision-previous-to-line () + "Visit the annotation of the revision before the revision at line." + (interactive) + (if (not (equal major-mode 'vc-annotate-mode)) + (message "Cannot be invoked outside of a vc annotate buffer") + (let* ((rev-at-line (vc-annotate-extract-revision-at-line)) + (prev-rev nil) + (rev (car rev-at-line)) + (fname (cdr rev-at-line))) + (if (not rev-at-line) + (message "Cannot extract revision number from the current line") + (setq prev-rev + (vc-call-backend vc-annotate-backend 'previous-revision + fname rev)) + (vc-annotate-warp-revision prev-rev fname))))) + +(defvar log-view-vc-backend) +(defvar log-view-vc-fileset) + +(defun vc-annotate-show-log-revision-at-line () + "Visit the log of the revision at line. +If the VC backend supports it, only show the log entry for the revision. +If a *vc-change-log* buffer exists and already shows a log for +the file in question, search for the log entry required and move point ." + (interactive) + (if (not (equal major-mode 'vc-annotate-mode)) + (message "Cannot be invoked outside of a vc annotate buffer") + (let ((rev-at-line (vc-annotate-extract-revision-at-line))) + (if (not rev-at-line) + (message "Cannot extract revision number from the current line") + (let ((backend vc-annotate-backend) + (log-buf (get-buffer "*vc-change-log*")) + pos) + (if (and + log-buf + ;; Look for a log buffer that already displays the correct file. + (with-current-buffer log-buf + (and (eq backend log-view-vc-backend) + (null (cdr log-view-vc-fileset)) + (string= (car log-view-vc-fileset) (cdr rev-at-line)) + ;; Check if the entry we require can be found. + (vc-call-backend + backend 'show-log-entry (car rev-at-line)) + (setq pos (point))))) + (progn + (pop-to-buffer log-buf) + (goto-char pos)) + ;; Ask the backend to display a single log entry. + (vc-print-log-internal + vc-annotate-backend (list (cdr rev-at-line)) + (car rev-at-line) t 1))))))) + +(defun vc-annotate-show-diff-revision-at-line-internal (filediff) + (if (not (equal major-mode 'vc-annotate-mode)) + (message "Cannot be invoked outside of a vc annotate buffer") + (let* ((rev-at-line (vc-annotate-extract-revision-at-line)) + (prev-rev nil) + (rev (car rev-at-line)) + (fname (cdr rev-at-line))) + (if (not rev-at-line) + (message "Cannot extract revision number from the current line") + (setq prev-rev + (vc-call-backend vc-annotate-backend 'previous-revision - fname rev)) ++ (if filediff fname nil) rev)) + (if (not prev-rev) + (message "Cannot diff from any revision prior to %s" rev) + (save-window-excursion + (vc-diff-internal + nil + ;; The value passed here should follow what + ;; `vc-deduce-fileset' returns. + (list vc-annotate-backend + (if filediff + (list fname) + nil)) + prev-rev rev)) + (switch-to-buffer "*vc-diff*")))))) + +(defun vc-annotate-show-diff-revision-at-line () + "Visit the diff of the revision at line from its previous revision." + (interactive) + (vc-annotate-show-diff-revision-at-line-internal t)) + +(defun vc-annotate-show-changeset-diff-revision-at-line () + "Visit the diff of the revision at line from its previous revision for all files in the changeset." + (interactive) + (when (eq 'file (vc-call-backend vc-annotate-backend 'revision-granularity)) + (error "The %s backend does not support changeset diffs" vc-annotate-backend)) + (vc-annotate-show-diff-revision-at-line-internal nil)) + +(defun vc-annotate-warp-revision (revspec &optional file) + "Annotate the revision described by REVSPEC. + +If REVSPEC is a positive integer, warp that many revisions forward, +if possible, otherwise echo a warning message. If REVSPEC is a +negative integer, warp that many revisions backward, if possible, +otherwise echo a warning message. If REVSPEC is a string, then it +describes a revision number, so warp to that revision." + (if (not (equal major-mode 'vc-annotate-mode)) + (message "Cannot be invoked outside of a vc annotate buffer") + (let* ((buf (current-buffer)) + (oldline (line-number-at-pos)) + (revspeccopy revspec) + (newrev nil)) + (cond + ((and (integerp revspec) (> revspec 0)) + (setq newrev vc-annotate-parent-rev) + (while (and (> revspec 0) newrev) + (setq newrev (vc-call-backend vc-annotate-backend 'next-revision + (or file vc-annotate-parent-file) newrev)) + (setq revspec (1- revspec))) + (unless newrev + (message "Cannot increment %d revisions from revision %s" + revspeccopy vc-annotate-parent-rev))) + ((and (integerp revspec) (< revspec 0)) + (setq newrev vc-annotate-parent-rev) + (while (and (< revspec 0) newrev) + (setq newrev (vc-call-backend vc-annotate-backend 'previous-revision + (or file vc-annotate-parent-file) newrev)) + (setq revspec (1+ revspec))) + (unless newrev + (message "Cannot decrement %d revisions from revision %s" + (- 0 revspeccopy) vc-annotate-parent-rev))) + ((stringp revspec) (setq newrev revspec)) + (t (error "Invalid argument to vc-annotate-warp-revision"))) + (when newrev + (vc-annotate (or file vc-annotate-parent-file) newrev + vc-annotate-parent-display-mode + buf + ;; Pass the current line so that vc-annotate will + ;; place the point in the line. + (min oldline (progn (goto-char (point-max)) + (forward-line -1) - (line-number-at-pos)))))))) ++ (line-number-at-pos))) ++ vc-annotate-backend))))) + +(defun vc-annotate-compcar (threshold a-list) + "Test successive cons cells of A-LIST against THRESHOLD. +Return the first cons cell with a car that is not less than THRESHOLD, +nil if no such cell exists." + (let ((i 1) + (tmp-cons (car a-list))) + (while (and tmp-cons (< (car tmp-cons) threshold)) + (setq tmp-cons (car (nthcdr i a-list))) + (setq i (+ i 1))) + tmp-cons)) ; Return the appropriate value + +(defun vc-annotate-convert-time (time) + "Convert a time value to a floating-point number of days. +The argument TIME is a list as returned by `current-time' or +`encode-time', only the first two elements of that list are considered." + (/ (+ (* (float (car time)) (lsh 1 16)) (cadr time)) 24 3600)) + +(defun vc-annotate-difference (&optional offset) + "Return the time span in days to the next annotation. +This calls the backend function annotate-time, and returns the +difference in days between the time returned and the current time, +or OFFSET if present." + (let ((next-time (vc-annotate-get-time-set-line-props))) + (when next-time + (- (or offset + (vc-call-backend vc-annotate-backend 'annotate-current-time)) + next-time)))) + +(defun vc-default-annotate-current-time (backend) + "Return the current time, encoded as fractional days." + (vc-annotate-convert-time (current-time))) + +(defvar vc-annotate-offset nil) + +(defun vc-annotate-display (ratio &optional offset) + "Highlight `vc-annotate' output in the current buffer. +RATIO is the expansion that should be applied to `vc-annotate-color-map'. +The annotations are relative to the current time, unless overridden by OFFSET." + (when (/= ratio 1.0) + (set (make-local-variable 'vc-annotate-color-map) + (mapcar (lambda (elem) (cons (* (car elem) ratio) (cdr elem))) + vc-annotate-color-map))) + (set (make-local-variable 'vc-annotate-offset) offset) + (font-lock-mode 1)) + +(defun vc-annotate-lines (limit) + (while (< (point) limit) + (let ((difference (vc-annotate-difference vc-annotate-offset)) + (start (point)) + (end (progn (forward-line 1) (point)))) + (when difference + (let* ((color (or (vc-annotate-compcar difference vc-annotate-color-map) + (cons nil vc-annotate-very-old-color))) + ;; substring from index 1 to remove any leading `#' in the name + (face-name (concat "vc-annotate-face-" + (if (string-equal + (substring (cdr color) 0 1) "#") + (substring (cdr color) 1) + (cdr color)))) + ;; Make the face if not done. + (face (or (intern-soft face-name) + (let ((tmp-face (make-face (intern face-name)))) + (set-face-foreground tmp-face (cdr color)) + (when vc-annotate-background + (set-face-background tmp-face + vc-annotate-background)) + tmp-face)))) ; Return the face + (put-text-property start end 'face face))))) + ;; Pretend to font-lock there were no matches. + nil) + +(provide 'vc-annotate) + +;; arch-tag: c3454a89-80e5-4ffd-8993-671b59612898 +;;; vc-annotate.el ends here diff --cc lisp/vc/vc-dir.el index 161013fbae0,00000000000..9cacef2f71b mode 100644,000000..100644 --- a/lisp/vc/vc-dir.el +++ b/lisp/vc/vc-dir.el @@@ -1,1256 -1,0 +1,1260 @@@ +;;; vc-dir.el --- Directory status display under VC + +;; Copyright (C) 2007, 2008, 2009, 2010 +;; Free Software Foundation, Inc. + +;; Author: Dan Nicolaescu +;; Keywords: vc tools + +;; 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 3 of the License, 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. If not, see . + +;;; Credits: + +;; The original VC directory status implementation was based on dired. +;; This implementation was inspired by PCL-CVS. +;; Many people contributed comments, ideas and code to this +;; implementation. These include: +;; +;; Alexandre Julliard +;; Stefan Monnier +;; Tom Tromey + +;;; Commentary: +;; + +;;; Todo: see vc.el. + +(require 'vc-hooks) +(require 'vc) +(require 'tool-bar) +(require 'ewoc) + +;;; Code: +(eval-when-compile + (require 'cl)) + +(defcustom vc-dir-mode-hook nil + "Normal hook run by `vc-dir-mode'. +See `run-hooks'." + :type 'hook + :group 'vc) + +;; Used to store information for the files displayed in the directory buffer. +;; Each item displayed corresponds to one of these defstructs. +(defstruct (vc-dir-fileinfo + (:copier nil) + (:type list) ;So we can use `member' on lists of FIs. + (:constructor + ;; We could define it as an alias for `list'. + vc-dir-create-fileinfo (name state &optional extra marked directory)) + (:conc-name vc-dir-fileinfo->)) + name ;Keep it as first, for `member'. + state + ;; For storing backend specific information. + extra + marked + ;; To keep track of not updated files during a global refresh + needs-update + ;; To distinguish files and directories. + directory) + +(defvar vc-ewoc nil) + +(defvar vc-dir-process-buffer nil + "The buffer used for the asynchronous call that computes status.") + +(defvar vc-dir-backend nil + "The backend used by the current *vc-dir* buffer.") + +(defun vc-dir-move-to-goal-column () + ;; Used to keep the cursor on the file name column. + (beginning-of-line) + (unless (eolp) + ;; Must be in sync with vc-default-dir-printer. + (forward-char 25))) + +(defun vc-dir-prepare-status-buffer (bname dir backend &optional create-new) + "Find a buffer named BNAME showing DIR, or create a new one." + (setq dir (file-name-as-directory (expand-file-name dir))) + (let* ;; Look for another buffer name BNAME visiting the same directory. + ((buf (save-excursion + (unless create-new + (dolist (buffer vc-dir-buffers) + (when (buffer-live-p buffer) + (set-buffer buffer) + (when (and (derived-mode-p 'vc-dir-mode) + (eq vc-dir-backend backend) + (string= default-directory dir)) + (return buffer)))))))) + (or buf + ;; Create a new buffer named BNAME. + ;; We pass a filename to create-file-buffer because it is what + ;; the function expects, and also what uniquify needs (if active) + (with-current-buffer (create-file-buffer (expand-file-name bname dir)) + (cd dir) + (vc-setup-buffer (current-buffer)) + ;; Reset the vc-parent-buffer-name so that it does not appear + ;; in the mode-line. + (setq vc-parent-buffer-name nil) + (current-buffer))))) + +(defvar vc-dir-menu-map + (let ((map (make-sparse-keymap "VC-dir"))) + (define-key map [quit] + '(menu-item "Quit" quit-window + :help "Quit")) + (define-key map [kill] + '(menu-item "Kill Update Command" vc-dir-kill-dir-status-process + :enable (vc-dir-busy) + :help "Kill the command that updates the directory buffer")) + (define-key map [refresh] + '(menu-item "Refresh" revert-buffer + :enable (not (vc-dir-busy)) + :help "Refresh the contents of the directory buffer")) + (define-key map [remup] + '(menu-item "Hide up-to-date" vc-dir-hide-up-to-date + :help "Hide up-to-date items from display")) + ;; Movement. + (define-key map [sepmv] '("--")) + (define-key map [next-line] + '(menu-item "Next line" vc-dir-next-line + :help "Go to the next line" :keys "n")) + (define-key map [previous-line] + '(menu-item "Previous line" vc-dir-previous-line + :help "Go to the previous line")) + ;; Marking. + (define-key map [sepmrk] '("--")) + (define-key map [unmark-all] + '(menu-item "Unmark All" vc-dir-unmark-all-files + :help "Unmark all files that are in the same state as the current file\ +\nWith prefix argument unmark all files")) + (define-key map [unmark-previous] + '(menu-item "Unmark previous " vc-dir-unmark-file-up + :help "Move to the previous line and unmark the file")) + + (define-key map [mark-all] + '(menu-item "Mark All" vc-dir-mark-all-files + :help "Mark all files that are in the same state as the current file\ +\nWith prefix argument mark all files")) + (define-key map [unmark] + '(menu-item "Unmark" vc-dir-unmark + :help "Unmark the current file or all files in the region")) + + (define-key map [mark] + '(menu-item "Mark" vc-dir-mark + :help "Mark the current file or all files in the region")) + + (define-key map [sepopn] '("--")) + (define-key map [qr] + '(menu-item "Query Replace in Files..." vc-dir-query-replace-regexp + :help "Replace a string in the marked files")) + (define-key map [se] + '(menu-item "Search Files..." vc-dir-search + :help "Search a regexp in the marked files")) + (define-key map [ires] + '(menu-item "Isearch Regexp Files..." vc-dir-isearch-regexp + :help "Incremental search a regexp in the marked files")) + (define-key map [ise] + '(menu-item "Isearch Files..." vc-dir-isearch + :help "Incremental search a string in the marked files")) + (define-key map [open-other] + '(menu-item "Open in other window" vc-dir-find-file-other-window + :help "Find the file on the current line, in another window")) + (define-key map [open] + '(menu-item "Open file" vc-dir-find-file + :help "Find the file on the current line")) + (define-key map [sepvcdet] '("--")) + ;; FIXME: This needs a key binding. And maybe a better name + ;; ("Insert" like PCL-CVS uses does not sound that great either)... + (define-key map [ins] + '(menu-item "Show File" vc-dir-show-fileentry + :help "Show a file in the VC status listing even though it might be up to date")) + (define-key map [annotate] + '(menu-item "Annotate" vc-annotate + :help "Display the edit history of the current file using colors")) + (define-key map [diff] + '(menu-item "Compare with Base Version" vc-diff + :help "Compare file set with the base version")) + (define-key map [logo] + '(menu-item "Show Outgoing Log" vc-log-outgoing + :help "Show a log of changes that will be sent with a push operation")) + (define-key map [logi] + '(menu-item "Show Incoming Log" vc-log-incoming + :help "Show a log of changes that will be received with a pull operation")) + (define-key map [log] + '(menu-item "Show history" vc-print-log + :help "List the change log of the current file set in a window")) + (define-key map [rlog] + '(menu-item "Show Top of the Tree History " vc-print-root-log + :help "List the change log for the current tree in a window")) + ;; VC commands. + (define-key map [sepvccmd] '("--")) + (define-key map [update] + '(menu-item "Update to latest version" vc-update + :help "Update the current fileset's files to their tip revisions")) + (define-key map [revert] + '(menu-item "Revert to base version" vc-revert + :help "Revert working copies of the selected fileset to their repository contents.")) + (define-key map [next-action] + ;; FIXME: This really really really needs a better name! + ;; And a key binding too. + '(menu-item "Check In/Out" vc-next-action + :help "Do the next logical version control operation on the current fileset")) + (define-key map [register] + '(menu-item "Register" vc-register + :help "Register file set into the version control system")) + map) + "Menu for VC dir.") + +;; VC backends can use this to add mode-specific menu items to +;; vc-dir-menu-map. +(defun vc-dir-menu-map-filter (orig-binding) + (when (and (symbolp orig-binding) (fboundp orig-binding)) + (setq orig-binding (indirect-function orig-binding))) + (let ((ext-binding + (when (derived-mode-p 'vc-dir-mode) + (vc-call-backend vc-dir-backend 'extra-status-menu)))) + (if (null ext-binding) + orig-binding + (append orig-binding + '("----") + ext-binding)))) + +(defvar vc-dir-mode-map + (let ((map (make-sparse-keymap))) + ;; VC commands + (define-key map "v" 'vc-next-action) ;; C-x v v + (define-key map "=" 'vc-diff) ;; C-x v = + (define-key map "i" 'vc-register) ;; C-x v i + (define-key map "+" 'vc-update) ;; C-x v + + (define-key map "l" 'vc-print-log) ;; C-x v l + ;; More confusing than helpful, probably + ;;(define-key map "R" 'vc-revert) ;; u is taken by vc-dir-unmark. + ;;(define-key map "A" 'vc-annotate) ;; g is taken by revert-buffer + ;; bound by `special-mode'. + ;; Marking. + (define-key map "m" 'vc-dir-mark) + (define-key map "M" 'vc-dir-mark-all-files) + (define-key map "u" 'vc-dir-unmark) + (define-key map "U" 'vc-dir-unmark-all-files) + (define-key map "\C-?" 'vc-dir-unmark-file-up) + (define-key map "\M-\C-?" 'vc-dir-unmark-all-files) + ;; Movement. + (define-key map "n" 'vc-dir-next-line) + (define-key map " " 'vc-dir-next-line) + (define-key map "\t" 'vc-dir-next-directory) + (define-key map "p" 'vc-dir-previous-line) + (define-key map [backtab] 'vc-dir-previous-directory) + ;;; Rebind paragraph-movement commands. + (define-key map "\M-}" 'vc-dir-next-directory) + (define-key map "\M-{" 'vc-dir-previous-directory) + (define-key map [C-down] 'vc-dir-next-directory) + (define-key map [C-up] 'vc-dir-previous-directory) + ;; The remainder. + (define-key map "f" 'vc-dir-find-file) + (define-key map "\C-m" 'vc-dir-find-file) + (define-key map "o" 'vc-dir-find-file-other-window) + (define-key map "\C-c\C-c" 'vc-dir-kill-dir-status-process) + (define-key map [down-mouse-3] 'vc-dir-menu) + (define-key map [mouse-2] 'vc-dir-toggle-mark) + (define-key map [follow-link] 'mouse-face) + (define-key map "x" 'vc-dir-hide-up-to-date) + (define-key map [?\C-k] 'vc-dir-kill-line) + (define-key map "S" 'vc-dir-search) ;; FIXME: Maybe use A like dired? + (define-key map "Q" 'vc-dir-query-replace-regexp) + (define-key map (kbd "M-s a C-s") 'vc-dir-isearch) + (define-key map (kbd "M-s a M-C-s") 'vc-dir-isearch-regexp) + + ;; Hook up the menu. + (define-key map [menu-bar vc-dir-mode] + `(menu-item + ;; VC backends can use this to add mode-specific menu items to + ;; vc-dir-menu-map. + "VC-dir" ,vc-dir-menu-map :filter vc-dir-menu-map-filter)) + map) + "Keymap for directory buffer.") + +(defmacro vc-dir-at-event (event &rest body) + "Evaluate BODY with point located at event-start of EVENT. +If BODY uses EVENT, it should be a variable, + otherwise it will be evaluated twice." + (let ((posn (make-symbol "vc-dir-at-event-posn"))) + `(save-excursion + (unless (equal ,event '(tool-bar)) + (let ((,posn (event-start ,event))) + (set-buffer (window-buffer (posn-window ,posn))) + (goto-char (posn-point ,posn)))) + ,@body))) + +(defun vc-dir-menu (e) + "Popup the VC dir menu." + (interactive "e") + (vc-dir-at-event e (popup-menu vc-dir-menu-map e))) + +(defvar vc-dir-tool-bar-map + (let ((map (make-sparse-keymap))) + (tool-bar-local-item-from-menu 'vc-dir-find-file "open" + map vc-dir-mode-map) + (tool-bar-local-item "bookmark_add" + 'vc-dir-toggle-mark 'vc-dir-toggle-mark map + :help "Toggle mark on current item" + :label "Toggle Mark") + (tool-bar-local-item-from-menu 'vc-dir-previous-line "left-arrow" + map vc-dir-mode-map + :rtl "right-arrow") + (tool-bar-local-item-from-menu 'vc-dir-next-line "right-arrow" + map vc-dir-mode-map + :rtl "left-arrow") + (tool-bar-local-item-from-menu 'vc-print-log "info" + map vc-dir-mode-map) + (tool-bar-local-item-from-menu 'revert-buffer "refresh" + map vc-dir-mode-map) + (tool-bar-local-item-from-menu 'nonincremental-search-forward + "search" map nil + :label "Search") + (tool-bar-local-item-from-menu 'vc-dir-query-replace-regexp + "search-replace" map vc-dir-mode-map + :label "Replace") + (tool-bar-local-item-from-menu 'vc-dir-kill-dir-status-process "cancel" + map vc-dir-mode-map + :label "Cancel") + (tool-bar-local-item-from-menu 'quit-window "exit" + map vc-dir-mode-map) + map)) + +(defun vc-dir-node-directory (node) + ;; Compute the directory for NODE. + ;; If it's a directory node, get it from the node. + (let ((data (ewoc-data node))) + (or (vc-dir-fileinfo->directory data) + ;; Otherwise compute it from the file name. + (file-name-directory + (directory-file-name + (expand-file-name + (vc-dir-fileinfo->name data))))))) + +(defun vc-dir-update (entries buffer &optional noinsert) + "Update BUFFER's ewoc from the list of ENTRIES. +If NOINSERT, ignore elements on ENTRIES which are not in the ewoc." + ;; Add ENTRIES to the vc-dir buffer BUFFER. + (with-current-buffer buffer + ;; Insert the entries sorted by name into the ewoc. + ;; We assume the ewoc is sorted too, which should be the + ;; case if we always add entries with vc-dir-update. + (setq entries + ;; Sort: first files and then subdirectories. + ;; XXX: this is VERY inefficient, it computes the directory + ;; names too many times + (sort entries + (lambda (entry1 entry2) + (let ((dir1 (file-name-directory + (directory-file-name (expand-file-name (car entry1))))) + (dir2 (file-name-directory + (directory-file-name (expand-file-name (car entry2)))))) + (cond + ((string< dir1 dir2) t) + ((not (string= dir1 dir2)) nil) + ((string< (car entry1) (car entry2)))))))) + ;; Insert directory entries in the right places. + (let ((entry (car entries)) + (node (ewoc-nth vc-ewoc 0)) + (to-remove nil) + (dotname (file-relative-name default-directory))) + ;; Insert . if it is not present. + (unless node + (ewoc-enter-last + vc-ewoc (vc-dir-create-fileinfo + dotname nil nil nil default-directory)) + (setq node (ewoc-nth vc-ewoc 0))) + + (while (and entry node) + (let* ((entryfile (car entry)) + (entrydir (file-name-directory (directory-file-name + (expand-file-name entryfile)))) + (nodedir (vc-dir-node-directory node))) + (cond + ;; First try to find the directory. + ((string-lessp nodedir entrydir) + (setq node (ewoc-next vc-ewoc node))) + ((string-equal nodedir entrydir) + ;; Found the directory, find the place for the file name. + (let ((nodefile (vc-dir-fileinfo->name (ewoc-data node)))) + (cond + ((string= nodefile dotname) + (setq node (ewoc-next vc-ewoc node))) + ((string-lessp nodefile entryfile) + (setq node (ewoc-next vc-ewoc node))) + ((string-equal nodefile entryfile) + (if (nth 1 entry) + (progn + (setf (vc-dir-fileinfo->state (ewoc-data node)) (nth 1 entry)) + (setf (vc-dir-fileinfo->extra (ewoc-data node)) (nth 2 entry)) + (setf (vc-dir-fileinfo->needs-update (ewoc-data node)) nil) + (ewoc-invalidate vc-ewoc node)) + ;; If the state is nil, the file does not exist + ;; anymore, so remember the entry so we can remove + ;; it after we are done inserting all ENTRIES. + (push node to-remove)) + (setq entries (cdr entries)) + (setq entry (car entries)) + (setq node (ewoc-next vc-ewoc node))) + (t - (ewoc-enter-before vc-ewoc node - (apply 'vc-dir-create-fileinfo entry)) ++ (unless noinsert ++ (ewoc-enter-before vc-ewoc node ++ (apply 'vc-dir-create-fileinfo entry))) + (setq entries (cdr entries)) + (setq entry (car entries)))))) + (t - ;; We might need to insert a directory node if the - ;; previous node was in a different directory. - (let* ((rd (file-relative-name entrydir)) - (prev-node (ewoc-prev vc-ewoc node)) - (prev-dir (vc-dir-node-directory prev-node))) - (unless (string-equal entrydir prev-dir) - (ewoc-enter-before - vc-ewoc node (vc-dir-create-fileinfo rd nil nil nil entrydir)))) - ;; Now insert the node itself. - (ewoc-enter-before vc-ewoc node - (apply 'vc-dir-create-fileinfo entry)) ++ (unless noinsert ++ ;; We might need to insert a directory node if the ++ ;; previous node was in a different directory. ++ (let* ((rd (file-relative-name entrydir)) ++ (prev-node (ewoc-prev vc-ewoc node)) ++ (prev-dir (vc-dir-node-directory prev-node))) ++ (unless (string-equal entrydir prev-dir) ++ (ewoc-enter-before ++ vc-ewoc node (vc-dir-create-fileinfo rd nil nil nil entrydir)))) ++ ;; Now insert the node itself. ++ (ewoc-enter-before vc-ewoc node ++ (apply 'vc-dir-create-fileinfo entry))) + (setq entries (cdr entries) entry (car entries)))))) + ;; We're past the last node, all remaining entries go to the end. + (unless (or node noinsert) + (let ((lastdir (vc-dir-node-directory (ewoc-nth vc-ewoc -1)))) + (dolist (entry entries) + (let ((entrydir (file-name-directory + (directory-file-name (expand-file-name (car entry)))))) + ;; Insert a directory node if needed. + (unless (string-equal lastdir entrydir) + (setq lastdir entrydir) + (let ((rd (file-relative-name entrydir))) + (ewoc-enter-last + vc-ewoc (vc-dir-create-fileinfo rd nil nil nil entrydir)))) + ;; Now insert the node itself. + (ewoc-enter-last vc-ewoc + (apply 'vc-dir-create-fileinfo entry)))))) + (when to-remove + (let ((inhibit-read-only t)) + (apply 'ewoc-delete vc-ewoc (nreverse to-remove))))))) + +(defun vc-dir-busy () + (and (buffer-live-p vc-dir-process-buffer) + (get-buffer-process vc-dir-process-buffer))) + +(defun vc-dir-kill-dir-status-process () + "Kill the temporary buffer and associated process." + (interactive) + (when (buffer-live-p vc-dir-process-buffer) + (let ((proc (get-buffer-process vc-dir-process-buffer))) + (when proc (delete-process proc)) + (setq vc-dir-process-buffer nil) + (setq mode-line-process nil)))) + +(defun vc-dir-kill-query () + ;; Make sure that when the status buffer is killed the update + ;; process running in background is also killed. + (if (vc-dir-busy) + (when (y-or-n-p "Status update process running, really kill status buffer? ") + (vc-dir-kill-dir-status-process) + t) + t)) + +(defun vc-dir-next-line (arg) + "Go to the next line. +If a prefix argument is given, move by that many lines." + (interactive "p") + (with-no-warnings + (ewoc-goto-next vc-ewoc arg) + (vc-dir-move-to-goal-column))) + +(defun vc-dir-previous-line (arg) + "Go to the previous line. +If a prefix argument is given, move by that many lines." + (interactive "p") + (ewoc-goto-prev vc-ewoc arg) + (vc-dir-move-to-goal-column)) + +(defun vc-dir-next-directory () + "Go to the next directory." + (interactive) + (let ((orig (point))) + (if + (catch 'foundit + (while t + (let* ((next (ewoc-next vc-ewoc (ewoc-locate vc-ewoc)))) + (cond ((not next) + (throw 'foundit t)) + (t + (progn + (ewoc-goto-node vc-ewoc next) + (vc-dir-move-to-goal-column) + (if (vc-dir-fileinfo->directory (ewoc-data next)) + (throw 'foundit nil)))))))) + (goto-char orig)))) + +(defun vc-dir-previous-directory () + "Go to the previous directory." + (interactive) + (let ((orig (point))) + (if + (catch 'foundit + (while t + (let* ((prev (ewoc-prev vc-ewoc (ewoc-locate vc-ewoc)))) + (cond ((not prev) + (throw 'foundit t)) + (t + (progn + (ewoc-goto-node vc-ewoc prev) + (vc-dir-move-to-goal-column) + (if (vc-dir-fileinfo->directory (ewoc-data prev)) + (throw 'foundit nil)))))))) + (goto-char orig)))) + +(defun vc-dir-mark-unmark (mark-unmark-function) + (if (use-region-p) + (let ((firstl (line-number-at-pos (region-beginning))) + (lastl (line-number-at-pos (region-end)))) + (save-excursion + (goto-char (region-beginning)) + (while (<= (line-number-at-pos) lastl) + (funcall mark-unmark-function)))) + (funcall mark-unmark-function))) + +(defun vc-dir-parent-marked-p (arg) + ;; Return nil if none of the parent directories of arg is marked. + (let* ((argdir (vc-dir-node-directory arg)) + (arglen (length argdir)) + (crt arg) + data dir) + ;; Go through the predecessors, checking if any directory that is + ;; a parent is marked. + (while (setq crt (ewoc-prev vc-ewoc crt)) + (setq data (ewoc-data crt)) + (setq dir (vc-dir-node-directory crt)) + (when (and (vc-dir-fileinfo->directory data) + (vc-string-prefix-p dir argdir)) + (when (vc-dir-fileinfo->marked data) + (error "Cannot mark `%s', parent directory `%s' marked" + (vc-dir-fileinfo->name (ewoc-data arg)) + (vc-dir-fileinfo->name data))))) + nil)) + +(defun vc-dir-children-marked-p (arg) + ;; Return nil if none of the children of arg is marked. + (let* ((argdir-re (concat "\\`" (regexp-quote (vc-dir-node-directory arg)))) + (is-child t) + (crt arg) + data dir) + (while (and is-child (setq crt (ewoc-next vc-ewoc crt))) + (setq data (ewoc-data crt)) + (setq dir (vc-dir-node-directory crt)) + (if (string-match argdir-re dir) + (when (vc-dir-fileinfo->marked data) + (error "Cannot mark `%s', child `%s' marked" + (vc-dir-fileinfo->name (ewoc-data arg)) + (vc-dir-fileinfo->name data))) + ;; We are done, we got to an entry that is not a child of `arg'. + (setq is-child nil))) + nil)) + +(defun vc-dir-mark-file (&optional arg) + ;; Mark ARG or the current file and move to the next line. + (let* ((crt (or arg (ewoc-locate vc-ewoc))) + (file (ewoc-data crt)) + (isdir (vc-dir-fileinfo->directory file))) + (when (or (and isdir (not (vc-dir-children-marked-p crt))) + (and (not isdir) (not (vc-dir-parent-marked-p crt)))) + (setf (vc-dir-fileinfo->marked file) t) + (ewoc-invalidate vc-ewoc crt) + (unless (or arg (mouse-event-p last-command-event)) + (vc-dir-next-line 1))))) + +(defun vc-dir-mark () + "Mark the current file or all files in the region. +If the region is active, mark all the files in the region. +Otherwise mark the file on the current line and move to the next +line." + (interactive) + (vc-dir-mark-unmark 'vc-dir-mark-file)) + +(defun vc-dir-mark-all-files (arg) + "Mark all files with the same state as the current one. +With a prefix argument mark all files. +If the current entry is a directory, mark all child files. + +The commands operate on files that are on the same state. +This command is intended to make it easy to select all files that +share the same state." + (interactive "P") + (if arg + ;; Mark all files. + (progn + ;; First check that no directory is marked, we can't mark + ;; files in that case. + (ewoc-map + (lambda (filearg) + (when (and (vc-dir-fileinfo->directory filearg) + (vc-dir-fileinfo->marked filearg)) + (error "Cannot mark all files, directory `%s' marked" + (vc-dir-fileinfo->name filearg)))) + vc-ewoc) + (ewoc-map + (lambda (filearg) + (unless (vc-dir-fileinfo->marked filearg) + (setf (vc-dir-fileinfo->marked filearg) t) + t)) + vc-ewoc)) + (let ((data (ewoc-data (ewoc-locate vc-ewoc)))) + (if (vc-dir-fileinfo->directory data) + ;; It's a directory, mark child files. + (let ((crt (ewoc-locate vc-ewoc))) + (unless (vc-dir-children-marked-p crt) + (while (setq crt (ewoc-next vc-ewoc crt)) + (let ((crt-data (ewoc-data crt))) + (unless (vc-dir-fileinfo->directory crt-data) + (setf (vc-dir-fileinfo->marked crt-data) t) + (ewoc-invalidate vc-ewoc crt)))))) + ;; It's a file + (let ((state (vc-dir-fileinfo->state data)) + (crt (ewoc-nth vc-ewoc 0))) + (while crt + (let ((crt-data (ewoc-data crt))) + (when (and (not (vc-dir-fileinfo->marked crt-data)) + (eq (vc-dir-fileinfo->state crt-data) state) + (not (vc-dir-fileinfo->directory crt-data))) + (vc-dir-mark-file crt))) + (setq crt (ewoc-next vc-ewoc crt)))))))) + +(defun vc-dir-unmark-file () + ;; Unmark the current file and move to the next line. + (let* ((crt (ewoc-locate vc-ewoc)) + (file (ewoc-data crt))) + (setf (vc-dir-fileinfo->marked file) nil) + (ewoc-invalidate vc-ewoc crt) + (unless (mouse-event-p last-command-event) + (vc-dir-next-line 1)))) + +(defun vc-dir-unmark () + "Unmark the current file or all files in the region. +If the region is active, unmark all the files in the region. +Otherwise mark the file on the current line and move to the next +line." + (interactive) + (vc-dir-mark-unmark 'vc-dir-unmark-file)) + +(defun vc-dir-unmark-file-up () + "Move to the previous line and unmark the file." + (interactive) + ;; If we're on the first line, we won't move up, but we will still + ;; remove the mark. This seems a bit odd but it is what buffer-menu + ;; does. + (let* ((prev (ewoc-goto-prev vc-ewoc 1)) + (file (ewoc-data prev))) + (setf (vc-dir-fileinfo->marked file) nil) + (ewoc-invalidate vc-ewoc prev) + (vc-dir-move-to-goal-column))) + +(defun vc-dir-unmark-all-files (arg) + "Unmark all files with the same state as the current one. +With a prefix argument unmark all files. +If the current entry is a directory, unmark all the child files. + +The commands operate on files that are on the same state. +This command is intended to make it easy to deselect all files +that share the same state." + (interactive "P") + (if arg + (ewoc-map + (lambda (filearg) + (when (vc-dir-fileinfo->marked filearg) + (setf (vc-dir-fileinfo->marked filearg) nil) + t)) + vc-ewoc) + (let* ((crt (ewoc-locate vc-ewoc)) + (data (ewoc-data crt))) + (if (vc-dir-fileinfo->directory data) + ;; It's a directory, unmark child files. + (while (setq crt (ewoc-next vc-ewoc crt)) + (let ((crt-data (ewoc-data crt))) + (unless (vc-dir-fileinfo->directory crt-data) + (setf (vc-dir-fileinfo->marked crt-data) nil) + (ewoc-invalidate vc-ewoc crt)))) + ;; It's a file + (let ((crt-state (vc-dir-fileinfo->state (ewoc-data crt)))) + (ewoc-map + (lambda (filearg) + (when (and (vc-dir-fileinfo->marked filearg) + (eq (vc-dir-fileinfo->state filearg) crt-state)) + (setf (vc-dir-fileinfo->marked filearg) nil) + t)) + vc-ewoc)))))) + +(defun vc-dir-toggle-mark-file () + (let* ((crt (ewoc-locate vc-ewoc)) + (file (ewoc-data crt))) + (if (vc-dir-fileinfo->marked file) + (vc-dir-unmark-file) + (vc-dir-mark-file)))) + +(defun vc-dir-toggle-mark (e) + (interactive "e") + (vc-dir-at-event e (vc-dir-mark-unmark 'vc-dir-toggle-mark-file))) + +(defun vc-dir-delete-file () + "Delete the marked files, or the current file if no marks." + (interactive) + (mapc 'vc-delete-file (or (vc-dir-marked-files) + (list (vc-dir-current-file))))) + +(defun vc-dir-find-file () + "Find the file on the current line." + (interactive) + (find-file (vc-dir-current-file))) + +(defun vc-dir-find-file-other-window (&optional event) + "Find the file on the current line, in another window." + (interactive (list last-nonmenu-event)) + (if event (posn-set-point (event-end event))) + (find-file-other-window (vc-dir-current-file))) + +(defun vc-dir-isearch () + "Search for a string through all marked buffers using Isearch." + (interactive) + (multi-isearch-files + (mapcar 'car (vc-dir-marked-only-files-and-states)))) + +(defun vc-dir-isearch-regexp () + "Search for a regexp through all marked buffers using Isearch." + (interactive) + (multi-isearch-files-regexp + (mapcar 'car (vc-dir-marked-only-files-and-states)))) + +(defun vc-dir-search (regexp) + "Search through all marked files for a match for REGEXP. +For marked directories, use the files displayed from those directories. +Stops when a match is found. +To continue searching for next match, use command \\[tags-loop-continue]." + (interactive "sSearch marked files (regexp): ") + (tags-search regexp '(mapcar 'car (vc-dir-marked-only-files-and-states)))) + +(defun vc-dir-query-replace-regexp (from to &optional delimited) + "Do `query-replace-regexp' of FROM with TO, on all marked files. +For marked directories, use the files displayed from those directories. +If a directory is marked, then use the files displayed for that directory. +Third arg DELIMITED (prefix arg) means replace only word-delimited matches. +If you exit (\\[keyboard-quit], RET or q), you can resume the query replace +with the command \\[tags-loop-continue]." + ;; FIXME: this is almost a copy of `dired-do-replace-regexp'. This + ;; should probably be made generic and used in both places instead of + ;; duplicating it here. + (interactive + (let ((common + (query-replace-read-args + "Query replace regexp in marked files" t t))) + (list (nth 0 common) (nth 1 common) (nth 2 common)))) + (dolist (file (mapcar 'car (vc-dir-marked-only-files-and-states))) + (let ((buffer (get-file-buffer file))) + (if (and buffer (with-current-buffer buffer + buffer-read-only)) + (error "File `%s' is visited read-only" file)))) + (tags-query-replace from to delimited + '(mapcar 'car (vc-dir-marked-only-files-and-states)))) + +(defun vc-dir-current-file () + (let ((node (ewoc-locate vc-ewoc))) + (unless node + (error "No file available")) + (expand-file-name (vc-dir-fileinfo->name (ewoc-data node))))) + +(defun vc-dir-marked-files () + "Return the list of marked files." + (mapcar + (lambda (elem) (expand-file-name (vc-dir-fileinfo->name elem))) + (ewoc-collect vc-ewoc 'vc-dir-fileinfo->marked))) + +(defun vc-dir-marked-only-files-and-states () + "Return the list of conses (FILE . STATE) for the marked files. +For marked directories return the corresponding conses for the +child files." + (let ((crt (ewoc-nth vc-ewoc 0)) + result) + (while crt + (let ((crt-data (ewoc-data crt))) + (if (vc-dir-fileinfo->marked crt-data) + ;; FIXME: use vc-dir-child-files-and-states here instead of duplicating it. + (if (vc-dir-fileinfo->directory crt-data) + (let* ((dir (vc-dir-fileinfo->directory crt-data)) + (dirlen (length dir)) + data) + (while + (and (setq crt (ewoc-next vc-ewoc crt)) + (vc-string-prefix-p dir + (progn + (setq data (ewoc-data crt)) + (vc-dir-node-directory crt)))) + (unless (vc-dir-fileinfo->directory data) + (push + (cons (expand-file-name (vc-dir-fileinfo->name data)) + (vc-dir-fileinfo->state data)) + result)))) + (push (cons (expand-file-name (vc-dir-fileinfo->name crt-data)) + (vc-dir-fileinfo->state crt-data)) + result) + (setq crt (ewoc-next vc-ewoc crt))) + (setq crt (ewoc-next vc-ewoc crt))))) + (nreverse result))) + +(defun vc-dir-child-files-and-states () + "Return the list of conses (FILE . STATE) for child files of the current entry if it's a directory. +If it is a file, return the corresponding cons for the file itself." + (let* ((crt (ewoc-locate vc-ewoc)) + (crt-data (ewoc-data crt)) + result) + (if (vc-dir-fileinfo->directory crt-data) + (let* ((dir (vc-dir-fileinfo->directory crt-data)) + (dirlen (length dir)) + data) + (while + (and (setq crt (ewoc-next vc-ewoc crt)) + (vc-string-prefix-p dir (progn + (setq data (ewoc-data crt)) + (vc-dir-node-directory crt)))) + (unless (vc-dir-fileinfo->directory data) + (push + (cons (expand-file-name (vc-dir-fileinfo->name data)) + (vc-dir-fileinfo->state data)) + result)))) + (push + (cons (expand-file-name (vc-dir-fileinfo->name crt-data)) + (vc-dir-fileinfo->state crt-data)) result)) + (nreverse result))) + +(defun vc-dir-recompute-file-state (fname def-dir) + (let* ((file-short (file-relative-name fname def-dir)) + (remove-me-when-CVS-works + (when (eq vc-dir-backend 'CVS) + ;; FIXME: Warning: UGLY HACK. The CVS backend caches the state + ;; info, this forces the backend to update it. + (vc-call-backend vc-dir-backend 'registered fname))) + (state (vc-call-backend vc-dir-backend 'state fname)) + (extra (vc-call-backend vc-dir-backend + 'status-fileinfo-extra fname))) + (list file-short state extra))) + +(defun vc-dir-find-child-files (dirname) + ;; Give a DIRNAME string return the list of all child files shown in + ;; the current *vc-dir* buffer. + (let ((crt (ewoc-nth vc-ewoc 0)) + children + dname) + ;; Find DIR + (while (and crt (not (vc-string-prefix-p + dirname (vc-dir-node-directory crt)))) + (setq crt (ewoc-next vc-ewoc crt))) + (while (and crt (vc-string-prefix-p + dirname + (setq dname (vc-dir-node-directory crt)))) + (let ((data (ewoc-data crt))) + (unless (vc-dir-fileinfo->directory data) + (push (expand-file-name (vc-dir-fileinfo->name data)) children))) + (setq crt (ewoc-next vc-ewoc crt))) + children)) + +(defun vc-dir-resync-directory-files (dirname) + ;; Update the entries for all the child files of DIRNAME shown in + ;; the current *vc-dir* buffer. + (let ((files (vc-dir-find-child-files dirname)) + (ddir default-directory) + fileentries) + (when files + (dolist (crt files) + (push (vc-dir-recompute-file-state crt ddir) + fileentries)) + (vc-dir-update fileentries (current-buffer))))) + +(defun vc-dir-resynch-file (&optional fname) + "Update the entries for FNAME in any directory buffers that list it." + (let ((file (or fname (expand-file-name buffer-file-name))) + (drop '())) + (save-current-buffer + ;; look for a vc-dir buffer that might show this file. + (dolist (status-buf vc-dir-buffers) + (if (not (buffer-live-p status-buf)) + (push status-buf drop) + (set-buffer status-buf) + (if (not (derived-mode-p 'vc-dir-mode)) + (push status-buf drop) + (let ((ddir default-directory)) + (when (vc-string-prefix-p ddir file) + (if (file-directory-p file) + (progn + (vc-dir-resync-directory-files file) + (ewoc-set-hf vc-ewoc + (vc-dir-headers vc-dir-backend default-directory) "")) - (let ((state (vc-dir-recompute-file-state file ddir))) ++ (let* ((complete-state (vc-dir-recompute-file-state file ddir)) ++ (state (cadr complete-state))) + (vc-dir-update - (list state) - status-buf (eq (cadr state) 'up-to-date)))))))))) ++ (list complete-state) ++ status-buf (or (not state) ++ (eq state 'up-to-date))))))))))) + ;; Remove out-of-date entries from vc-dir-buffers. + (dolist (b drop) (setq vc-dir-buffers (delq b vc-dir-buffers))))) + +(defvar use-vc-backend) ;; dynamically bound + +(define-derived-mode vc-dir-mode special-mode "VC dir" + "Major mode for VC directory buffers. +Marking/Unmarking key bindings and actions: +m - mark a file/directory + - if the region is active, mark all the files in region. + Restrictions: - a file cannot be marked if any parent directory is marked + - a directory cannot be marked if any child file or + directory is marked +u - unmark a file/directory + - if the region is active, unmark all the files in region. +M - if the cursor is on a file: mark all the files with the same state as + the current file + - if the cursor is on a directory: mark all child files + - with a prefix argument: mark all files +U - if the cursor is on a file: unmark all the files with the same state + as the current file + - if the cursor is on a directory: unmark all child files + - with a prefix argument: unmark all files +mouse-2 - toggles the mark state + +VC commands +VC commands in the `C-x v' prefix can be used. +VC commands act on the marked entries. If nothing is marked, VC +commands act on the current entry. + +Search & Replace +S - searches the marked files +Q - does a query replace on the marked files +M-s a C-s - does an isearch on the marked files +M-s a C-M-s - does a regexp isearch on the marked files +If nothing is marked, these commands act on the current entry. +When a directory is current or marked, the Search & Replace +commands act on the child files of that directory that are displayed in +the *vc-dir* buffer. + +\\{vc-dir-mode-map}" + (set (make-local-variable 'vc-dir-backend) use-vc-backend) + (setq buffer-read-only t) + (when (boundp 'tool-bar-map) + (set (make-local-variable 'tool-bar-map) vc-dir-tool-bar-map)) + (let ((buffer-read-only nil)) + (erase-buffer) + (set (make-local-variable 'vc-dir-process-buffer) nil) + (set (make-local-variable 'vc-ewoc) (ewoc-create #'vc-dir-printer)) + (set (make-local-variable 'revert-buffer-function) + 'vc-dir-revert-buffer-function) + (setq list-buffers-directory (expand-file-name "*vc-dir*" default-directory)) + (add-to-list 'vc-dir-buffers (current-buffer)) + ;; Make sure that if the directory buffer is killed, the update + ;; process running in the background is also killed. + (add-hook 'kill-buffer-query-functions 'vc-dir-kill-query nil t) + (hack-dir-local-variables-non-file-buffer) + (vc-dir-refresh))) + +(defun vc-dir-headers (backend dir) + "Display the headers in the *VC dir* buffer. +It calls the `dir-extra-headers' backend method to display backend +specific headers." + (concat + ;; First layout the common headers. + (propertize "VC backend : " 'face 'font-lock-type-face) + (propertize (format "%s\n" backend) 'face 'font-lock-variable-name-face) + (propertize "Working dir: " 'face 'font-lock-type-face) + (propertize (format "%s\n" (abbreviate-file-name dir)) + 'face 'font-lock-variable-name-face) + ;; Then the backend specific ones. + (vc-call-backend backend 'dir-extra-headers dir) + "\n")) + +(defun vc-dir-refresh-files (files default-state) + "Refresh some files in the *VC-dir* buffer." + (let ((def-dir default-directory) + (backend vc-dir-backend)) + (vc-set-mode-line-busy-indicator) + ;; Call the `dir-status-file' backend function. + ;; `dir-status-file' is supposed to be asynchronous. + ;; It should compute the results, and then call the function + ;; passed as an argument in order to update the vc-dir buffer + ;; with the results. + (unless (buffer-live-p vc-dir-process-buffer) + (setq vc-dir-process-buffer + (generate-new-buffer (format " *VC-%s* tmp status" backend)))) + (lexical-let ((buffer (current-buffer))) + (with-current-buffer vc-dir-process-buffer + (cd def-dir) + (erase-buffer) + (vc-call-backend + backend 'dir-status-files def-dir files default-state + (lambda (entries &optional more-to-come) + ;; ENTRIES is a list of (FILE VC_STATE EXTRA) items. + ;; If MORE-TO-COME is true, then more updates will come from + ;; the asynchronous process. + (with-current-buffer buffer + (vc-dir-update entries buffer) + (unless more-to-come + (setq mode-line-process nil) + ;; Remove the ones that haven't been updated at all. + ;; Those not-updated are those whose state is nil because the + ;; file/dir doesn't exist and isn't versioned. + (ewoc-filter vc-ewoc + (lambda (info) + ;; The state for directory entries might + ;; have been changed to 'up-to-date, + ;; reset it, othewise it will be removed when doing 'x' + ;; next time. + ;; FIXME: There should be a more elegant way to do this. + (when (and (vc-dir-fileinfo->directory info) + (eq (vc-dir-fileinfo->state info) + 'up-to-date)) + (setf (vc-dir-fileinfo->state info) nil)) + + (not (vc-dir-fileinfo->needs-update info)))))))))))) + +(defun vc-dir-revert-buffer-function (&optional ignore-auto noconfirm) + (vc-dir-refresh)) + +(defun vc-dir-refresh () + "Refresh the contents of the *VC-dir* buffer. +Throw an error if another update process is in progress." + (interactive) + (if (vc-dir-busy) + (error "Another update process is in progress, cannot run two at a time") + (let ((def-dir default-directory) + (backend vc-dir-backend)) + (vc-set-mode-line-busy-indicator) + ;; Call the `dir-status' backend function. + ;; `dir-status' is supposed to be asynchronous. + ;; It should compute the results, and then call the function + ;; passed as an argument in order to update the vc-dir buffer + ;; with the results. + + ;; Create a buffer that can be used by `dir-status' and call + ;; `dir-status' with this buffer as the current buffer. Use + ;; `vc-dir-process-buffer' to remember this buffer, so that + ;; it can be used later to kill the update process in case it + ;; takes too long. + (unless (buffer-live-p vc-dir-process-buffer) + (setq vc-dir-process-buffer + (generate-new-buffer (format " *VC-%s* tmp status" backend)))) + ;; set the needs-update flag on all non-directory entries + (ewoc-map (lambda (info) + (unless (vc-dir-fileinfo->directory info) + (setf (vc-dir-fileinfo->needs-update info) t) nil)) + vc-ewoc) + (lexical-let ((buffer (current-buffer))) + (with-current-buffer vc-dir-process-buffer + (cd def-dir) + (erase-buffer) + (vc-call-backend + backend 'dir-status def-dir + (lambda (entries &optional more-to-come) + ;; ENTRIES is a list of (FILE VC_STATE EXTRA) items. + ;; If MORE-TO-COME is true, then more updates will come from + ;; the asynchronous process. + (with-current-buffer buffer + (vc-dir-update entries buffer) + (unless more-to-come + (let ((remaining + (ewoc-collect + vc-ewoc 'vc-dir-fileinfo->needs-update))) + (if remaining + (vc-dir-refresh-files + (mapcar 'vc-dir-fileinfo->name remaining) + 'up-to-date) + (setq mode-line-process nil))))))))) + (ewoc-set-hf vc-ewoc (vc-dir-headers backend def-dir) "")))) + +(defun vc-dir-show-fileentry (file) + "Insert an entry for a specific file into the current *VC-dir* listing. +This is typically used if the file is up-to-date (or has been added +outside of VC) and one wants to do some operation on it." + (interactive "fShow file: ") + (vc-dir-update (list (list (file-relative-name file) (vc-state file))) (current-buffer))) + +(defun vc-dir-hide-up-to-date () + "Hide up-to-date items from display." + (interactive) + (let ((crt (ewoc-nth vc-ewoc -1)) + (first (ewoc-nth vc-ewoc 0))) + ;; Go over from the last item to the first and remove the + ;; up-to-date files and directories with no child files. + (while (not (eq crt first)) + (let* ((data (ewoc-data crt)) + (dir (vc-dir-fileinfo->directory data)) + (next (ewoc-next vc-ewoc crt)) + (prev (ewoc-prev vc-ewoc crt)) + ;; ewoc-delete does not work without this... + (inhibit-read-only t)) + (when (or + ;; Remove directories with no child files. + (and dir + (or + ;; Nothing follows this directory. + (not next) + ;; Next item is a directory. + (vc-dir-fileinfo->directory (ewoc-data next)))) + ;; Remove files in the up-to-date state. + (eq (vc-dir-fileinfo->state data) 'up-to-date)) + (ewoc-delete vc-ewoc crt)) + (setq crt prev))))) + +(defun vc-dir-kill-line () + "Remove the current line from display." + (interactive) + (let ((crt (ewoc-locate vc-ewoc)) + (inhibit-read-only t)) + (ewoc-delete vc-ewoc crt))) + +(defun vc-dir-printer (fileentry) + (vc-call-backend vc-dir-backend 'dir-printer fileentry)) + +(defun vc-dir-deduce-fileset (&optional state-model-only-files) + (let ((marked (vc-dir-marked-files)) + files + only-files-list + state + model) + (if marked + (progn + (setq files marked) + (when state-model-only-files + (setq only-files-list (vc-dir-marked-only-files-and-states)))) + (let ((crt (vc-dir-current-file))) + (setq files (list crt)) + (when state-model-only-files + (setq only-files-list (vc-dir-child-files-and-states))))) + + (when state-model-only-files + (setq state (cdar only-files-list)) + ;; Check that all files are in a consistent state, since we use that + ;; state to decide which operation to perform. + (dolist (crt (cdr only-files-list)) + (unless (vc-compatible-state (cdr crt) state) + (error "When applying VC operations to multiple files, the files are required\nto be in similar VC states.\n%s in state %s clashes with %s in state %s" + (car crt) (cdr crt) (caar only-files-list) state))) + (setq only-files-list (mapcar 'car only-files-list)) + (when (and state (not (eq state 'unregistered))) + (setq model (vc-checkout-model vc-dir-backend only-files-list)))) + (list vc-dir-backend files only-files-list state model))) + +;;;###autoload +(defun vc-dir (dir &optional backend) + "Show the VC status for \"interesting\" files in and below DIR. +This allows you to mark files and perform VC operations on them. +The list omits files which are up to date, with no changes in your copy +or the repository, if there is nothing in particular to say about them. + +Preparing the list of file status takes time; when the buffer +first appears, it has only the first few lines of summary information. +The file lines appear later. + +Optional second argument BACKEND specifies the VC backend to use. +Interactively, a prefix argument means to ask for the backend. + +These are the commands available for use in the file status buffer: + +\\{vc-dir-mode-map}" + + (interactive + (list + ;; When you hit C-x v d in a visited VC file, + ;; the *vc-dir* buffer visits the directory under its truename; + ;; therefore it makes sense to always do that. + ;; Otherwise if you do C-x v d -> C-x C-f -> C-c v d + ;; you may get a new *vc-dir* buffer, different from the original + (file-truename (read-file-name "VC status for directory: " + default-directory default-directory t + nil #'file-directory-p)) + (if current-prefix-arg + (intern + (completing-read + "Use VC backend: " + (mapcar (lambda (b) (list (symbol-name b))) + vc-handled-backends) + nil t nil nil))))) + (unless backend + (setq backend (vc-responsible-backend dir))) + (let (pop-up-windows) ; based on cvs-examine; bug#6204 + (pop-to-buffer (vc-dir-prepare-status-buffer "*vc-dir*" dir backend))) + (if (derived-mode-p 'vc-dir-mode) + (vc-dir-refresh) + ;; FIXME: find a better way to pass the backend to `vc-dir-mode'. + (let ((use-vc-backend backend)) + (vc-dir-mode)))) + +(defun vc-default-dir-extra-headers (backend dir) + ;; Be loud by default to remind people to add code to display + ;; backend specific headers. + ;; XXX: change this to return nil before the release. + (concat + (propertize "Extra : " 'face 'font-lock-type-face) + (propertize "Please add backend specific headers here. It's easy!" + 'face 'font-lock-warning-face))) + +(defvar vc-dir-filename-mouse-map + (let ((map (make-sparse-keymap))) + (define-key map [mouse-2] 'vc-dir-find-file-other-window) + map) + "Local keymap for visiting a file.") + +(defun vc-default-dir-printer (backend fileentry) + "Pretty print FILEENTRY." + ;; If you change the layout here, change vc-dir-move-to-goal-column. + ;; VC backends can implement backend specific versions of this + ;; function. Changes here might need to be reflected in the + ;; vc-BACKEND-dir-printer functions. + (let* ((isdir (vc-dir-fileinfo->directory fileentry)) + (state (if isdir "" (vc-dir-fileinfo->state fileentry))) + (filename (vc-dir-fileinfo->name fileentry))) + (insert + (propertize + (format "%c" (if (vc-dir-fileinfo->marked fileentry) ?* ? )) + 'face 'font-lock-type-face) + " " + (propertize + (format "%-20s" state) + 'face (cond ((eq state 'up-to-date) 'font-lock-builtin-face) + ((memq state '(missing conflict)) 'font-lock-warning-face) + (t 'font-lock-variable-name-face)) + 'mouse-face 'highlight) + " " + (propertize + (format "%s" filename) + 'face + (if isdir 'font-lock-comment-delimiter-face 'font-lock-function-name-face) + 'help-echo + (if isdir + "Directory\nVC operations can be applied to it\nmouse-3: Pop-up menu" + "File\nmouse-3: Pop-up menu") + 'mouse-face 'highlight + 'keymap vc-dir-filename-mouse-map)))) + +(defun vc-default-extra-status-menu (backend) + nil) + +(defun vc-default-status-fileinfo-extra (backend file) + "Default absence of extra information returned for a file." + nil) + +(provide 'vc-dir) + +;; arch-tag: 0274a2e3-e8e9-4b1a-a73c-e8b9129d5d15 +;;; vc-dir.el ends here diff --cc lisp/vc/vc-git.el index 6129b21c324,00000000000..cccccbdfd02 mode 100644,000000..100644 --- a/lisp/vc/vc-git.el +++ b/lisp/vc/vc-git.el @@@ -1,1031 -1,0 +1,1039 @@@ +;;; vc-git.el --- VC backend for the git version control system + +;; Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + +;; Author: Alexandre Julliard +;; Keywords: vc tools + +;; 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 3 of the License, 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. If not, see . + +;;; Commentary: + +;; This file contains a VC backend for the git version control +;; system. +;; + +;;; Installation: + +;; To install: put this file on the load-path and add Git to the list +;; of supported backends in `vc-handled-backends'; the following line, +;; placed in your ~/.emacs, will accomplish this: +;; +;; (add-to-list 'vc-handled-backends 'Git) + +;;; Todo: +;; - check if more functions could use vc-git-command instead +;; of start-process. +;; - changelog generation + +;; Implement the rest of the vc interface. See the comment at the +;; beginning of vc.el. The current status is: +;; ("??" means: "figure out what to do about it") +;; +;; FUNCTION NAME STATUS +;; BACKEND PROPERTIES +;; * revision-granularity OK +;; STATE-QUERYING FUNCTIONS +;; * registered (file) OK +;; * state (file) OK +;; - state-heuristic (file) NOT NEEDED +;; * working-revision (file) OK +;; - latest-on-branch-p (file) NOT NEEDED +;; * checkout-model (files) OK +;; - workfile-unchanged-p (file) OK +;; - mode-line-string (file) OK +;; STATE-CHANGING FUNCTIONS +;; * create-repo () OK +;; * register (files &optional rev comment) OK +;; - init-revision (file) NOT NEEDED +;; - responsible-p (file) OK +;; - could-register (file) NOT NEEDED, DEFAULT IS GOOD +;; - receive-file (file rev) NOT NEEDED +;; - unregister (file) OK +;; * checkin (files rev comment) OK +;; * find-revision (file rev buffer) OK +;; * checkout (file &optional editable rev) OK +;; * revert (file &optional contents-done) OK +;; - rollback (files) COULD BE SUPPORTED +;; - merge (file rev1 rev2) It would be possible to merge +;; changes into a single file, but +;; when committing they wouldn't +;; be identified as a merge +;; by git, so it's probably +;; not a good idea. +;; - merge-news (file) see `merge' +;; - steal-lock (file &optional revision) NOT NEEDED +;; HISTORY FUNCTIONS +;; * print-log (files buffer &optional shortlog start-revision limit) OK +;; - log-view-mode () OK +;; - show-log-entry (revision) OK +;; - comment-history (file) ?? +;; - update-changelog (files) COULD BE SUPPORTED +;; * diff (file &optional rev1 rev2 buffer) OK +;; - revision-completion-table (files) OK +;; - annotate-command (file buf &optional rev) OK +;; - annotate-time () OK +;; - annotate-current-time () NOT NEEDED +;; - annotate-extract-revision-at-line () OK +;; TAG SYSTEM +;; - create-tag (dir name branchp) OK +;; - retrieve-tag (dir name update) OK +;; MISCELLANEOUS +;; - make-version-backups-p (file) NOT NEEDED +;; - repository-hostname (dirname) NOT NEEDED +;; - previous-revision (file rev) OK +;; - next-revision (file rev) OK +;; - check-headers () COULD BE SUPPORTED +;; - clear-headers () NOT NEEDED +;; - delete-file (file) OK +;; - rename-file (old new) OK +;; - find-file-hook () NOT NEEDED + +(eval-when-compile + (require 'cl) + (require 'vc) + (require 'vc-dir) + (require 'grep)) + +(defcustom vc-git-diff-switches t + "String or list of strings specifying switches for Git diff under VC. +If nil, use the value of `vc-diff-switches'. If t, use no switches." + :type '(choice (const :tag "Unspecified" nil) + (const :tag "None" t) + (string :tag "Argument String") + (repeat :tag "Argument List" :value ("") string)) + :version "23.1" + :group 'vc) + +(defvar vc-git-commits-coding-system 'utf-8 + "Default coding system for git commits.") + +;;; BACKEND PROPERTIES + +(defun vc-git-revision-granularity () 'repository) +(defun vc-git-checkout-model (files) 'implicit) + +;;; STATE-QUERYING FUNCTIONS + +;;;###autoload (defun vc-git-registered (file) +;;;###autoload "Return non-nil if FILE is registered with git." +;;;###autoload (if (vc-find-root file ".git") ; Short cut. +;;;###autoload (progn +;;;###autoload (load "vc-git") +;;;###autoload (vc-git-registered file)))) + +(defun vc-git-registered (file) + "Check whether FILE is registered with git." + (let ((dir (vc-git-root file))) + (when dir + (with-temp-buffer + (let* (process-file-side-effects + ;; Do not use the `file-name-directory' here: git-ls-files + ;; sometimes fails to return the correct status for relative + ;; path specs. + ;; See also: http://marc.info/?l=git&m=125787684318129&w=2 + (name (file-relative-name file dir)) + (str (ignore-errors + (cd dir) + (vc-git--out-ok "ls-files" "-c" "-z" "--" name) + ;; If result is empty, use ls-tree to check for deleted + ;; file. + (when (eq (point-min) (point-max)) + (vc-git--out-ok "ls-tree" "--name-only" "-z" "HEAD" + "--" name)) + (buffer-string)))) + (and str + (> (length str) (length name)) + (string= (substring str 0 (1+ (length name))) + (concat name "\0")))))))) + +(defun vc-git--state-code (code) + "Convert from a string to a added/deleted/modified state." + (case (string-to-char code) + (?M 'edited) + (?A 'added) + (?D 'removed) + (?U 'edited) ;; FIXME + (?T 'edited))) ;; FIXME + +(defun vc-git-state (file) + "Git-specific version of `vc-state'." + ;; FIXME: This can't set 'ignored or 'conflict yet + ;; The 'ignored state could be detected with `git ls-files -i -o + ;; --exclude-standard` It also can't set 'needs-update or + ;; 'needs-merge. The rough equivalent would be that upstream branch + ;; for current branch is in fast-forward state i.e. current branch + ;; is direct ancestor of corresponding upstream branch, and the file + ;; was modified upstream. But we can't check that without a network + ;; operation. + (if (not (vc-git-registered file)) + 'unregistered + (vc-git--call nil "add" "--refresh" "--" (file-relative-name file)) + (let ((diff (vc-git--run-command-string + file "diff-index" "-z" "HEAD" "--"))) + (if (and diff (string-match ":[0-7]\\{6\\} [0-7]\\{6\\} [0-9a-f]\\{40\\} [0-9a-f]\\{40\\} \\([ADMUT]\\)\0[^\0]+\0" + diff)) + (vc-git--state-code (match-string 1 diff)) + (if (vc-git--empty-db-p) 'added 'up-to-date))))) + +(defun vc-git-working-revision (file) + "Git-specific version of `vc-working-revision'." + (let* (process-file-side-effects + (str (with-output-to-string + (with-current-buffer standard-output + (vc-git--out-ok "symbolic-ref" "HEAD"))))) + (if (string-match "^\\(refs/heads/\\)?\\(.+\\)$" str) + (match-string 2 str) + str))) + +(defun vc-git-workfile-unchanged-p (file) + (eq 'up-to-date (vc-git-state file))) + +(defun vc-git-mode-line-string (file) + "Return string for placement into the modeline for FILE." + (let* ((branch (vc-git-working-revision file)) + (def-ml (vc-default-mode-line-string 'Git file)) + (help-echo (get-text-property 0 'help-echo def-ml))) + (if (zerop (length branch)) + (propertize + (concat def-ml "!") + 'help-echo (concat help-echo "\nNo current branch (detached HEAD)")) + (propertize def-ml + 'help-echo (concat help-echo "\nCurrent branch: " branch))))) + +(defstruct (vc-git-extra-fileinfo + (:copier nil) + (:constructor vc-git-create-extra-fileinfo + (old-perm new-perm &optional rename-state orig-name)) + (:conc-name vc-git-extra-fileinfo->)) + old-perm new-perm ;; Permission flags. + rename-state ;; Rename or copy state. + orig-name) ;; Original name for renames or copies. + +(defun vc-git-escape-file-name (name) + "Escape a file name if necessary." + (if (string-match "[\n\t\"\\]" name) + (concat "\"" + (mapconcat (lambda (c) + (case c + (?\n "\\n") + (?\t "\\t") + (?\\ "\\\\") + (?\" "\\\"") + (t (char-to-string c)))) + name "") + "\"") + name)) + +(defun vc-git-file-type-as-string (old-perm new-perm) + "Return a string describing the file type based on its permissions." + (let* ((old-type (lsh (or old-perm 0) -9)) + (new-type (lsh (or new-perm 0) -9)) + (str (case new-type + (?\100 ;; File. + (case old-type + (?\100 nil) + (?\120 " (type change symlink -> file)") + (?\160 " (type change subproject -> file)"))) + (?\120 ;; Symlink. + (case old-type + (?\100 " (type change file -> symlink)") + (?\160 " (type change subproject -> symlink)") + (t " (symlink)"))) + (?\160 ;; Subproject. + (case old-type + (?\100 " (type change file -> subproject)") + (?\120 " (type change symlink -> subproject)") + (t " (subproject)"))) + (?\110 nil) ;; Directory (internal, not a real git state). + (?\000 ;; Deleted or unknown. + (case old-type + (?\120 " (symlink)") + (?\160 " (subproject)"))) + (t (format " (unknown type %o)" new-type))))) + (cond (str (propertize str 'face 'font-lock-comment-face)) + ((eq new-type ?\110) "/") + (t "")))) + +(defun vc-git-rename-as-string (state extra) + "Return a string describing the copy or rename associated with INFO, +or an empty string if none." + (let ((rename-state (when extra + (vc-git-extra-fileinfo->rename-state extra)))) + (if rename-state + (propertize + (concat " (" + (if (eq rename-state 'copy) "copied from " + (if (eq state 'added) "renamed from " + "renamed to ")) + (vc-git-escape-file-name + (vc-git-extra-fileinfo->orig-name extra)) + ")") + 'face 'font-lock-comment-face) + ""))) + +(defun vc-git-permissions-as-string (old-perm new-perm) + "Format a permission change as string." + (propertize + (if (or (not old-perm) + (not new-perm) + (eq 0 (logand ?\111 (logxor old-perm new-perm)))) + " " + (if (eq 0 (logand ?\111 old-perm)) "+x" "-x")) + 'face 'font-lock-type-face)) + +(defun vc-git-dir-printer (info) + "Pretty-printer for the vc-dir-fileinfo structure." + (let* ((isdir (vc-dir-fileinfo->directory info)) + (state (if isdir "" (vc-dir-fileinfo->state info))) + (extra (vc-dir-fileinfo->extra info)) + (old-perm (when extra (vc-git-extra-fileinfo->old-perm extra))) + (new-perm (when extra (vc-git-extra-fileinfo->new-perm extra)))) + (insert + " " + (propertize (format "%c" (if (vc-dir-fileinfo->marked info) ?* ? )) + 'face 'font-lock-type-face) + " " + (propertize + (format "%-12s" state) + 'face (cond ((eq state 'up-to-date) 'font-lock-builtin-face) + ((eq state 'missing) 'font-lock-warning-face) + (t 'font-lock-variable-name-face)) + 'mouse-face 'highlight) + " " (vc-git-permissions-as-string old-perm new-perm) + " " + (propertize (vc-git-escape-file-name (vc-dir-fileinfo->name info)) + 'face (if isdir 'font-lock-comment-delimiter-face + 'font-lock-function-name-face) + 'help-echo + (if isdir + "Directory\nVC operations can be applied to it\nmouse-3: Pop-up menu" + "File\nmouse-3: Pop-up menu") + 'keymap vc-dir-filename-mouse-map + 'mouse-face 'highlight) + (vc-git-file-type-as-string old-perm new-perm) + (vc-git-rename-as-string state extra)))) + +(defun vc-git-after-dir-status-stage (stage files update-function) + "Process sentinel for the various dir-status stages." + (let (next-stage result) + (goto-char (point-min)) + (case stage + (update-index + (setq next-stage (if (vc-git--empty-db-p) 'ls-files-added + (if files 'ls-files-up-to-date 'diff-index)))) + (ls-files-added + (setq next-stage 'ls-files-unknown) + (while (re-search-forward "\\([0-7]\\{6\\}\\) [0-9a-f]\\{40\\} 0\t\\([^\0]+\\)\0" nil t) + (let ((new-perm (string-to-number (match-string 1) 8)) + (name (match-string 2))) + (push (list name 'added (vc-git-create-extra-fileinfo 0 new-perm)) + result)))) + (ls-files-up-to-date + (setq next-stage 'diff-index) + (while (re-search-forward "\\([0-7]\\{6\\}\\) [0-9a-f]\\{40\\} 0\t\\([^\0]+\\)\0" nil t) + (let ((perm (string-to-number (match-string 1) 8)) + (name (match-string 2))) + (push (list name 'up-to-date + (vc-git-create-extra-fileinfo perm perm)) + result)))) + (ls-files-unknown + (when files (setq next-stage 'ls-files-ignored)) + (while (re-search-forward "\\([^\0]*?\\)\0" nil t 1) + (push (list (match-string 1) 'unregistered + (vc-git-create-extra-fileinfo 0 0)) + result))) + (ls-files-ignored + (while (re-search-forward "\\([^\0]*?\\)\0" nil t 1) + (push (list (match-string 1) 'ignored + (vc-git-create-extra-fileinfo 0 0)) + result))) + (diff-index + (setq next-stage 'ls-files-unknown) + (while (re-search-forward + ":\\([0-7]\\{6\\}\\) \\([0-7]\\{6\\}\\) [0-9a-f]\\{40\\} [0-9a-f]\\{40\\} \\(\\([ADMUT]\\)\0\\([^\0]+\\)\\|\\([CR]\\)[0-9]*\0\\([^\0]+\\)\0\\([^\0]+\\)\\)\0" + nil t 1) + (let ((old-perm (string-to-number (match-string 1) 8)) + (new-perm (string-to-number (match-string 2) 8)) + (state (or (match-string 4) (match-string 6))) + (name (or (match-string 5) (match-string 7))) + (new-name (match-string 8))) + (if new-name ; Copy or rename. + (if (eq ?C (string-to-char state)) + (push (list new-name 'added + (vc-git-create-extra-fileinfo old-perm new-perm + 'copy name)) + result) + (push (list name 'removed + (vc-git-create-extra-fileinfo 0 0 + 'rename new-name)) + result) + (push (list new-name 'added + (vc-git-create-extra-fileinfo old-perm new-perm + 'rename name)) + result)) + (push (list name (vc-git--state-code state) + (vc-git-create-extra-fileinfo old-perm new-perm)) + result)))))) + (when result + (setq result (nreverse result)) + (when files + (dolist (entry result) (setq files (delete (car entry) files))) + (unless files (setq next-stage nil)))) + (when (or result (not next-stage)) + (funcall update-function result next-stage)) + (when next-stage + (vc-git-dir-status-goto-stage next-stage files update-function)))) + +(defun vc-git-dir-status-goto-stage (stage files update-function) + (erase-buffer) + (case stage + (update-index + (if files + (vc-git-command (current-buffer) 'async files "add" "--refresh" "--") + (vc-git-command (current-buffer) 'async nil + "update-index" "--refresh"))) + (ls-files-added + (vc-git-command (current-buffer) 'async files + "ls-files" "-z" "-c" "-s" "--")) + (ls-files-up-to-date + (vc-git-command (current-buffer) 'async files + "ls-files" "-z" "-c" "-s" "--")) + (ls-files-unknown + (vc-git-command (current-buffer) 'async files + "ls-files" "-z" "-o" "--directory" + "--no-empty-directory" "--exclude-standard" "--")) + (ls-files-ignored + (vc-git-command (current-buffer) 'async files + "ls-files" "-z" "-o" "-i" "--directory" + "--no-empty-directory" "--exclude-standard" "--")) + ;; --relative added in Git 1.5.5. + (diff-index + (vc-git-command (current-buffer) 'async files + "diff-index" "--relative" "-z" "-M" "HEAD" "--"))) + (vc-exec-after + `(vc-git-after-dir-status-stage ',stage ',files ',update-function))) + +(defun vc-git-dir-status (dir update-function) + "Return a list of (FILE STATE EXTRA) entries for DIR." + ;; Further things that would have to be fixed later: + ;; - how to handle unregistered directories + ;; - how to support vc-dir on a subdir of the project tree + (vc-git-dir-status-goto-stage 'update-index nil update-function)) + +(defun vc-git-dir-status-files (dir files default-state update-function) + "Return a list of (FILE STATE EXTRA) entries for FILES in DIR." + (vc-git-dir-status-goto-stage 'update-index files update-function)) + +(defvar vc-git-stash-map + (let ((map (make-sparse-keymap))) + ;; Turn off vc-dir marking + (define-key map [mouse-2] 'ignore) + + (define-key map [down-mouse-3] 'vc-git-stash-menu) + (define-key map "\C-k" 'vc-git-stash-delete-at-point) + (define-key map "=" 'vc-git-stash-show-at-point) + (define-key map "\C-m" 'vc-git-stash-show-at-point) + (define-key map "A" 'vc-git-stash-apply-at-point) + (define-key map "P" 'vc-git-stash-pop-at-point) + (define-key map "S" 'vc-git-stash-snapshot) + map)) + +(defvar vc-git-stash-menu-map + (let ((map (make-sparse-keymap "Git Stash"))) + (define-key map [de] + '(menu-item "Delete stash" vc-git-stash-delete-at-point + :help "Delete the current stash")) + (define-key map [ap] + '(menu-item "Apply stash" vc-git-stash-apply-at-point + :help "Apply the current stash and keep it in the stash list")) + (define-key map [po] + '(menu-item "Apply and remove stash (pop)" vc-git-stash-pop-at-point + :help "Apply the current stash and remove it")) + (define-key map [sh] + '(menu-item "Show stash" vc-git-stash-show-at-point + :help "Show the contents of the current stash")) + map)) + +(defun vc-git-dir-extra-headers (dir) + (let ((str (with-output-to-string + (with-current-buffer standard-output + (vc-git--out-ok "symbolic-ref" "HEAD")))) + (stash (vc-git-stash-list)) + (stash-help-echo "Use M-x vc-git-stash to create stashes.") + branch remote remote-url) + (if (string-match "^\\(refs/heads/\\)?\\(.+\\)$" str) + (progn + (setq branch (match-string 2 str)) + (setq remote + (with-output-to-string + (with-current-buffer standard-output + (vc-git--out-ok "config" + (concat "branch." branch ".remote"))))) + (when (string-match "\\([^\n]+\\)" remote) + (setq remote (match-string 1 remote))) + (when remote + (setq remote-url + (with-output-to-string + (with-current-buffer standard-output + (vc-git--out-ok "config" + (concat "remote." remote ".url")))))) + (when (string-match "\\([^\n]+\\)" remote-url) + (setq remote-url (match-string 1 remote-url)))) + (setq branch "not (detached HEAD)")) + ;; FIXME: maybe use a different face when nothing is stashed. + (concat + (propertize "Branch : " 'face 'font-lock-type-face) + (propertize branch + 'face 'font-lock-variable-name-face) + (when remote + (concat + "\n" + (propertize "Remote : " 'face 'font-lock-type-face) + (propertize remote-url + 'face 'font-lock-variable-name-face))) + "\n" + (if stash + (concat + (propertize "Stash :\n" 'face 'font-lock-type-face + 'help-echo stash-help-echo) + (mapconcat + (lambda (x) + (propertize x + 'face 'font-lock-variable-name-face + 'mouse-face 'highlight + 'help-echo "mouse-3: Show stash menu\nRET: Show stash\nA: Apply stash\nP: Apply and remove stash (pop)\nC-k: Delete stash" + 'keymap vc-git-stash-map)) + stash "\n")) + (concat + (propertize "Stash : " 'face 'font-lock-type-face + 'help-echo stash-help-echo) + (propertize "Nothing stashed" + 'help-echo stash-help-echo + 'face 'font-lock-variable-name-face)))))) + +;;; STATE-CHANGING FUNCTIONS + +(defun vc-git-create-repo () + "Create a new Git repository." + (vc-git-command nil 0 nil "init")) + +(defun vc-git-register (files &optional rev comment) + "Register FILES into the git version-control system." + (let (flist dlist) + (dolist (crt files) + (if (file-directory-p crt) + (push crt dlist) + (push crt flist))) + (when flist + (vc-git-command nil 0 flist "update-index" "--add" "--")) + (when dlist + (vc-git-command nil 0 dlist "add")))) + +(defalias 'vc-git-responsible-p 'vc-git-root) + +(defun vc-git-unregister (file) + (vc-git-command nil 0 file "rm" "-f" "--cached" "--")) + +(declare-function log-edit-extract-headers "log-edit" (headers string)) + +(defun vc-git-checkin (files rev comment) + (let ((coding-system-for-write vc-git-commits-coding-system)) + (apply 'vc-git-command nil 0 files + (nconc (list "commit" "-m") + (log-edit-extract-headers '(("Author" . "--author") + ("Date" . "--date")) + comment) + (list "--only" "--"))))) + +(defun vc-git-find-revision (file rev buffer) + (let* (process-file-side-effects + (coding-system-for-read 'binary) + (coding-system-for-write 'binary) - (fullname (substring - (vc-git--run-command-string - file "ls-files" "-z" "--full-name" "--") - 0 -1))) ++ (fullname ++ (let ((fn (vc-git--run-command-string ++ file "ls-files" "-z" "--full-name" "--"))) ++ ;; ls-files does not return anything when looking for a ++ ;; revision of a file that has been renamed or removed. ++ (if (string= fn "") ++ (file-relative-name file (vc-git-root default-directory)) ++ (substring fn 0 -1))))) + (vc-git-command + buffer 0 - (concat (if rev rev "HEAD") ":" fullname) "cat-file" "blob"))) ++ nil ++ "cat-file" "blob" (concat (if rev rev "HEAD") ":" fullname)))) + +(defun vc-git-checkout (file &optional editable rev) + (vc-git-command nil 0 file "checkout" (or rev "HEAD"))) + +(defun vc-git-revert (file &optional contents-done) + "Revert FILE to the version stored in the git repository." + (if contents-done + (vc-git-command nil 0 file "update-index" "--") + (vc-git-command nil 0 file "reset" "-q" "--") + (vc-git-command nil nil file "checkout" "-q" "--"))) + +;;; HISTORY FUNCTIONS + +(defun vc-git-print-log (files buffer &optional shortlog start-revision limit) + "Get change log associated with FILES. +Note that using SHORTLOG requires at least Git version 1.5.6, +for the --graph option." + (let ((coding-system-for-read vc-git-commits-coding-system)) + ;; `vc-do-command' creates the buffer, but we need it before running + ;; the command. + (vc-setup-buffer buffer) + ;; If the buffer exists from a previous invocation it might be + ;; read-only. + (let ((inhibit-read-only t)) + (with-current-buffer + buffer + (apply 'vc-git-command buffer + 'async files + (append + '("log" "--no-color") + (when shortlog + '("--graph" "--decorate" "--date=short" + "--pretty=tformat:%d%h %ad %s" "--abbrev-commit")) + (when limit (list "-n" (format "%s" limit))) + (when start-revision (list start-revision)) + '("--"))))))) + +(defun vc-git-log-outgoing (buffer remote-location) + (interactive) + (vc-git-command + buffer 0 nil + "log" + "--no-color" "--graph" "--decorate" "--date=short" + "--pretty=tformat:%d%h %ad %s" "--abbrev-commit" + (concat (if (string= remote-location "") + "@{upstream}" + remote-location) + "..HEAD"))) + +(defun vc-git-log-incoming (buffer remote-location) + (interactive) + (vc-git-command nil 0 nil "fetch") + (vc-git-command + buffer 0 nil + "log" + "--no-color" "--graph" "--decorate" "--date=short" + "--pretty=tformat:%d%h %ad %s" "--abbrev-commit" + (concat "HEAD.." (if (string= remote-location "") + "@{upstream}" + remote-location)))) + +(defvar log-view-message-re) +(defvar log-view-file-re) +(defvar log-view-font-lock-keywords) +(defvar log-view-per-file-logs) + +(define-derived-mode vc-git-log-view-mode log-view-mode "Git-Log-View" + (require 'add-log) ;; We need the faces add-log. + ;; Don't have file markers, so use impossible regexp. + (set (make-local-variable 'log-view-file-re) "\\`a\\`") + (set (make-local-variable 'log-view-per-file-logs) nil) + (set (make-local-variable 'log-view-message-re) + (if (not (eq vc-log-view-type 'long)) + "^\\(?:[*/\\| ]+ \\)?\\(?: ([^)]+)\\)?\\([0-9a-z]+\\) \\([-a-z0-9]+\\) \\(.*\\)" + "^commit *\\([0-9a-z]+\\)")) + (set (make-local-variable 'log-view-font-lock-keywords) + (if (not (eq vc-log-view-type 'long)) + '( + ;; Same as log-view-message-re, except that we don't + ;; want the shy group for the tag name. + ("^\\(?:[*/\\| ]+ \\)?\\( ([^)]+)\\)?\\([0-9a-z]+\\) \\([-a-z0-9]+\\) \\(.*\\)" + (1 'highlight nil lax) + (2 'change-log-acknowledgement) + (3 'change-log-date))) + (append + `((,log-view-message-re (1 'change-log-acknowledgement))) + ;; Handle the case: + ;; user: foo@bar + '(("^Author:[ \t]+\\([A-Za-z0-9_.+-]+@[A-Za-z0-9_.-]+\\)" + (1 'change-log-email)) + ;; Handle the case: + ;; user: FirstName LastName + ("^Author:[ \t]+\\([^<(]+?\\)[ \t]*[(<]\\([A-Za-z0-9_.+-]+@[A-Za-z0-9_.-]+\\)[>)]" + (1 'change-log-name) + (2 'change-log-email)) + ("^ +\\(?:\\(?:[Aa]cked\\|[Ss]igned-[Oo]ff\\)-[Bb]y:\\)[ \t]+\\([A-Za-z0-9_.+-]+@[A-Za-z0-9_.-]+\\)" + (1 'change-log-name)) + ("^ +\\(?:\\(?:[Aa]cked\\|[Ss]igned-[Oo]ff\\)-[Bb]y:\\)[ \t]+\\([^<(]+?\\)[ \t]*[(<]\\([A-Za-z0-9_.+-]+@[A-Za-z0-9_.-]+\\)[>)]" + (1 'change-log-name) + (2 'change-log-email)) + ("^Merge: \\([0-9a-z]+\\) \\([0-9a-z]+\\)" + (1 'change-log-acknowledgement) + (2 'change-log-acknowledgement)) + ("^Date: \\(.+\\)" (1 'change-log-date)) + ("^summary:[ \t]+\\(.+\\)" (1 'log-view-message))))))) + + +(defun vc-git-show-log-entry (revision) + "Move to the log entry for REVISION. +REVISION may have the form BRANCH, BRANCH~N, +or BRANCH^ (where \"^\" can be repeated)." + (goto-char (point-min)) + (prog1 + (when revision + (search-forward + (format "\ncommit %s" revision) nil t + (cond ((string-match "~\\([0-9]\\)\\'" revision) + (1+ (string-to-number (match-string 1 revision)))) + ((string-match "\\^+\\'" revision) + (1+ (length (match-string 0 revision)))) + (t nil)))) + (beginning-of-line))) + +(defun vc-git-diff (files &optional rev1 rev2 buffer) + "Get a difference report using Git between two revisions of FILES." + (let (process-file-side-effects) + (apply #'vc-git-command (or buffer "*vc-diff*") 1 files + (if (and rev1 rev2) "diff-tree" "diff-index") + "--exit-code" + (append (vc-switches 'git 'diff) + (list "-p" (or rev1 "HEAD") rev2 "--"))))) + +(defun vc-git-revision-table (files) + ;; What about `files'?!? --Stef + (let (process-file-side-effects + (table (list "HEAD"))) + (with-temp-buffer + (vc-git-command t nil nil "for-each-ref" "--format=%(refname)") + (goto-char (point-min)) + (while (re-search-forward "^refs/\\(heads\\|tags\\|remotes\\)/\\(.*\\)$" + nil t) + (push (match-string 2) table))) + table)) + +(defun vc-git-revision-completion-table (files) + (lexical-let ((files files) + table) + (setq table (lazy-completion-table + table (lambda () (vc-git-revision-table files)))) + table)) + +(defun vc-git-annotate-command (file buf &optional rev) + (let ((name (file-relative-name file))) - (vc-git-command buf 'async name "blame" "--date=iso" "-C" "-C" rev))) ++ (vc-git-command buf 'async nil "blame" "--date=iso" "-C" "-C" rev "--" name))) + +(declare-function vc-annotate-convert-time "vc-annotate" (time)) + +(defun vc-git-annotate-time () + (and (re-search-forward "[0-9a-f]+[^()]+(.* \\([0-9]+\\)-\\([0-9]+\\)-\\([0-9]+\\) \\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\) \\([-+0-9]+\\) +[0-9]+) " nil t) + (vc-annotate-convert-time + (apply #'encode-time (mapcar (lambda (match) + (string-to-number (match-string match))) + '(6 5 4 3 2 1 7)))))) + +(defun vc-git-annotate-extract-revision-at-line () + (save-excursion + (move-beginning-of-line 1) + (when (looking-at "\\([0-9a-f^][0-9a-f]+\\) \\(\\([^(]+\\) \\)?") + (let ((revision (match-string-no-properties 1))) + (if (match-beginning 2) - (cons revision (expand-file-name (match-string-no-properties 3) - (vc-git-root default-directory))) ++ (let ((fname (match-string-no-properties 3))) ++ ;; Remove trailing whitespace from the file name. ++ (when (string-match " +\\'" fname) ++ (setq fname (substring fname 0 (match-beginning 0)))) ++ (cons revision ++ (expand-file-name fname (vc-git-root default-directory)))) + revision))))) + +;;; TAG SYSTEM + +(defun vc-git-create-tag (dir name branchp) + (let ((default-directory dir)) + (and (vc-git-command nil 0 nil "update-index" "--refresh") + (if branchp + (vc-git-command nil 0 nil "checkout" "-b" name) + (vc-git-command nil 0 nil "tag" name))))) + +(defun vc-git-retrieve-tag (dir name update) + (let ((default-directory dir)) + (vc-git-command nil 0 nil "checkout" name) + ;; FIXME: update buffers if `update' is true + )) + + +;;; MISCELLANEOUS + +(defun vc-git-previous-revision (file rev) + "Git-specific version of `vc-previous-revision'." + (if file - (let* ((default-directory (file-name-directory (expand-file-name file))) - (file (file-name-nondirectory file)) ++ (let* ((fname (file-relative-name file)) + (prev-rev (with-temp-buffer + (and - (vc-git--out-ok "rev-list" "-2" rev "--" file) ++ (vc-git--out-ok "rev-list" "-2" rev "--" fname) + (goto-char (point-max)) + (bolp) + (zerop (forward-line -1)) + (not (bobp)) + (buffer-substring-no-properties + (point) + (1- (point-max))))))) + (or (vc-git-symbolic-commit prev-rev) prev-rev)) + (with-temp-buffer + (and + (vc-git--out-ok "rev-parse" (concat rev "^")) + (buffer-substring-no-properties (point-min) (+ (point-min) 40)))))) + +(defun vc-git-next-revision (file rev) + "Git-specific version of `vc-next-revision'." + (let* ((default-directory (file-name-directory + (expand-file-name file))) + (file (file-name-nondirectory file)) + (current-rev + (with-temp-buffer + (and + (vc-git--out-ok "rev-list" "-1" rev "--" file) + (goto-char (point-max)) + (bolp) + (zerop (forward-line -1)) + (bobp) + (buffer-substring-no-properties + (point) + (1- (point-max)))))) + (next-rev + (and current-rev + (with-temp-buffer + (and + (vc-git--out-ok "rev-list" "HEAD" "--" file) + (goto-char (point-min)) + (search-forward current-rev nil t) + (zerop (forward-line -1)) + (buffer-substring-no-properties + (point) + (progn (forward-line 1) (1- (point))))))))) + (or (vc-git-symbolic-commit next-rev) next-rev))) + +(defun vc-git-delete-file (file) + (vc-git-command nil 0 file "rm" "-f" "--")) + +(defun vc-git-rename-file (old new) + (vc-git-command nil 0 (list old new) "mv" "-f" "--")) + +(defvar vc-git-extra-menu-map + (let ((map (make-sparse-keymap))) + (define-key map [git-grep] + '(menu-item "Git grep..." vc-git-grep + :help "Run the `git grep' command")) + (define-key map [git-sn] + '(menu-item "Stash a snapshot" vc-git-stash-snapshot + :help "Stash the current state of the tree and keep the current state")) + (define-key map [git-st] + '(menu-item "Create Stash..." vc-git-stash + :help "Stash away changes")) + (define-key map [git-ss] + '(menu-item "Show Stash..." vc-git-stash-show + :help "Show stash contents")) + map)) + +(defun vc-git-extra-menu () vc-git-extra-menu-map) + +(defun vc-git-extra-status-menu () vc-git-extra-menu-map) + +(defun vc-git-root (file) + (vc-find-root file ".git")) + +;; Derived from `lgrep'. +(defun vc-git-grep (regexp &optional files dir) + "Run git grep, searching for REGEXP in FILES in directory DIR. +The search is limited to file names matching shell pattern FILES. +FILES may use abbreviations defined in `grep-files-aliases', e.g. +entering `ch' is equivalent to `*.[ch]'. + +With \\[universal-argument] prefix, you can edit the constructed shell command line +before it is executed. +With two \\[universal-argument] prefixes, directly edit and run `grep-command'. + +Collect output in a buffer. While git grep runs asynchronously, you +can use \\[next-error] (M-x next-error), or \\\\[compile-goto-error] \ +in the grep output buffer, +to go to the lines where grep found matches. + +This command shares argument histories with \\[rgrep] and \\[grep]." + (interactive + (progn + (grep-compute-defaults) + (cond + ((equal current-prefix-arg '(16)) + (list (read-from-minibuffer "Run: " "git grep" + nil nil 'grep-history) + nil)) + (t (let* ((regexp (grep-read-regexp)) + (files (grep-read-files regexp)) + (dir (read-directory-name "In directory: " + nil default-directory t))) + (list regexp files dir)))))) + (require 'grep) + (when (and (stringp regexp) (> (length regexp) 0)) + (let ((command regexp)) + (if (null files) + (if (string= command "git grep") + (setq command nil)) + (setq dir (file-name-as-directory (expand-file-name dir))) + (setq command + (grep-expand-template "git grep -n -e -- " regexp files)) + (when command + (if (equal current-prefix-arg '(4)) + (setq command + (read-from-minibuffer "Confirm: " + command nil nil 'grep-history)) + (add-to-history 'grep-history command)))) + (when command + (let ((default-directory dir) + (compilation-environment '("PAGER="))) + ;; Setting process-setup-function makes exit-message-function work + ;; even when async processes aren't supported. + (compilation-start command 'grep-mode)) + (if (eq next-error-last-buffer (current-buffer)) + (setq default-directory dir)))))) + +(defun vc-git-stash (name) + "Create a stash." + (interactive "sStash name: ") + (let ((root (vc-git-root default-directory))) + (when root + (vc-git--call nil "stash" "save" name) + (vc-resynch-buffer root t t)))) + +(defun vc-git-stash-show (name) + "Show the contents of stash NAME." + (interactive "sStash name: ") + (vc-setup-buffer "*vc-git-stash*") + (vc-git-command "*vc-git-stash*" 'async nil "stash" "show" "-p" name) + (set-buffer "*vc-git-stash*") + (diff-mode) + (setq buffer-read-only t) + (pop-to-buffer (current-buffer))) + +(defun vc-git-stash-apply (name) + "Apply stash NAME." + (interactive "sApply stash: ") + (vc-git-command "*vc-git-stash*" 0 nil "stash" "apply" "-q" name) + (vc-resynch-buffer (vc-git-root default-directory) t t)) + +(defun vc-git-stash-pop (name) + "Pop stash NAME." + (interactive "sPop stash: ") + (vc-git-command "*vc-git-stash*" 0 nil "stash" "pop" "-q" name) + (vc-resynch-buffer (vc-git-root default-directory) t t)) + +(defun vc-git-stash-snapshot () + "Create a stash with the current tree state." + (interactive) + (vc-git--call nil "stash" "save" + (let ((ct (current-time))) + (concat + (format-time-string "Snapshot on %Y-%m-%d" ct) + (format-time-string " at %H:%M" ct)))) + (vc-git-command "*vc-git-stash*" 0 nil "stash" "apply" "-q" "stash@{0}") + (vc-resynch-buffer (vc-git-root default-directory) t t)) + +(defun vc-git-stash-list () + (delete + "" + (split-string + (replace-regexp-in-string + "^stash@" " " (vc-git--run-command-string nil "stash" "list")) + "\n"))) + +(defun vc-git-stash-get-at-point (point) + (save-excursion + (goto-char point) + (beginning-of-line) + (if (looking-at "^ +\\({[0-9]+}\\):") + (match-string 1) + (error "Cannot find stash at point")))) + +(defun vc-git-stash-delete-at-point () + (interactive) + (let ((stash (vc-git-stash-get-at-point (point)))) + (when (y-or-n-p (format "Remove stash %s ? " stash)) + (vc-git--run-command-string nil "stash" "drop" (format "stash@%s" stash)) + (vc-dir-refresh)))) + +(defun vc-git-stash-show-at-point () + (interactive) + (vc-git-stash-show (format "stash@%s" (vc-git-stash-get-at-point (point))))) + +(defun vc-git-stash-apply-at-point () + (interactive) + (vc-git-stash-apply (format "stash@%s" (vc-git-stash-get-at-point (point))))) + +(defun vc-git-stash-pop-at-point () + (interactive) + (vc-git-stash-pop (format "stash@%s" (vc-git-stash-get-at-point (point))))) + +(defun vc-git-stash-menu (e) + (interactive "e") + (vc-dir-at-event e (popup-menu vc-git-stash-menu-map e))) + + +;;; Internal commands + +(defun vc-git-command (buffer okstatus file-or-list &rest flags) + "A wrapper around `vc-do-command' for use in vc-git.el. +The difference to vc-do-command is that this function always invokes `git'." + (apply 'vc-do-command (or buffer "*vc*") okstatus "git" file-or-list flags)) + +(defun vc-git--empty-db-p () + "Check if the git db is empty (no commit done yet)." + (let (process-file-side-effects) + (not (eq 0 (vc-git--call nil "rev-parse" "--verify" "HEAD"))))) + +(defun vc-git--call (buffer command &rest args) + ;; We don't need to care the arguments. If there is a file name, it + ;; is always a relative one. This works also for remote + ;; directories. + (apply 'process-file "git" nil buffer nil command args)) + +(defun vc-git--out-ok (command &rest args) + (zerop (apply 'vc-git--call '(t nil) command args))) + +(defun vc-git--run-command-string (file &rest args) + "Run a git command on FILE and return its output as string. +FILE can be nil." + (let* ((ok t) + (str (with-output-to-string + (with-current-buffer standard-output + (unless (apply 'vc-git--out-ok + (if file + (append args (list (file-relative-name + file))) + args)) + (setq ok nil)))))) + (and ok str))) + +(defun vc-git-symbolic-commit (commit) + "Translate COMMIT string into symbolic form. +Returns nil if not possible." + (and commit + (let ((name (with-temp-buffer + (and + (vc-git--out-ok "name-rev" "--name-only" commit) + (goto-char (point-min)) + (= (forward-line 2) 1) + (bolp) + (buffer-substring-no-properties (point-min) + (1- (point-max))))))) + (and name (not (string= name "undefined")) name)))) + +(provide 'vc-git) + +;; arch-tag: bd10664a-0e5b-48f5-a877-6c17b135be12 +;;; vc-git.el ends here diff --cc lisp/vc/vc.el index 23dd6f0f7ae,00000000000..434c2a10e14 mode 100644,000000..100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@@ -1,2703 -1,0 +1,2706 @@@ +;;; vc.el --- drive a version-control system from within Emacs + +;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, +;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +;; Free Software Foundation, Inc. + +;; Author: FSF (see below for full credits) +;; Maintainer: Andre Spiegel +;; Keywords: vc tools + +;; 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 3 of the License, 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. If not, see . + +;;; Credits: + +;; VC was initially designed and implemented by Eric S. Raymond +;; in 1992. Over the years, many other people have +;; contributed substantial amounts of work to VC. These include: +;; +;; Per Cederqvist +;; Paul Eggert +;; Sebastian Kremer +;; Martin Lorentzson +;; Dave Love +;; Stefan Monnier +;; Thien-Thi Nguyen +;; Dan Nicolaescu +;; J.D. Smith +;; Andre Spiegel +;; Richard Stallman +;; +;; In July 2007 ESR returned and redesigned the mode to cope better +;; with modern version-control systems that do commits by fileset +;; rather than per individual file. +;; +;; If you maintain a client of the mode or customize it in your .emacs, +;; note that some backend functions which formerly took single file arguments +;; now take a list of files. These include: register, checkin, print-log, +;; rollback, and diff. + +;;; Commentary: + +;; This mode is fully documented in the Emacs user's manual. +;; +;; Supported version-control systems presently include CVS, RCS, GNU +;; Arch, Subversion, Bzr, Git, Mercurial, Monotone and SCCS +;; (or its free replacement, CSSC). +;; +;; If your site uses the ChangeLog convention supported by Emacs, the +;; function `log-edit-comment-to-change-log' could prove a useful checkin hook, +;; although you might prefer to use C-c C-a (i.e. `log-edit-insert-changelog') +;; from the commit buffer instead or to set `log-edit-setup-invert'. +;; +;; When using SCCS, RCS, CVS: be careful not to do repo surgery, or +;; operations like registrations and deletions and renames, outside VC +;; while VC is running. The support for these systems was designed +;; when disks were much slower, and the code maintains a lot of +;; internal state in order to reduce expensive operations to a +;; minimum. Thus, if you mess with the repo while VC's back is turned, +;; VC may get seriously confused. +;; +;; When using Subversion or a later system, anything you do outside VC +;; *through the VCS tools* should safely interlock with VC +;; operations. Under these VC does little state caching, because local +;; operations are assumed to be fast. The dividing line is +;; +;; ADDING SUPPORT FOR OTHER BACKENDS +;; +;; VC can use arbitrary version control systems as a backend. To add +;; support for a new backend named SYS, write a library vc-sys.el that +;; contains functions of the form `vc-sys-...' (note that SYS is in lower +;; case for the function and library names). VC will use that library if +;; you put the symbol SYS somewhere into the list of +;; `vc-handled-backends'. Then, for example, if `vc-sys-registered' +;; returns non-nil for a file, all SYS-specific versions of VC commands +;; will be available for that file. +;; +;; VC keeps some per-file information in the form of properties (see +;; vc-file-set/getprop in vc-hooks.el). The backend-specific functions +;; do not generally need to be aware of these properties. For example, +;; `vc-sys-working-revision' should compute the working revision and +;; return it; it should not look it up in the property, and it needn't +;; store it there either. However, if a backend-specific function does +;; store a value in a property, that value takes precedence over any +;; value that the generic code might want to set (check for uses of +;; the macro `with-vc-properties' in vc.el). +;; +;; In the list of functions below, each identifier needs to be prepended +;; with `vc-sys-'. Some of the functions are mandatory (marked with a +;; `*'), others are optional (`-'). +;; +;; BACKEND PROPERTIES +;; +;; * revision-granularity +;; +;; Takes no arguments. Returns either 'file or 'repository. Backends +;; that return 'file have per-file revision numbering; backends +;; that return 'repository have per-repository revision numbering, +;; so a revision level implicitly identifies a changeset +;; +;; STATE-QUERYING FUNCTIONS +;; +;; * registered (file) +;; +;; Return non-nil if FILE is registered in this backend. Both this +;; function as well as `state' should be careful to fail gracefully +;; in the event that the backend executable is absent. It is +;; preferable that this function's body is autoloaded, that way only +;; calling vc-registered does not cause the backend to be loaded +;; (all the vc-FOO-registered functions are called to try to find +;; the controlling backend for FILE. +;; +;; * state (file) +;; +;; Return the current version control state of FILE. For a list of +;; possible values, see `vc-state'. This function should do a full and +;; reliable state computation; it is usually called immediately after +;; C-x v v. If you want to use a faster heuristic when visiting a +;; file, put that into `state-heuristic' below. Note that under most +;; VCSes this won't be called at all, dir-status is used instead. +;; +;; - state-heuristic (file) +;; +;; If provided, this function is used to estimate the version control +;; state of FILE at visiting time. It should be considerably faster +;; than the implementation of `state'. For a list of possible values, +;; see the doc string of `vc-state'. +;; +;; - dir-status (dir update-function) +;; +;; Produce RESULT: a list of lists of the form (FILE VC-STATE EXTRA) +;; for the files in DIR. +;; EXTRA can be used for backend specific information about FILE. +;; If a command needs to be run to compute this list, it should be +;; run asynchronously using (current-buffer) as the buffer for the +;; command. When RESULT is computed, it should be passed back by +;; doing: (funcall UPDATE-FUNCTION RESULT nil). +;; If the backend uses a process filter, hence it produces partial results, +;; they can be passed back by doing: +;; (funcall UPDATE-FUNCTION RESULT t) +;; and then do a (funcall UPDATE-FUNCTION RESULT nil) +;; when all the results have been computed. +;; To provide more backend specific functionality for `vc-dir' +;; the following functions might be needed: `dir-extra-headers', +;; `dir-printer', `extra-dir-menu' and `dir-status-files'. +;; +;; - dir-status-files (dir files default-state update-function) +;; +;; This function is identical to dir-status except that it should +;; only report status for the specified FILES. Also it needs to +;; report on all requested files, including up-to-date or ignored +;; files. If not provided, the default is to consider that the files +;; are in DEFAULT-STATE. +;; +;; - dir-extra-headers (dir) +;; +;; Return a string that will be added to the *vc-dir* buffer header. +;; +;; - dir-printer (fileinfo) +;; +;; Pretty print the `vc-dir-fileinfo' FILEINFO. +;; If a backend needs to show more information than the default FILE +;; and STATE in the vc-dir listing, it can store that extra +;; information in `vc-dir-fileinfo->extra'. This function can be +;; used to display that extra information in the *vc-dir* buffer. +;; +;; - status-fileinfo-extra (file) +;; +;; Compute `vc-dir-fileinfo->extra' for FILE. +;; +;; * working-revision (file) +;; +;; Return the working revision of FILE. This is the revision fetched +;; by the last checkout or upate, not necessarily the same thing as the +;; head or tip revision. Should return "0" for a file added but not yet +;; committed. +;; +;; - latest-on-branch-p (file) +;; +;; Return non-nil if the working revision of FILE is the latest revision +;; on its branch (many VCSes call this the 'tip' or 'head' revision). +;; The default implementation always returns t, which means that +;; working with non-current revisions is not supported by default. +;; +;; * checkout-model (files) +;; +;; Indicate whether FILES need to be "checked out" before they can be +;; edited. See `vc-checkout-model' for a list of possible values. +;; +;; - workfile-unchanged-p (file) +;; +;; Return non-nil if FILE is unchanged from the working revision. +;; This function should do a brief comparison of FILE's contents +;; with those of the repository copy of the working revision. If +;; the backend does not have such a brief-comparison feature, the +;; default implementation of this function can be used, which +;; delegates to a full vc-BACKEND-diff. (Note that vc-BACKEND-diff +;; must not run asynchronously in this case, see variable +;; `vc-disable-async-diff'.) +;; +;; - mode-line-string (file) +;; +;; If provided, this function should return the VC-specific mode +;; line string for FILE. The returned string should have a +;; `help-echo' property which is the text to be displayed as a +;; tooltip when the mouse hovers over the VC entry on the mode-line. +;; The default implementation deals well with all states that +;; `vc-state' can return. +;; +;; STATE-CHANGING FUNCTIONS +;; +;; * create-repo (backend) +;; +;; Create an empty repository in the current directory and initialize +;; it so VC mode can add files to it. For file-oriented systems, this +;; need do no more than create a subdirectory with the right name. +;; +;; * register (files &optional rev comment) +;; +;; Register FILES in this backend. Optionally, an initial revision REV +;; and an initial description of the file, COMMENT, may be specified, +;; but it is not guaranteed that the backend will do anything with this. +;; The implementation should pass the value of vc-register-switches +;; to the backend command. (Note: in older versions of VC, this +;; command took a single file argument and not a list.) +;; +;; - init-revision (file) +;; +;; The initial revision to use when registering FILE if one is not +;; specified by the user. If not provided, the variable +;; vc-default-init-revision is used instead. +;; +;; - responsible-p (file) +;; +;; Return non-nil if this backend considers itself "responsible" for +;; FILE, which can also be a directory. This function is used to find +;; out what backend to use for registration of new files and for things +;; like change log generation. The default implementation always +;; returns nil. +;; +;; - could-register (file) +;; +;; Return non-nil if FILE could be registered under this backend. The +;; default implementation always returns t. +;; +;; - receive-file (file rev) +;; +;; Let this backend "receive" a file that is already registered under +;; another backend. The default implementation simply calls `register' +;; for FILE, but it can be overridden to do something more specific, +;; e.g. keep revision numbers consistent or choose editing modes for +;; FILE that resemble those of the other backend. +;; +;; - unregister (file) +;; +;; Unregister FILE from this backend. This is only needed if this +;; backend may be used as a "more local" backend for temporary editing. +;; +;; * checkin (files rev comment) +;; +;; Commit changes in FILES to this backend. REV is a historical artifact +;; and should be ignored. COMMENT is used as a check-in comment. +;; The implementation should pass the value of vc-checkin-switches to +;; the backend command. +;; +;; * find-revision (file rev buffer) +;; +;; Fetch revision REV of file FILE and put it into BUFFER. +;; If REV is the empty string, fetch the head of the trunk. +;; The implementation should pass the value of vc-checkout-switches +;; to the backend command. +;; +;; * checkout (file &optional editable rev) +;; +;; Check out revision REV of FILE into the working area. If EDITABLE +;; is non-nil, FILE should be writable by the user and if locking is +;; used for FILE, a lock should also be set. If REV is non-nil, that +;; is the revision to check out (default is the working revision). +;; If REV is t, that means to check out the head of the current branch; +;; if it is the empty string, check out the head of the trunk. +;; The implementation should pass the value of vc-checkout-switches +;; to the backend command. +;; +;; * revert (file &optional contents-done) +;; +;; Revert FILE back to the working revision. If optional +;; arg CONTENTS-DONE is non-nil, then the contents of FILE have +;; already been reverted from a version backup, and this function +;; only needs to update the status of FILE within the backend. +;; If FILE is in the `added' state it should be returned to the +;; `unregistered' state. +;; +;; - rollback (files) +;; +;; Remove the tip revision of each of FILES from the repository. If +;; this function is not provided, trying to cancel a revision is +;; caught as an error. (Most backends don't provide it.) (Also +;; note that older versions of this backend command were called +;; 'cancel-version' and took a single file arg, not a list of +;; files.) +;; +;; - merge (file rev1 rev2) +;; +;; Merge the changes between REV1 and REV2 into the current working file. +;; +;; - merge-news (file) +;; +;; Merge recent changes from the current branch into FILE. +;; +;; - steal-lock (file &optional revision) +;; +;; Steal any lock on the working revision of FILE, or on REVISION if +;; that is provided. This function is only needed if locking is +;; used for files under this backend, and if files can indeed be +;; locked by other users. +;; +;; - modify-change-comment (files rev comment) +;; +;; Modify the change comments associated with the files at the +;; given revision. This is optional, many backends do not support it. +;; +;; - mark-resolved (files) +;; +;; Mark conflicts as resolved. Some VC systems need to run a +;; command to mark conflicts as resolved. +;; +;; HISTORY FUNCTIONS +;; +;; * print-log (files buffer &optional shortlog start-revision limit) +;; +;; Insert the revision log for FILES into BUFFER. +;; If SHORTLOG is true insert a short version of the log. +;; If LIMIT is true insert only insert LIMIT log entries. If the +;; backend does not support limiting the number of entries to show +;; it should return `limit-unsupported'. +;; If START-REVISION is given, then show the log starting from the +;; revision. At this point START-REVISION is only required to work +;; in conjunction with LIMIT = 1. +;; +;; * log-outgoing (backend remote-location) +;; +;; Insert in BUFFER the revision log for the changes that will be +;; sent when performing a push operation to REMOTE-LOCATION. +;; +;; * log-incoming (backend remote-location) +;; +;; Insert in BUFFER the revision log for the changes that will be +;; received when performing a pull operation from REMOTE-LOCATION. +;; +;; - log-view-mode () +;; +;; Mode to use for the output of print-log. This defaults to +;; `log-view-mode' and is expected to be changed (if at all) to a derived +;; mode of `log-view-mode'. +;; +;; - show-log-entry (revision) +;; +;; If provided, search the log entry for REVISION in the current buffer, +;; and make sure it is displayed in the buffer's window. The default +;; implementation of this function works for RCS-style logs. +;; +;; - comment-history (file) +;; +;; Return a string containing all log entries that were made for FILE. +;; This is used for transferring a file from one backend to another, +;; retaining comment information. +;; +;; - update-changelog (files) +;; +;; Using recent log entries, create ChangeLog entries for FILES, or for +;; all files at or below the default-directory if FILES is nil. The +;; default implementation runs rcs2log, which handles RCS- and +;; CVS-style logs. +;; +;; * diff (files &optional rev1 rev2 buffer) +;; +;; Insert the diff for FILE into BUFFER, or the *vc-diff* buffer if +;; BUFFER is nil. If REV1 and REV2 are non-nil, report differences +;; from REV1 to REV2. If REV1 is nil, use the working revision (as +;; found in the repository) as the older revision; if REV2 is nil, +;; use the current working-copy contents as the newer revision. This +;; function should pass the value of (vc-switches BACKEND 'diff) to +;; the backend command. It should return a status of either 0 (no +;; differences found), or 1 (either non-empty diff or the diff is +;; run asynchronously). +;; +;; - revision-completion-table (files) +;; +;; Return a completion table for existing revisions of FILES. +;; The default is to not use any completion table. +;; +;; - annotate-command (file buf &optional rev) +;; +;; If this function is provided, it should produce an annotated display +;; of FILE in BUF, relative to revision REV. Annotation means each line +;; of FILE displayed is prefixed with version information associated with +;; its addition (deleted lines leave no history) and that the text of the +;; file is fontified according to age. +;; +;; - annotate-time () +;; +;; Only required if `annotate-command' is defined for the backend. +;; Return the time of the next line of annotation at or after point, +;; as a floating point fractional number of days. The helper +;; function `vc-annotate-convert-time' may be useful for converting +;; multi-part times as returned by `current-time' and `encode-time' +;; to this format. Return nil if no more lines of annotation appear +;; in the buffer. You can safely assume that point is placed at the +;; beginning of each line, starting at `point-min'. The buffer that +;; point is placed in is the Annotate output, as defined by the +;; relevant backend. This function also affects how much of the line +;; is fontified; where it leaves point is where fontification begins. +;; +;; - annotate-current-time () +;; +;; Only required if `annotate-command' is defined for the backend, +;; AND you'd like the current time considered to be anything besides +;; (vc-annotate-convert-time (current-time)) -- i.e. the current +;; time with hours, minutes, and seconds included. Probably safe to +;; ignore. Return the current-time, in units of fractional days. +;; +;; - annotate-extract-revision-at-line () +;; +;; Only required if `annotate-command' is defined for the backend. +;; Invoked from a buffer in vc-annotate-mode, return the revision +;; corresponding to the current line, or nil if there is no revision +;; corresponding to the current line. +;; If the backend supports annotating through copies and renames, +;; and displays a file name and a revision, then return a cons +;; (REVISION . FILENAME). +;; +;; TAG SYSTEM +;; +;; - create-tag (dir name branchp) +;; +;; Attach the tag NAME to the state of the working copy. This +;; should make sure that files are up-to-date before proceeding with +;; the action. DIR can also be a file and if BRANCHP is specified, +;; NAME should be created as a branch and DIR should be checked out +;; under this new branch. The default implementation does not +;; support branches but does a sanity check, a tree traversal and +;; assigns the tag to each file. +;; +;; - retrieve-tag (dir name update) +;; +;; Retrieve the version tagged by NAME of all registered files at or below DIR. +;; If UPDATE is non-nil, then update buffers of any files in the +;; tag that are currently visited. The default implementation +;; does a sanity check whether there aren't any uncommitted changes at +;; or below DIR, and then performs a tree walk, using the `checkout' +;; function to retrieve the corresponding revisions. +;; +;; MISCELLANEOUS +;; +;; - make-version-backups-p (file) +;; +;; Return non-nil if unmodified repository revisions of FILE should be +;; backed up locally. If this is done, VC can perform `diff' and +;; `revert' operations itself, without calling the backend system. The +;; default implementation always returns nil. +;; +;; - root (file) +;; Return the root of the VC controlled hierarchy for file. +;; +;; - repository-hostname (dirname) +;; +;; Return the hostname that the backend will have to contact +;; in order to operate on a file in DIRNAME. If the return value +;; is nil, it means that the repository is local. +;; This function is used in `vc-stay-local-p' which backends can use +;; for their convenience. +;; +;; - previous-revision (file rev) +;; +;; Return the revision number that precedes REV for FILE, or nil if no such +;; revision exists. +;; +;; - next-revision (file rev) +;; +;; Return the revision number that follows REV for FILE, or nil if no such +;; revision exists. +;; +;; - log-edit-mode () +;; +;; Turn on the mode used for editing the check in log. This +;; defaults to `log-edit-mode'. If changed, it should use a mode +;; derived from`log-edit-mode'. +;; +;; - check-headers () +;; +;; Return non-nil if the current buffer contains any version headers. +;; +;; - clear-headers () +;; +;; In the current buffer, reset all version headers to their unexpanded +;; form. This function should be provided if the state-querying code +;; for this backend uses the version headers to determine the state of +;; a file. This function will then be called whenever VC changes the +;; version control state in such a way that the headers would give +;; wrong information. +;; +;; - delete-file (file) +;; +;; Delete FILE and mark it as deleted in the repository. If this +;; function is not provided, the command `vc-delete-file' will +;; signal an error. +;; +;; - rename-file (old new) +;; +;; Rename file OLD to NEW, both in the working area and in the +;; repository. If this function is not provided, the renaming +;; will be done by (vc-delete-file old) and (vc-register new). +;; +;; - find-file-hook () +;; +;; Operation called in current buffer when opening a file. This can +;; be used by the backend to setup some local variables it might need. +;; +;; - extra-menu () +;; +;; Return a menu keymap, the items in the keymap will appear at the +;; end of the Version Control menu. The goal is to allow backends +;; to specify extra menu items that appear in the VC menu. This way +;; you can provide menu entries for functionality that is specific +;; to your backend and which does not map to any of the VC generic +;; concepts. +;; +;; - extra-dir-menu () +;; +;; Return a menu keymap, the items in the keymap will appear at the +;; end of the VC Status menu. The goal is to allow backends to +;; specify extra menu items that appear in the VC Status menu. This +;; makes it possible to provide menu entries for functionality that +;; is specific to a backend and which does not map to any of the VC +;; generic concepts. +;; +;; - conflicted-files (dir) +;; +;; Return the list of files where conflict resolution is needed in +;; the project that contains DIR. +;; FIXME: what should it do with non-text conflicts? + +;;; Todo: + +;; - Get rid of the "master file" terminology. + +;; - Add key-binding for vc-delete-file. + +;;;; New Primitives: +;; +;; - deal with push/pull operations. +;; +;; - add a mechanism for editing the underlying VCS's list of files +;; to be ignored, when that's possible. +;; +;;;; Primitives that need changing: +;; +;; - vc-update/vc-merge should deal with VC systems that don't +;; update/merge on a file basis, but on a whole repository basis. +;; vc-update and vc-merge assume the arguments are always files, +;; they don't deal with directories. Make sure the *vc-dir* buffer +;; is updated after these operations. +;; At least bzr, git and hg should benefit from this. +;; +;;;; Improved branch and tag handling: +;; +;; - add a generic mechanism for remembering the current branch names, +;; display the branch name in the mode-line. Replace +;; vc-cvs-sticky-tag with that. +;; +;;;; Internal cleanups: +;; +;; - backends that care about vc-stay-local should try to take it into +;; account for vc-dir. Is this likely to be useful??? YES! +;; +;; - vc-expand-dirs should take a backend parameter and only look for +;; files managed by that backend. +;; +;; - Another important thing: merge all the status-like backend operations. +;; We should remove dir-status, state, and dir-status-files, and +;; replace them with just `status' which takes a fileset and a continuation +;; (like dir-status) and returns a buffer in which the process(es) are run +;; (or nil if it worked synchronously). Hopefully we can define the old +;; 4 operations in term of this one. +;; +;;;; Other +;; +;; - when a file is in `conflict' state, turn on smerge-mode. +;; +;; - figure out what to do with conflicts that are not caused by the +;; file contents, but by metadata or other causes. Example: File A +;; gets renamed to B in one branch and to C in another and you merge +;; the two branches. Or you locally add file FOO and then pull a +;; change that also adds a new file FOO, ... +;; +;; - make it easier to write logs. Maybe C-x 4 a should add to the log +;; buffer, if one is present, instead of adding to the ChangeLog. +;; +;; - When vc-next-action calls vc-checkin it could pre-fill the +;; *VC-log* buffer with some obvious items: the list of files that +;; were added, the list of files that were removed. If the diff is +;; available, maybe it could even call something like +;; `diff-add-change-log-entries-other-window' to create a detailed +;; skeleton for the log... +;; +;; - most vc-dir backends need more work. They might need to +;; provide custom headers, use the `extra' field and deal with all +;; possible VC states. +;; +;; - add a function that calls vc-dir to `find-directory-functions'. +;; +;; - vc-diff, vc-annotate, etc. need to deal better with unregistered +;; files. Now that unregistered and ignored files are shown in +;; vc-dir, it is possible that these commands are called +;; for unregistered/ignored files. +;; +;; - vc-next-action needs work in order to work with multiple +;; backends: `vc-state' returns the state for the default backend, +;; not for the backend in the current *vc-dir* buffer. +;; +;; - vc-dir-kill-dir-status-process should not be specific to dir-status, +;; it should work for other async commands done through vc-do-command +;; as well, +;; +;; - vc-dir toolbar needs more icons. +;; +;; - The backends should avoid using `vc-file-setprop' and `vc-file-getprop'. +;; +;;; Code: + +(require 'vc-hooks) +(require 'vc-dispatcher) + +(eval-when-compile + (require 'cl) + (require 'dired)) + +(unless (assoc 'vc-parent-buffer minor-mode-alist) + (setq minor-mode-alist + (cons '(vc-parent-buffer vc-parent-buffer-name) + minor-mode-alist))) + +;; General customization + +(defgroup vc nil + "Version-control system in Emacs." + :group 'tools) + +(defcustom vc-initial-comment nil + "If non-nil, prompt for initial comment when a file is registered." + :type 'boolean + :group 'vc) + +(defcustom vc-default-init-revision "1.1" + "A string used as the default revision number when a new file is registered. +This can be overridden by giving a prefix argument to \\[vc-register]. This +can also be overridden by a particular VC backend." + :type 'string + :group 'vc + :version "20.3") + +(defcustom vc-checkin-switches nil + "A string or list of strings specifying extra switches for checkin. +These are passed to the checkin program by \\[vc-checkin]." + :type '(choice (const :tag "None" nil) + (string :tag "Argument String") + (repeat :tag "Argument List" + :value ("") + string)) + :group 'vc) + +(defcustom vc-checkout-switches nil + "A string or list of strings specifying extra switches for checkout. +These are passed to the checkout program by \\[vc-checkout]." + :type '(choice (const :tag "None" nil) + (string :tag "Argument String") + (repeat :tag "Argument List" + :value ("") + string)) + :group 'vc) + +(defcustom vc-register-switches nil + "A string or list of strings; extra switches for registering a file. +These are passed to the checkin program by \\[vc-register]." + :type '(choice (const :tag "None" nil) + (string :tag "Argument String") + (repeat :tag "Argument List" + :value ("") + string)) + :group 'vc) + +(defcustom vc-diff-switches nil + "A string or list of strings specifying switches for diff under VC. +When running diff under a given BACKEND, VC uses the first +non-nil value of `vc-BACKEND-diff-switches', `vc-diff-switches', +and `diff-switches', in that order. Since nil means to check the +next variable in the sequence, either of the first two may use +the value t to mean no switches at all. `vc-diff-switches' +should contain switches that are specific to version control, but +not specific to any particular backend." + :type '(choice (const :tag "Unspecified" nil) + (const :tag "None" t) + (string :tag "Argument String") + (repeat :tag "Argument List" :value ("") string)) + :group 'vc + :version "21.1") + +(defcustom vc-diff-knows-L nil + "Indicates whether diff understands the -L option. +The value is either `yes', `no', or nil. If it is nil, VC tries +to use -L and sets this variable to remember whether it worked." + :type '(choice (const :tag "Work out" nil) (const yes) (const no)) + :group 'vc) + +(defcustom vc-log-show-limit 2000 + "Limit the number of items shown by the VC log commands. +Zero means unlimited. +Not all VC backends are able to support this feature." + :type 'integer + :group 'vc) + +(defcustom vc-allow-async-revert nil + "Specifies whether the diff during \\[vc-revert] may be asynchronous. +Enabling this option means that you can confirm a revert operation even +if the local changes in the file have not been found and displayed yet." + :type '(choice (const :tag "No" nil) + (const :tag "Yes" t)) + :group 'vc + :version "22.1") + +;;;###autoload +(defcustom vc-checkout-hook nil + "Normal hook (list of functions) run after checking out a file. +See `run-hooks'." + :type 'hook + :group 'vc + :version "21.1") + +;;;###autoload +(defcustom vc-checkin-hook nil + "Normal hook (list of functions) run after commit or file checkin. +See also `log-edit-done-hook'." + :type 'hook + :options '(log-edit-comment-to-change-log) + :group 'vc) + +;;;###autoload +(defcustom vc-before-checkin-hook nil + "Normal hook (list of functions) run before a commit or a file checkin. +See `run-hooks'." + :type 'hook + :group 'vc) + +;; Header-insertion hair + +(defcustom vc-static-header-alist + '(("\\.c\\'" . + "\n#ifndef lint\nstatic char vcid[] = \"\%s\";\n#endif /* lint */\n")) + "Associate static header string templates with file types. +A \%s in the template is replaced with the first string associated with +the file's version control type in `vc-header-alist'." + :type '(repeat (cons :format "%v" + (regexp :tag "File Type") + (string :tag "Header String"))) + :group 'vc) + +(defcustom vc-comment-alist + '((nroff-mode ".\\\"" "")) + "Special comment delimiters for generating VC headers. +Add an entry in this list if you need to override the normal `comment-start' +and `comment-end' variables. This will only be necessary if the mode language +is sensitive to blank lines." + :type '(repeat (list :format "%v" + (symbol :tag "Mode") + (string :tag "Comment Start") + (string :tag "Comment End"))) + :group 'vc) + +(defcustom vc-checkout-carefully (= (user-uid) 0) + "Non-nil means be extra-careful in checkout. +Verify that the file really is not locked +and that its contents match what the repository version says." + :type 'boolean + :group 'vc) +(make-obsolete-variable 'vc-checkout-carefully + "the corresponding checks are always done now." + "21.1") + + +;; Variables users don't need to see + +(defvar vc-disable-async-diff nil + "VC sets this to t locally to disable some async diff operations. +Backends that offer asynchronous diffs should respect this variable +in their implementation of vc-BACKEND-diff.") + +;; File property caching + +(defun vc-clear-context () + "Clear all cached file properties." + (interactive) + (fillarray vc-file-prop-obarray 0)) + +(defmacro with-vc-properties (files form settings) + "Execute FORM, then maybe set per-file properties for FILES. +If any of FILES is actually a directory, then do the same for all +buffers for files in that directory. +SETTINGS is an association list of property/value pairs. After +executing FORM, set those properties from SETTINGS that have not yet +been updated to their corresponding values." + (declare (debug t)) + `(let ((vc-touched-properties (list t)) + (flist nil)) + (dolist (file ,files) + (if (file-directory-p file) + (dolist (buffer (buffer-list)) + (let ((fname (buffer-file-name buffer))) + (when (and fname (vc-string-prefix-p file fname)) + (push fname flist)))) + (push file flist))) + ,form + (dolist (file flist) + (dolist (setting ,settings) + (let ((property (car setting))) + (unless (memq property vc-touched-properties) + (put (intern file vc-file-prop-obarray) + property (cdr setting)))))))) + +;;; Code for deducing what fileset and backend to assume + +(defun vc-backend-for-registration (file) + "Return a backend that can be used for registering FILE. + +If no backend declares itself responsible for FILE, then FILE +must not be in a version controlled directory, so try to create a +repository, prompting for the directory and the VC backend to +use." + (catch 'found + ;; First try: find a responsible backend, it must be a backend + ;; under which FILE is not yet registered. + (dolist (backend vc-handled-backends) + (and (not (vc-call-backend backend 'registered file)) + (vc-call-backend backend 'responsible-p file) + (throw 'found backend))) + ;; no responsible backend + (let* ((possible-backends + (let (pos) + (dolist (crt vc-handled-backends) + (when (vc-find-backend-function crt 'create-repo) + (push crt pos))) + pos)) + (bk + (intern + ;; Read the VC backend from the user, only + ;; complete with the backends that have the + ;; 'create-repo method. + (completing-read + (format "%s is not in a version controlled directory.\nUse VC backend: " file) + (mapcar 'symbol-name possible-backends) nil t))) + (repo-dir + (let ((def-dir (file-name-directory file))) + ;; read the directory where to create the + ;; repository, make sure it's a parent of + ;; file. + (read-file-name + (format "create %s repository in: " bk) + default-directory def-dir t nil + (lambda (arg) + (message "arg %s" arg) + (and (file-directory-p arg) + (vc-string-prefix-p (expand-file-name arg) def-dir))))))) + (let ((default-directory repo-dir)) + (vc-call-backend bk 'create-repo)) + (throw 'found bk)))) + +(defun vc-responsible-backend (file) + "Return the name of a backend system that is responsible for FILE. + +If FILE is already registered, return the +backend of FILE. If FILE is not registered, then the +first backend in `vc-handled-backends' that declares itself +responsible for FILE is returned." + (or (and (not (file-directory-p file)) (vc-backend file)) + (catch 'found + ;; First try: find a responsible backend. If this is for registration, + ;; it must be a backend under which FILE is not yet registered. + (dolist (backend vc-handled-backends) + (and (vc-call-backend backend 'responsible-p file) + (throw 'found backend)))) + (error "No VC backend is responsible for %s" file))) + +(defun vc-expand-dirs (file-or-dir-list) + "Expands directories in a file list specification. +Within directories, only files already under version control are noticed." + (let ((flattened '())) + (dolist (node file-or-dir-list) + (when (file-directory-p node) + (vc-file-tree-walk + node (lambda (f) (when (vc-backend f) (push f flattened))))) + (unless (file-directory-p node) (push node flattened))) + (nreverse flattened))) + +(defvar vc-dir-backend) +(defvar log-view-vc-backend) +(defvar diff-vc-backend) + +(defun vc-deduce-backend () + (cond ((derived-mode-p 'vc-dir-mode) vc-dir-backend) + ((derived-mode-p 'log-view-mode) log-view-vc-backend) + ((derived-mode-p 'diff-mode) diff-vc-backend) + ((derived-mode-p 'dired-mode) + (vc-responsible-backend default-directory)) + (vc-mode (vc-backend buffer-file-name)))) + +(declare-function vc-dir-current-file "vc-dir" ()) +(declare-function vc-dir-deduce-fileset "vc-dir" (&optional state-model-only-files)) + +(defun vc-deduce-fileset (&optional observer allow-unregistered + state-model-only-files) + "Deduce a set of files and a backend to which to apply an operation. + +Return (BACKEND FILESET FILESET-ONLY-FILES STATE CHECKOUT-MODEL). +If we're in VC-dir mode, the fileset is the list of marked files. +Otherwise, if we're looking at a buffer visiting a version-controlled file, +the fileset is a singleton containing this file. +If none of these conditions is met, but ALLOW_UNREGISTERED is on and the +visited file is not registered, return a singleton fileset containing it. +Otherwise, throw an error. + +STATE-MODEL-ONLY-FILES if non-nil, means that the caller needs +the FILESET-ONLY-FILES STATE and MODEL info. Otherwise, that +part may be skipped. +BEWARE: this function may change the +current buffer." + ;; FIXME: OBSERVER is unused. The name is not intuitive and is not + ;; documented. It's set to t when called from diff and print-log. + (let (backend) + (cond + ((derived-mode-p 'vc-dir-mode) + (vc-dir-deduce-fileset state-model-only-files)) + ((derived-mode-p 'dired-mode) + (if observer + (vc-dired-deduce-fileset) + (error "State changing VC operations not supported in `dired-mode'"))) + ((setq backend (vc-backend buffer-file-name)) + (if state-model-only-files + (list backend (list buffer-file-name) + (list buffer-file-name) + (vc-state buffer-file-name) + (vc-checkout-model backend buffer-file-name)) + (list backend (list buffer-file-name)))) + ((and (buffer-live-p vc-parent-buffer) + ;; FIXME: Why this test? --Stef + (or (buffer-file-name vc-parent-buffer) + (with-current-buffer vc-parent-buffer + (derived-mode-p 'vc-dir-mode)))) + (progn ;FIXME: Why not `with-current-buffer'? --Stef. + (set-buffer vc-parent-buffer) + (vc-deduce-fileset observer allow-unregistered state-model-only-files))) + ((not buffer-file-name) + (error "Buffer %s is not associated with a file" (buffer-name))) + ((and allow-unregistered (not (vc-registered buffer-file-name))) + (if state-model-only-files + (list (vc-backend-for-registration (buffer-file-name)) + (list buffer-file-name) + (list buffer-file-name) + (when state-model-only-files 'unregistered) + nil) + (list (vc-backend-for-registration (buffer-file-name)) + (list buffer-file-name)))) + (t (error "No fileset is available here"))))) + +(defun vc-dired-deduce-fileset () + (let ((backend (vc-responsible-backend default-directory))) + (unless backend (error "Directory not under VC")) + (list backend + (dired-map-over-marks (dired-get-filename nil t) nil)))) + +(defun vc-ensure-vc-buffer () + "Make sure that the current buffer visits a version-controlled file." + (cond + ((derived-mode-p 'vc-dir-mode) + (set-buffer (find-file-noselect (vc-dir-current-file)))) + (t + (while (and vc-parent-buffer + (buffer-live-p vc-parent-buffer) + ;; Avoid infinite looping when vc-parent-buffer and + ;; current buffer are the same buffer. + (not (eq vc-parent-buffer (current-buffer)))) + (set-buffer vc-parent-buffer)) + (if (not buffer-file-name) + (error "Buffer %s is not associated with a file" (buffer-name)) + (unless (vc-backend buffer-file-name) + (error "File %s is not under version control" buffer-file-name)))))) + +;;; Support for the C-x v v command. +;; This is where all the single-file-oriented code from before the fileset +;; rewrite lives. + +(defsubst vc-editable-p (file) + "Return non-nil if FILE can be edited." + (let ((backend (vc-backend file))) + (and backend + (or (eq (vc-checkout-model backend (list file)) 'implicit) + (memq (vc-state file) '(edited needs-merge conflict)))))) + +(defun vc-compatible-state (p q) + "Controls which states can be in the same commit." + (or + (eq p q) + (and (member p '(edited added removed)) (member q '(edited added removed))))) + +;; Here's the major entry point. + +;;;###autoload +(defun vc-next-action (verbose) + "Do the next logical version control operation on the current fileset. +This requires that all files in the fileset be in the same state. + +For locking systems: + If every file is not already registered, this registers each for version +control. + If every file is registered and not locked by anyone, this checks out +a writable and locked file of each ready for editing. + If every file is checked out and locked by the calling user, this +first checks to see if each file has changed since checkout. If not, +it performs a revert on that file. + If every file has been changed, this pops up a buffer for entry +of a log message; when the message has been entered, it checks in the +resulting changes along with the log message as change commentary. If +the variable `vc-keep-workfiles' is non-nil (which is its default), a +read-only copy of each changed file is left in place afterwards. + If the affected file is registered and locked by someone else, you are +given the option to steal the lock(s). + +For merging systems: + If every file is not already registered, this registers each one for version +control. This does an add, but not a commit. + If every file is added but not committed, each one is committed. + If every working file is changed, but the corresponding repository file is +unchanged, this pops up a buffer for entry of a log message; when the +message has been entered, it checks in the resulting changes along +with the logmessage as change commentary. A writable file is retained. + If the repository file is changed, you are asked if you want to +merge in the changes into your working copy." + (interactive "P") + (let* ((vc-fileset (vc-deduce-fileset nil t 'state-model-only-files)) + (backend (car vc-fileset)) + (files (nth 1 vc-fileset)) + (fileset-only-files (nth 2 vc-fileset)) + ;; FIXME: We used to call `vc-recompute-state' here. + (state (nth 3 vc-fileset)) + ;; The backend should check that the checkout-model is consistent + ;; among all the `files'. + (model (nth 4 vc-fileset))) + + ;; Do the right thing + (cond + ((eq state 'missing) + (error "Fileset files are missing, so cannot be operated on")) + ((eq state 'ignored) + (error "Fileset files are ignored by the version-control system")) + ((or (null state) (eq state 'unregistered)) + (vc-register nil vc-fileset)) + ;; Files are up-to-date, or need a merge and user specified a revision + ((or (eq state 'up-to-date) (and verbose (eq state 'needs-update))) + (cond + (verbose + ;; go to a different revision + (let* ((revision + (read-string "Branch, revision, or backend to move to: ")) + (revision-downcase (downcase revision))) + (if (member + revision-downcase + (mapcar (lambda (arg) (downcase (symbol-name arg))) + vc-handled-backends)) + (let ((vsym (intern-soft revision-downcase))) + (dolist (file files) (vc-transfer-file file vsym))) + (dolist (file files) + (vc-checkout file (eq model 'implicit) revision))))) + ((not (eq model 'implicit)) + ;; check the files out + (dolist (file files) (vc-checkout file t))) + (t + ;; do nothing + (message "Fileset is up-to-date")))) + ;; Files have local changes + ((vc-compatible-state state 'edited) + (let ((ready-for-commit files)) + ;; If files are edited but read-only, give user a chance to correct + (dolist (file files) + (unless (file-writable-p file) + ;; Make the file+buffer read-write. + (unless (y-or-n-p (format "%s is edited but read-only; make it writable and continue?" file)) + (error "Aborted")) + (set-file-modes file (logior (file-modes file) 128)) + (let ((visited (get-file-buffer file))) + (when visited + (with-current-buffer visited + (toggle-read-only -1)))))) + ;; Allow user to revert files with no changes + (save-excursion + (dolist (file files) + (let ((visited (get-file-buffer file))) + ;; For files with locking, if the file does not contain + ;; any changes, just let go of the lock, i.e. revert. + (when (and (not (eq model 'implicit)) + (vc-workfile-unchanged-p file) + ;; If buffer is modified, that means the user just + ;; said no to saving it; in that case, don't revert, + ;; because the user might intend to save after + ;; finishing the log entry and committing. + (not (and visited (buffer-modified-p)))) + (vc-revert-file file) + (setq ready-for-commit (delete file ready-for-commit)))))) + ;; Remaining files need to be committed + (if (not ready-for-commit) + (message "No files remain to be committed") + (if (not verbose) + (vc-checkin ready-for-commit backend) + (let* ((revision (read-string "New revision or backend: ")) + (revision-downcase (downcase revision))) + (if (member + revision-downcase + (mapcar (lambda (arg) (downcase (symbol-name arg))) + vc-handled-backends)) + (let ((vsym (intern revision-downcase))) + (dolist (file files) (vc-transfer-file file vsym))) + (vc-checkin ready-for-commit backend revision))))))) + ;; locked by somebody else (locking VCSes only) + ((stringp state) + ;; In the old days, we computed the revision once and used it on + ;; the single file. Then, for the 2007-2008 fileset rewrite, we + ;; computed the revision once (incorrectly, using a free var) and + ;; used it on all files. To fix the free var bug, we can either + ;; use `(car files)' or do what we do here: distribute the + ;; revision computation among `files'. Although this may be + ;; tedious for those backends where a "revision" is a trans-file + ;; concept, it is nonetheless correct for both those and (more + ;; importantly) for those where "revision" is a per-file concept. + ;; If the intersection of the former group and "locking VCSes" is + ;; non-empty [I vaguely doubt it --ttn], we can reinstate the + ;; pre-computation approach of yore. + (dolist (file files) + (vc-steal-lock + file (if verbose + (read-string (format "%s revision to steal: " file)) + (vc-working-revision file)) + state))) + ;; conflict + ((eq state 'conflict) + ;; FIXME: Is it really the UI we want to provide? + ;; In my experience, the conflicted files should be marked as resolved + ;; one-by-one when saving the file after resolving the conflicts. + ;; I.e. stating explicitly that the conflicts are resolved is done + ;; very rarely. + (vc-mark-resolved backend files)) + ;; needs-update + ((eq state 'needs-update) + (dolist (file files) + (if (yes-or-no-p (format + "%s is not up-to-date. Get latest revision? " + (file-name-nondirectory file))) + (vc-checkout file (eq model 'implicit) t) + (when (and (not (eq model 'implicit)) + (yes-or-no-p "Lock this revision? ")) + (vc-checkout file t))))) + ;; needs-merge + ((eq state 'needs-merge) + (dolist (file files) + (when (yes-or-no-p (format + "%s is not up-to-date. Merge in changes now? " + (file-name-nondirectory file))) + (vc-maybe-resolve-conflicts + file (vc-call-backend backend 'merge-news file))))) + + ;; unlocked-changes + ((eq state 'unlocked-changes) + (dolist (file files) + (when (not (equal buffer-file-name file)) + (find-file-other-window file)) + (if (save-window-excursion + (vc-diff-internal nil + (cons (car vc-fileset) (cons (cadr vc-fileset) (list file))) + (vc-working-revision file) nil) + (goto-char (point-min)) + (let ((inhibit-read-only t)) + (insert + (format "Changes to %s since last lock:\n\n" file))) + (not (beep)) + (yes-or-no-p (concat "File has unlocked changes. " + "Claim lock retaining changes? "))) + (progn (vc-call-backend backend 'steal-lock file) + (clear-visited-file-modtime) + ;; Must clear any headers here because they wouldn't + ;; show that the file is locked now. + (vc-clear-headers file) + (write-file buffer-file-name) + (vc-mode-line file backend)) + (if (not (yes-or-no-p + "Revert to checked-in revision, instead? ")) + (error "Checkout aborted") + (vc-revert-buffer-internal t t) + (vc-checkout file t))))) + ;; Unknown fileset state + (t + (error "Fileset is in an unknown state %s" state))))) + +(defun vc-create-repo (backend) + "Create an empty repository in the current directory." + (interactive + (list + (intern + (upcase + (completing-read + "Create repository for: " + (mapcar (lambda (b) (list (downcase (symbol-name b)))) vc-handled-backends) + nil t))))) + (vc-call-backend backend 'create-repo)) + +(declare-function vc-dir-move-to-goal-column "vc-dir" ()) + +;;;###autoload +(defun vc-register (&optional set-revision vc-fileset comment) + "Register into a version control system. +If VC-FILESET is given, register the files in that fileset. +Otherwise register the current file. +With prefix argument SET-REVISION, allow user to specify initial revision +level. If COMMENT is present, use that as an initial comment. + +The version control system to use is found by cycling through the list +`vc-handled-backends'. The first backend in that list which declares +itself responsible for the file (usually because other files in that +directory are already registered under that backend) will be used to +register the file. If no backend declares itself responsible, the +first backend that could register the file is used." + (interactive "P") + (let* ((fileset-arg (or vc-fileset (vc-deduce-fileset nil t))) + (backend (car fileset-arg)) + (files (nth 1 fileset-arg))) + ;; We used to operate on `only-files', but VC wants to provide the + ;; possibility to register directories rather than files only, since + ;; many VCS allow that as well. + (dolist (fname files) + (let ((bname (get-file-buffer fname))) + (unless fname (setq fname buffer-file-name)) + (when (vc-backend fname) + (if (vc-registered fname) + (error "This file is already registered") + (unless (y-or-n-p "Previous master file has vanished. Make a new one? ") + (error "Aborted")))) + ;; Watch out for new buffers of size 0: the corresponding file + ;; does not exist yet, even though buffer-modified-p is nil. + (when bname + (with-current-buffer bname + (when (and (not (buffer-modified-p)) + (zerop (buffer-size)) + (not (file-exists-p buffer-file-name))) + (set-buffer-modified-p t)) + (vc-buffer-sync))))) + (message "Registering %s... " files) + (mapc 'vc-file-clearprops files) + (vc-call-backend backend 'register files + (if set-revision + (read-string (format "Initial revision level for %s: " files)) + (vc-call-backend backend 'init-revision)) + comment) + (mapc + (lambda (file) + (vc-file-setprop file 'vc-backend backend) + ;; FIXME: This is wrong: it should set `backup-inhibited' in all + ;; the buffers visiting files affected by this `vc-register', not + ;; in the current-buffer. + ;; (unless vc-make-backup-files + ;; (make-local-variable 'backup-inhibited) + ;; (setq backup-inhibited t)) + + (vc-resynch-buffer file vc-keep-workfiles t)) + files) + (when (derived-mode-p 'vc-dir-mode) + (vc-dir-move-to-goal-column)) + (message "Registering %s... done" files))) + +(defun vc-register-with (backend) + "Register the current file with a specified back end." + (interactive "SBackend: ") + (when (not (member backend vc-handled-backends)) + (error "Unknown back end")) + (let ((vc-handled-backends (list backend))) + (call-interactively 'vc-register))) + +(defun vc-checkout (file &optional writable rev) + "Retrieve a copy of the revision REV of FILE. +If WRITABLE is non-nil, make sure the retrieved file is writable. +REV defaults to the latest revision. + +After check-out, runs the normal hook `vc-checkout-hook'." + (and writable + (not rev) + (vc-call make-version-backups-p file) + (vc-up-to-date-p file) + (vc-make-version-backup file)) + (let ((backend (vc-backend file))) + (with-vc-properties (list file) + (condition-case err + (vc-call-backend backend 'checkout file writable rev) + (file-error + ;; Maybe the backend is not installed ;-( + (when writable + (let ((buf (get-file-buffer file))) + (when buf (with-current-buffer buf (toggle-read-only -1))))) + (signal (car err) (cdr err)))) + `((vc-state . ,(if (or (eq (vc-checkout-model backend (list file)) 'implicit) + (not writable)) + (if (vc-call-backend backend 'latest-on-branch-p file) + 'up-to-date + 'needs-update) + 'edited)) + (vc-checkout-time . ,(nth 5 (file-attributes file)))))) + (vc-resynch-buffer file t t) + (run-hooks 'vc-checkout-hook)) + +(defun vc-mark-resolved (backend files) + (prog1 (with-vc-properties + files + (vc-call-backend backend 'mark-resolved files) + ;; FIXME: Is this TRTD? Might not be. + `((vc-state . edited))) + (message + (substitute-command-keys + "Conflicts have been resolved in %s. \ +Type \\[vc-next-action] to check in changes.") + (if (> (length files) 1) + (format "%d files" (length files)) + "this file")))) + +(defun vc-steal-lock (file rev owner) + "Steal the lock on FILE." + (let (file-description) + (if rev + (setq file-description (format "%s:%s" file rev)) + (setq file-description file)) + (when (not (yes-or-no-p (format "Steal the lock on %s from %s? " + file-description owner))) + (error "Steal canceled")) + (message "Stealing lock on %s..." file) + (with-vc-properties + (list file) + (vc-call steal-lock file rev) + `((vc-state . edited))) + (vc-resynch-buffer file t t) + (message "Stealing lock on %s...done" file) + ;; Write mail after actually stealing, because if the stealing + ;; goes wrong, we don't want to send any mail. + (compose-mail owner (format "Stolen lock on %s" file-description)) + (setq default-directory (expand-file-name "~/")) + (goto-char (point-max)) + (insert + (format "I stole the lock on %s, " file-description) + (current-time-string) + ".\n") + (message "Please explain why you stole the lock. Type C-c C-c when done."))) + +(defun vc-checkin (files backend &optional rev comment initial-contents) + "Check in FILES. +The optional argument REV may be a string specifying the new revision +level (strongly deprecated). COMMENT is a comment +string; if omitted, a buffer is popped up to accept a comment. If +INITIAL-CONTENTS is non-nil, then COMMENT is used as the initial contents +of the log entry buffer. + +If `vc-keep-workfiles' is nil, FILE is deleted afterwards, provided +that the version control system supports this mode of operation. + +Runs the normal hooks `vc-before-checkin-hook' and `vc-checkin-hook'." + (when vc-before-checkin-hook + (run-hooks 'vc-before-checkin-hook)) + (lexical-let + ((backend backend)) + (vc-start-logentry + files comment initial-contents + "Enter a change comment." + "*VC-log*" + (lambda () + (vc-call-backend backend 'log-edit-mode)) + (lexical-let ((rev rev)) + (lambda (files comment) + (message "Checking in %s..." (vc-delistify files)) + ;; "This log message intentionally left almost blank". + ;; RCS 5.7 gripes about white-space-only comments too. + (or (and comment (string-match "[^\t\n ]" comment)) + (setq comment "*** empty log message ***")) + (with-vc-properties + files + ;; We used to change buffers to get local value of + ;; vc-checkin-switches, but 'the' local buffer is + ;; not a well-defined concept for filesets. + (progn + (vc-call-backend backend 'checkin files rev comment) + (mapc 'vc-delete-automatic-version-backups files)) + `((vc-state . up-to-date) + (vc-checkout-time . ,(nth 5 (file-attributes file))) + (vc-working-revision . nil))) + (message "Checking in %s...done" (vc-delistify files)))) + 'vc-checkin-hook))) + +;;; Additional entry points for examining version histories + +;; (defun vc-default-diff-tree (backend dir rev1 rev2) +;; "List differences for all registered files at and below DIR. +;; The meaning of REV1 and REV2 is the same as for `vc-revision-diff'." +;; ;; This implementation does an explicit tree walk, and calls +;; ;; vc-BACKEND-diff directly for each file. An optimization +;; ;; would be to use `vc-diff-internal', so that diffs can be local, +;; ;; and to call it only for files that are actually changed. +;; ;; However, this is expensive for some backends, and so it is left +;; ;; to backend-specific implementations. +;; (setq default-directory dir) +;; (vc-file-tree-walk +;; default-directory +;; (lambda (f) +;; (vc-exec-after +;; `(let ((coding-system-for-read (vc-coding-system-for-diff ',f))) +;; (message "Looking at %s" ',f) +;; (vc-call-backend ',(vc-backend f) +;; 'diff (list ',f) ',rev1 ',rev2)))))) + +(defun vc-coding-system-for-diff (file) + "Return the coding system for reading diff output for FILE." + (or coding-system-for-read + ;; if we already have this file open, + ;; use the buffer's coding system + (let ((buf (find-buffer-visiting file))) + (when buf (with-current-buffer buf + buffer-file-coding-system))) + ;; otherwise, try to find one based on the file name + (car (find-operation-coding-system 'insert-file-contents file)) + ;; and a final fallback + 'undecided)) + +(defun vc-switches (backend op) + "Return a list of vc-BACKEND switches for operation OP. +BACKEND is a symbol such as `CVS', which will be downcased. +OP is a symbol such as `diff'. + +In decreasing order of preference, return the value of: +vc-BACKEND-OP-switches (e.g. `vc-cvs-diff-switches'); +vc-OP-switches (e.g. `vc-diff-switches'); or, in the case of +diff only, `diff-switches'. + +If the chosen value is not a string or a list, return nil. +This is so that you may set, e.g. `vc-svn-diff-switches' to t in order +to override the value of `vc-diff-switches' and `diff-switches'." + (let ((switches + (or (when backend + (let ((sym (vc-make-backend-sym + backend (intern (concat (symbol-name op) + "-switches"))))) + (when (boundp sym) (symbol-value sym)))) + (let ((sym (intern (format "vc-%s-switches" (symbol-name op))))) + (when (boundp sym) (symbol-value sym))) + (cond + ((eq op 'diff) diff-switches))))) + (if (stringp switches) (list switches) + ;; If not a list, return nil. + ;; This is so we can set vc-diff-switches to t to override + ;; any switches in diff-switches. + (when (listp switches) switches)))) + +;; Old def for compatibility with Emacs-21.[123]. +(defmacro vc-diff-switches-list (backend) `(vc-switches ',backend 'diff)) +(make-obsolete 'vc-diff-switches-list 'vc-switches "22.1") + +(defun vc-diff-finish (buffer messages) + ;; The empty sync output case has already been handled, so the only + ;; possibility of an empty output is for an async process. + (when (buffer-live-p buffer) + (let ((window (get-buffer-window buffer t)) + (emptyp (zerop (buffer-size buffer)))) + (with-current-buffer buffer + (and messages emptyp + (let ((inhibit-read-only t)) + (insert (cdr messages) ".\n") + (message "%s" (cdr messages)))) + (goto-char (point-min)) + (when window + (shrink-window-if-larger-than-buffer window))) + (when (and messages (not emptyp)) + (message "%sdone" (car messages)))))) + +(defvar vc-diff-added-files nil + "If non-nil, diff added files by comparing them to /dev/null.") + +(defun vc-diff-internal (async vc-fileset rev1 rev2 &optional verbose) + "Report diffs between two revisions of a fileset. +Diff output goes to the *vc-diff* buffer. The function +returns t if the buffer had changes, nil otherwise." + (let* ((files (cadr vc-fileset)) + (messages (cons (format "Finding changes in %s..." + (vc-delistify files)) + (format "No changes between %s and %s" + (or rev1 "working revision") + (or rev2 "workfile")))) + ;; Set coding system based on the first file. It's a kluge, + ;; but the only way to set it for each file included would + ;; be to call the back end separately for each file. + (coding-system-for-read + (if files (vc-coding-system-for-diff (car files)) 'undecided))) + (vc-setup-buffer "*vc-diff*") + (message "%s" (car messages)) + ;; Many backends don't handle well the case of a file that has been + ;; added but not yet committed to the repo (notably CVS and Subversion). + ;; Do that work here so the backends don't have to futz with it. --ESR + ;; + ;; Actually most backends (including CVS) have options to control the + ;; behavior since which one is better depends on the user and on the + ;; situation). Worse yet: this code does not handle the case where + ;; `file' is a directory which contains added files. + ;; I made it conditional on vc-diff-added-files but it should probably + ;; just be removed (or copied/moved to specific backends). --Stef. + (when vc-diff-added-files + (let ((filtered '()) + process-file-side-effects) + (dolist (file files) + (if (or (file-directory-p file) + (not (string= (vc-working-revision file) "0"))) + (push file filtered) + ;; This file is added but not yet committed; + ;; there is no repository version to diff against. + (if (or rev1 rev2) + (error "No revisions of %s exist" file) + ;; We regard this as "changed". + ;; Diff it against /dev/null. + (apply 'vc-do-command "*vc-diff*" + 1 "diff" file + (append (vc-switches nil 'diff) '("/dev/null")))))) + (setq files (nreverse filtered)))) + (let ((vc-disable-async-diff (not async))) + (vc-call-backend (car vc-fileset) 'diff files rev1 rev2 "*vc-diff*")) + (set-buffer "*vc-diff*") + (if (and (zerop (buffer-size)) + (not (get-buffer-process (current-buffer)))) + ;; Treat this case specially so as not to pop the buffer. + (progn + (message "%s" (cdr messages)) + nil) + (diff-mode) + (set (make-local-variable 'diff-vc-backend) (car vc-fileset)) + (set (make-local-variable 'revert-buffer-function) + `(lambda (ignore-auto noconfirm) + (vc-diff-internal ,async ',vc-fileset ,rev1 ,rev2 ,verbose))) + ;; Make the *vc-diff* buffer read only, the diff-mode key + ;; bindings are nicer for read only buffers. pcl-cvs does the + ;; same thing. + (setq buffer-read-only t) + (vc-exec-after `(vc-diff-finish ,(current-buffer) ',(when verbose + messages))) + ;; Display the buffer, but at the end because it can change point. + (pop-to-buffer (current-buffer)) + ;; In the async case, we return t even if there are no differences + ;; because we don't know that yet. + t))) + +(defun vc-read-revision (prompt &optional files backend default initial-input) + (cond + ((null files) + (let ((vc-fileset (vc-deduce-fileset t))) ;FIXME: why t? --Stef + (setq files (cadr vc-fileset)) + (setq backend (car vc-fileset)))) + ((null backend) (setq backend (vc-backend (car files))))) + (let ((completion-table + (vc-call-backend backend 'revision-completion-table files))) + (if completion-table + (completing-read prompt completion-table + nil nil initial-input nil default) + (read-string prompt initial-input nil default)))) + +;;;###autoload +(defun vc-version-diff (files rev1 rev2) + "Report diffs between revisions of the fileset in the repository history." + (interactive + (let* ((vc-fileset (vc-deduce-fileset t)) ;FIXME: why t? --Stef + (files (cadr vc-fileset)) + (backend (car vc-fileset)) + (first (car files)) + (rev1-default nil) + (rev2-default nil)) + (cond + ;; someday we may be able to do revision completion on non-singleton + ;; filesets, but not yet. + ((/= (length files) 1) + nil) + ;; if it's a directory, don't supply any revision default + ((file-directory-p first) + nil) + ;; if the file is not up-to-date, use working revision as older revision + ((not (vc-up-to-date-p first)) + (setq rev1-default (vc-working-revision first))) + ;; if the file is not locked, use last and previous revisions as defaults + (t + (setq rev1-default (vc-call-backend backend 'previous-revision first + (vc-working-revision first))) + (when (string= rev1-default "") (setq rev1-default nil)) + (setq rev2-default (vc-working-revision first)))) + ;; construct argument list + (let* ((rev1-prompt (if rev1-default + (concat "Older revision (default " + rev1-default "): ") + "Older revision: ")) + (rev2-prompt (concat "Newer revision (default " + (or rev2-default "current source") "): ")) + (rev1 (vc-read-revision rev1-prompt files backend rev1-default)) + (rev2 (vc-read-revision rev2-prompt files backend rev2-default))) + (when (string= rev1 "") (setq rev1 nil)) + (when (string= rev2 "") (setq rev2 nil)) + (list files rev1 rev2)))) + ;; All that was just so we could do argument completion! + (when (and (not rev1) rev2) + (error "Not a valid revision range")) + ;; Yes, it's painful to call (vc-deduce-fileset) again. Alas, the + ;; placement rules for (interactive) don't actually leave us a choice. + (vc-diff-internal t (vc-deduce-fileset t) rev1 rev2 + (called-interactively-p 'interactive))) + +;;;###autoload +(defun vc-diff (historic &optional not-urgent) + "Display diffs between file revisions. +Normally this compares the currently selected fileset with their +working revisions. With a prefix argument HISTORIC, it reads two revision +designators specifying which revisions to compare. + +The optional argument NOT-URGENT non-nil means it is ok to say no to +saving the buffer." + (interactive (list current-prefix-arg t)) + (if historic + (call-interactively 'vc-version-diff) + (when buffer-file-name (vc-buffer-sync not-urgent)) + (vc-diff-internal t (vc-deduce-fileset t) nil nil + (called-interactively-p 'interactive)))) + +;;;###autoload +(defun vc-root-diff (historic &optional not-urgent) + "Display diffs between VC-controlled whole tree revisions. +Normally, this compares the tree corresponding to the current +fileset with the working revision. +With a prefix argument HISTORIC, prompt for two revision +designators specifying which revisions to compare. + +The optional argument NOT-URGENT non-nil means it is ok to say no to +saving the buffer." + (interactive (list current-prefix-arg t)) + (if historic + ;; FIXME: this does not work right, `vc-version-diff' ends up + ;; calling `vc-deduce-fileset' to find the files to diff, and + ;; that's not what we want here, we want the diff for the VC root dir. + (call-interactively 'vc-version-diff) + (when buffer-file-name (vc-buffer-sync not-urgent)) + (let ((backend (vc-deduce-backend)) + rootdir working-revision) + (unless backend + (error "Buffer is not version controlled")) + (setq rootdir (vc-call-backend backend 'root default-directory)) + (setq working-revision (vc-working-revision rootdir)) + ;; VC diff for the root directory produces output that is + ;; relative to it. Bind default-directory to the root directory + ;; here, this way the *vc-diff* buffer is setup correctly, so + ;; relative file names work. + (let ((default-directory rootdir)) + (vc-diff-internal + t (list backend (list rootdir) working-revision) nil nil + (called-interactively-p 'interactive)))))) + +;;;###autoload +(defun vc-revision-other-window (rev) + "Visit revision REV of the current file in another window. +If the current file is named `F', the revision is named `F.~REV~'. +If `F.~REV~' already exists, use it instead of checking it out again." + (interactive + (save-current-buffer + (vc-ensure-vc-buffer) + (list + (vc-read-revision "Revision to visit (default is working revision): " + (list buffer-file-name))))) + (vc-ensure-vc-buffer) + (let* ((file buffer-file-name) + (revision (if (string-equal rev "") + (vc-working-revision file) + rev))) + (switch-to-buffer-other-window (vc-find-revision file revision)))) + - (defun vc-find-revision (file revision) - "Read REVISION of FILE into a buffer and return the buffer." ++(defun vc-find-revision (file revision &optional backend) ++ "Read REVISION of FILE into a buffer and return the buffer. ++Use BACKEND as the VC backend if specified." + (let ((automatic-backup (vc-version-backup-file-name file revision)) + (filebuf (or (get-file-buffer file) (current-buffer))) + (filename (vc-version-backup-file-name file revision 'manual))) + (unless (file-exists-p filename) + (if (file-exists-p automatic-backup) + (rename-file automatic-backup filename nil) + (message "Checking out %s..." filename) + (with-current-buffer filebuf + (let ((failed t)) + (unwind-protect + (let ((coding-system-for-read 'no-conversion) + (coding-system-for-write 'no-conversion)) + (with-temp-file filename + (let ((outbuf (current-buffer))) + ;; Change buffer to get local value of + ;; vc-checkout-switches. + (with-current-buffer filebuf - (vc-call find-revision file revision outbuf)))) ++ (if backend ++ (vc-call-backend backend 'find-revision file revision outbuf) ++ (vc-call find-revision file revision outbuf))))) + (setq failed nil)) + (when (and failed (file-exists-p filename)) + (delete-file filename)))) + (vc-mode-line file)) + (message "Checking out %s...done" filename))) + (let ((result-buf (find-file-noselect filename))) + (with-current-buffer result-buf + ;; Set the parent buffer so that things like + ;; C-x v g, C-x v l, ... etc work. + (set (make-local-variable 'vc-parent-buffer) filebuf)) + result-buf))) + +;; Header-insertion code + +;;;###autoload +(defun vc-insert-headers () + "Insert headers into a file for use with a version control system. +Headers desired are inserted at point, and are pulled from +the variable `vc-BACKEND-header'." + (interactive) + (vc-ensure-vc-buffer) + (save-excursion + (save-restriction + (widen) + (when (or (not (vc-check-headers)) + (y-or-n-p "Version headers already exist. Insert another set? ")) + (let* ((delims (cdr (assq major-mode vc-comment-alist))) + (comment-start-vc (or (car delims) comment-start "#")) + (comment-end-vc (or (car (cdr delims)) comment-end "")) + (hdsym (vc-make-backend-sym (vc-backend buffer-file-name) + 'header)) + (hdstrings (and (boundp hdsym) (symbol-value hdsym)))) + (dolist (s hdstrings) + (insert comment-start-vc "\t" s "\t" + comment-end-vc "\n")) + (when vc-static-header-alist + (dolist (f vc-static-header-alist) + (when (string-match (car f) buffer-file-name) + (insert (format (cdr f) (car hdstrings))))))))))) + +(defun vc-clear-headers (&optional file) + "Clear all version headers in the current buffer (or FILE). +The headers are reset to their non-expanded form." + (let* ((filename (or file buffer-file-name)) + (visited (find-buffer-visiting filename)) + (backend (vc-backend filename))) + (when (vc-find-backend-function backend 'clear-headers) + (if visited + (let ((context (vc-buffer-context))) + ;; save-excursion may be able to relocate point and mark + ;; properly. If it fails, vc-restore-buffer-context + ;; will give it a second try. + (save-excursion + (vc-call-backend backend 'clear-headers)) + (vc-restore-buffer-context context)) + (set-buffer (find-file-noselect filename)) + (vc-call-backend backend 'clear-headers) + (kill-buffer filename))))) + +(defun vc-modify-change-comment (files rev oldcomment) + "Edit the comment associated with the given files and revision." + ;; Less of a kluge than it looks like; log-view mode only passes + ;; this function a singleton list. Arguments left in this form in + ;; case the more general operation ever becomes meaningful. + (let ((backend (vc-responsible-backend (car files)))) + (vc-start-logentry + files oldcomment t + "Enter a replacement change comment." + "*VC-log*" + (lambda () (vc-call-backend backend 'log-edit-mode)) + (lexical-let ((rev rev)) + (lambda (files comment) + (vc-call-backend backend + 'modify-change-comment files rev comment)))))) + +;;;###autoload +(defun vc-merge () + "Merge changes between two revisions into the current buffer's file. +This asks for two revisions to merge from in the minibuffer. If the +first revision is a branch number, then merge all changes from that +branch. If the first revision is empty, merge news, i.e. recent changes +from the current branch. + +See Info node `Merging'." + (interactive) + (vc-ensure-vc-buffer) + (vc-buffer-sync) + (let* ((file buffer-file-name) + (backend (vc-backend file)) + (state (vc-state file)) + first-revision second-revision status) + (cond + ((stringp state) ;; Locking VCses only + (error "File is locked by %s" state)) + ((not (vc-editable-p file)) + (if (y-or-n-p + "File must be checked out for merging. Check out now? ") + (vc-checkout file t) + (error "Merge aborted")))) + (setq first-revision + (vc-read-revision + (concat "Branch or revision to merge from " + "(default news on current branch): ") + (list file) + backend)) + (if (string= first-revision "") + (setq status (vc-call-backend backend 'merge-news file)) + (if (not (vc-find-backend-function backend 'merge)) + (error "Sorry, merging is not implemented for %s" backend) + (if (not (vc-branch-p first-revision)) + (setq second-revision + (vc-read-revision + "Second revision: " + (list file) backend nil + ;; FIXME: This is CVS/RCS/SCCS specific. + (concat (vc-branch-part first-revision) "."))) + ;; We want to merge an entire branch. Set revisions + ;; accordingly, so that vc-BACKEND-merge understands us. + (setq second-revision first-revision) + ;; first-revision must be the starting point of the branch + (setq first-revision (vc-branch-part first-revision))) + (setq status (vc-call-backend backend 'merge file + first-revision second-revision)))) + (vc-maybe-resolve-conflicts file status "WORKFILE" "MERGE SOURCE"))) + +(defun vc-maybe-resolve-conflicts (file status &optional name-A name-B) + (vc-resynch-buffer file t (not (buffer-modified-p))) + (if (zerop status) (message "Merge successful") + (smerge-mode 1) + (message "File contains conflicts."))) + +;;;###autoload +(defalias 'vc-resolve-conflicts 'smerge-ediff) + +;; TODO: This is OK but maybe we could integrate it better. +;; E.g. it could be run semi-automatically (via a prompt?) when saving a file +;; that was conflicted (i.e. upon mark-resolved). +;; FIXME: should we add an "other-window" version? Or maybe we should +;; hook it inside find-file so it automatically works for +;; find-file-other-window as well. E.g. find-file could use a new +;; `default-next-file' variable for its default file (M-n), and +;; we could then set it upon mark-resolve, so C-x C-s C-x C-f M-n would +;; automatically offer the next conflicted file. +(defun vc-find-conflicted-file () + "Visit the next conflicted file in the current project." + (interactive) + (let* ((backend (or (if buffer-file-name (vc-backend buffer-file-name)) + (vc-responsible-backend default-directory) + (error "No VC backend"))) + (files (vc-call-backend backend + 'conflicted-files default-directory))) + ;; Don't try and visit the current file. + (if (equal (car files) buffer-file-name) (pop files)) + (if (null files) + (message "No more conflicted files") + (find-file (pop files)) + (message "%s more conflicted files after this one" + (if files (length files) "No"))))) + +;; Named-configuration entry points + +(defun vc-tag-precondition (dir) + "Scan the tree below DIR, looking for files not up-to-date. +If any file is not up-to-date, return the name of the first such file. +\(This means, neither tag creation nor retrieval is allowed.\) +If one or more of the files are currently visited, return `visited'. +Otherwise, return nil." + (let ((status nil)) + (catch 'vc-locked-example + (vc-file-tree-walk + dir + (lambda (f) + (if (not (vc-up-to-date-p f)) (throw 'vc-locked-example f) + (when (get-file-buffer f) (setq status 'visited))))) + status))) + +;;;###autoload +(defun vc-create-tag (dir name branchp) + "Descending recursively from DIR, make a tag called NAME. +For each registered file, the working revision becomes part of +the named configuration. If the prefix argument BRANCHP is +given, the tag is made as a new branch and the files are +checked out in that new branch." + (interactive + (let ((granularity + (vc-call-backend (vc-responsible-backend default-directory) + 'revision-granularity))) + (list + (if (eq granularity 'repository) + ;; For VC's that do not work at file level, it's pointless + ;; to ask for a directory, branches are created at repository level. + default-directory + (read-file-name "Directory: " default-directory default-directory t)) + (read-string (if current-prefix-arg "New branch name: " "New tag name: ")) + current-prefix-arg))) + (message "Making %s... " (if branchp "branch" "tag")) + (when (file-directory-p dir) (setq dir (file-name-as-directory dir))) + (vc-call-backend (vc-responsible-backend dir) + 'create-tag dir name branchp) + (vc-resynch-buffer dir t t t) + (message "Making %s... done" (if branchp "branch" "tag"))) + +;;;###autoload +(defun vc-retrieve-tag (dir name) + "Descending recursively from DIR, retrieve the tag called NAME. +If NAME is empty, it refers to the latest revisions. +If locking is used for the files in DIR, then there must not be any +locked files at or below DIR (but if NAME is empty, locked files are +allowed and simply skipped)." + (interactive + (let ((granularity + (vc-call-backend (vc-responsible-backend default-directory) + 'revision-granularity))) + (list + (if (eq granularity 'repository) + ;; For VC's that do not work at file level, it's pointless + ;; to ask for a directory, branches are created at repository level. + default-directory + (read-file-name "Directory: " default-directory default-directory t)) + (read-string "Tag name to retrieve (default latest revisions): ")))) + (let ((update (yes-or-no-p "Update any affected buffers? ")) + (msg (if (or (not name) (string= name "")) + (format "Updating %s... " (abbreviate-file-name dir)) + (format "Retrieving tag into %s... " + (abbreviate-file-name dir))))) + (message "%s" msg) + (vc-call-backend (vc-responsible-backend dir) + 'retrieve-tag dir name update) + (vc-resynch-buffer dir t t t) + (message "%s" (concat msg "done")))) + + +;; Miscellaneous other entry points + +;; FIXME: this should be a defcustom +;; FIXME: maybe add another choice: +;; `root-directory' (or somesuch), which would mean show a short log +;; for the root directory. +(defvar vc-log-short-style '(directory) + "Whether or not to show a short log. +If it contains `directory' then if the fileset contains a directory show a short log. +If it contains `file' then show short logs for files. +Not all VC backends support short logs!") + +(defvar log-view-vc-fileset) + +(defun vc-print-log-setup-buttons (working-revision is-start-revision limit pl-return) + (when (and limit (not (eq 'limit-unsupported pl-return)) + (not is-start-revision)) + (goto-char (point-max)) + (lexical-let ((working-revision working-revision) + (limit limit)) + (widget-create 'push-button + :notify (lambda (&rest ignore) + (vc-print-log-internal + log-view-vc-backend log-view-vc-fileset + working-revision nil (* 2 limit))) + :help-echo "Show the log again, and double the number of log entries shown" + "Show 2X entries") + (widget-insert " ") + (widget-create 'push-button + :notify (lambda (&rest ignore) + (vc-print-log-internal + log-view-vc-backend log-view-vc-fileset + working-revision nil nil)) + :help-echo "Show the log again, showing all entries" + "Show unlimited entries")) + (widget-setup))) + +(defun vc-print-log-internal (backend files working-revision + &optional is-start-revision limit) + ;; Don't switch to the output buffer before running the command, + ;; so that any buffer-local settings in the vc-controlled + ;; buffer can be accessed by the command. + (let ((dir-present nil) + (vc-short-log nil) + (buffer-name "*vc-change-log*") + type + pl-return) + (dolist (file files) + (when (file-directory-p file) + (setq dir-present t))) + (setq vc-short-log + (not (null (if dir-present + (memq 'directory vc-log-short-style) + (memq 'file vc-log-short-style))))) + (setq type (if vc-short-log 'short 'long)) + (lexical-let + ((working-revision working-revision) + (limit limit) + (shortlog vc-short-log) + (is-start-revision is-start-revision)) + (vc-log-internal-common + backend buffer-name files type + (lambda (bk buf type-arg files-arg) + (vc-call-backend bk 'print-log files-arg buf + shortlog (when is-start-revision working-revision) limit)) + (lambda (bk files-arg ret) + (vc-print-log-setup-buttons working-revision + is-start-revision limit ret)) + (lambda (bk) + (vc-call-backend bk 'show-log-entry working-revision)))))) + +(defvar vc-log-view-type nil + "Set this to differentiate the different types of logs.") +(put 'vc-log-view-type 'permanent-local t) + +(defun vc-log-internal-common (backend + buffer-name + files + type + backend-func + setup-buttons-func + goto-location-func) + (let (retval) + (with-current-buffer (get-buffer-create buffer-name) + (set (make-local-variable 'vc-log-view-type) type)) + (setq retval (funcall backend-func backend buffer-name type files)) + (pop-to-buffer buffer-name) + (let ((inhibit-read-only t)) + ;; log-view-mode used to be called with inhibit-read-only bound + ;; to t, so let's keep doing it, just in case. + (vc-call-backend backend 'log-view-mode) + (set (make-local-variable 'log-view-vc-backend) backend) + (set (make-local-variable 'log-view-vc-fileset) files)) + (vc-exec-after + `(let ((inhibit-read-only t)) + (funcall ',setup-buttons-func ',backend ',files ',retval) + (shrink-window-if-larger-than-buffer) + (funcall ',goto-location-func ',backend) + (setq vc-sentinel-movepoint (point)) + (set-buffer-modified-p nil))))) + +(defun vc-incoming-outgoing-internal (backend remote-location buffer-name type) + (vc-log-internal-common + backend buffer-name nil type + (lexical-let + ((remote-location remote-location)) + (lambda (bk buf type-arg files) + (vc-call-backend bk type-arg buf remote-location))) + (lambda (bk files-arg ret)) + (lambda (bk) + (goto-char (point-min))))) + +;;;###autoload +(defun vc-print-log (&optional working-revision limit) + "List the change log of the current fileset in a window. +If WORKING-REVISION is non-nil, leave point at that revision. +If LIMIT is non-nil, it should be a number specifying the maximum +number of revisions to show; the default is `vc-log-show-limit'. + +When called interactively with a prefix argument, prompt for +WORKING-REVISION and LIMIT." + (interactive + (cond + (current-prefix-arg + (let ((rev (read-from-minibuffer "Log from revision (default: last revision): " nil + nil nil nil)) + (lim (string-to-number + (read-from-minibuffer + "Limit display (unlimited: 0): " + (format "%s" vc-log-show-limit) + nil nil nil)))) + (when (string= rev "") (setq rev nil)) + (when (<= lim 0) (setq lim nil)) + (list rev lim))) + (t + (list nil (when (> vc-log-show-limit 0) vc-log-show-limit))))) + (let* ((vc-fileset (vc-deduce-fileset t)) ;FIXME: Why t? --Stef + (backend (car vc-fileset)) + (files (cadr vc-fileset)) + (working-revision (or working-revision (vc-working-revision (car files))))) + (vc-print-log-internal backend files working-revision nil limit))) + +;;;###autoload +(defun vc-print-root-log (&optional limit) + "List the change log for the current VC controlled tree in a window. +If LIMIT is non-nil, it should be a number specifying the maximum +number of revisions to show; the default is `vc-log-show-limit'. +When called interactively with a prefix argument, prompt for LIMIT." + (interactive + (cond + (current-prefix-arg + (let ((lim (string-to-number + (read-from-minibuffer + "Limit display (unlimited: 0): " + (format "%s" vc-log-show-limit) + nil nil nil)))) + (when (<= lim 0) (setq lim nil)) + (list lim))) + (t + (list (when (> vc-log-show-limit 0) vc-log-show-limit))))) + (let ((backend (vc-deduce-backend)) + rootdir working-revision) + (unless backend + (error "Buffer is not version controlled")) + (setq rootdir (vc-call-backend backend 'root default-directory)) + (setq working-revision (vc-working-revision rootdir)) + (vc-print-log-internal backend (list rootdir) working-revision nil limit))) + +;;;###autoload +(defun vc-log-incoming (&optional remote-location) + "Show a log of changes that will be received with a pull operation from REMOTE-LOCATION." + (interactive "sRemote location (empty for default): ") + (let ((backend (vc-deduce-backend)) + rootdir working-revision) + (unless backend + (error "Buffer is not version controlled")) + (vc-incoming-outgoing-internal backend remote-location "*vc-incoming*" 'log-incoming))) + +;;;###autoload +(defun vc-log-outgoing (&optional remote-location) + "Show a log of changes that will be sent with a push operation to REMOTE-LOCATION." + (interactive "sRemote location (empty for default): ") + (let ((backend (vc-deduce-backend)) + rootdir working-revision) + (unless backend + (error "Buffer is not version controlled")) + (vc-incoming-outgoing-internal backend remote-location "*vc-outgoing*" 'log-outgoing))) + +;;;###autoload +(defun vc-revert () + "Revert working copies of the selected fileset to their repository contents. +This asks for confirmation if the buffer contents are not identical +to the working revision (except for keyword expansion)." + (interactive) + (let* ((vc-fileset (vc-deduce-fileset)) + (files (cadr vc-fileset))) + ;; If any of the files is visited by the current buffer, make + ;; sure buffer is saved. If the user says `no', abort since + ;; we cannot show the changes and ask for confirmation to + ;; discard them. + (when (or (not files) (memq (buffer-file-name) files)) + (vc-buffer-sync nil)) + (dolist (file files) + (let ((buf (get-file-buffer file))) + (when (and buf (buffer-modified-p buf)) + (error "Please kill or save all modified buffers before reverting"))) + (when (vc-up-to-date-p file) + (unless (yes-or-no-p (format "%s seems up-to-date. Revert anyway? " file)) + (error "Revert canceled")))) + (when (vc-diff-internal vc-allow-async-revert vc-fileset nil nil) + (unless (yes-or-no-p + (format "Discard changes in %s? " + (let ((str (vc-delistify files)) + (nfiles (length files))) + (if (< (length str) 50) + str + (format "%d file%s" nfiles + (if (= nfiles 1) "" "s")))))) + (error "Revert canceled")) + (delete-windows-on "*vc-diff*") + (kill-buffer "*vc-diff*")) + (dolist (file files) + (message "Reverting %s..." (vc-delistify files)) + (vc-revert-file file) + (message "Reverting %s...done" (vc-delistify files))))) + +;;;###autoload +(defun vc-rollback () + "Roll back (remove) the most recent changeset committed to the repository. +This may be either a file-level or a repository-level operation, +depending on the underlying version-control system." + (interactive) + (let* ((vc-fileset (vc-deduce-fileset)) + (backend (car vc-fileset)) + (files (cadr vc-fileset)) + (granularity (vc-call-backend backend 'revision-granularity))) + (unless (vc-find-backend-function backend 'rollback) + (error "Rollback is not supported in %s" backend)) + (when (and (not (eq granularity 'repository)) (/= (length files) 1)) + (error "Rollback requires a singleton fileset or repository versioning")) + ;; FIXME: latest-on-branch-p should take the fileset. + (when (not (vc-call-backend backend 'latest-on-branch-p (car files))) + (error "Rollback is only possible at the tip revision")) + ;; If any of the files is visited by the current buffer, make + ;; sure buffer is saved. If the user says `no', abort since + ;; we cannot show the changes and ask for confirmation to + ;; discard them. + (when (or (not files) (memq (buffer-file-name) files)) + (vc-buffer-sync nil)) + (dolist (file files) + (when (buffer-modified-p (get-file-buffer file)) + (error "Please kill or save all modified buffers before rollback")) + (when (not (vc-up-to-date-p file)) + (error "Please revert all modified workfiles before rollback"))) + ;; Accumulate changes associated with the fileset + (vc-setup-buffer "*vc-diff*") + (not-modified) + (message "Finding changes...") + (let* ((tip (vc-working-revision (car files))) + ;; FIXME: `previous-revision' should take the fileset. + (previous (vc-call-backend backend 'previous-revision + (car files) tip))) + (vc-diff-internal nil vc-fileset previous tip)) + ;; Display changes + (unless (yes-or-no-p "Discard these revisions? ") + (error "Rollback canceled")) + (delete-windows-on "*vc-diff*") + (kill-buffer"*vc-diff*") + ;; Do the actual reversions + (message "Rolling back %s..." (vc-delistify files)) + (with-vc-properties + files + (vc-call-backend backend 'rollback files) + `((vc-state . ,'up-to-date) + (vc-checkout-time . , (nth 5 (file-attributes file))) + (vc-working-revision . nil))) + (dolist (f files) (vc-resynch-buffer f t t)) + (message "Rolling back %s...done" (vc-delistify files)))) + +;;;###autoload +(define-obsolete-function-alias 'vc-revert-buffer 'vc-revert "23.1") + +;;;###autoload +(defun vc-update () + "Update the current fileset's files to their tip revisions. +For each one that contains no changes, and is not locked, then this simply +replaces the work file with the latest revision on its branch. If the file +contains changes, and the backend supports merging news, then any recent +changes from the current branch are merged into the working file." + (interactive) + (let* ((vc-fileset (vc-deduce-fileset)) + (backend (car vc-fileset)) + (files (cadr vc-fileset))) + (save-some-buffers ; save buffers visiting files + nil (lambda () + (and (buffer-modified-p) + (let ((file (buffer-file-name))) + (and file (member file files)))))) + (dolist (file files) + (if (vc-up-to-date-p file) + (vc-checkout file nil t) + (if (eq (vc-checkout-model backend (list file)) 'locking) + (if (eq (vc-state file) 'edited) + (error "%s" + (substitute-command-keys + "File is locked--type \\[vc-revert] to discard changes")) + (error "Unexpected file state (%s) -- type %s" + (vc-state file) + (substitute-command-keys + "\\[vc-next-action] to correct"))) + (vc-maybe-resolve-conflicts + file (vc-call-backend backend 'merge-news file))))))) + +(defun vc-version-backup-file (file &optional rev) + "Return name of backup file for revision REV of FILE. +If version backups should be used for FILE, and there exists +such a backup for REV or the working revision of file, return +its name; otherwise return nil." + (when (vc-call make-version-backups-p file) + (let ((backup-file (vc-version-backup-file-name file rev))) + (if (file-exists-p backup-file) + backup-file + ;; there is no automatic backup, but maybe the user made one manually + (setq backup-file (vc-version-backup-file-name file rev 'manual)) + (when (file-exists-p backup-file) + backup-file))))) + +(defun vc-revert-file (file) + "Revert FILE back to the repository working revision it was based on." + (with-vc-properties + (list file) + (let ((backup-file (vc-version-backup-file file))) + (when backup-file + (copy-file backup-file file 'ok-if-already-exists 'keep-date) + (vc-delete-automatic-version-backups file)) + (vc-call revert file backup-file)) + `((vc-state . up-to-date) + (vc-checkout-time . ,(nth 5 (file-attributes file))))) + (vc-resynch-buffer file t t)) + +;;;###autoload +(defun vc-switch-backend (file backend) + "Make BACKEND the current version control system for FILE. +FILE must already be registered in BACKEND. The change is not +permanent, only for the current session. This function only changes +VC's perspective on FILE, it does not register or unregister it. +By default, this command cycles through the registered backends. +To get a prompt, use a prefix argument." + (interactive + (list + (or buffer-file-name + (error "There is no version-controlled file in this buffer")) + (let ((crt-bk (vc-backend buffer-file-name)) + (backends nil)) + (unless crt-bk + (error "File %s is not under version control" buffer-file-name)) + ;; Find the registered backends. + (dolist (crt vc-handled-backends) + (when (and (vc-call-backend crt 'registered buffer-file-name) + (not (eq crt-bk crt))) + (push crt backends))) + ;; Find the next backend. + (let ((def (car backends)) + (others backends)) + (cond + ((null others) (error "No other backend to switch to")) + (current-prefix-arg + (intern + (upcase + (completing-read + (format "Switch to backend [%s]: " def) + (mapcar (lambda (b) (list (downcase (symbol-name b)))) backends) + nil t nil nil (downcase (symbol-name def)))))) + (t def)))))) + (unless (eq backend (vc-backend file)) + (vc-file-clearprops file) + (vc-file-setprop file 'vc-backend backend) + ;; Force recomputation of the state + (unless (vc-call-backend backend 'registered file) + (vc-file-clearprops file) + (error "%s is not registered in %s" file backend)) + (vc-mode-line file))) + +;;;###autoload +(defun vc-transfer-file (file new-backend) + "Transfer FILE to another version control system NEW-BACKEND. +If NEW-BACKEND has a higher precedence than FILE's current backend +\(i.e. it comes earlier in `vc-handled-backends'), then register FILE in +NEW-BACKEND, using the revision number from the current backend as the +base level. If NEW-BACKEND has a lower precedence than the current +backend, then commit all changes that were made under the current +backend to NEW-BACKEND, and unregister FILE from the current backend. +\(If FILE is not yet registered under NEW-BACKEND, register it.)" + (let* ((old-backend (vc-backend file)) + (edited (memq (vc-state file) '(edited needs-merge))) + (registered (vc-call-backend new-backend 'registered file)) + (move + (and registered ; Never move if not registered in new-backend yet. + ;; move if new-backend comes later in vc-handled-backends + (or (memq new-backend (memq old-backend vc-handled-backends)) + (y-or-n-p "Final transfer? ")))) + (comment nil)) + (when (eq old-backend new-backend) + (error "%s is the current backend of %s" new-backend file)) + (if registered + (set-file-modes file (logior (file-modes file) 128)) + ;; `registered' might have switched under us. + (vc-switch-backend file old-backend) + (let* ((rev (vc-working-revision file)) + (modified-file (and edited (make-temp-file file))) + (unmodified-file (and modified-file (vc-version-backup-file file)))) + ;; Go back to the base unmodified file. + (unwind-protect + (progn + (when modified-file + (copy-file file modified-file 'ok-if-already-exists) + ;; If we have a local copy of the unmodified file, handle that + ;; here and not in vc-revert-file because we don't want to + ;; delete that copy -- it is still useful for OLD-BACKEND. + (if unmodified-file + (copy-file unmodified-file file + 'ok-if-already-exists 'keep-date) + (when (y-or-n-p "Get base revision from repository? ") + (vc-revert-file file)))) + (vc-call-backend new-backend 'receive-file file rev)) + (when modified-file + (vc-switch-backend file new-backend) + (unless (eq (vc-checkout-model new-backend (list file)) 'implicit) + (vc-checkout file t nil)) + (rename-file modified-file file 'ok-if-already-exists) + (vc-file-setprop file 'vc-checkout-time nil))))) + (when move + (vc-switch-backend file old-backend) + (setq comment (vc-call-backend old-backend 'comment-history file)) + (vc-call-backend old-backend 'unregister file)) + (vc-switch-backend file new-backend) + (when (or move edited) + (vc-file-setprop file 'vc-state 'edited) + (vc-mode-line file new-backend) + (vc-checkin file new-backend nil comment (stringp comment))))) + +(defun vc-rename-master (oldmaster newfile templates) + "Rename OLDMASTER to be the master file for NEWFILE based on TEMPLATES." + (let* ((dir (file-name-directory (expand-file-name oldmaster))) + (newdir (or (file-name-directory newfile) "")) + (newbase (file-name-nondirectory newfile)) + (masters + ;; List of potential master files for `newfile' + (mapcar + (lambda (s) (vc-possible-master s newdir newbase)) + templates))) + (when (or (file-symlink-p oldmaster) + (file-symlink-p (file-name-directory oldmaster))) + (error "This is unsafe in the presence of symbolic links")) + (rename-file + oldmaster + (catch 'found + ;; If possible, keep the master file in the same directory. + (dolist (f masters) + (when (and f (string= (file-name-directory (expand-file-name f)) dir)) + (throw 'found f))) + ;; If not, just use the first possible place. + (dolist (f masters) + (and f (or (not (setq dir (file-name-directory f))) + (file-directory-p dir)) + (throw 'found f))) + (error "New file lacks a version control directory"))))) + +;;;###autoload +(defun vc-delete-file (file) + "Delete file and mark it as such in the version control system." + (interactive "fVC delete file: ") + (setq file (expand-file-name file)) + (let ((buf (get-file-buffer file)) + (backend (vc-backend file))) + (unless backend + (error "File %s is not under version control" + (file-name-nondirectory file))) + (unless (vc-find-backend-function backend 'delete-file) + (error "Deleting files under %s is not supported in VC" backend)) + (when (and buf (buffer-modified-p buf)) + (error "Please save or undo your changes before deleting %s" file)) + (let ((state (vc-state file))) + (when (eq state 'edited) + (error "Please commit or undo your changes before deleting %s" file)) + (when (eq state 'conflict) + (error "Please resolve the conflicts before deleting %s" file))) + (unless (y-or-n-p (format "Really want to delete %s? " + (file-name-nondirectory file))) + (error "Abort!")) + (unless (or (file-directory-p file) (null make-backup-files) + (not (file-exists-p file))) + (with-current-buffer (or buf (find-file-noselect file)) + (let ((backup-inhibited nil)) + (backup-buffer)))) + ;; Bind `default-directory' so that the command that the backend + ;; runs to remove the file is invoked in the correct context. + (let ((default-directory (file-name-directory file))) + (vc-call-backend backend 'delete-file file)) + ;; If the backend hasn't deleted the file itself, let's do it for him. + (when (file-exists-p file) (delete-file file)) + ;; Forget what VC knew about the file. + (vc-file-clearprops file) + ;; Make sure the buffer is deleted and the *vc-dir* buffers are + ;; updated after this. + (vc-resynch-buffer file nil t))) + +;;;###autoload +(defun vc-rename-file (old new) + "Rename file OLD to NEW in both work area and repository." + (interactive "fVC rename file: \nFRename to: ") + ;; in CL I would have said (setq new (merge-pathnames new old)) + (let ((old-base (file-name-nondirectory old))) + (when (and (not (string= "" old-base)) + (string= "" (file-name-nondirectory new))) + (setq new (concat new old-base)))) + (let ((oldbuf (get-file-buffer old))) + (when (and oldbuf (buffer-modified-p oldbuf)) + (error "Please save files before moving them")) + (when (get-file-buffer new) + (error "Already editing new file name")) + (when (file-exists-p new) + (error "New file already exists")) + (let ((state (vc-state old))) + (unless (memq state '(up-to-date edited)) + (error "Please %s files before moving them" + (if (stringp state) "check in" "update")))) + (vc-call rename-file old new) + (vc-file-clearprops old) + ;; Move the actual file (unless the backend did it already) + (when (file-exists-p old) (rename-file old new)) + ;; ?? Renaming a file might change its contents due to keyword expansion. + ;; We should really check out a new copy if the old copy was precisely equal + ;; to some checked-in revision. However, testing for this is tricky.... + (when oldbuf + (with-current-buffer oldbuf + (let ((buffer-read-only buffer-read-only)) + (set-visited-file-name new)) + (vc-mode-line new (vc-backend new)) + (set-buffer-modified-p nil))))) + +;;;###autoload +(defun vc-update-change-log (&rest args) + "Find change log file and add entries from recent version control logs. +Normally, find log entries for all registered files in the default +directory. + +With prefix arg of \\[universal-argument], only find log entries for the current buffer's file. + +With any numeric prefix arg, find log entries for all currently visited +files that are under version control. This puts all the entries in the +log for the default directory, which may not be appropriate. + +From a program, any ARGS are assumed to be filenames for which +log entries should be gathered." + (interactive + (cond ((consp current-prefix-arg) ;C-u + (list buffer-file-name)) + (current-prefix-arg ;Numeric argument. + (let ((files nil) + (buffers (buffer-list)) + file) + (while buffers + (setq file (buffer-file-name (car buffers))) + (and file (vc-backend file) + (setq files (cons file files))) + (setq buffers (cdr buffers))) + files)) + (t + ;; Don't supply any filenames to backend; this means + ;; it should find all relevant files relative to + ;; the default-directory. + nil))) + (vc-call-backend (vc-responsible-backend default-directory) + 'update-changelog args)) + +;; functions that operate on RCS revision numbers. This code should +;; also be moved into the backends. It stays for now, however, since +;; it is used in code below. +(defun vc-branch-p (rev) + "Return t if REV is a branch revision." + (not (eq nil (string-match "\\`[0-9]+\\(\\.[0-9]+\\.[0-9]+\\)*\\'" rev)))) + +;;;###autoload +(defun vc-branch-part (rev) + "Return the branch part of a revision number REV." + (let ((index (string-match "\\.[0-9]+\\'" rev))) + (when index + (substring rev 0 index)))) + +(define-obsolete-function-alias + 'vc-default-previous-version 'vc-default-previous-revision "23.1") + +(defun vc-default-responsible-p (backend file) + "Indicate whether BACKEND is reponsible for FILE. +The default is to return nil always." + nil) + +(defun vc-default-could-register (backend file) + "Return non-nil if BACKEND could be used to register FILE. +The default implementation returns t for all files." + t) + +(defun vc-default-latest-on-branch-p (backend file) + "Return non-nil if FILE is the latest on its branch. +This default implementation always returns non-nil, which means that +editing non-current revisions is not supported by default." + t) + +(defun vc-default-init-revision (backend) vc-default-init-revision) + +(defun vc-default-find-revision (backend file rev buffer) + "Provide the new `find-revision' op based on the old `checkout' op. +This is only for compatibility with old backends. They should be updated +to provide the `find-revision' operation instead." + (let ((tmpfile (make-temp-file (expand-file-name file)))) + (unwind-protect + (progn + (vc-call-backend backend 'checkout file nil rev tmpfile) + (with-current-buffer buffer + (insert-file-contents-literally tmpfile))) + (delete-file tmpfile)))) + +(defun vc-default-rename-file (backend old new) + (condition-case nil + (add-name-to-file old new) + (error (rename-file old new))) + (vc-delete-file old) + (with-current-buffer (find-file-noselect new) + (vc-register))) + +(defalias 'vc-default-check-headers 'ignore) + +(declare-function log-edit-mode "log-edit" ()) + +(defun vc-default-log-edit-mode (backend) (log-edit-mode)) + +(defun vc-default-log-view-mode (backend) (log-view-mode)) + +(defun vc-default-show-log-entry (backend rev) + (with-no-warnings + (log-view-goto-rev rev))) + +(defun vc-default-comment-history (backend file) + "Return a string with all log entries stored in BACKEND for FILE." + (when (vc-find-backend-function backend 'print-log) + (with-current-buffer "*vc*" + (vc-call-backend backend 'print-log (list file)) + (buffer-string)))) + +(defun vc-default-receive-file (backend file rev) + "Let BACKEND receive FILE from another version control system." + (vc-call-backend backend 'register (list file) rev "")) + +(defun vc-default-retrieve-tag (backend dir name update) + (if (string= name "") + (progn + (vc-file-tree-walk + dir + (lambda (f) (and + (vc-up-to-date-p f) + (vc-error-occurred + (vc-call-backend backend 'checkout f nil "") + (when update (vc-resynch-buffer f t t))))))) + (let ((result (vc-tag-precondition dir))) + (if (stringp result) + (error "File %s is locked" result) + (setq update (and (eq result 'visited) update)) + (vc-file-tree-walk + dir + (lambda (f) (vc-error-occurred + (vc-call-backend backend 'checkout f nil name) + (when update (vc-resynch-buffer f t t))))))))) + +(defun vc-default-revert (backend file contents-done) + (unless contents-done + (let ((rev (vc-working-revision file)) + (file-buffer (or (get-file-buffer file) (current-buffer)))) + (message "Checking out %s..." file) + (let ((failed t) + (backup-name (car (find-backup-file-name file)))) + (when backup-name + (copy-file file backup-name 'ok-if-already-exists 'keep-date) + (unless (file-writable-p file) + (set-file-modes file (logior (file-modes file) 128)))) + (unwind-protect + (let ((coding-system-for-read 'no-conversion) + (coding-system-for-write 'no-conversion)) + (with-temp-file file + (let ((outbuf (current-buffer))) + ;; Change buffer to get local value of vc-checkout-switches. + (with-current-buffer file-buffer + (let ((default-directory (file-name-directory file))) + (vc-call-backend backend 'find-revision + file rev outbuf))))) + (setq failed nil)) + (when backup-name + (if failed + (rename-file backup-name file 'ok-if-already-exists) + (and (not vc-make-backup-files) (delete-file backup-name)))))) + (message "Checking out %s...done" file)))) + +(defalias 'vc-default-revision-completion-table 'ignore) +(defalias 'vc-default-mark-resolved 'ignore) + +(defun vc-default-dir-status-files (backend dir files default-state update-function) + (funcall update-function + (mapcar (lambda (file) (list file default-state)) files))) + +(defun vc-check-headers () + "Check if the current file has any headers in it." + (interactive) + (vc-call-backend (vc-backend buffer-file-name) 'check-headers)) + + + +;; These things should probably be generally available + +(defun vc-string-prefix-p (prefix string) + (let ((lpref (length prefix))) + (and (>= (length string) lpref) + (eq t (compare-strings prefix nil nil string nil lpref))))) + +(defun vc-file-tree-walk (dirname func &rest args) + "Walk recursively through DIRNAME. +Invoke FUNC f ARGS on each VC-managed file f underneath it." + (vc-file-tree-walk-internal (expand-file-name dirname) func args) + (message "Traversing directory %s...done" dirname)) + +(defun vc-file-tree-walk-internal (file func args) + (if (not (file-directory-p file)) + (when (vc-backend file) (apply func file args)) + (message "Traversing directory %s..." (abbreviate-file-name file)) + (let ((dir (file-name-as-directory file))) + (mapcar + (lambda (f) (or + (string-equal f ".") + (string-equal f "..") + (member f vc-directory-exclusion-list) + (let ((dirf (expand-file-name f dir))) + (or + (file-symlink-p dirf) ;; Avoid possible loops. + (vc-file-tree-walk-internal dirf func args))))) + (directory-files dir))))) + +(provide 'vc) + +;; arch-tag: ca82c1de-3091-4e26-af92-460abc6213a6 +;;; vc.el ends here diff --cc src/ChangeLog index a6fb6852c6c,b6fe8f8c5c3..2d6c12a62b7 --- a/src/ChangeLog +++ b/src/ChangeLog @@@ -1,2554 -1,175 +1,2626 @@@ +2010-07-10 Eli Zaretskii + + * process.c: Reshuffle #include's. Condition some of the global + and static variables on `subprocesses'. + (hold_keyboard_input, unhold_keyboard_input, kbd_on_hold_p): + Leave only one implementation. + (Fget_buffer_process, Fprocess_inherit_coding_system_flag) + (kill_buffer_processes, Flist_system_processes) + (Fprocess_attributes, init_process, syms_of_process): Unify the + implementations for with subprocesses and without them. + +2010-07-09 Jan Djärv + + * xmenu.c (set_frame_menubar): Must realize menubar_widget to get the + correct size for Motif. + (free_frame_menubar): Call x_set_window_size to update frame size. + + * xfns.c (x_window): Set borderWidth to 0 for pane and + EmacsFrame. Frame size calculation is wrong otherwise. + +2010-07-09 Michael Albinus + + * dbusbind.c (xd_initialize): Add new argument RAISE_ERROR, which + allows to suppress errors when polling in Emacs' main loop. + (Fdbus_init_bus, Fdbus_get_unique_name, Fdbus_call_method) + (Fdbus_call_method_asynchronously, Fdbus_method_return_internal) + (Fdbus_method_error_internal, Fdbus_send_signal) + (xd_get_dispatch_status, xd_read_message, Fdbus_register_signal) + (Fdbus_register_method): Use it. (Bug#6579) + +2010-07-08 Dan Nicolaescu + + * alloc.c: Convert DEFUNs to standard C. + * buffer.c: + * bytecode.c: + * callint.c: + * callproc.c: + * casefiddle.c: + * casetab.c: + * category.c: + * character.c: + * charset.c: + * chartab.c: + * cmds.c: + * coding.c: + * composite.c: + * data.c: + * dbusbind.c: + * dired.c: + * dispnew.c: + * doc.c: + * dosfns.c: + * editfns.c: + * emacs.c: + * eval.c: + * fileio.c: + * filelock.c: + * floatfns.c: + * fns.c: + * font.c: + * fontset.c: + * frame.c: + * fringe.c: + * image.c: + * indent.c: + * insdel.c: + * keyboard.c: + * keymap.c: + * lread.c: + * macros.c: + * marker.c: + * menu.c: + * minibuf.c: + * msdos.c: + * nsfns.m: + * nsmenu.m: + * nsselect.m: + * print.c: + * process.c: + * search.c: + * sound.c: + * syntax.c: + * term.c: + * terminal.c: + * textprop.c: + * undo.c: + * w16select.c: + * w32console.c: + * w32fns.c: + * w32font.c: + * w32menu.c: + * w32proc.c: + * w32select.c: + * window.c: + * xdisp.c: + * xfaces.c: + * xfns.c: + * xmenu.c: + * xselect.c: + * xsettings.c: + * xsmfns.c: Likewise. + + +2010-07-08 Eli Zaretskii + + * process.c (kbd_is_on_hold, hold_keyboard_input) + (unhold_keyboard_input, kbd_on_hold_p) [!subprocesses]: Define. + +2010-07-08 Jan Djärv + + * xmenu.c (set_frame_menubar, create_and_show_popup_menu) + (create_and_show_dialog): Don't call apply_systemfont_to_(menu|dialog) + unless USE_LUCID. + +2010-07-08 Dan Nicolaescu + + * xdisp.c (store_mode_line_noprop_char): Remove K&R alternative declaration. + + Clean up include guards. + * tparam.c: Remove include guards for config.h, string.h and code + that assumes #ifndef emacs. + * termcap.c: + * unexalpha.c: + * sysdep.c: + * filemode.c: + * filelock.c: + * bidi.c: Likewise. + + Remove prefix-args.c + * prefix-args.c: Remove file. + * autodeps.mk (ALLOBJS): Remove reference to prefix-args. + * Makefile.in (temacs${EXEEXT}): Remove references to + PRE_EDIT_LDFLAGS and POST_EDIT_LDFLAGS. + (mostlyclean): Remove reference to prefix-args. + (prefix-args): Remove. + + Simplify cstart_of_data, start_of_code and related code. + * mem-limits.h: Remove !emacs and _LIBC conditional code. + (start_of_data): Merge into start_of_data function. + * sysdep.c (start_of_text): Remove. Move simplified versions of + it in the only users: unexaix.c and unexec.c. + (read_input_waiting): Remove local declaration of quit_char. + (start, etext): Remove declarations. + (start_of_data): Merge with the version in mem-limits.h and move + to vm-limits.c. + * vm-limit.c (start_of_data): Merged and simplified version of the + code formerly in mem-limits.h and sysdep.c. + * unexec.c (start): New declaration, moved from sysdep.c. + (start_of_text): Simplified version of the code formerly in sysdep.c. + * unexaix.c (start_of_text): Simplified version of the code + formerly in sysdep.c. + * m/alpha.h (HAVE_TEXT_START): Remove. + (TEXT_START): Move ... + * unexalpha.c (TEXT_START): ... here. + * s/hpux10-20.h (TEXT_START): Remove. + * s/darwin.h (TEXT_START): + * m/mips.h (TEXT_START): + * m/macppc.h (HAVE_TEXT_START): + * m/m68k.h (TEXT_START): + * m/iris4d.h (TEXT_START): + * m/intel386.h (TEXT_START): + * m/ibmrs6000.h (TEXT_START): + * m/ia64.h (HAVE_TEXT_START): + * s/msdos.h (TEXT_START): Likewise. + +2010-07-07 Andreas Schwab + + * alloc.c (overrun_check_malloc, overrun_check_realloc) + (overrun_check_free, xstrdup, allocate_string) + (allocate_string_data, compact_small_strings, Fmake_string) + (make_unibyte_string, make_multibyte_string) + (make_string_from_bytes, make_specified_string, make_float) + (Fcons, allocate_terminal, allocate_frame, make_pure_string) + (Fgarbage_collect): Replace bcopy, safe_bcopy, bzero, bcmp by + memcpy, memmove, memset, memcmp. + * atimer.c (start_atimer, set_alarm): Likewise. + * buffer.c (clone_per_buffer_values, report_overlay_modification) + (mmap_realloc, init_buffer_once): Likewise. + * callint.c (Fcall_interactively): Likewise. + * callproc.c (Fcall_process, Fcall_process_region, child_setup) + (getenv_internal_1): Likewise. + * casefiddle.c (casify_object): Likewise. + * ccl.c (ccl_driver): Likewise. + * character.c (str_as_multibyte, str_to_multibyte): Likewise. + * charset.c (load_charset_map_from_file) + (load_charset_map_from_file, load_charset_map_from_vector) + (Fdefine_charset_internal): Likewise. + * cm.c (Wcm_clear): Likewise. + * coding.c (decode_eol, decode_coding_object) + (Fset_coding_system_priority, make_subsidiaries): Likewise. + * data.c (Faset): Likewise. + * dired.c (directory_files_internal, file_name_completion_stat): + Likewise. + * dispnew.c (new_glyph_matrix, adjust_glyph_matrix) + (clear_glyph_row, copy_row_except_pointers) + (copy_glyph_row_contents, new_glyph_pool, realloc_glyph_pool) + (save_current_matrix, restore_current_matrix) + (build_frame_matrix_from_leaf_window, mirrored_line_dance) + (mirror_line_dance, scrolling_window): Likewise. + * doc.c (Fsnarf_documentation, Fsubstitute_command_keys): + Likewise. + * doprnt.c (doprnt): Likewise. + * editfns.c (Fuser_full_name, make_buffer_string_both) + (Fmessage_box, Fformat, Ftranspose_regions): Likewise. + * emacs.c (sort_args): Likewise. + * eval.c (Fapply, Ffuncall): Likewise. + * fileio.c (Ffile_name_directory, make_temp_name) + (Fexpand_file_name, search_embedded_absfilename) + (Fsubstitute_in_file_name, Ffile_symlink_p, Finsert_file_contents) + (auto_save_error): Likewise. + * fns.c (Fstring_equal, Fcopy_sequence, concat) + (string_to_multibyte, Fstring_as_unibyte, Fstring_as_multibyte) + (internal_equal, Fclear_string, larger_vector, copy_hash_table) + (Fmake_hash_table): Likewise. + * fringe.c (Fdefine_fringe_bitmap): Likewise. + * ftfont.c (ftfont_text_extents): Likewise. + * getloadavg.c (getloadavg): Likewise. + * image.c (define_image_type, make_image, make_image_cache) + (x_create_x_image_and_pixmap, xbm_image_p) + (w32_create_pixmap_from_bitmap_data, xbm_load, xpm_lookup_color) + (xpm_image_p, x_create_bitmap_from_xpm_data, xpm_load) + (init_color_table, x_build_heuristic_mask, pbm_image_p, pbm_load) + (png_image_p, png_read_from_memory, png_load, jpeg_image_p) + (tiff_image_p, tiff_read_from_memory, gif_image_p) + (gif_read_from_memory, gif_load, svg_image_p, gs_image_p): + Likewise. + * indent.c (scan_for_column, compute_motion): Likewise. + * insdel.c (gap_left, gap_right, make_gap_smaller, copy_text) + (insert_1_both, insert_from_gap, replace_range_2): Likewise. + * intervals.c (reproduce_tree, reproduce_tree_obj): Likewise. + * keyboard.c (echo_char, save_getcjmp, restore_getcjmp) + (kbd_buffer_store_event_hold, apply_modifiers_uncached) + (store_user_signal_events, menu_bar_items, tool_bar_items) + (process_tool_bar_item, append_tool_bar_item) + (read_char_minibuf_menu_prompt, read_key_sequence) + (Fread_key_sequence, Fread_key_sequence_vector, Frecent_keys): + Likewise. + * keymap.c (current_minor_maps, Fdescribe_buffer_bindings): + Likewise. + * lisp.h (STRING_COPYIN): Likewise. + * lread.c (Fload, read1, oblookup): Likewise. + * msdos.c (Frecent_doskeys): Likewise. + * nsfns.m (Fx_create_frame): Likewise. + * nsfont.m (nsfont_open, nsfont_text_extents, ns_glyph_metrics): + Likewise. + * nsimage.m (EmacsImage-initFromSkipXBM:width:height:) + (EmacsImage-initForXPMWithDepth:width:height:flip:length:): + Likewise. + * nsmenu.m (ns_update_menubar): Likewise. + * nsterm.m (ns_draw_fringe_bitmap, ns_term_init): Likewise. + * print.c (print_unwind, printchar, strout, print_string) + (print_error_message): Likewise. + * process.c (conv_lisp_to_sockaddr, set_socket_option) + (Fmake_network_process, Fnetwork_interface_list) + (Fnetwork_interface_info, read_process_output, Fprocess_send_eof) + (init_process): Likewise. + * ralloc.c (resize_bloc, r_alloc_sbrk, r_alloc_init): Likewise. + * regex.c (init_syntax_once, regex_compile, re_compile_fastmap): + Likewise. + * scroll.c (do_scrolling, do_direct_scrolling) + (scrolling_max_lines_saved): Likewise. + * search.c (search_buffer, wordify, Freplace_match): Likewise. + * sound.c (wav_init, au_init, Fplay_sound_internal): Likewise. + * syntax.c (skip_chars, skip_syntaxes): Likewise. + * sysdep.c (child_setup_tty, sys_subshell, emacs_get_tty) + (emacs_set_tty): Likewise. + * term.c (encode_terminal_code, calculate_costs) + (produce_special_glyphs, create_tty_output, init_tty, delete_tty): + Likewise. + * termcap.c (tgetst1, gobble_line): Likewise. + * termhooks.h (EVENT_INIT): Likewise. + * tparam.c (tparam1): Likewise. + * unexalpha.c (unexec): Likewise. + * unexec.c (write_segment): Likewise. + * unexmacosx.c (unexec_write_zero): Likewise. + * w32fns.c (w32_wnd_proc, Fx_create_frame, x_create_tip_frame) + (Fx_file_dialog, Fsystem_move_file_to_trash): Likewise. + * w32font.c (w32font_list_family, w32font_text_extents) + (w32font_list_internal, w32font_match_internal) + (w32font_open_internal, compute_metrics, Fx_select_font): + Likewise. + * w32menu.c (set_frame_menubar, add_menu_item) + (w32_menu_display_help, w32_free_submenu_strings): Likewise. + * w32term.c (XCreateGC, w32_initialize_display_info): Likewise. + * w32uniscribe.c (uniscribe_list_family): Likewise. + * w32xfns.c (get_next_msg, post_msg, prepend_msg): Likewise. + * window.c (make_window, replace_window, set_window_buffer) + (Fsplit_window): Likewise. + * xdisp.c (init_iterator, RECORD_OVERLAY_STRING, reseat_to_string) + (add_to_log, message3, x_consider_frame_title) + (append_space_for_newline, extend_face_to_end_of_line) + (decode_mode_spec_coding, init_glyph_string): Likewise. + * xfaces.c (x_create_gc, get_lface_attributes_no_remap) + (Finternal_copy_lisp_face, Finternal_merge_in_global_face) + (face_attr_equal_p, make_realized_face, make_face_cache) + (free_realized_faces, lookup_named_face, smaller_face) + (face_with_height, lookup_derived_face) + (x_supports_face_attributes_p, Finternal_set_font_selection_order) + (Finternal_set_font_selection_order, realize_default_face) + (compute_char_face, face_at_buffer_position) + (face_for_overlay_string, face_at_string_position, merge_faces): + Likewise. + * xfns.c (xic_create_fontsetname, Fx_create_frame) + (Fx_window_property, x_create_tip_frame) + (Fx_backspace_delete_keys_p): Likewise. + * xfont.c (xfont_list, xfont_match, xfont_list_family) + (xfont_text_extents): Likewise. + * xmenu.c (set_frame_menubar, xmenu_show): Likewise. + * xrdb.c (magic_file_p, x_get_resource): Likewise. + * xselect.c (x_queue_event, x_get_window_property) + (receive_incremental_selection): Likewise. + * xsmfns.c (x_session_check_input): Likewise. + * xterm.c (x_send_scroll_bar_event, SET_SAVED_MENU_EVENT) + (handle_one_xevent, x_check_errors, xim_initialize, x_term_init): + Likewise. + * character.h (BCOPY_SHORT): Removed. + * config.in: Regenerate. + * dispnew.c (safe_bcopy): Only define as dummy if PROFILING. + * emacs.c (main) [PROFILING]: Don't declare + dump_opcode_frequencies. + * lisp.h (safe_bcopy): Remove declaration. + (memset) [!HAVE_MEMSET]: Declare. + (memcpy) [!HAVE_MEMCPY]: Likewise. + (memmove) [!HAVE_MEMMOVE]: Likewise. + (memcmp) [!HAVE_MEMCMP]: Likewise. + * s/ms-w32.h (bzero, bcopy, bcmp, GAP_USE_BCOPY) + (BCOPY_UPWARD_SAFE, BCOPY_DOWNWARD_SAFE, HAVE_BCOPY, HAVE_BCMP): + Don't define. + (HAVE_MEMCMP, HAVE_MEMCPY, HAVE_MEMMOVE, HAVE_MEMSET): Define. + * s/msdos.h (GAP_USE_BCOPY, BCOPY_UPWARD_SAFE) + (BCOPY_DOWNWARD_SAFE): Don't define. + * sysdep.c (memset) [!HAVE_MEMSET]: Define. + (memcpy) [!HAVE_MEMCPY]: Define. + (memmove) [!HAVE_MEMMOVE]: Define. + (memcmp) [!HAVE_MEMCMP]: Define. + +2010-07-07 Jan Djärv + + * process.c (kbd_is_on_hold): New variable. + (hold_keyboard_input, unhold_keyboard_input, kbd_on_hold_p): New + functions. + (wait_reading_process_output): If kbd_on_hold_p returns non-zero, + select on empty input mask. + (init_process): Initialize kbd_is_on_hold to 0. + + * process.h (hold_keyboard_input, unhold_keyboard_input) + (kbd_on_hold_p): Declare. + + * keyboard.c (input_available_signal): Declare. + (kbd_buffer_nr_stored): New function. + (kbd_buffer_store_event_hold): If kbd_buffer_nr_stored returns + more than KBD_BUFFER_SIZE/2, stop reding input (Bug#6571). + (kbd_buffer_get_event): If input is suspended and kbd_buffer_nr_stored + returns less than KBD_BUFFER_SIZE/4, resume reding input (Bug#6571). + (tty_read_avail_input): If input is on hold, return. + Don't read more that free slots in kbd_buffer (Bug#6571). + +2010-07-07 Eli Zaretskii + + * msdos.h: + * msdos.c: + * dosfns.c: + * w16select.c: Convert function definitions to ANSI C. + + * msdos.h (ctrl_break_func, install_ctrl_break_check): Remove + unused prototypes. + +2010-07-07 Juanma Barranquero + + * coding.c, sysdep.c: Convert some more functions to standard C. + +2010-07-07 Juanma Barranquero + + * coding.c (decode_coding_gap, encode_coding_gap, decode_coding_object) + (encode_coding_object): Use SPECPDL_INDEX. + (syms_of_coding): Use DOS_NT. + +2010-07-07 Dan Nicolaescu + + * intervals.h (interval): Use EMACS_UINT instead of unsigned EMACS_INT. + + Make the function member of Lisp_Subr use standard C prototypes. + * lisp.h (struct Lisp_Subr): Use a union for the function member. + (DECL_ALIGN): Add a cast for the function. + * eval.c (Feval, Ffuncall): Use the proper type for each type + function call. + +2010-07-06 Chong Yidong + + * fringe.c (draw_fringe_bitmap_1): Use lookup_named_face to get + fringe face id, so face-remapping-alist works (Bug#6091). + +2010-07-06 Juanma Barranquero + + * w32.c, w32console.c, w32fns.c, w32font.c, w32heap.c, w32inevt.c + * w32menu.c, w32proc.c, w32reg.c, w32select.c, w32term.c + * w32uniscribe.c, w32xfns.c: Convert function definitions to standard C. + +2010-07-06 Andreas Schwab + + * xterm.c (x_get_keysym_name): Change type of parameter to int. + * lisp.h: Declare x_get_keysym_name. + * keyboard.c (modify_event_symbol): Don't declare + x_get_keysym_name here. + +2010-07-06 Dan Nicolaescu + + * ecrt0.c: Revert conversion to standard C. + +2010-07-05 Dan Nicolaescu + + * vm-limit.c (memory_warnings): + * keyboard.c (modify_event_symbol): + * floatfns.c (rounding_driver, ceiling2, floor2, truncate2) + (round2, emacs_rint): + * process.c (send_process, old_sigpipe): Convert function + definitions and declarations to standard C. + +2010-07-05 Juanma Barranquero + + * buffer.c, cm.c, eval.c, keyboard.c, process.c, term.c, vm-limit.c, + * xdisp.c: Convert function definitions to standard C. + + * cm.c (cmputc): Arg C is now int, not char. + * process.c (Fmake_network_process): Cast sockaddr_in* to sockaddr*. + +2010-07-05 James Cloos + + * xterm.h (Xatom_net_wm_name, Xatom_net_wm_icon_name): New. + + * xterm.c (x_term_init): Intern the _NET_WM_NAME and + _NET_WM_ICON_NAME atoms. + + * xfns.c (x_set_name_internal): Set the EWMH _NET_WM_NAME + and _NET_WM_ICON_NAME properties, too, matching what is + done in the Gtk+ case. + +2010-07-05 Jan Djärv + + * xterm.c (XTring_bell, XTset_terminal_window): Fix wrong prototype. + + * xsmfns.c (SSDATA): New macro. + (smc_save_yourself_CB, x_session_initialize): Use SSDATA for strings + passed to strlen/strcpy/strcat. + (create_client_leader_window): Surround with #ifndef USE_GTK. Cast + 7:th arg to XChangeProperty to (unsigned char *) + + * xsettings.c (something_changedCB, parse_settings) + (apply_xft_settings): Reformat prototype. + (something_changedCB, init_gconf): Remove unused variable i. + (read_settings): Remove unused variable long_len. + + * gtkutil.c (xg_get_pixbuf_from_pix_and_mask) + (xg_get_image_for_pixmap, create_dialog) + (xg_get_file_with_selection, xg_get_file_name, update_cl_data) + (menuitem_highlight_callback, make_menu_item) + (xg_create_one_menuitem, create_menus, xg_update_menu_item) + (xg_create_scroll_bar, xg_update_scrollbar_pos) + (xg_set_toolkit_scroll_bar_thumb, xg_tool_bar_button_cb) + (xg_tool_bar_proxy_help_callback, xg_tool_bar_detach_callback) + (xg_tool_bar_attach_callback, xg_tool_bar_help_callback) + (xg_tool_bar_item_expose_callback): Reformat prototype. + (xg_update_menubar): GList *group => GSList *group. + (xg_modify_menubar_widgets): Initialize witem to 0, check witem != 0 + before use. + (update_frame_tool_bar): 4:th param to xg_get_image_for_pixmap changed + to GTK_IMAGE (wimage). + +2010-07-05 Dan Nicolaescu + + * atimer.c: Use "" instead of <> for local includes for + consistency with the rest of the code. + + * xsmfns.c (smc_save_yourself_CB, smc_error_handler): + * xrdb.c (get_system_name): + * window.c (shrink_windows): + * syntax.c (forw_comment): + * scroll.c (calculate_scrolling, calculate_direct_scrolling) + (ins_del_costs): + * mem-limits.h (start_of_data): + * lread.c (readevalloop): + * gtkutil.c (xg_dialog_response_cb, xg_get_file_with_chooser) + (xg_get_file_with_selection, xg_update_menubar, xg_update_submenu): + * frame.c (x_get_focus_frame): + * floatfns.c (fmod_float): + * fileio.c (choose_write_coding_system): + * emacs.c (fatal_error_signal, init_cmdargs, argmatch) + (malloc_initialize_hook, sort_args, synchronize_locale): + * doprnt.c (doprnt): + * dired.c (compile_pattern): + * data.c (fmod_float): + * chartab.c (map_sub_char_table, map_sub_char_table_for_charset) + (map_char_table_for_charset): + * charset.c (define_charset_internal): + * alloc.c (Fgarbage_collect): Convert declarations or definitions + to standard C. + +2010-07-04 Tetsurou Okazaki (tiny change) + Stefan Monnier + + * lread.c (read1): Fix up last change to not mess up `c'. + +2010-07-04 Juanma Barranquero + + * strftime.c: Revert conversion to standard C (2010-07-04T07:50:25Z!dann@ics.uci.edu). + +2010-07-04 Juanma Barranquero + + Fix prototypes. + + * atimer.c (start_atimer): Use EMACS_TIME, not struct timeval. + * dired.c (file_name_completion_stat): Use DIRENTRY, not struct dirent. + * fileio.c (read_non_regular, read_non_regular_quit): Add Lisp_Object + arg, as required by internal_condition_case_1. + * print.c (strout): Use const char* for arg PTR. + * regex.c (bcmp_translate): Use RE_TRANSLATE_TYPE, not Lisp_Object. + (analyse_first): Fix "const const". + * sysdep.c (set_file_times): Use EMACS_TIME, not struct timeval. + * unexelf.c (round_up, find_section): Use ElfW macro for arguments. + * xgselect.c (xg_select): Use SELECT_TYPE, EMACS_TIME. + +2010-07-04 Dan Nicolaescu + + * alloc.c: Convert function definitions to standard C. + * atimer.c: + * bidi.c: + * bytecode.c: + * callint.c: + * callproc.c: + * casefiddle.c: + * casetab.c: + * category.c: + * ccl.c: + * character.c: + * charset.c: + * chartab.c: + * cmds.c: + * coding.c: + * composite.c: + * data.c: + * dbusbind.c: + * dired.c: + * dispnew.c: + * doc.c: + * doprnt.c: + * ecrt0.c: + * editfns.c: + * fileio.c: + * filelock.c: + * filemode.c: + * fns.c: + * font.c: + * fontset.c: + * frame.c: + * fringe.c: + * ftfont.c: + * ftxfont.c: + * gtkutil.c: + * indent.c: + * insdel.c: + * intervals.c: + * keymap.c: + * lread.c: + * macros.c: + * marker.c: + * md5.c: + * menu.c: + * minibuf.c: + * prefix-args.c: + * print.c: + * ralloc.c: + * regex.c: + * region-cache.c: + * scroll.c: + * search.c: + * sound.c: + * strftime.c: + * syntax.c: + * sysdep.c: + * termcap.c: + * terminal.c: + * terminfo.c: + * textprop.c: + * tparam.c: + * undo.c: + * unexelf.c: + * window.c: + * xfaces.c: + * xfns.c: + * xfont.c: + * xftfont.c: + * xgselect.c: + * xmenu.c: + * xrdb.c: + * xselect.c: + * xsettings.c: + * xsmfns.c: + * xterm.c: Likewise. + +2010-07-03 Eli Zaretskii + + * msdos.c (IT_set_frame_parameters): Fix setting of colors in + frames other than the initial one. Fix reversal of colors when + `reverse' is specified in the frame parameters. Call + update_face_from_frame_parameter instead of + internal-set-lisp-face-attribute. Initialize screen colors from + initial_screen_colors[] when f->default_face_done_p is zero, + instead of depending on being called with default-frame-alist as + the alist argument. + + * xfaces.c (update_face_from_frame_parameter): Move out of + HAVE_WINDOW_SYSTEM portion. Condition window-system only parts + with HAVE_WINDOW_SYSTEM. + + * msdos.c (IT_set_frame_parameters): Set menu-bar-lines according + to menu-bar-mode, if not set in the frame parameters or in + default-frame-alist. + + * w32console.c (sys_tputs): Adjust argument list to prototype in + term.c. + +2010-07-03 Juanma Barranquero + + * lisp.h (memory_warnings): Fix prototype. + + * cm.h (evalcost): Fix prototype. + + * cm.c (evalcost): Fix arg type. + +2010-07-02 Dan Nicolaescu + + * term.c (term_clear_mouse_face, Fidentity): + * syssignal.h (signal_handler_t): + * lisp.h (memory_warnings): + * coding.h (preferred_coding_system): + * cm.h (evalcost): + * blockinput.h (reinvoke_input_signal): Convert to standard C prototypes. + +2010-07-02 Eli Zaretskii + + * dosfns.h (msdos_stdcolor_idx, msdos_stdcolor_name): Remove P_ + from prototypes. + + * msdos.h (load_pixmap): Don't define away. + +2010-07-02 Jan Djärv + + * lisp.h: + * atimer.h: Remove define for P_. + + * alloc.c: Remove __P and P_ from .c and .m files. + * atimer.c: + * buffer.c: + * callint.c: + * category.c: + * charset.c: + * chartab.c: + * cm.c: + * coding.c: + * composite.c: + * data.c: + * dired.c: + * dispnew.c: + * doc.c: + * editfns.c: + * emacs.c: + * eval.c: + * fileio.c: + * filelock.c: + * fns.c: + * font.c: + * fontset.c: + * frame.c: + * ftfont.c: + * ftxfont.c: + * gmalloc.c: + * gtkutil.c: + * image.c: + * indent.c: + * intervals.c: + * keyboard.c: + * keymap.c: + * lread.c: + * marker.c: + * menu.c: + * minibuf.c: + * print.c: + * process.c: + * scroll.c: + * search.c: + * sound.c: + * strftime.c: + * syntax.c: + * sysdep.c: + * term.c: + * terminal.c: + * textprop.c: + * unexalpha.c: + * w32console.c: + * w32fns.c: + * w32font.c: + * w32menu.c: + * w32term.c: + * w32uniscribe.c: + * window.c: + * xdisp.c: + * xfaces.c: + * xfns.c: + * xfont.c: + * xftfont.c: + * xmenu.c: + * xselect.c: + * xterm.c: Likewise. + + Remove P_ and __P macros. + * atimer.h: Remove P_ and __P macros. + * buffer.h: + * category.h: + * ccl.h: + * character.h: + * charset.h: + * cm.h: + * coding.h: + * composite.h: + * dispextern.h: + * disptab.h: + * dosfns.h: + * font.h: + * fontset.h: + * frame.h: + * gtkutil.h: + * indent.h: + * intervals.h: + * keyboard.h: + * keymap.h: + * lisp.h: + * macros.h: + * md5.h: + * menu.h: + * msdos.h: + * nsterm.h: + * puresize.h: + * region-cache.h: + * syntax.h: + * syssignal.h: + * systime.h: + * termhooks.h: + * w32font.h: + * w32term.h: + * widget.h: + * window.h: + * xgselect.h: + * xsettings.h: + * xterm.h: Likewise. + +2010-07-02 Dan Nicolaescu + + * lisp.h: Document that USE_LISP_UNION_TYPE is now enabled using autoconf. + + Cleanup old code. + * dired.c (BSD4_3): Remove all uses, redundant with BSD4_2. + * syssignal.h: Remove code for Lynx, not supported anymore. + * vm-limit.c: Remove unused code the depends on emacs not being + defined and NO_LIM_DATA being defined. + * mem-limits.h: Remove dead code. + +2010-07-01 Jan Djärv + + * window.c (Fwindow_absolute_pixel_edges): Doc fix. + + * window.c (calc_absolute_offset, Fwindow_absolute_pixel_edges) + (Fwindow_inside_absolute_pixel_edges): New functions (bug#5721). + + * nsfns.m (compute_tip_xy): Do not convert coordinates from frame + parameters, they are already absolute. + + * nsterm.m (x_set_window_size, initFrameFromEmacs): Renamed + FRAME_NS_TOOLBAR_HEIGHT to FRAME_TOOLBAR_HEIGHT. + + * nsterm.h (FRAME_NS_TOOLBAR_HEIGHT): Rename to FRAME_TOOLBAR_HEIGH + + * nsmenu.m (update_frame_tool_bar, free_frame_tool_bar): Update + FRAME_TOOLBAR_HEIGHT. + + * nsmenu.m (free_frame_tool_bar, update_frame_tool_bar): Add + BLOCK/UNBLOCK_INPUT so asserts don't trigger. + +2010-06-30 Chong Yidong + + * frame.c (get_future_frame_param, Fmake_terminal_frame): Don't + check default-frame-alist. + +2010-06-30 Andreas Schwab + + * process.c (create_process): Avoid using invalid file descriptors. + + * callproc.c (child_setup): Avoid closing a file descriptor twice. + +2010-06-30 Jan Djärv + + * xsettings.c (Ffont_get_system_normal_font, Ffont_get_system_font): + Improve documentation. Return font regardless of use_system_font. + (syms_of_xsettings): Improve documentation for font-use-system-font. + - 2009-06-17 Naohiro Aota (tiny change) + 2010-07-10 Chong Yidong + - * xfaces.c (realize_face): Garbage the frame if a face is removed - (Bug#6593). ++ * xfaces.c (realize_face): Garbage the frame if a face is removed ++ (Bug#6593). ++ ++2010-07-05 Andreas Schwab ++ ++ * keyboard.c: Remove duplicate . ++ (read_key_sequence): Remove volatile qualifiers. ++ ++2010-07-05 YAMAMOTO Mitsuharu ++ ++ * dispextern.h (FRINGE_HEIGHT_BITS): New define. ++ (struct glyph_row): New members left_fringe_offset and ++ right_fringe_offset. ++ ++ * xterm.c (x_draw_fringe_bitmap): Don't clip bottom aligned bitmap ++ specially. ++ * w32term.c (w32_draw_fringe_bitmap): Likewise. ++ * nsterm.m (ns_draw_fringe_bitmap): Likewise. ++ ++ * fringe.c (draw_fringe_bitmap_1): Don't clip bitmap here. ++ Take account of bitmap offset. ++ (draw_window_fringes): Take account of window vscroll. ++ (update_window_fringes): Likewise. Extend top-aligned top indicator ++ or bottom-aligned bottom indicator to adjacent rows if it doesn't fit ++ in one row. Don't set redraw_fringe_bitmaps_p outside row comparison. ++ Set left_fringe_offset and right_fringe_offset (Bug#5634, Bug#6325). ++ ++2010-07-04 Juanma Barranquero ++ ++ * w32fns.c (Qtooltip): Declare. ++ Suggested by Andy Moreton . ++ ++2010-07-03 Jan Djärv ++ ++ * xmenu.c (x_activate_menubar): Send Press/Release for Gtk+ to avoid ++ grab on just Press (Bug#6499). ++ ++2010-07-02 Chong Yidong ++ ++ * frame.c (Qtooltip): New var. ++ (delete_frame): Use it. Fix faulty if statement. Don't update ++ mode line for tooltip frames. Suggested by Martin Rudalics. ++ ++ * xfns.c (x_create_tip_frame): ++ * w32fns.c (x_create_tip_frame): Use it. ++ ++2010-06-17 Naohiro Aota (tiny change) + + * xftfont.c (xftfont_open): Check font width one by one also when + spacing is dual. + + * ftfont.c (ftfont_open): Ditto. + +2010-06-30 Glenn Morris + + * s/sol2-6.h (INHIBIT_X11R6_XIM): Remove, handled by configure now. + + * Makefile.in (CANNOT_DUMP): Update for configure name change. + + * s/freebsd.h (USE_MMAP_FOR_BUFFERS): + * s/irix6-5.h (USE_MMAP_FOR_BUFFERS): + * s/darwin.h (SYSTEM_MALLOC): + * s/sol2-10.h (SYSTEM_MALLOC): Move to configure. + +2010-06-29 Jan Djärv + + * nsfns.m: extern declare Vmenu_bar_mode, Vtool_bar_mode. + (ns_get_screen): Don't assign integer to f. + (Fx_display_color_cells): Declarations before statements. + +2010-06-28 Jan Djärv + + * xfns.c (x_default_font_parameter): Remove got_from_system + (Bug#6526). + + * xterm.h (gtk_widget_get_window, gtk_widget_get_mapped) + (gtk_adjustment_get_page_size, gtk_adjustment_get_upper): New + defines based on what configure finds. + + * xterm.c (XTflash): Use gtk_widget_get_window. + (xg_scroll_callback): Use gtk_adjustment_get_upper and + gtk_adjustment_get_page_size. + (handle_one_xevent): Use gtk_widget_get_mapped. + (x_term_init): Remove HAVE_GTK_MULTIDISPLAY and associated error + messages. + + * xmenu.c (create_and_show_popup_menu): Call gtk_widget_get_mapped. + + * gtkutil.h: Replace HAVE_GTK_FILE_BOTH with + HAVE_GTK_FILE_SELECTION_NEW. + + * gtkutil.c (xg_display_open, xg_display_close): Remove + HAVE_GTK_MULTIDISPLAY, it is always defined. + (xg_display_open): Return type is void. + (gtk_widget_set_has_window) + (gtk_dialog_get_action_area, gtk_dialog_get_content_area) + (gtk_widget_get_sensitive, gtk_adjustment_set_page_size) + (gtk_adjustment_set_page_increment) + (gtk_adjustment_get_step_increment): #define these if not found + by configure. + (remove_submenu): New define based on Gtk+ version. + (xg_set_cursor, xg_frame_resized, xg_event_is_for_scrollbar): Use + gtk_widget_get_window. + (xg_frame_resized, xg_update_frame_menubar): Use gtk_widget_get_mapped. + (xg_create_frame_widgets): Use gtk_widget_set_has_window. + (create_dialog): Use gtk_dialog_get_action_area and + gtk_dialog_get_content_area. + (xg_uses_old_file_dialog, xg_get_file_name): Remove HAVE_GTK_FILE_BOTH + and HAVE_GTK_FILE_CHOOSER_DIALOG_NEW. File chooser is always + available, so checking for HAVE_GTK_FILE_SELECTION_NEW is enough. + (xg_update_menubar, xg_update_submenu, xg_show_toolbar_item): Use + g_object_ref and g_object_unref. + (xg_update_menu_item, xg_tool_bar_menu_proxy): Use + gtk_widget_get_sensitive. + (xg_update_submenu): Use remove_submenu. + (xg_update_scrollbar_pos): Don't use GtkFixedChild, use child + properties instead to get old x and y position. + (xg_set_toolkit_scroll_bar_thumb): Use gtk_adjustment_get_page_size, + gtk_adjustment_get_step_increment, gtk_adjustment_set_page_size, + gtk_adjustment_set_step_increment and gtk_adjustment_set_page_increment. + (xg_get_tool_bar_widgets): New function. + (xg_tool_bar_menu_proxy, xg_show_toolbar_item) + (update_frame_tool_bar): Call xg_get_tool_bar_widgets. + (toolbar_set_orientation): New #define based on if configure + finds gtk_orientable_set_orientation. + (xg_create_tool_bar): Call toolbar_set_orientation. + (xg_make_tool_item, xg_show_toolbar_item): Call gtk_box_pack_start + instead of gtk_box_pack_start_defaults. + +2010-06-28 Chong Yidong + + * cmds.c (Fdelete_backward_char): Move into Lisp. + +2010-06-27 Dan Nicolaescu + + * s/freebsd.h (BSD4_2): Remove redundant definition. + bsd-common.h defines it already. + +2010-06-27 Chong Yidong + + * xfns.c (Fx_create_frame): Don't consult X resouces when setting + menu-bar-lines and tool-bar-lines. Use menu-bar-mode and + tool-bar-mode, which are now set using these X resources at + startup, to determine the defaults (Bug#2249). + + * w32fns.c (Fx_create_frame): + * nsfns.m (Fx_create_frame): Likewise. + + * frame.c (Vmenu_bar_mode, Vtool_bar_mode): New vars. + +2010-06-24 Juanma Barranquero + + * gtkutil.c (xg_update_scrollbar_pos): + Avoid C99 mid-block variable declaration. + +2010-06-22 Jan Djärv + + * xterm.c (x_scroll_bar_create): Remove call to xg_show_scroll_bar. + + * gtkutil.h (xg_show_scroll_bar): Remove. + + * gtkutil.c (xg_update_scrollbar_pos): Show/hide scroll bar as needed + if height is less than scroll bar min size. + (xg_show_scroll_bar): Remove, show moved to xg_update_scrollbar_pos. + + * xfns.c (x_default_font_parameter): Try to open font from system + before using it (bug#6478). Rename got_from_gconf to got_from_system. + +2010-06-22 Keith Packard (tiny change) + + * font.c (font_parse_fcname): Allow . for sizes like 7.5 (bug#6437). + +2010-06-20 Eli Zaretskii + + * xdisp.c (try_scrolling): When scroll-conservatively is set to + most-positive-fixnum, be extra accurate when scrolling window + start, to avoid missing the cursor line. + +2010-06-19 Eli Zaretskii + + * xdisp.c (try_scrolling): Compute the limit for searching point + in forward scroll from scroll_max, instead of an arbitrary limit + of 10 screen lines. See + http://lists.gnu.org/archive/html/emacs-devel/2010-06/msg00766.html + and + http://lists.gnu.org/archive/html/emacs-devel/2010-06/msg00773.html + for details. + +2010-06-16 Glenn Morris + + * editfns.c (Fbyte_to_string): Pacify compiler. + +2010-06-16 Stefan Monnier + + * lread.c (read1): Phase out old-style backquotes a bit more. + +2010-06-12 Eli Zaretskii + + * makefile.w32-in ($(BLD)/bidi.$(O)): Depend on biditype.h and + bidimirror.h. + + * deps.mk (bidi.o): Depend on biditype.h and bidimirror.h. + + * bidi.c (bidi_initialize): Remove explicit initialization of + bidi_type_table; include biditype.h instead. Don't support + entries whose second codepoint is zero. Initialize bidi_mirror_table. + (bidi_mirror_char): Use bidi_mirror_table. + + * biditype.h: New file. + + * bidimirror.h: New file. + + * window.c (syms_of_window): Doc fix (bug#6409). + +2010-06-12 Romain Francoise + + * Makefile.in (lisp, shortlisp): Use new location of vc-hooks and + ediff-hook. + +2010-06-10 Glenn Morris + + * editfns.c (Fbyte_to_string): Pacify compiler. + + * m/ibms390x.h: Rather than duplicating ibms390.h, just include it. + ++2010-06-26 Andreas Schwab ++ ++ * alloc.c (Fmake_byte_code): Don't access undefined argument ++ (Bug#6517). ++ ++2010-06-25 Chong Yidong ++ ++ * xdisp.c (next_element_from_image): Ensure that after-strings are ++ read the next time we hit handle_stop (Bug#1336). ++ ++2010-06-23 Andreas Schwab ++ ++ * lread.c (read1): Signal error if #s is not followed by paren. ++ ++2010-06-19 Chong Yidong ++ ++ * image.c (free_image): Mark frame as garbaged (Bug#6426). ++ ++ * keymap.c (Fdefine_key): Doc fix (Bug#6460). ++ ++2010-06-15 Glenn Morris ++ ++ * editfns.c (Fbyte_to_string): Pacify compiler. ++ +2010-06-09 Stefan Monnier + + * dbusbind.c (xd_append_arg): Don't "make-unibyte" the string. + Check `object's type before accessing its guts. + +2010-06-09 Dan Nicolaescu + + * s/usg5-4.h: Fix previous change. + Suggested by Lawrence Mitchell + +2010-06-08 Andreas Schwab + + * minibuf.c (Fall_completions): Add more checks. + +2010-06-08 Juanma Barranquero + + * minibuf.c (Fall_completions): Check COLLECTION's size (bug#6378). + +2010-06-08 Dan Nicolaescu + + * lread.c (X_OK): Remove, unused. + + * dispnew.c: Remove obsolete comment. + + Remove INCLUDED_FCNTL. + * xterm.c (INCLUDED_FCNTL): + * callproc.c (INCLUDED_FCNTL): + * alloc.c (INCLUDED_FCNTL): + * systty.h (INCLUDED_FCNTL): Remove all uses, not needed anymore. + (emacs_get_tty, emacs_set_tty): Declare unconditionally. + +2010-06-07 Martin Rudalics + + * window.c (Fselect_window): Move `record_buffer' up to the + beginning of this function, so the buffer gets recorded + even if the selected window does not change. + http://lists.gnu.org/archive/html/emacs-devel/2010-06/msg00137.html + +2010-06-07 Juanma Barranquero + + * cmds.c (Fforward_char, Fbackward_char): Fix typos in docstrings. + (Fforward_line, Fbeginning_of_line): Reflow docstrings. + +2010-06-06 Dan Nicolaescu + + Remove BSTRING related code, all platforms define it. + * s/usg5-4.h (BSTRING): Remove definition. + * s/template.h (BSTRING): + * s/msdos.h (BSTRING): + * s/ms-w32.h (BSTRING): + * s/hpux10-20.h (BSTRING): + * s/gnu-linux.h (BSTRING): + * s/darwin.h (BSTRING): + * s/cygwin.h (BSTRING): + * s/bsd-common.h (BSTRING): + * s/aix4-2.h (BSTRING): Likewise. + * sysdep.c: Remove code depending on BSTRING not being defined. + +2010-06-05 Juanma Barranquero + + Remove obsolete macro BASE_LEADING_CODE_P. + * character.h (BASE_LEADING_CODE_P): Remove. + * regex.c [!emacs] (BASE_LEADING_CODE_P): Remove. + * buffer.c (Fset_buffer_multibyte): + * indent.c (scan_for_column, compute_motion): + * insdel.c (count_combining_before, count_combining_after): + Use LEADING_CODE_P instead of BASE_LEADING_CODE_P. + +2010-06-04 Juanma Barranquero + + Turn `directory-sep-char' into a noop. + + * lisp.h [WINDOWSNT] (Vdirectory_sep_char): Don't declare. + (DIRECTORY_SEP): Define unconditionally. + + * s/ms-w32.h (DIRECTORY_SEP): Remove. + + * emacs.c (decode_env_path): Don't check DIRECTORY_SEP, + call dostounix_filename directly. + + * fileio.c (CORRECT_DIR_SEPS): Remove. + (Ffile_name_directory, directory_file_name, Fexpand_file_name) + (Fsubstitute_in_file_name): Use dostounix_filename instead. + (file_name_as_directory): Use dostounix_filename, DIRECTORY_SEP. + (syms_of_fileio) : Move to subr.el. + + * w32proc.c (CORRECT_DIR_SEPS): Remove. + (Fw32_short_file_name, Fw32_long_file_name): Use dostounix_filename. + +2010-06-03 Andreas Schwab + + * process.c (conv_lisp_to_sockaddr): Fix conversion of IPv4 + address. (Bug#6346) + +2010-06-03 Juanma Barranquero + + * ccl.c (Fccl_program_p): Fix typo in docstring. + +2010-06-03 Dan Nicolaescu + + Move UNEXEC definition to autoconf. + * s/usg5-4.h (UNEXEC): Remove, move to configure.in. + * s/sol2-10.h (UNEXEC): + * s/irix6-5.h (UNEXEC): + * s/hpux10-20.h (UNEXEC): + * s/gnu-linux.h (UNEXEC): + * s/darwin.h (UNEXEC): + * s/cygwin.h (UNEXEC): + * s/bsd-common.h (UNEXEC): + * s/aix4-2.h (UNEXEC): + * m/alpha.h (UNEXEC): Likewise. + * Makefile.in (UNEXEC_OBJ): Define using @UNEXEC_OBJ@. + +2010-06-03 Juanma Barranquero + + Remove obsolete pre-unicode2 macros. + * character.h (MULTIBYTE_FORM_LENGTH, PARSE_MULTIBYTE_SEQ): Remove. + * composite.c (composition_reseat_it): + * data.c (Faset): + * fns.c (Ffillarray): + * regex.c (re_search_2): Use BYTES_BY_CHAR_HEAD. + [!emacs] (BYTES_BY_CHAR_HEAD): Define instead of MULTIBYTE_FORM_LENGTH. + +2010-06-03 Juri Linkov + + * buffer.c (Fother_buffer): Add CHECK_FRAME. + (Fswitch_to_buffer): Remove unused variable `err'. + +2010-06-03 Glenn Morris + + * m/template.h (NO_SOCK_SIGIO): Remove, no longer used. + + * m/hp800.h (alloca) [__NetBSD__ && __GNUC__]: No need to define it, + now that AH_BOTTOM does it. + + * m/hp800.h (HAVE_ALLOCA): + * m/ibms390x.h (HAVE_ALLOCA): Do not define, no longer needed. + + * m/ia64.h, s/gnu-linux.h, s/gnu.h, s/netbsd.h, s/usg5-4.h: + Remove NOT_C_CODE tests, it is always true now. + +2010-06-02 Dan Nicolaescu + + Fix config.h includes. + * xsettings.c: + * xgselect.c: + * nsterm.m: + * nsselect.m: + * nsimage.m: + * nsfont.m: + * nsfns.m: + * dbusbind.c: Use #include instead of "config.h" as all + other files do. + + * gmalloc.c: Remove BROKEN_PROTOTYPES reference, unused. + + * s/sol2-6.h: Remove obsolete comments. + + Remove unnecessary alloca.h includes. + * keymap.c: Do not include alloca.h, config.h does that. + * sysdep.c: Likewise. Do not define fwrite, not used. + +2010-06-01 Stefan Monnier + + * sysdep.c (child_setup_tty): Move the non-canonical initialization to + the HAVE_TERMIO where it belongs (bug#6149). + +2010-05-31 Stefan Monnier + + * keymap.c (Fwhere_is_internal): Fix handling of remapping (in thread + of bug#6305). + +2010-05-30 Eli Zaretskii + + * bidi.c (bidi_move_to_visually_next): Make sure the sentinel + state is always cached (bug#6306). + +2010-05-29 Eli Zaretskii + + Fix cursor motion in bidi-reordered continued lines. + * xdisp.c (try_cursor_movement): Backup to non-continuation line + only after finding point's row. Fix the logic. Rewrite the loop + over continuation lines in bidi-reordered buffers. Return + CURSOR_MOVEMENT_MUST_SCROLL upon failure to find a suitable row, + rather than CURSOR_MOVEMENT_CANNOT_BE_USED. + +2010-05-28 Michael Albinus + + * fileio.c (Fdelete_file): Pass TRASH arg to handler call. + +2010-05-28 Kenichi Handa + + * font.c (font_delete_unmatched): Check Vface_ignored_fonts. + Don't sheck SPEC if it is nil. + (font_list_entities): Call font_delete_unmatched if + Vface_ignored_fonts is non-nil. (Bug#6287) + +2010-05-28 Glenn Morris + + * Makefile.in (LIBES): Remove $LOADLIBES, it is never set. + +2010-05-27 Chong Yidong + + * fileio.c (Fdelete_file): Change meaning of optional arg to mean + whether to trash. + (internal_delete_file, Frename_file): Callers changed. + (delete_by_moving_to_trash): Doc fix. + (Fdelete_directory_internal): Don't move to trash. + + * callproc.c (delete_temp_file): + * buffer.c (Fkill_buffer): Callers changed. + + * lisp.h: Update prototype. + +2010-05-27 Chong Yidong + + * xdisp.c (redisplay_window): After redisplay, check if point is + still valid before setting it (Bug#6177). + +2010-05-27 Glenn Morris -2010-07-05 Andreas Schwab + * Makefile.in, autodeps.mk, deps.mk, ns.mk: + Convert comments to Makefile format. - * keyboard.c: Remove duplicate . - (read_key_sequence): Remove volatile qualifiers. + * Makefile.in (bootstrap-clean): No more Makefile.c. -2010-07-05 YAMAMOTO Mitsuharu +2010-05-26 Glenn Morris - * dispextern.h (FRINGE_HEIGHT_BITS): New define. - (struct glyph_row): New members left_fringe_offset and - right_fringe_offset. + * Makefile.in (YMF_PASS_LDFLAGS): Remove. + (temacs${EXEEXT}): Use PRE_EDIT_LDFLAGS, POST_EDIT_LDFLAGS. + + * Makefile.in (NS_IMPL_GNUSTEP_INC, NS_IMPL_GNUSTEP_TEMACS_LDFLAGS): + Remove. + (TEMACS_LDFLAGS): Do not use NS_IMPL_GNUSTEP_TEMACS_LDFLAGS. + +2010-05-26 Kenichi Handa + + * composite.c (composition_compute_stop_pos): Fix condition for + backward scanning. + +2010-05-25 Glenn Morris + + * Makefile.in (@NS_IMPL_GNUSTEP_INC@, NS_IMPL_GNUSTEP_TEMACS_LDFLAGS): + Move before TEMACS_LDFLAGS. + (TEMACS_LDFLAGS): Use $NS_IMPL_GNUSTEP_TEMACS_LDFLAGS. + (temacs${EXEEXT}): Do not use $NS_IMPL_GNUSTEP_TEMACS_LDFLAGS. + + * Makefile.in (NOT_C_CODE): No longer define. + (config.h): No longer include. + + * Makefile.in (LD_SWITCH_SYSTEM_TEMACS): Move definition after some + variables it may reference. + + * Makefile.in (LD_SWITCH_SYSTEM_EXTRA): Remove. + (TEMACS_LDFLAGS): Remove LD_SWITCH_SYSTEM_EXTRA. + +2010-05-25 Kenichi Handa + + * dispextern.h (struct composition_it): New members rule_idx and + charpos. + + * xdisp.c (set_iterator_to_next): While scanning backward, assume + that the character positions of IT point the last character of the + current grapheme cluster. + (next_element_from_composition): Don't change character positions + of IT. + (append_composite_glyph): Set glyph->charpos to + it->cmp_it.charpos. + + * composite.c (autocmp_chars): Change the first argument to RULE, + and try composition with RULE only. + (composition_compute_stop_pos): Record the index number of the + composition rule in CMP_IT->rule_idx. + (composition_reseat_it): Call autocmp_chars repeatedly until the + correct rule of the composition is found. + (composition_update_it): Set CMP_IT->charpos. Assume the CHARPOS + is at the last character of the current grapheme cluster when + CMP_IT->reversed_p is nonzero. + +2010-05-24 Stefan Monnier + + * editfns.c (Fbyte_to_string): New function. + +2010-05-24 Stefan Monnier + + * process.c (Fmake_network_process): Set :host to nil if it's not used. + Suggested by Masatake YAMATO . + +2010-05-23 Eli Zaretskii + + * dispextern.h (init_iterator): Sync prototype with changed definition. + +2010-05-20 enami tsugutomo + + * s/netbsd.h: If terminfo is found, use it in preference to + termcap. (Bug#6190) [Backport from trunk] + +2010-05-19 Eli Zaretskii + + Redesign and reimplement bidi-aware edge positions of glyph rows. + + * dispextern.h (struct glyph_row): New members minpos and maxpos. + (MATRIX_ROW_START_CHARPOS, MATRIX_ROW_START_BYTEPOS) + (MATRIX_ROW_END_CHARPOS, MATRIX_ROW_END_BYTEPOS): Reference minpos + and maxpos members instead of start.pos and end.pos, respectively. + + * xdisp.c (display_line): Compare IT_CHARPOS with the position in + row->start.pos, rather than with MATRIX_ROW_START_CHARPOS. + (cursor_row_p): Use row->end.pos rather than MATRIX_ROW_END_CHARPOS. + (try_window_reusing_current_matrix, try_window_id): + Use ROW->minpos rather than ROW->start.pos. + (init_from_display_pos, init_iterator): Use EMACS_INT for + character and byte positions. + (find_row_edges): Rename from find_row_end. Accept additional + arguments for minimum and maximum buffer positions seen by + display_line for this row. Don't use iterator to find the + position following the maximum one; instead, increment the + position found by display_line directly. Fix logic; eol_pos + should be tested before the rest. Handle the case of characters + delivered from display vector (bug#6036). Fix tests related to + it->method. Handle the truncated_on_right_p rows. + (RECORD_MAX_MIN_POS): New macro. + (display_line): Use it to record the minimum and maximum buffer + positions for glyphs in the row being assembled. Record the + position of the newline that terminates the line. If word wrap is + in effect, restore minimum and maximum positions seen up to the + wrap point, when iterator returns to it. + (try_window_reusing_current_matrix): Give up if in bidi-reordered + row and cursor not already at point. Restore original pre-bidi + code for unidirectional buffers. + + * dispnew.c (increment_row_positions, check_matrix_invariants): + Increment and check row->start.pos and row->end.pos, in addition + to MATRIX_ROW_START_CHARPOS and MATRIX_ROW_END_CHARPOS. + + * .gdbinit (prowlims): Display row->minpos and row->maxpos. + Display truncated_on_left_p and truncated_on_right_p flags. + Formatting fixes. + (pmtxrows): Display the ordinal number of each row. Don't display + rows beyond the last one. + + * bidi.c (bidi_cache_iterator_state): Don't zero out new_paragraph: + it is not copied by bidi_copy_it. + +2010-05-22 Eli Zaretskii + + * w32.c (sys_write): Break writes into chunks smaller than 32MB. + (Bug#6237) + +2010-05-22 Chong Yidong + + * image.c (Fimage_flush): Rename from image-refresh. + +2010-05-21 Chong Yidong + + * xdisp.c (redisplay_internal): Clear caches even if redisplaying + just one window. + + * image.c (Vimage_cache_eviction_delay): Decrease to 300. + (clear_image_cache): If the number of cached images is unusually + large, decrease the cache eviction delay (Bug#6230). + +2010-05-21 Glenn Morris + + * Makefile.in (${ns_appdir}, ${ns_appbindir}Emacs, ns-app): + Move these rules to ns.mk. + * ns.mk: New file. + + * Makefile.in (../src/$(OLDXMENU), $(OLDXMENU)): Always define rules. + + * Makefile.in (CANNOT_DUMP): New, set by configure. + (emacs${EXEEXT}, bootstrap-emacs${EXEEXT}): Use $CANNOT_DUMP. + +2010-05-20 Juri Linkov + + * fileio.c (Fdelete_file): Change interative spec to use + `read-file-name' like in `find-file-read-args' where the default + value is `default-directory' instead of `buffer-file-name'. + http://lists.gnu.org/archive/html/emacs-devel/2010-05/msg00533.html + +2010-05-20 Kevin Ryde + + * keyboard.c (Vlast_command, Vkeyboard_translate_table) + (Voverriding_terminal_local_map, Vsystem_key_alist) + (Vlocal_function_key_map): Fix manual link in docstring (Bug#6224). + +2010-05-20 Glenn Morris + + * Makefile.in (DEPDIR): New constant. + (DEPFLAGS): Set with configure, not cpp. + (MKDEPDIR): New, set by configure. + (.c.o, .m.o, ecrt0.o): Use $MKDEPDIR. + (clean): Use $DEPDIR. + (deps_frag): Include from configure. + Move static/dynamic dependency stuff to deps.mk/autodeps.mk. + * deps.mk, autodeps.mk: New files, extracted from Makefile.in. + + * bidi.c (bidi_cache_shrink, bidi_cache_iterator_state): Fix + reallocation of the cache. (Bug#6210) + +2010-05-19 Glenn Morris + + * s/msdos.h (ORDINARY_LINK): Move to sed2v2.inp. + + * Makefile.in (LD, YMF_PASS_LDFLAGS): Set with configure, not cpp. + (GNULIB_VAR): Remove. + (LIBES): Use LIB_GCC instead of GNULIB_VAR. + + * m/ibms390x.h (LINKER): + * m/macppc.h (LINKER) [GNU_LINUX]: + * s/aix4-2.h (ORDINARY_LINK): + * s/cygwin.h (LINKER): + * s/darwin.h (ORDINARY_LINK): + * s/gnu.h (ORDINARY_LINK): + * s/netbsd.h (LINKER): + * s/usg5-4.h (ORDINARY_LINK): + Move to configure. + + * s/aix4-2.h (LINKER): Remove; this file sets ORDINARY_LINK. + +2010-05-18 Chong Yidong + + * character.c (Fstring, Funibyte_string): Use SAFE_ALLOCA to + prevent stack overflow if number of arguments is too large + (Bug#6214). + +2010-05-18 Juanma Barranquero + + * charset.c (load_charset_map_from_file): Don't call close after fclose. + +2010-05-18 Glenn Morris + + * s/gnu-linux.h: Combine two conditionals. + + * Makefile.in (otherobj): Include $(VMLIMIT_OBJ) separately from + $(POST_ALLOC_OBJ). + + * Makefile.in (RALLOC_OBJ): New, set by configure. + (rallocobj): Replace with the previous variable. + (otherobj): Use $RALLOC_OBJ. + + * s/gnu.h (REL_ALLOC) [DOUG_LEA_MALLOC]: + * s/gnu-linux.h (REL_ALLOC) [DOUG_LEA_MALLOC]: Move undef to configure. + + * Makefile.in (GMALLOC_OBJ, VMLIMIT_OBJ): New, set by configure. + (gmallocobj, vmlimitobj): Replace with previous two variables. + (otherobj): Use $GMALLOC_OBJ, $VMLIMIT_OBJ. + +2010-05-17 Glenn Morris + + * Makefile.in (OLDXMENU_DEPS): New, set by configure. + (stamp-oldxmenu): Use $OLDXMENU_DEPS. + +2010-05-16 Glenn Morris + + * Makefile.in (${ns_appbindir}Emacs, ns-app): Always define these rules. + + * Makefile.in (clean): Get rid of HAVE_NS conditional. + + * Makefile.in (ns_appdir, ns_appbindir): Now configure adds the + trailing "/". + + * Makefile.in (TEMACS_LDFLAGS2): New, set by configure. + (temacs${EXEEXT}): Combine the NS_IMPL_GNUSTEP case with the default. + + * Makefile.in (GNUSTEP_SYSTEM_LIBRARIES): Remove, unused. + (NS_IMPL_GNUSTEP_TEMACS_LDFLAGS): New, set by configure. + (LD) [NS_IMPL_GNUSTEP]: Set to $(CC) -rdynamic. + (temacs${EXEEXT}): Remove $LOCALCPP, never defined or referenced. + Make most of the NS_IMPL_GNUSTEP case the same as the default case. + + * Makefile.in (temacs${EXEEXT}) [!NS_IMPL_GNUSTEP]: + Remove ${STARTFLAGS}, nothing ever sets it. + +2010-05-16 Dan Nicolaescu + + * m/ia64.h (UNEXEC): Remove, set in s/*.h. + +2010-05-16 Glenn Morris + + * Makefile.in (LIBX_BASE): Always define. + + * Makefile.in (LIBX_OTHER): Move out of cpp section. + + * Makefile.in (LIBXT): Always define. + +2010-05-15 Glenn Morris + + * Makefile.in (OLDXMENU, LIBXMENU, LIBX_OTHER): Always define. + + * Makefile.in (FONT_DRIVERS): Remove, replace with $FONT_OBJ. + (obj, SOME_MACHINE_OBJECTS): Use $FONT_OBJ. + +2010-05-15 Ken Raeburn + + * lisp.h (XFLOAT_DATA): Use "0?x:x" to generate an rvalue. (Bug#5916) + (LISP_MAKE_RVALUE) [!USE_LISP_UNION_TYPE && !__GNUC__]: Likewise. + + * emacs.c (main): Initialize initial-environment and + process-environment before generating from env, not after. + + Handle --version reasonably in CANNOT_DUMP configuration. + * emacs.c (emacs_version, emacs_copyright): New string variables. + (Vemacs_version, Vemacs_copyright): New Lisp_Object variables. + (syms_of_emacs): Defvar them, and initialize them from the C + string variables. + (main): If initialization hasn't been done, print initial version + info from the C strings, instead of starting an interactive session. + +2010-05-15 Eli Zaretskii + + * bidi.c (bidi_paragraph_init): Don't leave alone garbage values + of bidi_it->paragraph_dir. Call bidi_initialize if needed. + (bidi_paragraph_init): Remove redundant assertion that we are at + the beginning of a line after call to bidi_find_paragraph_start. + + * xdisp.c (Fcurrent_bidi_paragraph_direction): New function. + (syms_of_xdisp): Defsubr it. + + * cmds.c (Fforward_char, Fbackward_char): Doc fix. + + * Makefile.in: Fix MSDOS-related comments. + +2010-05-15 Glenn Morris + + * Makefile.in (OLDXMENU_TARGET): New, set by configure. + (really-lwlib, really-oldXMenu): Always define. + ($OLDXMENU): Depend on $OLDXMENU_TARGET. + + * Makefile.in: Simplify cpp conditional. + + * Makefile.in (${ns_appdir}): Simplify using umask. + + * Makefile.in (${ns_appdir}): Remove references to CVS-related files. + +2010-05-14 Stefan Monnier + + * eval.c (specbind): Remove left-over duplicate test. + Disallow let-binding frame-local vars. Add comment. + +2010-05-14 Eli Zaretskii + + Make the cache of bidi iterator states dynamically allocated. + * bidi.c (bidi_cache_shrink): New function. + (bidi_init_it): Call it. + (bidi_cache_iterator_state): Enlarge the cache if needed. + + * bidi.c (bidi_move_to_visually_next): Rename from + bidi_get_next_char_visually. All callers changed. + +2010-05-14 Kenichi Handa + + * dispextern.h (struct composition_it): New member reversed_p. + + * composite.c (composition_compute_stop_pos): Search backward if + ENDPOS < CHARPOS. + (composition_reseat_it): Handle the case that ENDPOS < CHARPOS. + Set CMP_IT->reversed_p. + (composition_update_it): Pay attention to CMP_IT->reversed_p. + + * xdisp.c (set_iterator_to_next): + Call composition_compute_stop_pos with negative ENDPOS if we are + scanning backward. Call composition_compute_stop_pos if scan + direction is changed. + (next_element_from_buffer): Call composition_compute_stop_pos with + negative ENDPOS if we are scanning backward. + (next_element_from_composition): Pay attention to + IT->cmp_it.reversed_p. + +2010-05-14 Kenichi Handa + + * font.c (font_range): Return the range for the font found at first. + +2010-05-14 Glenn Morris + + * Makefile.in (ns_appdir, ns_appbindir, ns_appsrc): Always define. + + * Makefile.in (mktime, X11, register): Move undefs to configure. + + * Makefile.in (MSDOS_OBJ): Default to empty, let msdos scripts set it. + (MSDOS_X_OBJ): New variable. + (MSDOS_SUPPORT_REAL): New constant. + (MSDOS_SUPPORT): Set as a variable, not with cpp. + (obj): Use MSDOS_X_OBJ. + (lisp): Use MSDOS_SUPPORT as a variable. + + * Makefile.in (REAL_MOUSE_SUPPORT): New constant. + (GPM_MOUSE_SUPPORT): Now it's a constant. + (MOUSE_SUPPORT, TOOLTIP_SUPPORT, WINDOW_SUPPORT): Set with configure, + not cpp. + + * Makefile.in (@NS_IMPL_GNUSTEP_INC@): Use in place of #ifdef. + (ns_appresdir): Remove, unused. + + * Makefile.in (SHELL): Move outside cpp section. + + * s/netbsd.h (AMPERSAND_FULL_NAME): Remove (defined in AH_BOTTOM). + +2010-05-13 Glenn Morris + + * Makefile.in (FONT_DRIVERS): Place with other HAVE_X_WINDOWS stuff. + (TOOLTIP_SUPPORT): Place with other HAVE_WINDOW_SYSTEM stuff. + + * Makefile.in (FONT_DRIVERS): If HAVE_X_WINDOWS is defined, + HAVE_WINDOW_SYSTEM must be too. + + * Makefile.in (WINNT_SUPPORT): Remove, nt build does not use this file. + (lisp): Remove WINNT_SUPPORT. + + * Makefile.in (OLDXMENU, LIBXMENU) [!HAVE_MENUS]: + Let configure set these variables (to empty) in this case as well. + + * Makefile.in (LD_SWITCH_X_SITE): Define as a variable, not via cpp. + (LIBX_BASE): Use $LD_SWITCH_X_SITE. + + * Makefile.in (C_SWITCH_X_SYSTEM, C_SWITCH_X_SITE, LIB_STANDARD) + (LIB_MATH, FONTCONFIG_CFLAGS, FONTCONFIG_LIBS, FREETYPE_CFLAGS) + (FREETYPE_LIBS, LIBOTF_CFLAGS, LIBOTF_LIBS, M17N_FLT_CFLAGS) + (M17N_FLT_LIBS, GNU_OBJC_CFLAGS, GNUSTEP_SYSTEM_LIBRARIES, LIBGPM) + (LIBRESOLV, UNEXEC_OBJ): For clarity, define variables to hold + the values output by configure. + (ALL_CFLAGS, obj, LIBES, temacs${EXEEXT}): Use the above variables. + +2010-05-12 Glenn Morris + + * Makefile.in (YMF_PASS_LDFLAGS, LD, LINKER): Simplify the logic. + (LINKER_WAS_SPECIFIED): Remove. + + * Makefile.in (LIB_GCC): Set using configure, not cpp. + (GNULIB_VAR) [!ORDINARY_LINK]: Always set to $LIB_GCC. + * m/arm.h (LIB_GCC) [GNU_LINUX]: + * s/cygwin.h (LIB_GCC): + * s/freebsd.h (LIB_GCC): + * s/gnu-linux.h (LIB_GCC): + * s/msdos.h (LIB_GCC): + * s/netbsd.h (LIB_GCC): + Move to configure. + +2010-05-11 Karel Klic + + * ftfont.c: Fix incorrect parentheses of #if condition for + definining M17N_FLT_USE_NEW_FEATURE. + +2010-05-11 Glenn Morris + + * Makefile.in (LIBS_SYSTEM) [MSDOS]: Do not reset. + * s/msdos.h (MSDOS_LIBS_SYSTEM): Remove. + +2010-05-10 Eli Zaretskii + + * xdisp.c (init_iterator): Don't turn on bidi reordering in + unibyte buffers. See + http://lists.gnu.org/archive/html/emacs-devel/2010-05/msg00263.html. + +2010-05-10 Glenn Morris + + * Makefile.in (LIBS_SYSTEM): Set using configure, not cpp. + (LIBS_SYSTEM) [MSDOS]: Reset with MSDOS_LIBS_SYSTEM. + (LIBES): Use LIBS_SYSTEM as a variable. + * s/msdos.h (LIBS_SYSTEM): Rename to MSDOS_LIBS_SYSTEM. Always define. + * s/aix4-2.h (LIBS_SYSTEM): + * s/freebsd.h (LIBS_SYSTEM): + * s/hpux10-20.h (LIBS_SYSTEM): + * s/sol2-6.h (LIBS_SYSTEM): + * s/unixware.h (LIBS_SYSTEM): + Move to configure. + + * s/aix4-2.h (MAIL_USE_LOCKF): + * s/bsd-common.h (MAIL_USE_FLOCK): + * s/darwin.h (MAIL_USE_FLOCK): + * s/gnu-linux.h (MAIL_USE_FLOCK): + * s/irix6-5.h (MAIL_USE_FLOCK): + * s/template.h (MAIL_USE_FLOCK): + Move to configure. + +2010-05-08 Chong Yidong + + * Version 23.2 released. + +2010-05-08 Andreas Schwab + + * composite.c (autocmp_chars): Save point as marker before calling + auto-composition-function (Bug#5984). + + * lisp.h (restore_point_unwind): Add prototype. + + * fileio.c (restore_point_unwind): Remove static attribute. + +2010-05-08 Kenichi Handa + + * ftfont.c (M17N_FLT_USE_NEW_FEATURE): Define it if we can use the + new feature of libotf and m17n-flt. + (ftfont_check_otf) [M17N_FLT_USE_NEW_FEATURE]: + Call OTF_check_features even if no specific feature is given. + (PACK_OTF_TAG) [M17N_FLT_USE_NEW_FEATURE]: New macro. + (ftfont_drive_otf) [M17N_FLT_USE_NEW_FEATURE]: Handle the case + that OUT is NULL. Use OTF_drive_gsub_with_log and + OTF_drive_gpos_with_log instead of OTF_drive_gsub and + OTF_drive_gpos. + (ftfont_try_otf) [M17N_FLT_USE_NEW_FEATURE]: New function. + (ftfont_shape_by_flt) [M17N_FLT_USE_NEW_FEATURE]: + Setup mflt_enable_new_feature and mflt_try_otf. + +2010-05-08 Jan Djärv + + * xsettings.c (Ftool_bar_get_system_style): Correct comment. + + * gtkutil.c (xg_pack_tool_bar): Change show_all to show for handle + box and toolbar (Bug #6139). + (xg_create_tool_bar): Remove comment (Bug #6139). + (xg_make_tool_item): Remove gtk_widget_show_all (Bug #6139). + (xg_show_toolbar_item): Add gtk_widget_show for weventbox (Bug #6139). + +2010-05-08 Juanma Barranquero + + * makefile.w32-in ($(BLD)/eval.$(O), $(BLD)/w32fns.$(O)): + Update dependencies. + +2010-05-08 Eli Zaretskii + + * fringe.c (update_window_fringes): Set up truncation bitmaps for + R2L lines. + +2010-05-08 Glenn Morris + + * Makefile.in (THIS_IS_MAKEFILE): Remove, unused. + + * Makefile.in (LIBS_TERMCAP): Set with configure, not cpp. + (TERMCAP_OBJ): New, set by configure, replacing termcapobj. + (termcapobj): Replace with TERMCAP_OBJ. + (otherobj): Use $TERMCAP_OBJ instead of $termcapobj. + (LIBES): Use LIBS_TERMCAP as a variable. + + * s/freebsd.h (osreldate.h): No longer include, since this file + does not use __FreeBSD_version any more. + + * s/aix4-2.h (TERMINFO): + * s/cygwin.h (TERMINFO): + * s/darwin.h (TERMINFO, LIBS_TERMCAP) [HAVE_LIBNCURSES]: + * s/freebsd.h (TERMINFO, LIBS_TERMCAP): + * s/gnu-linux.h (TERMINFO, LIBS_TERMCAP) [HAVE_LIBNCURSES]: + * s/gnu.h (TERMINFO, LIBS_TERMCAP) [HAVE_LIBNCURSES]: + * s/hpux10-20.h (TERMINFO, LIBS_TERMCAP): + * s/irix6-5.h (TERMINFO): + * s/netbsd.h (LIBS_TERMCAP): + * s/openbsd.h (TERMINFO, LIBS_TERMCAP): + * s/sol2-6.h (LIBS_TERMCAP) [!TERMINFO]: + * s/usg5-4.h (TERMINFO): + Move to configure. + +2010-05-07 Stefan Monnier + + * eval.c (unbind_to): Don't unbind a local binding into the global + binding when the local binding disappeared. Inversely, don't unbind + a global binding into a newly created local binding. + * data.c (set_internal): Make its `buf' arg into a `where' arg so we + can specify the frame to use, when applicable. Adjust callers. + +2010-05-07 Vincent Belaïche + Stefan Monnier + + * floatfns.c (Fisnan, Fcopysign, Ffrexp, Fldexp): New functions. + +2010-05-07 Eli Zaretskii + + * w32fns.c: Include w32.h. + (Fw32_shell_execute): Decode the error message before passing it + to `error'. (Bug#6126) + + * msdos.c (dos_set_window_size): + * w16select.c (Fx_selection_exists_p): Use `Fsymbol_value (foo)' + instead of `XSYMBOL (foo)->value'. + +2010-05-07 Eli Zaretskii + + Fix the MS-DOS build, broken by autoconfiscation. + + * Makefile.in: Don't use Make-style comments past the "start of + cpp stuff" line. + (MSDOS_OBJ): Remove xmenu.o (it is now defined by XMENU_OBJ). + + * s/msdos.h (UNEXEC): Don't define (@unexec@ in Makefile.in is + edited directly by msdos/sed1v2.inp). + +2010-05-07 Glenn Morris + + * Makefile.in (LD_SWITCH_SYSTEM): Set with configure, not cpp. + (LD_SWITCH_SYSTEM_EXTRA): New variable, set by configure. + (TEMACS_LDFLAGS): Use $LD_SWITCH_SYSTEM and $LD_SWITCH_SYSTEM_EXTRA, + move out of cpp section. + * s/freebsd.h (LD_SWITCH_SYSTEM): + * s/gnu-linux.h (LD_SWITCH_SYSTEM): + * s/netbsd.h (LD_SWITCH_SYSTEM): + * s/openbsd.h (LD_SWITCH_SYSTEM): Move to configure.in. + +2010-05-07 Dan Nicolaescu + + Define LIB_STANDARD and START_FILES using autoconf. + * s/usg5-4.h (LIB_STANDARD): + * s/netbsd.h (START_FILES): + * s/irix6-5.h (LIB_STANDARD): + * s/hpux10-20.h (LIB_STANDARD, START_FILES): + * s/gnu-linux.h (START_FILES, LIB_STANDARD): + * s/freebsd.h (START_FILES): + * s/darwin.h (START_FILES): + * s/cygwin.h (START_FILES): + * s/aix4-2.h (LIB_STANDARD): + * m/ibmrs6000.h (START_FILES): Remove, move logic to configure.in. + * Makefile.in (STARTFILES): Rename to START_FILES, define using + autoconf, not cpp. + +2010-05-06 Dan Nicolaescu + + Remove NEED_BSDTTY and NEED_UNISTD_H. + * s/hpux10-20.h (NEED_BSDTTY): Remove. + * s/aix4-2.h (NEED_UNISTD_H): Remove. + * systty.h: Simplify conditionals for including , + and . + + * emacs.c (main): Remove NO_DIR_LIBRARY conditional, unused. + + * Makefile.in (STARTFILES): Conditionally define to make the usage clear. + * s/gnu.h (START_FILES): Remove empty definition. + +2010-05-06 Jan Djärv + + * xterm.c (x_draw_image_relief): Move declaration of extra to beginning. + +2010-05-06 Glenn Morris + + * Makefile.in (CPP, LN_S): Remove unused variables. + +2010-05-05 Stefan Monnier + + * syntax.c (Fchar_syntax): Check the arg is a character (bug#6080). + +2010-05-05 Lawrence Mitchell + + * m/sparc.h: Fix typo in earlier change. + +2010-05-04 Stefan Monnier + + Misc tweaks. + * eval.c (Fdefvaralias): Remove unintended nested if. + (internal_condition_case_2, internal_condition_case_n): Use ANSI type. + +2010-05-04 Bernhard Herzog (tiny change) + + * xsmfns.c (smc_save_yourself_CB): strlen(client_id) => strlen(cwd). + +2010-05-04 Dan Nicolaescu + + Remove BSD_PGRPS. + * s/bsd-common.h (BSD_PGRPS): Remove undef. + * s/gnu-linux.h (BSD_PGRPS): Remove. + * term.c (dissociate_if_controlling_tty): + * sysdep.c (narrow_foreground_group, widen_foreground_group) + (init_sys_modes, reset_sys_modes): + * emacs.c (main): + * callproc.c (Fcall_process, child_setup): Remove code depending + on BSD_PGRPS. + + Remove POSIX_SIGNALS. + * s/usg5-4.h (POSIX_SIGNALS): + * s/netbsd.h (POSIX_SIGNALS): + * s/msdos.h (POSIX_SIGNALS): + * s/ms-w32.h (POSIX_SIGNALS): + * s/hpux11.h (POSIX_SIGNALS): + * s/gnu.h (POSIX_SIGNALS): + * s/gnu-linux.h (POSIX_SIGNALS): + * s/freebsd.h (POSIX_SIGNALS): + * s/darwin.h (POSIX_SIGNALS): + * s/cygwin.h (POSIX_SIGNALS): + * s/aix4-2.h (POSIX_SIGNALS): Remove definition. + * s/unixware.h: + * s/sol2-6.h: Remove comments on POSIX_SIGNALS. + * process.c (create_process): + * syssignal.h: + * sysdep.c (wait_for_termination, init_signals): + * process.c (create_process): + * msdos.c: POSIX_SIGNALS is always defined on all platforms, + remove all code that assumes the contrary. + +2010-05-04 Glenn Morris + + * s/gnu-linux.h (LD_SWITCH_SYSTEM): Use LD_SWITCH_X_SITE_AUX as a shell + variable. + * s/netbsd.h (LD_SWITCH_SYSTEM_tmp): Remove. + (LD_SWITCH_SYSTEM): Use $LD_SWITCH_X_SITE_AUX_RPATH. + * s/openbsd.h (LD_SWITCH_SYSTEM_tmp): Remove. + (LD_SWITCH_SYSTEM): Use $LD_SWITCH_X_SITE_AUX_RPATH instead of + LD_SWITCH_SYSTEM_tmp. + * Makefile.in (LD_SWITCH_X_SITE_AUX, LD_SWITCH_X_SITE_AUX_RPATH): + New variables, set by configure. + + * s/aix4-2.h (LD_SWITCH_SYSTEM_TEMACS): Move to configure.in. + * s/darwin.h (HEADERPAD_EXTRA, LIBS_NSGUI): Remove. + (LD_SWITCH_SYSTEM_TEMACS): Move to configure.in. + * Makefile.in (LD_SWITCH_SYSTEM_TEMACS): New variable, set by configure. + (TEMACS_LDFLAGS): Use $LD_SWITCH_SYSTEM_TEMACS. + + * s/aix4-2.h (C_SWITCH_SYSTEM): + * m/alpha.h (C_SWITCH_MACHINE): + Move to configure.in. + * Makefile.in (C_SWITCH_MACHINE, C_SWITCH_SYSTEM): + New variables, set by configure. + (ALL_CFLAGS): Use $C_SWITCH_MACHINE and $C_SWITCH_SYSTEM in place of + $c_switch_machine and $c_switch_system. + +2010-05-04 Dan Nicolaescu + + * s/hpux10-20.h (LIB_STANDARD): New definition. + * Makefile.in (ORDINARY_LINK): Remove setting LIB_STANDARD based + on it, not used anymore. + +2010-05-03 Chong Yidong + + * eval.c (internal_condition_case_n): Rename from + internal_condition_case_2. + (internal_condition_case_2): New function. + + * xdisp.c (safe_call): Use internal_condition_case_n. + + * fileio.c (Fdelete_file, internal_delete_file): New arg FORCE. + (internal_delete_file, Frename_file): Callers changed. + + * buffer.c (Fkill_buffer): + * callproc.c (delete_temp_file): Callers changed (Bug#6070). + + * lisp.h: Update prototypes. + +2010-05-03 Glenn Morris + + * Makefile.in (LIBX_EXTRA, LIBX_BASE): New variables. + (LIBXT_OTHER, LIBX_OTHER): New, set by configure. + (LIBXT): Set with configure, not cpp. + (LIBX): Remove. + (LIBES): Replace $LIBX with $LIBX_BASE and $LIBX_OTHER. + +2010-05-02 Dan Nicolaescu + + * m/amdx86-64.h (START_FILES, LIB_STANDARD): Remove. + The FreeBSD is not needed, the default works, Solaris version is + not needed, and the remaining case is not supported by configure. + +2010-05-02 Jan Djärv + + * xsmfns.c (CHDIR_OPT): New define. + (smc_save_yourself_CB): Add CHDIR_OPT to options to use when + restarting emacs. + + * xterm.c (x_connection_closed): Call Fkill_emacs instead of + shut_down_emacs. + + * emacs.c (USAGE1): Mention --chdir. + (main): Handle --chdir. + (standard_args): Add --chdir. + (fatal_error_signal): Call Fkill_emacs for SIGTERM and SIGHUP (Bug + #5552). + +2010-05-01 Dan Nicolaescu + + Remove LD_SWITCH_MACHINE. + * Makefile.in (LD_SWITCH_MACHINE): Remove definition, unused. + (TEMACS_LDFLAGS): Do not use LD_SWITCH_MACHINE. + + Clean up IRIX code. + * m/iris4d.h (TERMINFO, FIRST_PTY_LETTER): Move definitions ... + * s/irix6-5.h (TERMINFO, FIRST_PTY_LETTER): ... here. + + Clean up AIX code. + * m/ibmrs6000.inp: Remove file, unused. + * m/ibmrs6000.h (IBMR2AIX): Remove, unused. + (LD_SWITCH_MACHINE): Rename to LD_SWITCH_SYSTEM_TEMACS, and move + definition ... + * s/aix4-2.h (LD_SWITCH_SYSTEM_TEMACS): ... here. + + * sysdep.c (child_setup_tty, init_sys_modes): Remove !IBMR2AIX code, + unused. + +2010-05-01 Eli Zaretskii + + Emulate POSIX_SIGNALS on MS-Windows. + + * s/ms-w32.h (POSIX_SIGNALS, struct sigaction, SIG_BLOCK) + (SIG_SETMASK, SIG_UNBLOCK): Define. + + * sysdep.c (sys_signal) [WINDOWSNT]: #ifdef away. + (wait_for_termination) [WINDOWSNT]: Move MS-Windows specific code + from non-POSIX_SIGNALS section to POSIX_SIGNALS section. - * xterm.c (x_draw_fringe_bitmap): Don't clip bottom aligned bitmap - specially. - * w32term.c (w32_draw_fringe_bitmap): Likewise. - * nsterm.m (ns_draw_fringe_bitmap): Likewise. + * w32.c (sigemptyset, sigaddset, sigfillset, sigprocmask): + New stubs. - * fringe.c (draw_fringe_bitmap_1): Don't clip bitmap here. - Take account of bitmap offset. - (draw_window_fringes): Take account of window vscroll. - (update_window_fringes): Likewise. Extend top-aligned top indicator - or bottom-aligned bottom indicator to adjacent rows if it doesn't fit - in one row. Don't set redraw_fringe_bitmaps_p outside row comparison. - Set left_fringe_offset and right_fringe_offset (Bug#5634, Bug#6325). + Miscellaneous fixes of bidi display. -2010-07-04 Juanma Barranquero + * xdisp.c (find_row_end): New function, refactored from display_line. + (display_line): Use it. + (extend_face_to_end_of_line): In almost-filled rows, extend only + if the row is R2L and not continued. + (display_line): Fix prepending of truncation glyphs to R2L rows. + Preserve overlay and string info in row->end. + (insert_left_trunc_glyphs): Support addition of left truncation + glyphs to R2L rows. + (set_cursor_from_row): Don't place cursor on the vertical border + glyph between adjacent windows. Fix a crash when a display string + is continued to the next line. Don't return zero if cursor was + found by `cursor' property of a display string. + (try_cursor_movement): Don't assume that row->end == (row+1)->start, + test for that explicitly. - * w32fns.c (Qtooltip): Declare. - Suggested by Andy Moreton . +2010-05-01 Glenn Morris -2010-07-03 Jan Djärv + * Makefile.in (gmallocobj, rallocobj, vmlimitobj): Initialize to null, + for clarity. + (OTHER_OBJ): Remove. + (PRE_ALLOC_OBJ, POST_ALLOC_OBJ): New, set by configure. + (otherobj): Use PRE_ALLOC_OBJ, POST_ALLOC_OBJ rather than OTHER_OBJ. - * xmenu.c (x_activate_menubar): Send Press/Release for Gtk+ to avoid - grab on just Press (Bug#6499). +2010-05-01 Karel Klíč -2010-07-02 Chong Yidong + * fileio.c (Ffile_selinux_context): Context functions may return null. - * frame.c (Qtooltip): New var. - (delete_frame): Use it. Fix faulty if statement. Don't update - mode line for tooltip frames. Suggested by Martin Rudalics. +2010-04-30 Dan Nicolaescu - * xfns.c (x_create_tip_frame): - * w32fns.c (x_create_tip_frame): Use it. + * s/gnu.h (POSIX_SIGNALS, START_FILES): New definitions. -2010-06-30 Naohiro Aota (tiny change) +2010-04-30 Glenn Morris - * xftfont.c (xftfont_open): Check font width one by one also when - spacing is dual. + * Makefile.in (vmlimitobj) [!SYSTEM_MALLOC]: New variable. (Bug#6065) + (OTHER_OBJ): Define as a separate variable, for clarity. - * ftfont.c (ftfont_open): Ditto. +2010-04-30 Jan Djärv -2010-06-26 Andreas Schwab + * xsettings.c: include limits.h and update file comment. - * alloc.c (Fmake_byte_code): Don't access undefined argument - (Bug#6517). +2010-04-30 Glenn Morris -2010-06-25 Chong Yidong + * Makefile.in (OLDXMENU, LIBXMENU) [HAVE_MENUS]: + Set with configure, not cpp. + (LIBW): Remove, replace with $TOOLKIT_LIBW. - * xdisp.c (next_element_from_image): Ensure that after-strings are - read the next time we hit handle_stop (Bug#1336). + * Makefile.in (mallocobj): Remove. + (otherobj): Simplify using @OTHER_OBJ@. -2010-06-23 Andreas Schwab + * Makefile.in (dispnew.o, frame.o, fringe.o, font.o, fontset.o) + (keyboard.o, window.o, xdisp.o, xfaces.o, menu.o): + Don't bother making nsgui.h dependency platform-specific. - * lread.c (read1): Signal error if #s is not followed by paren. + * Makefile.in (nsfns.o): Remove duplicate nsgui.h dependency. -2010-06-19 Chong Yidong +2010-04-29 Stefan Monnier - * image.c (free_image): Mark frame as garbaged (Bug#6426). + * process.c (read_process_output, exec_sentinel): Don't burp if the + sentinel/filter kills the current buffer (bug#6060). - * keymap.c (Fdefine_key): Doc fix (Bug#6460). + Fix wrong-docstring problem introduced with hash-consing. (Bug#6008) + * eval.c (Fautoload): Set doc to a unique number rather than to 0. + Remove unused var `args'. + * lisp.h (XSETCARFASTINT, XSETCDRFASTINT): Remove. + (LOADHIST_ATTACH): Wrap with do...while to avoid surprises for callers. + * doc.c (store_function_docstring): Use XSETCAR. -2010-06-15 Glenn Morris +2010-04-28 Glenn Morris - * editfns.c (Fbyte_to_string): Pacify compiler. + * Makefile.in (BASE_WINDOW_SUPPORT, X_WINDOW_SUPPORT): New variables. + (WINDOW_SUPPORT) [HAVE_WINDOW_SYSTEM]: Use them. -2010-06-09 Stefan Monnier + * Makefile.in (CYGWIN_OBJ): Set with configure, not cpp. - * dbusbind.c (xd_append_arg): Don't "make-unibyte" the string. - Check `object's type before accessing its guts. + * Makefile.in (GPM_MOUSE_SUPPORT): New, set by configure. + (MOUSE_SUPPORT) [!HAVE_MOUSE]: Use $GPM_MOUSE_SUPPORT. -2010-06-08 Andreas Schwab + * Makefile.in (FONT_OBJ): New, set by configure. + (FONT_DRIVERS): Use $FONT_OBJ. - * minibuf.c (Fall_completions): Add more checks. + * Makefile.in (LIBXMU): Set with configure, not cpp. + * s/aix4-2.h (LIBXMU): + * s/hpux10-20.h (LIBXMU): + Remove definition, now set in configure. -2010-06-08 Juanma Barranquero + * Makefile.in (NS_OBJ, NS_SUPPORT): Set with configure, not cpp. - * minibuf.c (Fall_completions): Check COLLECTION's size (bug#6378). + * m/amdx86-64.h [i386]: Move this test to configure.in. -2010-06-03 Andreas Schwab +2010-04-27 Glenn Morris - * process.c (conv_lisp_to_sockaddr): Fix conversion of IPv4 - address. (Bug#6346) + * Makefile.in (LIBXTR6): Set with configure, not cpp. + * s/unixware.h (NEED_LIBW): Remove definition. -2010-06-03 Juanma Barranquero + * Makefile.in (LUCID_LIBW, MOTIF_LIBW): Remove, replacing by... + (TOOLKIT_LIBW): New, set by configure. + (@X_TOOLKIT_TYPE@): No longer define it. - * ccl.c (Fccl_program_p): Fix typo in docstring. + * Makefile.in (LIBXP): Remove, since included in MOTIF_LIBW. + (MOTIF_LIBW): Set with configure, not cpp. + * s/aix4-2.h (LIB_MOTIF): + * s/gnu-linux.h (LIB_MOTIF): + * s/unixware.h (LIB_MOTIF): Move to configure.in. -2010-05-31 Stefan Monnier +2010-04-27 Dan Nicolaescu - * keymap.c (Fwhere_is_internal): Fix handling of remapping (in thread - of bug#6305). + Reduce CPP usage. + * Makefile.in (LIB_X11_LIB): Remove, inline in the only user. + (obj): Use autoconf for unexec instead of cpp. + (C_SWITCH_SYSTEM, C_SWITCH_MACHINE, C_SWITCH_X_SITE): Remove + definitions and undefs. Inline definitions in the only user. + (ALL_CFLAGS): Substitute C_SWITCH_X_SYSTEM using autoconf. -2010-05-27 Chong Yidong +2010-04-27 Glenn Morris - * xdisp.c (redisplay_window): After redisplay, check if point is - still valid before setting it (Bug#6177). + * m/amdx86-64.h (START_FILES, LIB_STANDARD): Change the logic around, + since the defaults (set by the system file) are fine in most cases. + [GNU_LINUX, __OpenBSD__, __NetBSD__, __APPLE__]: Remove sections. + * m/ibms390x.h (START_FILES, LIB_STANDARD): + * m/macppc.h (START_FILES, LIB_STANDARD) [GNU_LINUX]: + * m/sparc.h (START_FILES, LIB_STANDARD) [__linux__]: + Remove definitions, since they are set correctly in s/gnu-linux.h. + * s/freebsd.h (START_FILES, LIB_STANDARD): + * s/gnu-linux.h (START_FILES, LIB_STANDARD): + * s/hpux10-20.h (START_FILES): + * s/netbsd.h (START_FILES, LIB_STANDARD, START_FILES_1, END_FILES_1): + Use $CRT_DIR in place of fixed /usr/lib, /lib directories. -2010-05-20 enami tsugutomo + * Makefile.in (LIBXP, LUCID_LIBW, WIDGET_OBJ): Set via configure. + (MOTIF_LIBW): Use $LIBXP. + (otherobj): Use $WIDGET_OBJ. - * s/netbsd.h: If terminfo is found, use it in preference to - termcap. (Bug#6190) [Backport from trunk] +2010-04-26 Dan Nicolaescu -2010-05-20 Kevin Ryde + * Makefile.in (LIBS_MACHINE): Remove, unused. - * keyboard.c (Vlast_command, Vkeyboard_translate_table) - (Voverriding_terminal_local_map, Vsystem_key_alist) - (Vlocal_function_key_map): Fix manual link in docstring (Bug#6224). + Use autoconf instead of cpp for LIB_MATH. + * s/darwin.h (LIB_MATH): Do not define here, move to configure. + * s/cygwin.h (LIB_MATH): Likewise. + * Makefile.in (LIB_MATH): Do not define with cpp. + (LIBES): Use autoconf for LIB_MATH. -2010-05-19 Stefan Monnier +2010-04-26 Kenichi Handa - * editfns.c (Fbyte_to_string): New function. + * composite.c (Ffind_composition_internal): Fix the return value + for an automatic composition. -2010-05-18 Chong Yidong +2010-04-25 Dan Nicolaescu - * character.c (Fstring, Funibyte_string): Use SAFE_ALLOCA to - prevent stack overflow if number of arguments is too large - (Bug#6214). + Remove all NO_ARG_ARRAY uses. + * fns.c (concat2, concat3, nconc2): + * eval.c (apply1, call1, call2, call3, call4, call5, call6) + (call7): Remove NO_ARG_ARRAY usage, assume it's always true. + * m/xtensa.h (NO_ARG_ARRAY): + * m/template.h (NO_ARG_ARRAY): + * m/sparc.h (NO_ARG_ARRAY): + * m/sh3.h (NO_ARG_ARRAY): + * m/mips.h (NO_ARG_ARRAY): + * m/macppc.h (NO_ARG_ARRAY): + * m/iris4d.h (NO_ARG_ARRAY): + * m/intel386.h (NO_ARG_ARRAY): + * m/ibms390x.h (NO_ARG_ARRAY): + * m/ibms390.h (NO_ARG_ARRAY): + * m/ibmrs6000.h (NO_ARG_ARRAY): + * m/ia64.h (NO_ARG_ARRAY): + * m/hp800.h (NO_ARG_ARRAY): + * m/arm.h (NO_ARG_ARRAY): + * m/amdx86-64.h (NO_ARG_ARRAY): + * m/alpha.h (NO_ARG_ARRAY): Remove definition. -2010-05-11 Eli Zaretskii +2010-04-25 Eli Zaretskii - * makefile.w32-in ($(BLD)/w32fns.$(O)): Depend on $(SRC)/w32.h. + * xdisp.c (display_line): Don't assume 2nd call to + get_next_display_element cannot return zero. (Bug#6030) + (iterate_out_of_display_property): New function, body from pop_it. + (pop_it): Use it. - * w32fns.c: Include w32.h. - (Fw32_shell_execute): Decode the error message before passing it - to `error'. (Bug#6126) +2010-04-24 Glenn Morris -2010-05-11 Karel Klic + * m/amdx86-64.h (START_FILES, LIB_STANDARD) [__OpenBSD__]: + For clarity, revert to using fixed /usr/lib rather than $CRT_DIR. + (START_FILES, LIB_STANDARD) [__FreeBSD__]: Merge into the generic case, + since CRT_DIR defaults to /usr/lib. Suggested by Dan Nicolaescu. - * ftfont.c: Fix incorrect parentheses of #if condition for - definining M17N_FLT_USE_NEW_FEATURE. +2010-04-24 Eli Zaretskii -2010-05-07 Chong Yidong + * xdisp.c (display_line): Use `reseat' instead of `reseat_1', and + use `get_next_display_element' and `set_iterator_to_next' to + advance to the next character, when looking for the character that + begins the next row. + + * .gdbinit: Add a "set Fmake_symbol" line to force GDB to load the + definition of "struct Lisp_Symbol". + +2010-04-24 Glenn Morris + + * Makefile.in (CRT_DIR): New variable, set by configure. + * m/amdx86-64.h, m/ibms390x.h (START_FILES, LIB_STANDARD): + Use $CRT_DIR rather than HAVE_LIB64_DIR. (Bug#5655) + +2010-04-23 Dan Nicolaescu + + * Makefile.in: Remove C_SWITCH_X_MACHINE, unused. + + * s/cygwin.h (LIBS_DEBUG): Remove, unused. + + Remove redundant flags. + * s/freebsd.h (C_SWITCH_SYSTEM): + * s/hpux10-20.h (C_SWITCH_X_SYSTEM, LD_SWITCH_X_DEFAULT): + * s/netbsd.h (C_SWITCH_SYSTEM): + * s/openbsd.h (LD_SWITCH_X_DEFAULT): Remove, configure takes care + of these. + + Simplify m/intel386.h. + * m/intel386.h (CRT0_DUMMIES): Remove, inline value in the only + user: ecrt0.c. + (SOLARIS2): Remove LOAD_AVE_TYPE, LOAD_AVE_CVT, LIBS_MACHINE, unused. + (USG5_4): Move LOAD_AVE_TYPE, LOAD_AVE_CVT, FSCALE definitions to + the only user: s/unixware.h. + * ecrt0.c: Remove #ifndef static. Inline CRT0_DUMMIES definition + from m/intel386.h. + * s/unixware.h (LOAD_AVE_TYPE, LOAD_AVE_CVT, FSCALE): Definitions + moved here from m/intel386.h. + + * m/mips.h: Remove #if 0 code. + +2010-04-23 Eli Zaretskii + + Fix display of composed characters from L2R scripts in bidi buffers. + * xdisp.c (set_iterator_to_next, next_element_from_composition): + After advancing IT past the composition, resync the bidi iterator + with IT's position. (Bug#5977) + +2010-04-23 Dan Nicolaescu + + * Makefile.in (LD_SWITCH_MACHINE_TEMACS): Remove, unused. + (TEMACS_LDFLAGS): Don't use LD_SWITCH_SYSTEM_TEMACS. + +2010-04-23 Stefan Monnier + + * gtkutil.c: Include xsettings.h for Ftool_bar_get_system_style. + +2010-04-23 Eli Zaretskii + + Support `display' text properties and overlay strings in bidi buffers. + * xdisp.c (pop_it): When the stack is popped after displaying + from a string, bidi-iterate to exit from the text portion covered + by the `display' property or overlay. (Bug#5988, bug#5920) + +2010-04-23 Dan Nicolaescu + + * m/macppc.h (LD_SWITCH_SYSTEM_TEMACS): Remove #undef. + (LD_SWITCH_MACHINE_TEMACS): Remove, configure sets nocombreloc. + + * s/netbsd.h (LD_SWITCH_SYSTEM_TEMACS): Remove, configure sets nocombreloc. + * s/openbsd.h (LD_SWITCH_SYSTEM_TEMACS): Remove. + + Simplify STARTFILES definition. + * s/hpux10-20.h (START_FILES): Explicitly define here instead of + relying on Makefile.in to define it. + * s/cygwin.h (START_FILES): Likewise. + * Makefile.in (STARTFILES): Remove conditional code, not needed anymore. + + Clean up Solaris code. + * s/sol2-6.h (LD_SWITCH_SYSTEM_TEMACS, C_SWITCH_X_SYSTEM) + (LIB_MOTIF): Remove, configure takes care of this. + (NOT_USING_MOTIF): Remove, unused. + * xrdb.c: Remove #if 0-ed #include. + (SYSV): Remove conditional for old SysV. + * sysdep.c (closedir): Remove conditional code for Solaris, + Solaris has closedir. - * Version 23.2 released. +2010-04-22 Jan Djärv + + * xsettings.c (read_and_apply_settings): Check if current_font is + NULL before strcmp (Bug#6001). -2010-04-30 Andreas Schwab +2010-04-21 Dan Nicolaescu - * composite.c (autocmp_chars): Save point as marker before calling - auto-composition-function (Bug#5984). + Clean up HP-UX files. + * m/hp800.h (NO_REMAP, VIRT_ADDR_VARIES, DATA_SEG_BITS) + (DATA_START, TEXT_START, LOAD_AVE_TYPE, LOAD_AVE_CVT) + (LDAV_SYMBOL, index, rindex): Move definitions only used in HP-UX ... + * s/hpux10-20.h: ... to the only user, here. - * lisp.h (restore_point_unwind): Add prototype. +2010-04-21 Eli Zaretskii + + * bidi.c (bidi_find_paragraph_start, bidi_at_paragraph_end): Don't + use buffer-local values of paragraph-start and paragraph-separate. + : Rename from + fallback_paragraph_start_re and fallback_paragraph_separate_re. + (Bug#5992) - * fileio.c (restore_point_unwind): Remove static attribute. +2010-04-21 Jan Djärv + + * xsettings.c: Qmonospace_font_name, Qtool_bar_style and + current_tool_bar_style are new. + (store_config_changed_event): Rename from store_font_changed_event. + (XSETTINGS_TOOL_BAR_STYLE): New define. + (SEEN_FONT, SEEN_TB_STYLE): New enum values. + (struct xsettings): Add font and tb_style, set xft stuff inside #ifdef + HAVE_XFT. + (something_changedCB): store_font_changed_event is now + store_config_changed_event + (parse_settings): Rename from parse_xft_settings. Read + non-xft xsettings outside #ifdef HAVE_XFT. + (read_settings): Renamed from read_xft_settings. + (apply_xft_settings): Take current settings as parameter. Do not + call read_(xft)_settings. + (read_and_apply_settings): New function. + (xft_settings_event): Do non-xft stuff out of HAVE_XFT. Call + read_and_apply_settings if there are settings to be read. + (init_xsettings): Renamed from init_xfd_settings. + Call read_and_apply_settings unconditionally. + (xsettings_initialize): Call init_xsettings. + (Ftool_bar_get_system_style): New function. + (syms_of_xsettings): Define Qmonospace_font_name and + Qtool_bar_style. Initialize current_tool_bar_style to nil. + defsubr Stool_bar_get_system_style. Fprovide on + dynamic-setting. + Move misplaced HAVE_GCONF -2010-04-23 Kenichi Handa + * xsettings.h (Ftool_bar_get_system_style): Declare. - * ftfont.c (M17N_FLT_USE_NEW_FEATURE): Define it if we can use the - new feature of libotf and m17n-flt. - (ftfont_check_otf) [M17N_FLT_USE_NEW_FEATURE]: Call - OTF_check_features even if no specific feature is given. - (PACK_OTF_TAG) [M17N_FLT_USE_NEW_FEATURE]: New macro. - (ftfont_drive_otf) [M17N_FLT_USE_NEW_FEATURE]: Handle the case - that OUT is NULL. Use OTF_drive_gsub_with_log and - OTF_drive_gpos_with_log instead of OTF_drive_gsub and - OTF_drive_gpos. - (ftfont_try_otf) [M17N_FLT_USE_NEW_FEATURE]: New function. - (ftfont_shape_by_flt) [M17N_FLT_USE_NEW_FEATURE]: Setup - mflt_enable_new_feature and mflt_try_otf. + * xdisp.c: Vtool_bar_style, tool_bar_max_label_size, + Qtext, Qboth, Qboth_horiz are new. + (syms_of_xdisp): Intern Qtext, Qboth, Qboth_horiz, DEFVAR + Vtool_bar_style, tool_bar_max_label_size. + + * lisp.h: Extern declare Qtext, Qboth, Qboth_horiz. + + * keyboard.c: QClabel is new. + (parse_tool_bar_item): Take out QClabel from tool bar items. + Try to construct a label if ther is no QClabel. + (syms_of_keyboard): Intern :label as QClabel. + + * dispextern.h (tool_bar_item_idx): TOOL_BAR_ITEM_LABEL is new. + (Vtool_bar_style, tool_bar_max_label_size, DEFAULT_TOOL_BAR_LABEL_SIZE): + New. + + * Makefile.in (SOME_MACHINE_LISP): font-setting.el renamed to + dynamic-setting.el. + + * gtkutil.c (xg_tool_bar_menu_proxy): Handle label in tool bar item. + (xg_make_tool_item, xg_show_toolbar_item): New function. + (update_frame_tool_bar): Take label from TOOL_BAR_ITEM_LABEL. + Call xg_make_tool_item to make a tool bar item. + Call xg_show_toolbar_item. Use wtoolbar instead of x->toolbar_widget. + + * xterm.c (x_draw_image_relief): Take Vtool_bar_button_margin + into account for toolbars. + +2010-04-21 Jan Djärv + + * data.c (make_blv): Declarations before code (Bug#5993). + +2010-04-21 Glenn Morris + + * Makefile.in (DBUS_OBJ, GTK_OBJ, XMENU_OBJ, XOBJ): + Define using autoconf, not cpp. + (LIBXSM): New variable, set by autoconf. + (LIBXT): Use $LIBXSM. + +2010-04-21 Dan Nicolaescu + + Remove NOMULTIPLEJOBS, unused. + * s/template.h (NOMULTIPLEJOBS): + * s/msdos.h (NOMULTIPLEJOBS): Remove, unused. + + Simplify LD_SWITCH_SYSTEM_TEMACS usage. + * s/freebsd.h (LD_SWITCH_SYSTEM_TEMACS): + * s/gnu-linux.h (LD_SWITCH_SYSTEM_TEMACS): Remove, configure + detects -znocombreloc and passes it to the linker + * s/hpux10-20.h (LD_SWITCH_SYSTEM_TEMACS): Remove, empty. + +2010-04-21 Glenn Morris + + * Makefile.in (LIBSELINUX_LIBS): Move out of #ifdef. + +2010-04-21 Karel Klíč + + * Makefile.in (LIBSELINUX_LIBS): New. + (LIBES): Add $LIBSELINUX_LIBS. + * eval.c, lisp.h (call7): New function. + * fileio.c [HAVE_LIBSELINUX]: Include selinux headers. + (Ffile_selinux_context, Fset_file_selinux_context): + New functions. + (Fcopy_file): New parameter preserve-selinux-context. + (Frename_file): Preserve selinux context when renaming by copy-file. + +2010-04-21 Juanma Barranquero + Eli Zaretskii + + Don't depend on cm.c or termcap.c on Windows, use stubs. + * makefile.w32-in (OBJ1): Remove cm.$(O) and termcap.$(O). + ($(BLD)/cm.$(O), $(BLD)/termcap.$(O)): Remove. + * w32console.c (current_tty, cost): New vars; lifted from cm.c. + (evalcost, cmputc, cmcheckmagic, cmcostinit, cmgoto, Wcm_clear) + (sys_tputs, sys_tgetstr): New stubs. + * s/ms-w32.h (chcheckmagic, cmcostinit, cmgoto, cmputc, Wcm_clear) + (tputs, tgetstr): New; define to sys_*. + +2010-04-20 Juanma Barranquero + + * buffer.c (syms_of_buffer) : Doc fix. + +2010-04-20 Stefan Monnier + + * data.c (Fmake_variable_buffer_local, Fmake_local_variable): + Just signal a warning rather than an error when inside a let. + (Fmake_variable_frame_local): Add the same test. + + * font.c (syms_of_font): Make the style table vars read-only. + + * buffer.h (struct buffer): Remove unused var `direction_reversed'. + * buffer.c (init_buffer_once, syms_of_buffer): Remove its initialization. + + * bidi.c (bidi_initialize): Simplify fallback_paragraph_*_re init. + +2010-04-20 Eli Zaretskii + + Fix R2L paragraph display on TTY. + + * xdisp.c (unproduce_glyphs): New function. + (display_line): Use it when produced glyphs are discarded from R2L + glyph rows. + (append_composite_glyph): In R2L rows, prepend the glyph rather + than appending it. + + * term.c (append_composite_glyph): In R2L rows, prepend the glyph + rather than append it. Set up the resolved_level and bidi_type + attributes of the appended glyph. + (produce_special_glyphs): Mirror the backslash continuation + character in R2L lines. + + Implement display of R2L paragraphs in GUI sessions. + + * xdisp.c [HAVE_WINDOW_SYSTEM]: Add prototype for + append_stretch_glyph. + (set_cursor_from_row) : Remove unused variable. Fix + off-by-one error in computing x at end of text in the row. + (append_stretch_glyph): In reversed row, prepend the glyph rather + than append it. Set resolved_level and bidi_type of the glyph. + (extend_face_to_end_of_line): If the row is reversed, prepend a + stretch glyph whose width is such that the rightmost glyph will be + drawn at the right margin of the window. Fix off-by-one error on + TTY frames in testing whether a line needs face extension. Fix + face extension at ZV. If this is the last glyph row, use + DEFAULT_FACE_ID, to avoid painting the rest of the window with the + region face. + (set_cursor_from_row, display_line): Use + MATRIX_ROW_CONTINUATION_LINE_P instead of testing value of + row->continuation_lines_width. + (next_element_from_buffer): Don't call bidi_paragraph_init if we + are at ZV. Fixes a crash when reseated to ZV by + try_window_reusing_current_matrix. + (display_and_set_cursor, erase_phys_cursor): Handle negative HPOS, + which happens with R2L glyph rows. Fixes a crash when inserting a + character at end of an R2L line. + (set_cursor_from_row): Don't be fooled by truncated rows: don't + treat them as having zero-width characters. Improve comments. + Don't reverse pos_before and pos_after for reversed glyph rows. + Set cursor.x to negative value when the cursor might be on the + left fringe. + (IT_OVERFLOW_NEWLINE_INTO_FRINGE): For R2L lines, consider the + left fringe, not the right one. + (notice_overwritten_cursor, draw_phys_cursor_glyph) + (erase_phys_cursor): For reversed cursor_row, support cursor on + the left fringe. + + * fringe.c (update_window_fringes): For R2L rows, swap the bitmaps + of continuation indicators on the fringes. + (draw_fringe_bitmap): For reversed glyph rows, allow cursor on the + left fringe. + + * w32term.c (w32_draw_window_cursor): For reversed glyph rows, + draw cursor on the left fringe. + + * xterm.c (x_draw_window_cursor): For reversed glyph rows, draw + cursor on the left fringe. + + * dispnew.c (update_text_area): Handle reversed desired rows when + the cursor is on the left fringe. + (set_window_cursor_after_update): Limit cursor's hpos by -1 from + below, not by 0, for when the cursor is on the left fringe. + +2010-04-20 Jan Djärv + + * gtkutil.c (xg_event_is_for_scrollbar): Check if grabbed + widget is a scrollbar. + +2010-04-20 Kenichi Handa + + * charset.c (char_charset): Consider Vcharset_non_preferred_head + only when the arg CHARSET_LIST is nil. + +2010-04-20 Stefan Monnier + + Make variable forwarding explicit rather the using special values. + Basically, this makes the structure of buffer-local values and object + forwarding explicit in the type of Lisp_Symbols rather than use + special Lisp_Objects for that. This tends to lead to slightly more + verbose code, but is more C-like, simpler, and makes it easier to make + sure we handled all cases, among other things by letting the compiler + help us check it. + * lisp.h (enum Lisp_Misc_Type, union Lisp_Misc): + Removing forwarding objects. + (enum Lisp_Fwd_Type, enum symbol_redirect, union Lisp_Fwd): New types. + (struct Lisp_Symbol): Make the various forms of variable-forwarding + explicit rather than hiding them inside Lisp_Object "values". + (XFWDTYPE): New macro. + (XINTFWD, XBOOLFWD, XOBJFWD, XKBOARD_OBJFWD): Redefine. + (XBUFFER_LOCAL_VALUE): Remove. + (SYMBOL_VAL, SYMBOL_ALIAS, SYMBOL_BLV, SYMBOL_FWD, SET_SYMBOL_VAL) + (SET_SYMBOL_ALIAS, SET_SYMBOL_BLV, SET_SYMBOL_FWD): New macros. + (SYMBOL_VALUE, SET_SYMBOL_VALUE): Remove. + (struct Lisp_Intfwd, struct Lisp_Boolfwd, struct Lisp_Objfwd) + (struct Lisp_Buffer_Objfwd, struct Lisp_Kboard_Objfwd): + Remove the Lisp_Misc_* header. + (struct Lisp_Buffer_Local_Value): Redefine. + (BLV_FOUND, SET_BLV_FOUND, BLV_VALUE, SET_BLV_VALUE): New macros. + (struct Lisp_Misc_Any): Add filler to get the right size. + (struct Lisp_Free): Use struct Lisp_Misc_Any rather than struct + Lisp_Intfwd. + (DEFVAR_LISP, DEFVAR_LISP_NOPRO, DEFVAR_BOOL, DEFVAR_INT) + (DEFVAR_KBOARD): Allocate a forwarding object. + * data.c (do_blv_forwarding, store_blv_forwarding): New macros. + (let_shadows_global_binding_p): New function. + (union Lisp_Val_Fwd): New type. + (make_blv): New function. + (swap_in_symval_forwarding, indirect_variable, do_symval_forwarding) + (store_symval_forwarding, swap_in_global_binding, Fboundp) + (swap_in_symval_forwarding, find_symbol_value, Fset) + (let_shadows_buffer_binding_p, set_internal, default_value) + (Fset_default, Fmake_variable_buffer_local, Fmake_local_variable) + (Fkill_local_variable, Fmake_variable_frame_local) + (Flocal_variable_p, Flocal_variable_if_set_p) + (Fvariable_binding_locus): + * xdisp.c (select_frame_for_redisplay): + * lread.c (Fintern, Funintern, init_obarray, defvar_int) + (defvar_bool, defvar_lisp_nopro, defvar_lisp, defvar_kboard): + * frame.c (store_frame_param): + * eval.c (Fdefvaralias, Fuser_variable_p, specbind, unbind_to): + * bytecode.c (Fbyte_code) : Adapt to the new symbol + value structure. + * buffer.c (PER_BUFFER_SYMBOL): Move from buffer.h. + (clone_per_buffer_values): Only adjust markers into the current buffer. + (reset_buffer_local_variables): PER_BUFFER_IDX is never -2. + (Fbuffer_local_value, set_buffer_internal_1) + (swap_out_buffer_local_variables): + Adapt to the new symbol value structure. + (DEFVAR_PER_BUFFER): Allocate a Lisp_Buffer_Objfwd object. + (defvar_per_buffer): Take a new arg for the fwd object. + (buffer_lisp_local_variables): Return a proper alist (different fix + for bug#4138). + * alloc.c (Fmake_symbol): Use SET_SYMBOL_VAL. + (Fgarbage_collect): Don't handle buffer_defaults specially. + (mark_object): Handle new symbol value structure rather than the old + special Lisp_Misc_* objects. + (gc_sweep) : Free also the buffer-local-value objects. + * term.c (set_tty_color_mode): + * bidi.c (bidi_initialize): Don't access the ->value field directly. + * buffer.h (PER_BUFFER_VAR_OFFSET): Don't bother with + a buffer_local_flags. + * print.c (print_object): Get rid of impossible forwarding objects. + +2010-04-19 Eli Zaretskii + + * bidi.c (bidi_get_type, bidi_get_category) + (bidi_at_paragraph_end, bidi_resolve_weak, bidi_resolve_neutral) + (bidi_type_of_next_char, bidi_level_of_next_char): + Declare static. Use `INLINE' rather than `inline'. 2010-04-19 Juanma Barranquero diff --cc src/fringe.c index 50d5a5c9747,2425e236b98..399779009dc --- a/src/fringe.c +++ b/src/fringe.c @@@ -1061,17 -1200,23 +1179,24 @@@ update_window_fringes (struct window *w left = row->left_user_fringe_bitmap; left_face_id = row->left_user_fringe_face_id; } - else if (row->truncated_on_left_p) + else if ((!row->reversed_p && row->truncated_on_left_p) + || (row->reversed_p && row->truncated_on_right_p)) left = LEFT_FRINGE(0, Qtruncation, 0); else if (row->indicate_bob_p && EQ (boundary_top, Qleft)) - left = ((row->indicate_eob_p && EQ (boundary_bot, Qleft)) - ? LEFT_FRINGE (1, Qtop_bottom, row->ends_at_zv_p) - : LEFT_FRINGE (2, Qtop, 0)); + { + left = ((row->indicate_eob_p && EQ (boundary_bot, Qleft)) + ? LEFT_FRINGE (1, Qtop_bottom, top_row_ends_at_zv_p) + : LEFT_FRINGE (2, Qtop, 0)); + if (top_ind_min_y >= 0) + left_offset = top_ind_min_y - row->y; + } else if (row->indicate_eob_p && EQ (boundary_bot, Qleft)) - left = LEFT_FRINGE (3, Qbottom, row->ends_at_zv_p); - else if ((!row->reversed_p && MATRIX_ROW_CONTINUATION_LINE_P (row)) - || (row->reversed_p && row->continued_p)) + { + left = LEFT_FRINGE (3, Qbottom, bot_row_ends_at_zv_p); + if (bot_ind_max_y >= 0) + left_offset = bot_ind_max_y - (row->y + row->visible_height); + } + else if (MATRIX_ROW_CONTINUATION_LINE_P (row)) left = LEFT_FRINGE (4, Qcontinuation, 0); else if (row->indicate_empty_line_p && EQ (empty_pos, Qleft)) left = LEFT_FRINGE (5, Qempty_line, 0); @@@ -1090,22 -1243,36 +1223,37 @@@ right = row->right_user_fringe_bitmap; right_face_id = row->right_user_fringe_face_id; } - else if (row->truncated_on_right_p) + else if ((!row->reversed_p && row->truncated_on_right_p) + || (row->reversed_p && row->truncated_on_left_p)) right = RIGHT_FRINGE (0, Qtruncation, 0); else if (row->indicate_bob_p && EQ (boundary_top, Qright)) - right = ((row->indicate_eob_p && EQ (boundary_bot, Qright)) - ? RIGHT_FRINGE (1, Qtop_bottom, row->ends_at_zv_p) - : RIGHT_FRINGE (2, Qtop, 0)); + { + right = ((row->indicate_eob_p && EQ (boundary_bot, Qright)) + ? RIGHT_FRINGE (1, Qtop_bottom, top_row_ends_at_zv_p) + : RIGHT_FRINGE (2, Qtop, 0)); + if (top_ind_min_y >= 0) + right_offset = top_ind_min_y - row->y; + } else if (row->indicate_eob_p && EQ (boundary_bot, Qright)) - right = RIGHT_FRINGE (3, Qbottom, row->ends_at_zv_p); - else if ((!row->reversed_p && row->continued_p) - || (row->reversed_p && MATRIX_ROW_CONTINUATION_LINE_P (row))) + { + right = RIGHT_FRINGE (3, Qbottom, bot_row_ends_at_zv_p); + if (bot_ind_max_y >= 0) + right_offset = bot_ind_max_y - (row->y + row->visible_height); + } + else if (row->continued_p) right = RIGHT_FRINGE (4, Qcontinuation, 0); else if (row->indicate_top_line_p && EQ (arrow_top, Qright)) - right = RIGHT_FRINGE (6, Qup, 0); + { + right = RIGHT_FRINGE (6, Qup, 0); + if (top_ind_min_y >= 0) + right_offset = top_ind_min_y - row->y; + } else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qright)) - right = RIGHT_FRINGE (7, Qdown, 0); + { + right = RIGHT_FRINGE (7, Qdown, 0); + if (bot_ind_max_y >= 0) + right_offset = bot_ind_max_y - (row->y + row->visible_height); + } else if (row->indicate_empty_line_p && EQ (empty_pos, Qright)) right = RIGHT_FRINGE (5, Qempty_line, 0); else diff --cc src/keyboard.c index 6ea0b90b9b4,056e379a44a..cddf04788a6 --- a/src/keyboard.c +++ b/src/keyboard.c @@@ -8996,15 -9172,20 +8995,15 @@@ keyremap_step (Lisp_Object *keybuf, in from the selected window's buffer. */ static int -read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, - can_return_switch_frame, fix_current_buffer) - Lisp_Object *keybuf; - int bufsize; - Lisp_Object prompt; - int dont_downcase_last; - int can_return_switch_frame; - int fix_current_buffer; +read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, + int dont_downcase_last, int can_return_switch_frame, + int fix_current_buffer) { - volatile Lisp_Object from_string; - volatile int count = SPECPDL_INDEX (); + Lisp_Object from_string; + int count = SPECPDL_INDEX (); /* How many keys there are in the current key sequence. */ - volatile int t; + int t; /* The length of the echo buffer when we started reading, and the length of this_command_keys when we started reading. */ diff --cc src/keymap.c index 1245caf3b9b,b5efd12cd6e..40005a51008 --- a/src/keymap.c +++ b/src/keymap.c @@@ -1126,11 -1175,13 +1126,13 @@@ DEFUN ("define-key", Fdefine_key, Sdefi doc: /* In KEYMAP, define key sequence KEY as DEF. KEYMAP is a keymap. - KEY is a string or a vector of symbols and characters meaning a + KEY is a string or a vector of symbols and characters, representing a sequence of keystrokes and events. Non-ASCII characters with codes - above 127 (such as ISO Latin-1) can be included if you use a vector. - Using [t] for KEY creates a default definition, which applies to any - event type that has no other definition in this keymap. + above 127 (such as ISO Latin-1) can be represented by vectors. + Two types of vector have special meanings: - [remap COMMAND] remaps any key binding for COMMAND in KEYMAP. ++ [remap COMMAND] remaps any key binding for COMMAND. + [t] creates a default definition, which applies to any event with no + other definition in KEYMAP. DEF is anything that can be a key's definition: nil (means key is undefined in this keymap), diff --cc src/w32fns.c index 916aea28eea,8fabb13fb82..c1791f2bf3e --- a/src/w32fns.c +++ b/src/w32fns.c @@@ -288,10 -288,13 +288,15 @@@ unsigned int msh_mousewheel = 0 #define MENU_FREE_DELAY 1000 static unsigned menu_free_timer = 0; + /* In dispnew.c */ + + extern Lisp_Object Vwindow_system_version; + /* The below are defined in frame.c. */ +extern Lisp_Object Vmenu_bar_mode, Vtool_bar_mode; +extern Lisp_Object Vwindow_system_version; + extern Lisp_Object Qtooltip; #ifdef GLYPH_DEBUG int image_cache_refcount, dpyinfo_refcount; diff --cc src/xdisp.c index d145e7bd9f6,73ed675c4d2..b6bd231bb67 --- a/src/xdisp.c +++ b/src/xdisp.c @@@ -6622,9 -6425,11 +6622,10 @@@ next_element_from_ellipsis (struct it * static int -next_element_from_image (it) - struct it *it; +next_element_from_image (struct it *it) { it->what = IT_IMAGE; + it->ignore_overlay_strings_at_pos_p = 0; return 1; } diff --cc src/xfns.c index 1dfaa381b3e,d06b83b5186..988725ead00 --- a/src/xfns.c +++ b/src/xfns.c @@@ -198,13 -203,9 +198,14 @@@ Lisp_Object Qfont_param extern Lisp_Object Vwindow_system_version; +/* In editfns.c */ + +extern Lisp_Object Vsystem_name; + /* The below are defined in frame.c. */ +extern Lisp_Object Vmenu_bar_mode, Vtool_bar_mode; + extern Lisp_Object Qtooltip; #if GLYPH_DEBUG int image_cache_refcount, dpyinfo_refcount;