elisp-vcs/dvc/lisp/dvc-xemacs.el
2009-10-10 08:02:43 +02:00

427 lines
16 KiB
EmacsLisp

;;; dvc-xemacs.el --- Compatibility stuff for XEmacs
;;;
;;; This file should be loaded when using XEmacs; load
;;; dvc-emacs.el when using Gnu Emacs.
;; Copyright (C) 2004-2006, 2008 by all contributors
;; Author: Robert Widhopf-Fenk <hack@robf.de>
;; This file is part of DVC.
;;
;; DVC is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;; DVC is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Policy: see dvc-emacs.el for policy on what goes in this file.
;;; Code:
(eval-when-compile
(require 'cl))
(eval-and-compile
(require 'overlay)
(require 'wid-edit)
;; The following require causes a infinite recursion as the (provide ...) is at
;; the file end. Thus we live with the warnings about unknown variables etc.
;;(require 'dvc-core)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; fixes warnings about undefined variables
(unless (boundp 'add-log-buffer-file-name-function)
(defvar add-log-buffer-file-name-function nil))
(unless (boundp 'add-log-file-name-function)
(defvar add-log-file-name-function nil))
(unless (boundp 'add-log-keep-changes-together)
(defvar add-log-keep-changes-together nil))
(unless (boundp 'global-font-lock-mode)
(defvar global-font-lock-mode nil))
(unless (boundp 'vc-ignore-vc-files)
(defvar vc-ignore-vc-files nil))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(unless (functionp 'add-log-file-name)
(defun add-log-file-name (buffer-file log-file)
;; Never want to add a change log entry for the ChangeLog file itself.
(unless (or (null buffer-file) (string= buffer-file log-file))
(if add-log-file-name-function
(funcall add-log-file-name-function buffer-file)
(setq buffer-file
(if (string-match
(concat "^" (regexp-quote (file-name-directory log-file)))
buffer-file)
(substring buffer-file (match-end 0))
(file-name-nondirectory buffer-file)))
;; If we have a backup file, it's presumably because we're
;; comparing old and new versions (e.g. for deleted
;; functions) and we'll want to use the original name.
(if (backup-file-name-p buffer-file)
(file-name-sans-versions buffer-file)
buffer-file)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; the unless check seems to fail
;;(unless (functionp 'replace-regexp-in-string)
(defun replace-regexp-in-string (regexp rep string
&optional fixedcase literal)
(replace-in-string string regexp rep literal))
;;)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(unless (functionp 'line-end-position)
(defun line-end-position ()
(save-excursion (end-of-line) (point))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(unless (functionp 'line-beginning-position)
(defun line-beginning-position (&optional n)
(save-excursion
(if n (forward-line n))
(beginning-of-line)
(point))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(unless (functionp 'mouse-set-point)
(defun mouse-set-point (event)
(goto-char (event-point event))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(unless (functionp 'match-string-no-properties)
(defun match-string-no-properties (arg &optional string)
(match-string arg string)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(unless (functionp 'clone-buffer)
(defun clone-buffer (&optional newname display-flag)
"Create a twin copy of the current buffer.
If NEWNAME is nil, it defaults to the current buffer's name;
NEWNAME is modified by adding or incrementing <N> at the end as necessary.
If DISPLAY-FLAG is non-nil, the new buffer is shown with `pop-to-buffer'.
This runs the normal hook `clone-buffer-hook' in the new buffer
after it has been set up properly in other respects."
(interactive (list (if current-prefix-arg (read-string "Name: "))
t))
(if buffer-file-name
(error "Cannot clone a file-visiting buffer"))
(if (get major-mode 'no-clone)
(error "Cannot clone a buffer in %s mode" mode-name))
(setq newname (or newname (buffer-name)))
(if (string-match "<[0-9]+>\\'" newname)
(setq newname (substring newname 0 (match-beginning 0))))
(let ((buf (current-buffer))
(ptmin (point-min))
(ptmax (point-max))
(pt (point))
(mk (mark t))
(modified (buffer-modified-p))
(mode major-mode)
(lvars (buffer-local-variables))
(process (get-buffer-process (current-buffer)))
(new (generate-new-buffer (or newname (buffer-name)))))
(save-restriction
(widen)
(with-current-buffer new
(insert-buffer-substring buf)))
(with-current-buffer new
(narrow-to-region ptmin ptmax)
(goto-char pt)
(if mk (set-mark mk))
(set-buffer-modified-p modified)
;; Clone the old buffer's process, if any.
(when process (clone-process process))
;; Now set up the major mode.
(funcall mode)
;; Set up other local variables.
(mapcar (lambda (v)
(condition-case () ;in case var is read-only
(if (symbolp v)
(makunbound v)
(set (make-local-variable (car v)) (cdr v)))
(error nil)))
lvars)
;; Run any hooks (typically set up by the major mode
;; for cloning to work properly).
(run-hooks 'clone-buffer-hook))
(if display-flag (pop-to-buffer new))
new)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(unless (functionp 'make-temp-file)
(defun make-temp-file (prefix &optional dir-flag)
"Create a temporary file.
The returned file name (created by `make-temp-name', is guaranteed to point to
a newly created empty file.
You can then use `write-region' to write new data into the file.
If DIR-FLAG is non-nil, create a new empty directory instead of a file."
(let (file)
(while (condition-case ()
(progn
(setq file
(make-temp-name
(expand-file-name prefix)))
(if dir-flag
(make-directory file)
(write-region "" nil file nil 'silent nil))
nil)
(file-already-exists t))
;; the file was somehow created by someone else between
;; `make-temp-name' and `write-region', let's try again.
nil)
file)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; AFAIK easy-menu cannot be used for dynamic menus
(defun dvc-xemacs-dvc-mode-p (buf)
"Helper function for menu-related functions.
Return t if BUF is a dvc-related buffer."
(if (bufferp buf)
(setq buf (format "%s" (symbol-value-in-buffer 'major-mode buf))))
(string-match "^dvc-" buf))
(defvar dvc-dead-process-buffer-queue nil)
(defun dvc-xemacs-buffers-menu (menu)
"Create the markers-menu.
MENU is the menu to which items should be added."
(interactive (list nil))
(let ((bufs (buffer-list))
(queue dvc-dead-process-buffer-queue)
queue-menu
b)
;; the user buffers
(while bufs
(setq b (car bufs)
bufs (cdr bufs))
(if (dvc-xemacs-dvc-mode-p b)
(setq menu (cons (vector (buffer-name b)
(list 'switch-to-buffer b) t)
menu))))
(setq menu (sort menu
(lambda (m1 m2) (string< (aref m1 0) (aref m2 0)))))
;; the queue buffers
(while queue
(setq b (car queue)
queue (cdr queue)
queue-menu (cons (vector (buffer-name b)
(list 'switch-to-buffer b) t)
queue-menu)))
(setq queue-menu (sort queue-menu
(lambda (m1 m2) (string< (aref m1 0) (aref m2 0)))))
;; combine menus
(setq menu (cons (append '("Queue") queue-menu) menu))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun dvc-group-buffers-menu-by-mode-then-alphabetically (buf1 buf2)
"For use as a value of `buffers-menu-grouping-function'.
This groups buffers by major mode. It only really makes sense if
`buffers-menu-sorting-function' is
'dvc-sort-buffers-menu-by-mode-then-alphabetically'.
(setq buffers-menu-grouping-function 'dvc-group-buffers-menu-by-mode-then-alphabetically)
BUF1 and BUF2 are successive members of the sorted buffers list after
being passed through `buffers-menu-sort-function'. It should return
non-nil if the second buffer begins a new group.
This is a modified version of
`group-buffers-menu-by-mode-then-alphabetically'
adding an submenu \"DVC\" containing all dvc buffers."
(cond ((and buf1 buf2
(not (dvc-xemacs-dvc-mode-p buf1))
(dvc-xemacs-dvc-mode-p buf2))
(if (string-match "\\`*" (buffer-name buf1))
"*Misc*"
(symbol-value-in-buffer 'mode-name buf1)))
((and buf1
(dvc-xemacs-dvc-mode-p buf1)
(or (not buf2)
(not (dvc-xemacs-dvc-mode-p buf2))))
"DVC")
((string-match "\\`*" (buffer-name buf1))
(and (null buf2) "*Misc*"))
((or (null buf2)
(string-match "\\`*" (buffer-name buf2))
(not (eq (symbol-value-in-buffer 'major-mode buf1)
(symbol-value-in-buffer 'major-mode buf2))))
(symbol-value-in-buffer 'mode-name buf1))
(t nil)))
(defun dvc-sort-buffers-menu-by-mode-then-alphabetically (buf1 buf2)
"For use as a value of `buffers-menu-sort-function'.
Sorts first by major mode and then alphabetically by name, but puts buffers
beginning with a star at the end of the list.
(setq buffers-menu-sort-function 'dvc-sort-buffers-menu-by-mode-then-alphabetically)
It will be passed two arguments BUF1 and BUF2 (two buffers to compare)
and will return t if the first is \"less\" than the second.
This is a modified version of `sort-buffers-menu-by-mode-then-alphabetically',
causing all *dvc-* buffers to be treated as having the same major mode."
(let* ((nam1 (buffer-name buf1))
(nam2 (buffer-name buf2))
(inv1p (not (null (string-match "\\` " nam1))))
(inv2p (not (null (string-match "\\` " nam2))))
(star1p (not (null (string-match "\\`*" nam1))))
(star2p (not (null (string-match "\\`*" nam2))))
(mode1 (symbol-value-in-buffer 'major-mode buf1))
(mode2 (symbol-value-in-buffer 'major-mode buf2)))
(if (dvc-xemacs-dvc-mode-p mode1)
(setq mode1 "dvc"))
(if (dvc-xemacs-dvc-mode-p mode1)
(setq mode2 "dvc"))
(cond ((not (eq inv1p inv2p))
(not inv1p))
((not (eq star1p star2p))
(not star1p))
((and star1p star2p (string-lessp nam1 nam2)))
((string-lessp mode1 mode2)
t)
((string-lessp mode2 mode1)
nil)
(t
(string-lessp nam1 nam2)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; since the custom.el coming with XEmacs does not know about the :inherit
;; keyword of defface we are dealing with it for our faces ...
(let ((faces (face-list)) face inherit)
(while faces
(setq face (car faces)
faces (cdr faces))
(when (string-match "^dvc-" (format "%s" face))
(setq inherit (assoc :inherit (car (custom-face-get-spec face))))
(if inherit
(set-face-parent face (cadr inherit))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(unless (functionp 'minibuffer-contents)
(defun minibuffer-contents ()
"Return the user input in a minbuffer as a string.
The current buffer must be a minibuffer."
(buffer-substring)))
(unless (functionp 'minibufferp)
(defun minibufferp ()
"Return non-nil if within a minibuffer."
(equal (selected-window)
(active-minibuffer-window))))
(unless (functionp 'diff-hunk-next)
(defalias 'diff-hunk-next 'diff-next-hunk))
(unless (functionp 'diff-hunk-prev)
(defalias 'diff-hunk-prev 'diff-prev-hunk))
(defalias 'dvc-expand-file-name 'expand-file-name)
;; FIXME: move to dvc-utils?
(defun dvc-xmas-make-temp-dir (prefix)
"Make a temporary directory using PREFIX.
Return the name of the directory."
(let ((dir (make-temp-name (expand-file-name prefix (temp-directory)))))
(make-directory dir)
dir))
(defalias 'dvc-make-temp-dir 'dvc-xmas-make-temp-dir)
;; From Gnus.
(defun dvc-xmas-move-overlay (extent start end &optional buffer)
(set-extent-endpoints extent start end buffer))
(defun dvc-xmas-kill-all-overlays ()
"Delete all extents in the current buffer."
(map-extents (lambda (extent ignore)
(delete-extent extent)
nil)))
(defun dvc-xmas-add-text-properties (start end props &optional object)
(add-text-properties start end props object)
(put-text-property start end 'start-closed nil object))
(defun dvc-xmas-put-text-property (start end prop value &optional object)
(put-text-property start end prop value object)
(put-text-property start end 'start-closed nil object))
(defun dvc-xmas-assq-delete-all (key alist)
(let ((elem nil))
(while (setq elem (assq key alist))
(setq alist (delq elem alist)))
alist))
(defalias 'dvc-make-overlay 'make-extent)
(defalias 'dvc-delete-overlay 'delete-extent)
(defalias 'dvc-overlay-put 'set-extent-property)
(defalias 'dvc-move-overlay 'dvc-xmas-move-overlay)
(defalias 'dvc-overlay-buffer 'extent-object)
(defalias 'dvc-overlay-start 'extent-start-position)
(defalias 'dvc-overlay-end 'extent-end-position)
(defalias 'dvc-kill-all-overlays 'dvc-xmas-kill-all-overlays)
(defalias 'dvc-extent-detached-p 'extent-detached-p)
(defalias 'dvc-add-text-properties 'dvc-xmas-add-text-properties)
(defalias 'dvc-put-text-property 'dvc-xmas-put-text-property)
(defalias 'dvc-deactivate-mark 'ignore)
(defalias 'dvc-window-edges 'window-pixel-edges)
(defalias 'dvc-assq-delete-all 'dvc-xmas-assq-delete-all)
(defconst dvc-mouse-face-prop 'highlight)
;; end from Gnus
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defalias 'dvc-line-number-at-pos (if (functionp 'line-number-at-pos)
'line-number-at-pos
'line-number))
(defvar allow-remote-paths nil)
(if (fboundp 'ewoc-delete)
(defalias 'dvc-ewoc-delete 'ewoc-delete)
(defun dvc-ewoc-delete (ewoc &rest nodes)
"Delete NODES from EWOC."
(ewoc--set-buffer-bind-dll-let* ewoc
((L nil) (R nil) (last (ewoc--last-node ewoc)))
(dolist (node nodes)
;; If we are about to delete the node pointed at by last-node,
;; set last-node to nil.
(when (eq last node)
(setf last nil (ewoc--last-node ewoc) nil))
(delete-region (ewoc--node-start-marker node)
(ewoc--node-start-marker (ewoc--node-next dll node)))
(set-marker (ewoc--node-start-marker node) nil)
(setf L (ewoc--node-left node)
R (ewoc--node-right node)
;; Link neighbors to each other.
(ewoc--node-right L) R
(ewoc--node-left R) L
;; Forget neighbors.
(ewoc--node-left node) nil
(ewoc--node-right node) nil)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(provide 'dvc-xemacs)
;; Local Variables:
;; End:
;;; dvc-xemacs.el ends here