]> code.delx.au - gnu-emacs/blobdiff - lisp/term/x-win.el
* term/x-win.el (x-select-text, x-cut-buffer-or-selection-value):
[gnu-emacs] / lisp / term / x-win.el
index e49836f0c2b76908485223d5c9988b676f51daef..0e68fa575eb9155616ccd347241910c33494666c 100644 (file)
@@ -1,6 +1,7 @@
 ;;; x-win.el --- parse relevant switches and set up for X  -*-coding: iso-2022-7bit;-*-
 
-;; Copyright (C) 1993, 1994, 2001, 2002 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 1994, 2001, 2002, 2003, 2004,
+;;   2005, 2006 Free Software Foundation, Inc.
 
 ;; Author: FSF
 ;; Keywords: terminals, i18n
@@ -19,8 +20,8 @@
 
 ;; 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., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
@@ -53,8 +54,6 @@
 ;; -font               *font
 ;; -foreground         *foreground
 ;; -geometry           .geometry
-;; -i                  .iconType
-;; -itype              .iconType
 ;; -iconic             .iconic
 ;; -name               .name
 ;; -reverse            *reverseVideo
 (require 'select)
 (require 'menu-bar)
 (require 'fontset)
+(require 'x-dnd)
 
 (defvar x-invocation-args)
+(defvar x-keysym-table)
+(defvar x-selection-timeout)
+(defvar x-session-id)
+(defvar x-session-previous-id)
 
 (defvar x-command-line-resources nil)
 
        (let ((param (nth 3 aelt)))
          (setq default-frame-alist
                (cons (cons param
-                           (string-to-int (car x-invocation-args)))
+                           (string-to-number (car x-invocation-args)))
                      default-frame-alist)
                x-invocation-args
                (cdr x-invocation-args))))))
                                  initial-frame-alist)))
 
 (defvar x-display-name nil
-  "The X display name specifying server and X frame.")
+  "The name of the X display on which Emacs was started.
+
+For the X display name of individual frames, see the `display'
+frame parameter.")
 
 (defun x-handle-display (switch)
+  "Handle -display DISPLAY option."
   (setq x-display-name (car x-invocation-args)
        x-invocation-args (cdr x-invocation-args))
   ;; Make subshell programs see the same DISPLAY value Emacs really uses.
@@ -1503,6 +1511,36 @@ as returned by `x-server-vendor'."
        (#x5f1 . ?\e,Gq\e(B)
        (#x5f2 . ?\e,Gr\e(B)
        ;; Cyrillic
+       (#x680 . ?\e$,1)R\e(B)
+       (#x681 . ?\e$,1)V\e(B)
+       (#x682 . ?\e$,1)Z\e(B)
+       (#x683 . ?\e$,1)\\e(B)
+       (#x684 . ?\e$,1)b\e(B)
+       (#x685 . ?\e$,1)n\e(B)
+       (#x686 . ?\e$,1)p\e(B)
+       (#x687 . ?\e$,1)r\e(B)
+       (#x688 . ?\e$,1)v\e(B)
+       (#x689 . ?\e$,1)x\e(B)
+       (#x68a . ?\e$,1)z\e(B)
+       (#x68c . ?\e$,1*8\e(B)
+       (#x68d . ?\e$,1*B\e(B)
+       (#x68e . ?\e$,1*H\e(B)
+       (#x68f . ?\e$,1*N\e(B)
+       (#x690 . ?\e$,1)S\e(B)
+       (#x691 . ?\e$,1)W\e(B)
+       (#x692 . ?\e$,1)[\e(B)
+       (#x693 . ?\e$,1)]\e(B)
+       (#x694 . ?\e$,1)c\e(B)
+       (#x695 . ?\e$,1)o\e(B)
+       (#x696 . ?\e$,1)q\e(B)
+       (#x697 . ?\e$,1)s\e(B)
+       (#x698 . ?\e$,1)w\e(B)
+       (#x699 . ?\e$,1)y\e(B)
+       (#x69a . ?\e$,1){\e(B)
+       (#x69c . ?\e$,1*9\e(B)
+       (#x69d . ?\e$,1*C\e(B)
+       (#x69e . ?\e$,1*I\e(B)
+       (#x69f . ?\e$,1*O\e(B)
        (#x6a1 . ?\e,Lr\e(B)
        (#x6a2 . ?\e,Ls\e(B)
        (#x6a3 . ?\e,Lq\e(B)
@@ -2082,12 +2120,12 @@ as returned by `x-server-vendor'."
 \f
 ;;;; Selections and cut buffers
 
-;;; We keep track of the last text selected here, so we can check the
-;;; current selection against it, and avoid passing back our own text
-;;; from x-cut-buffer-or-selection-value.  We track all three
-;;; seperately in case another X application only sets one of them
-;;; (say the cut buffer) we aren't fooled by the PRIMARY or
-;;; CLIPBOARD selection staying the same.
+;; We keep track of the last text selected here, so we can check the
+;; current selection against it, and avoid passing back our own text
+;; from x-cut-buffer-or-selection-value.  We track all three
+;; seperately in case another X application only sets one of them
+;; (say the cut buffer) we aren't fooled by the PRIMARY or
+;; CLIPBOARD selection staying the same.
 (defvar x-last-selected-text-clipboard nil
   "The value of the CLIPBOARD X selection last time we selected or
 pasted text.")
@@ -2095,12 +2133,15 @@ pasted text.")
   "The value of the PRIMARY X selection last time we selected or
 pasted text.")
 (defvar x-last-selected-text-cut nil
-  "The value of the X cut buffer last time we selected or pasted text.")
+  "The value of the X cut buffer last time we selected or pasted text.
+The actual text stored in the X cut buffer is what encoded from this value.")
+(defvar x-last-selected-text-cut-encoded nil
+  "The value of the X cut buffer last time we selected or pasted text.
+This is the actual text stored in the X cut buffer.")
 
-;;; It is said that overlarge strings are slow to put into the cut buffer.
-;;; Note this value is overridden below.
-(defvar x-cut-buffer-max 20000
-  "Max number of characters to put in the cut buffer.")
+(defvar x-cut-buffer-max 20000 ; Note this value is overridden below.
+  "Max number of characters to put in the cut buffer.
+It is said that overlarge strings are slow to put into the cut buffer.")
 
 (defcustom x-select-enable-clipboard nil
   "Non-nil means cutting and pasting uses the clipboard.
@@ -2108,29 +2149,24 @@ This is in addition to, but in preference to, the primary selection."
   :type 'boolean
   :group 'killing)
 
-;;; Make TEXT, a string, the primary X selection.
-;;; Also, set the value of X cut buffer 0, for backward compatibility
-;;; with older X applications.
-;;; gildea@stop.mail-abuse.org says it's not desirable to put kills
-;;; in the clipboard.
 (defun x-select-text (text &optional push)
+  "Make TEXT, a string, the primary X selection.
+Also, set the value of X cut buffer 0, for backward compatibility
+with older X applications.
+gildea@stop.mail-abuse.org says it's not desirable to put kills
+in the clipboard."
   ;; Don't send the cut buffer too much text.
   ;; It becomes slow, and if really big it causes errors.
   (cond ((>= (length text) x-cut-buffer-max)
         (x-set-cut-buffer "" push)
-        (setq x-last-selected-text-cut ""))
-       ;; Don't store a multibyte string that contains
-       ;; eight-bit-control/graphic chars because they can't be
-       ;; restored correctly by x-get-cut-buffer.
-       ((and (multibyte-string-p text)
-             (let ((charsets (find-charset-string text)))
-               (or (memq 'eight-bit-control charsets)
-                   (memq 'eight-bit-graphic charsets))))
-        (x-set-cut-buffer "" push)
-        (setq x-last-selected-text-cut ""))
+        (setq x-last-selected-text-cut ""
+              x-last-selected-text-cut-encoded ""))
        (t
-        (x-set-cut-buffer text push)
-        (setq x-last-selected-text-cut text)))
+        (setq x-last-selected-text-cut text
+              x-last-selected-text-cut-encoded
+              ;; ICCCM says cut buffer always contain ISO-Latin-1
+              (encode-coding-string text 'iso-latin-1))
+        (x-set-cut-buffer x-last-selected-text-cut-encoded push)))
   (x-set-selection 'PRIMARY text)
   (setq x-last-selected-text-primary text)
   (when x-select-enable-clipboard
@@ -2138,24 +2174,121 @@ This is in addition to, but in preference to, the primary selection."
     (setq x-last-selected-text-clipboard text))
   )
 
-;;; Return the value of the current X selection.
-;;; Consult the selection, and the cut buffer.  Treat empty strings
-;;; as if they were unset.
-;;; If this function is called twice and finds the same text,
-;;; it returns nil the second time.  This is so that a single
-;;; selection won't be added to the kill ring over and over.
+(defvar x-select-request-type nil
+  "*Data type request for X selection.
+The value is nil, one of the following data types, or a list of them:
+  `COMPOUND_TEXT', `UTF8_STRING', `STRING', `TEXT'
+
+If the value is nil, try `COMPOUND_TEXT' and `UTF8_STRING', and
+use the more appropriate result.  If both fail, try `STRING', and
+then `TEXT'.
+
+If the value is one of the above symbols, try only the specified
+type.
+
+If the value is a list of them, try each of them in the specified
+order until succeed.")
+
+;; Helper function for x-selection-value.  Select UTF8 or CTEXT
+;; whichever is more appropriate.  Here, we use this heurisitcs.
+;;
+;;   (1) If their lengthes are different, select the longer one.  This
+;;   is because an X client may just cut off unsupported characters.
+;;
+;;   (2) Otherwise, if the Nth character of CTEXT is an ASCII
+;;   character that is different from the Nth character of UTF8,
+;;   select UTF8.  This is because an X client may replace unsupported
+;;   characters with some ASCII character (typically ` ' or `?') in
+;;   CTEXT.
+;;
+;;   (3) Otherwise, select CTEXT.  This is because legacy charsets are
+;;   better for the current Emacs, especially when the selection owner
+;;   is also Emacs.
+
+(defun x-select-utf8-or-ctext (utf8 ctext)
+  (let ((len-utf8 (length utf8))
+       (len-ctext (length ctext))
+       (selected ctext)
+       (i 0)
+       char)
+    (if (/= len-utf8 len-ctext)
+       (if (> len-utf8 len-ctext) utf8 ctext)
+      (let ((result (compare-strings utf8 0 len-utf8 ctext 0 len-ctext)))
+       (if (or (eq result t)
+               (>= (aref ctext (1- (abs result))) 128))
+           ctext
+         utf8)))))
+
+;; Get a selection value of type TYPE by calling x-get-selection with
+;; an appropiate DATA-TYPE argument decidd by `x-select-request-type'.
+;; The return value is already decoded.  If x-get-selection causes an
+;; error, this function return nil.
+
+(defun x-selection-value (type)
+  (let (text)
+    (cond ((null x-select-request-type)
+          (let (utf8 ctext utf8-coding)
+            ;; We try both UTF8_STRING and COMPOUND_TEXT, and choose
+            ;; the more appropriate one.  If both fail, try STRING.
+
+            ;; At first try UTF8_STRING.
+            (setq utf8 (condition-case nil
+                           (x-get-selection type 'UTF8_STRING)
+                         (error nil))
+                  utf8-coding last-coding-system-used)
+            (if utf8
+                ;; If it is a local selection, or it contains only
+                ;; ASCII characers, choose it.
+                (if (or (not (get-text-property 0 'foreign-selection utf8))
+                        (= (length utf8) (string-bytes utf8)))
+                    (setq text utf8)))
+            ;; If not yet decided, try COMPOUND_TEXT.
+            (if (not text)
+                (if (setq ctext (condition-case nil
+                                    (x-get-selection type 'COMPOUND_TEXT)
+                                  (error nil)))
+                    ;; If UTF8_STRING was also successful, choose the
+                    ;; more appropriate one from UTF8 and CTEXT.
+                    (if utf8
+                        (setq text (x-select-utf8-or-ctext utf8 ctext))
+                      ;; Othewise, choose CTEXT.
+                      (setq text ctext))
+                  (setq text utf8)))
+            ;; If not yet decided, try STRING.
+            (or text
+                (setq text (condition-case nil
+                               (x-get-selection type 'STRING)
+                             (error nil))))
+            (if (eq text utf8)
+                (setq last-coding-system-used utf8-coding))))
+
+         ((consp x-select-request-type)
+          (let ((tail x-select-request-type))
+            (while (and tail (not text))
+              (condition-case nil
+                  (setq text (x-get-selection type (car tail)))
+                (error nil))
+              (setq tail (cdr tail)))))
+
+         (t
+          (condition-case nil
+              (setq text (x-get-selection type x-select-request-type))
+            (error nil))))
+
+    (if text
+       (remove-text-properties 0 (length text) '(foreign-selection nil) text))
+    text))
+
+;; Return the value of the current X selection.
+;; Consult the selection, and the cut buffer.  Treat empty strings
+;; as if they were unset.
+;; If this function is called twice and finds the same text,
+;; it returns nil the second time.  This is so that a single
+;; selection won't be added to the kill ring over and over.
 (defun x-cut-buffer-or-selection-value ()
   (let (clip-text primary-text cut-text)
     (when x-select-enable-clipboard
-      ;; Don't die if x-get-selection signals an error.
-      (if (null clip-text)
-         (condition-case c
-             (setq clip-text (x-get-selection 'CLIPBOARD 'COMPOUND_TEXT))
-           (error nil)))
-      (if (null clip-text)
-         (condition-case c
-             (setq clip-text (x-get-selection 'CLIPBOARD 'STRING))
-           (error nil)))
+      (setq clip-text (x-selection-value 'CLIPBOARD))
       (if (string= clip-text "") (setq clip-text nil))
 
       ;; Check the CLIPBOARD selection for 'newness', is it different
@@ -2175,15 +2308,7 @@ This is in addition to, but in preference to, the primary selection."
              (setq x-last-selected-text-clipboard clip-text))))
       )
 
-    ;; Don't die if x-get-selection signals an error.
-    (if (null primary-text)
-       (condition-case c
-           (setq primary-text (x-get-selection 'PRIMARY 'COMPOUND_TEXT))
-         (error nil)))
-    (if (null primary-text)
-       (condition-case c
-           (setq primary-text (x-get-selection 'PRIMARY 'STRING))
-         (error nil)))
+    (setq primary-text (x-selection-value 'PRIMARY))
     ;; Check the PRIMARY selection for 'newness', is it different
     ;; from what we remebered them to be last time we did a
     ;; cut/paste operation.
@@ -2206,17 +2331,26 @@ This is in addition to, but in preference to, the primary selection."
     ;; from what we remebered them to be last time we did a
     ;; cut/paste operation.
     (setq cut-text
-         (cond;; check primary selection
+         (cond;; check cut buffer
           ((or (not cut-text) (string= cut-text ""))
            (setq x-last-selected-text-cut nil))
-          ((eq      cut-text x-last-selected-text-cut) nil)
-          ((string= cut-text x-last-selected-text-cut)
+          ;; This short cut doesn't work because x-get-cut-buffer
+          ;; always returns a newly created string.
+          ;; ((eq      cut-text x-last-selected-text-cut) nil)
+          ((string= cut-text x-last-selected-text-cut-encoded)
+           ;; See the comment above.  No need of this recording.
            ;; Record the newer string,
            ;; so subsequent calls can use the `eq' test.
-           (setq x-last-selected-text-cut cut-text)
-      nil)
-     (t
-           (setq x-last-selected-text-cut cut-text))))
+           ;; (setq x-last-selected-text-cut cut-text)
+           nil)
+          (t
+           (setq x-last-selected-text-cut-encoded cut-text
+                 x-last-selected-text-cut
+                 ;; ICCCM says cut buffer always contain ISO-Latin-1
+                 (decode-coding-string cut-text 'iso-latin-1)))))
+
+    ;; As we have done one selection, clear this now.
+    (setq next-selection-coding-system nil)
 
     ;; At this point we have recorded the current values for the
     ;; selection from clipboard (if we are supposed to) primary,
@@ -2242,12 +2376,12 @@ This is in addition to, but in preference to, the primary selection."
     ))
 
 \f
-;;; Do the actual X Windows setup here; the above code just defines
-;;; functions and variables that we use now.
+;; Do the actual X Windows setup here; the above code just defines
+;; functions and variables that we use now.
 
 (setq command-line-args (x-handle-args command-line-args))
 
-;;; Make sure we have a valid resource name.
+;; Make sure we have a valid resource name.
 (or (stringp x-resource-name)
     (let (i)
       (setq x-resource-name (invocation-name))
@@ -2299,12 +2433,6 @@ This is in addition to, but in preference to, the primary selection."
        ;; generated from FONT.
        (create-fontset-from-ascii-font font resolved-name "startup"))))
 
-;; Sun expects the menu bar cut and paste commands to use the clipboard.
-;; This has ,? to match both on Sunos and on Solaris.
-(if (string-match "Sun Microsystems,? Inc\\."
-                 (x-server-vendor))
-    (menu-bar-enable-clipboard))
-
 ;; Apply a geometry resource to the initial frame.  Put it at the end
 ;; of the alist, so that anything specified on the command line takes
 ;; precedence.
@@ -2320,12 +2448,15 @@ This is in addition to, but in preference to, the primary selection."
                               (cons '(user-size . t) parsed))))
        ;; All geometry parms apply to the initial frame.
        (setq initial-frame-alist (append initial-frame-alist parsed))
-       ;; The size parms apply to all frames.
-       (if (assq 'height parsed)
+       ;; The size parms apply to all frames.  Don't set it if there are
+       ;; sizes there already (from command line).
+       (if (and (assq 'height parsed)
+                (not (assq 'height default-frame-alist)))
            (setq default-frame-alist
                  (cons (cons 'height (cdr (assq 'height parsed)))
                        default-frame-alist)))
-       (if (assq 'width parsed)
+       (if (and (assq 'width parsed)
+                (not (assq 'width default-frame-alist)))
            (setq default-frame-alist
                  (cons (cons 'width (cdr (assq 'width parsed)))
                        default-frame-alist))))))
@@ -2349,12 +2480,12 @@ This is in addition to, but in preference to, the primary selection."
   (error "Suspending an Emacs running under X makes no sense"))
 (add-hook 'suspend-hook 'x-win-suspend-error)
 
-;;; Arrange for the kill and yank functions to set and check the clipboard.
+;; Arrange for the kill and yank functions to set and check the clipboard.
 (setq interprogram-cut-function 'x-select-text)
 (setq interprogram-paste-function 'x-cut-buffer-or-selection-value)
 
-;;; Turn off window-splitting optimization; X is usually fast enough
-;;; that this is only annoying.
+;; Turn off window-splitting optimization; X is usually fast enough
+;; that this is only annoying.
 (setq split-window-keep-point t)
 
 ;; Don't show the frame name; that's redundant with X.
@@ -2370,4 +2501,38 @@ This is in addition to, but in preference to, the primary selection."
 ;; Turn on support for mouse wheels.
 (mouse-wheel-mode 1)
 
+
+;; Enable CLIPBOARD copy/paste through menu bar commands.
+(menu-bar-enable-clipboard)
+
+;; Override Paste so it looks at CLIPBOARD first.
+(defun x-clipboard-yank ()
+  "Insert the clipboard contents, or the last stretch of killed text."
+  (interactive "*")
+  (let ((clipboard-text (x-selection-value 'CLIPBOARD))
+       (x-select-enable-clipboard t))
+    (if (and clipboard-text (> (length clipboard-text) 0))
+       (kill-new clipboard-text))
+    (yank)))
+
+(define-key menu-bar-edit-menu [paste]
+  '(menu-item "Paste" x-clipboard-yank
+             :enable (not buffer-read-only)
+             :help "Paste (yank) text most recently cut/copied"))
+
+;; Initiate drag and drop
+(add-hook 'after-make-frame-functions 'x-dnd-init-frame)
+(define-key special-event-map [drag-n-drop] 'x-dnd-handle-drag-n-drop-event)
+
+;; Let F10 do menu bar navigation.
+(defun x-menu-bar-open (&optional frame)
+  "Open the menu bar if `menu-bar-mode' is on. otherwise call `tmm-menubar'."
+  (interactive "i")
+  (if menu-bar-mode (menu-bar-open frame)
+    (tmm-menubar)))
+                  
+(and (fboundp 'menu-bar-open)
+     (global-set-key [f10] 'x-menu-bar-open))
+
+;; arch-tag: f1501302-db8b-4d95-88e3-116697d89f78
 ;;; x-win.el ends here