]> code.delx.au - gnu-emacs/blobdiff - lisp/org/org-compat.el
Merge from emacs-23
[gnu-emacs] / lisp / org / org-compat.el
index f0d0904b735e2e6f4c9c96a8cba72b7f961e3296..b739d6d1b1eda3818abef41ba98af6d17a296a91 100644 (file)
@@ -6,7 +6,7 @@
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.33x
+;; Version: 7.4
 ;;
 ;; This file is part of GNU Emacs.
 ;;
 (declare-function find-library-name "find-func"  (library))
 (declare-function w32-focus-frame "term/w32-win" (frame))
 
-(defconst org-xemacs-p (featurep 'xemacs)) ; not used by org.el itself
+;; The following constant is for backward compatibility.  We do not use
+;; it in org-mode, because the Byte compiler evaluates (featurep 'xemacs)
+;; at compilation time and can therefore optimize code better.
+(defconst org-xemacs-p (featurep 'xemacs))
 (defconst org-format-transports-properties-p
   (let ((x "a"))
     (add-text-properties 0 1 '(test t) x)
@@ -86,25 +89,44 @@ any other entries, and any resulting duplicates will be removed entirely."
    (t specs)))
 (put 'org-compatible-face 'lisp-indent-function 1)
 
+(defun org-version-check (version feature level)
+  (let* ((v1 (mapcar 'string-to-number (split-string version "[.]")))
+        (v2 (mapcar 'string-to-number (split-string emacs-version "[.]")))
+        (rmaj (or (nth 0 v1) 99))
+        (rmin (or (nth 1 v1) 99))
+        (rbld (or (nth 2 v1) 99))
+        (maj (or (nth 0 v2) 0))
+        (min (or (nth 1 v2) 0))
+        (bld (or (nth 2 v2) 0)))
+    (if (or (< maj rmaj)
+           (and (= maj rmaj)
+                (< min rmin))
+           (and (= maj rmaj)
+                (= min rmin)
+                (< bld rbld)))
+       (if (eq level :predicate)
+           ;; just return if we have the version
+           nil
+         (let ((msg (format "Emacs %s or greater is recommended for %s"
+                            version feature)))
+           (display-warning 'org msg level)
+           t))
+      t)))
+
 ;;;; Emacs/XEmacs compatibility
 
+;; Keys
+(defconst org-xemacs-key-equivalents
+  '(([mouse-1] . [button1])
+    ([mouse-2] . [button2])
+    ([mouse-3] . [button3])
+    ([C-mouse-4] . [(control mouse-4)])
+    ([C-mouse-5] . [(control mouse-5)]))
+  "Translation alist for a couple of keys.")
+
 ;; Overlay compatibility functions
-(defun org-make-overlay (beg end &optional buffer)
-  (if (featurep 'xemacs)
-      (make-extent beg end buffer)
-    (make-overlay beg end buffer)))
-(defun org-delete-overlay (ovl)
-  (if (featurep 'xemacs) (progn (delete-extent ovl) nil) (delete-overlay ovl)))
 (defun org-detach-overlay (ovl)
   (if (featurep 'xemacs) (detach-extent ovl) (delete-overlay ovl)))
-(defun org-move-overlay (ovl beg end &optional buffer)
-  (if (featurep 'xemacs)
-      (set-extent-endpoints ovl beg end (or buffer (current-buffer)))
-    (move-overlay ovl beg end buffer)))
-(defun org-overlay-put (ovl prop value)
-  (if (featurep 'xemacs)
-      (set-extent-property ovl prop value)
-    (overlay-put ovl prop value)))
 (defun org-overlay-display (ovl text &optional face evap)
   "Make overlay OVL display TEXT with face FACE."
   (if (featurep 'xemacs)
@@ -124,32 +146,33 @@ any other entries, and any resulting duplicates will be removed entirely."
     (if face (org-add-props text nil 'face face))
     (overlay-put ovl 'before-string text)
     (if evap (overlay-put ovl 'evaporate t))))
-(defun org-overlay-get (ovl prop)
-  (if (featurep 'xemacs)
-      (extent-property ovl prop)
-    (overlay-get ovl prop)))
-(defun org-overlays-at (pos)
-  (if (featurep 'xemacs) (extents-at pos) (overlays-at pos)))
-(defun org-overlays-in (&optional start end)
-  (if (featurep 'xemacs)
-      (extent-list nil start end)
-    (overlays-in start end)))
-(defun org-overlay-start (o)
-  (if (featurep 'xemacs) (extent-start-position o) (overlay-start o)))
-(defun org-overlay-end (o)
-  (if (featurep 'xemacs) (extent-end-position o) (overlay-end o)))
-(defun org-overlay-buffer (o)
-  (if (featurep 'xemacs) (extent-buffer o) (overlay-buffer o)))
 (defun org-find-overlays (prop &optional pos delete)
   "Find all overlays specifying PROP at POS or point.
 If DELETE is non-nil, delete all those overlays."
-  (let ((overlays (org-overlays-at (or pos (point))))
+  (let ((overlays (overlays-at (or pos (point))))
        ov found)
     (while (setq ov (pop overlays))
-      (if (org-overlay-get ov prop)
-          (if delete (org-delete-overlay ov) (push ov found))))
+      (if (overlay-get ov prop)
+          (if delete (delete-overlay ov) (push ov found))))
     found))
 
+(defun org-get-x-clipboard (value)
+  "Get the value of the x clipboard, compatible with XEmacs, and GNU Emacs 21."
+  (if (eq window-system 'x)
+      (let ((x (org-get-x-clipboard-compat value)))
+       (if x (org-no-properties x)))))
+
+(defsubst org-decompose-region (beg end)
+  "Decompose from BEG to END."
+  (if (featurep 'xemacs)
+      (let ((modified-p (buffer-modified-p))
+           (buffer-read-only nil))
+       (remove-text-properties beg end '(composition nil))
+       (set-buffer-modified-p modified-p))
+    (decompose-region beg end)))
+
+;; Miscellaneous functions
+
 (defun org-add-hook (hook function &optional append local)
   "Add-hook, compatible with both Emacsen."
   (if (and local (featurep 'xemacs))
@@ -170,7 +193,7 @@ that will be added to PLIST.  Returns the string that was modified."
   "Fit WINDOW to the buffer, but only if it is not a side-by-side window.
 WINDOW defaults to the selected window.  MAX-HEIGHT and MIN-HEIGHT are
 passed through to `fit-window-to-buffer'.  If SHRINK-ONLY is set, call
-`shrink-window-if-larger-than-buffer' instead, the hight limit are
+`shrink-window-if-larger-than-buffer' instead, the height limit is
 ignored in this case."
   (cond ((if (fboundp 'window-full-width-p)
             (not (window-full-width-p window))
@@ -183,6 +206,26 @@ ignored in this case."
         (shrink-window-if-larger-than-buffer window)))
   (or window (selected-window)))
 
+(defun org-number-sequence (from &optional to inc)
+  "Call `number-sequence or emulate it."
+  (if (fboundp 'number-sequence)
+      (number-sequence from to inc)
+    (if (or (not to) (= from to))
+       (list from)
+      (or inc (setq inc 1))
+      (when (zerop inc) (error "The increment can not be zero"))
+      (let (seq (n 0) (next from))
+       (if (> inc 0)
+           (while (<= next to)
+             (setq seq (cons next seq)
+                   n (1+ n)
+                   next (+ from (* n inc))))
+         (while (>= next to)
+           (setq seq (cons next seq)
+                 n (1+ n)
+                 next (+ from (* n inc)))))
+       (nreverse seq)))))
+
 ;; Region compatibility
 
 (defvar org-ignore-region nil
@@ -206,19 +249,6 @@ Works on both Emacs and XEmacs."
 
 ;; Invisibility compatibility
 
-(defun org-add-to-invisibility-spec (arg)
-  "Add elements to `buffer-invisibility-spec'.
-See documentation for `buffer-invisibility-spec' for the kind of elements
-that can be added."
-  (cond
-   ((fboundp 'add-to-invisibility-spec)
-    (add-to-invisibility-spec arg))
-   ((or (null buffer-invisibility-spec) (eq buffer-invisibility-spec t))
-    (setq buffer-invisibility-spec (list arg)))
-   (t
-    (setq buffer-invisibility-spec
-         (cons arg buffer-invisibility-spec)))))
-
 (defun org-remove-from-invisibility-spec (arg)
   "Remove elements from `buffer-invisibility-spec'."
   (if (fboundp 'remove-from-invisibility-spec)
@@ -233,62 +263,42 @@ that can be added."
       (member arg buffer-invisibility-spec)
     nil))
 
+(defmacro org-xemacs-without-invisibility (&rest body)
+  "Turn off exents with invisibility while executing BODY."
+  `(let ((ext-inv (extent-list nil (point-at-bol) (point-at-eol)
+                              'all-extents-closed-open 'invisible))
+        ext-inv-specs)
+     (dolist (ext ext-inv)
+       (when (extent-property ext 'invisible)
+        (add-to-list 'ext-inv-specs (list ext (extent-property
+                                               ext 'invisible)))
+        (set-extent-property ext 'invisible nil)))
+     ,@body
+     (dolist (ext-inv-spec ext-inv-specs)
+       (set-extent-property (car ext-inv-spec) 'invisible
+                           (cadr ext-inv-spec)))))
+
 (defun org-indent-to-column (column &optional minimum buffer)
   "Work around a bug with extents with invisibility in XEmacs."
   (if (featurep 'xemacs)
-      (let ((ext-inv (extent-list
-                     nil (point-at-bol) (point-at-eol)
-                     'all-extents-closed-open 'invisible))
-           ext-inv-specs)
-       (dolist (ext ext-inv)
-         (when (extent-property ext 'invisible)
-           (add-to-list 'ext-inv-specs (list ext (extent-property
-                                                  ext 'invisible)))
-           (set-extent-property ext 'invisible nil)))
-       (indent-to-column column minimum buffer)
-       (dolist (ext-inv-spec ext-inv-specs)
-         (set-extent-property (car ext-inv-spec) 'invisible
-                              (cadr ext-inv-spec))))
+      (org-xemacs-without-invisibility (indent-to-column column minimum buffer))
     (indent-to-column column minimum)))
 
 (defun org-indent-line-to (column)
   "Work around a bug with extents with invisibility in XEmacs."
   (if (featurep 'xemacs)
-      (let ((ext-inv (extent-list
-                     nil (point-at-bol) (point-at-eol)
-                     'all-extents-closed-open 'invisible))
-           ext-inv-specs)
-       (dolist (ext ext-inv)
-         (when (extent-property ext 'invisible)
-           (add-to-list 'ext-inv-specs (list ext (extent-property
-                                                  ext 'invisible)))
-           (set-extent-property ext 'invisible nil)))
-       (indent-line-to column)
-       (dolist (ext-inv-spec ext-inv-specs)
-         (set-extent-property (car ext-inv-spec) 'invisible
-                              (cadr ext-inv-spec))))
+      (org-xemacs-without-invisibility (indent-line-to column))
     (indent-line-to column)))
 
 (defun org-move-to-column (column &optional force buffer)
   (if (featurep 'xemacs)
-      (let ((ext-inv (extent-list
-                     nil (point-at-bol) (point-at-eol)
-                     'all-extents-closed-open 'invisible))
-           ext-inv-specs)
-       (dolist (ext ext-inv)
-         (when (extent-property ext 'invisible)
-           (add-to-list 'ext-inv-specs (list ext (extent-property ext
-                                                                  'invisible)))
-           (set-extent-property ext 'invisible nil)))
-       (move-to-column column force buffer)
-       (dolist (ext-inv-spec ext-inv-specs)
-         (set-extent-property (car ext-inv-spec) 'invisible
-                              (cadr ext-inv-spec))))
+      (org-xemacs-without-invisibility (move-to-column column force buffer))
     (move-to-column column force)))
 
 (defun org-get-x-clipboard-compat (value)
-  "Get the clipboard value on XEmacs or Emacs 21"
-  (cond (org-xemacs-p (org-no-warnings (get-selection-no-error value)))
+  "Get the clipboard value on XEmacs or Emacs 21."
+  (cond ((featurep 'xemacs)
+        (org-no-warnings (get-selection-no-error value)))
        ((fboundp 'x-get-selection)
         (condition-case nil
             (or (x-get-selection value 'UTF8_STRING)
@@ -362,6 +372,58 @@ TIME defaults to the current time."
       (time-to-seconds (or time (current-time)))
     (float-time time)))
 
+(if (fboundp 'string-match-p)
+    (defalias 'org-string-match-p 'string-match-p)
+  (defun org-string-match-p (regexp string &optional start)
+    (save-match-data
+      (funcall 'string-match regexp string start))))
+
+(if (fboundp 'looking-at-p)
+    (defalias 'org-looking-at-p 'looking-at-p)
+  (defun org-looking-at-p (&rest args)
+    (save-match-data
+      (apply 'looking-at args))))
+
+; XEmacs does not have `looking-back'.
+(if (fboundp 'looking-back)
+    (defalias 'org-looking-back 'looking-back)
+  (defun org-looking-back (regexp &optional limit greedy)
+    "Return non-nil if text before point matches regular expression REGEXP.
+Like `looking-at' except matches before point, and is slower.
+LIMIT if non-nil speeds up the search by specifying a minimum
+starting position, to avoid checking matches that would start
+before LIMIT.
+
+If GREEDY is non-nil, extend the match backwards as far as
+possible, stopping when a single additional previous character
+cannot be part of a match for REGEXP.  When the match is
+extended, its starting position is allowed to occur before
+LIMIT."
+    (let ((start (point))
+         (pos
+          (save-excursion
+            (and (re-search-backward (concat "\\(?:" regexp "\\)\\=") limit t)
+                 (point)))))
+      (if (and greedy pos)
+         (save-restriction
+           (narrow-to-region (point-min) start)
+           (while (and (> pos (point-min))
+                       (save-excursion
+                         (goto-char pos)
+                         (backward-char 1)
+                         (looking-at (concat "\\(?:"  regexp "\\)\\'"))))
+             (setq pos (1- pos)))
+           (save-excursion
+             (goto-char pos)
+             (looking-at (concat "\\(?:"  regexp "\\)\\'")))))
+      (not (null pos)))))
+
+(defun org-floor* (x &optional y)
+  "Return a list of the floor of X and the fractional part of X.
+With two arguments, return floor and remainder of their quotient."
+  (let ((q (floor x y)))
+    (list q (- x (if y (* y q) q)))))
+
 (provide 'org-compat)
 
 ;; arch-tag: a0a0579f-e68c-4bdf-9e55-93768b846bbe