=== modified file 'configure.in' --- configure.in 2011-07-13 10:36:12 +0000 +++ configure.in 2011-07-17 10:24:18 +0000 @@ -168,6 +168,7 @@ OPTION_DEFAULT_ON([xaw3d],[don't use Xaw3d]) OPTION_DEFAULT_ON([xim],[don't use X11 XIM]) OPTION_DEFAULT_OFF([ns],[use NeXTstep (Cocoa or GNUstep) windowing system]) +OPTION_DEFAULT_OFF([w32], [use a Win32]) OPTION_DEFAULT_ON([gpm],[don't use -lgpm for mouse support on a GNU/Linux console]) OPTION_DEFAULT_ON([dbus],[don't compile with D-Bus support]) @@ -1534,6 +1535,7 @@ NS_HAVE_NSINTEGER=no fi fi + AC_SUBST(TEMACS_LDFLAGS2) ns_frag=/dev/null @@ -1559,6 +1561,31 @@ AC_SUBST(LIB_STANDARD) AC_SUBST_FILE(ns_frag) +HAVE_W32=no +W32_OBJ= +W32_LIBS= +if test "${with_w32}" != no; then + if test "${opsys}" != "cygwin"; then + AC_MSG_ERROR([Using win32 with an autotools build is only supported for Cygwin.]) + fi + AC_CHECK_HEADER([windows.h], [HAVE_W32=yes], + [AC_MSG_ERROR([`--with-w32' was specified, but windows.h + cannot be found.])]) + AC_DEFINE(HAVE_NTGUI, 1, [Define to use native Windows GUI.]) + W32_OBJ="w32fns.o w32menu.o w32reg.o fringe.o" + W32_OBJ="$W32_OBJ fontset.o w32font.o w32term.o" + W32_OBJ="$W32_OBJ w32xfns.o w32select.o image.o w32uniscribe.o" + W32_LIBS="$W32_LIBS -lkernel32 -luser32 -lgdi32 -lole32 -lcomdlg32" + W32_LIBS="$W32_LIBS -lusp10 -lcomctl32 -lwinspool" +fi +AC_SUBST(W32_OBJ) +AC_SUBST(W32_LIBS) + +if test "${HAVE_W32}" = "yes"; then + window_system=w32 + with_xft=no +fi + case "${window_system}" in x11 ) HAVE_X_WINDOWS=yes @@ -1578,6 +1605,11 @@ * ) USE_X_TOOLKIT=maybe ;; esac ;; + w32 ) + HAVE_X_WINDOWS=no + HAVE_X11=no + USE_X_TOOLKIT=none + ;; nextstep | none ) HAVE_X_WINDOWS=no HAVE_X11=no @@ -2222,6 +2254,9 @@ elif test "${HAVE_NS}" = "yes"; then AC_DEFINE(USE_TOOLKIT_SCROLL_BARS) USE_TOOLKIT_SCROLL_BARS=yes + elif test "${HAVE_W32}" = "yes"; then + AC_DEFINE(USE_TOOLKIT_SCROLL_BARS) + USE_TOOLKIT_SCROLL_BARS=yes fi fi @@ -2572,6 +2607,9 @@ OTHER_FILES=ns-app fi +if test "${HAVE_W32}" = "yes"; then + HAVE_MENUS=yes +fi ### Use session management (-lSM -lICE) if available HAVE_X_SM=no @@ -3317,7 +3355,7 @@ AC_SUBST(RALLOC_OBJ) if test "$opsys" = "cygwin"; then - CYGWIN_OBJ="sheap.o" + CYGWIN_OBJ="sheap.o cygw32.o" ## Cygwin differs because of its unexec(). PRE_ALLOC_OBJ= POST_ALLOC_OBJ=lastfile.o @@ -3467,8 +3505,11 @@ AC_SUBST(LIB_GCC) -## If we're using X11/GNUstep, define some consequences. -if test "$HAVE_X_WINDOWS" = "yes" || test "$HAVE_NS" = "yes"; then +## If we're using X11, GNUstep, or Cygwin-Win32, define some +## consequences. +if test "$HAVE_X_WINDOWS" = "yes" || test "$HAVE_NS" = "yes" || + test "$HAVE_W32" = "yes" +then AC_DEFINE(HAVE_WINDOW_SYSTEM, 1, [Define if you have a window system.]) AC_DEFINE(HAVE_MOUSE, 1, [Define if you have mouse support.]) fi === modified file 'lib/filemode.c' --- lib/filemode.c 2011-02-20 10:51:50 +0000 +++ lib/filemode.c 2011-07-16 11:34:30 +0000 @@ -73,19 +73,36 @@ if (S_ISSOCK (bits)) return 's'; +#ifdef S_ISCTG /* Nonstandard file types. */ if (S_ISCTG (bits)) return 'C'; +#endif + +#ifdef S_ISDOOR if (S_ISDOOR (bits)) return 'D'; +#endif + +#ifdef S_ISMPB if (S_ISMPB (bits) || S_ISMPC (bits)) return 'm'; +#endif + +#ifdef S_ISNWK if (S_ISNWK (bits)) return 'n'; +#endif + +#ifdef S_ISPORT if (S_ISPORT (bits)) return 'P'; +#endif + +#ifdef S_ISWHT if (S_ISWHT (bits)) return 'w'; +#endif return '?'; } === modified file 'lisp/battery.el' --- lisp/battery.el 2011-06-27 08:04:55 +0000 +++ lisp/battery.el 2011-07-17 12:33:54 +0000 @@ -57,7 +57,7 @@ (> (buffer-size) 0))) (error nil))) 'battery-pmset) - ((eq system-type 'windows-nt) + ((fboundp 'w32-battery-status) 'w32-battery-status)) "Function for getting battery status information. The function has to return an alist of conversion definitions. === modified file 'lisp/faces.el' --- lisp/faces.el 2011-07-10 02:04:45 +0000 +++ lisp/faces.el 2011-07-17 12:36:34 +0000 @@ -89,7 +89,7 @@ ;; This is defined originally in xfaces.c. (defcustom face-font-registry-alternatives (mapcar (lambda (arg) (mapcar 'purecopy arg)) - (if (eq system-type 'windows-nt) + (if (featurep 'w32) '(("iso8859-1" "ms-oemlatin") ("gb2312.1980" "gb2312" "gbk" "gb18030") ("jisx0208.1990" "jisx0208.1983" "jisx0208.1978") === modified file 'lisp/loadup.el' --- lisp/loadup.el 2011-07-06 22:43:48 +0000 +++ lisp/loadup.el 2011-07-16 14:45:18 +0000 @@ -207,15 +207,17 @@ (load "term/common-win") (load "term/x-win"))) -(if (eq system-type 'windows-nt) +(if (or (eq system-type 'windows-nt) + (featurep 'w32)) (progn (load "w32-vars") (load "term/common-win") (load "term/w32-win") - (load "ls-lisp") (load "disp-table") - (load "dos-w32") - (load "w32-fns"))) + (when (eq system-type 'windows-nt) + (load "ls-lisp") + (load "dos-w32") + (load "w32-fns")))) (if (eq system-type 'ms-dos) (progn (load "dos-w32") === modified file 'lisp/mouse.el' --- lisp/mouse.el 2011-07-14 14:01:16 +0000 +++ lisp/mouse.el 2011-07-17 12:31:18 +0000 @@ -1277,7 +1277,7 @@ (or mouse-yank-at-point (mouse-set-point click)) (let ((primary (cond - ((eq system-type 'windows-nt) + ((eq (framep (selected-frame)) 'w32) ;; MS-Windows emulates PRIMARY in x-get-selection, but not ;; in x-get-selection-value (the latter only accesses the ;; clipboard). So try PRIMARY first, in case they selected === modified file 'lisp/simple.el' --- lisp/simple.el 2011-07-13 23:35:36 +0000 +++ lisp/simple.el 2011-07-17 12:38:50 +0000 @@ -6550,7 +6550,7 @@ (if (if (eq normal-erase-is-backspace 'maybe) (and (not noninteractive) (or (memq system-type '(ms-dos windows-nt)) - (memq window-system '(ns)) + (memq window-system '(w32 ns)) (and (memq window-system '(x)) (fboundp 'x-backspace-delete-keys-p) (x-backspace-delete-keys-p)) === modified file 'lisp/term/common-win.el' --- lisp/term/common-win.el 2011-01-25 04:08:28 +0000 +++ lisp/term/common-win.el 2011-07-17 12:26:34 +0000 @@ -57,7 +57,7 @@ On Nextstep, put TEXT in the pasteboard (`x-select-enable-clipboard' is not used)." - (cond ((eq system-type 'windows-nt) + (cond ((eq (framep (selected-frame)) 'w32) (if x-select-enable-clipboard (w32-set-clipboard-data text)) (setq x-last-selected-text text)) === modified file 'lisp/term/w32-win.el' --- lisp/term/w32-win.el 2011-05-04 14:03:16 +0000 +++ lisp/term/w32-win.el 2011-07-17 23:04:45 +0000 @@ -36,30 +36,30 @@ ;; These are the standard X switches from the Xt Initialize.c file of ;; Release 4. -;; Command line Resource Manager string +;; Command line Resource Manager string -;; +rv *reverseVideo -;; +synchronous *synchronous -;; -background *background -;; -bd *borderColor -;; -bg *background -;; -bordercolor *borderColor -;; -borderwidth .borderWidth -;; -bw .borderWidth -;; -display .display -;; -fg *foreground -;; -fn *font -;; -font *font -;; -foreground *foreground -;; -geometry .geometry -;; -i .iconType -;; -itype .iconType -;; -iconic .iconic -;; -name .name -;; -reverse *reverseVideo -;; -rv *reverseVideo +;; +rv *reverseVideo +;; +synchronous *synchronous +;; -background *background +;; -bd *borderColor +;; -bg *background +;; -bordercolor *borderColor +;; -borderwidth .borderWidth +;; -bw .borderWidth +;; -display .display +;; -fg *foreground +;; -fn *font +;; -font *font +;; -foreground *foreground +;; -geometry .geometry +;; -i .iconType +;; -itype .iconType +;; -iconic .iconic +;; -name .name +;; -reverse *reverseVideo +;; -rv *reverseVideo ;; -selectionTimeout .selectionTimeout -;; -synchronous *synchronous +;; -synchronous *synchronous ;; -xrm ;; An alist of X options and the function which handles them. See @@ -110,23 +110,23 @@ ;; before setting the selected frame - otherwise it ;; won't work. (let* ((window (posn-window (event-start event))) - (coords (posn-x-y (event-start event))) - (x (car coords)) - (y (cdr coords))) + (coords (posn-x-y (event-start event))) + (x (car coords)) + (y (cdr coords))) (if (and (> x 0) (> y 0)) - (set-frame-selected-window nil window)) + (set-frame-selected-window nil window)) (mapc (lambda (file-name) - (let ((f (subst-char-in-string ?\\ ?/ file-name)) - (coding (or file-name-coding-system - default-file-name-coding-system))) - (setq file-name - (mapconcat 'url-hexify-string - (split-string (encode-coding-string f coding) - "/") - "/"))) - (dnd-handle-one-url window 'private - (concat "file:" file-name))) - (car (cdr (cdr event))))) + (let ((f (subst-char-in-string ?\\ ?/ file-name)) + (coding (or file-name-coding-system + default-file-name-coding-system))) + (setq file-name + (mapconcat 'url-hexify-string + (split-string (encode-coding-string f coding) + "/") + "/"))) + (dnd-handle-one-url window 'private + (concat "file:" file-name))) + (car (cdr (cdr event))))) (raise-frame))) (defun w32-drag-n-drop-other-frame (event) @@ -197,11 +197,11 @@ ;; the version we were compiled against. (If we were compiled ;; without PNG support, libpng-version's value is -1.) (if (>= libpng-version 10400) - ;; libpng14-14.dll is libpng 1.4.3 from GTK+ - '(png "libpng14-14.dll" "libpng14.dll") - '(png "libpng12d.dll" "libpng12.dll" "libpng3.dll" "libpng.dll" - ;; these are libpng 1.2.8 from GTK+ - "libpng13d.dll" "libpng13.dll")) + ;; libpng14-14.dll is libpng 1.4.3 from GTK+ + '(png "libpng14-14.dll" "libpng14.dll") + '(png "libpng12d.dll" "libpng12.dll" "libpng3.dll" "libpng.dll" + ;; these are libpng 1.2.8 from GTK+ + "libpng13d.dll" "libpng13.dll")) '(jpeg "jpeg62.dll" "libjpeg.dll" "jpeg-62.dll" "jpeg.dll") '(tiff "libtiff3.dll" "libtiff.dll") '(gif "giflib4.dll" "libungif4.dll" "libungif.dll") @@ -252,9 +252,9 @@ (condition-case err (create-fontset-from-fontset-spec w32-standard-fontset-spec t) (error (display-warning - 'initialization - (format "Creation of the standard fontset failed: %s" err) - :error))) + 'initialization + (format "Creation of the standard fontset failed: %s" err) + :error))) ;; Create fontset specified in X resources "Fontset-N" (N is 0, 1,...). (create-fontset-from-x-resource) @@ -313,6 +313,254 @@ (add-to-list 'frame-creation-function-alist '(w32 . x-create-frame-with-faces)) (add-to-list 'window-system-initialization-alist '(w32 . w32-initialize-window-system)) +(declare-function set-message-beep "w32fns.c") + +(declare-function w32-raw-clipboard-fetch-data "w32select.c") +(declare-function x-server-version "w32fns.c" (&optional display)) + +(defun w32-version () + "Return the MS-Windows version numbers. +The value is a list of three integers: the major and minor version +numbers, and the build number." + (x-server-version)) + +;;; Fix interface to (X-specific) mouse.el +(defun x-set-selection (type data) + "Make an X selection of type TYPE and value DATA. +The argument TYPE (nil means `PRIMARY') says which selection, and +DATA specifies the contents. TYPE must be a symbol. \(It can also +be a string, which stands for the symbol with that name, but this +is considered obsolete.) DATA may be a string, a symbol, an +integer (or a cons of two integers or list of two integers). + +The selection may also be a cons of two markers pointing to the same buffer, +or an overlay. In these cases, the selection is considered to be the text +between the markers *at whatever time the selection is examined*. +Thus, editing done in the buffer after you specify the selection +can alter the effective value of the selection. + +The data may also be a vector of valid non-vector selection values. + +The return value is DATA. + +Interactively, this command sets the primary selection. Without +prefix argument, it reads the selection in the minibuffer. With +prefix argument, it uses the text of the region as the selection value. + +Note that on MS-Windows, primary and secondary selections set by Emacs +are not available to other programs." + (put 'x-selections (or type 'PRIMARY) data)) + +(defun x-get-selection (&optional type _data-type) + "Return the value of an X Windows selection. +The argument TYPE (default `PRIMARY') says which selection, +and the argument DATA-TYPE (default `STRING') says +how to convert the data. + +TYPE may be any symbol \(but nil stands for `PRIMARY'). However, +only a few symbols are commonly used. They conventionally have +all upper-case names. The most often used ones, in addition to +`PRIMARY', are `SECONDARY' and `CLIPBOARD'. + +DATA-TYPE is usually `STRING', but can also be one of the symbols +in `selection-converter-alist', which see." + (get 'x-selections (or type 'PRIMARY))) + +;; x-selection-owner-p is used in simple.el +(defun x-selection-owner-p (&optional type) + (and (memq type '(nil PRIMARY SECONDARY)) + (get 'x-selections (or type 'PRIMARY)))) + +;; Set to a system sound if you want a fancy bell. +(set-message-beep nil) + +;; The "Windows" keys on newer keyboards bring up the Start menu +;; whether you want it or not - make Emacs ignore these keystrokes +;; rather than beep. +(global-set-key [lwindow] 'ignore) +(global-set-key [rwindow] 'ignore) + +(make-obsolete-variable 'w32-enable-italics + 'w32-enable-synthesized-fonts "21.1") +(make-obsolete-variable 'w32-charset-to-codepage-alist + 'w32-charset-info-alist "21.1") + + +;;;; Selections + +;; 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-selection-value. +(defvar x-last-selected-text nil) + +(defun x-get-selection-value () + "Return the value of the current selection. +Consult the selection. Treat empty strings as if they were unset." + (if x-select-enable-clipboard + (let (text) + ;; Don't die if x-get-selection signals an error. + (condition-case c + (setq text (w32-get-clipboard-data)) + (error (message "w32-get-clipboard-data:%s" c))) + (if (string= text "") (setq text nil)) + (cond + ((not text) nil) + ((eq text x-last-selected-text) nil) + ((string= text x-last-selected-text) + ;; Record the newer string, so subsequent calls can use the 'eq' test. + (setq x-last-selected-text text) + nil) + (t + (setq x-last-selected-text text)))))) + +(defalias 'x-selection-value 'x-get-selection-value) + +(defvar w32-clipboard-current-data nil + "The value currently advertised as being available on the +clipboard.") + +;; 13 == CF_UNICODETEXT +(add-hook 'w32-clipboard-render-functions + (defun w32-clipboard-render-cf-unicodetext (format) + (when (eql format 13) + (concat + (encode-coding-string w32-clipboard-current-data 'utf-16le-dos t) + "\0")))) +(add-to-list 'w32-clipboard-advertised-types 13) + +(defconst w32-clipboard-format-html + (w32-register-clipboard-format "HTML Format") + "The system-specific numeric ID of the HTML clipboard format.") + +(defconst w32-clipboard-html-header + (concat "Version:0.9\r\n" + "StartHTML:%0006d\r\n" + "EndHTML:%0006d\r\n" + "StartFragment%0006d\r\n" + "EndFragment:%0006d\r\n")) + +(defconst w32-clipboard-html-fragment-prefix + (concat "\r\n" + "\r\n" + "\r\n" + "" +)) + +(defconst w32-clipboard-html-fragment-suffix + (concat + "\r\n" + "\r\n" + "\r\n")) + +(defun w32-clipboard-color-string (name color) + (if color + (progn + (setq color (color-values color)) + (format "%s:#%02x%02x%02x;" + name + (/ (car color) 256) + (/ (car (cdr color)) 256) + (/ (car (cdr (cdr color))) 256))) + "")) + +(defun w32-clipboard-face-as-style (face &optional background) + (if (null face) + "" + (concat + " style=\"" + (w32-clipboard-color-string + "color" + (face-attribute face :foreground nil 'default)) + (if background + (w32-clipboard-color-string + "background-color" + (face-attribute face :background nil 'default)) + "") + "\""))) + +(defun w32-clipboard-string-to-html (str) + "Format a string for Windows HTML interchange via the clipboard." + (let (face prev-face + body + result + chr part + (i 0) (len (length str))) + (while (< i len) + (setq chr (aref str i)) + (cond ((and (>= chr 32) + (<= chr 126) + (not (memql chr '(?\< ?\> ?\" \?&)))) + (setq part (char-to-string chr))) + ((eql chr ?\n) + (setq part "\r\n")) + (t + (setq part (format "&#x%x;" chr)))) + (setq face (or (get-text-property i 'face str))) + (when (or (not body) (not (eq face prev-face))) + (setq body (cons (format (if body "" "") + (w32-clipboard-face-as-style face)) + body)) + (setq prev-face face)) + (setq body (cons part body)) + (setq i (1+ i))) + + (when body + (setq body (cons "" body))) + (setq body (mapconcat #'identity (nreverse body) "")) + (let* ((prefix (format w32-clipboard-html-fragment-prefix + (w32-clipboard-face-as-style 'default t))) + (suffix w32-clipboard-html-fragment-suffix) + (StartHTML (length w32-clipboard-html-header)) + (StartFragment (+ StartHTML (length prefix))) + (EndFragment (+ StartFragment (length body))) + (EndHTML (+ EndFragment (length suffix)))) + (setq result + (concat + (format w32-clipboard-html-header + StartHTML + EndHTML + StartFragment + EndFragment) + prefix + body + suffix)) + (message "%S" result) + result))) + +(add-hook 'w32-clipboard-render-functions + (defun w32-clipboard-render-cf-html (format) + (when (eql format w32-clipboard-format-html) + (w32-clipboard-string-to-html w32-clipboard-current-data)))) +(add-to-list 'w32-clipboard-advertised-types w32-clipboard-format-html) + +(defun w32-clipboard-render (type) + (run-hook-with-args-until-success 'w32-clipboard-render-functions type)) + +(add-hook 'w32-lost-selection-functions + (defun w32-clipboard-lost-selection (cb) + (setq w32-clipboard-current-data nil))) + +(defun w32-set-clipboard-data (string &optional ignored) + (setq w32-clipboard-current-data string) + (w32-claim-clipboard)) + +(defun w32-get-clipboard-data (&optional ignored) + "This gets the clipboard data in text format. " + ;; Don't return our own selection. + (unless w32-clipboard-current-data + (let ((raw-unicode (w32-get-raw-clipboard-data 13))) + (when raw-unicode + (decode-coding-string + ;; Trim off trailing nulls + (if (> (length raw-unicode) 2) + (substring raw-unicode 0 -2) + raw-unicode) + 'utf-16le t))))) + +;; 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-get-selection-value) + (provide 'w32-win) ;;; w32-win.el ends here === modified file 'lisp/w32-fns.el' --- lisp/w32-fns.el 2011-06-30 03:13:35 +0000 +++ lisp/w32-fns.el 2011-07-16 14:36:16 +0000 @@ -31,24 +31,13 @@ ;;;; Function keys -(declare-function set-message-beep "w32console.c") -(declare-function w32-get-clipboard-data "w32select.c") (declare-function w32-get-locale-info "w32proc.c") (declare-function w32-get-valid-locale-ids "w32proc.c") -(declare-function w32-set-clipboard-data "w32select.c") ;; Map all versions of a filename (8.3, longname, mixed case) to the ;; same buffer. (setq find-file-visit-truename t) -(declare-function x-server-version "w32fns.c" (&optional display)) - -(defun w32-version () - "Return the MS-Windows version numbers. -The value is a list of three integers: the major and minor version -numbers, and the build number." - (x-server-version)) - (defun w32-using-nt () "Return non-nil if running on a Windows NT descendant. That includes all Windows systems except for 9X/Me." @@ -258,53 +247,6 @@ (setq start (match-end 0)))) name))) -;;; Fix interface to (X-specific) mouse.el -(defun x-set-selection (type data) - "Make an X selection of type TYPE and value DATA. -The argument TYPE (nil means `PRIMARY') says which selection, and -DATA specifies the contents. TYPE must be a symbol. \(It can also -be a string, which stands for the symbol with that name, but this -is considered obsolete.) DATA may be a string, a symbol, an -integer (or a cons of two integers or list of two integers). - -The selection may also be a cons of two markers pointing to the same buffer, -or an overlay. In these cases, the selection is considered to be the text -between the markers *at whatever time the selection is examined*. -Thus, editing done in the buffer after you specify the selection -can alter the effective value of the selection. - -The data may also be a vector of valid non-vector selection values. - -The return value is DATA. - -Interactively, this command sets the primary selection. Without -prefix argument, it reads the selection in the minibuffer. With -prefix argument, it uses the text of the region as the selection value. - -Note that on MS-Windows, primary and secondary selections set by Emacs -are not available to other programs." - (put 'x-selections (or type 'PRIMARY) data)) - -(defun x-get-selection (&optional type _data-type) - "Return the value of an X Windows selection. -The argument TYPE (default `PRIMARY') says which selection, -and the argument DATA-TYPE (default `STRING') says -how to convert the data. - -TYPE may be any symbol \(but nil stands for `PRIMARY'). However, -only a few symbols are commonly used. They conventionally have -all upper-case names. The most often used ones, in addition to -`PRIMARY', are `SECONDARY' and `CLIPBOARD'. - -DATA-TYPE is usually `STRING', but can also be one of the symbols -in `selection-converter-alist', which see." - (get 'x-selections (or type 'PRIMARY))) - -;; x-selection-owner-p is used in simple.el -(defun x-selection-owner-p (&optional type) - (and (memq type '(nil PRIMARY SECONDARY)) - (get 'x-selections (or type 'PRIMARY)))) - (defun set-w32-system-coding-system (coding-system) "Set the coding system used by the Windows system to CODING-SYSTEM. This is used for things like passing font names with non-ASCII @@ -326,15 +268,6 @@ ;; w32-system-coding-system. Use that instead. (defvaralias 'w32-system-coding-system 'locale-coding-system) -;; Set to a system sound if you want a fancy bell. -(set-message-beep nil) - -;; The "Windows" keys on newer keyboards bring up the Start menu -;; whether you want it or not - make Emacs ignore these keystrokes -;; rather than beep. -(global-set-key [lwindow] 'ignore) -(global-set-key [rwindow] 'ignore) - (defvar w32-charset-info-alist) ; w32font.c (defun w32-add-charset-info (xlfd-charset windows-charset codepage) @@ -392,45 +325,6 @@ (w32-add-charset-info "tis620-0" 'w32-charset-thai 874) (w32-add-charset-info "iso8859-1" 'w32-charset-ansi 1252) -(make-obsolete-variable 'w32-enable-italics - 'w32-enable-synthesized-fonts "21.1") -(make-obsolete-variable 'w32-charset-to-codepage-alist - 'w32-charset-info-alist "21.1") - - -;;;; Selections - -;; 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-selection-value. -(defvar x-last-selected-text nil) - -(defun x-get-selection-value () - "Return the value of the current selection. -Consult the selection. Treat empty strings as if they were unset." - (if x-select-enable-clipboard - (let (text) - ;; Don't die if x-get-selection signals an error. - (condition-case c - (setq text (w32-get-clipboard-data)) - (error (message "w32-get-clipboard-data:%s" c))) - (if (string= text "") (setq text nil)) - (cond - ((not text) nil) - ((eq text x-last-selected-text) nil) - ((string= text x-last-selected-text) - ;; Record the newer string, so subsequent calls can use the 'eq' test. - (setq x-last-selected-text text) - nil) - (t - (setq x-last-selected-text text)))))) - -(defalias 'x-selection-value 'x-get-selection-value) - -;; 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-get-selection-value) - ;;;; Support for build process === modified file 'src/ChangeLog' --- src/ChangeLog 2011-07-15 17:41:24 +0000 +++ src/ChangeLog 2011-07-17 06:57:48 +0000 @@ -1,3 +1,8 @@ +2011-07-17 Daniel Colascione + + * s/cygwin.h: Remove prohibition against vfork. It's okay to use + now. + 2011-07-09 Lawrence Mitchell * gnutls.c (Qgnutls_bootprop_min_prime_bits): New variable. === modified file 'src/Makefile.in' --- src/Makefile.in 2011-07-08 20:20:19 +0000 +++ src/Makefile.in 2011-07-17 10:24:47 +0000 @@ -252,6 +252,13 @@ address@hidden@ ## Only set if NS_IMPL_GNUSTEP. address@hidden@ +## w32fns.o w32menu.c w32reg.o fringe.o fontset.o w32font.o w32term.o +## w32xfns.o w32select.o image.o w32uniscribe.o if HAVE_W32, else +## empty. address@hidden@ +## -lkernel32 -luser32 -lgdi32 -lole32 -lcomdlg32 lusp10 -lcomctl32 +## --lwinspool if HAVE_W32, else empty. address@hidden@ ## Empty if !HAVE_X_WINDOWS ## xfont.o ftfont.o xftfont.o ftxfont.o if HAVE_XFT @@ -337,7 +344,8 @@ process.o gnutls.o callproc.o \ region-cache.o sound.o atimer.o \ doprnt.o intervals.o textprop.o composite.o xml.o \ - $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) + $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \ + $(W32_OBJ) obj = $(base_obj) $(NS_OBJC_OBJ) ## Object files used on some machine or other. @@ -346,9 +354,9 @@ ## in the list, in case they ever add any such entries. SOME_MACHINE_OBJECTS = dosfns.o msdos.o \ xterm.o xfns.o xmenu.o xselect.o xrdb.o xsmfns.o fringe.o image.o \ - fontset.o dbusbind.o \ + fontset.o dbusbind.o cygw32.o \ nsterm.o nsfns.o nsmenu.o nsselect.o nsimage.o nsfont.o \ - w32.o w32console.o w32fns.o w32heap.o w32inevt.o \ + w32.o w32console.o w32fns.o w32heap.o \ w32menu.o w32proc.o w32reg.o w32select.o w32term.o w32xfns.o \ w16select.o widget.o xfont.o ftfont.o xftfont.o ftxfont.o gtkutil.o \ xsettings.o xgselect.o termcap.o @@ -380,7 +388,7 @@ ## Note that SunOS needs -lm to come before -lc; otherwise, you get ## duplicated symbols. If the standard libraries were compiled ## with GCC, we might need LIB_GCC again after them. -LIBES = $(LIBS) $(LIBX_BASE) $(LIBX_OTHER) $(LIBSOUND) \ +LIBES = $(LIBS) $(W32_LIBS) $(LIBX_BASE) $(LIBX_OTHER) $(LIBSOUND) \ $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(DBUS_LIBS) \ $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) \ $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \ === added file 'src/cygw32.c' --- src/cygw32.c 1970-01-01 00:00:00 +0000 +++ src/cygw32.c 2011-07-17 12:08:27 +0000 @@ -0,0 +1,150 @@ +/* Cygwin support routines. + Copyright (C) 2011 Free Software Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 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 . */ + + +#include "cygw32.h" + +static Lisp_Object Qutf_16_le; + +/* Advance the given string by one character */ +BYTE* +_mbsinc (const BYTE* current) +{ + return (BYTE*)current + 1; /* XXX: stub */ +} + +unsigned +_mbsnextc (const BYTE* current) +{ + return *current; /* XXX: stub */ +} + +BYTE* +_mbsncpy (BYTE* dest, const BYTE* src, size_t count) +{ + return strncpy (dest, src, count); /* XXX: stub */ +} + +extern Lisp_Object +conv_filename_to_w32_unicode (Lisp_Object in, int absolute_p) +{ + ssize_t converted_len; + Lisp_Object converted; + unsigned flags; + + flags = CCP_POSIX_TO_WIN_W; + if (!absolute_p) { + flags |= CCP_RELATIVE; + } + + in = ENCODE_UTF_8 (in); + + converted_len = cygwin_conv_path (flags, SDATA (in), NULL, 0); + if (converted_len < 2) + error ("cygwin_conv_path: %s", strerror (errno)); + + converted = make_uninit_string (converted_len - 1); + if (cygwin_conv_path (flags, SDATA (in), + SDATA (converted), converted_len)) + error ("cygwin_conv_path: %s", strerror (errno)); + + return converted; +} + +extern Lisp_Object +conv_filename_from_w32_unicode (const wchar_t* in, int absolute_p) +{ + ssize_t converted_len; + Lisp_Object converted; + unsigned flags; + + flags = CCP_WIN_W_TO_POSIX; + if (!absolute_p) { + flags |= CCP_RELATIVE; + } + + converted_len = cygwin_conv_path (flags, in, NULL, 0); + if (converted_len < 1) + error ("cygwin_conv_path: %s", strerror (errno)); + + converted = make_uninit_string (converted_len - 1 /*subtract terminator*/); + if (cygwin_conv_path (flags, in, SDATA (converted), converted_len)) + error ("cygwin_conv_path: %s", strerror (errno)); + + return code_convert_string_norecord (converted, Qutf_8, 0); +} + +Lisp_Object +from_unicode (Lisp_Object str) +{ + CHECK_STRING (str); + if (!STRING_MULTIBYTE (str) && + SBYTES (str) & 1) + { + str = Fsubstring (str, make_number (0), make_number (-1)); + } + + return code_convert_string_norecord (str, Qutf_16_le, 0); +} + +wchar_t* +to_unicode (Lisp_Object str, Lisp_Object* buf) +{ + *buf = code_convert_string_norecord (str, Qutf_16_le, 1); + /* We need to make an additional copy to ensure that the final + string is _doubly_ zero terminated --- that is, that the string + is terminated by two zero bytes and one utf-16le null character. + Because strings are already terminated with a single zero byte, + we just add one additional zero. */ + str = make_uninit_string (SBYTES (*buf) + 1); + memcpy (SDATA (str), SDATA (*buf), SBYTES (*buf)); + SDATA (str) [SBYTES (*buf)] = '\0'; + *buf = str; + return WCSDATA (*buf); +} + +DEFUN ("cygwin-convert-path-to-windows", + Fcygwin_convert_path_to_windows, Scygwin_convert_path_to_windows, + 1, 2, 0, + doc: /* Convert PATH to a Windows path. If ABSOLUTE-P if + non-nil, return an absolute path.*/) + (Lisp_Object path, Lisp_Object absolute_p) +{ + return from_unicode ( + conv_filename_to_w32_unicode (path, absolute_p == Qnil ? 0 : 1)); +} + +DEFUN ("cygwin-convert-path-from-windows", + Fcygwin_convert_path_from_windows, Scygwin_convert_path_from_windows, + 1, 2, 0, + doc: /* Convert a Windows path to a Cygwin path. If ABSOLUTE-P + if non-nil, return an absolute path.*/) + (Lisp_Object path, Lisp_Object absolute_p) +{ + return conv_filename_from_w32_unicode (to_unicode (path, &path), + absolute_p == Qnil ? 0 : 1); +} + +void +syms_of_cygw32 (void) +{ + /* No, not utf-16-le: that one has a BOM. */ + DEFSYM (Qutf_16_le, "utf-16le"); + defsubr (&Scygwin_convert_path_from_windows); + defsubr (&Scygwin_convert_path_to_windows); +} === modified file 'src/dispextern.h' --- src/dispextern.h 2011-07-14 17:28:42 +0000 +++ src/dispextern.h 2011-07-16 10:15:54 +0000 @@ -3106,7 +3106,7 @@ int update_window_fringes (struct window *, int); void compute_fringe_widths (struct frame *, int); -#ifdef WINDOWSNT +#ifdef HAVE_NTGUI void w32_init_fringe (struct redisplay_interface *); void w32_reset_fringes (void); #endif @@ -3207,7 +3207,7 @@ #ifdef HAVE_X_WINDOWS void gamma_correct (struct frame *, XColor *); #endif -#ifdef WINDOWSNT +#ifdef HAVE_NTGUI void gamma_correct (struct frame *, COLORREF *); #endif === modified file 'src/emacs.c' --- src/emacs.c 2011-07-10 08:20:10 +0000 +++ src/emacs.c 2011-07-17 13:41:12 +0000 @@ -35,7 +35,11 @@ #include #include /* just for w32.h */ #include "w32.h" -#include "w32heap.h" /* for prototype of sbrk */ +#endif + +#if WINDOWSNT || HAVE_NTGUI +#include "w32heap.h" +#include "w32select.h" #endif #ifdef NS_IMPL_GNUSTEP @@ -1410,6 +1414,11 @@ tzset (); #endif /* MSDOS */ +#if WINDOWSNT || HAVE_NTGUI + hinst = GetModuleHandle(NULL); + cache_system_info (); +#endif + #ifdef WINDOWSNT globals_of_w32 (); /* Initialize environment from registry settings. */ @@ -1512,6 +1521,9 @@ #ifdef WINDOWSNT syms_of_ntproc (); #endif /* WINDOWSNT */ +#ifdef CYGWIN + syms_of_cygw32 (); +#endif /* CYGWIN */ syms_of_window (); syms_of_xdisp (); syms_of_font (); @@ -1542,11 +1554,14 @@ #ifdef HAVE_NTGUI syms_of_w32term (); syms_of_w32fns (); - syms_of_w32select (); syms_of_w32menu (); syms_of_fontset (); #endif /* HAVE_NTGUI */ +#ifdef HAVE_W32SELECT + syms_of_w32select (); +#endif /* HAVE_W32SELECT */ + #ifdef MSDOS syms_of_xmenu (); syms_of_dosfns(); @@ -1588,8 +1603,11 @@ #ifdef HAVE_NTGUI globals_of_w32fns (); globals_of_w32menu (); +#endif /* HAVE_NTGUI */ + +#ifdef HAVE_W32SELECT globals_of_w32select (); -#endif /* HAVE_NTGUI */ +#endif /* HAVE_W32SELECT */ } init_charset (); === modified file 'src/font.c' --- src/font.c 2011-07-10 08:20:10 +0000 +++ src/font.c 2011-07-16 12:10:21 +0000 @@ -5207,9 +5207,9 @@ #ifdef HAVE_BDFFONT syms_of_bdffont (); #endif /* HAVE_BDFFONT */ -#ifdef WINDOWSNT +#ifdef HAVE_NTGUI syms_of_w32font (); -#endif /* WINDOWSNT */ +#endif /* HAVE_NTGUI */ #ifdef HAVE_NS syms_of_nsfont (); #endif /* HAVE_NS */ === modified file 'src/font.h' --- src/font.h 2011-06-20 05:51:47 +0000 +++ src/font.h 2011-07-16 06:51:09 +0000 @@ -830,11 +830,11 @@ extern void syms_of_bdffont (void); #endif /* HAVE_BDFFONT */ #endif /* HAVE_X_WINDOWS */ -#ifdef WINDOWSNT +#ifdef HAVE_NTGUI extern struct font_driver w32font_driver; extern struct font_driver uniscribe_font_driver; extern void syms_of_w32font (void); -#endif /* WINDOWSNT */ +#endif /* HAVE_NTGUI */ #ifdef HAVE_NS extern Lisp_Object Qfontsize; extern struct font_driver nsfont_driver; === modified file 'src/fontset.c' --- src/fontset.c 2011-06-13 04:55:03 +0000 +++ src/fontset.c 2011-07-16 10:55:38 +0000 @@ -45,7 +45,7 @@ #ifdef HAVE_X_WINDOWS #include "xterm.h" #endif -#ifdef WINDOWSNT +#ifdef HAVE_NTGUI #include "w32term.h" #endif #ifdef HAVE_NS === modified file 'src/frame.c' --- src/frame.c 2011-06-24 21:25:22 +0000 +++ src/frame.c 2011-07-16 12:10:01 +0000 @@ -29,7 +29,7 @@ #ifdef HAVE_X_WINDOWS #include "xterm.h" #endif -#ifdef WINDOWSNT +#ifdef HAVE_NTGUI #include "w32term.h" #endif #ifdef HAVE_NS @@ -2734,7 +2734,7 @@ {"tool-bar-position", &Qtool_bar_position}, }; -#ifdef WINDOWSNT +#ifdef HAVE_NTGUI /* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the wanted positions of the WM window (not Emacs window). @@ -2778,7 +2778,7 @@ *height = newheight; } -#endif /* WINDOWSNT */ +#endif /* HAVE_NTGUI */ #ifdef HAVE_WINDOW_SYSTEM === modified file 'src/frame.h' --- src/frame.h 2011-06-11 21:31:32 +0000 +++ src/frame.h 2011-07-16 10:13:49 +0000 @@ -1092,7 +1092,7 @@ extern Lisp_Object Qface_set_after_frame_default; -#ifdef WINDOWSNT +#ifdef HAVE_NTGUI extern void x_fullscreen_adjust (struct frame *f, int *, int *, int *, int *); #endif === modified file 'src/image.c' --- src/image.c 2011-07-10 08:20:10 +0000 +++ src/image.c 2011-07-16 10:48:39 +0000 @@ -48,10 +48,13 @@ #include "termhooks.h" #include "font.h" +#if HAVE_X_WINDOWS || (CYGWIN && HAVE_NTGUI) +#include +#include +#endif + #ifdef HAVE_X_WINDOWS #include "xterm.h" -#include -#include #define COLOR_TABLE_SUPPORT 1 @@ -67,7 +70,11 @@ #ifdef HAVE_NTGUI +#if CYGWIN +#include "cygw32.h" +#else #include "w32.h" +#endif #include "w32term.h" /* W32_TODO : Color tables on W32. */ @@ -588,7 +595,7 @@ static void x_emboss (struct frame *, struct image *); static int x_build_heuristic_mask (struct frame *, struct image *, Lisp_Object); -#ifdef HAVE_NTGUI +#if WINDOWSNT #define CACHE_IMAGE_TYPE(type, status) \ do { Vlibrary_cache = Fcons (Fcons (type, status), Vlibrary_cache); } while (0) #else @@ -2910,7 +2917,7 @@ else bits = (char *) XBOOL_VECTOR (data)->data; -#ifdef WINDOWSNT +#ifdef HAVE_NTGUI { char *invertedBits; int nbytes, i; @@ -8614,7 +8621,7 @@ of `dynamic-library-alist', which see). */) (Lisp_Object type, Lisp_Object libraries) { -#ifdef HAVE_NTGUI +#ifdef WINDOWSNT /* Don't try to reload the library. */ Lisp_Object tested = Fassq (type, Vlibrary_cache); if (CONSP (tested)) === modified file 'src/keyboard.c' --- src/keyboard.c 2011-07-14 18:34:54 +0000 +++ src/keyboard.c 2011-07-17 07:59:27 +0000 @@ -321,7 +321,7 @@ /* Symbols to denote kinds of events. */ static Lisp_Object Qfunction_key; Lisp_Object Qmouse_click; -#if defined (WINDOWSNT) +#if defined (HAVE_NTGUI) Lisp_Object Qlanguage_change; #endif static Lisp_Object Qdrag_n_drop; @@ -3777,8 +3777,8 @@ #ifdef subprocesses if (kbd_on_hold_p () && kbd_buffer_nr_stored () < KBD_BUFFER_SIZE/4) { - /* Start reading input again, we have processed enough so we can - accept new events again. */ + /* Start reading input again because we have processed enough to + be able to accept new events again. */ unhold_keyboard_input (); #ifdef SIGIO if (!noninteractive) @@ -3962,7 +3962,7 @@ x_activate_menubar (XFRAME (event->frame_or_window)); } #endif -#if defined (WINDOWSNT) +#if defined (HAVE_NTGUI) else if (event->kind == LANGUAGE_CHANGE_EVENT) { /* Make an event (language-change (FRAME CHARSET LCID)). */ @@ -5412,7 +5412,7 @@ (sizeof (lispy_function_keys) / sizeof (lispy_function_keys[0]))); -#ifdef WINDOWSNT +#ifdef HAVE_NTGUI case MULTIMEDIA_KEY_EVENT: if (event->code < (sizeof (lispy_multimedia_keys) / sizeof (lispy_multimedia_keys[0])) @@ -11528,7 +11528,7 @@ DEFSYM (Qconfig_changed_event, "config-changed-event"); DEFSYM (Qmenu_enable, "menu-enable"); -#if defined (WINDOWSNT) +#if defined (HAVE_NTGUI) DEFSYM (Qlanguage_change, "language-change"); #endif === modified file 'src/keyboard.h' --- src/keyboard.h 2011-06-23 06:31:41 +0000 +++ src/keyboard.h 2011-07-16 06:28:00 +0000 @@ -511,6 +511,6 @@ extern EMACS_TIME timer_check (void); extern void mark_kboards (void); -#ifdef WINDOWSNT +#ifdef HAVE_NTGUI extern const char *const lispy_function_keys[]; #endif === modified file 'src/lisp.h' --- src/lisp.h 2011-06-24 21:25:22 +0000 +++ src/lisp.h 2011-07-17 17:34:15 +0000 @@ -27,6 +27,14 @@ #include +#define t(...) \ + ({ \ + fprintf (stderr, "T:%s:%u: ", \ + __FUNCTION__, __LINE__); \ + fprintf (stderr, __VA_ARGS__); \ + fputc ('\n', stderr); \ + }) + /* Use the configure flag --enable-checking[=LIST] to enable various types of run time checks for Lisp objects. */ === modified file 'src/process.c' --- src/process.c 2011-07-06 18:04:23 +0000 +++ src/process.c 2011-07-17 09:23:40 +0000 @@ -108,6 +108,9 @@ #ifdef HAVE_NS #include "nsterm.h" #endif +#ifdef HAVE_NTGUI +#include "w32term.h" +#endif Lisp_Object Qeuid, Qegid, Qcomm, Qstate, Qppid, Qpgrp, Qsess, Qttname, Qtpgid; Lisp_Object Qminflt, Qmajflt, Qcminflt, Qcmajflt, Qutime, Qstime, Qcstime; @@ -4531,6 +4534,8 @@ nfds = xg_select #elif defined (HAVE_NS) nfds = ns_select +#elif defined (USE_W32_SELECT) + nfds = w32_select #else nfds = select #endif === modified file 'src/regex.c' --- src/regex.c 2011-07-10 08:20:10 +0000 +++ src/regex.c 2011-07-16 16:34:09 +0000 @@ -1891,7 +1891,9 @@ /* Explicit quit checking is only used on NTemacs and whenever we use polling to process input events. */ -#if defined emacs && (defined WINDOWSNT || defined SYNC_INPUT) && defined QUIT +#if (defined emacs && \ + (defined WINDOWSNT || defined HAVE_NTGUI || defined SYNC_INPUT) && \ + defined QUIT) extern int immediate_quit; # define IMMEDIATE_QUIT_CHECK \ do { \ === modified file 'src/s/cygwin.h' --- src/s/cygwin.h 2011-03-17 05:15:08 +0000 +++ src/s/cygwin.h 2011-07-17 09:40:15 +0000 @@ -81,10 +81,6 @@ #define HAVE_SOCKETS -/* vfork() interacts badly with setsid(), causing ptys to fail to - change their controlling terminal */ -#define vfork fork - /* This should work (at least when compiling with gcc). But I have no way or intention to verify or even test it. If you encounter a problem with it, feel free to change this setting, but please add a comment here about @@ -102,3 +98,23 @@ /* Send signals to subprocesses by "typing" special chars at them. */ #define SIGNALS_VIA_CHARACTERS + +#ifdef HAVE_NTGUI + +/* Work around Cygwin signal bug + * */ +#define USE_W32_SELECT + +extern int getloadavg (double *, int); + +#ifdef EMACSDEBUG +extern void _DebPrint (const char *fmt, ...); +#define DebPrint(stuff) _DebPrint stuff +#else +#define DebPrint(stuff) +#endif /* EMACSDEBUG */ + +#endif /* HAVE_NTGUI */ + +/* For benefit of normally WINDOWSNT code. */ + === modified file 'src/termhooks.h' --- src/termhooks.h 2011-06-06 19:43:39 +0000 +++ src/termhooks.h 2011-07-16 06:29:45 +0000 @@ -102,9 +102,9 @@ HORIZ_WHEEL_EVENT, /* A wheel event generated by a second horizontal wheel that is present on some mice. See WHEEL_EVENT. */ -#if defined (WINDOWSNT) +#if defined (HAVE_NTGUI) LANGUAGE_CHANGE_EVENT, /* A LANGUAGE_CHANGE_EVENT is - generated on WINDOWSNT or Mac OS + generated on HAVE_NTGUI or Mac OS when the keyboard layout or input language is changed by the user. */ @@ -183,7 +183,7 @@ , CONFIG_CHANGED_EVENT -#ifdef WINDOWSNT +#ifdef HAVE_NTGUI /* Generated when an APPCOMMAND event is received, in response to Multimedia or Internet buttons on some keyboards. Such keys are available as normal function keys on X through the === modified file 'src/unexcw.c' --- src/unexcw.c 2011-03-17 20:18:59 +0000 +++ src/unexcw.c 2011-07-16 06:24:32 +0000 @@ -31,6 +31,8 @@ #define DOTEXE ".exe" +extern void report_sheap_usage (int); + extern int bss_sbrk_did_unexec; /* emacs symbols that indicate where bss and data end for emacs internals */ === modified file 'src/w32.c' --- src/w32.c 2011-07-09 07:00:58 +0000 +++ src/w32.c 2011-07-16 07:04:58 +0000 @@ -31,7 +31,6 @@ #include #include #include -#include /* for _mbspbrk */ #include #include #include @@ -39,6 +38,7 @@ /* must include CRT headers *before* config.h */ #include +#include /* for _mbspbrk */ #undef access #undef chdir @@ -738,23 +738,6 @@ return (s_pfn_Get_System_times (lpIdleTime, lpKernelTime, lpUserTime)); } -/* Equivalent of strerror for W32 error codes. */ -char * -w32_strerror (int error_no) -{ - static char buf[500]; - - if (error_no == 0) - error_no = GetLastError (); - - buf[0] = '\0'; - if (!FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, - error_no, - 0, /* choose most suitable language */ - buf, sizeof (buf), NULL)) - sprintf (buf, "w32 error %u", error_no); - return buf; -} /* Return 1 if P is a valid pointer to an object of size SIZE. Return 0 if P is NOT a valid pointer. Return -1 if we cannot validate P. === modified file 'src/w32.h' --- src/w32.h 2011-05-04 14:03:16 +0000 +++ src/w32.h 2011-07-17 14:01:09 +0000 @@ -133,9 +133,6 @@ extern void syms_of_w32term (void); extern void syms_of_w32fns (void); extern void globals_of_w32fns (void); -extern void syms_of_w32select (void); -extern void globals_of_w32select (void); -extern void term_w32select (void); extern void syms_of_w32menu (void); extern void globals_of_w32menu (void); extern void syms_of_fontset (void); === modified file 'src/w32console.c' --- src/w32console.c 2011-05-07 15:44:19 +0000 +++ src/w32console.c 2011-07-16 13:47:54 +0000 @@ -350,53 +350,6 @@ scroll_line (f, n, LEFT); } -static unsigned int sound_type = 0xFFFFFFFF; -#define MB_EMACS_SILENT (0xFFFFFFFF - 1) - -void -w32_sys_ring_bell (struct frame *f) -{ - if (sound_type == 0xFFFFFFFF) - { - Beep (666, 100); - } - else if (sound_type == MB_EMACS_SILENT) - { - /* Do nothing. */ - } - else - MessageBeep (sound_type); -} - -DEFUN ("set-message-beep", Fset_message_beep, Sset_message_beep, 1, 1, 0, - doc: /* Set the sound generated when the bell is rung. -SOUND is 'asterisk, 'exclamation, 'hand, 'question, 'ok, or 'silent -to use the corresponding system sound for the bell. The 'silent sound -prevents Emacs from making any sound at all. -SOUND is nil to use the normal beep. */) - (Lisp_Object sound) -{ - CHECK_SYMBOL (sound); - - if (NILP (sound)) - sound_type = 0xFFFFFFFF; - else if (EQ (sound, intern ("asterisk"))) - sound_type = MB_ICONASTERISK; - else if (EQ (sound, intern ("exclamation"))) - sound_type = MB_ICONEXCLAMATION; - else if (EQ (sound, intern ("hand"))) - sound_type = MB_ICONHAND; - else if (EQ (sound, intern ("question"))) - sound_type = MB_ICONQUESTION; - else if (EQ (sound, intern ("ok"))) - sound_type = MB_OK; - else if (EQ (sound, intern ("silent"))) - sound_type = MB_EMACS_SILENT; - else - sound_type = 0xFFFFFFFF; - - return sound; -} static void w32con_reset_terminal_modes (struct terminal *t) @@ -755,6 +708,5 @@ defsubr (&Sset_screen_color); defsubr (&Sget_screen_color); defsubr (&Sset_cursor_size); - defsubr (&Sset_message_beep); } === modified file 'src/w32fns.c' --- src/w32fns.c 2011-07-08 12:46:17 +0000 +++ src/w32fns.c 2011-07-17 17:45:48 +0000 @@ -45,8 +45,14 @@ #include "fontset.h" #include "systime.h" #include "termhooks.h" + #include "w32heap.h" + +#if CYGWIN +#include "cygw32.h" +#else #include "w32.h" +#endif #include "bitmaps/gray.xbm" @@ -79,6 +85,7 @@ extern void w32_menu_display_help (HWND, HMENU, UINT, UINT); extern void w32_free_menu_strings (HWND); extern const char *map_w32_filename (const char *, const char **); +extern char * w32_strerror (int error_no); /* If non-zero, a w32 timer that, when it expires, displays an hourglass cursor on all frames. */ @@ -201,6 +208,30 @@ static void w32_show_hourglass (struct frame *); static void w32_hide_hourglass (void); +int faked_key; + +/* This gives us the page size and the size of the allocation unit on NT. */ +SYSTEM_INFO sysinfo_cache; + +/* This gives us version, build, and platform identification. */ +OSVERSIONINFO osinfo_cache; + +unsigned long syspage_mask = 0; + +/* The major and minor versions of NT. */ +int w32_major_version; +int w32_minor_version; +int w32_build_number; + +/* Distinguish between Windows NT and Windows 95. */ +int os_subtype; + +#ifdef HAVE_NTGUI +HINSTANCE hinst = NULL; +#endif + +static unsigned int sound_type = 0xFFFFFFFF; +#define MB_EMACS_SILENT (0xFFFFFFFF - 1) /* Error if we are not connected to MS-Windows. */ @@ -1067,12 +1098,20 @@ If ALLOC is nonzero, allocate a new colormap cell. */ int -w32_defined_color (FRAME_PTR f, char *color, XColor *color_def, int alloc) +w32_defined_color (FRAME_PTR f, const char *color, XColor *color_def, int alloc) { register Lisp_Object tem; COLORREF w32_color_ref; - - tem = x_to_w32_color (color); + char* color_tem; + USE_SAFE_ALLOCA; + + /* Allocate a temporary copy of COLOR because x_to_w32_color + * modifies it and we promised our caller we wouldn't. */ + + SAFE_ALLOCA (color_tem, char*, strlen (color)); + strcpy (color_tem, color); + tem = x_to_w32_color (color_tem); + SAFE_FREE (); if (!NILP (tem)) { @@ -1829,10 +1868,7 @@ /* Do first time app init */ - if (!hprevinst) - { - w32_init_class (hinst); - } + w32_init_class (hinst); if (f->size_hint_flags & USPosition || f->size_hint_flags & PPosition) { @@ -2232,6 +2268,58 @@ } } +#if EMACSDEBUG +const char* +w32_name_of_message (UINT msg) +{ + unsigned i; + static char buf[64]; + static const struct { + UINT msg; + const char* name; + } msgnames[] = { +#define M(msg) { msg, # msg } + M (WM_PAINT), + M (WM_TIMER), + M (WM_USER), + M (WM_MOUSEMOVE), + M (WM_LBUTTONUP), + M (WM_KEYDOWN), + M (WM_EMACS_KILL), + M (WM_EMACS_CREATEWINDOW), + M (WM_EMACS_DONE), + M (WM_EMACS_CREATESCROLLBAR), + M (WM_EMACS_SHOWWINDOW), + M (WM_EMACS_SETWINDOWPOS), + M (WM_EMACS_DESTROYWINDOW), + M (WM_EMACS_TRACKPOPUPMENU), + M (WM_EMACS_SETFOCUS), + M (WM_EMACS_SETFOREGROUND), + M (WM_EMACS_SETLOCALE), + M (WM_EMACS_SETKEYBOARDLAYOUT), + M (WM_EMACS_REGISTER_HOT_KEY), + M (WM_EMACS_UNREGISTER_HOT_KEY), + M (WM_EMACS_TOGGLE_LOCK_KEY), + M (WM_EMACS_TRACK_CARET), + M (WM_EMACS_DESTROY_CARET), + M (WM_EMACS_SHOW_CARET), + M (WM_EMACS_HIDE_CARET), + M (WM_EMACS_SETCURSOR), + M (WM_EMACS_PAINT), + M (WM_CHAR), +#undef M + { 0, 0 } + }; + + for (i = 0; msgnames[i].name; ++i) + if (msgnames[i].msg == msg) + return msgnames[i].name; + + sprintf (buf, "message 0x%04x", (unsigned)msg); + return buf; +} +#endif /* EMACSDEBUG */ + /* Main message dispatch loop. */ static void @@ -2245,6 +2333,10 @@ while (GetMessage (&msg, NULL, 0, 0)) { + + /* DebPrint (("w32_msg_pump: %s time:%u\n", */ + /* w32_name_of_message (msg.message), msg.time)); */ + if (msg.hwnd == NULL) { switch (msg.message) @@ -4653,6 +4745,37 @@ { return Qnil; } + +DEFUN ("set-message-beep", Fset_message_beep, Sset_message_beep, 1, 1, 0, + doc: /* Set the sound generated when the bell is rung. +SOUND is 'asterisk, 'exclamation, 'hand, 'question, 'ok, or 'silent +to use the corresponding system sound for the bell. The 'silent sound +prevents Emacs from making any sound at all. +SOUND is nil to use the normal beep. */) + (Lisp_Object sound) +{ + CHECK_SYMBOL (sound); + + if (NILP (sound)) + sound_type = 0xFFFFFFFF; + else if (EQ (sound, intern ("asterisk"))) + sound_type = MB_ICONASTERISK; + else if (EQ (sound, intern ("exclamation"))) + sound_type = MB_ICONEXCLAMATION; + else if (EQ (sound, intern ("hand"))) + sound_type = MB_ICONHAND; + else if (EQ (sound, intern ("question"))) + sound_type = MB_ICONQUESTION; + else if (EQ (sound, intern ("ok"))) + sound_type = MB_OK; + else if (EQ (sound, intern ("silent"))) + sound_type = MB_EMACS_SILENT; + else + sound_type = 0xFFFFFFFF; + + return sound; +} + int x_pixel_width (register struct frame *f) @@ -5841,7 +5964,7 @@ { if (msg == WM_NOTIFY) { - OFNOTIFY * notify = (OFNOTIFY *)lParam; + OFNOTIFYW * notify = (OFNOTIFYW *)lParam; /* Detect when the Filter dropdown is changed. */ if (notify->hdr.code == CDN_TYPECHANGE || notify->hdr.code == CDN_INITDONE) @@ -5869,7 +5992,7 @@ if (notify->lpOFN->nFilterIndex == 2) { CommDlg_OpenSave_SetControlText (dialog, FILE_NAME_TEXT_FIELD, - "Current Directory"); + L"Current Directory"); EnableWindow (edit_control, FALSE); /* Note that at least on Windows 7, the above call to EnableWindow disables the window that would ordinarily have focus. If we @@ -5885,7 +6008,7 @@ /* Don't override default filename on init done. */ if (notify->hdr.code == CDN_TYPECHANGE) CommDlg_OpenSave_SetControlText (dialog, - FILE_NAME_TEXT_FIELD, ""); + FILE_NAME_TEXT_FIELD, L""); EnableWindow (edit_control, TRUE); } } @@ -5893,19 +6016,6 @@ return 0; } -/* Since we compile with _WIN32_WINNT set to 0x0400 (for NT4 compatibility) - we end up with the old file dialogs. Define a big enough struct for the - new dialog to trick GetOpenFileName into giving us the new dialogs on - Windows 2000 and XP. */ -typedef struct -{ - OPENFILENAME real_details; - void * pReserved; - DWORD dwReserved; - DWORD FlagsEx; -} NEWOPENFILENAME; - - DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0, doc: /* Read file name, prompting with PROMPT in directory DIR. Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file @@ -5919,131 +6029,109 @@ { struct frame *f = SELECTED_FRAME (); Lisp_Object file = Qnil; + Lisp_Object filename = empty_unibyte_string; + Lisp_Object filter = Qnil; int count = SPECPDL_INDEX (); - struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6; - char filename[MAX_PATH + 1]; - char init_dir[MAX_PATH + 1]; + wchar_t filename_buf[MAX_PATH * 4]; int default_filter_index = 1; /* 1: All Files, 2: Directories only */ + struct gcpro gcpro1, gcpro2, gcpro3; - GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, file); + GCPRO3 (file, filename, filter); CHECK_STRING (prompt); CHECK_STRING (dir); + to_unicode (prompt, &prompt); + /* Create the dialog with PROMPT as title, using DIR as initial directory and using "*" as pattern. */ - dir = Fexpand_file_name (dir, Qnil); - strncpy (init_dir, SDATA (ENCODE_FILE (dir)), MAX_PATH); - init_dir[MAX_PATH] = '\0'; - unixtodos_filename (init_dir); - - if (STRINGP (default_filename)) - { - char *file_name_only; - char *full_path_name = SDATA (ENCODE_FILE (default_filename)); - - unixtodos_filename (full_path_name); - - file_name_only = strrchr (full_path_name, '\\'); - if (!file_name_only) - file_name_only = full_path_name; - else - file_name_only++; - - strncpy (filename, file_name_only, MAX_PATH); - filename[MAX_PATH] = '\0'; - } - else - filename[0] = '\0'; - - /* The code in file_dialog_callback that attempts to set the text - of the file name edit window when handling the CDN_INITDONE - WM_NOTIFY message does not work. Setting filename to "Current - Directory" in the only_dir_p case here does work however. */ - if (filename[0] == 0 && ! NILP (only_dir_p)) - strcpy (filename, "Current Directory"); + to_unicode (Fexpand_file_name (dir, Qnil), &dir); + + to_unicode (build_string ("All Files (*.*)\0*.*\0Directories\0*|*\0\0"), + &filter); { - NEWOPENFILENAME new_file_details; + OPENFILENAMEW file_details; BOOL file_opened = FALSE; - OPENFILENAME * file_details = &new_file_details.real_details; /* Prevent redisplay. */ specbind (Qinhibit_redisplay, Qt); BLOCK_INPUT; - memset (&new_file_details, 0, sizeof (new_file_details)); - /* Apparently NT4 crashes if you give it an unexpected size. - I'm not sure about Windows 9x, so play it safe. */ - if (w32_major_version > 4 && w32_major_version < 95) - file_details->lStructSize = sizeof (NEWOPENFILENAME); - else - file_details->lStructSize = sizeof (OPENFILENAME); - - file_details->hwndOwner = FRAME_W32_WINDOW (f); + memset (&file_details, 0, sizeof (file_details)); + file_details.lStructSize = sizeof (file_details); + + if (wcslen (WCSDATA (filename)) >= MAX_PATH*4) { + filename = empty_unibyte_string; + } + wcscpy (filename_buf, WCSDATA (filename)); + + file_details.hwndOwner = FRAME_W32_WINDOW (f); /* Undocumented Bug in Common File Dialog: If a filter is not specified, shell links are not resolved. */ - file_details->lpstrFilter = "All Files (*.*)\0*.*\0Directories\0*|*\0\0"; - file_details->lpstrFile = filename; - file_details->nMaxFile = sizeof (filename); - file_details->lpstrInitialDir = init_dir; - file_details->lpstrTitle = SDATA (prompt); + file_details.lpstrFilter = WCSDATA (filter); + file_details.lpstrFile = filename_buf; + file_details.nMaxFile = sizeof (filename_buf) / sizeof (*filename_buf); + file_details.lpstrInitialDir = WCSDATA (dir); + file_details.lpstrTitle = WCSDATA (prompt); if (! NILP (only_dir_p)) default_filter_index = 2; - file_details->nFilterIndex = default_filter_index; + file_details.nFilterIndex = default_filter_index; - file_details->Flags = (OFN_HIDEREADONLY | OFN_NOCHANGEDIR + file_details.Flags = (OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_ENABLEHOOK); if (!NILP (mustmatch)) { /* Require that the path to the parent directory exists. */ - file_details->Flags |= OFN_PATHMUSTEXIST; + file_details.Flags |= OFN_PATHMUSTEXIST; /* If we are looking for a file, require that it exists. */ if (NILP (only_dir_p)) - file_details->Flags |= OFN_FILEMUSTEXIST; + file_details.Flags |= OFN_FILEMUSTEXIST; } - file_details->lpfnHook = (LPOFNHOOKPROC) file_dialog_callback; - - file_opened = GetOpenFileName (file_details); + file_details.lpfnHook = (LPOFNHOOKPROC) file_dialog_callback; + file_opened = GetOpenFileNameW (&file_details); UNBLOCK_INPUT; if (file_opened) { - dostounix_filename (filename); - if (file_details->nFilterIndex == 2) + if (file_details.nFilterIndex == 2) { /* "Directories" selected - strip dummy file name. */ - char * last = strrchr (filename, '/'); - *last = '\0'; + wchar_t * last = wcsrchr (filename_buf, L'\\'); + if (last) + *last = '\0'; } - - file = DECODE_FILE (build_string (filename)); + filename = conv_filename_from_w32_unicode (filename_buf, 0); } /* User cancelled the dialog without making a selection. */ else if (!CommDlgExtendedError ()) - file = Qnil; + filename = Qnil; /* An error occurred, fallback on reading from the mini-buffer. */ else - file = Fcompleting_read (prompt, intern ("read-file-name-internal"), - dir, mustmatch, dir, Qfile_name_history, - default_filename, Qnil); - - file = unbind_to (count, file); + filename = Fcompleting_read (from_unicode (prompt), + intern ("read-file-name-internal"), + from_unicode (dir), + mustmatch, + from_unicode (dir), + Qfile_name_history, + default_filename, Qnil ); + filename = unbind_to (count, filename); } UNGCPRO; /* Make "Cancel" equivalent to C-g. */ - if (NILP (file)) + if (NILP (filename)) Fsignal (Qquit, Qnil); - return unbind_to (count, file); + return unbind_to (count, filename); } +#ifdef WINDOWSNT /* Moving files to the system recycle bin. Used by `move-file-to-trash' instead of the default moving to ~/.Trash */ @@ -6098,6 +6186,8 @@ return Qnil; } +#endif /* WINDOWSNT */ + /*********************************************************************** w32 specialized functions @@ -6532,7 +6622,7 @@ else { char buffer[16]; - _snprintf (buffer, 16, "%d", system_status.BatteryLifePercent); + snprintf (buffer, 16, "%d", system_status.BatteryLifePercent); load_percentage = build_string (buffer); } @@ -6543,18 +6633,18 @@ long m; float h; char buffer[16]; - _snprintf (buffer, 16, "%ld", seconds_left); + snprintf (buffer, 16, "%ld", seconds_left); seconds = build_string (buffer); m = seconds_left / 60; - _snprintf (buffer, 16, "%ld", m); + snprintf (buffer, 16, "%ld", m); minutes = build_string (buffer); h = seconds_left / 3600.0; - _snprintf (buffer, 16, "%3.1f", h); + snprintf (buffer, 16, "%3.1f", h); hours = build_string (buffer); - _snprintf (buffer, 16, "%ld:%02ld", m / 60, m % 60); + snprintf (buffer, 16, "%ld:%02ld", m / 60, m % 60); remain = build_string (buffer); } sequences[0] = Fcons (make_number ('L'), line_status); @@ -6716,10 +6806,10 @@ { /* a remote printer */ if (*ppi2->pServerName == '\\') - _snprintf (pname_buf, sizeof (pname_buf), "%s\\%s", ppi2->pServerName, + snprintf (pname_buf, sizeof (pname_buf), "%s\\%s", ppi2->pServerName, ppi2->pShareName); else - _snprintf (pname_buf, sizeof (pname_buf), "\\\\%s\\%s", ppi2->pServerName, + snprintf (pname_buf, sizeof (pname_buf), "\\\\%s\\%s", ppi2->pServerName, ppi2->pShareName); pname_buf[sizeof (pname_buf) - 1] = '\0'; } @@ -6738,6 +6828,276 @@ return build_string (pname_buf); } + +/* Equivalent of strerror for W32 error codes. */ +char * +w32_strerror (int error_no) +{ + static char buf[500]; + DWORD ret; + + if (error_no == 0) + error_no = GetLastError (); + + ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + error_no, + 0, /* choose most suitable language */ + buf, sizeof (buf), NULL); + + while (ret > 0 && (buf[ret - 1] == '\n' || + buf[ret - 1] == '\r' )) + --ret; + buf[ret] = '\0'; + if (!ret) + sprintf (buf, "w32 error %u", error_no); + + return buf; +} + +/* For convenience when debugging. */ +int +w32_last_error (void) +{ + return GetLastError (); +} + +/* Cache information describing the NT system for later use. */ +void +cache_system_info (void) +{ + union + { + struct info + { + char major; + char minor; + short platform; + } info; + DWORD data; + } version; + + /* Cache the version of the operating system. */ + version.data = GetVersion (); + w32_major_version = version.info.major; + w32_minor_version = version.info.minor; + + if (version.info.platform & 0x8000) + os_subtype = OS_WIN95; + else + os_subtype = OS_NT; + + /* Cache page size, allocation unit, processor type, etc. */ + GetSystemInfo (&sysinfo_cache); + syspage_mask = sysinfo_cache.dwPageSize - 1; + + /* Cache os info. */ + osinfo_cache.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); + GetVersionEx (&osinfo_cache); + + w32_build_number = osinfo_cache.dwBuildNumber; + if (os_subtype == OS_WIN95) + w32_build_number &= 0xffff; + + w32_num_mouse_buttons = GetSystemMetrics (SM_CMOUSEBUTTONS); +} + +#ifdef EMACSDEBUG +void +_DebPrint (const char *fmt, ...) +{ + char buf[1024]; + va_list args; + + va_start (args, fmt); + vsprintf (buf, fmt, args); + va_end (args); +#if CYGWIN + fprintf (stderr, "%s", buf); +#endif + OutputDebugString (buf); +} +#endif + +int +w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state) +{ + int cur_state = (GetKeyState (vk_code) & 1); + + if (NILP (new_state) + || (NUMBERP (new_state) + && ((XUINT (new_state)) & 1) != cur_state)) + { + faked_key = vk_code; + + keybd_event ((BYTE) vk_code, + (BYTE) MapVirtualKey (vk_code, 0), + KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); + keybd_event ((BYTE) vk_code, + (BYTE) MapVirtualKey (vk_code, 0), + KEYEVENTF_EXTENDEDKEY | 0, 0); + keybd_event ((BYTE) vk_code, + (BYTE) MapVirtualKey (vk_code, 0), + KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); + cur_state = !cur_state; + } + + return cur_state; +} + +/* Translate console modifiers to emacs modifiers. + German keyboard support (Kai Morgan Zeise 2/18/95). */ +int +w32_kbd_mods_to_emacs (DWORD mods, WORD key) +{ + int retval = 0; + + /* If we recognize right-alt and left-ctrl as AltGr, and it has been + pressed, first remove those modifiers. */ + if (!NILP (Vw32_recognize_altgr) + && (mods & (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED)) + == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED)) + mods &= ~ (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED); + + if (mods & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) + retval = ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier); + + if (mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) + { + retval |= ctrl_modifier; + if ((mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) + == (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) + retval |= meta_modifier; + } + + if (mods & LEFT_WIN_PRESSED) + retval |= w32_key_to_modifier (VK_LWIN); + if (mods & RIGHT_WIN_PRESSED) + retval |= w32_key_to_modifier (VK_RWIN); + if (mods & APPS_PRESSED) + retval |= w32_key_to_modifier (VK_APPS); + if (mods & SCROLLLOCK_ON) + retval |= w32_key_to_modifier (VK_SCROLL); + + /* Just in case someone wanted the original behavior, make it + optional by setting w32-capslock-is-shiftlock to t. */ + if (NILP (Vw32_capslock_is_shiftlock) + /* Keys that should _not_ be affected by CapsLock. */ + && ( (key == VK_BACK) + || (key == VK_TAB) + || (key == VK_CLEAR) + || (key == VK_RETURN) + || (key == VK_ESCAPE) + || ((key >= VK_SPACE) && (key <= VK_HELP)) + || ((key >= VK_NUMPAD0) && (key <= VK_F24)) + || ((key >= VK_NUMPAD_CLEAR) && (key <= VK_NUMPAD_DELETE)) + )) + { + /* Only consider shift state. */ + if ((mods & SHIFT_PRESSED) != 0) + retval |= shift_modifier; + } + else + { + /* Ignore CapsLock state if not enabled. */ + if (NILP (Vw32_enable_caps_lock)) + mods &= ~CAPSLOCK_ON; + if ((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) != 0) + retval |= shift_modifier; + } + + return retval; +} + +/* The return code indicates key code size. */ +int +w32_kbd_patch_key (KEY_EVENT_RECORD *event) +{ + unsigned int key_code = event->wVirtualKeyCode; + unsigned int mods = event->dwControlKeyState; + BYTE keystate[256]; + static BYTE ansi_code[4]; + static int isdead = 0; + + if (isdead == 2) + { + event->uChar.AsciiChar = ansi_code[2]; + isdead = 0; + return 1; + } + if (event->uChar.AsciiChar != 0) + return 1; + + memset (keystate, 0, sizeof (keystate)); + keystate[key_code] = 0x80; + if (mods & SHIFT_PRESSED) + keystate[VK_SHIFT] = 0x80; + if (mods & CAPSLOCK_ON) + keystate[VK_CAPITAL] = 1; + /* If we recognize right-alt and left-ctrl as AltGr, set the key + states accordingly before invoking ToAscii. */ + if (!NILP (Vw32_recognize_altgr) + && (mods & LEFT_CTRL_PRESSED) && (mods & RIGHT_ALT_PRESSED)) + { + keystate[VK_CONTROL] = 0x80; + keystate[VK_LCONTROL] = 0x80; + keystate[VK_MENU] = 0x80; + keystate[VK_RMENU] = 0x80; + } + + /* On NT, call ToUnicode instead and then convert to the current + locale's default codepage. */ + if (os_subtype == OS_NT) + { + WCHAR buf[128]; + + isdead = ToUnicode (event->wVirtualKeyCode, event->wVirtualScanCode, + keystate, buf, 128, 0); + if (isdead > 0) + { + char cp[20]; + int cpId; + + event->uChar.UnicodeChar = buf[isdead - 1]; + + GetLocaleInfo (GetThreadLocale (), + LOCALE_IDEFAULTANSICODEPAGE, cp, 20); + cpId = atoi (cp); + isdead = WideCharToMultiByte (cpId, 0, buf, isdead, + ansi_code, 4, NULL, NULL); + } + else + isdead = 0; + } + else + { + isdead = ToAscii (event->wVirtualKeyCode, event->wVirtualScanCode, + keystate, (LPWORD) ansi_code, 0); + } + + if (isdead == 0) + return 0; + event->uChar.AsciiChar = ansi_code[0]; + return isdead; +} + +void +w32_sys_ring_bell (struct frame *f) +{ + if (sound_type == 0xFFFFFFFF) + { + Beep (666, 100); + } + else if (sound_type == MB_EMACS_SILENT) + { + /* Do nothing. */ + } + else + MessageBeep (sound_type); +} + + /*********************************************************************** Initialization ***********************************************************************/ @@ -7105,10 +7465,10 @@ defsubr (&Sfile_system_info); defsubr (&Sdefault_printer_name); + defsubr (&Sset_message_beep); check_window_system_func = check_w32; - hourglass_timer = 0; hourglass_hwnd = NULL; @@ -7123,7 +7483,9 @@ staticpro (&last_show_tip_args); defsubr (&Sx_file_dialog); +#ifdef WINDOWSNT defsubr (&Ssystem_move_file_to_trash); +#endif } @@ -7202,9 +7564,3 @@ } } -/* For convenience when debugging. */ -int -w32_last_error (void) -{ - return GetLastError (); -} === modified file 'src/w32font.c' --- src/w32font.c 2011-05-12 07:07:06 +0000 +++ src/w32font.c 2011-07-16 11:21:20 +0000 @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -1309,6 +1310,9 @@ return 1; } +#if !WINDOWSNT +#define _strlwr strlwr +#endif static int check_face_name (LOGFONT *font, char *full_name) === modified file 'src/w32heap.c' --- src/w32heap.c 2011-05-05 04:00:38 +0000 +++ src/w32heap.c 2011-07-16 10:27:01 +0000 @@ -29,60 +29,6 @@ #define RVA_TO_PTR(rva) ((unsigned char *)((DWORD)(rva) + (DWORD)GetModuleHandle (NULL))) -/* This gives us the page size and the size of the allocation unit on NT. */ -SYSTEM_INFO sysinfo_cache; - -/* This gives us version, build, and platform identification. */ -OSVERSIONINFO osinfo_cache; - -unsigned long syspage_mask = 0; - -/* The major and minor versions of NT. */ -int w32_major_version; -int w32_minor_version; -int w32_build_number; - -/* Distinguish between Windows NT and Windows 95. */ -int os_subtype; - -/* Cache information describing the NT system for later use. */ -void -cache_system_info (void) -{ - union - { - struct info - { - char major; - char minor; - short platform; - } info; - DWORD data; - } version; - - /* Cache the version of the operating system. */ - version.data = GetVersion (); - w32_major_version = version.info.major; - w32_minor_version = version.info.minor; - - if (version.info.platform & 0x8000) - os_subtype = OS_WIN95; - else - os_subtype = OS_NT; - - /* Cache page size, allocation unit, processor type, etc. */ - GetSystemInfo (&sysinfo_cache); - syspage_mask = sysinfo_cache.dwPageSize - 1; - - /* Cache os info. */ - osinfo_cache.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); - GetVersionEx (&osinfo_cache); - - w32_build_number = osinfo_cache.dwBuildNumber; - if (os_subtype == OS_WIN95) - w32_build_number &= 0xffff; -} - /* Emulate getpagesize. */ int getpagesize (void) === modified file 'src/w32heap.h' --- src/w32heap.h 2011-01-25 04:08:28 +0000 +++ src/w32heap.h 2011-07-16 10:33:53 +0000 @@ -24,6 +24,23 @@ #include +extern int w32_major_version; +extern int w32_minor_version; +extern int w32_build_number; +extern BOOL using_dynamic_heap; + +enum { + OS_WIN95 = 1, + OS_NT +}; + +extern int os_subtype; + +#define get_w32_major_version() w32_major_version +#define get_w32_minor_version() w32_minor_version + +#if WINDOWSNT + #define ROUND_UP(p, align) (((DWORD)(p) + (align)-1) & ~((align)-1)) #define ROUND_DOWN(p, align) ((DWORD)(p) & ~((align)-1)) @@ -37,25 +54,12 @@ #define get_page_size() sysinfo_cache.dwPageSize #define get_allocation_unit() sysinfo_cache.dwAllocationGranularity #define get_processor_type() sysinfo_cache.dwProcessorType -#define get_w32_major_version() w32_major_version -#define get_w32_minor_version() w32_minor_version extern unsigned char *get_data_start (void); extern unsigned char *get_data_end (void); extern unsigned long reserved_heap_size; extern SYSTEM_INFO sysinfo_cache; extern OSVERSIONINFO osinfo_cache; -extern BOOL using_dynamic_heap; -extern int w32_major_version; -extern int w32_minor_version; -extern int w32_build_number; - -enum { - OS_WIN95 = 1, - OS_NT -}; - -extern int os_subtype; /* Emulation of Unix sbrk(). */ extern void *sbrk (unsigned long size); @@ -91,5 +95,7 @@ relative virtual address. */ IMAGE_SECTION_HEADER * rva_to_section (DWORD rva, IMAGE_NT_HEADERS * nt_header); +#endif /* WINDOWSNT */ + #endif /* NTHEAP_H_ */ === modified file 'src/w32inevt.c' --- src/w32inevt.c 2011-05-14 19:06:08 +0000 +++ src/w32inevt.c 2011-07-16 11:24:02 +0000 @@ -97,169 +97,6 @@ return SELECTED_FRAME (); } -/* Translate console modifiers to emacs modifiers. - German keyboard support (Kai Morgan Zeise 2/18/95). */ -int -w32_kbd_mods_to_emacs (DWORD mods, WORD key) -{ - int retval = 0; - - /* If we recognize right-alt and left-ctrl as AltGr, and it has been - pressed, first remove those modifiers. */ - if (!NILP (Vw32_recognize_altgr) - && (mods & (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED)) - == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED)) - mods &= ~ (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED); - - if (mods & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) - retval = ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier); - - if (mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) - { - retval |= ctrl_modifier; - if ((mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) - == (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) - retval |= meta_modifier; - } - - if (mods & LEFT_WIN_PRESSED) - retval |= w32_key_to_modifier (VK_LWIN); - if (mods & RIGHT_WIN_PRESSED) - retval |= w32_key_to_modifier (VK_RWIN); - if (mods & APPS_PRESSED) - retval |= w32_key_to_modifier (VK_APPS); - if (mods & SCROLLLOCK_ON) - retval |= w32_key_to_modifier (VK_SCROLL); - - /* Just in case someone wanted the original behavior, make it - optional by setting w32-capslock-is-shiftlock to t. */ - if (NILP (Vw32_capslock_is_shiftlock) - /* Keys that should _not_ be affected by CapsLock. */ - && ( (key == VK_BACK) - || (key == VK_TAB) - || (key == VK_CLEAR) - || (key == VK_RETURN) - || (key == VK_ESCAPE) - || ((key >= VK_SPACE) && (key <= VK_HELP)) - || ((key >= VK_NUMPAD0) && (key <= VK_F24)) - || ((key >= VK_NUMPAD_CLEAR) && (key <= VK_NUMPAD_DELETE)) - )) - { - /* Only consider shift state. */ - if ((mods & SHIFT_PRESSED) != 0) - retval |= shift_modifier; - } - else - { - /* Ignore CapsLock state if not enabled. */ - if (NILP (Vw32_enable_caps_lock)) - mods &= ~CAPSLOCK_ON; - if ((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) != 0) - retval |= shift_modifier; - } - - return retval; -} - -#if 0 -/* Return nonzero if the virtual key is a dead key. */ -static int -is_dead_key (int wparam) -{ - unsigned int code = MapVirtualKey (wparam, 2); - - /* Windows 95 returns 0x8000, NT returns 0x80000000. */ - return (code & 0x80008000) ? 1 : 0; -} -#endif - -/* The return code indicates key code size. */ -int -w32_kbd_patch_key (KEY_EVENT_RECORD *event) -{ - unsigned int key_code = event->wVirtualKeyCode; - unsigned int mods = event->dwControlKeyState; - BYTE keystate[256]; - static BYTE ansi_code[4]; - static int isdead = 0; - - if (isdead == 2) - { - event->uChar.AsciiChar = ansi_code[2]; - isdead = 0; - return 1; - } - if (event->uChar.AsciiChar != 0) - return 1; - - memset (keystate, 0, sizeof (keystate)); - keystate[key_code] = 0x80; - if (mods & SHIFT_PRESSED) - keystate[VK_SHIFT] = 0x80; - if (mods & CAPSLOCK_ON) - keystate[VK_CAPITAL] = 1; - /* If we recognize right-alt and left-ctrl as AltGr, set the key - states accordingly before invoking ToAscii. */ - if (!NILP (Vw32_recognize_altgr) - && (mods & LEFT_CTRL_PRESSED) && (mods & RIGHT_ALT_PRESSED)) - { - keystate[VK_CONTROL] = 0x80; - keystate[VK_LCONTROL] = 0x80; - keystate[VK_MENU] = 0x80; - keystate[VK_RMENU] = 0x80; - } - -#if 0 - /* Because of an OS bug, ToAscii corrupts the stack when called to - convert a dead key in console mode on NT4. Unfortunately, trying - to check for dead keys using MapVirtualKey doesn't work either - - these functions apparently use internal information about keyboard - layout which doesn't get properly updated in console programs when - changing layout (though apparently it gets partly updated, - otherwise ToAscii wouldn't crash). */ - if (is_dead_key (event->wVirtualKeyCode)) - return 0; -#endif - - /* On NT, call ToUnicode instead and then convert to the current - locale's default codepage. */ - if (os_subtype == OS_NT) - { - WCHAR buf[128]; - - isdead = ToUnicode (event->wVirtualKeyCode, event->wVirtualScanCode, - keystate, buf, 128, 0); - if (isdead > 0) - { - char cp[20]; - int cpId; - - event->uChar.UnicodeChar = buf[isdead - 1]; - - GetLocaleInfo (GetThreadLocale (), - LOCALE_IDEFAULTANSICODEPAGE, cp, 20); - cpId = atoi (cp); - isdead = WideCharToMultiByte (cpId, 0, buf, isdead, - ansi_code, 4, NULL, NULL); - } - else - isdead = 0; - } - else - { - isdead = ToAscii (event->wVirtualKeyCode, event->wVirtualScanCode, - keystate, (LPWORD) ansi_code, 0); - } - - if (isdead == 0) - return 0; - event->uChar.AsciiChar = ansi_code[0]; - return isdead; -} - - -static int faked_key = 0; - /* return code -1 means that event_queue_ptr won't be incremented. In other word, this event makes two key codes. (by himi) */ static int @@ -510,32 +347,6 @@ return 1; } -int -w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state) -{ - int cur_state = (GetKeyState (vk_code) & 1); - - if (NILP (new_state) - || (NUMBERP (new_state) - && ((XUINT (new_state)) & 1) != cur_state)) - { - faked_key = vk_code; - - keybd_event ((BYTE) vk_code, - (BYTE) MapVirtualKey (vk_code, 0), - KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); - keybd_event ((BYTE) vk_code, - (BYTE) MapVirtualKey (vk_code, 0), - KEYEVENTF_EXTENDEDKEY | 0, 0); - keybd_event ((BYTE) vk_code, - (BYTE) MapVirtualKey (vk_code, 0), - KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); - cur_state = !cur_state; - } - - return cur_state; -} - /* Mouse position hook. */ void w32_console_mouse_position (FRAME_PTR *f, === modified file 'src/w32menu.c' --- src/w32menu.c 2011-06-24 21:25:22 +0000 +++ src/w32menu.c 2011-07-16 10:09:02 +0000 @@ -21,7 +21,6 @@ #include #include -#include #include #include "lisp.h" @@ -40,6 +39,12 @@ if this is not done before the other system files. */ #include "w32term.h" +#if CYGWIN +#include "cygw32.h" +#else +#include +#endif + /* Load sys/types.h if not already loaded. In some systems loading it twice is suicidal. */ #ifndef makedev @@ -96,6 +101,11 @@ static int fill_in_menu (HMENU, widget_value *); void w32_free_menu_strings (HWND); + +#if CYGWIN + +#endif + /* This is set nonzero after the user activates the menu bar, and set === modified file 'src/w32proc.c' --- src/w32proc.c 2011-06-24 21:25:22 +0000 +++ src/w32proc.c 2011-07-16 05:58:37 +0000 @@ -68,20 +68,6 @@ Lisp_Object Qhigh, Qlow; -#ifdef EMACSDEBUG -void -_DebPrint (const char *fmt, ...) -{ - char buf[1024]; - va_list args; - - va_start (args, fmt); - vsprintf (buf, fmt, args); - va_end (args); - OutputDebugString (buf); -} -#endif - typedef void (_CALLBACK_ *signal_handler) (int); /* Signal handlers...SIG_DFL == 0 so this is initialized correctly. */ === modified file 'src/w32select.c' --- src/w32select.c 2011-06-24 21:25:22 +0000 +++ src/w32select.c 2011-07-17 20:32:49 +0000 @@ -21,58 +21,20 @@ /* - * Notes on usage of selection-coding-system and - * next-selection-coding-system on MS Windows: - * - * The selection coding system variables apply only to the version of - * the clipboard data that is closest in type, i.e. when a 16-bit - * Unicode coding system is given, they apply to he Unicode clipboard - * (CF_UNICODETEXT), when a well-known console codepage is given, they - * apply to the console version of the clipboard data (CF_OEMTEXT), - * else they apply to the normal 8-bit text clipboard (CF_TEXT). - * - * When pasting (getting data from the OS), the clipboard format that - * matches the {next-}selection-coding-system is retrieved. If - * Unicode is requested, but not available, 8-bit text (CF_TEXT) is - * used. In all other cases the OS will transparently convert - * formats, so no other fallback is needed. + * Notes: * * When copying or cutting (sending data to the OS), the data is * announced and stored internally, but only actually rendered on - * request. The requester determines the format provided. The - * {next-}selection-coding-system is only used, when its corresponding - * clipboard type matches the type requested. - * - * Scenarios to use the facilities for customizing the selection - * coding system are: - * - * ;; Generally use KOI8-R instead of the russian MS codepage for - * ;; the 8-bit clipboard. - * (set-selection-coding-system 'koi8-r-dos) - * - * Or - * - * ;; Create a special clipboard copy function that uses codepage - * ;; 1253 (Greek) to copy Greek text to a specific non-Unicode - * ;; application. - * (defun greek-copy (beg end) - * (interactive "r") - * (set-next-selection-coding-system 'cp1253-dos) - * (copy-region-as-kill beg end)) - * (global-set-key "\C-c\C-c" 'greek-copy) - */ - -/* - * Ideas for further directions: - * - * The encoding and decoding routines could be moved to Lisp code - * similar to how xselect.c does it (using well-known routine names - * for the delayed rendering). If the definition of which clipboard - * types should be supported is also moved to Lisp, functionality - * could be expanded to CF_HTML, CF_RTF and maybe other types. + * request. The requester determines the format provided. + * + * We marshal clipboard writes across to the clipboard thread so that + * we can use SetClipboardData in the context of the owning WindowProc + * as the documentation suggests. Clipboard reads can be done in any + * thread. */ #include +#include #include #include "lisp.h" #include "w32term.h" /* for all of the w32 includes */ @@ -82,57 +44,53 @@ #include "coding.h" #include "composite.h" - -static HGLOBAL convert_to_handle_as_ascii (void); -static HGLOBAL convert_to_handle_as_coded (Lisp_Object coding_system); -static Lisp_Object render (Lisp_Object oformat); -static Lisp_Object render_locale (void); -static Lisp_Object render_all (Lisp_Object ignore); -static void run_protected (Lisp_Object (*code) (Lisp_Object), Lisp_Object arg); -static Lisp_Object lisp_error_handler (Lisp_Object error); +#ifdef CYGWIN +#include "cygw32.h" +#endif + +/* No conflict because with w32term messages because messages are + * disambiguated by recipient. */ + +/* Sent to owner window to have it claim ownership. */ +#define WM_EMACS_CLAIM_CLIPBOARD (WM_USER + 0) + +/* Sent to clipboard window with wParam equal to memory handle and + lParam equal to the rendered data type. Use wParam == 0 to + terminate. */ +#define WM_EMACS_CLIPBOARD_DATA (WM_USER + 1) + static LRESULT CALLBACK owner_callback (HWND win, UINT msg, WPARAM wp, LPARAM lp); static HWND create_owner (void); -static void setup_config (void); -static BOOL WINAPI enum_locale_callback (/*const*/ char* loc_string); -static UINT cp_from_locale (LCID lcid, UINT format); -static Lisp_Object coding_from_cp (UINT codepage); -static Lisp_Object validate_coding_system (Lisp_Object coding_system); -static void setup_windows_coding_system (Lisp_Object coding_system, - struct coding_system * coding); - - /* A remnant from X11: Symbol for the CLIPBORD selection type. Other selections are not used on Windows, so we don't need symbols for PRIMARY and SECONDARY. */ Lisp_Object QCLIPBOARD; +/* Function, defined in Lisp, that renders the clipboard in a given + format. */ +Lisp_Object Qw32_clipboard_render; +Lisp_Object Qw32_lost_selection_functions; + /* Internal pseudo-constants, initialized in globals_of_w32select() based on current system parameters. */ -static LCID DEFAULT_LCID; -static UINT ANSICP, OEMCP; -static Lisp_Object QUNICODE, QANSICP, QOEMCP; +static Lisp_Object QUNICODE; /* A hidden window just for the clipboard management. */ static HWND clipboard_owner; + +/* The thread managing the clipboard_owner window. (Windows have + thread affinity, and the main thread doesn't pump messages until we + tell it to do so.) */ +static HANDLE clipboard_thread; + /* A flag to tell WM_DESTROYCLIPBOARD who is to blame this time (just checking GetClipboardOwner() doesn't work, sadly). */ static int modifying_clipboard = 0; -/* Configured transfer parameters, based on the last inspection of - selection-coding-system. */ -static Lisp_Object cfg_coding_system; -static UINT cfg_codepage; -static LCID cfg_lcid; -static UINT cfg_clipboard_type; - -/* The current state for delayed rendering. */ -static Lisp_Object current_text; -static Lisp_Object current_coding_system; -static int current_requires_encoding, current_num_nls; -static UINT current_clipboard_type; -static LCID current_lcid; +#undef TRACE +#define TRACE 1 #if TRACE #define ONTRACE(stmt) stmt @@ -140,303 +98,183 @@ #define ONTRACE(stmt) /*stmt*/ #endif - -/* This function assumes that there is no multibyte character in - current_text, so we can short-cut encoding. */ - -static HGLOBAL -convert_to_handle_as_ascii (void) -{ - HGLOBAL htext = NULL; - int nbytes; - int truelen; - unsigned char *src; - unsigned char *dst; - - ONTRACE (fprintf (stderr, "convert_to_handle_as_ascii\n")); - - nbytes = SBYTES (current_text) + 1; - src = SDATA (current_text); - - /* We need to add to the size the number of LF chars where we have - to insert CR chars (the standard CF_TEXT clipboard format uses - CRLF line endings, while Emacs uses just LF internally). */ - - truelen = nbytes + current_num_nls; - - if ((htext = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, truelen)) == NULL) - return NULL; - - if ((dst = (unsigned char *) GlobalLock (htext)) == NULL) - { - GlobalFree (htext); - return NULL; - } - - /* convert to CRLF line endings expected by clipboard */ - while (1) - { - unsigned char *next; - /* copy next line or remaining bytes including '\0' */ - next = _memccpy (dst, src, '\n', nbytes); - if (next) - { - /* copied one line ending with '\n' */ - int copied = next - dst; - nbytes -= copied; - src += copied; - /* insert '\r' before '\n' */ - next[-1] = '\r'; - next[0] = '\n'; - dst = next + 1; - } - else - /* copied remaining partial line -> now finished */ - break; - } - - GlobalUnlock (htext); - - return htext; -} - -/* This function assumes that there are multibyte or NUL characters in - current_text, or that we need to construct Unicode. It runs the - text through the encoding machinery. */ - -static HGLOBAL -convert_to_handle_as_coded (Lisp_Object coding_system) -{ - HGLOBAL htext; - unsigned char *dst = NULL; - struct coding_system coding; - - ONTRACE (fprintf (stderr, "convert_to_handle_as_coded: %s\n", - SDATA (SYMBOL_NAME (coding_system)))); - - setup_windows_coding_system (coding_system, &coding); - coding.dst_bytes = SBYTES (current_text) * 2; - coding.destination = (unsigned char *) xmalloc (coding.dst_bytes); - encode_coding_object (&coding, current_text, 0, 0, - SCHARS (current_text), SBYTES (current_text), Qnil); - - htext = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, coding.produced +2); - - if (htext != NULL) - dst = (unsigned char *) GlobalLock (htext); - - if (dst != NULL) - { - memcpy (dst, coding.destination, coding.produced); - /* Add the string terminator. Add two NULs in case we are - producing Unicode here. */ - dst[coding.produced] = dst[coding.produced+1] = '\0'; - - GlobalUnlock (htext); - } - - xfree (coding.destination); - - return htext; -} - -static Lisp_Object -render (Lisp_Object oformat) -{ - HGLOBAL htext = NULL; - UINT format = XFASTINT (oformat); - - ONTRACE (fprintf (stderr, "render\n")); - - if (NILP (current_text)) - return Qnil; - - if (current_requires_encoding || format == CF_UNICODETEXT) - { - if (format == current_clipboard_type) - htext = convert_to_handle_as_coded (current_coding_system); - else - switch (format) - { - case CF_UNICODETEXT: - htext = convert_to_handle_as_coded (QUNICODE); - break; - case CF_TEXT: - case CF_OEMTEXT: - { - Lisp_Object cs; - cs = coding_from_cp (cp_from_locale (current_lcid, format)); - htext = convert_to_handle_as_coded (cs); - break; - } - } - } - else - htext = convert_to_handle_as_ascii (); - - ONTRACE (fprintf (stderr, "render: htext = 0x%08X\n", (unsigned) htext)); - - if (htext == NULL) - return Qnil; - - if (SetClipboardData (format, htext) == NULL) - { - GlobalFree (htext); - return Qnil; - } - - return Qt; -} - -static Lisp_Object -render_locale (void) -{ - HANDLE hlocale = NULL; - LCID * lcid_ptr; - - ONTRACE (fprintf (stderr, "render_locale\n")); - - if (current_lcid == LOCALE_NEUTRAL || current_lcid == DEFAULT_LCID) - return Qt; - - hlocale = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, sizeof (current_lcid)); - if (hlocale == NULL) - return Qnil; - - if ((lcid_ptr = (LCID *) GlobalLock (hlocale)) == NULL) - { - GlobalFree (hlocale); - return Qnil; - } - - *lcid_ptr = current_lcid; - GlobalUnlock (hlocale); - - if (SetClipboardData (CF_LOCALE, hlocale) == NULL) - { - GlobalFree (hlocale); - return Qnil; - } - - return Qt; -} - -/* At the end of the program, we want to ensure that our clipboard - data survives us. This code will do that. */ - -static Lisp_Object -render_all (Lisp_Object ignore) -{ - ONTRACE (fprintf (stderr, "render_all\n")); - - /* According to the docs we should not call OpenClipboard() here, - but testing on W2K and working code in other projects shows that - it is actually necessary. */ - - OpenClipboard (NULL); - - /* There is no usefull means to report errors here, there are none - expected anyway, and even if there were errors, they wouldn't do - any harm. So we just go ahead and do what has to be done without - bothering with error handling. */ +static void +claim_clipboard (void) +{ + Lisp_Object format; + + if (!OpenClipboard (clipboard_owner)) + return; ++modifying_clipboard; EmptyClipboard (); --modifying_clipboard; - /* For text formats that we don't render here, the OS can use its - own translation rules instead, so we don't really need to offer - everything. To minimize memory consumption we cover three - possible situations based on our primary format as detected from - selection-coding-system (see setup_config()): - - - Post CF_TEXT only. Let the OS convert to CF_OEMTEXT and the OS - (on NT) or the application (on 9x/Me) convert to - CF_UNICODETEXT. - - - Post CF_OEMTEXT only. Similar automatic conversions happen as - for CF_TEXT. - - - Post CF_UNICODETEXT + CF_TEXT. 9x itself ignores - CF_UNICODETEXT, even though some applications can still handle - it. - - Note 1: We render the less capable CF_TEXT *before* the more - capable CF_UNICODETEXT, to prevent clobbering through automatic - conversions, just in case. - - Note 2: We could check os_subtype here and only render the - additional CF_TEXT on 9x/Me. But OTOH with - current_clipboard_type == CF_UNICODETEXT we don't involve the - automatic conversions anywhere else, so to get consistent - results, we probably don't want to rely on it here either. */ - - render_locale (); - - if (current_clipboard_type == CF_UNICODETEXT) - render (make_number (CF_TEXT)); - render (make_number (current_clipboard_type)); - - CloseClipboard (); - - return Qnil; -} - -static void -run_protected (Lisp_Object (*code) (Lisp_Object), Lisp_Object arg) -{ - /* FIXME: This works but it doesn't feel right. Too much fiddling - with global variables and calling strange looking functions. Is - this really the right way to run Lisp callbacks? */ - - extern int waiting_for_input; /* from keyboard.c */ - int owfi; - - BLOCK_INPUT; - - /* Fsignal calls abort() if it sees that waiting_for_input is - set. */ - owfi = waiting_for_input; - waiting_for_input = 0; - - internal_condition_case_1 (code, arg, Qt, lisp_error_handler); - - waiting_for_input = owfi; - - UNBLOCK_INPUT; -} - -static Lisp_Object -lisp_error_handler (Lisp_Object error) -{ - Vsignaling_function = Qnil; - cmd_error_internal (error, "Error in delayed clipboard rendering: "); - Vinhibit_quit = Qt; - return Qt; -} - + for (format = Vw32_clipboard_advertised_types; + CONSP (format); + format = XCDR (format)) + { + if (INTEGERP (XCAR (format))) + SetClipboardData (XFASTINT (XCAR (format)), NULL); + } + + CloseClipboard (); +} + +static Lisp_Object +clipboard_render_cb_unwind (Lisp_Object arg) +{ + PostMessage (clipboard_owner, WM_EMACS_CLIPBOARD_DATA, 0, 0); + return Qnil; +} + +static Lisp_Object +global_free_unwind (Lisp_Object arg) +{ + HGLOBAL* mem = XSAVE_VALUE (arg)->pointer; + if (mem != NULL) + GlobalFree (*mem); + return Qnil; +} + +static Lisp_Object +close_clipboard_unwind (Lisp_Object arg) +{ + CloseClipboard (); + return Qnil; +} + +/* Send a rendered string RENDERED to the clipboard thread, which must + be waiting in wait_for_clipboard_render. */ +static void +send_clipboard_render (UINT format, void* mem, size_t bytes) +{ + int count; + HGLOBAL htext; + void* buf; + + count = SPECPDL_INDEX (); + record_unwind_protect (global_free_unwind, + make_save_value (&htext, 0)); + + htext = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, bytes); + if (!htext) + error ("GlobalAlloc: %s", w32_strerror (GetLastError ())); + + buf = GlobalLock (htext); + if (!buf) + error ("GlobalLock: %s", w32_strerror (GetLastError ())); + + memcpy (buf, mem, bytes); + if (GlobalUnlock (htext) && GetLastError () != NO_ERROR) + error ("GlobalUnlock: %s", w32_strerror (GetLastError ())); + + /* Use PostMessage instead of SendMessage so we return faster --- + we're on the UI thread, after all. Transfer ownership of htext + to the clipboard thread. */ + + if (!PostMessage (clipboard_owner, WM_EMACS_CLIPBOARD_DATA, + (WPARAM)htext, (LPARAM)format)) + error ("SendMessage: %s", w32_strerror (GetLastError ())); + + htext = NULL; + + unbind_to (count, Qnil); +} + +/* Run in main thread. Try to render in the given format and if we + are successful, send the result back to the clipboard thread via + WM_EMACS_CLIPBOARD_DATA. */ +static void +clipboard_render_cb (struct atimer* at) +{ + void* arg = at->client_data; + UINT format = (UINT)arg; + Lisp_Object ret; + int count = SPECPDL_INDEX (); + + record_unwind_protect (clipboard_render_cb_unwind, Qnil); + ret = call1 (Qw32_clipboard_render, make_number ((unsigned)arg)); + + if (ret != Qnil) { + CHECK_STRING (ret); + send_clipboard_render (format, SDATA (ret), SBYTES (ret) + 1); + } + + unbind_to (count, Qnil); +} + +/* Process rendered data from the currently scheduled render*_cb call + and block until it tells us it's done. */ +static void +wait_for_clipboard_render () +{ + MSG msg; + while (GetMessage (&msg, clipboard_owner, + WM_EMACS_CLIPBOARD_DATA, + WM_EMACS_CLIPBOARD_DATA)) + { + if (msg.message != WM_EMACS_CLIPBOARD_DATA) { + eassert (0); + DispatchMessage (&msg); + continue; + } + + t ("Got WM_EMACS_CLIPBOARD_DATA lParam:%x wParam:%x", + msg.lParam, msg.wParam); + + if (msg.wParam) { + SetClipboardData ((UINT)msg.lParam, (HGLOBAL)msg.wParam); + GlobalFree ((HGLOBAL)msg.wParam); + } else { + break; + } + } +} + +static void +clipboard_lost_cb (struct atimer* ignored) +{ + Lisp_Object args[2]; + args[0] = Qw32_lost_selection_functions; + args[1] = QCLIPBOARD; + run_hook_with_args (2, args, Ffuncall); +} static LRESULT CALLBACK owner_callback (HWND win, UINT msg, WPARAM wp, LPARAM lp) { + t ("owner_callback"); + switch (msg) { + case WM_EMACS_CLIPBOARD_DATA: + ONTRACE (fprintf (stderr, "WM_EMACS_CLIPBOARD_DATA\n")); + /* Ignore out-of-context data messages. */ + return 0; + + case WM_EMACS_CLAIM_CLIPBOARD: + ONTRACE (fprintf (stderr, "WM_EMACS_CLAIM_CLIPBOARD\n")); + claim_clipboard (); + return 0; + case WM_RENDERFORMAT: ONTRACE (fprintf (stderr, "WM_RENDERFORMAT\n")); - run_protected (render, make_number (wp)); + call_on_main_thread (clipboard_render_cb, (void*)wp); + wait_for_clipboard_render (); return 0; case WM_RENDERALLFORMATS: ONTRACE (fprintf (stderr, "WM_RENDERALLFORMATS\n")); - run_protected (render_all, Qnil); + call_on_main_thread (clipboard_render_cb, (void*)-1); + wait_for_clipboard_render (); return 0; case WM_DESTROYCLIPBOARD: if (!modifying_clipboard) { ONTRACE (fprintf (stderr, "WM_DESTROYCLIPBOARD (other)\n")); - current_text = Qnil; - current_coding_system = Qnil; + call_on_main_thread (clipboard_lost_cb, NULL); } else { @@ -478,536 +316,58 @@ DestroyWindow (clipboard_owner); } -static void -setup_config (void) -{ - const char *coding_name; - const char *cp; - char *end; - int slen; - Lisp_Object coding_system; - Lisp_Object dos_coding_system; - - CHECK_SYMBOL (Vselection_coding_system); - - coding_system = NILP (Vnext_selection_coding_system) ? - Vselection_coding_system : Vnext_selection_coding_system; - - dos_coding_system = validate_coding_system (coding_system); - if (NILP (dos_coding_system)) - Fsignal (Qerror, - list2 (build_string ("Coding system is invalid or doesn't have " - "an eol variant for dos line ends"), - coding_system)); - - /* Check if we have it cached */ - if (!NILP (cfg_coding_system) - && EQ (cfg_coding_system, dos_coding_system)) - return; - cfg_coding_system = dos_coding_system; - - /* Set some sensible fallbacks */ - cfg_codepage = ANSICP; - cfg_lcid = LOCALE_NEUTRAL; - cfg_clipboard_type = CF_TEXT; - - /* Interpret the coding system symbol name */ - coding_name = SDATA (SYMBOL_NAME (cfg_coding_system)); - - /* "(.*-)?utf-16.*" -> CF_UNICODETEXT */ - cp = strstr (coding_name, "utf-16"); - if (cp != NULL && (cp == coding_name || cp[-1] == '-')) - { - cfg_clipboard_type = CF_UNICODETEXT; - return; - } - - /* "cp[0-9]+.*" or "windows-[0-9]+.*" -> CF_TEXT or CF_OEMTEXT */ - slen = strlen (coding_name); - if (slen >= 4 && coding_name[0] == 'c' && coding_name[1] == 'p') - cp = coding_name + 2; - else if (slen >= 10 && memcmp (coding_name, "windows-", 8) == 0) - cp = coding_name + 8; - else - return; - - end = (char*)cp; - cfg_codepage = strtol (cp, &end, 10); - - /* Error return from strtol() or number of digits < 2 -> Restore the - default and drop it. */ - if (cfg_codepage == 0 || (end-cp) < 2 ) - { - cfg_codepage = ANSICP; - return; - } - - /* Is it the currently active system default? */ - if (cfg_codepage == ANSICP) - { - /* cfg_clipboard_type = CF_TEXT; */ - return; - } - if (cfg_codepage == OEMCP) - { - cfg_clipboard_type = CF_OEMTEXT; - return; - } - - /* Else determine a suitable locale the hard way. */ - EnumSystemLocales (enum_locale_callback, LCID_INSTALLED); -} - -static BOOL WINAPI -enum_locale_callback (/*const*/ char* loc_string) -{ - LCID lcid; - UINT codepage; - - lcid = strtoul (loc_string, NULL, 16); - - /* Is the wanted codepage the "ANSI" codepage for this locale? */ - codepage = cp_from_locale (lcid, CF_TEXT); - if (codepage == cfg_codepage) - { - cfg_lcid = lcid; - cfg_clipboard_type = CF_TEXT; - return FALSE; /* Stop enumeration */ - } - - /* Is the wanted codepage the OEM codepage for this locale? */ - codepage = cp_from_locale (lcid, CF_OEMTEXT); - if (codepage == cfg_codepage) - { - cfg_lcid = lcid; - cfg_clipboard_type = CF_OEMTEXT; - return FALSE; /* Stop enumeration */ - } - - return TRUE; /* Continue enumeration */ -} - -static UINT -cp_from_locale (LCID lcid, UINT format) -{ - char buffer[20] = ""; - UINT variant, cp; - - variant = - format == CF_TEXT ? LOCALE_IDEFAULTANSICODEPAGE : LOCALE_IDEFAULTCODEPAGE; - - GetLocaleInfo (lcid, variant, buffer, sizeof (buffer)); - cp = strtoul (buffer, NULL, 10); - - if (cp == CP_ACP) - return ANSICP; - else if (cp == CP_OEMCP) - return OEMCP; - else - return cp; -} - -static Lisp_Object -coding_from_cp (UINT codepage) -{ - char buffer[30]; - sprintf (buffer, "cp%d-dos", (int) codepage); - return intern (buffer); - /* We don't need to check that this coding system actually exists - right here, because that is done later for all coding systems - used, regardless of where they originate. */ -} - -static Lisp_Object -validate_coding_system (Lisp_Object coding_system) -{ - Lisp_Object eol_type; - - /* Make sure the input is valid. */ - if (NILP (Fcoding_system_p (coding_system))) - return Qnil; - - /* Make sure we use a DOS coding system as mandated by the system - specs. */ - eol_type = Fcoding_system_eol_type (coding_system); - - /* Already a DOS coding system? */ - if (EQ (eol_type, make_number (1))) - return coding_system; - - /* Get EOL_TYPE vector of the base of CODING_SYSTEM. */ - if (!VECTORP (eol_type)) - { - eol_type = Fcoding_system_eol_type (Fcoding_system_base (coding_system)); - if (!VECTORP (eol_type)) - return Qnil; - } - - return AREF (eol_type, 1); -} - -static void -setup_windows_coding_system (Lisp_Object coding_system, - struct coding_system * coding) -{ - memset (coding, 0, sizeof (*coding)); - setup_coding_system (coding_system, coding); - - /* Unset CODING_ANNOTATE_COMPOSITION_MASK. Previous code had - comments about crashes in encode_coding_iso2022 trying to - dereference a null pointer when composition was on. Selection - data should not contain any composition sequence on Windows. - - CODING_ANNOTATION_MASK also includes - CODING_ANNOTATE_DIRECTION_MASK and CODING_ANNOTATE_CHARSET_MASK, - which both apply to ISO6429 only. We don't know if these really - need to be unset on Windows, but it probably doesn't hurt - either. */ - coding->mode &= ~CODING_ANNOTATION_MASK; - coding->mode |= CODING_MODE_LAST_BLOCK | CODING_MODE_SAFE_ENCODING; -} - - - -DEFUN ("w32-set-clipboard-data", Fw32_set_clipboard_data, - Sw32_set_clipboard_data, 1, 2, 0, - doc: /* This sets the clipboard data to the given text. */) - (Lisp_Object string, Lisp_Object ignored) -{ - BOOL ok = TRUE; - int nbytes; - unsigned char *src; - unsigned char *dst; - unsigned char *end; - - /* This parameter used to be the current frame, but we don't use - that any more. */ - (void) ignored; - - CHECK_STRING (string); - - setup_config (); - - current_text = string; - current_coding_system = cfg_coding_system; - current_clipboard_type = cfg_clipboard_type; - current_lcid = cfg_lcid; - current_num_nls = 0; - current_requires_encoding = 0; - - BLOCK_INPUT; - - /* Check for non-ASCII characters. While we are at it, count the - number of LFs, so we know how many CRs we will have to add later - (just in the case where we can use our internal ASCII rendering, - see code and comment in convert_to_handle_as_ascii() above). */ - nbytes = SBYTES (string); - src = SDATA (string); - - for (dst = src, end = src+nbytes; dst < end; dst++) - { - if (*dst == '\n') - current_num_nls++; - else if (*dst >= 0x80 || *dst == 0) - { - current_requires_encoding = 1; - break; - } - } - - if (!current_requires_encoding) - { - /* If all we have is ASCII we don't need to pretend we offer - anything fancy. */ - current_coding_system = Qraw_text; - current_clipboard_type = CF_TEXT; - current_lcid = LOCALE_NEUTRAL; - } - - if (!OpenClipboard (clipboard_owner)) - goto error; - - ++modifying_clipboard; - ok = EmptyClipboard (); - --modifying_clipboard; - - /* If we have something non-ASCII we may want to set a locale. We - do that directly (non-delayed), as it's just a small bit. */ - if (ok) - ok = !NILP (render_locale ()); - - if (ok) - { - if (clipboard_owner == NULL) - { - /* If for some reason we don't have a clipboard_owner, we - just set the text format as chosen by the configuration - and than forget about the whole thing. */ - ok = !NILP (render (make_number (current_clipboard_type))); - current_text = Qnil; - current_coding_system = Qnil; - } - else - { - /* Advertise all supported formats so that whatever the - requester chooses, only one encoding step needs to be - made. This is intentionally different from what we do in - the handler for WM_RENDERALLFORMATS. */ - SetClipboardData (CF_UNICODETEXT, NULL); - SetClipboardData (CF_TEXT, NULL); - SetClipboardData (CF_OEMTEXT, NULL); - } - } - - CloseClipboard (); - - /* With delayed rendering we haven't really "used" this coding - system yet, and it's even unclear if we ever will. But this is a - way to tell the upper level what we *would* use under ideal - circumstances. - - We don't signal the actually used coding-system later when we - finally render, because that can happen at any time and we don't - want to disturb the "foreground" action. */ - if (ok) - Vlast_coding_system_used = current_coding_system; - - Vnext_selection_coding_system = Qnil; - - if (ok) goto done; - - error: - - ok = FALSE; - current_text = Qnil; - current_coding_system = Qnil; - - done: - UNBLOCK_INPUT; - - return (ok ? string : Qnil); -} - - -DEFUN ("w32-get-clipboard-data", Fw32_get_clipboard_data, - Sw32_get_clipboard_data, 0, 1, 0, - doc: /* This gets the clipboard data in text format. */) - (Lisp_Object ignored) +DEFUN ("w32-claim-clipboard", + Fw32_claim_clipboard, Sw32_claim_clipboard, 0, 0, 0, + doc: /* Claim ownership of the clipboard, clear it, and begin +advertising our content. The formats advertised are given by the list +`w32-clipboard-advertised-types'. */) + (void) +{ + if (!clipboard_owner) { + error ("clipboard not initialized"); + } + + /* Use SendMessage and not PostMessage so the clipboard thread can + be confident that we're not GCing or mutating. */ + SendMessage (clipboard_owner, WM_EMACS_CLAIM_CLIPBOARD, 0, 0); +} + +DEFUN ("w32-get-raw-clipboard-data", Fw32_get_raw_clipboard_data, + Sw32_get_raw_clipboard_data, 1, 1, 0, + doc: /* Retrieve the Win32 clipboard data of the given type +TYPE. Return nil if there is nothing in the clipboard of the given +type. TYPE is an integer giving the raw Win32 clipboard format +constant.*/) + (Lisp_Object format) { HGLOBAL htext; Lisp_Object ret = Qnil; - UINT actual_clipboard_type; - int use_configured_coding_system = 1; - - /* This parameter used to be the current frame, but we don't use - that any more. */ - (void) ignored; - - /* Don't pass our own text from the clipboard (which might be - troublesome if the killed text includes null characters). */ - if (!NILP (current_text)) - return ret; - - setup_config (); - actual_clipboard_type = cfg_clipboard_type; - - BLOCK_INPUT; - - if (!OpenClipboard (clipboard_owner)) - goto done; - - if ((htext = GetClipboardData (actual_clipboard_type)) == NULL) - { - /* If we want CF_UNICODETEXT but can't get it, the current - coding system is useless. OTOH we can still try and decode - CF_TEXT based on the locale that the system gives us and that - we get down below. */ - if (actual_clipboard_type == CF_UNICODETEXT) - { - htext = GetClipboardData (CF_TEXT); - if (htext != NULL) - { - actual_clipboard_type = CF_TEXT; - use_configured_coding_system = 0; - } - } - } - if (htext == NULL) - goto closeclip; - - { - unsigned char *src; - unsigned char *dst; - int nbytes; - int truelen; - int require_decoding = 0; - - if ((src = (unsigned char *) GlobalLock (htext)) == NULL) - goto closeclip; - - /* If the clipboard data contains any non-ascii code, we need to - decode it with a coding system. */ - if (actual_clipboard_type == CF_UNICODETEXT) - { - nbytes = lstrlenW ((WCHAR *)src) * 2; - require_decoding = 1; - } - else - { - int i; - - nbytes = strlen (src); - - for (i = 0; i < nbytes; i++) - { - if (src[i] >= 0x80) - { - require_decoding = 1; - break; - } - } - } - - if (require_decoding) - { - struct coding_system coding; - Lisp_Object coding_system = Qnil; - Lisp_Object dos_coding_system; - - /* `next-selection-coding-system' should override everything, - even when the locale passed by the system disagrees. The - only exception is when `next-selection-coding-system' - requested CF_UNICODETEXT and we couldn't get that. */ - if (use_configured_coding_system - && !NILP (Vnext_selection_coding_system)) - coding_system = Vnext_selection_coding_system; - - /* If we have CF_TEXT or CF_OEMTEXT, we want to check out - CF_LOCALE, too. */ - else if (actual_clipboard_type != CF_UNICODETEXT) - { - HGLOBAL hlocale; - LCID lcid = DEFAULT_LCID; - UINT cp; - - /* Documentation says that the OS always generates - CF_LOCALE info automatically, so the locale handle - should always be present. Fact is that this is not - always true on 9x ;-(. */ - hlocale = GetClipboardData (CF_LOCALE); - if (hlocale != NULL) - { - const LCID * lcid_ptr; - lcid_ptr = (const LCID *) GlobalLock (hlocale); - if (lcid_ptr != NULL) - { - lcid = *lcid_ptr; - GlobalUnlock (hlocale); - } - - /* 9x has garbage as the sort order (to be exact there - is another instance of the language id in the upper - word). We don't care about sort order anyway, so - we just filter out the unneeded mis-information to - avoid irritations. */ - lcid = MAKELCID (LANGIDFROMLCID (lcid), SORT_DEFAULT); - } - - /* If we are using fallback from CF_UNICODETEXT, we can't - use the configured coding system. Also we don't want - to use it, if the system has supplied us with a locale - and it is not just the system default. */ - if (!use_configured_coding_system || lcid != DEFAULT_LCID) - { - cp = cp_from_locale (lcid, actual_clipboard_type); - /* If it's just our current standard setting anyway, - use the coding system that the user has selected. - Otherwise create a new spec to match the locale - that was specified by the other side or the - system. */ - if (!use_configured_coding_system || cp != cfg_codepage) - coding_system = coding_from_cp (cp); - } - } - - if (NILP (coding_system)) - coding_system = Vselection_coding_system; - Vnext_selection_coding_system = Qnil; - - dos_coding_system = validate_coding_system (coding_system); - if (!NILP (dos_coding_system)) - { - setup_windows_coding_system (dos_coding_system, &coding); - coding.source = src; - decode_coding_object (&coding, Qnil, 0, 0, nbytes, nbytes, Qt); - ret = coding.dst_object; - - Vlast_coding_system_used = CODING_ID_NAME (coding.id); - } - } - else - { - /* FIXME: We may want to repeat the code in this branch for - the Unicode case. */ - - /* Need to know final size after CR chars are removed because - we can't change the string size manually, and doing an - extra copy is silly. We only remove CR when it appears as - part of CRLF. */ - - truelen = nbytes; - dst = src; - /* avoid using strchr because it recomputes the length everytime */ - while ((dst = memchr (dst, '\r', nbytes - (dst - src))) != NULL) - { - if (dst[1] == '\n') /* safe because of trailing '\0' */ - truelen--; - dst++; - } - - ret = make_uninit_string (truelen); - - /* Convert CRLF line endings (the standard CF_TEXT clipboard - format) to LF endings as used internally by Emacs. */ - - dst = SDATA (ret); - while (1) - { - unsigned char *next; - /* copy next line or remaining bytes excluding '\0' */ - next = _memccpy (dst, src, '\r', nbytes); - if (next) - { - /* copied one line ending with '\r' */ - int copied = next - dst; - nbytes -= copied; - dst += copied; - src += copied; - if (*src == '\n') - dst--; /* overwrite '\r' with '\n' */ - } - else - /* copied remaining partial line -> now finished */ - break; - } - - Vlast_coding_system_used = Qraw_text; - } - - GlobalUnlock (htext); - } - - closeclip: - CloseClipboard (); - - done: - UNBLOCK_INPUT; - - return (ret); + wchar_t* buf = NULL; + int count = SPECPDL_INDEX (); + + CHECK_NUMBER (format); + + if (!OpenClipboard (NULL)) { + return Qnil; + } + + record_unwind_protect (close_clipboard_unwind, Qnil); + htext = GetClipboardData (XFASTINT (format)); + + if (htext != NULL) { + ret = make_uninit_string (GlobalSize (htext)); + buf = GlobalLock (htext); + if (!buf) + error ("GlobalLock: %s", w32_strerror (GetLastError ())); + + memcpy (SDATA (ret), buf, GlobalSize (htext)); + if (!GlobalUnlock (htext) && GetLastError () != NO_ERROR) + error ("GlobalUnlock: %s", w32_strerror (GetLastError ())); + } + + return unbind_to (count, ret); } -/* Support checking for a clipboard selection. */ - DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p, 0, 1, 0, doc: /* Whether there is an owner for the given X Selection. @@ -1027,17 +387,11 @@ { Lisp_Object val = Qnil; - setup_config (); - if (OpenClipboard (NULL)) { UINT format = 0; while ((format = EnumClipboardFormats (format))) - /* Check CF_TEXT in addition to cfg_clipboard_type, - because we can fall back on that if CF_UNICODETEXT is - not available. Actually a check for CF_TEXT only - should be enough. */ - if (format == cfg_clipboard_type || format == CF_TEXT) + if (format == CF_UNICODETEXT) { val = Qt; break; @@ -1049,93 +403,65 @@ return Qnil; } +DEFUN ("w32-register-clipboard-format", + Fw32_register_clipboard_format, Sw32_register_clipboard_format, + 1, 1, 0, + doc: /* Return the system-wide numberic identifier for clipboard +format FORMAT (a string). */) + (Lisp_Object format) +{ + return make_number (RegisterClipboardFormatW (to_unicode (format, &format))); +} + /* One-time init. Called in the un-dumped Emacs, but not in the dumped version. */ void syms_of_w32select (void) { - defsubr (&Sw32_set_clipboard_data); - defsubr (&Sw32_get_clipboard_data); + defsubr (&Sw32_get_raw_clipboard_data); defsubr (&Sx_selection_exists_p); - - DEFVAR_LISP ("selection-coding-system", Vselection_coding_system, - doc: /* Coding system for communicating with other programs. - -For MS-Windows and MS-DOS: -When sending or receiving text via selection and clipboard, the text -is encoded or decoded by this coding system. The default value is -the current system default encoding on 9x/Me, `utf-16le-dos' -\(Unicode) on NT/W2K/XP, and `iso-latin-1-dos' on MS-DOS. - -For X Windows: -When sending text via selection and clipboard, if the target -data-type matches with the type of this coding system, it is used -for encoding the text. Otherwise (including the case that this -variable is nil), a proper coding system is used as below: - -data-type coding system ---------- ------------- -UTF8_STRING utf-8 -COMPOUND_TEXT compound-text-with-extensions -STRING iso-latin-1 -C_STRING no-conversion - -When receiving text, if this coding system is non-nil, it is used -for decoding regardless of the data-type. If this is nil, a -proper coding system is used according to the data-type as above. - -See also the documentation of the variable `x-select-request-type' how -to control which data-type to request for receiving text. - -The default value is nil. */); - /* The actual value is set dynamically in the dumped Emacs, see - below. */ - Vselection_coding_system = Qnil; - - DEFVAR_LISP ("next-selection-coding-system", Vnext_selection_coding_system, - doc: /* Coding system for the next communication with other programs. -Usually, `selection-coding-system' is used for communicating with -other programs (X Windows clients or MS Windows programs). But, if this -variable is set, it is used for the next communication only. -After the communication, this variable is set to nil. */); - Vnext_selection_coding_system = Qnil; + defsubr (&Sw32_claim_clipboard); + defsubr (&Sw32_register_clipboard_format); DEFSYM (QCLIPBOARD, "CLIPBOARD"); - - cfg_coding_system = Qnil; staticpro (&cfg_coding_system); - current_text = Qnil; staticpro (¤t_text); - current_coding_system = Qnil; staticpro (¤t_coding_system); - DEFSYM (QUNICODE, "utf-16le-dos"); - QANSICP = Qnil; staticpro (&QANSICP); - QOEMCP = Qnil; staticpro (&QOEMCP); -} - -/* One-time init. Called in the dumped Emacs, but not in the - un-dumped version. */ + DEFSYM (Qw32_clipboard_render, "w32-clipboard-render"); + DEFSYM (Qw32_lost_selection_functions, "w32-lost-selection-functions"); + + DEFVAR_LISP ("w32-lost-selection-functions", Vw32_lost_selection_functions, + doc: /* A list of functions to be called when Emacs +loses an X selection. \(This happens when some other client makes its +own selection or when a Lisp program explicitly clears the selection.) +The functions are called with one argument, the selection type \(a +symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'). */); + Vw32_lost_selection_functions = Qnil; + + DEFVAR_LISP ("w32-clipboard-advertised-types", + Vw32_clipboard_advertised_types, + doc: /* A list of data types to offer other programs +via the clipboard. Each one is an integer giving the number ID of the +type to offer. The correct values can be found in the platform +SDK. */); + Vw32_clipboard_advertised_types = Qnil; +} + +static DWORD CALLBACK +clipboard_threadproc (LPVOID ignored) +{ + MSG msg; + clipboard_owner = create_owner (); + while (GetMessage (&msg, NULL, 0, 0)) { + DispatchMessage (&msg); + } +} void globals_of_w32select (void) { - DEFAULT_LCID = GetUserDefaultLCID (); - /* Drop the sort order from the LCID, so we can compare this with - CF_LOCALE objects that have the same fix on 9x. */ - DEFAULT_LCID = MAKELCID (LANGIDFROMLCID (DEFAULT_LCID), SORT_DEFAULT); - - ANSICP = GetACP (); - OEMCP = GetOEMCP (); - - QANSICP = coding_from_cp (ANSICP); - QOEMCP = coding_from_cp (OEMCP); - - if (os_subtype == OS_NT) - Vselection_coding_system = QUNICODE; - else if (inhibit_window_system) - Vselection_coding_system = QOEMCP; - else - Vselection_coding_system = QANSICP; - - clipboard_owner = create_owner (); + clipboard_owner = NULL; + clipboard_thread = CreateThread (NULL, 0, + clipboard_threadproc, + NULL, 0, NULL); } === modified file 'src/w32term.c' --- src/w32term.c 2011-05-28 22:39:39 +0000 +++ src/w32term.c 2011-07-17 16:31:27 +0000 @@ -52,7 +52,14 @@ #include "atimer.h" #include "keymap.h" +#ifdef WINDOWSNT #include "w32heap.h" +#endif + +#ifndef WINDOWSNT +#include /* for get_osfhandle */ +#endif + #include #include "font.h" @@ -188,6 +195,11 @@ static int input_signal_count; #endif +#ifdef USE_W32_SELECT +int w32_evt_pipe[2] = { -1, -1 }; +HANDLE w32_evt_write; +#endif /* USE_W32_SELECT */ + /* Keyboard code page - may be changed by language-change events. */ static int keyboard_codepage; @@ -4057,12 +4069,27 @@ struct input_event inev; int do_help = 0; + /* DebPrint (("w32_read_socket: %s time:%u\n", */ + /* w32_name_of_message (msg.msg.message), */ + /* msg.msg.time)); */ + EVENT_INIT (inev); inev.kind = NO_EVENT; inev.arg = Qnil; switch (msg.msg.message) { + case WM_EMACS_MT_CALL: + { + EMACS_TIME interval; + void* data; + + EMACS_SET_SECS_USECS (interval, 0, 0); + memcpy (&data, &msg.rect, sizeof(data)); + start_atimer (ATIMER_RELATIVE, interval, + (atimer_callback)msg.msg.lParam, data); + } + break; case WM_EMACS_PAINT: f = x_window_to_frame (dpyinfo, msg.msg.hwnd); @@ -6168,8 +6195,13 @@ w32_defined_color (0, "black", &color, 1); } - /* Add the default keyboard. */ +#ifdef WINDOWSNT + /* Add the default keyboard. When !WINDOWSNT, we're using the + standard Emacs console handling machinery and don't need an + explicit FD here; w32_select will take care of waking Emacs when + we have GUI input. */ add_keyboard_wait_descriptor (0); +#endif /* Create Fringe Bitmaps and store them for later use. @@ -6180,15 +6212,6 @@ the bitmaps. */ w32_init_fringe (terminal->rif); -#ifdef F_SETOWN - fcntl (connection, F_SETOWN, getpid ()); -#endif /* ! defined (F_SETOWN) */ - -#ifdef SIGIO - if (interrupt_input) - init_sigio (connection); -#endif /* ! defined (SIGIO) */ - UNBLOCK_INPUT; return dpyinfo; @@ -6238,6 +6261,46 @@ w32_reset_fringes (); } + + +/* Event loop integration when we're not running on bare NT. */ + +#ifdef USE_W32_SELECT + +/* Unless we're a native Windows program, we're integrated into normal + * Emacs event loop. This function is just like select, but also + * returns when we have pending Win32 events. */ +int +w32_select (int nfds, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, struct timeval *timeout) +{ + fd_set modified_readfds; + char buf; + + if (w32_evt_pipe[0] == -1) { + return select (nfds, readfds, writefds, exceptfds, timeout); + } + + modified_readfds = *readfds; + FD_SET (w32_evt_pipe[0], &modified_readfds); + nfds = select (max (nfds, w32_evt_pipe[0] + 1), + &modified_readfds, writefds, exceptfds, timeout); + if (nfds < 1) { + return nfds; + } + + if (FD_ISSET (w32_evt_pipe[0], &modified_readfds)) { + FD_CLR (w32_evt_pipe[0], &modified_readfds); + read (w32_evt_pipe[0], &buf, sizeof(buf)); + } + + *readfds = modified_readfds; + return nfds; +} + + +#endif /* USE_W32_SELECT */ + /* Set up use of W32. */ @@ -6275,6 +6338,15 @@ set_user_model (L"GNU.Emacs"); } +#ifdef USE_W32_SELECT + if (pipe (w32_evt_pipe)) { + fatal ("pipe: %s", strerror (errno)); + } + fcntl (w32_evt_pipe[0], F_SETFD, FD_CLOEXEC); + fcntl (w32_evt_pipe[1], F_SETFD, FD_CLOEXEC); + w32_evt_write = (HANDLE)get_osfhandle (w32_evt_pipe[1]); +#endif /* USE_W32_SELET */ + /* Initialize w32_use_visible_system_caret based on whether a screen reader is in use. */ if (!SystemParametersInfo (SPI_GETSCREENREADER, 0, @@ -6434,4 +6506,6 @@ staticpro (&last_mouse_motion_frame); last_mouse_motion_frame = Qnil; + + Fprovide (intern_c_string ("w32"), Qnil); } === modified file 'src/w32term.h' --- src/w32term.h 2011-06-22 06:16:16 +0000 +++ src/w32term.h 2011-07-17 16:31:05 +0000 @@ -19,6 +19,8 @@ /* Added by Kevin Gallo */ #include "w32gui.h" +#include "frame.h" +#include "atimer.h" #define BLACK_PIX_DEFAULT(f) PALETTERGB(0,0,0) @@ -195,11 +197,47 @@ Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object); +extern void x_focus_on_frame (struct frame *f); + +/* also defined in xterm.h XXX: factor out to common header */ + extern struct w32_display_info *w32_term_init (Lisp_Object, char *, char *); - +extern void check_w32 (void); +extern int w32_defined_color (FRAME_PTR f, const char *color, + XColor *color_def, int alloc); +extern void set_frame_menubar (struct frame *f, int first_time, int deep_p); +extern void x_set_window_size (struct frame *f, int change_grav, + int cols, int rows); extern int x_display_pixel_height (struct w32_display_info *); extern int x_display_pixel_width (struct w32_display_info *); +extern void x_sync (struct frame *); +extern Lisp_Object x_get_focus_frame (struct frame *); +extern void x_set_mouse_position (struct frame *f, int h, int v); +extern void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y); +extern void x_make_frame_visible (struct frame *f); +extern void x_make_frame_invisible (struct frame *f); +extern void x_iconify_frame (struct frame *f); +extern int x_char_width (struct frame *f); +extern int x_char_height (struct frame *f); +extern int x_pixel_width (struct frame *f); +extern int x_pixel_height (struct frame *f); +extern void x_set_frame_alpha (struct frame *f); +extern void x_set_menu_bar_lines (struct frame *, Lisp_Object, Lisp_Object); +extern void x_set_tool_bar_lines (struct frame *f, + Lisp_Object value, + Lisp_Object oldval); +extern void x_activate_menubar (struct frame *); +extern int x_bitmap_icon (struct frame *, Lisp_Object); +extern void initialize_frame_menubar (struct frame *); +extern void x_free_frame_resources (struct frame *); +extern void x_wm_set_size_hint (struct frame *, long, int); +extern void x_real_positions (struct frame *, int *, int *); + +/* w32inevt.c */ +extern int w32_kbd_patch_key (KEY_EVENT_RECORD *event); +extern int w32_kbd_mods_to_emacs (DWORD mods, WORD key); + #define PIX_TYPE COLORREF @@ -576,7 +614,8 @@ #define WM_EMACS_HIDE_CARET (WM_EMACS_START + 18) #define WM_EMACS_SETCURSOR (WM_EMACS_START + 19) #define WM_EMACS_PAINT (WM_EMACS_START + 20) -#define WM_EMACS_END (WM_EMACS_START + 21) +#define WM_EMACS_MT_CALL (WM_EMACS_START + 21) +#define WM_EMACS_END (WM_EMACS_START + 22) #define WND_FONTWIDTH_INDEX (0) #define WND_LINEHEIGHT_INDEX (4) @@ -598,6 +637,8 @@ RECT rect; } W32Msg; +extern BOOL prepend_msg (W32Msg *lpmsg); + /* Structure for recording message when input thread must return a result that depends on lisp thread to compute. Lisp thread can complete deferred messages out of order. */ @@ -630,6 +671,8 @@ extern BOOL post_msg (W32Msg *); extern void complete_deferred_msg (HWND hwnd, UINT msg, LRESULT result); +extern void call_on_main_thread (atimer_callback callback, void* data); + extern BOOL parse_button (int, int, int *, int *); extern void w32_sys_ring_bell (struct frame *f); @@ -701,3 +744,24 @@ extern int w32_system_caret_height; extern int w32_system_caret_x; extern int w32_system_caret_y; + +#if EMACSDEBUG +extern const char* +w32_name_of_message (UINT msg); +#endif /* EMACSDEBUG */ + +#ifdef USE_W32_SELECT + +/* Ordinarily, we'd just send SIGALRM to ourselves when we have input, + * terminating a normal select call with EINTR. However, Cygwin has a + * known bug [1] that causes us to crash when sending a signal to our + * main thread from our message pump thread. The workaround is to use + * an old-fashioned self-pipe. + * + * [1] + */ +extern int w32_evt_pipe[2]; +extern HANDLE w32_evt_write; +extern int w32_select (int nfds, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, struct timeval *timeout); +#endif /* USE_W32_SELECT */ === modified file 'src/w32xfns.c' --- src/w32xfns.c 2011-03-12 19:19:47 +0000 +++ src/w32xfns.c 2011-07-17 14:35:53 +0000 @@ -20,6 +20,11 @@ #include #include #include + +#if CYGWIN +#include +#endif + #include "lisp.h" #include "keyboard.h" #include "frame.h" @@ -33,7 +38,11 @@ #define myfree(lp) GlobalFreePtr (lp) CRITICAL_SECTION critsect; + +#if WINDOWSNT extern HANDLE keyboard_handle; +#endif + HANDLE input_available = NULL; HANDLE interrupt_handle = NULL; @@ -44,7 +53,11 @@ /* For safety, input_available should only be reset by get_next_msg when the input queue is empty, so make it a manual reset event. */ - keyboard_handle = input_available = CreateEvent (NULL, TRUE, FALSE, NULL); + input_available = CreateEvent (NULL, TRUE, FALSE, NULL); + +#if WINDOWSNT + keyboard_handle = input_available; +#endif /* interrupt_handle is signaled when quit (C-g) is detected, so that blocking system calls can be interrupted. We make it a manual @@ -241,6 +254,47 @@ return (bRet); } +extern char * w32_strerror (int error_no); + +/* Tell waiters that we have input available. Call with lock + * held. */ +static void +notify_msg_ready (void) +{ + SetEvent (input_available); + +#ifdef USE_W32_SELECT + { + /* Signal main thread that an event is ready. Use pure Win32 to + * do it so as not to quicken the wrath of the undefined + * behavior Cygwin gods. Use overlapped IO because Cygwin + * creates pipes as overlapped files in order to select on + * them. */ + + char buf = '\0'; + DWORD nr_written; + OVERLAPPED op; + static HANDLE ev = NULL; + BOOL status; + + if (ev == NULL) { + ev = CreateEvent (NULL, TRUE /*manual-reset*/, FALSE, NULL); + } + ResetEvent (ev); + memset (&op, 0, sizeof(op)); + op.hEvent = ev; + status = WriteFile (w32_evt_write, &buf, sizeof(buf), &nr_written, &op); + if (status == FALSE && GetLastError () == ERROR_IO_PENDING) { + status = GetOverlappedResult (w32_evt_write, &op, &nr_written, TRUE); + } + + if (status == FALSE) { + fatal ("writing to evt pipe: %s", w32_strerror (GetLastError ())); + } + } +#endif +} + BOOL post_msg (W32Msg * lpmsg) { @@ -264,13 +318,23 @@ } lpTail = lpNew; - SetEvent (input_available); - + notify_msg_ready (); leave_crit (); return (TRUE); } +void +call_on_main_thread (atimer_callback callback, void* data) +{ + W32Msg cbmsg; + memset (&cbmsg, 0, sizeof (cbmsg)); + cbmsg.msg.message = WM_EMACS_MT_CALL; + cbmsg.msg.lParam = (LPARAM) callback; + memcpy (&cbmsg.rect, &data, sizeof(data)); + post_msg (&cbmsg); +} + BOOL prepend_msg (W32Msg *lpmsg) { @@ -438,7 +502,7 @@ /* x_sync is a no-op on W32. */ void -x_sync (void *f) +x_sync (struct frame *f) { } === modified file 'src/window.c' --- src/window.c 2011-07-14 17:28:42 +0000 +++ src/window.c 2011-07-16 06:02:55 +0000 @@ -40,7 +40,7 @@ #ifdef HAVE_X_WINDOWS #include "xterm.h" #endif /* HAVE_X_WINDOWS */ -#ifdef WINDOWSNT +#ifdef HAVE_NTGUI #include "w32term.h" #endif #ifdef MSDOS === modified file 'src/xdisp.c' --- src/xdisp.c 2011-07-15 10:50:03 +0000 +++ src/xdisp.c 2011-07-16 10:34:55 +0000 @@ -302,7 +302,7 @@ #ifdef HAVE_X_WINDOWS #include "xterm.h" #endif -#ifdef WINDOWSNT +#ifdef HAVE_NTGUI #include "w32term.h" #endif #ifdef HAVE_NS @@ -27809,7 +27809,7 @@ /* Since w32 does not support atimers, it defines its own implementation of the following three functions in w32fns.c. */ -#ifndef WINDOWSNT +#ifndef HAVE_NTGUI /* Platform-independent portion of hourglass implementation. */ @@ -27867,4 +27867,4 @@ hide_hourglass (); #endif } -#endif /* ! WINDOWSNT */ +#endif /* ! HAVE_NTGUI */ === modified file 'src/xfaces.c' --- src/xfaces.c 2011-07-10 08:20:10 +0000 +++ src/xfaces.c 2011-07-16 05:43:00 +0000 @@ -225,7 +225,7 @@ #include "dosfns.h" #endif -#ifdef WINDOWSNT +#ifdef HAVE_NTGUI #include "w32term.h" #include "fontset.h" /* Redefine X specifics to W32 equivalents to avoid cluttering the @@ -236,7 +236,7 @@ #define FRAME_X_FONT_TABLE FRAME_W32_FONT_TABLE #define check_x check_w32 #define GCGraphicsExposures 0 -#endif /* WINDOWSNT */ +#endif /* HAVE_NTGUI */ #ifdef HAVE_NS #include "nsterm.h" @@ -667,7 +667,7 @@ #endif /* HAVE_X_WINDOWS */ -#ifdef WINDOWSNT +#ifdef HAVE_NTGUI /* W32 emulation of GCs */ static inline GC @@ -691,7 +691,7 @@ xfree (gc); } -#endif /* WINDOWSNT */ +#endif /* HAVE_NTGUI */ #ifdef HAVE_NS /* NS emulation of GCs */ @@ -785,7 +785,7 @@ #ifdef HAVE_X_WINDOWS if (!FRAME_X_P (f) || FRAME_X_WINDOW (f)) #endif -#ifdef WINDOWSNT +#ifdef HAVE_NTGUI if (!FRAME_WINDOW_P (f) || FRAME_W32_WINDOW (f)) #endif #ifdef HAVE_NS @@ -1159,7 +1159,7 @@ else if (FRAME_X_P (f)) return x_defined_color (f, color_name, color_def, alloc); #endif -#ifdef WINDOWSNT +#ifdef HAVE_NTGUI else if (FRAME_W32_P (f)) return w32_defined_color (f, color_name, color_def, alloc); #endif @@ -3239,7 +3239,7 @@ param = Qbackground_color; } #ifdef HAVE_WINDOW_SYSTEM -#ifndef WINDOWSNT +#ifndef HAVE_NTGUI else if (EQ (face, Qscroll_bar)) { /* Changing the colors of `scroll-bar' sets frame parameters @@ -3249,7 +3249,7 @@ else if (EQ (attr, QCbackground)) param = Qscroll_bar_background; } -#endif /* not WINDOWSNT */ +#endif /* not HAVE_NTGUI */ else if (EQ (face, Qborder)) { /* Changing background color of `border' sets frame parameter @@ -6293,7 +6293,7 @@ if (num >= 0 && name[num] == '\n') name[num] = 0; cmap = Fcons (Fcons (build_string (name), -#ifdef WINDOWSNT +#ifdef HAVE_NTGUI make_number (RGB (red, green, blue))), #else make_number ((red << 16) | (green << 8) | blue)),