? lisp/patch-shell-quote-argument.diff ? lisp/tutorial.el ? lisp/emulation/viper-tut ? lisp/emulation/viper-tut.el ? nt/emacs-ifdefs.el ? nt/recompile.cmd ? nt/icons/gnu-m-x-16+32.ico ? site-lisp/subdirs.el ? src/make-ifdefs-all-defs.h ? src/make-ifdefs-cc.txt ? src/make-ifdefs-temp.el ? src/make-ifdefs.h ? src/make-ifdefs.pl Index: lisp/apropos.el =================================================================== RCS file: /cvsroot/emacs/emacs/lisp/apropos.el,v retrieving revision 1.118 diff -u -r1.118 apropos.el --- lisp/apropos.el 6 Nov 2006 02:41:31 -0000 1.118 +++ lisp/apropos.el 6 Nov 2006 08:27:58 -0000 @@ -85,7 +85,7 @@ :group 'apropos :type 'face) -(defcustom apropos-label-face 'italic +(defcustom apropos-label-face 'button "*Face for label (`Command', `Variable' ...) in Apropos output. A value of nil means don't use any special font for them, and also turns off mouse highlighting." @@ -982,15 +982,17 @@ (if (stringp (setq i (nth i apropos-item))) (progn (insert " ") - (insert-text-button (button-type-get type 'apropos-label) - 'type type - ;; Can't use the default button face, since - ;; user may have changed the variable! - ;; Just say `no' to variables containing faces! - 'face apropos-label-face - 'apropos-symbol (car apropos-item)) - (insert ": ") - (insert (if do-keys (substitute-command-keys i) i)) + (let ((start (point))) + (insert-text-button (button-type-get type 'apropos-label) + 'type type + ;; Can't use the default button face, since + ;; user may have changed the variable! + ;; Just say `no' to variables containing faces! + 'face apropos-label-face + 'apropos-symbol (car apropos-item)) + (insert ": ") + (insert (if do-keys (substitute-command-keys i) i)) + (fill-region start (point))) (or (bolp) (terpri))))) Index: lisp/button.el =================================================================== RCS file: /cvsroot/emacs/emacs/lisp/button.el,v retrieving revision 1.21 diff -u -r1.21 button.el --- lisp/button.el 6 Feb 2006 14:33:32 -0000 1.21 +++ lisp/button.el 25 Jun 2006 08:07:32 -0000 @@ -52,9 +52,8 @@ ;; Globals ;; Use color for the MS-DOS port because it doesn't support underline. -(defface button '((((type pc) (class color)) - (:foreground "lightblue")) - (t :underline t)) +(defface button + '((t :inherit link)) "Default face used for buttons." :group 'basic-faces) Index: lisp/filesets.el =================================================================== RCS file: /cvsroot/emacs/emacs/lisp/filesets.el,v retrieving revision 1.31 diff -u -r1.31 filesets.el --- lisp/filesets.el 14 Oct 2006 23:25:55 -0000 1.31 +++ lisp/filesets.el 15 Oct 2006 19:24:19 -0000 @@ -574,8 +574,8 @@ query-replace-regexp (filesets-cmd-query-replace-getargs)) ("Grep <>" - "grep" - ("-n " filesets-get-quoted-selection " " "<>")) + filesets-grep + (filesets-grep-getargs)) ("Run Shell Command" filesets-cmd-shell-command (filesets-cmd-shell-command-getargs))) @@ -1596,6 +1596,19 @@ (insert output) (newline)) +(defun filesets-grep-show-result (cmd output) + "Show OUTPUT of Grep." + (pop-to-buffer "*Filesets: Grep Command Output*") + (grep-mode) + (setq buffer-read-only nil) + (with-no-warnings + (end-of-buffer)) + (insert "*** ") + (insert cmd) + (newline) + (insert output) + (newline)) + (defun filesets-run-cmd--repl-fn (arg &optional format-fn) "Helper function for `filesets-run-cmd'. Apply FORMAT-FN to arg. Replace or <> with filename." @@ -1629,36 +1642,42 @@ (when files (let ((fn (filesets-cmd-get-fn cmd-name)) (args (filesets-cmd-get-args cmd-name))) - (dolist (this files nil) - (save-excursion - (save-restriction - (let ((buffer (filesets-find-file this))) - (when buffer - (goto-char (point-min)) + (dolist (this-file files nil) + (save-excursion + (save-restriction + (let ((buffer (filesets-find-file this-file))) + (when buffer + (goto-char (point-min)) (let () - (cond - ((stringp fn) - (let* ((args - (let ((txt "")) - (dolist (this args txt) - (setq txt - (concat txt - (filesets-run-cmd--repl-fn - this - (lambda (this) - (if (equal txt "") "" " ") - (format "%s" this)))))))) - (cmd (concat fn " " args))) - (filesets-cmd-show-result - cmd (shell-command-to-string cmd)))) + (cond + ((stringp fn) + (let* ((args + (let ((txt "")) +;; (dolist (this args txt) +;; (setq txt +;; (concat txt +;; (filesets-run-cmd--repl-fn +;; this +;; (lambda (this) +;; (if (equal txt "") "" " ") +;; (format "%s" this)))))))) + (dolist (this-arg args txt) + (setq txt + (concat txt + (if (equal txt "") "" " ") + (shell-quote-argument this-arg)))))) + (setq fn (shell-quote-argument fn)) + (cmd (concat fn " " args))) + (filesets-cmd-show-result + cmd (shell-command-to-string cmd)))) ((symbolp fn) (let ((args (let ((argl nil)) - (dolist (this args argl) + (dolist (this-arg args argl) (setq argl (append argl (filesets-run-cmd--repl-fn - this + this-arg 'list))))))) (apply fn args)))))))))))))))) @@ -1685,6 +1704,31 @@ "Filesets query replace: respect word boundaries? "))) (list from-string to-string delimited))) +(defun filesets-grep-getargs () + "Get arguments for `filesets-grep'." + (grep-compute-defaults) + (let* ((pattern (read-string "Grep pattern: " + (when (mark) + (buffer-substring-no-properties + (region-beginning) + (region-end))))) + (grep-cmd (concat grep-command pattern " %s"))) + grep-cmd)) + +(defun filesets-grep (txt) + "Wrapper function for `grep'." + (let ((ok (if (buffer-modified-p) + (let ((ok (y-or-n-p "Save buffer? "))) + (when ok + (save-buffer)) + ok) + t))) + (when ok + (let ((cmd (format txt (shell-quote-argument (buffer-file-name))))) + (message "Filesets: %s" cmd) + (filesets-grep-show-result cmd + (shell-command-to-string cmd)))))) + (defun filesets-cmd-shell-command-getargs () "Get arguments for `filesets-cmd-shell-command'." (let* ((arg (read-string "Shell command (%s = file): " Index: lisp/isearch.el =================================================================== RCS file: /cvsroot/emacs/emacs/lisp/isearch.el,v retrieving revision 1.291 diff -u -r1.291 isearch.el --- lisp/isearch.el 3 Oct 2006 14:03:46 -0000 1.291 +++ lisp/isearch.el 15 Oct 2006 19:24:36 -0000 @@ -374,6 +374,8 @@ ;; Turned off because I find I expect to get the global definition--rms. ;; ;; Instead bind C-h to special help command for isearch-mode. ;; (define-key map "\C-h" 'isearch-mode-help) + (define-key map "\C-h" 'isearch-mode-help) + (define-key map [(f1)] 'isearch-mode-help) (define-key map "\M-n" 'isearch-ring-advance) (define-key map "\M-p" 'isearch-ring-retreat) @@ -614,6 +616,10 @@ (defun isearch-mode-help () (interactive) (describe-function 'isearch-forward) + (with-current-buffer (help-buffer) + (let ((inhibit-read-only t)) + (insert (substitute-command-keys + "To scroll help use \\[scroll-other-window-down] and \\[scroll-other-window].\n\n")))) (isearch-update)) @@ -1030,7 +1036,9 @@ (isearch-message-prefix nil nil isearch-nonincremental) isearch-string minibuffer-local-isearch-map nil - (if isearch-regexp 'regexp-search-ring 'search-ring) + (cons + (if isearch-regexp 'regexp-search-ring 'search-ring) + 1) nil t) isearch-new-message (mapconcat 'isearch-text-char-description @@ -1697,6 +1705,18 @@ ((eq search-exit-option 'edit) (apply 'isearch-unread keylist) (isearch-edit-string)) + ;; Always scroll other window if help buffer + ((let ((binding (key-binding key)) + other-buffer-is-help) + (when (or (eq binding 'scroll-other-window-down) + (eq binding 'scroll-other-window)) + (save-selected-window + (other-window 1) + (setq other-buffer-is-help (equal (buffer-name) "*Help*"))) + (when other-buffer-is-help + (command-execute binding) + (isearch-update) + t)))) ;; Handle a scrolling function. ((and isearch-allow-scroll (progn (setq key (isearch-reread-key-sequence-naturally keylist)) Index: lisp/wid-edit.el =================================================================== RCS file: /cvsroot/emacs/emacs/lisp/wid-edit.el,v retrieving revision 1.170 diff -u -r1.170 wid-edit.el --- lisp/wid-edit.el 3 Nov 2006 15:08:02 -0000 1.170 +++ lisp/wid-edit.el 6 Nov 2006 08:28:10 -0000 @@ -124,6 +124,12 @@ :type 'face :group 'widget-faces) +(defface widget-link + '((t :inherit link)) + "Face for attributes that are links or similar to links." + :group 'widget-faces) + + ;; TTY gets special definitions here and in the next defface, because ;; the gray colors defined for other displays cause black text on a black ;; background, at least on light-background TTYs. @@ -2928,8 +2934,13 @@ (widget-create-child-and-convert widget 'visibility :help-echo "Show or hide rest of the documentation." - :on "Hide Rest" - :off "More" + :on "<<" + :off "More..." + :button-face 'widget-link + :mouse-face 'highlight + :pressed-face 'highlight + :button-prefix "" + :button-suffix "" :always-active t :action 'widget-parent-action shown)) Index: lisp/net/ange-ftp.el =================================================================== RCS file: /cvsroot/emacs/emacs/lisp/net/ange-ftp.el,v retrieving revision 1.80 diff -u -r1.80 ange-ftp.el --- lisp/net/ange-ftp.el 6 Feb 2006 11:33:04 -0000 1.80 +++ lisp/net/ange-ftp.el 6 Nov 2006 13:56:30 -0000 @@ -1643,8 +1643,21 @@ (defun ange-ftp-process-filter (proc str) ;; Eliminate nulls. - (while (string-match "\000+" str) - (setq str (replace-match "" nil nil str))) + ;; + ;; Also on w32 check if str consists of only nulls. In that case + ;; throw to `ange-ftp-raw-send' that will restart the ftp + ;; process. It this is not done Emacs will hang when using the gnu + ;; w32 ftp program + ;; (ftp://ftp.gnu.org/old-gnu/emacs/windows/contrib/ftp-for-win32.zip). + (let ((str-len (length str))) + (while (string-match "\000+" str) + (setq str (replace-match "" nil nil str))) + (when (and (boundp 'ange-ftp-check-proc-ok) + ange-ftp-check-proc-ok + (eq system-type 'windows-nt) + (= 0 (length str)) + (< 20 str-len)) + (throw 'ange-ftp-proc-defunct t))) ;; see if the buffer is still around... it could have been deleted. (when (buffer-live-p (process-buffer proc)) @@ -2277,7 +2290,10 @@ (ange-ftp-this-user user) (ange-ftp-this-host host) (ange-ftp-this-msg msg) - cmd2 cmd3 host-type fix-name-func result) + cmd2 cmd3 host-type fix-name-func result + (ange-ftp-check-proc-ok (not nowait)) + (sent-sts nil) + (sent-res nil)) (cond @@ -2365,37 +2381,55 @@ (and cmd2 (concat " " cmd2)))) ;; Actually send the resulting command. - (if (and (consp result) (null (car result))) - ;; `ange-ftp-cd' has failed, so there's no point sending `cmd'. - result - (let (afsc-result - afsc-line) - (ange-ftp-raw-send-cmd - (ange-ftp-get-process host user) - cmd - msg - (list (lambda (result line host user cmd msg cont nowait) - (or cont (setq afsc-result result - afsc-line line)) - (if result (ange-ftp-call-cont cont result line) - (ange-ftp-raw-send-cmd - (ange-ftp-get-process host user) - cmd - msg - (list (lambda (result line cont) - (or cont (setq afsc-result result - afsc-line line)) - (ange-ftp-call-cont cont result line)) - cont) - nowait))) - host user cmd msg cont nowait) - nowait) - - (if nowait - nil - (if cont - nil - (cons afsc-result afsc-line))))))) + (while (not (eq 'ok sent-sts)) + (when (eq sent-sts 'sent-tried) + ;; Delete ftp process if send failed before, it will be + ;; restarted by `ange-ftp-get-process'. + ;; + ;; FIX-ME: There is something strange here, the message below + ;; does not show up in the message buffer. Why? + (message "Ftp process possibly defunct, deleting it ...") + (let ((proc (ange-ftp-get-process host user))) + (delete-process proc) + (sit-for 0.1) + (unless (eq 'exit (process-status proc)) + (kill-process proc)))) + (if (and (consp result) (null (car result))) + ;; `ange-ftp-cd' has failed, so there's no point sending `cmd'. + ;;(setq sent-res result) + (setq sent-res nil) + (let (afsc-result + afsc-line) + (catch 'ange-ftp-proc-defunct + (setq sent-sts 'sent-tried) + (ange-ftp-raw-send-cmd + (ange-ftp-get-process host user) + cmd + msg + (list (lambda (result line host user cmd msg cont nowait) + (or cont (setq afsc-result result + afsc-line line)) + (if result (ange-ftp-call-cont cont result line) + (ange-ftp-raw-send-cmd + (ange-ftp-get-process host user) + cmd + msg + (list (lambda (result line cont) + (or cont (setq afsc-result result + afsc-line line)) + (ange-ftp-call-cont cont result line)) + cont) + nowait))) + host user cmd msg cont nowait) + nowait) + + (setq sent-sts 'ok) + (if nowait + (setq sent-res nil) + (if cont + (setq sent-res nil) + (setq sent-res (cons afsc-result afsc-line)))))))) + sent-res)) ;; It might be nice to message users about the host type identified, ;; but there is so much other messaging going on, it would not be Index: lisp/play/fortune.el =================================================================== RCS file: /cvsroot/emacs/emacs/lisp/play/fortune.el,v retrieving revision 1.14 diff -u -r1.14 fortune.el --- lisp/play/fortune.el 5 Feb 2006 14:10:44 -0000 1.14 +++ lisp/play/fortune.el 11 Oct 2006 22:54:10 -0000 @@ -252,7 +252,8 @@ (message "Compiling new fortune database %s" fortune-dat) (shell-command (concat fortune-strfile fortune-strfile-options - " " fortune-file fortune-quiet-strfile-options)))))) + " " (shell-quote-argument fortune-file) + fortune-quiet-strfile-options)))))) (t (error "Can't compile fortune file %s" fortune-file))))) Index: lisp/textmodes/fill.el =================================================================== RCS file: /cvsroot/emacs/emacs/lisp/textmodes/fill.el,v retrieving revision 1.192 diff -u -r1.192 fill.el --- lisp/textmodes/fill.el 6 Nov 2006 16:01:53 -0000 1.192 +++ lisp/textmodes/fill.el 7 Nov 2006 08:16:43 -0000 @@ -967,6 +967,8 @@ (forward-paragraph)) (setq max (copy-marker (point) t)) (goto-char (setq beg (min from to))) + ;;(skip-chars-forward " \t\n") ;; is this the way to go??? + (forward-paragraph 1) (forward-paragraph -1) (beginning-of-line) (while (< (point) max) (let ((initial (point)) @@ -987,9 +989,15 @@ (forward-paragraph -1)) (if (< (point) beg) (goto-char beg)) - (if (>= (point) initial) - (setq fill-pfx - (fill-region-as-paragraph (point) end justify nosqueeze)) + ;;(message "at point")(sit-for 1) + ;;(save-excursion (goto-char end)(message "at end")(sit-for 1)) + ;;(if (>= (point) initial) + (if (and (>= (point) initial) + (>= end (point))) + (progn + ;;(message "after skip")(sit-for 1) + (setq fill-pfx + (fill-region-as-paragraph (point) end justify nosqueeze))) (goto-char end)))) fill-pfx)) Index: src/keyboard.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/keyboard.c,v retrieving revision 1.879 diff -u -r1.879 keyboard.c --- src/keyboard.c 22 Oct 2006 22:25:03 -0000 1.879 +++ src/keyboard.c 23 Oct 2006 07:00:14 -0000 @@ -533,6 +533,9 @@ #endif Lisp_Object Qdrag_n_drop; Lisp_Object Qsave_session; +#ifdef WINDOWSNT +Lisp_Object Qw32_endsession_event; +#endif #ifdef MAC_OS Lisp_Object Qmac_apple_event; #endif @@ -4121,6 +4124,13 @@ obj = Fcons (Qsave_session, Qnil); kbd_fetch_ptr = event + 1; } +#ifdef WINDOWSNT + else if (event->kind == W32_ENDSESSION_EVENT) + { + obj = Fcons (Qw32_endsession_event, Qnil); + kbd_fetch_ptr = event + 1; + } +#endif /* Just discard these, by returning nil. With MULTI_KBOARD, these events are used as placeholders when we need to randomly delete events from the queue. @@ -5958,6 +5968,11 @@ case SAVE_SESSION_EVENT: return Qsave_session; +#ifdef WINDOWSNT + case W32_ENDSESSION_EVENT: + return Qw32_endsession_event; +#endif + #ifdef MAC_OS case MAC_APPLE_EVENT: { @@ -11021,6 +11036,11 @@ Qsave_session = intern ("save-session"); staticpro (&Qsave_session); +#ifdef WINDOWSNT + Qw32_endsession_event = intern ("w32-endsession-event"); + staticpro (&Qw32_endsession_event); +#endif + #ifdef MAC_OS Qmac_apple_event = intern ("mac-apple-event"); staticpro (&Qmac_apple_event); @@ -11663,6 +11683,12 @@ * "handle-select-window"); */ initial_define_lispy_key (Vspecial_event_map, "save-session", "handle-save-session"); + /* W32 log off event */ + initial_define_lispy_key (Vspecial_event_map, "w32-endsession-event", + /* There should maybe be some other + function here (like do-auto-save + + kill-emacs): */ + "save-buffers-kill-emacs"); } /* Mark the pointers in the kboard objects. Index: src/termhooks.h =================================================================== RCS file: /cvsroot/emacs/emacs/src/termhooks.h,v retrieving revision 1.74 diff -u -r1.74 termhooks.h --- src/termhooks.h 5 May 2006 06:45:04 -0000 1.74 +++ src/termhooks.h 27 Jun 2006 14:36:25 -0000 @@ -328,6 +328,10 @@ save yourself before shutdown. */ SAVE_SESSION_EVENT, +#ifdef WINDOWSNT + W32_ENDSESSION_EVENT, +#endif + #ifdef MAC_OS /* Generated when an Apple event, a HICommand event, or a Services menu event is received and the corresponding handler is @@ -337,6 +341,7 @@ are converted to those in Apple events. */ MAC_APPLE_EVENT #endif + }; /* If a struct input_event has a kind which is SELECTION_REQUEST_EVENT Index: src/w32console.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/w32console.c,v retrieving revision 1.46 diff -u -r1.46 w32console.c --- src/w32console.c 30 Jun 2006 01:32:24 -0000 1.46 +++ src/w32console.c 2 Jul 2006 09:32:20 -0000 @@ -41,6 +41,7 @@ #undef HAVE_WINDOW_SYSTEM #include "frame.h" #include "w32inevt.h" +#include "w32term.h" /* from window.c */ extern Lisp_Object Frecenter (); @@ -95,8 +96,31 @@ ctrl_c_handler (unsigned long type) { /* Only ignore "interrupt" events when running interactively. */ - return (!noninteractive - && (type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT)); +/* return (!noninteractive */ +/* && (type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT)); */ + if (!noninteractive) { + switch (type) + { + case CTRL_C_EVENT: + case CTRL_BREAK_EVENT: + return TRUE; + case CTRL_CLOSE_EVENT: // 2 + case CTRL_LOGOFF_EVENT: // 5 + case CTRL_SHUTDOWN_EVENT: // 6 + /* Ending session so tell user */ + //printf("ctrl_c_handler=%d, dwWindowsThreadid=%d\n", type, dwWindowsThreadId); fflush(stdout); + { + W32Msg wmsg; + wmsg.msg.hwnd = 0; + wmsg.msg.message = WM_EMACS_KILL; + wmsg.msg.wParam = 0; + wmsg.msg.lParam = 0; + post_msg(&wmsg); + return TRUE; + } + } + } + return FALSE; } /* If we're updating a frame, use it as the current frame Index: src/w32fns.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/w32fns.c,v retrieving revision 1.279 diff -u -r1.279 w32fns.c --- src/w32fns.c 4 Nov 2006 12:21:29 -0000 1.279 +++ src/w32fns.c 6 Nov 2006 08:29:11 -0000 @@ -2163,9 +2163,20 @@ #define EMACS_LMENU 2 #define EMACS_RMENU 3 -static int modifiers[4]; +/* The keys above are also saved in modifiers[]. To allow + w32-pass-lwindow-to-system to be nil the state of the left and + right windows keys must also be saved in modifiers[]. This is a bit + tricky since Windows does not keep track of the state of those keys + when StickyKeys are on. (Because they are registered as hot + keys?) */ + +#define EMACS_LWIN 4 +#define EMACS_RWIN 5 + +static int modifiers[6]; static int modifiers_recorded; static int modifier_key_support_tested; +static BOOL b_menu_pending = FALSE; static void test_modifier_support (unsigned int wparam) @@ -2199,10 +2210,25 @@ if (!modifier_key_support_tested) test_modifier_support (wparam); - if ((wparam != VK_CONTROL && wparam != VK_MENU) || !modifiers_recorded) - return; + if (VK_LWIN != wparam && VK_RWIN != wparam) { + if ((wparam != VK_CONTROL && wparam != VK_MENU) || !modifiers_recorded) + return; + } else { + if (VK_LWIN == wparam && !NILP(Vw32_pass_lwindow_to_system)) { + return; + } + if (VK_RWIN == wparam && !NILP(Vw32_pass_rwindow_to_system)) { + return; + } + } - if (wparam == VK_CONTROL) + //printf("record_keydow2 wp=%d lp=%x\n", wparam, lparam); fflush(stdout); + + if (VK_LWIN == wparam) { + i = EMACS_LWIN; + } else if (VK_RWIN == wparam) { + i = EMACS_RWIN; + } else if (wparam == VK_CONTROL) i = (lparam & 0x1000000) ? EMACS_RCONTROL : EMACS_LCONTROL; else i = (lparam & 0x1000000) ? EMACS_RMENU : EMACS_LMENU; @@ -2215,17 +2241,47 @@ { int i; - if ((wparam != VK_CONTROL && wparam != VK_MENU) || !modifiers_recorded) - return; + if (VK_LWIN != wparam && VK_RWIN != wparam) { + if ((wparam != VK_CONTROL && wparam != VK_MENU) || !modifiers_recorded) + return; + } else { + if (VK_LWIN == wparam && !NILP(Vw32_pass_lwindow_to_system)) { + return; + } + if (VK_RWIN == wparam && !NILP(Vw32_pass_rwindow_to_system)) { + return; + } + } + //printf("record_keyup2 wp=%d lp=%x\n", wparam, lparam); fflush(stdout); - if (wparam == VK_CONTROL) + if (VK_LWIN == wparam) { + i = EMACS_LWIN; + } else if (VK_RWIN == wparam) { + i = EMACS_RWIN; + } else if (wparam == VK_CONTROL) i = (lparam & 0x1000000) ? EMACS_RCONTROL : EMACS_LCONTROL; else i = (lparam & 0x1000000) ? EMACS_RMENU : EMACS_LMENU; + if (EMACS_LWIN == i || EMACS_RWIN == i) { + //printf("record_keyup wp=%d, i=%d\n", wparam, i); fflush(stdout); + } modifiers[i] = 0; } +static void +set_key_state(int vkey, int state) +{ + BYTE keystate[256]; + +#define CURRENT_STATE(key) ((GetAsyncKeyState (key) & 0x8000) >> 8) + + GetKeyboardState (keystate); + keystate[vkey] = state; + SetKeyboardState (keystate); +} + + /* Emacs can lose focus while a modifier key has been pressed. When it regains focus, be conservative and clear all modifiers since we cannot reconstruct the left and right modifier state. */ @@ -2238,6 +2294,9 @@ /* Emacs doesn't have keyboard focus. Do nothing. */ return; + //printf("resetting menu_pending 2\n"); fflush(stdout); + b_menu_pending = FALSE; + ctrl = GetAsyncKeyState (VK_CONTROL); alt = GetAsyncKeyState (VK_MENU); @@ -2249,6 +2308,15 @@ /* Clear any recorded alt modifier state. */ modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0; + if (!(GetAsyncKeyState(VK_LWIN) & 0x08000)) { + //printf("EMACS_LWIN 1=0\n"); fflush(stdout); + modifiers[EMACS_LWIN] = 0; + } + if (!(GetAsyncKeyState(VK_RWIN) & 0x08000)) { + //printf("EMACS_RWIN 1=0\n"); fflush(stdout); + modifiers[EMACS_RWIN] = 0; + } + /* Update the state of all modifier keys, because modifiers used in hot-key combinations can get stuck on if Emacs loses focus as a result of a hot-key being pressed. */ @@ -2287,13 +2355,31 @@ if (!(GetKeyState (VK_MENU) & 0x8000)) modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0; + + if (!(GetKeyState (VK_LWIN) & 0x8000)) { + //printf("EMACS_LWIN 2=0\n"); fflush(stdout); + modifiers[EMACS_LWIN] = 0; + } + if (!(GetKeyState (VK_RWIN) & 0x8000)) { + //printf("EMACS_RWIN 2=0\n"); fflush(stdout); + modifiers[EMACS_RWIN] = 0; + } } static int modifier_set (int vkey) { + //if (vkey) { printf("modifier_set %d\n", vkey); fflush(stdout); } if (vkey == VK_CAPITAL || vkey == VK_SCROLL) return (GetKeyState (vkey) & 0x1); + if (VK_LWIN == vkey && NILP(Vw32_pass_lwindow_to_system)) { + //printf("modifier_set L %d, %d\n", vkey, modifiers[EMACS_LWIN]); fflush(stdout); + return modifiers[EMACS_LWIN]; + } + if (VK_RWIN == vkey && NILP(Vw32_pass_rwindow_to_system)) { + //printf("modifier_set R %d, %d\n", vkey, modifiers[EMACS_RWIN]); fflush(stdout); + return modifiers[EMACS_RWIN]; + } if (!modifiers_recorded) return (GetKeyState (vkey) & 0x8000); @@ -2489,6 +2575,13 @@ } } +int cAccelerators = 0; // number of accelerators in table +static HACCEL hAccelDyn = NULL; +static LPACCEL lpaccelDyn = NULL; + +BOOL add_LowLevelKeyboardProc(); +BOOL remove_LowLevelKeyboardProc(); + /* Main message dispatch loop. */ static void @@ -2497,11 +2590,15 @@ MSG msg; int result; HWND focus_window; + BOOL bRet; msh_mousewheel = RegisterWindowMessage (MSH_MOUSEWHEEL); - while (GetMessage (&msg, NULL, 0, 0)) + while ( (bRet = GetMessage (&msg, NULL, 0, 0)) != 0) { + if (-1 == bRet) { + // error, handle? + } else { if (msg.hwnd == NULL) { switch (msg.message) @@ -2509,6 +2606,27 @@ case WM_NULL: /* Produced by complete_deferred_msg; just ignore. */ break; + case WM_QUERYENDSESSION: + //case WM_ENDSESSION: default handling + /* This is currently not used since Emacs does not + recieve this message (at least not to the windows + thread) but might be if Emacs is restructured. */ + { + W32Msg wmsg; + //printf("w32_msg_pump 1: WM_QUERYENDSESSION\n"); fflush(stdout); + my_post_msg (&wmsg, 0, WM_EMACS_KILL, 0, 0); + break; + } + case WM_EMACS_KBD_LL: + if (msg.wParam) { + result = (int) add_LowLevelKeyboardProc(); + } else { + result = (int) remove_LowLevelKeyboardProc(); + } + if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, + result, 0)) + abort (); + break; case WM_EMACS_CREATEWINDOW: w32_createwindow ((struct frame *) msg.wParam); if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0)) @@ -2584,8 +2702,19 @@ } else { - DispatchMessage (&msg); + BOOL bHandled = FALSE; + if (hAccelDyn) + if (Vw32_pass_alt_to_system) { + bHandled = TranslateAccelerator(msg.hwnd, hAccelDyn, &msg); + if (bHandled) { + //printf("...handled\n"); fflush(stdout); + } else { + printf("...TA failed: %s\n", w32_strerror(GetLastError())); fflush(stdout); + } + } + if (!bHandled) DispatchMessage (&msg); } + } /* Exit nested loop when our deferred message has completed. */ if (msg_buf->completed) @@ -2689,6 +2818,119 @@ PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0); } + + +LRESULT +LowLevelKeyboardProc(INT nCode, WPARAM wParam, LPARAM lParam) +{ + if (nCode == HC_ACTION) + { + KBDLLHOOKSTRUCT *pkbdllhook = (KBDLLHOOKSTRUCT *)lParam; + BOOL bHandle = FALSE; + UINT transition_state; + UINT previous_state = 0; + UINT context_code; + UINT extended_key; + UINT msg; + WPARAM wParamMsg; + LPARAM lParamMsg; + + switch (wParam) + { + case WM_KEYUP: + case WM_SYSKEYUP: + previous_state = 1; + case WM_KEYDOWN: // This was not in the MS example, why?? + case WM_SYSKEYDOWN: + /* Convert the message and send it on. + FIX-ME: This code should be moved down to bHandle part after + testing. */ + transition_state = pkbdllhook->flags >> 7 & 1; + context_code = pkbdllhook->flags >> 5 & 1; + extended_key = pkbdllhook->flags & 1; + msg = wParam; + wParamMsg = pkbdllhook->vkCode; + lParamMsg = + pkbdllhook->scanCode << 16 + | transition_state << 31 + | previous_state << 30 + | context_code << 29 + | extended_key << 24 + | 1; // repeat count +/* if (0 != GetFocus()) { */ +/* if (91 == pkbdllhook->vkCode) { */ +/* printf("ll wp=%d lp=%x, ts=%d, cc=%d, ek=%d\n", wParamMsg, lParamMsg, transition_state, context_code, extended_key); */ +/* fflush(stdout); */ +/* } */ +/* } */ + switch (pkbdllhook->vkCode) + { + /* Since Vw32_pass_lwindow_to_system is just a struct + and NILP a comparision with == we do not have to sync + to make this comparision in the windows thread. The + value might temporarily be wrong, but no crashes can + occor. (But what about cashing of the value in the + windows thread?) */ + case VK_LWIN: + { + bHandle = NILP(Vw32_pass_lwindow_to_system); + break; + } + case VK_RWIN: + { + bHandle = NILP(Vw32_pass_rwindow_to_system); + break; + } + } + } + if (bHandle) { + // Just to be sure check we are in the right thread + if (GetCurrentThreadId() == dwWindowsThreadId) { + // Do we have keyboard focus? + HWND hwnd = GetFocus(); + if (0 != hwnd) { + //printf("ll SendMessage(hwnd, msg, %x, %x)\n", wParamMsg, lParamMsg); fflush(stdout); + SendMessage (hwnd, msg, wParamMsg, lParamMsg); + return TRUE; + } + } + } + + + + } + HHOOK hhook; return CallNextHookEx(hhook, nCode, wParam, lParam); +} + +static HHOOK hLowKBhookW = NULL; + +BOOL +add_LowLevelKeyboardProc() +{ + if (NULL != hLowKBhookW) return TRUE; + if (GetCurrentThreadId() == dwWindowsThreadId) { + hLowKBhookW = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, (HINSTANCE) GetModuleHandle(NULL), 0); + if (NULL == hLowKBhookW) { + printf("SetWindowsHookEx error: %s\n", w32_strerror(GetLastError())); fflush(stdout); + return FALSE; + } + } else { + printf("add_LowLevelKeyboardProc called from other thread then windows thread\n"); fflush(stdout); + abort(); + } + return TRUE; +} +BOOL +remove_LowLevelKeyboardProc() +{ + if (NULL == hLowKBhookW) return TRUE; + if (!UnhookWindowsHookEx(hLowKBhookW)) { + printf("UnhookWindowsHookEx error: %s\n", w32_strerror(GetLastError())); fflush(stdout); + } + hLowKBhookW = NULL; +} + + DWORD w32_msg_worker (dw) DWORD dw; @@ -2709,8 +2951,33 @@ /* This is the inital message loop which should only exit when the application quits. */ + + /* Below is some test code if someone would like to use it. The + code is written after an example from MS but it does not work ;-) + */ +/* cAccelerators = 1; // number of accelerators in table */ +/* lpaccelDyn = (LPACCEL) LocalAlloc(LPTR, cAccelerators * sizeof(ACCEL)); */ +/* if (!lpaccelDyn) { */ +/* printf("LocalAlloc error: %s\n", w32_strerror(GetLastError())); fflush(stdout); */ +/* } else { */ +/* printf("LocalAlloc ok: %s\n", w32_strerror(GetLastError())); fflush(stdout); */ +/* } */ +/* lpaccelDyn[0].fVirt = FVIRTKEY; */ +/* lpaccelDyn[0].key = VK_F4; */ +/* lpaccelDyn[0].cmd = 0; //SC_CLOSE; */ +/* hAccelDyn = CreateAcceleratorTable(lpaccelDyn, cAccelerators); */ +/* if (!hAccelDyn) { */ +/* printf("CreateAcceleratorTable error: %s\n", w32_strerror(GetLastError())); fflush(stdout); */ +/* } else { */ +/* printf("CreateAcceleratorTable ok: %s\n", w32_strerror(GetLastError())); fflush(stdout); */ +/* } */ + w32_msg_pump (&dummy_buf); + if (lpaccelDyn) { + LocalFree(lpaccelDyn); + } + return 0; } @@ -2733,17 +3000,25 @@ static void -post_character_message (hwnd, msg, wParam, lParam, modifiers) +post_character_message (hwnd, msg, wParam, lParam, dwmodifiers) HWND hwnd; UINT msg; WPARAM wParam; LPARAM lParam; - DWORD modifiers; + DWORD dwmodifiers; { W32Msg wmsg; - wmsg.dwModifiers = modifiers; + //printf("post_char, msg=%d, wp=%x, lp=%x, mod=%x\n", msg, wParam, lParam, dwmodifiers); fflush(stdout); + // Clear LWIN here to be able to handle it for StickyKeys + modifiers[EMACS_LWIN] = modifiers[EMACS_RWIN] = 0; + + // Never post alt_modifier here if system should have ALT + if (!NILP (Vw32_pass_alt_to_system)) { + dwmodifiers = (dwmodifiers | alt_modifier) ^ alt_modifier; + } + wmsg.dwModifiers = dwmodifiers; /* Detect quit_char and set quit-flag directly. Note that we still need to post a message to ensure the main thread will be @@ -2805,6 +3080,17 @@ WPARAM wParam; LPARAM lParam; { + //printf("w32_wnd_proc(hwnd, %d, %x, %x)\n", msg, wParam, lParam); fflush(stdout); + BOOL bStickyKeysOn = FALSE; + STICKYKEYS stick; + /* Bit 24 should be "extended key" for key messages. However + it seems to have some other functions too when StickyKeys are + on. */ + BOOL bit24 = FALSE; + /* Bit 29 is context code for key messages (Alt pressed or not) */ + //BOOL bit29 = FALSE; + static BOOL b_was_menu_pending = FALSE; + struct frame *f; struct w32_display_info *dpyinfo = &one_w32_display_info; W32Msg wmsg; @@ -2944,13 +3230,136 @@ PostMessage (hwnd, WM_KEYDOWN, HIWORD (lParam), 0); return (0); - case WM_KEYUP: + case WM_SYSCOMMAND: + //printf("WM_SYSCOMMAND, wpar=%x, lpar=%x\n", wParam, lParam); fflush(stdout); + goto dflt; case WM_SYSKEYUP: - record_keyup (wParam, lParam); + case WM_KEYUP: +/* b_was_menu_pending = b_menu_pending; */ +/* if (b_was_menu_pending) { */ +/* HWND hwndIn = hwnd; */ +/* UINT msgIn = msg; */ +/* WPARAM wParamIn = wParam; */ +/* LPARAM lParamIn = lParam; */ +/* //b_menu_pending = FALSE; */ +/* printf("sending WM_SYSCOMMAND, hwnd=%d, menu=%d\n", hwnd, GetMenu(hwnd)); fflush(stdout); */ +/* SendMessage (hwnd, WM_SYSCOMMAND, SC_KEYMENU, 0); */ +/* PostMessage (hwndIn, msgIn, wParamIn, lParamIn); */ +/* return 0; */ +/* } */ + + stick.cbSize = sizeof(STICKYKEYS); + if (!SystemParametersInfo(SPI_GETSTICKYKEYS, stick.cbSize, &stick, 0)) { + printf("error in spi: %s\n", w32_strerror(GetLastError)); fflush(stdout); + } else { + bStickyKeysOn = stick.dwFlags & SKF_STICKYKEYSON; + } + if (lParam >> 24 & 1) bit24 = TRUE; +/* { */ +/* BOOL vkmenu = FALSE; */ +/* BOOL vklmenu = FALSE; */ +/* BOOL vkrmenu = FALSE; */ +/* BOOL vklwin = FALSE; */ +/* BOOL vkrwin = FALSE; */ +/* BOOL vklwset = FALSE; */ +/* BOOL vkrwset = FALSE; */ +/* switch (wParam) { */ +/* case VK_MENU: */ +/* vkmenu = TRUE; */ +/* break; */ +/* case VK_RMENU: */ +/* vkrmenu = TRUE; */ +/* break; */ +/* case VK_LMENU: */ +/* vklmenu = TRUE; */ +/* break; */ +/* case VK_LWIN: */ +/* vklwin = TRUE; */ +/* break; */ +/* case VK_RWIN: */ +/* vkrwin = TRUE; */ +/* break; */ +/* } */ +/* vklwset = modifier_set(VK_LWIN); */ +/* vkrwset = modifier_set(VK_RWIN); */ +/* //if (91 == wParam) */ +/* //printf("WM_KUP, m=%d wp=%d lp=%x VK_M=%x VK_LM=%x VK_RM=%x VK_LW=%x 24=%x st=%d,%d\n", */ +/* printf(" WM_KUP, m=%d wp=%d lp=%8x VK_LW=%x,%x VK_RW=%x,%x 24=%x st=%d,%d\n", */ +/* //msg, wParam, lParam, vkmenu, vklmenu, vkrmenu, vklwin, */ +/* msg, wParam, lParam, vklwin, vklwset, vkrwin, vkrwset, */ +/* bit24, */ +/* GetKeyState(wParam), GetAsyncKeyState(wParam) */ +/* ); fflush(stdout); */ +/* if (wParam==8) { printf("\n"); fflush(stdout); } */ +/* } */ + + /* If StickyKeys is on we need to record VK_LWIN and VK_RWIN + when the system sends the special key up message when + pressing next key. */ + /* FIX-ME: Key state toggling works only with VK_LWIN! The code + below tries to make the use of LWIN and RWIN work in Emacs + both when using StickyKeys and not. When using StickyKeys + the keys should be "toggleable". Bit 24 seems to be useful + for toggling LWIN, but not for RWIN. For some reason the + messages sent in Windows are not the same for LWIN and RWIN. + I do not believe that the use of bit 24 this way is + documented so this part of the code might break. In that + case the version without bit 24 could be used. The only + thing that is lost is the possibility to toggle the state of + LWIN. From a user perspective this can always be done by + pressing C-g since M-C-g is never bound (I hope!). */ + //if (!((VK_LWIN == wParam || VK_RWIN ==wParam) && bStickyKeysOn)) + if (!(((VK_LWIN == wParam && 0 == bit24) || VK_RWIN == wParam) && bStickyKeysOn)) + record_keyup (wParam, lParam); goto dflt; - case WM_KEYDOWN: case WM_SYSKEYDOWN: + case WM_KEYDOWN: + stick.cbSize = sizeof(STICKYKEYS); + if (!SystemParametersInfo(SPI_GETSTICKYKEYS, stick.cbSize, &stick, 0)) { + printf("error in spi: %s\n", w32_strerror(GetLastError)); fflush(stdout); + } else { + bStickyKeysOn = stick.dwFlags & SKF_STICKYKEYSON; + } + if (lParam >> 24 & 1) bit24 = TRUE; + +/* { */ +/* BOOL vkmenu = FALSE; */ +/* BOOL vklmenu = FALSE; */ +/* BOOL vkrmenu = FALSE; */ +/* BOOL vklwin = FALSE; */ +/* BOOL vkrwin = FALSE; */ +/* BOOL vklwset = FALSE; */ +/* BOOL vkrwset = FALSE; */ +/* switch (wParam) { */ +/* case VK_MENU: */ +/* vkmenu = TRUE; */ +/* break; */ +/* case VK_RMENU: */ +/* vkrmenu = TRUE; */ +/* break; */ +/* case VK_LMENU: */ +/* vklmenu = TRUE; */ +/* break; */ +/* case VK_LWIN: */ +/* vklwin = TRUE; */ +/* break; */ +/* case VK_RWIN: */ +/* vkrwin = TRUE; */ +/* break; */ +/* } */ +/* vklwset = modifier_set(VK_LWIN); */ +/* vkrwset = modifier_set(VK_RWIN); */ +/* if (lParam >> 24 & 1) bit24 = TRUE; */ +/* //if (91 == wParam) */ +/* //printf("WM_DWN m=%d w=%d lp=%x VK_M=%x VK_LM=%x VK_RM=%x VK_LW=%x B24=%x 29=%d BS=%x, s=%d,%d sy=%d\n", */ +/* printf("WM_DWN, m=%d wp=%d lp=%10x VK_LW=%x,%x VK_RW=%x,%x 24=%x st=%d,%d\n", */ +/* msg, wParam, lParam, vklwin, vklwset, vkrwin, vkrwset, */ +/* bit24, */ +/* GetKeyState(wParam), GetAsyncKeyState(wParam) */ +/* ); fflush(stdout); */ +/* } */ + /* Ignore keystrokes we fake ourself; see below. */ if (dpyinfo->faked_key == wParam) { @@ -2968,6 +3377,8 @@ } /* Synchronize modifiers with current keystroke. */ + b_was_menu_pending = b_menu_pending; + b_menu_pending = FALSE; sync_modifiers (); record_keydown (wParam, lParam); wParam = map_keypad_keys (wParam, (lParam & 0x1000000L) != 0); @@ -2977,39 +3388,44 @@ switch (wParam) { case VK_LWIN: - if (NILP (Vw32_pass_lwindow_to_system)) - { - /* Prevent system from acting on keyup (which opens the - Start menu if no other key was pressed) by simulating a - press of Space which we will ignore. */ - if (GetAsyncKeyState (wParam) & 1) - { - if (NUMBERP (Vw32_phantom_key_code)) - key = XUINT (Vw32_phantom_key_code) & 255; - else - key = VK_SPACE; - dpyinfo->faked_key = key; - keybd_event (key, (BYTE) MapVirtualKey (key, 0), 0, 0); - } - } - if (!NILP (Vw32_lwindow_modifier)) - return 0; + if (NULL == hLowKBhookW) { + if (NILP (Vw32_pass_lwindow_to_system)) + { + /* Prevent system from acting on keyup (which opens the + Start menu if no other key was pressed) by simulating a + press of Space which we will ignore. */ + //printf("Sending 255 to prevent\n"); fflush(stdout); + if (GetAsyncKeyState (wParam) & 1) + { + if (NUMBERP (Vw32_phantom_key_code)) + key = XUINT (Vw32_phantom_key_code) & 255; + else + key = VK_SPACE; + dpyinfo->faked_key = key; + keybd_event (key, (BYTE) MapVirtualKey (key, 0), 0, 0); + } + } + } else { + //printf("Avoided sending 255 to prevent\n"); fflush(stdout); + } + if (!NILP (Vw32_lwindow_modifier)) return 0; break; case VK_RWIN: - if (NILP (Vw32_pass_rwindow_to_system)) - { - if (GetAsyncKeyState (wParam) & 1) - { - if (NUMBERP (Vw32_phantom_key_code)) - key = XUINT (Vw32_phantom_key_code) & 255; - else - key = VK_SPACE; - dpyinfo->faked_key = key; - keybd_event (key, (BYTE) MapVirtualKey (key, 0), 0, 0); - } - } - if (!NILP (Vw32_rwindow_modifier)) - return 0; + if (NULL == hLowKBhookW) { + if (NILP (Vw32_pass_rwindow_to_system)) + { + if (GetAsyncKeyState (wParam) & 1) + { + if (NUMBERP (Vw32_phantom_key_code)) + key = XUINT (Vw32_phantom_key_code) & 255; + else + key = VK_SPACE; + dpyinfo->faked_key = key; + keybd_event (key, (BYTE) MapVirtualKey (key, 0), 0, 0); + } + } + } + if (!NILP (Vw32_rwindow_modifier)) return 0; break; case VK_APPS: if (!NILP (Vw32_apps_modifier)) @@ -3019,7 +3435,12 @@ if (NILP (Vw32_pass_alt_to_system)) /* Prevent DefWindowProc from activating the menu bar if an Alt key is pressed and released by itself. */ - return 0; + return 0; + /* By not testing for StickyKeysOn here we get the advantage + that holding down Alt and then typing a letter can open + the menu. This seems to be the way other apps behave on + w32. */ + b_menu_pending = TRUE; windows_translate = 1; break; case VK_CAPITAL: @@ -3080,6 +3501,24 @@ wParam = VK_NUMLOCK; break; default: + if (b_was_menu_pending) { + /* FIX-ME: Where should this go? Should it go to the + WM_CHAR section where the translated WM_KEY... returns? + (Remember to move b_was_menu_pending too!) */ + HWND hwndIn = hwnd; + UINT msgIn = msg; + WPARAM wParamIn = wParam; + LPARAM lParamIn = lParam; + b_menu_pending = FALSE; + + if(!(modifier_set (VK_LCONTROL) && modifier_set (VK_RMENU))) { + //printf("sending WM_SYSCOMMAND, hwnd=%d, menu=%d\n", hwnd, GetMenu(hwnd)); fflush(stdout); + SendMessage (hwnd, WM_SYSCOMMAND, SC_KEYMENU, wParam); + return 0; + } else { + //printf("... no menu, was AltGr...\n"); fflush(stdout); + } + } /* If not defined as a function key, change it to a WM_CHAR message. */ if (lispy_function_keys[wParam] == 0) { @@ -3431,6 +3870,9 @@ goto dflt; case WM_INITMENU: + //printf("WM_INITMENU in w32fns.c, hwnd=%d, wParam=%d\n", hwnd, wParam); fflush(stdout); + //printf("resetting menu_pending 1\n"); fflush(stdout); + b_menu_pending = FALSE; button_state = 0; ReleaseCapture (); /* We must ensure menu bar is fully constructed and up to date @@ -3468,7 +3910,23 @@ if (find_deferred_msg (hwnd, msg) != NULL) abort (); - return send_deferred_msg (&msg_buf, hwnd, msg, wParam, lParam); + //return send_deferred_msg (&msg_buf, hwnd, msg, wParam, lParam); + + my_post_msg (&wmsg, hwnd, msg, wParam, lParam); + { + MSG msg; + /* Use PeekMessage to avoid blocking infinitely. 2 sec max + (this an arbitrary choice). 40 ms is choosen to be as + long as possible but still short enough to be + "invisible". */ + // FIX-ME: maybe check for C-g in the loop! + int i; + for (i = 1; i < 50; i++) { + if (PeekMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE, PM_REMOVE)) break; + Sleep(40); + } + } + return 0; } case WM_EXITMENULOOP: @@ -3650,10 +4108,21 @@ goto dflt; case WM_CLOSE: + //printf("w32_wnd_proc WM_CLOSE\n"); fflush(stdout); wmsg.dwModifiers = w32_get_modifiers (); my_post_msg (&wmsg, hwnd, msg, wParam, lParam); return 0; + case WM_QUERYENDSESSION: + //case WM_ENDSESSION: + // I do not think this should happen but I am not sure. + { + W32Msg wmsg; + //printf("w32_wnd_proc: WM_QUERYENDSESSION\n"); fflush(stdout); + my_post_msg (&wmsg, 0, WM_EMACS_KILL, 0, 0); + } + return 0; + case WM_WINDOWPOSCHANGING: /* Don't restrict the sizing of tip frames. */ if (hwnd == tip_window) @@ -3707,12 +4176,14 @@ However for top/left sizing we will need to fix the X and Y positions as well. */ - lppos->cx -= wdiff; - lppos->cy -= hdiff; +/* lppos->cx -= wdiff; */ +/* lppos->cy -= hdiff; */ if (wp.showCmd != SW_SHOWMAXIMIZED && (lppos->flags & SWP_NOMOVE) == 0) { + lppos->cx -= wdiff; + lppos->cy -= hdiff; if (lppos->x != wr.left || lppos->y != wr.top) { lppos->x += wdiff; @@ -3791,8 +4262,14 @@ case WM_EMACS_SETWINDOWPOS: { WINDOWPOS * pos = (WINDOWPOS *) wParam; - return SetWindowPos (hwnd, pos->hwndInsertAfter, - pos->x, pos->y, pos->cx, pos->cy, pos->flags); + if (IsZoomed(hwnd)) { + return SetWindowPos (hwnd, pos->hwndInsertAfter, + pos->x, pos->y, pos->cx, pos->cy, + pos->flags | SWP_NOMOVE | SWP_NOSIZE); + } else { + return SetWindowPos (hwnd, pos->hwndInsertAfter, + pos->x, pos->y, pos->cx, pos->cy, pos->flags); + } } case WM_EMACS_DESTROYWINDOW: @@ -8172,6 +8649,34 @@ return HOTKEY (vk_code, w32_modifiers); } +DEFUN ("w32-wh-keyboard-ll", Fw32_wh_keyboard_ll, + Sw32_wh_keyboard_ll, 1, 1, 0, + doc: /* Activate/deactivate Emacs low level keyboard hook. +A low level Windows keyboard hook must be used to trap keys that other +applications have registered as hot keys. If ON is non-nil Emacs low +level keyboard hook is activated, if ON is nil it is deactivated. + +The keys that can be trapped are the left and right windows +keys. Beware that these are not present on all keyboards. If +`w32-pass-lwindow-to-system' and `w32-pass-rwindow-to-system' are nil +these keys will not be sent to the application that has registered +them as hot keys if Emacs low level keyboard hook as active. + +You should normally not call this function directly. Use +`w32-meta-style' instead. */) + (on) + Lisp_Object on; +{ + DWORD wp = 1; + MSG msg; + if (NILP(on)) wp = 0; + if (!PostThreadMessage (dwWindowsThreadId, WM_EMACS_KBD_LL, (WPARAM) wp, 0)) + abort(); + GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE); + if (msg.wParam == 0) return Qnil; + return Qt; +} + DEFUN ("w32-register-hot-key", Fw32_register_hot_key, Sw32_register_hot_key, 1, 1, 0, doc: /* Register KEY as a hot-key combination. @@ -8933,6 +9438,7 @@ defsubr (&Sw32_load_color_file); defsubr (&Sw32_send_sys_command); defsubr (&Sw32_shell_execute); + defsubr (&Sw32_wh_keyboard_ll); defsubr (&Sw32_register_hot_key); defsubr (&Sw32_unregister_hot_key); defsubr (&Sw32_registered_hot_keys); Index: src/w32menu.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/w32menu.c,v retrieving revision 1.84 diff -u -r1.84 w32menu.c --- src/w32menu.c 6 Nov 2006 16:47:20 -0000 1.84 +++ src/w32menu.c 7 Nov 2006 08:17:09 -0000 @@ -987,7 +987,8 @@ f->output_data.w32->menubar_active = 1; /* Signal input thread to return from WM_INITMENU. */ - complete_deferred_msg (FRAME_W32_WINDOW (f), WM_INITMENU, 0); + //complete_deferred_msg (FRAME_W32_WINDOW (f), WM_INITMENU, 0); + if (!PostThreadMessage(dwWindowsThreadId, WM_EMACS_DONE, 0, 0)) abort(); } /* This callback is called from the menu bar pulldown menu Index: src/w32term.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/w32term.c,v retrieving revision 1.252 diff -u -r1.252 w32term.c --- src/w32term.c 27 Oct 2006 22:35:49 -0000 1.252 +++ src/w32term.c 2 Nov 2006 14:42:14 -0000 @@ -3558,7 +3558,12 @@ pos.flags = flags; SendMessage (hwnd, WM_EMACS_SETWINDOWPOS, (WPARAM) &pos, 0); #else - SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags); + if (IsZoomed(hwnd)) { + SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, + flags | SWP_NOMOVE | SWP_NOSIZE); + } else { + SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags); + } #endif } @@ -3754,9 +3759,11 @@ /* Make sure scroll bar is "visible" before moving, to ensure the area of the parent window now exposed will be refreshed. */ my_show_window (f, hwnd, SW_HIDE); - MoveWindow (hwnd, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, - top, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2, - max (height, 1), TRUE); + if (!IsZoomed (hwnd)) { + MoveWindow (hwnd, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, + top, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2, + max (height, 1), TRUE); + } si.cbSize = sizeof (si); si.fMask = SIF_RANGE; @@ -4683,6 +4690,11 @@ } break; + case WM_EMACS_KILL: + //printf("w32_read_socket WM_EMACS_KILL\n"); fflush(stdout); + inev.kind = W32_ENDSESSION_EVENT; + break; + case WM_INITMENU: f = x_window_to_frame (dpyinfo, msg.msg.hwnd); Index: src/w32term.h =================================================================== RCS file: /cvsroot/emacs/emacs/src/w32term.h,v retrieving revision 1.66 diff -u -r1.66 w32term.h --- src/w32term.h 7 Feb 2006 07:59:50 -0000 1.66 +++ src/w32term.h 16 Feb 2006 23:55:07 -0000 @@ -630,7 +630,8 @@ #define WM_EMACS_SHOW_CARET (WM_EMACS_START + 17) #define WM_EMACS_HIDE_CARET (WM_EMACS_START + 18) #define WM_EMACS_SETCURSOR (WM_EMACS_START + 19) -#define WM_EMACS_END (WM_EMACS_START + 20) +#define WM_EMACS_KBD_LL (WM_EMACS_START + 20) +#define WM_EMACS_END (WM_EMACS_START + 21) #define WND_FONTWIDTH_INDEX (0) #define WND_LINEHEIGHT_INDEX (4)