? old ? lib-src/old ? lisp/help-scroll-isearch.patch ? lisp/help-scroll.patch ? lisp/isearch.patch ? lisp/old ? nt/bootstrap-050927.tmp ? nt/bootstrap-050928.tmp ? nt/bootstrap-050930.tmp ? nt/bootstrap-051005.tmp ? nt/bootstrap-051010.tmp ? nt/bootstrap-051021.tmp ? nt/config-050927.tmp ? nt/config-050928.tmp ? nt/config-050930.tmp ? nt/config-051005.tmp ? nt/config-051010.tmp ? nt/config-051021.tmp ? nt/emacs-ifdefs.el ? nt/info-050927.tmp ? nt/info-050928.tmp ? nt/info-050930.tmp ? nt/info-051005.tmp ? nt/info-051010.tmp ? nt/info-051021.tmp ? nt/install-050927.tmp ? nt/install-050928.tmp ? nt/install-050930.tmp ? nt/install-051005.tmp ? nt/install-051010.tmp ? nt/install-051021.tmp ? nt/junkinc.h ? nt/recompile.cmd ? nt/temprwin.txt ? nt/w32-meta.el ? nt/icons/gnu-m-x-16+32.ico ? site-lisp/subdirs.el ? src/junk.c ? src/junkinc.h ? src/keymap-c.diff ? src/kim-balance.diff ? src/make-ifdefs-all-defs.h ? src/make-ifdefs-cc.txt ? src/make-ifdefs-temp.el ? src/make-ifdefs.h ? src/make-ifdefs.pl ? src/old ? src/orig ? src/patch ? src/temp.pl ? src/tempdef.h ? src/w32fns.diff ? src/w32menu.diff ? src/w32term_h.diff Index: lisp/help-macro.el =================================================================== RCS file: /cvsroot/emacs/emacs/lisp/help-macro.el,v retrieving revision 1.34 diff -u -r1.34 help-macro.el --- lisp/help-macro.el 6 Aug 2005 22:13:43 -0000 1.34 +++ lisp/help-macro.el 9 Aug 2005 01:09:18 -0000 @@ -83,21 +83,32 @@ (defmacro make-help-screen (fname help-line help-text helped-map) "Construct help-menu function name FNAME. -When invoked, FNAME shows HELP-LINE and reads a command using HELPED-MAP. -If the command is the help character, FNAME displays HELP-TEXT -and continues trying to read a command using HELPED-MAP. +When invoked, FNAME shows HELP-LINE and reads a command using +HELPED-MAP. If the command is the help character, FNAME displays +HELP-TEXT and continues trying to read a command using +HELPED-MAP. + If HELP-TEXT contains the sequence `%THIS-KEY%', that is replaced with the key sequence that invoked FNAME. + +When calling FNAME if the optional parameters X-FUNCTION, X-CHAR +and X-DESCRIPTION to the defined function FNAME are given they +must all be given. In this case the the sequence +`%X-DESCRIPTION%' in HELP-TEXT is replaced with the parameters +X-CHAR character and the X-DESCRIPTION string. Also the keyboard +character X-CHAR is bound to the parameter X-FUNCTION. + When FNAME finally does get a command, it executes that command and then returns." (let ((doc-fn (intern (concat (symbol-name fname) "-doc")))) `(progn (defun ,doc-fn () ,help-text) - (defun ,fname () + (defun ,fname (&optional x-function x-char x-description) "Help command." (interactive) (let ((line-prompt (substitute-command-keys ,help-line))) + (when x-char (setq line-prompt (concat (char-to-string x-char) " " line-prompt))) (if three-step-help (message "%s" line-prompt)) (let* ((help-screen (documentation (quote ,doc-fn))) @@ -105,6 +116,12 @@ ;; sections, *excluding* where we switch buffers ;; and where we execute the chosen help command. (local-map (make-sparse-keymap)) + ;; Some keys should still be available + (still-map (make-sparse-keymap)) + (still-lst (list '(scroll-other-window-down . scroll-down) + '(scroll-other-window . scroll-up))) + still-cmd + (curr-wind (selected-window)) (minor-mode-map-alist nil) (prev-frame (selected-frame)) config new-frame key char) @@ -112,9 +129,28 @@ (setq help-screen (replace-match (key-description (substring (this-command-keys) 0 -1)) t t help-screen))) + (when (string-match "%X-DESCRIPTION%" help-screen) + (let ((x-repl + (if x-description + (format "\n%s %s\n\n" (char-to-string x-char) x-description) + ""))) + (setq help-screen + (replace-match x-repl + t t help-screen)))) + (mapc (lambda (elt) + (let ((new (if (consp elt) (cdr elt) elt)) + (orig (if (consp elt) (car elt) elt))) + (mapc (lambda (key) + (define-key still-map key new)) + (where-is-internal orig)))) + still-lst) + ;; Maybe it is good for new users with just next/prior? + (define-key still-map [(next)] 'scroll-up) + (define-key still-map [(prior)] 'scroll-down) (unwind-protect (progn (setcdr local-map ,helped-map) + (when x-function (define-key local-map (make-vector 1 x-char) x-function)) (define-key local-map [t] 'undefined) ;; Make the scroll bar keep working normally. (define-key local-map [vertical-scroll-bar] @@ -146,7 +182,8 @@ (while (or (memq char (append help-event-list (cons help-char '(?? ?\C-v ?\s ?\177 delete backspace vertical-scroll-bar ?\M-v)))) (eq (car-safe char) 'switch-frame) - (equal key "\M-v")) + (equal key "\M-v") + still-cmd) (condition-case nil (progn (if (eq (car-safe char) 'switch-frame) @@ -161,12 +198,23 @@ (let ((cursor-in-echo-area t) (overriding-local-map local-map)) (setq key (read-key-sequence - (format "Type one of the options listed%s: " - (if (pos-visible-in-window-p - (point-max)) - "" ", or SPACE or DEL to scroll"))) - char (aref key 0))) - + (format "Type one of the options listed, or %s: " + (if (pos-visible-in-window-p (point-max)) + "Page Up" + (if (pos-visible-in-window-p (point-min)) + "Page Down" + "or Page Up/Down to scroll")))) + char (aref key 0))) + + ;; If this is one of the commands we still should run then run it. + (setq still-cmd (lookup-key still-map key)) + (when still-cmd + (let ((cmd (assq still-cmd still-lst))) + (unless cmd (setq cmd still-cmd)) + (condition-case nil + (command-execute cmd nil key) + (error nil)))) + ;; If this is a scroll bar command, just run it. (when (eq char 'vertical-scroll-bar) (command-execute (lookup-key local-map key) nil key))))) @@ -181,19 +229,23 @@ (let ((defn (lookup-key local-map key))) (if defn (progn - (if config - (progn - (set-window-configuration config) - (setq config nil))) - (if new-frame - (progn (iconify-frame new-frame) - (setq new-frame nil))) - (call-interactively defn)) - (ding))))) - (if new-frame (iconify-frame new-frame)) - (if config - (set-window-configuration config)))))) - ))) + ;; Do not restore in this case since we are still in help + (when (eq defn x-function) + (unless new-frame + (select-window curr-wind) + (setq config nil))) + (if config + (progn + (set-window-configuration config) + (setq config nil))) + (if new-frame + (progn (iconify-frame new-frame) + (setq new-frame nil))) + (call-interactively defn)) + (ding))))) + (if new-frame (iconify-frame new-frame)) + (if config + (set-window-configuration config))))))))) (provide 'help-macro) Index: lisp/help.el =================================================================== RCS file: /cvsroot/emacs/emacs/lisp/help.el,v retrieving revision 1.284 diff -u -r1.284 help.el --- lisp/help.el 6 Aug 2005 22:13:43 -0000 1.284 +++ lisp/help.el 9 Aug 2005 01:09:19 -0000 @@ -186,8 +186,8 @@ (make-help-screen help-for-help-internal "a b c C e f F i I k C-k l L m p s t v w C-c C-d C-f C-n C-p C-t C-w . or ? :" "You have typed %THIS-KEY%, the help character. Type a Help option: -\(Use SPC or DEL to scroll through this text. Type \\\\[help-quit] to exit the Help command.) - +\(Use Page Up/Down to scroll through this text. Type \\\\[help-quit] to exit the Help command.) +%X-DESCRIPTION% a command-apropos. Give a substring, and see a list of commands (functions that are interactively callable) that contain that substring. See also the apropos command. Index: lisp/isearch.el =================================================================== RCS file: /cvsroot/emacs/emacs/lisp/isearch.el,v retrieving revision 1.275 diff -u -r1.275 isearch.el --- lisp/isearch.el 29 Sep 2005 22:55:53 -0000 1.275 +++ lisp/isearch.el 29 Sep 2005 23:56:45 -0000 @@ -193,7 +193,7 @@ "Index in `regexp-search-ring' of last string reused. It is nil if none yet.") -(defcustom search-ring-update nil +(defcustom isearch-ring-update nil "*Non-nil if advancing or retreating in the search ring should cause search. Default value, nil, means edit the string instead." :type 'boolean @@ -370,7 +370,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) @@ -609,6 +610,12 @@ (defun isearch-mode-help () (interactive) (describe-function 'isearch-forward) + (save-excursion + (set-buffer "*Help*") + (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)) @@ -1701,6 +1708,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)) + (other-window 1) + (setq other-buffer-is-help (equal (buffer-name) "*Help*")) + (other-window -1) + (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)) @@ -1842,13 +1861,14 @@ (defun isearch-ring-adjust (advance) ;; Helper for isearch-ring-advance and isearch-ring-retreat (isearch-ring-adjust1 advance) - (if search-ring-update + ;; Changed because isearch-edit-string calls isearch-push-state + ;; but isearch-search does not + (if isearch-ring-update (progn (isearch-search) + (isearch-push-state) (isearch-update)) - (isearch-edit-string) - ) - (isearch-push-state)) + (isearch-edit-string))) (defun isearch-ring-advance () "Advance to the next search string in the ring." Index: src/w32fns.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/w32fns.c,v retrieving revision 1.256 diff -u -r1.256 w32fns.c --- src/w32fns.c 7 Aug 2005 12:33:18 -0000 1.256 +++ src/w32fns.c 28 Sep 2005 20:13:15 -0000 @@ -2143,9 +2143,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) @@ -2176,13 +2187,30 @@ { int i; + //printf("record_keydown wp=%d lp=%x, mod_rec=%d sup_tst=%d\n", wparam, lparam, modifiers_recorded, modifier_key_support_tested); fflush(stdout); + 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; @@ -2194,18 +2222,47 @@ record_keyup (unsigned int wparam, unsigned int lparam) { int i; + //printf("record_keyup wp=%d lp=%x\n", wparam, lparam); fflush(stdout); - 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. */ @@ -2218,6 +2275,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); @@ -2229,6 +2289,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. */ @@ -2267,13 +2336,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); @@ -2284,8 +2371,10 @@ case VK_RCONTROL: return modifiers[EMACS_RCONTROL]; case VK_LMENU: + //printf("modifier_set L2 %d, %d\n", vkey, modifiers[EMACS_LWIN]); fflush(stdout); return modifiers[EMACS_LMENU]; case VK_RMENU: + //printf("modifier_set R2 %d, %d\n", vkey, modifiers[EMACS_RWIN]); fflush(stdout); return modifiers[EMACS_RMENU]; } return (GetKeyState (vkey) & 0x8000); @@ -2345,6 +2434,7 @@ unsigned int w32_get_modifiers () { + //printf("w32_get_modifiers\n"); fflush(stdout); return ((modifier_set (VK_SHIFT) ? shift_modifier : 0) | (modifier_set (VK_CONTROL) ? ctrl_modifier : 0) | (modifier_set (VK_LWIN) ? w32_key_to_modifier (VK_LWIN) : 0) | @@ -2469,6 +2559,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 @@ -2477,11 +2574,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) @@ -2489,6 +2590,16 @@ case WM_NULL: /* Produced by complete_deferred_msg; just ignore. */ 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)) @@ -2564,8 +2675,16 @@ } 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", w32_strerror(GetLastError())); fflush(stdout); } + } + if (!bHandled) DispatchMessage (&msg); } + } /* Exit nested loop when our deferred message has completed. */ if (msg_buf->completed) @@ -2669,6 +2788,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; @@ -2689,23 +2921,56 @@ /* 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; } 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 @@ -2765,6 +3030,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; @@ -2904,13 +3180,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) { @@ -2928,6 +3327,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); @@ -2937,49 +3338,60 @@ 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)) return 0; break; - case VK_MENU: - if (NILP (Vw32_pass_alt_to_system)) - /* Prevent DefWindowProc from activating the menu bar if an + case VK_MENU: + 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: @@ -3040,6 +3452,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) { @@ -3372,6 +3802,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 @@ -3409,7 +3842,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: @@ -3648,12 +4097,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; @@ -3732,8 +4183,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: @@ -8111,6 +8568,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. @@ -8853,6 +9338,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.77 diff -u -r1.77 w32menu.c --- src/w32menu.c 31 Aug 2005 15:22:15 -0000 1.77 +++ src/w32menu.c 2 Sep 2005 23:23:39 -0000 @@ -986,7 +986,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.236 diff -u -r1.236 w32term.c --- src/w32term.c 14 Oct 2005 08:09:33 -0000 1.236 +++ src/w32term.c 21 Oct 2005 07:40:40 -0000 @@ -3560,7 +3560,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 } @@ -3764,9 +3769,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); + } if (pfnSetScrollInfo) { SCROLLINFO si; Index: src/w32term.h =================================================================== RCS file: /cvsroot/emacs/emacs/src/w32term.h,v retrieving revision 1.64 diff -u -r1.64 w32term.h --- src/w32term.h 7 Aug 2005 12:33:18 -0000 1.64 +++ src/w32term.h 9 Aug 2005 01:13:21 -0000 @@ -633,7 +633,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) Index: src/w32xfns.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/w32xfns.c,v retrieving revision 1.23 diff -u -r1.23 w32xfns.c --- src/w32xfns.c 7 Aug 2005 12:33:18 -0000 1.23 +++ src/w32xfns.c 9 Aug 2005 01:13:21 -0000 @@ -208,6 +208,7 @@ post_msg (lpmsg) W32Msg * lpmsg; { + //printf("post_msg: %d, %d, %x, %x)\n", lpmsg->msg.message, lpmsg->msg.wParam, lpmsg->msg.lParam, lpmsg->dwModifiers); fflush(stdout); int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg)); if (!lpNew)