unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* [PATCH] Override Windows default Win-* key combinations when using Emacs
@ 2016-01-05 12:51 Jussi Lahdenniemi
  2016-01-05 13:54 ` Herring, Davis
  2016-01-05 17:05 ` Eli Zaretskii
  0 siblings, 2 replies; 63+ messages in thread
From: Jussi Lahdenniemi @ 2016-01-05 12:51 UTC (permalink / raw)
  To: emacs-devel

Hello,

I finally got around to submitting a patch I wrote some four years ago 
that enables Emacs users on Windows to override the default Windows key 
combinations reserved by the operating system. Especially the newer 
Windowses (7, 8, 10) define quite a large number of Win+* hotkeys to a 
variety of shell functions, restricting the available S-* keys on Emacs.

This is accomplished by running an external process (supersuper.exe) 
that captures keypresses, suppressing unwanted ones from the system, and 
informing the currently active Emacs process about them as necessary. 
All Win key combinations are thus blocked and made available for Emacs, 
except Win+L which is handled on a lower level of the operating system 
and cannot be intercepted.

The feature is enabled by executing (w32-supersuper-run t). nil as the 
argument disables the functionality.

Being new to Emacs-devel, I am not sure this is the way to go with patch 
submissions, but I have attached the git format-patch output below. Note 
that near the end of the file the "^L" should be replaced with a real ^L 
before applying the patch.

Please let me know if something is amiss.


---
  nt/Makefile.in  |   5 +-
  nt/supersuper.c | 236 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  src/w32fns.c    |  49 ++++++++++++
  3 files changed, 289 insertions(+), 1 deletion(-)
  create mode 100644 nt/supersuper.c

diff --git a/nt/Makefile.in b/nt/Makefile.in
index fc6887f..658edb7 100644
--- a/nt/Makefile.in
+++ b/nt/Makefile.in
@@ -135,7 +135,7 @@ MKDIR_P = @MKDIR_P@
  # ========================== Lists of Files ===========================

  # Things that a user might actually run, which should be installed in 
bindir.
-INSTALLABLES = runemacs${EXEEXT} addpm${EXEEXT}
+INSTALLABLES = runemacs${EXEEXT} addpm${EXEEXT} supersuper${EXEEXT}

  # Things that Emacs runs internally, which should not be installed in 
bindir.
  UTILITIES = cmdproxy${EXEEXT} ddeclient${EXEEXT}
@@ -242,6 +242,9 @@ cmdproxy${EXEEXT}: ${srcdir}/cmdproxy.c
  runemacs${EXEEXT}: ${srcdir}/runemacs.c $(EMACSRES)
  	$(AM_V_CCLD)$(CC) ${ALL_CFLAGS} $^ -mwindows -o $@

+supersuper${EXEEXT}: ${srcdir}/supersuper.c ../src/epaths.h
+	$(AM_V_CCLD)$(CC) ${ALL_CFLAGS} $< -o $@
+
  ## Also used in ../src/Makefile.
  emacs.res ../src/emacs.res: emacs.rc ${srcdir}/icons/emacs.ico \
    ${srcdir}/icons/hand.cur ${srcdir}/$(EMACS_MANIFEST)
diff --git a/nt/supersuper.c b/nt/supersuper.c
new file mode 100644
index 0000000..2f3fd9b
--- /dev/null
+++ b/nt/supersuper.c
@@ -0,0 +1,236 @@
+/**
+ * @file   supersuper.c
+ * @author Jussi Lahdenniemi <jussi@aprikoodi.fi>
+ * @date   2011-09-30 23:54
+ *
+ * @brief  supersuper keyboard hook
+ *
+ * Hooks the keyboard, provides supersuper services to emacs.
+ */
+
+#define STRICT
+#ifdef _WIN32_WINNT
+# undef _WIN32_WINNT
+#endif
+#define _WIN32_WINNT 0x0501
+#include <windows.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifndef WM_WTSSESSION_CHANGE
+# define WM_WTSSESSION_CHANGE  0x02B1
+# define WTS_SESSION_LOCK      0x7
+#endif
+
+static HANDLE  h_quit;          /**< Event handle: quit the hook 
executable */
+static HANDLE  h_lwin;          /**< Event handle: left Windows key 
pressed */
+static HANDLE  h_rwin;          /**< Event handle: right Windows key 
pressed */
+
+static int  lwindown  =  0;     /**< Left Windows key currently pressed */
+static int  rwindown  =  0;     /**< Right Windows key currently pressed */
+static int  capsdown  =  0;     /**< Caps lock currently pressed */
+static int  winsdown  =  0;     /**< Number of handled keys currently 
pressed */
+static int  suppress  =  0;     /**< Suppress Windows keyup for this 
press? */
+static int  winseen   =  0;     /**< Windows keys seen during this 
press? */
+
+/**
+ * Determines whether an Emacs is currently on the foreground.
+ *
+ * @return nonzero if Emacs, zero if not.
+ */
+static int emacsp()
+{
+  HWND fg = GetForegroundWindow();
+  if( fg != 0 )
+    {
+      TCHAR cls[16];
+      GetClassName( fg, cls, 16 );
+      return memcmp( cls, TEXT("Emacs"), sizeof(TEXT("Emacs"))) == 0;
+    }
+  return 0;
+}
+
+/**
+ * The keyboard hook function.
+ *
+ * @param code Negative -> call next hook
+ * @param w    Keyboard message ID
+ * @param l    KBDLLHOOKSTRUCT'
+ *
+ * @return nonzero to terminate processing
+ */
+static LRESULT CALLBACK funhook( int code, WPARAM w, LPARAM l )
+{
+  KBDLLHOOKSTRUCT const* hs = (KBDLLHOOKSTRUCT*)l;
+  if( code < 0 || (hs->flags & LLKHF_INJECTED))
+    {
+      return CallNextHookEx( 0, code, w, l );
+    }
+
+  if( hs->vkCode == VK_LWIN ||
+      hs->vkCode == VK_RWIN ||
+      hs->vkCode == VK_CAPITAL )
+    {
+      if( emacsp() && w == WM_KEYDOWN )
+        {
+          /* pressing key in emacs */
+          if( hs->vkCode == VK_LWIN && !lwindown )
+            {
+              SetEvent( h_lwin );
+              lwindown = 1;
+              winseen = 1;
+              winsdown++;
+            }
+          else if( hs->vkCode == VK_RWIN && !rwindown )
+            {
+              SetEvent( h_rwin );
+              rwindown = 1;
+              winseen = 1;
+              winsdown++;
+            }
+          else if( hs->vkCode == VK_CAPITAL && !capsdown )
+            {
+              SetEvent( h_lwin );
+              capsdown = 1;
+              winsdown++;
+            }
+          return 1;
+        }
+      else if( winsdown > 0 && w == WM_KEYUP )
+        {
+          /* releasing captured key */
+          if( hs->vkCode == VK_LWIN && lwindown )
+            {
+              lwindown = 0;
+              winsdown--;
+              if( !capsdown ) ResetEvent( h_lwin );
+            }
+          else if( hs->vkCode == VK_RWIN && rwindown )
+            {
+              rwindown = 0;
+              winsdown--;
+              ResetEvent( h_rwin );
+            }
+          else if( hs->vkCode == VK_CAPITAL && capsdown )
+            {
+              capsdown = 0;
+              winsdown--;
+              if( !lwindown ) ResetEvent( h_lwin );
+            }
+          if( winsdown == 0 && !suppress && winseen )
+            {
+              /* Releasing Win without other keys inbetween */
+              INPUT inputs[2];
+              memset( inputs, 0, sizeof(inputs));
+              inputs[0].type = INPUT_KEYBOARD;
+              inputs[0].ki.wVk = hs->vkCode;
+              inputs[0].ki.wScan = hs->vkCode;
+              inputs[0].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
+              inputs[0].ki.time = 0;
+              inputs[1].type = INPUT_KEYBOARD;
+              inputs[1].ki.wVk = hs->vkCode;
+              inputs[1].ki.wScan = hs->vkCode;
+              inputs[1].ki.dwFlags = KEYEVENTF_EXTENDEDKEY | 
KEYEVENTF_KEYUP;
+              inputs[1].ki.time = 0;
+              SendInput( 2, inputs, sizeof(INPUT));
+            }
+          if( winsdown == 0 )
+            {
+              suppress = 0;
+              winseen = 0;
+            }
+          return 1;
+        }
+    }
+  else if( winsdown > 0 )
+    {
+      /* S-? combination detected, do not pass keypress to Windows */
+      suppress = 1;
+    }
+  return CallNextHookEx( 0, code, w, l );
+}
+
+/**
+ * Window procedure for the event listener window.
+ *
+ * @param wnd     Window handle
+ * @param msg     Message
+ * @param wparam  Parameter
+ * @param lparam  Parameter
+ *
+ * @return Message result
+ */
+static LRESULT WINAPI wndproc( HWND wnd, UINT msg, WPARAM wparam, 
LPARAM lparam )
+{
+  if( msg == WM_WTSSESSION_CHANGE && wparam == WTS_SESSION_LOCK )
+    {
+      /* Clear keypress status on lock event - otherwise, when
+         the user presses Win+L to lock the workstation with
+         emacs as the foreground application, the Windows key
+         gets "stuck down" and after unlock all keys result in
+         S-* key combinations until Win is pressed and released. */
+      lwindown = 0;
+      rwindown = 0;
+      capsdown = 0;
+      winsdown = 0;
+      suppress = 0;
+      winseen = 0;
+    }
+  return DefWindowProc( wnd, msg, wparam, lparam );
+}
+
+/**
+ * Main function for the application.
+ *
+ * @param inst        Instance handle
+ * @param HINSTANCE   Not used
+ * @param LPSTR       Not used
+ * @param int         Not used
+ *
+ * @return Process exit code
+ */
+int CALLBACK WinMain( HINSTANCE inst, HINSTANCE prev, LPSTR args, int 
cmdshow )
+{
+  MSG msg;
+  HHOOK hook;
+  WNDCLASSEX wcex;
+  HWND wnd;
+
+  (void)prev; (void)args; (void)cmdshow;
+
+  h_quit = CreateEvent( 0, TRUE, FALSE, "supersuper.quit" );
+  if( GetLastError() == ERROR_ALREADY_EXISTS )
+    {
+      /* do not run twice */
+      CloseHandle( h_quit );
+      return 0;
+    }
+  h_lwin = CreateEvent( 0, TRUE, FALSE, "supersuper.left" );
+  h_rwin = CreateEvent( 0, TRUE, FALSE, "supersuper.right" );
+  hook = SetWindowsHookEx( WH_KEYBOARD_LL, funhook, inst, 0 );
+
+  /* Create a dummy window so that we receive WM_WTSESSION_CHANGE 
messages */
+  memset( &wcex, 0, sizeof(WNDCLASSEX));
+  wcex.cbSize = sizeof(wcex);
+  wcex.lpfnWndProc = wndproc;
+  wcex.hInstance = inst;
+  wcex.lpszClassName = "sswc";
+  RegisterClassEx( &wcex );
+  wnd = CreateWindow( "sswc", "", WS_POPUP, 0, 0, 0, 0, 0, 0, inst, 0 );
+
+  while( MsgWaitForMultipleObjects( 1, &h_quit, FALSE, INFINITE, 
QS_ALLINPUT ) != WAIT_OBJECT_0 )
+    {
+      while( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
+        {
+          TranslateMessage( &msg );
+          DispatchMessage( &msg );
+        }
+    }
+
+  UnhookWindowsHookEx( hook );
+  CloseHandle( h_lwin );
+  CloseHandle( h_rwin );
+  CloseHandle( h_quit );
+  DestroyWindow( wnd );
+  return 0;
+}
diff --git a/src/w32fns.c b/src/w32fns.c
index c1d9bff..8140f35 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -2218,6 +2218,20 @@ sync_modifiers (void)
  }

  static int
+supersuper_winkeystate (int vkey)
+{
+  static HANDLE evh_left = NULL;
+  static HANDLE evh_right = NULL;
+  HANDLE* h = (vkey == VK_RWIN) ? &evh_right : &evh_left;
+  if (*h == NULL)
+    *h = OpenEvent (SYNCHRONIZE, TRUE,
+                    (vkey == VK_RWIN) ? "supersuper.right" : 
"supersuper.left");
+  if (*h == NULL)
+    return (GetKeyState (vkey) & 0x8000);
+  return WaitForSingleObject (*h, 0) == WAIT_OBJECT_0;
+}
+
+static int
  modifier_set (int vkey)
  {
    /* Warning: The fact that VK_NUMLOCK is not treated as the other 2
@@ -2248,6 +2262,8 @@ modifier_set (int vkey)
        else
  	return (GetKeyState (vkey) & 0x1);
      }
+  if (vkey == VK_LWIN || vkey == VK_RWIN)
+    return supersuper_winkeystate(vkey);

    if (!modifiers_recorded)
      return (GetKeyState (vkey) & 0x8000);
@@ -8223,6 +8239,38 @@ The following %-sequences are provided:
    return status;
  }

+DEFUN ("w32-supersuper-run", Fw32_supersuper_run, Sw32_supersuper_run, 
1, 1, 0,
+       doc: /* Control running of the supersuper keyboard hook application.
+Specify nil as RUN to terminate supersuper, non-nil to start it.
+Returns t if the operation succeeds, nil if it fails. */)
+  (run)
+  Lisp_Object run;
+{
+  if (NILP (run))
+    {
+      /* Terminate supersuper by setting the quit event */
+      HANDLE quit = OpenEvent (EVENT_MODIFY_STATE, TRUE, 
"supersuper.quit");
+      if (quit == NULL)
+        return Qnil;
+      SetEvent (quit);
+      CloseHandle (quit);
+      return Qt;
+    }
+  else
+    {
+      /* Start up the supersuper app */
+      STARTUPINFO sui;
+      PROCESS_INFORMATION pi;
+      sui.cb = sizeof(STARTUPINFO);
+      GetStartupInfo (&sui);
+      if (!CreateProcess (NULL, "supersuper.exe", NULL, NULL, TRUE,0, 
NULL, NULL, &sui, &pi))
+        return Qnil;
+      CloseHandle (pi.hProcess);
+      CloseHandle (pi.hThread);
+      return Qt;
+    }
+}
+
^L
  #ifdef WINDOWSNT
  typedef BOOL (WINAPI *GetDiskFreeSpaceExW_Proc)
@@ -9628,6 +9676,7 @@ This variable has effect only on Windows Vista and 
later.  */);
    defsubr (&Sw32_window_exists_p);
    defsubr (&Sw32_battery_status);
    defsubr (&Sw32__menu_bar_in_use);
+  defsubr (&Sw32_supersuper_run);
  #if defined WINDOWSNT && !defined HAVE_DBUS
    defsubr (&Sw32_notification_notify);
    defsubr (&Sw32_notification_close);
-- 
2.6.2






^ permalink raw reply related	[flat|nested] 63+ messages in thread

* RE: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-05 12:51 [PATCH] Override Windows default Win-* key combinations when using Emacs Jussi Lahdenniemi
@ 2016-01-05 13:54 ` Herring, Davis
  2016-01-05 17:05   ` Eli Zaretskii
  2016-01-05 17:05 ` Eli Zaretskii
  1 sibling, 1 reply; 63+ messages in thread
From: Herring, Davis @ 2016-01-05 13:54 UTC (permalink / raw)
  To: Jussi Lahdenniemi, emacs-devel@gnu.org

> # Things that a user might actually run, which should be installed in
bindir.
> -INSTALLABLES = runemacs${EXEEXT} addpm${EXEEXT}
> +INSTALLABLES = runemacs${EXEEXT} addpm${EXEEXT} supersuper${EXEEXT}
> 
> # Things that Emacs runs internally, which should not be installed in
bindir.
> UTILITIES = cmdproxy${EXEEXT} ddeclient${EXEEXT}

One minor point: this certainly seems more like UTILITIES than like INSTALLABLES.

Davis


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-05 12:51 [PATCH] Override Windows default Win-* key combinations when using Emacs Jussi Lahdenniemi
  2016-01-05 13:54 ` Herring, Davis
@ 2016-01-05 17:05 ` Eli Zaretskii
  2016-01-05 19:03   ` Rasmus
                     ` (2 more replies)
  1 sibling, 3 replies; 63+ messages in thread
From: Eli Zaretskii @ 2016-01-05 17:05 UTC (permalink / raw)
  To: Jussi Lahdenniemi; +Cc: emacs-devel

> From: Jussi Lahdenniemi <jussi@aprikoodi.fi>
> Date: Tue, 5 Jan 2016 14:51:36 +0200
> 
> I finally got around to submitting a patch I wrote some four years ago 
> that enables Emacs users on Windows to override the default Windows key 
> combinations reserved by the operating system. Especially the newer 
> Windowses (7, 8, 10) define quite a large number of Win+* hotkeys to a 
> variety of shell functions, restricting the available S-* keys on Emacs.
> 
> This is accomplished by running an external process (supersuper.exe) 
> that captures keypresses, suppressing unwanted ones from the system, and 
> informing the currently active Emacs process about them as necessary. 
> All Win key combinations are thus blocked and made available for Emacs, 
> except Win+L which is handled on a lower level of the operating system 
> and cannot be intercepted.
> 
> The feature is enabled by executing (w32-supersuper-run t). nil as the 
> argument disables the functionality.

Thank you for your contribution.  It is large enough to require legal
paperwork; I can send you the forms off-list if you agree.

As for the patch: why does this have to be an external program?  Can't
Emacs itself do this job?  Doing part of Emacs's keyboard input in a
separate process has several downsides, so I think it should be
avoided if possible.

Also, did you try this with the latest Emacs sources?  The way
keyboard input works in Emacs on Windows has changed several months
ago.

Finally, will this also work in the console (a.k.a. "TTY") session, or
just in GUI sessions?



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-05 13:54 ` Herring, Davis
@ 2016-01-05 17:05   ` Eli Zaretskii
  2016-01-05 19:32     ` Jussi Lahdenniemi
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2016-01-05 17:05 UTC (permalink / raw)
  To: Herring, Davis; +Cc: jussi, emacs-devel

> From: "Herring, Davis" <herring@lanl.gov>
> Date: Tue, 5 Jan 2016 13:54:20 +0000
> Accept-Language: en-US
> 
> > # Things that a user might actually run, which should be installed in
> bindir.
> > -INSTALLABLES = runemacs${EXEEXT} addpm${EXEEXT}
> > +INSTALLABLES = runemacs${EXEEXT} addpm${EXEEXT} supersuper${EXEEXT}
> > 
> > # Things that Emacs runs internally, which should not be installed in
> bindir.
> > UTILITIES = cmdproxy${EXEEXT} ddeclient${EXEEXT}
> 
> One minor point: this certainly seems more like UTILITIES than like INSTALLABLES.

I agree.  But then the program's invocation code should be updated, I
think, because it won't be on PATH.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-05 17:05 ` Eli Zaretskii
@ 2016-01-05 19:03   ` Rasmus
  2016-01-05 19:17     ` Eli Zaretskii
       [not found]     ` <<83d1tf4z0h.fsf@gnu.org>
  2016-01-05 19:41   ` Jussi Lahdenniemi
  2016-01-09 19:58   ` Jussi Lahdenniemi
  2 siblings, 2 replies; 63+ messages in thread
From: Rasmus @ 2016-01-05 19:03 UTC (permalink / raw)
  To: emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

> Also, did you try this with the latest Emacs sources?  The way
> keyboard input works in Emacs on Windows has changed several months
> ago.

Interesting.  One thing that I hate when using Emacs on Windows in that
M-Tab open some auxiliary Windows dialog with running programs rather than
e.g. completion-at-point.  It would be *very* welcomed if one could let
Emacs take over these key inputs.

On windows I just use the latest release so I haven not tried the new
code.

Thanks,
Rasmus

-- 
What will be next?




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-05 19:03   ` Rasmus
@ 2016-01-05 19:17     ` Eli Zaretskii
  2016-01-05 19:31       ` Jussi Lahdenniemi
       [not found]     ` <<83d1tf4z0h.fsf@gnu.org>
  1 sibling, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2016-01-05 19:17 UTC (permalink / raw)
  To: Rasmus; +Cc: emacs-devel

> From: Rasmus <rasmus@gmx.us>
> Date: Tue, 05 Jan 2016 20:03:12 +0100
> 
> Interesting.  One thing that I hate when using Emacs on Windows in that
> M-Tab open some auxiliary Windows dialog with running programs rather than
> e.g. completion-at-point.  It would be *very* welcomed if one could let
> Emacs take over these key inputs.

This is already possible, via w32-register-hot-key, see the node
"Windows Keyboard" in the Emacs manual.  (However, I think someone
reported that w32-register-hot-key doesn't work on latest Windows
versions, due to some change in how Windows handles that.)



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-05 19:17     ` Eli Zaretskii
@ 2016-01-05 19:31       ` Jussi Lahdenniemi
  0 siblings, 0 replies; 63+ messages in thread
From: Jussi Lahdenniemi @ 2016-01-05 19:31 UTC (permalink / raw)
  To: Eli Zaretskii, Rasmus; +Cc: emacs-devel

>> Interesting.  One thing that I hate when using Emacs on Windows in that
>> M-Tab open some auxiliary Windows dialog with running programs rather than
>> e.g. completion-at-point.  It would be *very* welcomed if one could let
>> Emacs take over these key inputs.
>
> This is already possible, via w32-register-hot-key, see the node
> "Windows Keyboard" in the Emacs manual.  (However, I think someone
> reported that w32-register-hot-key doesn't work on latest Windows
> versions, due to some change in how Windows handles that.)

I can confirm that this does not work on Windows 10. I could try 
incorporating this into w32-supersuper, while I am on it.

-- 
Jussi Lahdenniemi





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-05 17:05   ` Eli Zaretskii
@ 2016-01-05 19:32     ` Jussi Lahdenniemi
  0 siblings, 0 replies; 63+ messages in thread
From: Jussi Lahdenniemi @ 2016-01-05 19:32 UTC (permalink / raw)
  To: Eli Zaretskii, Herring, Davis; +Cc: emacs-devel

>>> # Things that a user might actually run, which should be installed in
>> bindir.
>>> -INSTALLABLES = runemacs${EXEEXT} addpm${EXEEXT}
>>> +INSTALLABLES = runemacs${EXEEXT} addpm${EXEEXT} supersuper${EXEEXT}
>>>
>>> # Things that Emacs runs internally, which should not be installed in
>> bindir.
>>> UTILITIES = cmdproxy${EXEEXT} ddeclient${EXEEXT}
>>
>> One minor point: this certainly seems more like UTILITIES than like INSTALLABLES.
>
> I agree.  But then the program's invocation code should be updated, I
> think, because it won't be on PATH.

Indeed. I'll fix this.

-- 
Jussi Lahdenniemi





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-05 17:05 ` Eli Zaretskii
  2016-01-05 19:03   ` Rasmus
@ 2016-01-05 19:41   ` Jussi Lahdenniemi
  2016-01-05 20:01     ` Eli Zaretskii
  2016-01-09 19:58   ` Jussi Lahdenniemi
  2 siblings, 1 reply; 63+ messages in thread
From: Jussi Lahdenniemi @ 2016-01-05 19:41 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

> Thank you for your contribution.  It is large enough to require legal
> paperwork; I can send you the forms off-list if you agree.

Sure!

> As for the patch: why does this have to be an external program?  Can't
> Emacs itself do this job?  Doing part of Emacs's keyboard input in a
> separate process has several downsides, so I think it should be
> avoided if possible.

While submitting the change, I thought about this as well. I wrote the 
code four years ago, and could not remember why I chose this approach; 
possibly both for better performance when several emacses are running 
and for smaller changes in the core emacs code (as that was the first 
time I touched the emacs code base).

I'll see how much it would take to incorporate the code in the emacs 
process.

> Also, did you try this with the latest Emacs sources?  The way
> keyboard input works in Emacs on Windows has changed several months
> ago.

Yes, this patch was done on the latest emacs master branch on git. Also, 
I verified that the w32-register-hot-key does not do the job for the 
Windows key combinations.

> Finally, will this also work in the console (a.k.a. "TTY") session, or
> just in GUI sessions?

No, it currently only works for GUI. Supporting the console would 
require some additional code (to check if the currently active window is 
a console running Emacs, basically) but it could be done. I'll check 
this as well.

-- 
Jussi Lahdenniemi





^ permalink raw reply	[flat|nested] 63+ messages in thread

* RE: [PATCH] Override Windows default Win-* key combinations when using Emacs
       [not found]     ` <<83d1tf4z0h.fsf@gnu.org>
@ 2016-01-05 19:45       ` Drew Adams
  0 siblings, 0 replies; 63+ messages in thread
From: Drew Adams @ 2016-01-05 19:45 UTC (permalink / raw)
  To: Eli Zaretskii, Rasmus; +Cc: emacs-devel

> > Interesting.  One thing that I hate when using Emacs on Windows in that
> > M-Tab open some auxiliary Windows dialog with running programs rather than
> > e.g. completion-at-point.  It would be *very* welcomed if one could let
> > Emacs take over these key inputs.
> 
> This is already possible, via w32-register-hot-key, see the node
> "Windows Keyboard" in the Emacs manual.  (However, I think someone
> reported that w32-register-hot-key doesn't work on latest Windows
> versions, due to some change in how Windows handles that.)

Correct. It does not work with Windows 10, at least.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-05 19:41   ` Jussi Lahdenniemi
@ 2016-01-05 20:01     ` Eli Zaretskii
  0 siblings, 0 replies; 63+ messages in thread
From: Eli Zaretskii @ 2016-01-05 20:01 UTC (permalink / raw)
  To: Jussi Lahdenniemi; +Cc: emacs-devel

> From: Jussi Lahdenniemi <jussi@aprikoodi.fi>
> Date: Tue, 5 Jan 2016 21:41:02 +0200
> Cc: emacs-devel@gnu.org
> 
> > Thank you for your contribution.  It is large enough to require legal
> > paperwork; I can send you the forms off-list if you agree.
> 
> Sure!

Sent off-list.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-05 17:05 ` Eli Zaretskii
  2016-01-05 19:03   ` Rasmus
  2016-01-05 19:41   ` Jussi Lahdenniemi
@ 2016-01-09 19:58   ` Jussi Lahdenniemi
  2016-01-11 18:54     ` Eli Zaretskii
  2 siblings, 1 reply; 63+ messages in thread
From: Jussi Lahdenniemi @ 2016-01-09 19:58 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

On 5.1.2016 19.05, Eli Zaretskii wrote:
> Thank you for your contribution.  It is large enough to require legal
> paperwork; I can send you the forms off-list if you agree.

I finished integrating the code more tightly into Emacs sources, 
removing the need for the additional process and adding functionality 
for grabbing Alt-based keyboard input (M-tab, M-ESC) in addition to the 
Windows keys. I also updated the documentation.

The patch is attached. I decided to place the new functionality in a new 
file (w32hook.c) - it could have been added to some existing file as well.

The assignment paperwork is in the mail.


----------------------- 8< 8< -----------------------
The Windows keyboard hooking code properly grabs system hotkeys such as 
Win-*
and Alt-Tab for Emacs use.  The new code replaces the w32-register-hot-key
functionality.  The hooking code also works for both windowed and console
(emacs -nw) mode.

* configure.ac: Added the new file src/w32hook.c
* src/w32term.h: Added new function prototypes
* src/w32fns.c: Updated the w32-register-hot-key related code to use
   the new hooking code instead
* src/w32console.c: Updated to support hooking for console Emacs
* src/w32inevt.c: Ditto
* src/w32hook.c: New file containing the hooking code
* doc/emacs/msdos.texi: Updated documentation for the new functionality

Fixes
---
  configure.ac         |   1 +
  doc/emacs/msdos.texi | 100 +++++++++------
  src/w32console.c     |   3 +
  src/w32fns.c         | 288 ++++++++++--------------------------------
  src/w32hook.c        | 343 
+++++++++++++++++++++++++++++++++++++++++++++++++++
  src/w32inevt.c       |  12 +-
  src/w32term.h        |  10 ++
  7 files changed, 485 insertions(+), 272 deletions(-)
  create mode 100644 src/w32hook.c

diff --git a/configure.ac b/configure.ac
index 0aa863a..4ae0f26 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1959,6 +1959,7 @@ if test "${HAVE_W32}" = "yes"; then
                  [AC_MSG_ERROR([No resource compiler found.])])
    W32_OBJ="w32fns.o w32menu.o w32reg.o w32font.o w32term.o"
    W32_OBJ="$W32_OBJ w32xfns.o w32select.o w32uniscribe.o"
+  W32_OBJ="$W32_OBJ w32hook.o"
    EMACSRES="emacs.res"
    case "$canonical" in
      x86_64-*-*) EMACS_MANIFEST="emacs-x64.manifest" ;;
diff --git a/doc/emacs/msdos.texi b/doc/emacs/msdos.texi
index f1cdb26..34ad639 100644
--- a/doc/emacs/msdos.texi
+++ b/doc/emacs/msdos.texi
@@ -504,39 +504,6 @@ Windows Keyboard
  key.  If you wish it to produce the @code{Alt} modifier instead, set
  the variable @code{w32-alt-is-meta} to a @code{nil} value.

-@findex w32-register-hot-key
-@findex w32-unregister-hot-key
-  MS-Windows reserves certain key combinations, such as
-@kbd{@key{Alt}-@key{TAB}}, for its own use.  These key combinations are
-intercepted by the system before Emacs can see them.  You can use the
-@code{w32-register-hot-key} function to allow a key sequence to be
-seen by Emacs instead of being grabbed by Windows.  This function
-registers a key sequence as a @dfn{hot key}, overriding the special
-meaning of that key sequence for Windows.  (MS-Windows is told that
-the key sequence is a hot key only when one of the Emacs windows has
-focus, so that the special keys still have their usual meaning for
-other Windows applications.)
-
-  The argument to @code{w32-register-hot-key} must be a single key,
-with or without modifiers, in vector form that would be acceptable to
-@code{define-key}.  The meta modifier is interpreted as the @key{Alt}
-key if @code{w32-alt-is-meta} is @code{t} (the default), and the hyper
-modifier is always interpreted as the Windows key (usually labeled
-with @key{start} and the Windows logo).  If the function succeeds in
-registering the key sequence, it returns the hotkey ID, a number;
-otherwise it returns @code{nil}.
-
-@kindex M-TAB@r{, (MS-Windows)}
-@cindex @kbd{M-@key{TAB}} vs @kbd{@key{Alt}-@key{TAB}} (MS-Windows)
-@cindex @kbd{@key{Alt}-@key{TAB}} vs @kbd{M-@key{TAB}} (MS-Windows)
-  For example, @code{(w32-register-hot-key [M-tab])} lets you use
-@kbd{M-@key{TAB}} normally in Emacs; for instance, to complete the word or
-symbol at point at top level, or to complete the current search string
-against previously sought strings during incremental search.
-
-  The function @code{w32-unregister-hot-key} reverses the effect of
-@code{w32-register-hot-key} for its argument key sequence.
-
  @vindex w32-capslock-is-shiftlock
    By default, the @key{CapsLock} key only affects normal character
  keys (it converts lower-case characters to their upper-case
@@ -582,6 +549,66 @@ Windows Keyboard
  right Windows key produces the symbol @code{rwindow} and @key{ScrLock}
  produces the symbol @code{scroll}.

+@findex w32-register-hot-key
+@findex w32-unregister-hot-key
+  MS-Windows reserves certain key combinations, such as
+@kbd{@key{Alt}-@key{TAB}} and a number of Windows key combinations,
+for its own use.  These key combinations are intercepted by the system
+before Emacs can see them.  Also, on Windows 10, all Windows key
+combinations are reserved by the system in such a way that they are
+never propagated to applications, even if the system does not
+currently define a hotkey on the specific combination.  You can use
+the @code{w32-register-hot-key} function to allow a key sequence to be
+seen by Emacs instead of being grabbed by Windows.  When registered as
+a hot key, the key combination is pulled out of the system's input
+queue before it is handled by Windows, effectively overriding the
+special meaning of that key sequence for Windows.  The override is
+only effective when Emacs is active; with other applications on the
+foreground the keys behave normally.
+
+   The argument to @code{w32-register-hot-key} must be a single key with a
+single modifier, in vector form that would be acceptable to
+@code{define-key}.  The control and shift modifiers have no effect on the
+argument.  The meta modifier is interpreted as the @key{Alt} key if
+@code{w32-alt-is-meta} is @code{t} (the default), and the super and hyper
+modifiers are interpreted according to the bindings of
+@code{w32-lwindow-modifier} and @code{w32-rwindow-modifier}. 
Additionally, a
+modifier with the trailing dash but with no key indicates that all
+Windows defined hotkeys for that modifier are to be overridden in the
+favor of Emacs.
+
+@kindex M-TAB@r{, (MS-Windows)}
+@cindex @kbd{M-@key{TAB}} vs @kbd{@key{Alt}-@key{TAB}} (MS-Windows)
+@cindex @kbd{@key{Alt}-@key{TAB}} vs @kbd{M-@key{TAB}} (MS-Windows)
+   For example, @code{(w32-register-hot-key [M-tab])} lets you use
+@kbd{M-@key{TAB}} normally in Emacs; for instance, to complete the
+word or symbol at point at top level, or to complete the current
+search string against previously sought strings during incremental
+search.  @code{(w32-register-hot-key [s-])} with
+@code{w32-lwindow-modifier} bound to @code{super} disables all the
+Windows' own Windows key based shortcuts.@footnote{There is one known
+exception: The combination @kbd{@key{Windows}-@key{L}} that locks the
+workstation is handled by the system on a lower level.  For this
+reason, @code{w32-register-hot-key} cannot override this key
+combination - it always locks the computer.}
+
+   Note that @code{w32-register-hot-key} checks the
+@code{w32-[lr]window-modifier} values at the time of the function
+call.  Thus, you can set @code{w32-lwindow-modifier} as @code{super},
+then call @code{(w32-register-hot-key [s-r])}, and finally set
+@code{w32-rwindow-modifier} as @code{super} as well.  The result is
+that the left Windows key together with @key{R} invokes whichever
+function you have bound for the combination in Emacs, and the right
+Windows key and @key{R} opens the Windows @code{Run} dialog.
+
+   The hotkey registrations always also include all the shift and
+control modifier combinations for the given hotkey; that is,
+registering @kbd{s-@key{a}} as a hotkey gives you @kbd{s-@key{A}},
+@kbd{C-s-@key{a}} and @kbd{C-s-@key{A}} as well.
+
+  The function @code{w32-unregister-hot-key} reverses the effect of
+@code{w32-register-hot-key} for its argument key sequence.
+
  @vindex w32-pass-alt-to-system
  @cindex Windows system menu
  @cindex @code{Alt} key invokes menu (Windows)
@@ -607,12 +634,7 @@ Windows Keyboard
  otherwise it is passed to Windows.  The default is @code{t} for both
  of these variables.  Passing each of these keys to Windows produces
  its normal effect: for example, @kbd{@key{Lwindow}} opens the
-@code{Start} menu, etc.@footnote{
-Some combinations of the ``Windows'' keys with other keys are caught
-by Windows at a low level in a way that Emacs currently cannot prevent.
-For example, @kbd{@key{Lwindow} r} always pops up the Windows
-@samp{Run} dialog.  Customizing the value of
-@code{w32-phantom-key-code} might help in some cases, though.}
+@code{Start} menu, etc.

  @vindex w32-recognize-altgr
  @kindex AltGr @r{(MS-Windows)}
diff --git a/src/w32console.c b/src/w32console.c
index 7fffabf..57f74d1 100644
--- a/src/w32console.c
+++ b/src/w32console.c
@@ -759,6 +759,9 @@ initialize_w32_display (struct terminal *term, int 
*width, int *height)

    /* Setup w32_display_info structure for this frame. */
    w32_initialize_display_info (build_string ("Console"));
+
+  /* Set up the keyboard hook */
+  setup_w32_kbdhook ();
  }


diff --git a/src/w32fns.c b/src/w32fns.c
index c1d9bff..99c9ed1 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -2248,6 +2248,8 @@ modifier_set (int vkey)
        else
  	return (GetKeyState (vkey) & 0x1);
      }
+  if (vkey == VK_LWIN || vkey == VK_RWIN)
+    return check_w32_winkey_state (vkey);

    if (!modifiers_recorded)
      return (GetKeyState (vkey) & 0x8000);
@@ -2387,60 +2389,6 @@ map_keypad_keys (unsigned int virt_key, unsigned 
int extended)
    return virt_key;
  }

-/* List of special key combinations which w32 would normally capture,
-   but Emacs should grab instead.  Not directly visible to lisp, to
-   simplify synchronization.  Each item is an integer encoding a virtual
-   key code and modifier combination to capture.  */
-static Lisp_Object w32_grabbed_keys;
-
-#define HOTKEY(vk, mods)      make_number (((vk) & 255) | ((mods) << 8))
-#define HOTKEY_ID(k)          (XFASTINT (k) & 0xbfff)
-#define HOTKEY_VK_CODE(k)     (XFASTINT (k) & 255)
-#define HOTKEY_MODIFIERS(k)   (XFASTINT (k) >> 8)
-
-#define RAW_HOTKEY_ID(k)        ((k) & 0xbfff)
-#define RAW_HOTKEY_VK_CODE(k)   ((k) & 255)
-#define RAW_HOTKEY_MODIFIERS(k) ((k) >> 8)
-
-/* Register hot-keys for reserved key combinations when Emacs has
-   keyboard focus, since this is the only way Emacs can receive key
-   combinations like Alt-Tab which are used by the system.  */
-
-static void
-register_hot_keys (HWND hwnd)
-{
-  Lisp_Object keylist;
-
-  /* Use CONSP, since we are called asynchronously.  */
-  for (keylist = w32_grabbed_keys; CONSP (keylist); keylist = XCDR 
(keylist))
-    {
-      Lisp_Object key = XCAR (keylist);
-
-      /* Deleted entries get set to nil.  */
-      if (!INTEGERP (key))
-	continue;
-
-      RegisterHotKey (hwnd, HOTKEY_ID (key),
-		      HOTKEY_MODIFIERS (key), HOTKEY_VK_CODE (key));
-    }
-}
-
-static void
-unregister_hot_keys (HWND hwnd)
-{
-  Lisp_Object keylist;
-
-  for (keylist = w32_grabbed_keys; CONSP (keylist); keylist = XCDR 
(keylist))
-    {
-      Lisp_Object key = XCAR (keylist);
-
-      if (!INTEGERP (key))
-	continue;
-
-      UnregisterHotKey (hwnd, HOTKEY_ID (key));
-    }
-}
-
  #if EMACSDEBUG
  const char*
  w32_name_of_message (UINT msg)
@@ -2570,27 +2518,6 @@ w32_msg_pump (deferred_msg * msg_buf)
  				      result, 0))
  		emacs_abort ();
  	      break;
-	    case WM_EMACS_REGISTER_HOT_KEY:
-	      focus_window = GetFocus ();
-	      if (focus_window != NULL)
-		RegisterHotKey (focus_window,
-				RAW_HOTKEY_ID (msg.wParam),
-				RAW_HOTKEY_MODIFIERS (msg.wParam),
-				RAW_HOTKEY_VK_CODE (msg.wParam));
-	      /* Reply is not expected.  */
-	      break;
-	    case WM_EMACS_UNREGISTER_HOT_KEY:
-	      focus_window = GetFocus ();
-	      if (focus_window != NULL)
-		UnregisterHotKey (focus_window, RAW_HOTKEY_ID (msg.wParam));
-	      /* Mark item as erased.  NB: this code must be
-		 thread-safe.  The next line is okay because the cons
-		 cell is never made into garbage and is not relocated by
-		 GC.  */
-	      XSETCAR (make_lisp_ptr ((void *)msg.lParam, Lisp_Cons), Qnil);
-	      if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
-		emacs_abort ();
-	      break;
  	    case WM_EMACS_TOGGLE_LOCK_KEY:
  	      {
  		int vk_code = (int) msg.wParam;
@@ -3401,11 +3328,6 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, 
LPARAM lParam)
        }
        goto dflt;

-    case WM_HOTKEY:
-      /* Synchronize hot keys with normal input.  */
-      PostMessage (hwnd, WM_KEYDOWN, HIWORD (lParam), 0);
-      return (0);
-
      case WM_KEYUP:
      case WM_SYSKEYUP:
        record_keyup (wParam, lParam);
@@ -3439,41 +3361,16 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM 
wParam, LPARAM lParam)

        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;
-	  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;
-	  break;
+          /* The Win keys are handled in w32hook.c and must be silently
+             ignored here when used as a modifier */
+        case VK_LWIN:
+          if (!NILP (Vw32_lwindow_modifier))
+            return 0;
+          break;
+        case VK_RWIN:
+          if (!NILP (Vw32_rwindow_modifier))
+            return 0;
+          break;
  	case VK_APPS:
  	  if (!NILP (Vw32_apps_modifier))
  	    return 0;
@@ -4316,10 +4213,8 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, 
LPARAM lParam)
      case WM_SETFOCUS:
        dpyinfo->faked_key = 0;
        reset_modifiers ();
-      register_hot_keys (hwnd);
        goto command;
      case WM_KILLFOCUS:
-      unregister_hot_keys (hwnd);
        button_state = 0;
        ReleaseCapture ();
        /* Relinquish the system caret.  */
@@ -4348,10 +4243,20 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM 
wParam, LPARAM lParam)
        my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
        goto dflt;

+    case WM_CREATE:
+      setup_w32_kbdhook ();
+      goto dflt;
+
      case WM_DESTROY:
+      remove_w32_kbdhook ();
        CoUninitialize ();
        return 0;

+    case WM_WTSSESSION_CHANGE:
+      if (wParam == WTS_SESSION_LOCK)
+        reset_w32_kbdhook_state ();
+      goto dflt;
+
      case WM_CLOSE:
        wmsg.dwModifiers = w32_get_modifiers ();
        my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
@@ -7617,19 +7522,31 @@ lookup_vk_code (char *key)
  	&& strcmp (lispy_function_keys[i], key) == 0)
        return i;

+  /* alphanumerics map to themselves */
+  if (key[1] == 0)
+    {
+      if (key[0] >= 'A' && key[0] <= 'Z' ||
+          key[0] >= '0' && key[0] <= '9')
+        return key[0];
+      if (key[0] >= 'a' && key[0] <= 'z')
+        return toupper(key[0]);
+    }
+
    return -1;
  }

  /* Convert a one-element vector style key sequence to a hot key
     definition.  */
  static Lisp_Object
-w32_parse_hot_key (Lisp_Object key)
+w32_parse_and_register_hot_key (Lisp_Object key, int hook)
  {
    /* Copied from Fdefine_key and store_in_keymap.  */
    register Lisp_Object c;
    int vk_code;
    int lisp_modifiers;
    int w32_modifiers;
+  Lisp_Object res = Qnil;
+  char* vkname;

    CHECK_VECTOR (key);

@@ -7652,7 +7569,12 @@ w32_parse_hot_key (Lisp_Object key)
        c = Fcar (c);
        if (!SYMBOLP (c))
  	emacs_abort ();
-      vk_code = lookup_vk_code (SSDATA (SYMBOL_NAME (c)));
+      vkname = SSDATA (SYMBOL_NAME (c));
+      /* [s-], [M-], [h-]: Register all keys for this modifier */
+      if (vkname[0] == 0)
+        vk_code = VK_ANY;
+      else
+        vk_code = lookup_vk_code (vkname);
      }
    else if (INTEGERP (c))
      {
@@ -7668,21 +7590,27 @@ w32_parse_hot_key (Lisp_Object key)
        && !NILP (Vw32_alt_is_meta))
      lisp_modifiers |= alt_modifier;

-  /* Supply defs missing from mingw32.  */
-#ifndef MOD_ALT
-#define MOD_ALT         0x0001
-#define MOD_CONTROL     0x0002
-#define MOD_SHIFT       0x0004
-#define MOD_WIN         0x0008
-#endif
-
-  /* Convert lisp modifiers to Windows hot-key form.  */
-  w32_modifiers  = (lisp_modifiers & hyper_modifier)    ? MOD_WIN : 0;
-  w32_modifiers |= (lisp_modifiers & alt_modifier)      ? MOD_ALT : 0;
-  w32_modifiers |= (lisp_modifiers & ctrl_modifier)     ? MOD_CONTROL : 0;
-  w32_modifiers |= (lisp_modifiers & shift_modifier)    ? MOD_SHIFT : 0;
+  /* Register Alt-x combinations */
+  if (lisp_modifiers & alt_modifier)
+    {
+      hook_w32_key (hook, VK_MENU, vk_code);
+      res = Qt;
+    }
+  /* Register Win-x combinations based on modifier mappings */
+  if ((lisp_modifiers & hyper_modifier) && EQ (Vw32_lwindow_modifier, 
Qhyper) ||
+      (lisp_modifiers & super_modifier) && EQ (Vw32_lwindow_modifier, 
Qsuper))
+    {
+      hook_w32_key (hook, VK_LWIN, vk_code);
+      res = Qt;
+    }
+  if ((lisp_modifiers & hyper_modifier) && EQ (Vw32_rwindow_modifier, 
Qhyper) ||
+      (lisp_modifiers & super_modifier) && EQ (Vw32_rwindow_modifier, 
Qsuper))
+    {
+      hook_w32_key (hook, VK_RWIN, vk_code);
+      res = Qt;
+    }

-  return HOTKEY (vk_code, w32_modifiers);
+  return res;
  }

  DEFUN ("w32-register-hot-key", Fw32_register_hot_key,
@@ -7701,26 +7629,7 @@ is always interpreted as the Windows modifier keys.
  The return value is the hotkey-id if registered, otherwise nil.  */)
    (Lisp_Object key)
  {
-  key = w32_parse_hot_key (key);
-
-  if (!NILP (key) && NILP (Fmemq (key, w32_grabbed_keys)))
-    {
-      /* Reuse an empty slot if possible.  */
-      Lisp_Object item = Fmemq (Qnil, w32_grabbed_keys);
-
-      /* Safe to add new key to list, even if we have focus.  */
-      if (NILP (item))
-	w32_grabbed_keys = Fcons (key, w32_grabbed_keys);
-      else
-	XSETCAR (item, key);
-
-      /* Notify input thread about new hot-key definition, so that it
-	 takes effect without needing to switch focus.  */
-      PostThreadMessage (dwWindowsThreadId, WM_EMACS_REGISTER_HOT_KEY,
-			 (WPARAM) XINT (key), 0);
-    }
-
-  return key;
+  return w32_parse_and_register_hot_key (key, 1);
  }

  DEFUN ("w32-unregister-hot-key", Fw32_unregister_hot_key,
@@ -7728,73 +7637,7 @@ DEFUN ("w32-unregister-hot-key", 
Fw32_unregister_hot_key,
         doc: /* Unregister KEY as a hot-key combination.  */)
    (Lisp_Object key)
  {
-  Lisp_Object item;
-
-  if (!INTEGERP (key))
-    key = w32_parse_hot_key (key);
-
-  item = Fmemq (key, w32_grabbed_keys);
-
-  if (!NILP (item))
-    {
-      LPARAM lparam;
-
-      eassert (CONSP (item));
-      /* Pass the tail of the list as a pointer to a Lisp_Cons cell,
-	 so that it works in a --with-wide-int build as well.  */
-      lparam = (LPARAM) XUNTAG (item, Lisp_Cons);
-
-      /* Notify input thread about hot-key definition being removed, so
-	 that it takes effect without needing focus switch.  */
-      if (PostThreadMessage (dwWindowsThreadId, 
WM_EMACS_UNREGISTER_HOT_KEY,
-			     (WPARAM) XINT (XCAR (item)), lparam))
-	{
-	  MSG msg;
-	  GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
-	}
-      return Qt;
-    }
-  return Qnil;
-}
-
-DEFUN ("w32-registered-hot-keys", Fw32_registered_hot_keys,
-       Sw32_registered_hot_keys, 0, 0, 0,
-       doc: /* Return list of registered hot-key IDs.  */)
-  (void)
-{
-  return Fdelq (Qnil, Fcopy_sequence (w32_grabbed_keys));
-}
-
-DEFUN ("w32-reconstruct-hot-key", Fw32_reconstruct_hot_key,
-       Sw32_reconstruct_hot_key, 1, 1, 0,
-       doc: /* Convert hot-key ID to a lisp key combination.
-usage: (w32-reconstruct-hot-key ID)  */)
-  (Lisp_Object hotkeyid)
-{
-  int vk_code, w32_modifiers;
-  Lisp_Object key;
-
-  CHECK_NUMBER (hotkeyid);
-
-  vk_code = HOTKEY_VK_CODE (hotkeyid);
-  w32_modifiers = HOTKEY_MODIFIERS (hotkeyid);
-
-  if (vk_code < 256 && lispy_function_keys[vk_code])
-    key = intern (lispy_function_keys[vk_code]);
-  else
-    key = make_number (vk_code);
-
-  key = Fcons (key, Qnil);
-  if (w32_modifiers & MOD_SHIFT)
-    key = Fcons (Qshift, key);
-  if (w32_modifiers & MOD_CONTROL)
-    key = Fcons (Qctrl, key);
-  if (w32_modifiers & MOD_ALT)
-    key = Fcons (NILP (Vw32_alt_is_meta) ? Qalt : Qmeta, key);
-  if (w32_modifiers & MOD_WIN)
-    key = Fcons (Qhyper, key);
-
-  return key;
+  return w32_parse_and_register_hot_key (key, 0);
  }

  DEFUN ("w32-toggle-lock-key", Fw32_toggle_lock_key,
@@ -9307,9 +9150,6 @@ syms_of_w32fns (void)
    Fput (Qundefined_color, Qerror_message,
  	build_pure_c_string ("Undefined color"));

-  staticpro (&w32_grabbed_keys);
-  w32_grabbed_keys = Qnil;
-
    DEFVAR_LISP ("w32-color-map", Vw32_color_map,
  	       doc: /* An array of color name mappings for Windows.  */);
    Vw32_color_map = Qnil;
@@ -9622,8 +9462,6 @@ This variable has effect only on Windows Vista and 
later.  */);
    defsubr (&Sw32_shell_execute);
    defsubr (&Sw32_register_hot_key);
    defsubr (&Sw32_unregister_hot_key);
-  defsubr (&Sw32_registered_hot_keys);
-  defsubr (&Sw32_reconstruct_hot_key);
    defsubr (&Sw32_toggle_lock_key);
    defsubr (&Sw32_window_exists_p);
    defsubr (&Sw32_battery_status);
diff --git a/src/w32hook.c b/src/w32hook.c
new file mode 100644
index 0000000..1b1e35b
--- /dev/null
+++ b/src/w32hook.c
@@ -0,0 +1,343 @@
+/* System hooks for GNU Emacs on the Microsoft Windows API.
+   Copyright (C) 1992, 1999, 2001-2015 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 <http://www.gnu.org/licenses/>.  */
+
+/* Written by Jussi Lahdenniemi <jussi@aprikoodi.fi>.
+
+   This code handles grabbing of the Windows keys and Alt-* key
+   combinations reserved by the system.  Handling Alt is a bit easier,
+   as Windows intends Alt-* shortcuts for application use in Windows;
+   hotkeys such as Alt-tab and Alt-escape are special cases.  Win-*
+   hotkeys, on the other hand, are primarily meant for system use.
+
+   As a result, when we want Emacs to be able to grab the Win-* keys,
+   we must swallow all Win key presses in a low-level keyboard hook.
+   Unfortunately, thismeans that the Emacs window procedure (and
+   console input handler) never see the keypresses either.  Thus, to
+   check the modifier states properly, Emacs code must use the
+   check_w32_winkey_state function that uses the flags directly
+   updated by the hook callback.
+
+   The keyboard hook sees keyboard input on all processes (except
+   elevated ones, when Emacs itself is not elevated).  As such, care
+   must be taken to only filter out keyboard input when Emacs itself
+   is on the foreground.
+ */
+
+#include <string.h>
+#include <config.h>
+#include "lisp.h"
+#include "w32common.h"
+#include "w32term.h"
+#include "w32inevt.h"
+
+static int hook_count = 0; /* counter, if several windows are created */
+static HHOOK hook = NULL;  /* hook handle */
+
+static int lwindown = 0;      /* Left Windows key currently pressed 
(and hooked) */
+static int rwindown = 0;      /* Right Windows key currently pressed 
(and hooked) */
+static int winsdown = 0;      /* Number of handled keys currently 
pressed */
+static int send_win_up = 0;   /* Pass through the keyup for this 
Windows key press? */
+static int suppress_lone = 0; /* Suppress simulated Windows 
keydown-keyup for this press? */
+static int winseen = 0;       /* Windows keys seen during this press? */
+
+static char alt_hooked[256] = {0};  /* hook Alt+[this key]? */
+static char lwin_hooked[256] = {0}; /* hook left Win+[this key]? */
+static char rwin_hooked[256] = {0}; /* hook right Win+[this key]? */
+
+/* stdin, from w32console.c */
+extern HANDLE keyboard_handle;
+
+/* The Windows keyboard hook callback */
+static LRESULT CALLBACK funhook( int code, WPARAM w, LPARAM l )
+{
+  INPUT inputs[2];
+  HWND focus = GetFocus();
+  int console = 0;
+  KBDLLHOOKSTRUCT const* hs = (KBDLLHOOKSTRUCT*)l;
+
+  if( code < 0 || (hs->flags & LLKHF_INJECTED))
+    {
+      return CallNextHookEx( 0, code, w, l );
+    }
+
+  /* GetFocus() returns a non-NULL window if another application is active,
+     and always for a console Emacs process.  For a console Emacs, 
determine
+     focus by checking if the current foreground window is the process's
+     console window. */
+  if (focus == NULL)
+    {
+      HWND con = GetConsoleWindow();
+      if (con == GetForegroundWindow())
+        {
+          focus = con;
+          console = 1;
+        }
+    }
+
+  /* First, check hooks for the left and right Windows keys */
+  if( hs->vkCode == VK_LWIN || hs->vkCode == VK_RWIN)
+    {
+      if( focus != NULL && (w == WM_KEYDOWN || w == WM_SYSKEYDOWN))
+        {
+          /* The key is being pressed in an Emacs window */
+          if( hs->vkCode == VK_LWIN && !lwindown )
+            {
+              lwindown = 1;
+              winseen = 1;
+              winsdown++;
+            }
+          else if( hs->vkCode == VK_RWIN && !rwindown )
+            {
+              rwindown = 1;
+              winseen = 1;
+              winsdown++;
+            }
+          /* Returning 1 here drops the keypress without further 
processing.
+             If the keypress was allowed to go through, the normal Windows
+             hotkeys would take over. */
+          return 1;
+        }
+      else if( winsdown > 0 && (w == WM_KEYUP || w == WM_SYSKEYUP))
+        {
+          /* A key that has been captured earlier is being released now. */
+          if( hs->vkCode == VK_LWIN && lwindown )
+            {
+              lwindown = 0;
+              winsdown--;
+            }
+          else if( hs->vkCode == VK_RWIN && rwindown )
+            {
+              rwindown = 0;
+              winsdown--;
+            }
+          if( winsdown == 0 && winseen )
+            {
+              if( !suppress_lone )
+                {
+                  /* The Windows key was pressed, then released, 
without any other
+                     key pressed simultaneously.  Normally, this opens 
the Start
+                     menu, but the user can prevent this by setting the
+                     w32-pass-[lr]window-to-system variable to NIL. */
+                  if (hs->vkCode == VK_LWIN && 
!NILP(Vw32_pass_lwindow_to_system) ||
+                      hs->vkCode == VK_RWIN && 
!NILP(Vw32_pass_rwindow_to_system))
+                    {
+                      /* Not prevented - Simulate the keypress to the 
system */
+                      memset( inputs, 0, sizeof(inputs));
+                      inputs[0].type = INPUT_KEYBOARD;
+                      inputs[0].ki.wVk = hs->vkCode;
+                      inputs[0].ki.wScan = hs->vkCode;
+                      inputs[0].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
+                      inputs[0].ki.time = 0;
+                      inputs[1].type = INPUT_KEYBOARD;
+                      inputs[1].ki.wVk = hs->vkCode;
+                      inputs[1].ki.wScan = hs->vkCode;
+                      inputs[1].ki.dwFlags = KEYEVENTF_EXTENDEDKEY | 
KEYEVENTF_KEYUP;
+                      inputs[1].ki.time = 0;
+                      SendInput( 2, inputs, sizeof(INPUT));
+                    }
+                  else if( focus != NULL )
+                    {
+                      /* When not passed to system, must simulate 
privately to Emacs */
+                      PostMessage( focus, WM_SYSKEYDOWN, hs->vkCode, 0 );
+                      PostMessage( focus, WM_SYSKEYUP, hs->vkCode, 0 );
+                    }
+                }
+            }
+          if( winsdown == 0 )
+            {
+              /* No Windows keys pressed anymore - clear the state flags */
+              suppress_lone = 0;
+              winseen = 0;
+            }
+          if( !send_win_up )
+            {
+              /* Swallow this release message, as not to confuse 
applications who
+                 did not get to see the original WM_KEYDOWN message 
either. */
+              return 1;
+            }
+          send_win_up = 0;
+        }
+    }
+  else if( winsdown > 0 )
+    {
+      /* Some other key was pressed while a captured Win key is down.
+         This is either an Emacs registered hotkey combination, or a
+         system hotkey. */
+      if( lwindown && lwin_hooked[hs->vkCode] ||
+          rwindown && rwin_hooked[hs->vkCode] )
+        {
+          /* Hooked Win-x combination, do not pass the keypress to 
Windows */
+          suppress_lone = 1;
+        }
+      else if (!suppress_lone)
+        {
+          /* Unhooked S-x combination; simulate the combination now
+             (will be seen by the system) */
+          memset( inputs, 0, sizeof(inputs));
+          inputs[0].type = INPUT_KEYBOARD;
+          inputs[0].ki.wVk = lwindown ? VK_LWIN : VK_RWIN;
+          inputs[0].ki.wScan = lwindown ? VK_LWIN : VK_RWIN;
+          inputs[0].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
+          inputs[0].ki.time = 0;
+          inputs[1].type = INPUT_KEYBOARD;
+          inputs[1].ki.wVk = hs->vkCode;
+          inputs[1].ki.wScan = hs->scanCode;
+          inputs[1].ki.dwFlags = (hs->flags & LLKHF_EXTENDED) ? 
KEYEVENTF_EXTENDEDKEY : 0;
+          inputs[1].ki.time = 0;
+          SendInput( 2, inputs, sizeof(INPUT));
+          /* Stop processing of this Win sequence here; the
+             corresponding keyup messages will come through the normal
+             channel when the keys are released. */
+          suppress_lone = 1;
+          send_win_up = 1;
+          /* Swallow the original keypress (as we want the Win key
+             down message simulated above to precede this real message). */
+          return 1;
+        }
+    }
+
+  /* Next, handle the registered Alt-* combinations */
+  if( (w == WM_SYSKEYDOWN || w == WM_KEYDOWN) &&
+      alt_hooked[hs->vkCode] &&
+      focus != NULL &&
+      (GetAsyncKeyState(VK_MENU) & 0x8000))
+    {
+      /* Prevent the system from getting this Alt-* key - suppress the
+         message and post as a normal keypress to Emacs.
+
+         For some reason, in case of the Alt-escape combination on a
+         console Emacs, the console process swallows the escape
+         keydown message here.  Simulating the keypress with SendInput
+         just gives the standard functionality of sending the window
+         to back.  So, to make Alt-escape to work on a console Emacs,
+         the keypress would need to be communicated directly from here
+         to the key_event functionality in w32inevt.c; but this hook
+         code does not run on the same thread as the normal keyboard
+         input code, so proper synchronization should be done.  As
+         this is quite a corner case, it is left unimplemented for
+         now. */
+      if( console )
+        {
+          INPUT_RECORD rec;
+          DWORD n;
+          rec.EventType = KEY_EVENT;
+          rec.Event.KeyEvent.bKeyDown = TRUE;
+          rec.Event.KeyEvent.wVirtualKeyCode = hs->vkCode;
+          rec.Event.KeyEvent.wVirtualScanCode = hs->scanCode;
+          rec.Event.KeyEvent.uChar.UnicodeChar = 0;
+          rec.Event.KeyEvent.dwControlKeyState =
+            ((GetAsyncKeyState(VK_LMENU) & 0x8000) ? LEFT_ALT_PRESSED : 
0) |
+            ((GetAsyncKeyState(VK_RMENU) & 0x8000) ? RIGHT_ALT_PRESSED 
: 0) |
+            ((GetAsyncKeyState(VK_LCONTROL) & 0x8000) ? 
LEFT_CTRL_PRESSED : 0) |
+            ((GetAsyncKeyState(VK_RCONTROL) & 0x8000) ? 
RIGHT_CTRL_PRESSED : 0) |
+            ((GetAsyncKeyState(VK_SHIFT) & 0x8000) ? SHIFT_PRESSED : 0) |
+            ((hs->flags & LLKHF_EXTENDED) ? ENHANCED_KEY : 0);
+          if( w32_console_unicode_input )
+            WriteConsoleInputW(keyboard_handle, &rec, 1, &n);
+          else
+            WriteConsoleInputA(keyboard_handle, &rec, 1, &n);
+        }
+      else
+        PostMessage( focus, w, hs->vkCode, 1 | (1<<29));
+      return 1;
+    }
+
+  /* The normal case - pass the message through */
+  return CallNextHookEx( 0, code, w, l );
+}
+
+/* Set up the hook; can be called several times, with matching
+   remove_w32_kbdhook calls. */
+void setup_w32_kbdhook (void)
+{
+  hook_count++;
+  if (hook_count == 1)
+    {
+      hook = SetWindowsHookEx( WH_KEYBOARD_LL, funhook, 
GetModuleHandle(NULL), 0 );
+    }
+}
+
+/* Remove the hook */
+void remove_w32_kbdhook (void)
+{
+  hook_count--;
+  if (hook_count == 0)
+    {
+      UnhookWindowsHookEx( hook );
+      hook = NULL;
+    }
+}
+
+/* Check the current Win key pressed state - see the discussion at the
+   top of the file for the rationale */
+int check_w32_winkey_state (int vkey)
+{
+  switch (vkey)
+  {
+    case VK_LWIN: return lwindown;
+    case VK_RWIN: return rwindown;
+  }
+  return 0;
+}
+
+/* Mark a specific key combination as hooked, preventing it to be
+   handled by the system */
+void hook_w32_key (int hook, int modifier, int vkey)
+{
+  char* tbl = NULL;
+
+  switch(modifier)
+    {
+    case VK_MENU: tbl = alt_hooked; break;
+    case VK_LWIN: tbl = lwin_hooked; break;
+    case VK_RWIN: tbl = rwin_hooked; break;
+    }
+
+  if (tbl != NULL && vkey >= 0 && vkey <= 255)
+    {
+      /* VK_ANY hooks all keys for this modifier */
+      if (vkey == VK_ANY)
+        memset(tbl, (char)hook, 256);
+      else
+        tbl[vkey] = (char)hook;
+      /* Alt-<modifier>s should go through */
+      alt_hooked[VK_MENU] = 0;
+      alt_hooked[VK_LMENU] = 0;
+      alt_hooked[VK_RMENU] = 0;
+      alt_hooked[VK_CONTROL] = 0;
+      alt_hooked[VK_LCONTROL] = 0;
+      alt_hooked[VK_RCONTROL] = 0;
+      alt_hooked[VK_SHIFT] = 0;
+      alt_hooked[VK_LSHIFT] = 0;
+      alt_hooked[VK_RSHIFT] = 0;
+    }
+}
+
+/* Resets the keyboard hook state. Locking the workstation with Win-L
+   leaves the Win key(s) "down" from the hook's point of view - the
+   keyup event is never seen.  Thus, this function must be called when
+   the system is locked. */
+void reset_w32_kbdhook_state (void)
+{
+  lwindown = 0;
+  rwindown = 0;
+  winsdown = 0;
+  send_win_up = 0;
+  suppress_lone = 0;
+  winseen = 0;
+}
diff --git a/src/w32inevt.c b/src/w32inevt.c
index db2e218..931fb20 100644
--- a/src/w32inevt.c
+++ b/src/w32inevt.c
@@ -147,12 +147,6 @@ key_event (KEY_EVENT_RECORD *event, struct 
input_event *emacs_ev, int *isdead)
      {
        switch (event->wVirtualKeyCode)
  	{
-	case VK_LWIN:
-	  mod_key_state &= ~LEFT_WIN_PRESSED;
-	  break;
-	case VK_RWIN:
-	  mod_key_state &= ~RIGHT_WIN_PRESSED;
-	  break;
  	case VK_APPS:
  	  mod_key_state &= ~APPS_PRESSED;
  	  break;
@@ -185,7 +179,6 @@ key_event (KEY_EVENT_RECORD *event, struct 
input_event *emacs_ev, int *isdead)
  	      keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
  	    }
  	}
-      mod_key_state |= LEFT_WIN_PRESSED;
        if (!NILP (Vw32_lwindow_modifier))
  	return 0;
        break;
@@ -201,7 +194,6 @@ key_event (KEY_EVENT_RECORD *event, struct 
input_event *emacs_ev, int *isdead)
  	      keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
  	    }
  	}
-      mod_key_state |= RIGHT_WIN_PRESSED;
        if (!NILP (Vw32_rwindow_modifier))
  	return 0;
        break;
@@ -267,6 +259,10 @@ key_event (KEY_EVENT_RECORD *event, struct 
input_event *emacs_ev, int *isdead)

    /* Recognize state of Windows and Apps keys.  */
    event->dwControlKeyState |= mod_key_state;
+  if (check_w32_winkey_state(VK_LWIN))
+    event->dwControlKeyState |= LEFT_WIN_PRESSED;
+  if (check_w32_winkey_state(VK_RWIN))
+    event->dwControlKeyState |= RIGHT_WIN_PRESSED;

    /* Distinguish numeric keypad keys from extended keys.  */
    event->wVirtualKeyCode =
diff --git a/src/w32term.h b/src/w32term.h
index 3377b53..8432843 100644
--- a/src/w32term.h
+++ b/src/w32term.h
@@ -738,6 +738,12 @@ extern int handle_file_notifications (struct 
input_event *);
  extern void w32_initialize_display_info (Lisp_Object);
  extern void initialize_w32_display (struct terminal *, int *, int *);

+extern void setup_w32_kbdhook (void);
+extern void remove_w32_kbdhook (void);
+extern void hook_w32_key (int hook, int modifier, int vkey);
+extern int check_w32_winkey_state (int vkey);
+extern void reset_w32_kbdhook_state (void);
+
  /* Keypad command key support.  W32 doesn't have virtual keys defined
     for the function keys on the keypad (they are mapped to the standard
     function keys), so we define our own.  */
@@ -762,6 +768,10 @@ extern void initialize_w32_display (struct terminal 
*, int *, int *);
  #define VK_APPS			0x5D
  #endif

+/* Special virtual key code for indicating "any" key.  This can be used
+   as an argument to the hook_w32_key function. */
+#define VK_ANY                  0xFF
+
  /* Support for treating Windows and Apps keys as modifiers.  These
     constants must not overlap with any of the dwControlKeyState flags in
     KEY_EVENT_RECORD.  */
-- 
2.6.2




^ permalink raw reply related	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-09 19:58   ` Jussi Lahdenniemi
@ 2016-01-11 18:54     ` Eli Zaretskii
  2016-01-12 11:16       ` Jussi Lahdenniemi
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2016-01-11 18:54 UTC (permalink / raw)
  To: Jussi Lahdenniemi; +Cc: emacs-devel

> Cc: emacs-devel@gnu.org
> From: Jussi Lahdenniemi <jussi@aprikoodi.fi>
> Date: Sat, 9 Jan 2016 21:58:52 +0200
> 
> On 5.1.2016 19.05, Eli Zaretskii wrote:
> > Thank you for your contribution.  It is large enough to require legal
> > paperwork; I can send you the forms off-list if you agree.
> 
> I finished integrating the code more tightly into Emacs sources, 
> removing the need for the additional process and adding functionality 
> for grabbing Alt-based keyboard input (M-tab, M-ESC) in addition to the 
> Windows keys. I also updated the documentation.

Thanks.

> The patch is attached. I decided to place the new functionality in a new 
> file (w32hook.c) - it could have been added to some existing file as well.

I'd prefer not to create a new file, but to have this in w32fns.c.  It
might even allow you to make some functions static.

> -@findex w32-register-hot-key
> -@findex w32-unregister-hot-key
> -  MS-Windows reserves certain key combinations, such as

I'm not sure I understand why you moved this stuff down in the file.
Was something wrong with its original place?  You could make the
changes without moving the stuff, no?

> +   The hotkey registrations always also include all the shift and
> +control modifier combinations for the given hotkey; that is,
> +registering @kbd{s-@key{a}} as a hotkey gives you @kbd{s-@key{A}},
> +@kbd{C-s-@key{a}} and @kbd{C-s-@key{A}} as well.

I believe you meant to use "C-S-" etc. here, for the Shift key (not
"super").

> -		  if (NUMBERP (Vw32_phantom_key_code))
> -		    key = XUINT (Vw32_phantom_key_code) & 255;
> -		  else
> -		    key = VK_SPACE;

It looks like you are removing the support for this feature.  Is it
really not needed anymore?  If so, we should mention this change in
NEWS, and tell there how to achieve the same effect without this
variable.

> +/* The Windows keyboard hook callback */

Comments should have a period at the end of a sentence, and 2 spaces
after that.

> +static LRESULT CALLBACK funhook( int code, WPARAM w, LPARAM l )

A blank between the function name and the left parenthesis, and no
blank after the parenthesis.  Same near the right parenthesis.

I've briefly reviewed the rest of the patch, and it looks OK to me.
Did you make sure the new code doesn't call any API that might be
unavailable on older systems?  We still support Windows 98 and later.

Also, I understand that this code will work on versions of Windows
before v8, is that right?

Thanks.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-11 18:54     ` Eli Zaretskii
@ 2016-01-12 11:16       ` Jussi Lahdenniemi
  2016-01-12 15:08         ` covici
  2016-01-12 15:54         ` Eli Zaretskii
  0 siblings, 2 replies; 63+ messages in thread
From: Jussi Lahdenniemi @ 2016-01-12 11:16 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

>> The patch is attached. I decided to place the new functionality in a new
>> file (w32hook.c) - it could have been added to some existing file as well.
>
> I'd prefer not to create a new file, but to have this in w32fns.c.  It
> might even allow you to make some functions static.

OK.

>> -@findex w32-register-hot-key
>> -@findex w32-unregister-hot-key
>> -  MS-Windows reserves certain key combinations, such as
>
> I'm not sure I understand why you moved this stuff down in the file.
> Was something wrong with its original place?  You could make the
> changes without moving the stuff, no?

In the documentation for w32-register-hot-key I am now referring to the 
w32-[lr]window-modifier variables; there is a strongish dependency 
between these now. For this reason, I preferred documenting the 
w32-*-hot-key functions after the w32-*-modifier part. But of course, 
this is not a must.

>> +   The hotkey registrations always also include all the shift and
>> +control modifier combinations for the given hotkey; that is,
>> +registering @kbd{s-@key{a}} as a hotkey gives you @kbd{s-@key{A}},
>> +@kbd{C-s-@key{a}} and @kbd{C-s-@key{A}} as well.
>
> I believe you meant to use "C-S-" etc. here, for the Shift key (not
> "super").

No, what I mean is that registering s-a also registers S-s-a, C-s-a, and 
C-S-s-a. I wrote S-*-a as *-A in that documentation, base on the 
observation that for example C-h k M-S-a is shown as M-A by Emacs. But 
maybe it would be better to write a lower-case a and explicit S modifier 
in all the cases?

>> -		  if (NUMBERP (Vw32_phantom_key_code))
>> -		    key = XUINT (Vw32_phantom_key_code) & 255;
>> -		  else
>> -		    key = VK_SPACE;
>
> It looks like you are removing the support for this feature.  Is it
> really not needed anymore?  If so, we should mention this change in
> NEWS, and tell there how to achieve the same effect without this
> variable.

True. I have never used the w32-phantom-key-code myself, so I did not 
notice that (and, actually, the variable is still checked - 
unnecessarily - in w32inevt.c). But, setting 
w32-pass-[lr]window-to-system to NIL has now the desired effect even 
without the use of a phantom key code; the keypress is routed directly 
from the hook function to the Emacs input handler, without passing 
through the standard system keyboard functionality inbetween, which 
eliminates the need to lie to the system about the key that has been 
pressed.

> I've briefly reviewed the rest of the patch, and it looks OK to me.
> Did you make sure the new code doesn't call any API that might be
> unavailable on older systems?  We still support Windows 98 and later.

Unfortunately, Windows 98 does not include the low-level keyboard hook 
functionality that is essential for my code to work. It is supported in 
Windows 2000 (and even NT4, apparently), but not on the 95/98/ME branch.

So, probably I would need to change the code so that the old 
functionality is preserved and used if the new API are not available 
(pre-Win2000), in the same style that w32uniscribe works? It should 
still even be possible to write a single configuration file that works 
on both environments.

> Also, I understand that this code will work on versions of Windows
> before v8, is that right?

I have tested the code on Windows 10 (my physical PC) and Windows 7 (in 
a VM) both as 32-bit and 64-bit versions. I'll try to get Win2000 
installed on another VM as well and test with it, just to be sure.

-- 
Jussi Lahdenniemi





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-12 11:16       ` Jussi Lahdenniemi
@ 2016-01-12 15:08         ` covici
  2016-01-13  5:07           ` Jussi Lahdenniemi
  2016-01-12 15:54         ` Eli Zaretskii
  1 sibling, 1 reply; 63+ messages in thread
From: covici @ 2016-01-12 15:08 UTC (permalink / raw)
  To: Jussi Lahdenniemi; +Cc: Eli Zaretskii, emacs-devel

Jussi Lahdenniemi <jussi@aprikoodi.fi> wrote:

> >> The patch is attached. I decided to place the new functionality in a new
> >> file (w32hook.c) - it could have been added to some existing file as well.
> >
> > I'd prefer not to create a new file, but to have this in w32fns.c.  It
> > might even allow you to make some functions static.
> 
> OK.
> 
> >> -@findex w32-register-hot-key
> >> -@findex w32-unregister-hot-key
> >> -  MS-Windows reserves certain key combinations, such as
> >
> > I'm not sure I understand why you moved this stuff down in the file.
> > Was something wrong with its original place?  You could make the
> > changes without moving the stuff, no?
> 
> In the documentation for w32-register-hot-key I am now referring to
> the w32-[lr]window-modifier variables; there is a strongish dependency
> between these now. For this reason, I preferred documenting the
> w32-*-hot-key functions after the w32-*-modifier part. But of course,
> this is not a must.
> 
> >> +   The hotkey registrations always also include all the shift and
> >> +control modifier combinations for the given hotkey; that is,
> >> +registering @kbd{s-@key{a}} as a hotkey gives you @kbd{s-@key{A}},
> >> +@kbd{C-s-@key{a}} and @kbd{C-s-@key{A}} as well.
> >
> > I believe you meant to use "C-S-" etc. here, for the Shift key (not
> > "super").
> 
> No, what I mean is that registering s-a also registers S-s-a, C-s-a,
> and C-S-s-a. I wrote S-*-a as *-A in that documentation, base on the
> observation that for example C-h k M-S-a is shown as M-A by Emacs. But
> maybe it would be better to write a lower-case a and explicit S
> modifier in all the cases?
> 
> >> -		  if (NUMBERP (Vw32_phantom_key_code))
> >> -		    key = XUINT (Vw32_phantom_key_code) & 255;
> >> -		  else
> >> -		    key = VK_SPACE;
> >
> > It looks like you are removing the support for this feature.  Is it
> > really not needed anymore?  If so, we should mention this change in
> > NEWS, and tell there how to achieve the same effect without this
> > variable.
> 
> True. I have never used the w32-phantom-key-code myself, so I did not
> notice that (and, actually, the variable is still checked - 
> unnecessarily - in w32inevt.c). But, setting
> w32-pass-[lr]window-to-system to NIL has now the desired effect even
> without the use of a phantom key code; the keypress is routed directly
> from the hook function to the Emacs input handler, without passing
> through the standard system keyboard functionality inbetween, which
> eliminates the need to lie to the system about the key that has been
> pressed.
> 
> > I've briefly reviewed the rest of the patch, and it looks OK to me.
> > Did you make sure the new code doesn't call any API that might be
> > unavailable on older systems?  We still support Windows 98 and later.
> 
> Unfortunately, Windows 98 does not include the low-level keyboard hook
> functionality that is essential for my code to work. It is supported
> in Windows 2000 (and even NT4, apparently), but not on the 95/98/ME
> branch.
> 
> So, probably I would need to change the code so that the old
> functionality is preserved and used if the new API are not available
> (pre-Win2000), in the same style that w32uniscribe works? It should
> still even be possible to write a single configuration file that works
> on both environments.
> 
> > Also, I understand that this code will work on versions of Windows
> > before v8, is that right?
> 
> I have tested the code on Windows 10 (my physical PC) and Windows 7
> (in a VM) both as 32-bit and 64-bit versions. I'll try to get Win2000
> installed on another VM as well and test with it, just to be sure.
> 
> -- 
> Jussi Lahdenniemi

I have a screen reader which is also doing keyboard coding at the low
level,  I wonder if this patch  would effect that program?  Also, I hope
you don't hijack alt-tab, that is necessary even when emacs is running.



-- 
Your life is like a penny.  You're going to lose it.  The question is:
How do
you spend it?

         John Covici
         covici@ccs.covici.com



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-12 11:16       ` Jussi Lahdenniemi
  2016-01-12 15:08         ` covici
@ 2016-01-12 15:54         ` Eli Zaretskii
  2016-01-13  5:31           ` Jussi Lahdenniemi
  2016-01-13  9:16           ` Jussi Lahdenniemi
  1 sibling, 2 replies; 63+ messages in thread
From: Eli Zaretskii @ 2016-01-12 15:54 UTC (permalink / raw)
  To: Jussi Lahdenniemi; +Cc: emacs-devel

> From: Jussi Lahdenniemi <jussi@aprikoodi.fi>
> Cc: emacs-devel@gnu.org
> Date: Tue, 12 Jan 2016 13:16:14 +0200
> 
> > I've briefly reviewed the rest of the patch, and it looks OK to me.
> > Did you make sure the new code doesn't call any API that might be
> > unavailable on older systems?  We still support Windows 98 and later.
> 
> Unfortunately, Windows 98 does not include the low-level keyboard hook 
> functionality that is essential for my code to work. It is supported in 
> Windows 2000 (and even NT4, apparently), but not on the 95/98/ME branch.
> 
> So, probably I would need to change the code so that the old 
> functionality is preserved and used if the new API are not available 
> (pre-Win2000), in the same style that w32uniscribe works?

Which APIs that you used in the patch are not available on Windows 9X?
I thought I went over all of them, and they all are, but maybe I
missed some.

Most of the examples of how to use an API that might not be available
and should be detected at run time are in w32.c, although
w32uniscribe.c also does something similar in a few cases.

> > Also, I understand that this code will work on versions of Windows
> > before v8, is that right?
> 
> I have tested the code on Windows 10 (my physical PC) and Windows 7 (in 
> a VM) both as 32-bit and 64-bit versions. I'll try to get Win2000 
> installed on another VM as well and test with it, just to be sure.

If W2K is difficult to get by, XP should be good enough.

Thanks.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-12 15:08         ` covici
@ 2016-01-13  5:07           ` Jussi Lahdenniemi
  0 siblings, 0 replies; 63+ messages in thread
From: Jussi Lahdenniemi @ 2016-01-13  5:07 UTC (permalink / raw)
  To: covici; +Cc: Eli Zaretskii, emacs-devel

On 12.1.2016 17.08, covici@ccs.covici.com wrote:
> I have a screen reader which is also doing keyboard coding at the low
> level,  I wonder if this patch  would effect that program?  Also, I hope
> you don't hijack alt-tab, that is necessary even when emacs is running.

My code does not hijack anything unless the user wants to. Alt-tab can 
be captured with the call (w32-register-hot-key [M-tab]), but unless 
that call is issued, there is no effect.

The possible effect to the screen reader is that the screen reader's 
hook does not necessarily get to see the keypress events of the Windows 
keys and the captured Alt-* combinations. All other input goes through 
as-is. If the w32-register-hot-key function is not called, ALL input 
goes through as-is.

-- 
Jussi Lahdenniemi





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-12 15:54         ` Eli Zaretskii
@ 2016-01-13  5:31           ` Jussi Lahdenniemi
  2016-01-13 15:49             ` Eli Zaretskii
  2016-01-13  9:16           ` Jussi Lahdenniemi
  1 sibling, 1 reply; 63+ messages in thread
From: Jussi Lahdenniemi @ 2016-01-13  5:31 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

On 12.1.2016 17.54, Eli Zaretskii wrote:
> Which APIs that you used in the patch are not available on Windows 9X?
> I thought I went over all of them, and they all are, but maybe I
> missed some.

Actually, there is only one: GetConsoleWindow. However, the 
WH_KEYBOARD_LL hook is not implemented at all on Win98. So, if we want 
to offer the old w32-register-hot-key/w32-phantom-key-code functionality 
to users of Win98, the new patch needs to be added to the existing code 
instead of replacing it.

Which road should I take? Assuming that the patch runs on Win2k, the 
only people affected by the choice are those running Win98 and ME. Keep 
the old functionality for a bit messier code base and documentation, or 
replace the old functionality and have Win98/ME people lose 
w32-register-hot-key?

-- 
Jussi Lahdenniemi





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-12 15:54         ` Eli Zaretskii
  2016-01-13  5:31           ` Jussi Lahdenniemi
@ 2016-01-13  9:16           ` Jussi Lahdenniemi
  2016-01-13 11:28             ` Jussi Lahdenniemi
  2016-01-13 15:53             ` Eli Zaretskii
  1 sibling, 2 replies; 63+ messages in thread
From: Jussi Lahdenniemi @ 2016-01-13  9:16 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

On 12.1.2016 17.54, Eli Zaretskii wrote:
> Which APIs that you used in the patch are not available on Windows 9X?
> I thought I went over all of them, and they all are, but maybe I
> missed some.

By the way, now that I tried running Emacs on Win98 and Win2k I noticed 
that the commit 7afa4f300 by you in August seems to break compatibility 
with these old operating systems by linking to the function 
_resetstkoflw in msvcrt.dll. The function was apparently introduced in 
version 7.0 of msvcrt.dll, while Win2k still ships with version 6.1.

-- 
Jussi Lahdenniemi





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-13  9:16           ` Jussi Lahdenniemi
@ 2016-01-13 11:28             ` Jussi Lahdenniemi
  2016-01-13 15:57               ` Eli Zaretskii
  2016-01-13 15:53             ` Eli Zaretskii
  1 sibling, 1 reply; 63+ messages in thread
From: Jussi Lahdenniemi @ 2016-01-13 11:28 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

On 13.1.2016 11.16, I wrote:
> By the way, now that I tried running Emacs on Win98 and Win2k I noticed
> that the commit 7afa4f300 by you in August seems to break compatibility
> with these old operating systems by linking to the function
> _resetstkoflw in msvcrt.dll. The function was apparently introduced in
> version 7.0 of msvcrt.dll, while Win2k still ships with version 6.1.

And, even after removing the call to _resetstkoflw, an attempt to run 
Emacs on Windows 98 (with or without my modifications, master branch or 
the emacs-25 branch) results in an immediate crash, with the message 
"Wrong type argument: stringp, #<EMACS BUG: INVALID DATATYPE (MISC 
0xde84) Save your buffers immediately and please report this bug>"; the 
hex tag value varies.

This is not due to my build environment; emacs-24.5 built from the 
sources runs fine.

Getting back to the original issue: I verified that my code works on 
Win2000. Unfortunately, I was not able to install NT4 on a VM, so I 
cannot verify the code on that.

-- 
Jussi Lahdenniemi




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-13  5:31           ` Jussi Lahdenniemi
@ 2016-01-13 15:49             ` Eli Zaretskii
  0 siblings, 0 replies; 63+ messages in thread
From: Eli Zaretskii @ 2016-01-13 15:49 UTC (permalink / raw)
  To: Jussi Lahdenniemi; +Cc: emacs-devel

> Cc: emacs-devel@gnu.org
> From: Jussi Lahdenniemi <jussi@aprikoodi.fi>
> Date: Wed, 13 Jan 2016 07:31:50 +0200
> 
> On 12.1.2016 17.54, Eli Zaretskii wrote:
> > Which APIs that you used in the patch are not available on Windows 9X?
> > I thought I went over all of them, and they all are, but maybe I
> > missed some.
> 
> Actually, there is only one: GetConsoleWindow. However, the 
> WH_KEYBOARD_LL hook is not implemented at all on Win98.

Right.  I checked the APIs, but not the values of the parameters.

> So, if we want to offer the old
> w32-register-hot-key/w32-phantom-key-code functionality to users of
> Win98, the new patch needs to be added to the existing code instead
> of replacing it.
> 
> Which road should I take? Assuming that the patch runs on Win2k, the 
> only people affected by the choice are those running Win98 and ME. Keep 
> the old functionality for a bit messier code base and documentation, or 
> replace the old functionality and have Win98/ME people lose 
> w32-register-hot-key?

The former, I guess.  We still want to support Windows 9X.

Thanks.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-13  9:16           ` Jussi Lahdenniemi
  2016-01-13 11:28             ` Jussi Lahdenniemi
@ 2016-01-13 15:53             ` Eli Zaretskii
  1 sibling, 0 replies; 63+ messages in thread
From: Eli Zaretskii @ 2016-01-13 15:53 UTC (permalink / raw)
  To: Jussi Lahdenniemi; +Cc: emacs-devel

> Cc: emacs-devel@gnu.org
> From: Jussi Lahdenniemi <jussi@aprikoodi.fi>
> Date: Wed, 13 Jan 2016 11:16:55 +0200
> 
> On 12.1.2016 17.54, Eli Zaretskii wrote:
> > Which APIs that you used in the patch are not available on Windows 9X?
> > I thought I went over all of them, and they all are, but maybe I
> > missed some.
> 
> By the way, now that I tried running Emacs on Win98 and Win2k I noticed 
> that the commit 7afa4f300 by you in August seems to break compatibility 
> with these old operating systems by linking to the function 
> _resetstkoflw in msvcrt.dll. The function was apparently introduced in 
> version 7.0 of msvcrt.dll, while Win2k still ships with version 6.1.

My references were ambiguous about that when I wrote that code.

Can you replace the direct call to _resetstkoflw with a call through a
pointer which is assigned the right address at run time, if the
function available, and avoid calling it if not?  Like what we do with
the other such functions in w32.c and elsewhere.

I can write the code for this, if you want, but I cannot test it.

Thanks.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-13 11:28             ` Jussi Lahdenniemi
@ 2016-01-13 15:57               ` Eli Zaretskii
  2016-01-14 12:49                 ` Jussi Lahdenniemi
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2016-01-13 15:57 UTC (permalink / raw)
  To: Jussi Lahdenniemi; +Cc: emacs-devel

> From: Jussi Lahdenniemi <jussi@aprikoodi.fi>
> Date: Wed, 13 Jan 2016 13:28:22 +0200
> Cc: emacs-devel@gnu.org
> 
> And, even after removing the call to _resetstkoflw, an attempt to run 
> Emacs on Windows 98 (with or without my modifications, master branch or 
> the emacs-25 branch) results in an immediate crash, with the message 
> "Wrong type argument: stringp, #<EMACS BUG: INVALID DATATYPE (MISC 
> 0xde84) Save your buffers immediately and please report this bug>"; the 
> hex tag value varies.

If you can see in GDB where does this come from and show the
backtrace, that would be great.  Failing that, let's leave Windows 9X
testing alone for a while (you can always test the fallback code by
forcefully failing one of the run-time tests for the newer versions)
and test only on W2K.  We can return to the 9X problem later.

> This is not due to my build environment; emacs-24.5 built from the 
> sources runs fine.

I presume you built on a newer version of Windows and only ran on
Windows 9X?  I don't think the build procedure supports 9X.

> Getting back to the original issue: I verified that my code works on 
> Win2000. Unfortunately, I was not able to install NT4 on a VM, so I 
> cannot verify the code on that.

That's OK, W2K is good enough.  Thanks.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-13 15:57               ` Eli Zaretskii
@ 2016-01-14 12:49                 ` Jussi Lahdenniemi
  2016-01-14 17:10                   ` Jussi Lahdenniemi
  2016-01-14 18:15                   ` Eli Zaretskii
  0 siblings, 2 replies; 63+ messages in thread
From: Jussi Lahdenniemi @ 2016-01-14 12:49 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1976 bytes --]

On 13.1.2016 17.57, Eli Zaretskii wrote:
> If you can see in GDB where does this come from and show the
> backtrace, that would be great.  Failing that, let's leave Windows 9X
> testing alone for a while (you can always test the fallback code by
> forcefully failing one of the run-time tests for the newer versions)
> and test only on W2K.  We can return to the 9X problem later.

I was able to get a GDB dump of this, after installing MinGW from 2009. 
The backtrace is attached.

> I presume you built on a newer version of Windows and only ran on
> Windows 9X?  I don't think the build procedure supports 9X.

Yes, exactly.

>> Getting back to the original issue: I verified that my code works on
>> Win2000. Unfortunately, I was not able to install NT4 on a VM, so I
>> cannot verify the code on that.
>
> That's OK, W2K is good enough.  Thanks.

I *was* able to get NT4 installed finally as well, in a VM running 
inside a Win7 VM.  However, even the official Emacs 24.5 release binary 
fails to work on NT4.  It dies right at the start due to being unable to 
load its initialization files.

I investigated the problem and found out that it resulted from NT4's 
MultiByteToWideChar function not supporting the MB_ERR_INVALID_CHARS 
flags.  I made the flag conditional on the OS version, after which Emacs 
runs just fine on NT4.  I'm attaching a patch that contains this fix, 
and the conditional use of _resetstkoflw (which is also not supported on 
NT4) as well.

Also, I noticed that addpm.exe fails to load on a out-of-the-box NT4SP6, 
due to its dependency to a Shell32.dll version that ships with IE4. 
After installing IE4, addpm works.  It's worth noting that directly 
installing IE6 on NT4 does NOT make addpm functional, as IE6 does not 
contain the shell update.

My keyboard hooking code works on NT4 as well (although not on console 
mode due to the lack of the GetConsoleWindow function - I'll try to find 
a workaround for this).

-- 
Jussi Lahdenniemi

[-- Attachment #2: emacs-w98-crash.txt --]
[-- Type: text/plain, Size: 2671 bytes --]

#0  0xbff768a1 in ?? () from C:\WINDOWS\SYSTEM\KERNEL32.DLL
#1  0x01232146 in emacs_abort () at ../../emacs/src/w32fns.c:9794
#2  0x01107bd5 in terminate_due_to_signal (sig=22, backtrace_limit=2147483647)
    at ../../emacs/src/emacs.c:401
#3  0x0118720a in die (
    msg=0x14e9974 "XTYPE (a) == type && XUNTAG (a, type) == ptr",
    file=0x14e987c "../../emacs/src/lisp.h", line=1110)
    at ../../emacs/src/alloc.c:7063
#4  0x01103082 in make_lisp_ptr (ptr=0x2a3da84, type=Lisp_Vectorlike)
    at ../../emacs/src/lisp.h:1110
#5  0x01130714 in Fget_buffer_create (buffer_or_name=19694956)
    at ../../emacs/src/buffer.c:586
#6  0x011a9a9d in Ffuncall (nargs=2, args=0xd2ed64)
    at ../../emacs/src/eval.c:2693
#7  0x011f0c2b in exec_byte_code (bytestr=19694740, vector=19694757,
    maxdepth=26, args_template=0, nargs=0, args=0x0)
    at ../../emacs/src/bytecode.c:880
#8  0x011aa7c1 in funcall_lambda (fun=19694677, nargs=4, arg_vector=0xd2ef94)
    at ../../emacs/src/eval.c:2921
#9  0x011a9d13 in Ffuncall (nargs=5, args=0xd2ef90)
    at ../../emacs/src/eval.c:2742
#10 0x011a95b9 in call4 (fn=-11384880, arg1=23769076, arg2=23769076,
    arg3=23184, arg4=23184) at ../../emacs/src/eval.c:2577
#11 0x011d67ff in Fload (file=23769092, noerror=23184, nomessage=23184,
    nosuffix=23184, must_suffix=0) at ../../emacs/src/lread.c:1275
#12 0x011a9b9d in Ffuncall (nargs=5, args=0xd2f590)
    at ../../emacs/src/eval.c:2709
#13 0x011f0c2b in exec_byte_code (bytestr=20205940, vector=20205957,
    maxdepth=50, args_template=2, nargs=0, args=0xd2f730)
    at ../../emacs/src/bytecode.c:880
#14 0x011aa3aa in funcall_lambda (fun=20205917, nargs=0, arg_vector=0xd2f730)
    at ../../emacs/src/eval.c:2855
#15 0x011aa07b in apply_lambda (fun=20205917, args=0, count=3)
    at ../../emacs/src/eval.c:2794
#16 0x011a85a3 in eval_sub (form=24342443) at ../../emacs/src/eval.c:2211
#17 0x011a7b9b in Feval (form=24342443, lexical=0)
    at ../../emacs/src/eval.c:1988
#18 0x0110b9ff in top_level_2 () at ../../emacs/src/keyboard.c:1096
#19 0x011a636a in internal_condition_case (bfun=0x110b9dc <top_level_2>,
    handlers=9072, hfun=0x110b424 <cmd_error>) at ../../emacs/src/eval.c:1309
#20 0x0110ba3f in top_level_1 (ignore=0) at ../../emacs/src/keyboard.c:1104
#21 0x011a59fd in internal_catch (tag=24120, func=0x110ba01 <top_level_1>,
    arg=0) at ../../emacs/src/eval.c:1074
#22 0x0110b926 in command_loop () at ../../emacs/src/keyboard.c:1065
#23 0x0110af9f in recursive_edit_1 () at ../../emacs/src/keyboard.c:672
#24 0x0110b187 in Frecursive_edit () at ../../emacs/src/keyboard.c:743
#25 0x011090d9 in main (argc=2, argv=0x2610510)
    at ../../emacs/src/emacs.c:1667

[-- Attachment #3: 0001-Windows-98-and-NT4-compatibility-fixes.patch --]
[-- Type: text/plain, Size: 9090 bytes --]

From adaf947b7d045bbbc6b3fb7febd5e482abf0d28a Mon Sep 17 00:00:00 2001
From: Jussi Lahdenniemi <jussi@aprikoodi.fi>
Date: Thu, 14 Jan 2016 14:28:52 +0200
Subject: [PATCH] Windows 98 and NT4 compatibility fixes

* w32.h: Add the variable multiByteToWideCharFlags
* w32.c: MultiByteToWideChar flags conditional on OS
* w32fns.c: Ditto, plus call _resetstkovflw through
a function pointer
---
 src/w32.c    | 15 +++++++++++----
 src/w32.h    |  1 +
 src/w32fns.c | 39 +++++++++++++++++++++++----------------
 3 files changed, 35 insertions(+), 20 deletions(-)

diff --git a/src/w32.c b/src/w32.c
index 4770718..27a9fea 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -484,6 +484,7 @@ typedef DWORD (WINAPI *GetAdaptersInfo_Proc) (
 
 int (WINAPI *pMultiByteToWideChar)(UINT,DWORD,LPCSTR,int,LPWSTR,int);
 int (WINAPI *pWideCharToMultiByte)(UINT,DWORD,LPCWSTR,int,LPSTR,int,LPCSTR,LPBOOL);
+DWORD multiByteToWideCharFlags;
 
   /* ** A utility function ** */
 static BOOL
@@ -1550,7 +1551,7 @@ codepage_for_filenames (CPINFO *cp_info)
 int
 filename_to_utf16 (const char *fn_in, wchar_t *fn_out)
 {
-  int result = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, fn_in, -1,
+  int result = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, fn_in, -1,
 				     fn_out, MAX_PATH);
 
   if (!result)
@@ -1641,7 +1642,7 @@ filename_from_ansi (const char *fn_in, char *fn_out)
 {
   wchar_t fn_utf16[MAX_PATH];
   int codepage = codepage_for_filenames (NULL);
-  int result = pMultiByteToWideChar (codepage, MB_ERR_INVALID_CHARS, fn_in, -1,
+  int result = pMultiByteToWideChar (codepage, multiByteToWideCharFlags, fn_in, -1,
 				     fn_utf16, MAX_PATH);
 
   if (!result)
@@ -9081,13 +9082,13 @@ check_windows_init_file (void)
 		   "not unpacked properly.\nSee the README.W32 file in the "
 		   "top-level Emacs directory for more information.",
 		   init_file_name, load_path);
-	  needed = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, buffer,
+	  needed = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, buffer,
 					 -1, NULL, 0);
 	  if (needed > 0)
 	    {
 	      wchar_t *msg_w = alloca ((needed + 1) * sizeof (wchar_t));
 
-	      pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, buffer, -1,
+	      pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, buffer, -1,
 				    msg_w, needed);
 	      needed = pWideCharToMultiByte (CP_ACP, 0, msg_w, -1,
 					     NULL, 0, NULL, NULL);
@@ -9275,6 +9276,7 @@ maybe_load_unicows_dll (void)
 	    (MultiByteToWideChar_Proc)GetProcAddress (ret, "MultiByteToWideChar");
 	  pWideCharToMultiByte =
 	    (WideCharToMultiByte_Proc)GetProcAddress (ret, "WideCharToMultiByte");
+          multiByteToWideCharFlags = MB_ERR_INVALID_CHARS;
 	  return ret;
 	}
       else
@@ -9304,6 +9306,11 @@ maybe_load_unicows_dll (void)
 	 pointers; no need for the LoadLibrary dance.  */
       pMultiByteToWideChar = MultiByteToWideChar;
       pWideCharToMultiByte = WideCharToMultiByte;
+      /* On NT 4.0, though, MB_ERR_INVALID_CHARS is not supported.  */
+      if (w32_major_version < 5)
+        multiByteToWideCharFlags = 0;
+      else
+        multiByteToWideCharFlags = MB_ERR_INVALID_CHARS;
       return LoadLibrary ("Gdi32.dll");
     }
 }
diff --git a/src/w32.h b/src/w32.h
index 501056d..097241b 100644
--- a/src/w32.h
+++ b/src/w32.h
@@ -183,6 +183,7 @@ typedef int (WINAPI *MultiByteToWideChar_Proc)(UINT,DWORD,LPCSTR,int,LPWSTR,int)
 typedef int (WINAPI *WideCharToMultiByte_Proc)(UINT,DWORD,LPCWSTR,int,LPSTR,int,LPCSTR,LPBOOL);
 extern MultiByteToWideChar_Proc pMultiByteToWideChar;
 extern WideCharToMultiByte_Proc pWideCharToMultiByte;
+extern DWORD multiByteToWideCharFlags;
 
 extern void init_environment (char **);
 extern void check_windows_init_file (void);
diff --git a/src/w32fns.c b/src/w32fns.c
index f3806a9..3778557 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -6984,12 +6984,12 @@ value of DIR as in previous invocations; this is standard Windows behavior.  */)
 	    if (errno == ENOENT && filename_buf_w[MAX_PATH - 1] != 0)
 	      report_file_error ("filename too long", default_filename);
 	  }
-	len = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
+	len = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
 				    SSDATA (prompt), -1, NULL, 0);
 	if (len > 32768)
 	  len = 32768;
 	prompt_w = alloca (len * sizeof (wchar_t));
-	pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
+	pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
 			      SSDATA (prompt), -1, prompt_w, len);
       }
     else
@@ -7002,12 +7002,12 @@ value of DIR as in previous invocations; this is standard Windows behavior.  */)
 	    if (errno == ENOENT && filename_buf_a[MAX_PATH - 1] != 0)
 	      report_file_error ("filename too long", default_filename);
 	  }
-	len = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
+	len = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
 				    SSDATA (prompt), -1, NULL, 0);
 	if (len > 32768)
 	  len = 32768;
 	prompt_w = alloca (len * sizeof (wchar_t));
-	pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
+	pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
 			      SSDATA (prompt), -1, prompt_w, len);
 	len = pWideCharToMultiByte (CP_ACP, 0, prompt_w, -1, NULL, 0, NULL, NULL);
 	if (len > 32768)
@@ -7489,10 +7489,10 @@ a ShowWindow flag:
   current_dir = ENCODE_FILE (current_dir);
   /* Cannot use filename_to_utf16/ansi with DOCUMENT, since it could
      be a URL that is not limited to MAX_PATH chararcters.  */
-  doclen = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
+  doclen = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
 				 SSDATA (document), -1, NULL, 0);
   doc_w = xmalloc (doclen * sizeof (wchar_t));
-  pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
+  pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
 			SSDATA (document), -1, doc_w, doclen);
   if (use_unicode)
     {
@@ -7507,12 +7507,12 @@ a ShowWindow flag:
 	  int len;
 
 	  parameters = ENCODE_SYSTEM (parameters);
-	  len = pMultiByteToWideChar (CP_ACP, MB_ERR_INVALID_CHARS,
+	  len = pMultiByteToWideChar (CP_ACP, multiByteToWideCharFlags,
 				      SSDATA (parameters), -1, NULL, 0);
 	  if (len > 32768)
 	    len = 32768;
 	  params_w = alloca (len * sizeof (wchar_t));
-	  pMultiByteToWideChar (CP_ACP, MB_ERR_INVALID_CHARS,
+	  pMultiByteToWideChar (CP_ACP, multiByteToWideCharFlags,
 				SSDATA (parameters), -1, params_w, len);
 	  params_w[len - 1] = 0;
 	}
@@ -8959,7 +8959,7 @@ add_tray_notification (struct frame *f, const char *icon, const char *tip,
 	 later versions support up to 128.  */
       if (nidw.cbSize == MYNOTIFYICONDATAW_V1_SIZE)
 	{
-	  tiplen = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
+	  tiplen = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
 					 tip, utf8_mbslen_lim (tip, 63),
 					 tipw, 64);
 	  if (tiplen >= 63)
@@ -8967,7 +8967,7 @@ add_tray_notification (struct frame *f, const char *icon, const char *tip,
 	}
       else
 	{
-	  tiplen = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
+	  tiplen = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
 					 tip, utf8_mbslen_lim (tip, 127),
 					 tipw, 128);
 	  if (tiplen >= 127)
@@ -8986,7 +8986,7 @@ add_tray_notification (struct frame *f, const char *icon, const char *tip,
 	{
 	  int slen;
 
-	  slen = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
+	  slen = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
 					     msg, utf8_mbslen_lim (msg, 255),
 					     msgw, 256);
 	  if (slen >= 255)
@@ -8999,7 +8999,7 @@ add_tray_notification (struct frame *f, const char *icon, const char *tip,
 	    }
 	  wcscpy (nidw.szInfo, msgw);
 	  nidw.uTimeout = timeout;
-	  slen = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
+	  slen = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
 				       title, utf8_mbslen_lim (title, 63),
 				       titlew, 64);
 	  if (slen >= 63)
@@ -9670,6 +9670,11 @@ static PVOID except_addr;
 
 /* Stack overflow recovery.  */
 
+/* MinGW headers don't declare this (should be in malloc.h).  Also,
+   the function is not present pre-Win2000, so make the call through
+   a function pointer.  */
+typedef int (__cdecl *_resetstkoflw_proc) (void);
+
 /* Re-establish the guard page at stack limit.  This is needed because
    when a stack overflow is detected, Windows removes the guard bit
    from the guard page, so if we don't re-establish that protection,
@@ -9677,12 +9682,14 @@ static PVOID except_addr;
 void
 w32_reset_stack_overflow_guard (void)
 {
-  /* MinGW headers don't declare this (should be in malloc.h).  */
-  _CRTIMP int __cdecl _resetstkoflw (void);
-
+  static _resetstkoflw_proc resetstkoflw;
+  if (resetstkoflw == NULL)
+    resetstkoflw = (_resetstkoflw_proc)GetProcAddress (GetModuleHandle ("msvcrt.dll"),
+						       "_resetstkoflw");
   /* We ignore the return value.  If _resetstkoflw fails, the next
      stack overflow will crash the program.  */
-  (void)_resetstkoflw ();
+  if (resetstkoflw != NULL)
+    (void)resetstkoflw ();
 }
 
 static void
-- 
2.6.2


^ permalink raw reply related	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-14 12:49                 ` Jussi Lahdenniemi
@ 2016-01-14 17:10                   ` Jussi Lahdenniemi
  2016-01-14 18:07                     ` Eli Zaretskii
  2016-01-14 18:15                   ` Eli Zaretskii
  1 sibling, 1 reply; 63+ messages in thread
From: Jussi Lahdenniemi @ 2016-01-14 17:10 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 524 bytes --]

On 14.1.2016 14.49, Jussi Lahdenniemi wrote:
> My keyboard hooking code works on NT4 as well (although not on console
> mode due to the lack of the GetConsoleWindow function - I'll try to find
> a workaround for this).

Here is the (once more) finalized patch, with the above mentioned 
workaround for NT4.  This has now been tested successfully as a 32-bit 
build on NT4, Win2k, Win7 and Win10, and as a 64-bit build on Win7 and 
Win10, both in windowed and console (-nw) mode on all the platforms.

-- 
Jussi Lahdenniemi


[-- Attachment #2: 0001-Implementation-of-a-Windows-keyboard-hook.patch --]
[-- Type: text/plain, Size: 36483 bytes --]

From 55789efca3eaba68550a36d93a6540e630836bbb Mon Sep 17 00:00:00 2001
From: Jussi Lahdenniemi <jussi@aprikoodi.fi>
Date: Wed, 13 Jan 2016 11:57:35 +0200
Subject: [PATCH] Implementation of a Windows keyboard hook

The Windows keyboard hooking code properly grabs system hotkeys such as Win-*
and Alt-Tab for Emacs use.  The new code replaces the w32-register-hot-key
functionality for NT based OSes (not Windows 98/ME).  The hooking code works
for both windowed and console (emacs -nw) mode.

* src/w32term.h: Add new function prototypes
* src/w32fns.c: Main location for new functionality
* src/w32console.c: Update to support hooking for console Emacs
* src/w32inevt.c: Ditto
* doc/emacs/msdos.texi: Documentation update
---
 doc/emacs/msdos.texi |  81 +++++---
 src/w32console.c     |   3 +
 src/w32fns.c         | 543 +++++++++++++++++++++++++++++++++++++++++++++++----
 src/w32inevt.c       |  20 +-
 src/w32term.h        |   6 +
 5 files changed, 582 insertions(+), 71 deletions(-)

diff --git a/doc/emacs/msdos.texi b/doc/emacs/msdos.texi
index ea8a24d..854d65f 100644
--- a/doc/emacs/msdos.texi
+++ b/doc/emacs/msdos.texi
@@ -507,32 +507,64 @@ Windows Keyboard
 @findex w32-register-hot-key
 @findex w32-unregister-hot-key
   MS-Windows reserves certain key combinations, such as
-@kbd{@key{Alt}-@key{TAB}}, for its own use.  These key combinations are
-intercepted by the system before Emacs can see them.  You can use the
-@code{w32-register-hot-key} function to allow a key sequence to be
-seen by Emacs instead of being grabbed by Windows.  This function
-registers a key sequence as a @dfn{hot key}, overriding the special
-meaning of that key sequence for Windows.  (MS-Windows is told that
-the key sequence is a hot key only when one of the Emacs windows has
-focus, so that the special keys still have their usual meaning for
-other Windows applications.)
-
-  The argument to @code{w32-register-hot-key} must be a single key,
-with or without modifiers, in vector form that would be acceptable to
-@code{define-key}.  The meta modifier is interpreted as the @key{Alt}
-key if @code{w32-alt-is-meta} is @code{t} (the default), and the hyper
-modifier is always interpreted as the Windows key (usually labeled
-with @key{start} and the Windows logo).  If the function succeeds in
-registering the key sequence, it returns the hotkey ID, a number;
-otherwise it returns @code{nil}.
+@kbd{@key{Alt}-@key{TAB}} and a number of Windows key combinations,
+for its own use.  These key combinations are intercepted by the system
+before Emacs can see them.  Also, on Windows 10, all Windows key
+combinations are reserved by the system in such a way that they are
+never propagated to applications, even if the system does not
+currently define a hotkey on the specific combination.  You can use
+the @code{w32-register-hot-key} function to allow a key sequence to be
+seen by Emacs instead of being grabbed by Windows.  When registered as
+a hot key, the key combination is pulled out of the system's input
+queue before it is handled by Windows, effectively overriding the
+special meaning of that key sequence for Windows.  The override is
+only effective when Emacs is active; with other applications on the
+foreground the keys behave normally.
+
+  The argument to @code{w32-register-hot-key} must be a single key with a
+single modifier, in vector form that would be acceptable to
+@code{define-key}.  The control and shift modifiers have no effect on the
+argument.  The meta modifier is interpreted as the @key{Alt} key if
+@code{w32-alt-is-meta} is @code{t} (the default), and the super and hyper
+modifiers are interpreted according to the bindings of
+@code{w32-lwindow-modifier} and @code{w32-rwindow-modifier}.  Additionally, a
+modifier with the trailing dash but with no key indicates that all
+Windows defined hotkeys for that modifier are to be overridden in the
+favor of Emacs.
 
 @kindex M-TAB@r{, (MS-Windows)}
 @cindex @kbd{M-@key{TAB}} vs @kbd{@key{Alt}-@key{TAB}} (MS-Windows)
 @cindex @kbd{@key{Alt}-@key{TAB}} vs @kbd{M-@key{TAB}} (MS-Windows)
   For example, @code{(w32-register-hot-key [M-tab])} lets you use
-@kbd{M-@key{TAB}} normally in Emacs; for instance, to complete the word or
-symbol at point at top level, or to complete the current search string
-against previously sought strings during incremental search.
+@kbd{M-@key{TAB}} normally in Emacs; for instance, to complete the
+word or symbol at point at top level, or to complete the current
+search string against previously sought strings during incremental
+search.  @code{(w32-register-hot-key [s-])} with
+@code{w32-lwindow-modifier} bound to @code{super} disables all the
+Windows' own Windows key based shortcuts.@footnote{There is one known
+exception: The combination @kbd{@key{Windows}-@key{L}} that locks the
+workstation is handled by the system on a lower level.  For this
+reason, @code{w32-register-hot-key} cannot override this key
+combination - it always locks the computer.}
+
+  Note that @code{w32-register-hot-key} checks the
+@code{w32-[lr]window-modifier} values at the time of the function
+call.  Thus, you can set @code{w32-lwindow-modifier} as @code{super},
+then call @code{(w32-register-hot-key [s-r])}, and finally set
+@code{w32-rwindow-modifier} as @code{super} as well.  The result is
+that the left Windows key together with @key{R} invokes whichever
+function you have bound for the combination in Emacs, and the right
+Windows key and @key{R} opens the Windows @code{Run} dialog.
+
+  The hotkey registrations always also include all the shift and
+control modifier combinations for the given hotkey; that is,
+registering @kbd{s-@key{a}} as a hotkey gives you @kbd{S-s-@key{a}},
+@kbd{C-s-@key{a}} and @kbd{C-S-s-@key{a}} as well.
+
+  On Windows 98 and ME, the hotkey registration is more restricted.
+The desired hotkey must always be fully specified, and
+@code{w32-phantom-key-code} can be customized to achieve desired
+results.
 
   The function @code{w32-unregister-hot-key} reverses the effect of
 @code{w32-register-hot-key} for its argument key sequence.
@@ -607,12 +639,7 @@ Windows Keyboard
 otherwise it is passed to Windows.  The default is @code{t} for both
 of these variables.  Passing each of these keys to Windows produces
 its normal effect: for example, @kbd{@key{Lwindow}} opens the
-@code{Start} menu, etc.@footnote{
-Some combinations of the ``Windows'' keys with other keys are caught
-by Windows at a low level in a way that Emacs currently cannot prevent.
-For example, @kbd{@key{Lwindow} r} always pops up the Windows
-@samp{Run} dialog.  Customizing the value of
-@code{w32-phantom-key-code} might help in some cases, though.}
+@code{Start} menu, etc.
 
 @vindex w32-recognize-altgr
 @kindex AltGr @r{(MS-Windows)}
diff --git a/src/w32console.c b/src/w32console.c
index 6277f13..fdadd48 100644
--- a/src/w32console.c
+++ b/src/w32console.c
@@ -759,6 +759,9 @@ initialize_w32_display (struct terminal *term, int *width, int *height)
 
   /* Setup w32_display_info structure for this frame. */
   w32_initialize_display_info (build_string ("Console"));
+
+  /* Set up the keyboard hook.  */
+  setup_w32_kbdhook ();
 }
 
 
diff --git a/src/w32fns.c b/src/w32fns.c
index 3778557..80bcebe 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -20,6 +20,9 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 /* Added by Kevin Gallo */
 
 #include <config.h>
+/* Override API version to get the latest functionality.  */
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0600
 
 #include <signal.h>
 #include <stdio.h>
@@ -41,6 +44,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "coding.h"
 
 #include "w32common.h"
+#include "w32inevt.h"
 
 #ifdef WINDOWSNT
 #include <mbstring.h>
@@ -52,6 +56,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "w32.h"
 #endif
 
+#include <basetyps.h>
+#include <unknwn.h>
 #include <commctrl.h>
 #include <commdlg.h>
 #include <shellapi.h>
@@ -251,6 +257,38 @@ HINSTANCE hinst = NULL;
 static unsigned int sound_type = 0xFFFFFFFF;
 #define MB_EMACS_SILENT (0xFFFFFFFF - 1)
 
+/* Special virtual key code for indicating "any" key.  */
+#define VK_ANY 0xFF
+
+#ifndef WM_WTSSESSION_CHANGE
+/* 32-bit MinGW does not define these constants.  */
+# define WM_WTSSESSION_CHANGE  0x02B1
+# define WTS_SESSION_LOCK      0x7
+#endif
+
+/* Keyboard hook state data.  */
+static struct
+{
+  int hook_count; /* counter, if several windows are created */
+  HHOOK hook;     /* hook handle */
+  HWND console;   /* console window handle */
+
+  int lwindown;      /* Left Windows key currently pressed (and hooked) */
+  int rwindown;      /* Right Windows key currently pressed (and hooked) */
+  int winsdown;      /* Number of handled keys currently pressed */
+  int send_win_up;   /* Pass through the keyup for this Windows key press? */
+  int suppress_lone; /* Suppress simulated Windows keydown-keyup for this press? */
+  int winseen;       /* Windows keys seen during this press? */
+
+  char alt_hooked[256];  /* hook Alt+[this key]? */
+  char lwin_hooked[256]; /* hook left Win+[this key]? */
+  char rwin_hooked[256]; /* hook right Win+[this key]? */
+} kbdhook;
+typedef HWND (WINAPI *GetConsoleWindow_Proc) (void);
+
+/* stdin, from w32console.c */
+extern HANDLE keyboard_handle;
+
 /* Let the user specify a display with a frame.
    nil stands for the selected frame--or, if that is not a w32 frame,
    the first display on the list.  */
@@ -2074,6 +2112,338 @@ my_post_msg (W32Msg * wmsg, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
   post_msg (wmsg);
 }
 
+/* The Windows keyboard hook callback.  */
+static LRESULT CALLBACK funhook (int code, WPARAM w, LPARAM l)
+{
+  INPUT inputs[2];
+  HWND focus = GetFocus ();
+  int console = 0;
+  KBDLLHOOKSTRUCT const *hs = (KBDLLHOOKSTRUCT*)l;
+
+  if (code < 0 || (hs->flags & LLKHF_INJECTED))
+    return CallNextHookEx (0, code, w, l);
+
+  /* The keyboard hook sees keyboard input on all processes (except
+     elevated ones, when Emacs itself is not elevated).  As such,
+     care must be taken to only filter out keyboard input when Emacs
+     itself is on the foreground.
+
+     GetFocus returns a non-NULL window if another application is active,
+     and always for a console Emacs process.  For a console Emacs, determine
+     focus by checking if the current foreground window is the process's
+     console window.  */
+  if (focus == NULL && kbdhook.console != NULL)
+    {
+      if (GetForegroundWindow () == kbdhook.console)
+	{
+	  focus = kbdhook.console;
+	  console = 1;
+	}
+    }
+
+  /* First, check hooks for the left and right Windows keys.  */
+  if (hs->vkCode == VK_LWIN || hs->vkCode == VK_RWIN)
+    {
+      if (focus != NULL && (w == WM_KEYDOWN || w == WM_SYSKEYDOWN))
+	{
+	  /* The key is being pressed in an Emacs window.  */
+	  if (hs->vkCode == VK_LWIN && !kbdhook.lwindown)
+	    {
+	      kbdhook.lwindown = 1;
+	      kbdhook.winseen = 1;
+	      kbdhook.winsdown++;
+	    }
+	  else if (hs->vkCode == VK_RWIN && !kbdhook.rwindown)
+	    {
+	      kbdhook.rwindown = 1;
+	      kbdhook.winseen = 1;
+	      kbdhook.winsdown++;
+	    }
+	  /* Returning 1 here drops the keypress without further processing.
+	     If the keypress was allowed to go through, the normal Windows
+	     hotkeys would take over.  */
+	  return 1;
+	}
+      else if (kbdhook.winsdown > 0 && (w == WM_KEYUP || w == WM_SYSKEYUP))
+	{
+	  /* A key that has been captured earlier is being released now.  */
+	  if (hs->vkCode == VK_LWIN && kbdhook.lwindown)
+	    {
+	      kbdhook.lwindown = 0;
+	      kbdhook.winsdown--;
+	    }
+	  else if (hs->vkCode == VK_RWIN && kbdhook.rwindown)
+	    {
+	      kbdhook.rwindown = 0;
+	      kbdhook.winsdown--;
+	    }
+	  if (kbdhook.winsdown == 0 && kbdhook.winseen)
+	    {
+	      if (!kbdhook.suppress_lone)
+	        {
+		  /* The Windows key was pressed, then released,
+		     without any other key pressed simultaneously.
+		     Normally, this opens the Start menu, but the user
+		     can prevent this by setting the
+		     w32-pass-[lr]window-to-system variable to
+		     NIL.  */
+		  if (hs->vkCode == VK_LWIN && !NILP (Vw32_pass_lwindow_to_system) ||
+		      hs->vkCode == VK_RWIN && !NILP (Vw32_pass_rwindow_to_system))
+		    {
+		      /* Not prevented - Simulate the keypress to the system.  */
+		      memset (inputs, 0, sizeof (inputs));
+		      inputs[0].type = INPUT_KEYBOARD;
+		      inputs[0].ki.wVk = hs->vkCode;
+		      inputs[0].ki.wScan = hs->vkCode;
+		      inputs[0].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
+		      inputs[0].ki.time = 0;
+		      inputs[1].type = INPUT_KEYBOARD;
+		      inputs[1].ki.wVk = hs->vkCode;
+		      inputs[1].ki.wScan = hs->vkCode;
+		      inputs[1].ki.dwFlags = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
+		      inputs[1].ki.time = 0;
+		      SendInput (2, inputs, sizeof (INPUT));
+		    }
+		  else if (focus != NULL)
+		    {
+		      /* When not passed to system, must simulate privately to Emacs.	 */
+		      PostMessage (focus, WM_SYSKEYDOWN, hs->vkCode, 0);
+		      PostMessage (focus, WM_SYSKEYUP, hs->vkCode, 0);
+		    }
+		}
+	    }
+	  if (kbdhook.winsdown == 0)
+	    {
+	      /* No Windows keys pressed anymore - clear the state flags.  */
+	      kbdhook.suppress_lone = 0;
+	      kbdhook.winseen = 0;
+	    }
+	  if (!kbdhook.send_win_up)
+	    {
+	      /* Swallow this release message, as not to confuse applications who
+		 did not get to see the original WM_KEYDOWN message either.  */
+	      return 1;
+	    }
+	  kbdhook.send_win_up = 0;
+	}
+    }
+  else if (kbdhook.winsdown > 0)
+    {
+      /* Some other key was pressed while a captured Win key is down.
+	 This is either an Emacs registered hotkey combination, or a
+	 system hotkey.	 */
+      if (kbdhook.lwindown && kbdhook.lwin_hooked[hs->vkCode] ||
+	  kbdhook.rwindown && kbdhook.rwin_hooked[hs->vkCode])
+	{
+	  /* Hooked Win-x combination, do not pass the keypress to Windows.  */
+	  kbdhook.suppress_lone = 1;
+	}
+      else if (!kbdhook.suppress_lone)
+	{
+	  /* Unhooked S-x combination; simulate the combination now
+	     (will be seen by the system).  */
+	  memset (inputs, 0, sizeof (inputs));
+	  inputs[0].type = INPUT_KEYBOARD;
+	  inputs[0].ki.wVk = kbdhook.lwindown ? VK_LWIN : VK_RWIN;
+	  inputs[0].ki.wScan = kbdhook.lwindown ? VK_LWIN : VK_RWIN;
+	  inputs[0].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
+	  inputs[0].ki.time = 0;
+	  inputs[1].type = INPUT_KEYBOARD;
+	  inputs[1].ki.wVk = hs->vkCode;
+	  inputs[1].ki.wScan = hs->scanCode;
+	  inputs[1].ki.dwFlags = (hs->flags & LLKHF_EXTENDED) ? KEYEVENTF_EXTENDEDKEY : 0;
+	  inputs[1].ki.time = 0;
+	  SendInput (2, inputs, sizeof (INPUT));
+	  /* Stop processing of this Win sequence here; the
+	     corresponding keyup messages will come through the normal
+	     channel when the keys are released.  */
+	  kbdhook.suppress_lone = 1;
+	  kbdhook.send_win_up = 1;
+	  /* Swallow the original keypress (as we want the Win key
+	     down message simulated above to precede this real message).  */
+	  return 1;
+	}
+    }
+
+  /* Next, handle the registered Alt-* combinations.  */
+  if ((w == WM_SYSKEYDOWN || w == WM_KEYDOWN) &&
+      kbdhook.alt_hooked[hs->vkCode] &&
+      focus != NULL &&
+      (GetAsyncKeyState (VK_MENU) & 0x8000))
+    {
+      /* Prevent the system from getting this Alt-* key - suppress the
+	 message and post as a normal keypress to Emacs.  */
+      if (console)
+	{
+	  INPUT_RECORD rec;
+	  DWORD n;
+	  rec.EventType = KEY_EVENT;
+	  rec.Event.KeyEvent.bKeyDown = TRUE;
+	  rec.Event.KeyEvent.wVirtualKeyCode = hs->vkCode;
+	  rec.Event.KeyEvent.wVirtualScanCode = hs->scanCode;
+	  rec.Event.KeyEvent.uChar.UnicodeChar = 0;
+	  rec.Event.KeyEvent.dwControlKeyState =
+	    ((GetAsyncKeyState (VK_LMENU) & 0x8000) ? LEFT_ALT_PRESSED : 0) |
+	    ((GetAsyncKeyState (VK_RMENU) & 0x8000) ? RIGHT_ALT_PRESSED : 0) |
+	    ((GetAsyncKeyState (VK_LCONTROL) & 0x8000) ? LEFT_CTRL_PRESSED : 0) |
+	    ((GetAsyncKeyState (VK_RCONTROL) & 0x8000) ? RIGHT_CTRL_PRESSED : 0) |
+	    ((GetAsyncKeyState (VK_SHIFT) & 0x8000) ? SHIFT_PRESSED : 0) |
+	    ((hs->flags & LLKHF_EXTENDED) ? ENHANCED_KEY : 0);
+	  if (w32_console_unicode_input)
+	    WriteConsoleInputW (keyboard_handle, &rec, 1, &n);
+	  else
+	    WriteConsoleInputA (keyboard_handle, &rec, 1, &n);
+	}
+      else
+	PostMessage (focus, w, hs->vkCode, 1 | (1<<29));
+      return 1;
+    }
+
+  /* The normal case - pass the message through.  */
+  return CallNextHookEx (0, code, w, l);
+}
+
+/* Set up the hook; can be called several times, with matching
+   remove_w32_kbdhook calls.  */
+void setup_w32_kbdhook (void)
+{
+  kbdhook.hook_count++;
+
+  /* Hooking is only available on NT architecture systems, as
+     indicated by the w32_kbdhook_active variable.  */
+  if (kbdhook.hook_count == 1 && w32_kbdhook_active)
+    {
+      /* Get the handle of the Emacs console window.  As the
+	 GetConsoleWindow function is only available on Win2000+, a
+	 hackish workaround described in Microsoft KB article 124103
+	 (https://support.microsoft.com/en-us/kb/124103) is used for
+	 NT 4 systems.  */
+      GetConsoleWindow_Proc get_console = (GetConsoleWindow_Proc)
+	GetProcAddress (GetModuleHandle ("kernel32.dll"), "GetConsoleWindow");
+
+      if (get_console != NULL)
+	kbdhook.console = get_console();
+      else
+        {
+	  GUID guid;
+	  wchar_t *oldTitle = malloc (1024 * sizeof(wchar_t));
+	  wchar_t newTitle[64];
+	  int i;
+
+	  CoCreateGuid (&guid);
+	  StringFromGUID2 (&guid, newTitle, 64);
+	  if (newTitle != NULL)
+	    {
+	      GetConsoleTitleW (oldTitle, 1024);
+	      SetConsoleTitleW (newTitle);
+	      for (i = 0; i < 25; i++)
+	        {
+		  Sleep (40);
+		  kbdhook.console = FindWindowW (NULL, newTitle);
+		  if (kbdhook.console != NULL)
+		    break;
+		}
+	      SetConsoleTitleW (oldTitle);
+	    }
+	  free (oldTitle);
+	}
+
+      /* Set the hook.  */
+      kbdhook.hook = SetWindowsHookEx (WH_KEYBOARD_LL, funhook, GetModuleHandle(NULL), 0);
+    }
+}
+
+/* Remove the hook.  */
+void remove_w32_kbdhook (void)
+{
+  kbdhook.hook_count--;
+  if (kbdhook.hook_count == 0 && w32_kbdhook_active)
+    {
+      UnhookWindowsHookEx( kbdhook.hook );
+      kbdhook.hook = NULL;
+    }
+}
+
+/* Mark a specific key combination as hooked, preventing it to be
+   handled by the system.  */
+void hook_w32_key (int hook, int modifier, int vkey)
+{
+  char *tbl = NULL;
+
+  switch (modifier)
+    {
+    case VK_MENU:
+      tbl = kbdhook.alt_hooked;
+      break;
+    case VK_LWIN:
+      tbl = kbdhook.lwin_hooked;
+      break;
+    case VK_RWIN:
+      tbl = kbdhook.rwin_hooked;
+      break;
+    }
+
+  if (tbl != NULL && vkey >= 0 && vkey <= 255)
+    {
+       /* VK_ANY hooks all keys for this modifier */
+       if (vkey == VK_ANY)
+	 memset (tbl, (char)hook, 256);
+       else
+	 tbl[vkey] = (char)hook;
+       /* Alt-<modifier>s should go through */
+       kbdhook.alt_hooked[VK_MENU] = 0;
+       kbdhook.alt_hooked[VK_LMENU] = 0;
+       kbdhook.alt_hooked[VK_RMENU] = 0;
+       kbdhook.alt_hooked[VK_CONTROL] = 0;
+       kbdhook.alt_hooked[VK_LCONTROL] = 0;
+       kbdhook.alt_hooked[VK_RCONTROL] = 0;
+       kbdhook.alt_hooked[VK_SHIFT] = 0;
+       kbdhook.alt_hooked[VK_LSHIFT] = 0;
+       kbdhook.alt_hooked[VK_RSHIFT] = 0;
+    }
+}
+
+/* Check the current Win key pressed state.  */
+int check_w32_winkey_state (int vkey)
+{
+  /* The hook code handles grabbing of the Windows keys and Alt-* key
+     combinations reserved by the system.  Handling Alt is a bit
+     easier, as Windows intends Alt-* shortcuts for application use in
+     Windows; hotkeys such as Alt-tab and Alt-escape are special
+     cases.  Win-* hotkeys, on the other hand, are primarily meant for
+     system use.
+
+     As a result, when we want Emacs to be able to grab the Win-*
+     keys, we must swallow all Win key presses in a low-level keyboard
+     hook.  Unfortunately, this means that the Emacs window procedure
+     (and console input handler) never see the keypresses either.
+     Thus, to check the modifier states properly, Emacs code must use
+     the check_w32_winkey_state function that uses the flags directly
+     updated by the hook callback.  */
+  switch (vkey)
+    {
+    case VK_LWIN:
+      return kbdhook.lwindown;
+    case VK_RWIN:
+      return kbdhook.rwindown;
+    }
+  return 0;
+}
+
+/* Resets the keyboard hook state.  Locking the workstation with Win-L
+   leaves the Win key(s) "down" from the hook's point of view - the
+   keyup event is never seen.  Thus, this function must be called when
+   the system is locked.  */
+void reset_w32_kbdhook_state (void)
+{
+  kbdhook.lwindown = 0;
+  kbdhook.rwindown = 0;
+  kbdhook.winsdown = 0;
+  kbdhook.send_win_up = 0;
+  kbdhook.suppress_lone = 0;
+  kbdhook.winseen = 0;
+}
+
 /* GetKeyState and MapVirtualKey on Windows 95 do not actually distinguish
    between left and right keys as advertised.  We test for this
    support dynamically, and set a flag when the support is absent.  If
@@ -2248,6 +2618,10 @@ modifier_set (int vkey)
       else
 	return (GetKeyState (vkey) & 0x1);
     }
+  if (w32_kbdhook_active && (vkey == VK_LWIN || vkey == VK_RWIN))
+    {
+      return check_w32_winkey_state (vkey);
+    }
 
   if (!modifiers_recorded)
     return (GetKeyState (vkey) & 0x8000);
@@ -2390,7 +2764,9 @@ map_keypad_keys (unsigned int virt_key, unsigned int extended)
 /* List of special key combinations which w32 would normally capture,
    but Emacs should grab instead.  Not directly visible to lisp, to
    simplify synchronization.  Each item is an integer encoding a virtual
-   key code and modifier combination to capture.  */
+   key code and modifier combination to capture.
+   Note: This code is not used if keyboard hooks are active
+   (Windows 2000 and later).  */
 static Lisp_Object w32_grabbed_keys;
 
 #define HOTKEY(vk, mods)      make_number (((vk) & 255) | ((mods) << 8))
@@ -3440,7 +3816,7 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
       switch (wParam)
 	{
 	case VK_LWIN:
-	  if (NILP (Vw32_pass_lwindow_to_system))
+	  if (!w32_kbdhook_active && 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
@@ -3459,7 +3835,7 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 	    return 0;
 	  break;
 	case VK_RWIN:
-	  if (NILP (Vw32_pass_rwindow_to_system))
+	  if (!w32_kbdhook_active && NILP (Vw32_pass_rwindow_to_system))
 	    {
 	      if (GetAsyncKeyState (wParam) & 1)
 		{
@@ -4316,10 +4692,12 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
     case WM_SETFOCUS:
       dpyinfo->faked_key = 0;
       reset_modifiers ();
-      register_hot_keys (hwnd);
+      if (!w32_kbdhook_active)
+	register_hot_keys (hwnd);
       goto command;
     case WM_KILLFOCUS:
-      unregister_hot_keys (hwnd);
+      if (!w32_kbdhook_active)
+	unregister_hot_keys (hwnd);
       button_state = 0;
       ReleaseCapture ();
       /* Relinquish the system caret.  */
@@ -4348,10 +4726,20 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
       goto dflt;
 
+    case WM_CREATE:
+      setup_w32_kbdhook ();
+      goto dflt;
+
     case WM_DESTROY:
+      remove_w32_kbdhook ();
       CoUninitialize ();
       return 0;
 
+    case WM_WTSSESSION_CHANGE:
+      if (wParam == WTS_SESSION_LOCK)
+        reset_w32_kbdhook_state ();
+      goto dflt;
+
     case WM_CLOSE:
       wmsg.dwModifiers = w32_get_modifiers ();
       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
@@ -7617,19 +8005,34 @@ lookup_vk_code (char *key)
 	&& strcmp (lispy_function_keys[i], key) == 0)
       return i;
 
+  if (w32_kbdhook_active)
+    {
+      /* alphanumerics map to themselves */
+      if (key[1] == 0)
+      {
+	if (key[0] >= 'A' && key[0] <= 'Z' ||
+	    key[0] >= '0' && key[0] <= '9')
+	  return key[0];
+	if (key[0] >= 'a' && key[0] <= 'z')
+	  return toupper(key[0]);
+      }
+    }
+
   return -1;
 }
 
 /* Convert a one-element vector style key sequence to a hot key
    definition.  */
 static Lisp_Object
-w32_parse_hot_key (Lisp_Object key)
+w32_parse_and_hook_hot_key (Lisp_Object key, int hook)
 {
   /* Copied from Fdefine_key and store_in_keymap.  */
   register Lisp_Object c;
   int vk_code;
   int lisp_modifiers;
   int w32_modifiers;
+  Lisp_Object res = Qnil;
+  char* vkname;
 
   CHECK_VECTOR (key);
 
@@ -7652,7 +8055,12 @@ w32_parse_hot_key (Lisp_Object key)
       c = Fcar (c);
       if (!SYMBOLP (c))
 	emacs_abort ();
-      vk_code = lookup_vk_code (SSDATA (SYMBOL_NAME (c)));
+      vkname = SSDATA (SYMBOL_NAME (c));
+      /* [s-], [M-], [h-]: Register all keys for this modifier */
+      if (w32_kbdhook_active && vkname[0] == 0)
+        vk_code = VK_ANY;
+      else
+        vk_code = lookup_vk_code (vkname);
     }
   else if (INTEGERP (c))
     {
@@ -7676,34 +8084,70 @@ w32_parse_hot_key (Lisp_Object key)
 #define MOD_WIN         0x0008
 #endif
 
-  /* Convert lisp modifiers to Windows hot-key form.  */
-  w32_modifiers  = (lisp_modifiers & hyper_modifier)    ? MOD_WIN : 0;
-  w32_modifiers |= (lisp_modifiers & alt_modifier)      ? MOD_ALT : 0;
-  w32_modifiers |= (lisp_modifiers & ctrl_modifier)     ? MOD_CONTROL : 0;
-  w32_modifiers |= (lisp_modifiers & shift_modifier)    ? MOD_SHIFT : 0;
+  if (w32_kbdhook_active)
+    {
+      /* Register Alt-x combinations */
+      if (lisp_modifiers & alt_modifier)
+        {
+          hook_w32_key (hook, VK_MENU, vk_code);
+          res = Qt;
+        }
+      /* Register Win-x combinations based on modifier mappings */
+      if ((lisp_modifiers & hyper_modifier) && EQ (Vw32_lwindow_modifier, Qhyper) ||
+          (lisp_modifiers & super_modifier) && EQ (Vw32_lwindow_modifier, Qsuper))
+        {
+          hook_w32_key (hook, VK_LWIN, vk_code);
+          res = Qt;
+        }
+      if ((lisp_modifiers & hyper_modifier) && EQ (Vw32_rwindow_modifier, Qhyper) ||
+          (lisp_modifiers & super_modifier) && EQ (Vw32_rwindow_modifier, Qsuper))
+        {
+          hook_w32_key (hook, VK_RWIN, vk_code);
+          res = Qt;
+        }
+      return res;
+    }
+  else
+    {
+      /* Convert lisp modifiers to Windows hot-key form.  */
+      w32_modifiers  = (lisp_modifiers & hyper_modifier)    ? MOD_WIN : 0;
+      w32_modifiers |= (lisp_modifiers & alt_modifier)      ? MOD_ALT : 0;
+      w32_modifiers |= (lisp_modifiers & ctrl_modifier)     ? MOD_CONTROL : 0;
+      w32_modifiers |= (lisp_modifiers & shift_modifier)    ? MOD_SHIFT : 0;
 
-  return HOTKEY (vk_code, w32_modifiers);
+      return HOTKEY (vk_code, w32_modifiers);
+    }
 }
 
 DEFUN ("w32-register-hot-key", Fw32_register_hot_key,
        Sw32_register_hot_key, 1, 1, 0,
        doc: /* Register KEY as a hot-key combination.
-Certain key combinations like Alt-Tab are reserved for system use on
-Windows, and therefore are normally intercepted by the system.  However,
-most of these key combinations can be received by registering them as
-hot-keys, overriding their special meaning.
-
-KEY must be a one element key definition in vector form that would be
-acceptable to `define-key' (e.g. [A-tab] for Alt-Tab).  The meta
-modifier is interpreted as Alt if `w32-alt-is-meta' is t, and hyper
-is always interpreted as the Windows modifier keys.
-
-The return value is the hotkey-id if registered, otherwise nil.  */)
+Certain key combinations like Alt-Tab and Win-R are reserved for
+system use on Windows, and therefore are normally intercepted by the
+system.  These key combinations can be received by registering them
+as hot-keys, except for Win-L which always locks the computer.
+
+On Windows 98 and ME, KEY must be a one element key definition in
+vector form that would be acceptable to `define-key' (e.g. [A-tab] for
+Alt-Tab).  The meta modifier is interpreted as Alt if
+`w32-alt-is-meta' is t, and hyper is always interpreted as the Windows
+modifier keys.  The return value is the hotkey-id if registered, otherwise nil.
+
+On other Windows versions, KEY can also be specified as [M-], [s-] or
+[h-] to indicate that all combinations of that key should be processed
+by Emacs instead of the operating system.  The super and hyper
+modifiers are interpreted according to the current values of
+`w32-lwindow-modifier` and `w32-rwindow-modifier`.  For instance,
+setting `w32-lwindow-modifier` to `super` and then calling
+`(register-hot-key [s-])` grabs all combinations of the left Windows
+key to Emacs, but leaves the right Windows key free for the operating
+system keyboard shortcuts.  The return value is t if the call affected
+any key combinations, otherwise nil.  */)
   (Lisp_Object key)
 {
-  key = w32_parse_hot_key (key);
+  key = w32_parse_and_hook_hot_key (key, 1);
 
-  if (!NILP (key) && NILP (Fmemq (key, w32_grabbed_keys)))
+  if (!w32_kbdhook_active && !NILP (key) && NILP (Fmemq (key, w32_grabbed_keys)))
     {
       /* Reuse an empty slot if possible.  */
       Lisp_Object item = Fmemq (Qnil, w32_grabbed_keys);
@@ -7731,7 +8175,10 @@ DEFUN ("w32-unregister-hot-key", Fw32_unregister_hot_key,
   Lisp_Object item;
 
   if (!INTEGERP (key))
-    key = w32_parse_hot_key (key);
+    key = w32_parse_and_hook_hot_key (key, 0);
+
+  if (w32_kbdhook_active)
+    return key;
 
   item = Fmemq (key, w32_grabbed_keys);
 
@@ -9338,11 +9785,15 @@ When non-nil, the Start menu is opened by tapping the key.
 If you set this to nil, the left \"Windows\" key is processed by Emacs
 according to the value of `w32-lwindow-modifier', which see.
 
-Note that some combinations of the left \"Windows\" key with other keys are
-caught by Windows at low level, and so binding them in Emacs will have no
-effect.  For example, <lwindow>-r always pops up the Windows Run dialog,
-<lwindow>-<Pause> pops up the "System Properties" dialog, etc.  However, see
-the doc string of `w32-phantom-key-code'.  */);
+Note that some combinations of the left \"Windows\" key with other
+keys are caught by Windows at low level.  For example, <lwindow>-r
+pops up the Windows Run dialog, <lwindow>-<Pause> pops up the "System
+Properties" dialog, etc.  On Windows 10, no \"Windows\" key
+combinations are normally handed to applications.  To enable Emacs to
+process \"Windows\" key combinations, use the function
+`w32-register-hot-key`.
+
+For Windows 98/ME, see the doc string of `w32-phantom-key-code'.  */);
   Vw32_pass_lwindow_to_system = Qt;
 
   DEFVAR_LISP ("w32-pass-rwindow-to-system",
@@ -9353,11 +9804,15 @@ When non-nil, the Start menu is opened by tapping the key.
 If you set this to nil, the right \"Windows\" key is processed by Emacs
 according to the value of `w32-rwindow-modifier', which see.
 
-Note that some combinations of the right \"Windows\" key with other keys are
-caught by Windows at low level, and so binding them in Emacs will have no
-effect.  For example, <rwindow>-r always pops up the Windows Run dialog,
-<rwindow>-<Pause> pops up the "System Properties" dialog, etc.  However, see
-the doc string of `w32-phantom-key-code'.  */);
+Note that some combinations of the right \"Windows\" key with other
+keys are caught by Windows at low level.  For example, <rwindow>-r
+pops up the Windows Run dialog, <rwindow>-<Pause> pops up the "System
+Properties" dialog, etc.  On Windows 10, no \"Windows\" key
+combinations are normally handed to applications.  To enable Emacs to
+process \"Windows\" key combinations, use the function
+`w32-register-hot-key`.
+
+For Windows 98/ME, see the doc string of `w32-phantom-key-code'.  */);
   Vw32_pass_rwindow_to_system = Qt;
 
   DEFVAR_LISP ("w32-phantom-key-code",
@@ -9367,7 +9822,11 @@ Value is a number between 0 and 255.
 
 Phantom key presses are generated in order to stop the system from
 acting on \"Windows\" key events when `w32-pass-lwindow-to-system' or
-`w32-pass-rwindow-to-system' is nil.  */);
+`w32-pass-rwindow-to-system' is nil.
+
+This variable is only used on Windows 98 and ME.  For other Windows
+versions, see the documentation of the `w32-register-hot-key`
+function.  */);
   /* Although 255 is technically not a valid key code, it works and
      means that this hack won't interfere with any real key code.  */
   XSETINT (Vw32_phantom_key_code, 255);
@@ -9397,7 +9856,9 @@ Any other value will cause the Scroll Lock key to be ignored.  */);
 	       doc: /* Modifier to use for the left \"Windows\" key.
 The value can be hyper, super, meta, alt, control or shift for the
 respective modifier, or nil to appear as the `lwindow' key.
-Any other value will cause the key to be ignored.  */);
+Any other value will cause the key to be ignored.
+
+Also see the documentation of the `w32-register-hot-key` function.  */);
   Vw32_lwindow_modifier = Qnil;
 
   DEFVAR_LISP ("w32-rwindow-modifier",
@@ -9405,7 +9866,9 @@ Any other value will cause the key to be ignored.  */);
 	       doc: /* Modifier to use for the right \"Windows\" key.
 The value can be hyper, super, meta, alt, control or shift for the
 respective modifier, or nil to appear as the `rwindow' key.
-Any other value will cause the key to be ignored.  */);
+Any other value will cause the key to be ignored.
+
+Also see the documentation of the `w32-register-hot-key` function.  */);
   Vw32_rwindow_modifier = Qnil;
 
   DEFVAR_LISP ("w32-apps-modifier",
diff --git a/src/w32inevt.c b/src/w32inevt.c
index 54b0b13..80f9067 100644
--- a/src/w32inevt.c
+++ b/src/w32inevt.c
@@ -41,6 +41,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "termchar.h"	/* for Mouse_HLInfo, tty_display_info */
 #include "w32term.h"
 #include "w32inevt.h"
+#include "w32common.h"
 
 /* stdin, from w32console.c */
 extern HANDLE keyboard_handle;
@@ -148,10 +149,12 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
       switch (event->wVirtualKeyCode)
 	{
 	case VK_LWIN:
-	  mod_key_state &= ~LEFT_WIN_PRESSED;
+          if (!w32_kbdhook_active)
+            mod_key_state &= ~LEFT_WIN_PRESSED;
 	  break;
 	case VK_RWIN:
-	  mod_key_state &= ~RIGHT_WIN_PRESSED;
+          if (!w32_kbdhook_active)
+            mod_key_state &= ~RIGHT_WIN_PRESSED;
 	  break;
 	case VK_APPS:
 	  mod_key_state &= ~APPS_PRESSED;
@@ -185,7 +188,8 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
 	      keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
 	    }
 	}
-      mod_key_state |= LEFT_WIN_PRESSED;
+      if (!w32_kbdhook_active)
+        mod_key_state |= LEFT_WIN_PRESSED;
       if (!NILP (Vw32_lwindow_modifier))
 	return 0;
       break;
@@ -201,7 +205,8 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
 	      keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
 	    }
 	}
-      mod_key_state |= RIGHT_WIN_PRESSED;
+      if (!w32_kbdhook_active)
+        mod_key_state |= RIGHT_WIN_PRESSED;
       if (!NILP (Vw32_rwindow_modifier))
 	return 0;
       break;
@@ -267,6 +272,13 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
 
   /* Recognize state of Windows and Apps keys.  */
   event->dwControlKeyState |= mod_key_state;
+  if (w32_kbdhook_active)
+    {
+      if (check_w32_winkey_state (VK_LWIN))
+        event->dwControlKeyState |= LEFT_WIN_PRESSED;
+      if (check_w32_winkey_state (VK_RWIN))
+        event->dwControlKeyState |= RIGHT_WIN_PRESSED;
+    }
 
   /* Distinguish numeric keypad keys from extended keys.  */
   event->wVirtualKeyCode =
diff --git a/src/w32term.h b/src/w32term.h
index 5090624..6139414 100644
--- a/src/w32term.h
+++ b/src/w32term.h
@@ -738,6 +738,12 @@ extern int handle_file_notifications (struct input_event *);
 extern void w32_initialize_display_info (Lisp_Object);
 extern void initialize_w32_display (struct terminal *, int *, int *);
 
+/* Keyboard hooks.  */
+extern void setup_w32_kbdhook (void);
+extern void remove_w32_kbdhook (void);
+extern int check_w32_winkey_state (int vkey);
+#define w32_kbdhook_active (os_subtype != OS_9X)
+
 /* Keypad command key support.  W32 doesn't have virtual keys defined
    for the function keys on the keypad (they are mapped to the standard
    function keys), so we define our own.  */
-- 
2.6.2


^ permalink raw reply related	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-14 17:10                   ` Jussi Lahdenniemi
@ 2016-01-14 18:07                     ` Eli Zaretskii
  0 siblings, 0 replies; 63+ messages in thread
From: Eli Zaretskii @ 2016-01-14 18:07 UTC (permalink / raw)
  To: Jussi Lahdenniemi; +Cc: emacs-devel

> Cc: emacs-devel@gnu.org
> From: Jussi Lahdenniemi <jussi@aprikoodi.fi>
> Date: Thu, 14 Jan 2016 19:10:26 +0200
> 
> On 14.1.2016 14.49, Jussi Lahdenniemi wrote:
> > My keyboard hooking code works on NT4 as well (although not on console
> > mode due to the lack of the GetConsoleWindow function - I'll try to find
> > a workaround for this).
> 
> Here is the (once more) finalized patch, with the above mentioned 
> workaround for NT4.  This has now been tested successfully as a 32-bit 
> build on NT4, Win2k, Win7 and Win10, and as a 64-bit build on Win7 and 
> Win10, both in windowed and console (-nw) mode on all the platforms.

Thanks.  I guess we are now waiting for your legal paperwork to come
through.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-14 12:49                 ` Jussi Lahdenniemi
  2016-01-14 17:10                   ` Jussi Lahdenniemi
@ 2016-01-14 18:15                   ` Eli Zaretskii
  2016-01-15  6:56                     ` Jussi Lahdenniemi
  2016-01-16  9:58                     ` Eli Zaretskii
  1 sibling, 2 replies; 63+ messages in thread
From: Eli Zaretskii @ 2016-01-14 18:15 UTC (permalink / raw)
  To: Jussi Lahdenniemi; +Cc: emacs-devel

> Cc: emacs-devel@gnu.org
> From: Jussi Lahdenniemi <jussi@aprikoodi.fi>
> Date: Thu, 14 Jan 2016 14:49:31 +0200
> 
> On 13.1.2016 17.57, Eli Zaretskii wrote:
> > If you can see in GDB where does this come from and show the
> > backtrace, that would be great.  Failing that, let's leave Windows 9X
> > testing alone for a while (you can always test the fallback code by
> > forcefully failing one of the run-time tests for the newer versions)
> > and test only on W2K.  We can return to the 9X problem later.
> 
> I was able to get a GDB dump of this, after installing MinGW from 2009. 
> The backtrace is attached.

Looks like it's unable to create a buffer.  Hmm...

If you can spare some time to try debugging this with me, please file
a bug report about this problem with "M-x report-emacs-bug", and let's
take it up there.  The first thing I'd like to know is what buffer is
that (I'm guessing *scratch* or *Messages*), and what is the value of
'a' in this call frame:

  #4  0x01103082 in make_lisp_ptr (ptr=0x2a3da84, type=Lisp_Vectorlike)
      at ../../emacs/src/lisp.h:1110

One of the major changes since Emacs 24.5 is that we allocate memory
in a completely different manner, using VirtualAlloc directly for
buffer text and HeapAlloc for everything else (see w32heap.c).
Perhaps some of that doesn't work on Windows 9X?

> I investigated the problem and found out that it resulted from NT4's 
> MultiByteToWideChar function not supporting the MB_ERR_INVALID_CHARS 
> flags.  I made the flag conditional on the OS version, after which Emacs 
> runs just fine on NT4.  I'm attaching a patch that contains this fix, 
> and the conditional use of _resetstkoflw (which is also not supported on 
> NT4) as well.

Thanks, I will push these to the emacs-25 branch soon.

> Also, I noticed that addpm.exe fails to load on a out-of-the-box NT4SP6, 
> due to its dependency to a Shell32.dll version that ships with IE4. 
> After installing IE4, addpm works.  It's worth noting that directly 
> installing IE6 on NT4 does NOT make addpm functional, as IE6 does not 
> contain the shell update.

Thanks, I will mention this in some place, although addpm is
semi-obsolescent nowadays.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-14 18:15                   ` Eli Zaretskii
@ 2016-01-15  6:56                     ` Jussi Lahdenniemi
  2016-01-15  7:52                       ` Jussi Lahdenniemi
  2016-01-16  9:58                     ` Eli Zaretskii
  1 sibling, 1 reply; 63+ messages in thread
From: Jussi Lahdenniemi @ 2016-01-15  6:56 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

On 14.1.2016 20.15, Eli Zaretskii wrote:
> If you can spare some time to try debugging this with me, please file
> a bug report about this problem with "M-x report-emacs-bug", and let's
> take it up there.

OK, I did that.  If you like to continue the debugging on that thread, 
feel free to reply there!

> The first thing I'd like to know is what buffer is
> that (I'm guessing *scratch* or *Messages*), and what is the value of
> 'a' in this call frame:

the value of the name variable in the Fget_buffer_create function is " 
*load*", and a in frame #4 is 0x02a22101.

The tag seems to indicate 'a' being a Lisp_Misc object, but the memory 
dump on that does not quite match:

(gdb) x/4xw 0x2a22100
0x2a22100:  0x0181826c  0x00000000  0x018b6d5c  0x00000000

More to the point, 'a' seems to be a Lisp_Misc pointer to 'b'+4 in 
Fget_buffer_create:

(gdb) up
#5  0x01130714 in Fget_buffer_create ...
(gdb) print b
$3 = (struct buffer *) 0x2a220fc

-- 
Jussi Lahdenniemi




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-15  6:56                     ` Jussi Lahdenniemi
@ 2016-01-15  7:52                       ` Jussi Lahdenniemi
  2016-01-15  8:08                         ` Windows 9X crash (was: [PATCH] Override Windows default Win-* key combinations when using Emacs) Eli Zaretskii
  2016-01-15  9:23                         ` [PATCH] Override Windows default Win-* key combinations when using Emacs Yuri Khan
  0 siblings, 2 replies; 63+ messages in thread
From: Jussi Lahdenniemi @ 2016-01-15  7:52 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

On 15.1.2016 8.56, Jussi Lahdenniemi wrote:
>> The first thing I'd like to know is what buffer is
>> that (I'm guessing *scratch* or *Messages*), and what is the value of
>> 'a' in this call frame:
>
> the value of the name variable in the Fget_buffer_create function is "
> *load*", and a in frame #4 is 0x02a22101.

Ah, of course; when allocating 'b' in Fget_buffer_create, Emacs got the 
pointer 0x...fc, which is NOT aligned at an 8-byte boundary as required 
by USE_LSB_TAG.  This messes up the tags and causes the crash.

So, apparently, on Windows 98 HeapAlloc does not guarantee 8-byte 
alignment of memory.  Not that this would be documented anywhere...

How should we fix this?  I can write and test the fix, but I'd like to 
hear your opinion on the preferred mechanism.

-- 
Jussi Lahdenniemi





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Windows 9X crash (was: [PATCH] Override Windows default Win-* key combinations when using Emacs)
  2016-01-15  7:52                       ` Jussi Lahdenniemi
@ 2016-01-15  8:08                         ` Eli Zaretskii
  2016-01-15  9:35                           ` Windows 9X crash Jussi Lahdenniemi
  2016-01-15  9:47                           ` Windows 9X crash (was: [PATCH] Override Windows default Win-* key combinations when using Emacs) Fabrice Popineau
  2016-01-15  9:23                         ` [PATCH] Override Windows default Win-* key combinations when using Emacs Yuri Khan
  1 sibling, 2 replies; 63+ messages in thread
From: Eli Zaretskii @ 2016-01-15  8:08 UTC (permalink / raw)
  To: Jussi Lahdenniemi, Fabrice Popineau; +Cc: emacs-devel

(Adding Fabrice, who wrote the new allocator code, to the discussion.)

> Cc: emacs-devel@gnu.org
> From: Jussi Lahdenniemi <jussi@aprikoodi.fi>
> Date: Fri, 15 Jan 2016 09:52:38 +0200
> 
> On 15.1.2016 8.56, Jussi Lahdenniemi wrote:
> >> The first thing I'd like to know is what buffer is
> >> that (I'm guessing *scratch* or *Messages*), and what is the value of
> >> 'a' in this call frame:
> >
> > the value of the name variable in the Fget_buffer_create function is "
> > *load*", and a in frame #4 is 0x02a22101.
> 
> Ah, of course; when allocating 'b' in Fget_buffer_create, Emacs got the 
> pointer 0x...fc, which is NOT aligned at an 8-byte boundary as required 
> by USE_LSB_TAG.  This messes up the tags and causes the crash.
>
> So, apparently, on Windows 98 HeapAlloc does not guarantee 8-byte 
> alignment of memory.  Not that this would be documented anywhere...

Right, this can explain everything.  It probably means that a build
configured --with-wide-int should also be tested there, as it has
different alignment needs.

> How should we fix this?  I can write and test the fix, but I'd like to 
> hear your opinion on the preferred mechanism.

What fix did you have in mind?  Over-allocating and recording the
offset in the initial part of the block that we don't pass to the
application?



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-15  7:52                       ` Jussi Lahdenniemi
  2016-01-15  8:08                         ` Windows 9X crash (was: [PATCH] Override Windows default Win-* key combinations when using Emacs) Eli Zaretskii
@ 2016-01-15  9:23                         ` Yuri Khan
  1 sibling, 0 replies; 63+ messages in thread
From: Yuri Khan @ 2016-01-15  9:23 UTC (permalink / raw)
  To: Jussi Lahdenniemi; +Cc: Eli Zaretskii, Emacs developers

On Fri, Jan 15, 2016 at 1:52 PM, Jussi Lahdenniemi <jussi@aprikoodi.fi> wrote:

> So, apparently, on Windows 98 HeapAlloc does not guarantee 8-byte alignment
> of memory.  Not that this would be documented anywhere...

By the Rules As Written, absence of a documented minimum alignment
should be interpreted as permission for the implementation to return
any unaligned addresses.

In practice, a particular implementation of HeapAlloc is likely to
satisfy the requirements of C’s malloc and C++’s operator new, which
guarantee alignment suitable for any object.

On a 32-bit x86 system, 4-byte alignment is not strictly required for
32-bit quantities, but gives a performance benefit, so HeapAlloc is
likely to yield 4-byte-aligned blocks.

> How should we fix this?  I can write and test the fix, but I'd like to hear
> your opinion on the preferred mechanism.

I have seen one library implement an aligned allocator this way:

* When a block of size N aligned to A bytes is requested, allocate an
unaligned block of size N + sizeof(void*) + (A - 1). Let’s call its
starting address P. Calculate the result address P' as (P +
sizeof(void*) + (A - 1)) & ~(A - 1). Store the value of P at address
P' - sizeof(void*). Return P'.

* When the aligned block at address P' is freed and P' is not null,
read the pointer value P from address P' - sizeof(void*). Free the
unaligned block starting at P.

(Obviously this scheme is not particularly efficient for small allocations.)



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Windows 9X crash
  2016-01-15  8:08                         ` Windows 9X crash (was: [PATCH] Override Windows default Win-* key combinations when using Emacs) Eli Zaretskii
@ 2016-01-15  9:35                           ` Jussi Lahdenniemi
  2016-01-15 10:18                             ` Eli Zaretskii
  2016-01-15  9:47                           ` Windows 9X crash (was: [PATCH] Override Windows default Win-* key combinations when using Emacs) Fabrice Popineau
  1 sibling, 1 reply; 63+ messages in thread
From: Jussi Lahdenniemi @ 2016-01-15  9:35 UTC (permalink / raw)
  To: Eli Zaretskii, Fabrice Popineau; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 866 bytes --]

On 15.1.2016 10.08, Eli Zaretskii wrote:
> Right, this can explain everything.  It probably means that a build
> configured --with-wide-int should also be tested there, as it has
> different alignment needs.

I'll test that as well, then.

>> How should we fix this?  I can write and test the fix, but I'd like to
>> hear your opinion on the preferred mechanism.
>
> What fix did you have in mind?  Over-allocating and recording the
> offset in the initial part of the block that we don't pass to the
> application?

That was my first idea, yes.  Of course, this introduces some memory 
overhead, especially if there are many small allocations.

A proposal patch is attached.  Reallocs needed some additional care, as 
there are two special cases to handle (source being in dumped memory, 
and source and destination alignments mismatching).

-- 
Jussi Lahdenniemi


[-- Attachment #2: win98-heap-fix.diff --]
[-- Type: text/plain, Size: 3478 bytes --]

diff --git a/nt/inc/ms-w32.h b/nt/inc/ms-w32.h
index cdbfac0..a37510e 100644
--- a/nt/inc/ms-w32.h
+++ b/nt/inc/ms-w32.h
@@ -457,6 +457,10 @@ extern void *malloc_after_dump(size_t);
 extern void *realloc_after_dump(void *, size_t);
 extern void free_after_dump(void *);
 
+extern void *malloc_after_dump_9x(size_t);
+extern void *realloc_after_dump_9x(void *, size_t);
+extern void free_after_dump_9x(void *);
+
 extern malloc_fn the_malloc_fn;
 extern realloc_fn the_realloc_fn;
 extern free_fn the_free_fn;
diff --git a/src/w32heap.c b/src/w32heap.c
index 54646bf..3f6ed67 100644
--- a/src/w32heap.c
+++ b/src/w32heap.c
@@ -258,9 +258,18 @@ init_heap (void)
 	}
 #endif
 
-      the_malloc_fn = malloc_after_dump;
-      the_realloc_fn = realloc_after_dump;
-      the_free_fn = free_after_dump;
+      if (os_subtype == OS_9X)
+        {
+          the_malloc_fn = malloc_after_dump_9x;
+          the_realloc_fn = realloc_after_dump_9x;
+          the_free_fn = free_after_dump_9x;
+        }
+      else
+        {
+          the_malloc_fn = malloc_after_dump;
+          the_realloc_fn = realloc_after_dump;
+          the_free_fn = free_after_dump;
+        }
     }
   else
     {
@@ -291,9 +300,18 @@ init_heap (void)
 	  exit (-1);
 	}
       heap = s_pfn_Rtl_Create_Heap (0, data_region_base, 0, 0, NULL, &params);
-      the_malloc_fn = malloc_before_dump;
-      the_realloc_fn = realloc_before_dump;
-      the_free_fn = free_before_dump;
+
+      if (os_subtype == OS_9X)
+        {
+          fprintf (stderr, "Cannot run pre-dump Emacs on Windows 9X.\n" );
+          exit (-1);
+        }
+      else
+        {
+          the_malloc_fn = malloc_before_dump;
+          the_realloc_fn = realloc_before_dump;
+          the_free_fn = free_before_dump;
+        }
     }
 
   /* Update system version information to match current system.  */
@@ -504,6 +522,65 @@ free_before_dump (void *ptr)
     }
 }
 
+/* On Windows 98, HeapAlloc may return pointers that are not aligned
+   to 8-byte boundary, which is expected by the Lisp memory
+   management.  To circumvent this problem, manually enforce alignment
+   on Windows 9X.  */
+
+void *
+malloc_after_dump_9x (size_t size)
+{
+  void *p = malloc_after_dump (size + 8);
+  void *pa;
+  if (p == NULL)
+    return p;
+  pa = (void*)(((intptr_t)p + 8) & ~7);
+  *((void**)pa-1) = p;
+  return pa;
+}
+
+void *
+realloc_after_dump_9x (void *ptr, size_t size)
+{
+  if (FREEABLE_P (ptr))
+    {
+      void *po = *((void**)ptr-1);
+      void *p;
+      void *pa;
+      p = realloc_after_dump (po, size + 8);
+      if (p == NULL)
+        return p;
+      pa = (void*)(((intptr_t)p + 8) & ~7);
+      if (ptr != NULL &&
+          (char*)pa - (char*)p != (char*)ptr - (char*)po)
+        {
+          /* Handle the case where alignment in pre-realloc and
+             post-realloc blocks do not match.  */
+          MoveMemory (pa, (void*)((char*)p + ((char*)ptr - (char*)po)), size);
+        }
+      *((void**)pa-1) = p;
+      return pa;
+    }
+  else
+    {
+      /* Non-freeable pointers have no alignment-enforcing header
+         (since dumping is not allowed on Windows 9X).  */
+      void* p = malloc_after_dump_9x (size);
+      if (p != NULL)
+	CopyMemory (p, ptr, size);
+      return p;
+    }
+}
+
+void
+free_after_dump_9x (void *ptr)
+{
+  if (FREEABLE_P (ptr))
+    {
+      free_after_dump (*((void**)ptr-1));
+    }
+}
+
 #ifdef ENABLE_CHECKING
 void
 report_temacs_memory_usage (void)

^ permalink raw reply related	[flat|nested] 63+ messages in thread

* Re: Windows 9X crash (was: [PATCH] Override Windows default Win-* key combinations when using Emacs)
  2016-01-15  8:08                         ` Windows 9X crash (was: [PATCH] Override Windows default Win-* key combinations when using Emacs) Eli Zaretskii
  2016-01-15  9:35                           ` Windows 9X crash Jussi Lahdenniemi
@ 2016-01-15  9:47                           ` Fabrice Popineau
  2016-01-15  9:56                             ` Windows 9X crash Jussi Lahdenniemi
  1 sibling, 1 reply; 63+ messages in thread
From: Fabrice Popineau @ 2016-01-15  9:47 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Jussi Lahdenniemi, Emacs developers

[-- Attachment #1: Type: text/plain, Size: 1727 bytes --]

Hi,

Strange that HeapAlloc() returns 4-byte aligned blocks and that is not
documented.
I used to have MSDN cdroms from that time
I would write a small program doing random allocation
and checking the alignment of the blocks returned.
Just to make sure that the problem does not lie elsewhere (?)

Fabrice

2016-01-15 9:08 GMT+01:00 Eli Zaretskii <eliz@gnu.org>:

> (Adding Fabrice, who wrote the new allocator code, to the discussion.)
>
> > Cc: emacs-devel@gnu.org
> > From: Jussi Lahdenniemi <jussi@aprikoodi.fi>
> > Date: Fri, 15 Jan 2016 09:52:38 +0200
> >
> > On 15.1.2016 8.56, Jussi Lahdenniemi wrote:
> > >> The first thing I'd like to know is what buffer is
> > >> that (I'm guessing *scratch* or *Messages*), and what is the value of
> > >> 'a' in this call frame:
> > >
> > > the value of the name variable in the Fget_buffer_create function is "
> > > *load*", and a in frame #4 is 0x02a22101.
> >
> > Ah, of course; when allocating 'b' in Fget_buffer_create, Emacs got the
> > pointer 0x...fc, which is NOT aligned at an 8-byte boundary as required
> > by USE_LSB_TAG.  This messes up the tags and causes the crash.
> >
> > So, apparently, on Windows 98 HeapAlloc does not guarantee 8-byte
> > alignment of memory.  Not that this would be documented anywhere...
>
> Right, this can explain everything.  It probably means that a build
> configured --with-wide-int should also be tested there, as it has
> different alignment needs.
>
> > How should we fix this?  I can write and test the fix, but I'd like to
> > hear your opinion on the preferred mechanism.
>
> What fix did you have in mind?  Over-allocating and recording the
> offset in the initial part of the block that we don't pass to the
> application?
>

[-- Attachment #2: Type: text/html, Size: 2418 bytes --]

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Windows 9X crash
  2016-01-15  9:47                           ` Windows 9X crash (was: [PATCH] Override Windows default Win-* key combinations when using Emacs) Fabrice Popineau
@ 2016-01-15  9:56                             ` Jussi Lahdenniemi
  2016-01-15 10:19                               ` Eli Zaretskii
  0 siblings, 1 reply; 63+ messages in thread
From: Jussi Lahdenniemi @ 2016-01-15  9:56 UTC (permalink / raw)
  To: Fabrice Popineau, Eli Zaretskii; +Cc: Emacs developers

On 15.1.2016 11.47, Fabrice Popineau wrote:
> Strange that HeapAlloc() returns 4-byte aligned blocks and that is not
> documented.
> I used to have MSDN cdroms from that time
> I would write a small program doing random allocation
> and checking the alignment of the blocks returned.
> Just to make sure that the problem does not lie elsewhere (?)

Emacs served well as the "small" program, and yes, HeapAlloc returned 
addresses that were 4-byte-aligned but not 8-byte-aligned.  Fixing the 
alignment did make Emacs run smoothly, so alignment was indeed the problem.

I have now also tested the --with-wide-int build and it seems to work 
correctly as well.

-- 
Jussi Lahdenniemi





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Windows 9X crash
  2016-01-15  9:35                           ` Windows 9X crash Jussi Lahdenniemi
@ 2016-01-15 10:18                             ` Eli Zaretskii
  2016-01-15 10:31                               ` Fabrice Popineau
  2016-01-15 10:33                               ` Jussi Lahdenniemi
  0 siblings, 2 replies; 63+ messages in thread
From: Eli Zaretskii @ 2016-01-15 10:18 UTC (permalink / raw)
  To: Jussi Lahdenniemi; +Cc: fabrice.popineau, emacs-devel

> Cc: emacs-devel@gnu.org
> From: Jussi Lahdenniemi <jussi@aprikoodi.fi>
> Date: Fri, 15 Jan 2016 11:35:20 +0200
> 
> > What fix did you have in mind?  Over-allocating and recording the
> > offset in the initial part of the block that we don't pass to the
> > application?
> 
> That was my first idea, yes.  Of course, this introduces some memory 
> overhead, especially if there are many small allocations.
> 
> A proposal patch is attached.  Reallocs needed some additional care, as 
> there are two special cases to handle (source being in dumped memory, 
> and source and destination alignments mismatching).

Thanks.  Fabrice, any comments to the patch?

I think the 9X-specific code should be #ifdef'ed away in 64-bit
builds, is that right?  The alignment code and the "p - 1" stuff is
wrong for 64-bit code anyway, I think.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Windows 9X crash
  2016-01-15  9:56                             ` Windows 9X crash Jussi Lahdenniemi
@ 2016-01-15 10:19                               ` Eli Zaretskii
  0 siblings, 0 replies; 63+ messages in thread
From: Eli Zaretskii @ 2016-01-15 10:19 UTC (permalink / raw)
  To: Jussi Lahdenniemi; +Cc: fabrice.popineau, emacs-devel

> Cc: Emacs developers <emacs-devel@gnu.org>
> From: Jussi Lahdenniemi <jussi@aprikoodi.fi>
> Date: Fri, 15 Jan 2016 11:56:34 +0200
> 
> I have now also tested the --with-wide-int build and it seems to work 
> correctly as well.

Great, thanks for testing.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Windows 9X crash
  2016-01-15 10:18                             ` Eli Zaretskii
@ 2016-01-15 10:31                               ` Fabrice Popineau
  2016-01-15 10:33                               ` Jussi Lahdenniemi
  1 sibling, 0 replies; 63+ messages in thread
From: Fabrice Popineau @ 2016-01-15 10:31 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Jussi Lahdenniemi, Emacs developers

[-- Attachment #1: Type: text/plain, Size: 703 bytes --]

2016-01-15 11:18 GMT+01:00 Eli Zaretskii <eliz@gnu.org>:

> > Cc: emacs-devel@gnu.org
> > From: Jussi Lahdenniemi <jussi@aprikoodi.fi>
> > Date: Fri, 15 Jan 2016 11:35:20 +0200
> >
>
> > A proposal patch is attached.  Reallocs needed some additional care, as
> > there are two special cases to handle (source being in dumped memory,
> > and source and destination alignments mismatching).
>
> Thanks.  Fabrice, any comments to the patch?
>
> I think the 9X-specific code should be #ifdef'ed away in 64-bit
> builds, is that right?  The alignment code and the "p - 1" stuff is
> wrong for 64-bit code anyway, I think.
>

I think it would be better, yes. Anyway, a 64 bit build won't run on W98.

Fabrice

[-- Attachment #2: Type: text/html, Size: 1316 bytes --]

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Windows 9X crash
  2016-01-15 10:18                             ` Eli Zaretskii
  2016-01-15 10:31                               ` Fabrice Popineau
@ 2016-01-15 10:33                               ` Jussi Lahdenniemi
  2016-01-16  9:15                                 ` Eli Zaretskii
  1 sibling, 1 reply; 63+ messages in thread
From: Jussi Lahdenniemi @ 2016-01-15 10:33 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: fabrice.popineau, emacs-devel

On 15.1.2016 12.18, Eli Zaretskii wrote:
> I think the 9X-specific code should be #ifdef'ed away in 64-bit
> builds, is that right?  The alignment code and the "p - 1" stuff is
> wrong for 64-bit code anyway, I think.

It can be #ifdef'd away if wanted, but it's not used on 64-bit OSes 
anyway (due to the "if (os_subtype == OS_9X)" in init_heap), and it's 
not causing any warnings or errors in the 64-bit build process.

Of course, should Microsoft release a 64-bit version of the Windows 9X 
family appear on the market, then the code would be broken :)

The "p-1" stuff would not be broken for a 64-bit Windows 98, though; the 
"+8"s would (they should be "+12" to ensure enough room for 64-bit 
void*s).  But then again, the theoretical 64-bit Windows 98 would most 
probably HeapAllocate on 8-byte boundaries - and in that case, the code 
would work perfectly as-is.

-- 
Jussi Lahdenniemi





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Windows 9X crash
  2016-01-15 10:33                               ` Jussi Lahdenniemi
@ 2016-01-16  9:15                                 ` Eli Zaretskii
  0 siblings, 0 replies; 63+ messages in thread
From: Eli Zaretskii @ 2016-01-16  9:15 UTC (permalink / raw)
  To: Jussi Lahdenniemi; +Cc: fabrice.popineau, emacs-devel

> Cc: fabrice.popineau@gmail.com, emacs-devel@gnu.org
> From: Jussi Lahdenniemi <jussi@aprikoodi.fi>
> Date: Fri, 15 Jan 2016 12:33:23 +0200
> 
> On 15.1.2016 12.18, Eli Zaretskii wrote:
> > I think the 9X-specific code should be #ifdef'ed away in 64-bit
> > builds, is that right?  The alignment code and the "p - 1" stuff is
> > wrong for 64-bit code anyway, I think.
> 
> It can be #ifdef'd away if wanted, but it's not used on 64-bit OSes 
> anyway (due to the "if (os_subtype == OS_9X)" in init_heap), and it's 
> not causing any warnings or errors in the 64-bit build process.
> 
> Of course, should Microsoft release a 64-bit version of the Windows 9X 
> family appear on the market, then the code would be broken :)
> 
> The "p-1" stuff would not be broken for a 64-bit Windows 98, though; the 
> "+8"s would (they should be "+12" to ensure enough room for 64-bit 
> void*s).  But then again, the theoretical 64-bit Windows 98 would most 
> probably HeapAllocate on 8-byte boundaries - and in that case, the code 
> would work perfectly as-is.

OK, I pushed the patch to the emacs-25 branch.  Thanks.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-14 18:15                   ` Eli Zaretskii
  2016-01-15  6:56                     ` Jussi Lahdenniemi
@ 2016-01-16  9:58                     ` Eli Zaretskii
  2016-01-16 11:00                       ` Jussi Lahdenniemi
  1 sibling, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2016-01-16  9:58 UTC (permalink / raw)
  To: jussi; +Cc: emacs-devel

> Date: Thu, 14 Jan 2016 20:15:56 +0200
> From: Eli Zaretskii <eliz@gnu.org>
> Cc: emacs-devel@gnu.org
> 
> > I investigated the problem and found out that it resulted from NT4's 
> > MultiByteToWideChar function not supporting the MB_ERR_INVALID_CHARS 
> > flags.  I made the flag conditional on the OS version, after which Emacs 
> > runs just fine on NT4.  I'm attaching a patch that contains this fix, 
> > and the conditional use of _resetstkoflw (which is also not supported on 
> > NT4) as well.
> 
> Thanks, I will push these to the emacs-25 branch soon.

Done now.

Note one gotcha with calling functions that might not be available at
run time: you cannot rely on a static function pointer to be NULL when
Emacs starts.  That's because when Emacs is dumped, the value of the
pointer from the system where Emacs is built is (or could be) recorded
in the dumped binary, and is non-NULL.  So you must explicitly zero it
out every Emacs startup; see the various globals_of_w32* functions
which do this for several such pointers.  I added a line to reset the
resetstkovflw pointer when Emacs starts.

> > Also, I noticed that addpm.exe fails to load on a out-of-the-box NT4SP6, 
> > due to its dependency to a Shell32.dll version that ships with IE4. 
> > After installing IE4, addpm works.  It's worth noting that directly 
> > installing IE6 on NT4 does NOT make addpm functional, as IE6 does not 
> > contain the shell update.
> 
> Thanks, I will mention this in some place, although addpm is
> semi-obsolescent nowadays.

Added an entry in etc/PROBLEMS about this.

Thanks.

P.S. These patches all but exhaust your grace limit of contributed
code we can accept without your assigning copyright, so I hope your
legal paperwork is well under way, and we will be able to accept your
contributions soon.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-16  9:58                     ` Eli Zaretskii
@ 2016-01-16 11:00                       ` Jussi Lahdenniemi
  2016-01-16 11:41                         ` Eli Zaretskii
  2016-02-03 13:59                         ` Jussi Lahdenniemi
  0 siblings, 2 replies; 63+ messages in thread
From: Jussi Lahdenniemi @ 2016-01-16 11:00 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

On 16.1.2016 11.58, Eli Zaretskii wrote:
>> Thanks, I will push these to the emacs-25 branch soon.
>
> Done now.

Thanks!

> Note one gotcha with calling functions that might not be available at
> run time: you cannot rely on a static function pointer to be NULL when
> Emacs starts.  That's because when Emacs is dumped, the value of the
> pointer from the system where Emacs is built is (or could be) recorded
> in the dumped binary, and is non-NULL.  So you must explicitly zero it
> out every Emacs startup; see the various globals_of_w32* functions
> which do this for several such pointers.  I added a line to reset the
> resetstkovflw pointer when Emacs starts.

Oh, of course.  Didn't think about that.  Thanks!

> P.S. These patches all but exhaust your grace limit of contributed
> code we can accept without your assigning copyright, so I hope your
> legal paperwork is well under way, and we will be able to accept your
> contributions soon.

My paperwork went into an extra round this week, as I had signed the 
first set of papers with a date in 2015.  I expect the new set to reach 
FSF during the next week, if the mail is as quick this time as it was 
with the first set.

-- 
Jussi Lahdenniemi





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-16 11:00                       ` Jussi Lahdenniemi
@ 2016-01-16 11:41                         ` Eli Zaretskii
  2016-02-03 13:59                         ` Jussi Lahdenniemi
  1 sibling, 0 replies; 63+ messages in thread
From: Eli Zaretskii @ 2016-01-16 11:41 UTC (permalink / raw)
  To: Jussi Lahdenniemi; +Cc: emacs-devel

> Cc: emacs-devel@gnu.org
> From: Jussi Lahdenniemi <jussi@aprikoodi.fi>
> Date: Sat, 16 Jan 2016 13:00:35 +0200
> 
> > P.S. These patches all but exhaust your grace limit of contributed
> > code we can accept without your assigning copyright, so I hope your
> > legal paperwork is well under way, and we will be able to accept your
> > contributions soon.
> 
> My paperwork went into an extra round this week, as I had signed the 
> first set of papers with a date in 2015.  I expect the new set to reach 
> FSF during the next week, if the mail is as quick this time as it was 
> with the first set.

Thanks.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-01-16 11:00                       ` Jussi Lahdenniemi
  2016-01-16 11:41                         ` Eli Zaretskii
@ 2016-02-03 13:59                         ` Jussi Lahdenniemi
  2016-02-03 15:42                           ` Eli Zaretskii
  1 sibling, 1 reply; 63+ messages in thread
From: Jussi Lahdenniemi @ 2016-02-03 13:59 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

> On 16.1.2016 11.58, Eli Zaretskii wrote:
>> P.S. These patches all but exhaust your grace limit of contributed
>> code we can accept without your assigning copyright, so I hope your
>> legal paperwork is well under way, and we will be able to accept your
>> contributions soon.

I just got notified by FSF that my paperwork is complete.

-- 
Jussi Lahdenniemi





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-02-03 13:59                         ` Jussi Lahdenniemi
@ 2016-02-03 15:42                           ` Eli Zaretskii
  2016-02-26 10:55                             ` Eli Zaretskii
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2016-02-03 15:42 UTC (permalink / raw)
  To: Jussi Lahdenniemi; +Cc: emacs-devel

> Cc: emacs-devel@gnu.org
> From: Jussi Lahdenniemi <jussi@aprikoodi.fi>
> Date: Wed, 3 Feb 2016 15:59:28 +0200
> 
> > On 16.1.2016 11.58, Eli Zaretskii wrote:
> >> P.S. These patches all but exhaust your grace limit of contributed
> >> code we can accept without your assigning copyright, so I hope your
> >> legal paperwork is well under way, and we will be able to accept your
> >> contributions soon.
> 
> I just got notified by FSF that my paperwork is complete.

Great, thanks.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-02-03 15:42                           ` Eli Zaretskii
@ 2016-02-26 10:55                             ` Eli Zaretskii
  2016-02-26 10:59                               ` Jussi Lahdenniemi
  2016-02-27  2:11                               ` Lars Ingebrigtsen
  0 siblings, 2 replies; 63+ messages in thread
From: Eli Zaretskii @ 2016-02-26 10:55 UTC (permalink / raw)
  To: jussi; +Cc: emacs-devel

> Date: Wed, 03 Feb 2016 17:42:43 +0200
> From: Eli Zaretskii <eliz@gnu.org>
> Cc: emacs-devel@gnu.org
> 
> > Cc: emacs-devel@gnu.org
> > From: Jussi Lahdenniemi <jussi@aprikoodi.fi>
> > Date: Wed, 3 Feb 2016 15:59:28 +0200
> > 
> > > On 16.1.2016 11.58, Eli Zaretskii wrote:
> > >> P.S. These patches all but exhaust your grace limit of contributed
> > >> code we can accept without your assigning copyright, so I hope your
> > >> legal paperwork is well under way, and we will be able to accept your
> > >> contributions soon.
> > 
> > I just got notified by FSF that my paperwork is complete.
> 
> Great, thanks.

I've pushed your changes to the master branch.  Thank you for your
contribution.

If you are looking for a topic for your next contributions, may I
suggest adding getaddrinfo_a functionality to the Windows build (and
fixing the current bug with https connections while at that)?

TIA



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-02-26 10:55                             ` Eli Zaretskii
@ 2016-02-26 10:59                               ` Jussi Lahdenniemi
  2016-02-27 11:34                                 ` Eli Zaretskii
  2016-02-27  2:11                               ` Lars Ingebrigtsen
  1 sibling, 1 reply; 63+ messages in thread
From: Jussi Lahdenniemi @ 2016-02-26 10:59 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

> I've pushed your changes to the master branch.  Thank you for your
> contribution.

Thanks!

> If you are looking for a topic for your next contributions, may I
> suggest adding getaddrinfo_a functionality to the Windows build (and
> fixing the current bug with https connections while at that)?

I could take a look at that.

-- 
Jussi Lahdenniemi





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-02-26 10:55                             ` Eli Zaretskii
  2016-02-26 10:59                               ` Jussi Lahdenniemi
@ 2016-02-27  2:11                               ` Lars Ingebrigtsen
  2016-02-27  7:47                                 ` Eli Zaretskii
  1 sibling, 1 reply; 63+ messages in thread
From: Lars Ingebrigtsen @ 2016-02-27  2:11 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: jussi, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

> If you are looking for a topic for your next contributions, may I
> suggest adding getaddrinfo_a functionality to the Windows build

Paul mentioned adding getaddrinfo_a to gnulib, so that should take care
of that.

> (and fixing the current bug with https connections while at that)?

That would be nice.  :-)

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-02-27  2:11                               ` Lars Ingebrigtsen
@ 2016-02-27  7:47                                 ` Eli Zaretskii
  2016-02-28  4:40                                   ` Lars Ingebrigtsen
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2016-02-27  7:47 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: jussi, emacs-devel

> From: Lars Ingebrigtsen <larsi@gnus.org>
> Cc: jussi@aprikoodi.fi,  emacs-devel@gnu.org
> Date: Sat, 27 Feb 2016 12:41:00 +1030
> 
> Eli Zaretskii <eliz@gnu.org> writes:
> 
> > If you are looking for a topic for your next contributions, may I
> > suggest adding getaddrinfo_a functionality to the Windows build
> 
> Paul mentioned adding getaddrinfo_a to gnulib, so that should take care
> of that.

I very much doubt that Paul volunteered to write the Windows part of
that ;-)

If we have the code in Emacs, it will be easy to factor it out to
Gnulib later.

Thanks.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-02-26 10:59                               ` Jussi Lahdenniemi
@ 2016-02-27 11:34                                 ` Eli Zaretskii
  2016-02-28  8:42                                   ` Paul Eggert
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2016-02-27 11:34 UTC (permalink / raw)
  To: Jussi Lahdenniemi; +Cc: emacs-devel

> From: Jussi Lahdenniemi <jussi@aprikoodi.fi>
> Date: Fri, 26 Feb 2016 12:59:17 +0200
> Cc: emacs-devel@gnu.org
> 
> > If you are looking for a topic for your next contributions, may I
> > suggest adding getaddrinfo_a functionality to the Windows build (and
> > fixing the current bug with https connections while at that)?
> 
> I could take a look at that.

Thanks.

Note that currently, we don't use getaddrinfo on Windows (because it
wasn't available before XP).  So a useful first step would be to add
support for getaddrinfo, when it is available.  This would require
making the tests for its availability in process.c run-time rather
than compile-time.  The result should be support for IPv6 on Windows,
a useful functionality on its own.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-02-27  7:47                                 ` Eli Zaretskii
@ 2016-02-28  4:40                                   ` Lars Ingebrigtsen
  0 siblings, 0 replies; 63+ messages in thread
From: Lars Ingebrigtsen @ 2016-02-28  4:40 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: jussi, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

> I very much doubt that Paul volunteered to write the Windows part of
> that ;-)
>
> If we have the code in Emacs, it will be easy to factor it out to
> Gnulib later.

Well, the code would basically be an unemacsified version of non-async
bits of `make-network-process', which already has Windowsified code
paths.  :-)  So if I were to implement this stuff, I would further
refactor `make-network-process' so that the DNS resolution is one
standalone function, and then I would call that from the new async
resolver, too (as well as from the current sync code path).

It would also make `make-network-process' more readable.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-02-27 11:34                                 ` Eli Zaretskii
@ 2016-02-28  8:42                                   ` Paul Eggert
  2016-02-28 15:50                                     ` Eli Zaretskii
  0 siblings, 1 reply; 63+ messages in thread
From: Paul Eggert @ 2016-02-28  8:42 UTC (permalink / raw)
  To: Eli Zaretskii, Jussi Lahdenniemi; +Cc: emacs-devel

Eli Zaretskii wrote:
> currently, we don't use getaddrinfo on Windows (because it
> wasn't available before XP).  So a useful first step would be to add
> support for getaddrinfo, when it is available.

It would be easy to the Gnulib getaddrinfo module, which is supposed to add 
support for getaddrinfo on MS-Windows platforms that lack it.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-02-28  8:42                                   ` Paul Eggert
@ 2016-02-28 15:50                                     ` Eli Zaretskii
  2016-02-28 20:03                                       ` Paul Eggert
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2016-02-28 15:50 UTC (permalink / raw)
  To: Paul Eggert; +Cc: jussi, emacs-devel

> Cc: emacs-devel@gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Sun, 28 Feb 2016 00:42:40 -0800
> 
> Eli Zaretskii wrote:
> > currently, we don't use getaddrinfo on Windows (because it
> > wasn't available before XP).  So a useful first step would be to add
> > support for getaddrinfo, when it is available.
> 
> It would be easy to the Gnulib getaddrinfo module, which is supposed to add 
> support for getaddrinfo on MS-Windows platforms that lack it.

What would be the point of that?  The fallback code is already in
Emacs, and it isn't Windows-specific, whereas the test whether
getaddrinfo is available is a trivial one-liner.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-02-28 15:50                                     ` Eli Zaretskii
@ 2016-02-28 20:03                                       ` Paul Eggert
  2016-02-28 20:10                                         ` Eli Zaretskii
  2016-02-28 23:33                                         ` John Wiegley
  0 siblings, 2 replies; 63+ messages in thread
From: Paul Eggert @ 2016-02-28 20:03 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: jussi, emacs-devel

Eli Zaretskii wrote:
>> >Eli Zaretskii wrote:
>>> > >currently, we don't use getaddrinfo on Windows (because it
>>> > >wasn't available before XP).  So a useful first step would be to add
>>> > >support for getaddrinfo, when it is available.
>> >
>> >It would be easy to the Gnulib getaddrinfo module, which is supposed to add
>> >support for getaddrinfo on MS-Windows platforms that lack it.
> What would be the point of that?  The fallback code is already in
> Emacs, and it isn't Windows-specific

The point is to separate concerns. Using the getaddrinfo module should make 
Emacs easier to maintain, since Emacs wouldn't need "#ifndef HAVE_GETADDRINFO" 
etc. sprinkled throughout its own source code. The total amount of code in the 
Emacs tarball (i.e., Emacs proper + Emacs copy of gnulib subset) should be about 
the same, but the "port to non-getaddrinfo" stuff would be in gnulib and would 
be shared better with other GNU projects.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-02-28 20:03                                       ` Paul Eggert
@ 2016-02-28 20:10                                         ` Eli Zaretskii
  2016-02-28 23:27                                           ` Paul Eggert
  2016-02-28 23:33                                         ` John Wiegley
  1 sibling, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2016-02-28 20:10 UTC (permalink / raw)
  To: Paul Eggert; +Cc: jussi, emacs-devel

> Cc: jussi@aprikoodi.fi, emacs-devel@gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Sun, 28 Feb 2016 12:03:35 -0800
> 
> The point is to separate concerns. Using the getaddrinfo module should make 
> Emacs easier to maintain, since Emacs wouldn't need "#ifndef HAVE_GETADDRINFO" 
> etc. sprinkled throughout its own source code. The total amount of code in the 
> Emacs tarball (i.e., Emacs proper + Emacs copy of gnulib subset) should be about 
> the same, but the "port to non-getaddrinfo" stuff would be in gnulib and would 
> be shared better with other GNU projects.

How is any of this related to Windows?



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-02-28 20:10                                         ` Eli Zaretskii
@ 2016-02-28 23:27                                           ` Paul Eggert
  2016-02-29  3:31                                             ` Eli Zaretskii
  0 siblings, 1 reply; 63+ messages in thread
From: Paul Eggert @ 2016-02-28 23:27 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: jussi, emacs-devel

Eli Zaretskii wrote:

> How is any of this related to Windows?

The Gnulib getaddrinfo module is supposed to work on MS-Windows. If Emacs used 
the Gnulib getaddrinfo module, the mainline Emacs code could be simplified by 
assuming that getaddrinfo works.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-02-28 20:03                                       ` Paul Eggert
  2016-02-28 20:10                                         ` Eli Zaretskii
@ 2016-02-28 23:33                                         ` John Wiegley
  1 sibling, 0 replies; 63+ messages in thread
From: John Wiegley @ 2016-02-28 23:33 UTC (permalink / raw)
  To: Paul Eggert; +Cc: Eli Zaretskii, jussi, emacs-devel

>>>>> Paul Eggert <eggert@cs.ucla.edu> writes:

> The point is to separate concerns. Using the getaddrinfo module should make
> Emacs easier to maintain, since Emacs wouldn't need "#ifndef
> HAVE_GETADDRINFO" etc. sprinkled throughout its own source code. The total
> amount of code in the Emacs tarball (i.e., Emacs proper + Emacs copy of
> gnulib subset) should be about the same, but the "port to non-getaddrinfo"
> stuff would be in gnulib and would be shared better with other GNU projects.

In general, where such separation of concerns can be achieved, I'm in favor.

-- 
John Wiegley                  GPG fingerprint = 4710 CF98 AF9B 327B B80F
http://newartisans.com                          60E1 46C4 BD1A 7AC1 4BA2



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-02-28 23:27                                           ` Paul Eggert
@ 2016-02-29  3:31                                             ` Eli Zaretskii
  2016-02-29  7:07                                               ` Paul Eggert
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2016-02-29  3:31 UTC (permalink / raw)
  To: Paul Eggert; +Cc: jussi, emacs-devel

> Cc: jussi@aprikoodi.fi, emacs-devel@gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Sun, 28 Feb 2016 15:27:33 -0800
> 
> Eli Zaretskii wrote:
> 
> > How is any of this related to Windows?
> 
> The Gnulib getaddrinfo module is supposed to work on MS-Windows. If Emacs used 
> the Gnulib getaddrinfo module, the mainline Emacs code could be simplified by 
> assuming that getaddrinfo works.

But the non-getaddrinfo parts are not conditioned on MS-Windows in any
way.  What about other systems that might be using them?



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-02-29  3:31                                             ` Eli Zaretskii
@ 2016-02-29  7:07                                               ` Paul Eggert
  2016-02-29 15:52                                                 ` Eli Zaretskii
  0 siblings, 1 reply; 63+ messages in thread
From: Paul Eggert @ 2016-02-29  7:07 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: jussi, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 783 bytes --]

Eli Zaretskii wrote:
>> The Gnulib getaddrinfo module is supposed to work on MS-Windows. If Emacs used
>> >the Gnulib getaddrinfo module, the mainline Emacs code could be simplified by
>> >assuming that getaddrinfo works.

> But the non-getaddrinfo parts are not conditioned on MS-Windows in any
> way.  What about other systems that might be using them?

Sorry, you've lost me.  The non-getaddrinfo parts of Gnulib?  Of Emacs?

For what it's worth, the Gnulib getaddrinfo module is supposed to work on a wide 
variety of systems lacking getaddrinfo, not just on MS-Windows.

I'm sure you mean something straightforward, it's just that I'm not getting it.

What I was thinking was that we add the Gnulib getaddrinfo module, and apply 
something like the attached (untested) patch.



[-- Attachment #2: t.diff --]
[-- Type: text/x-diff, Size: 5643 bytes --]

diff --git a/lib-src/pop.c b/lib-src/pop.c
index 57a5e52..55f2b10 100644
--- a/lib-src/pop.c
+++ b/lib-src/pop.c
@@ -962,13 +962,9 @@ static int have_winsock = 0;
 static int
 socket_connection (char *host, int flags)
 {
-#ifdef HAVE_GETADDRINFO
   struct addrinfo *res, *it;
   struct addrinfo hints;
   int ret;
-#else /* !HAVE_GETADDRINFO */
-  struct hostent *hostent;
-#endif
   struct servent *servent;
   struct sockaddr_in addr;
   char found_port = 0;
@@ -1055,7 +1051,6 @@ socket_connection (char *host, int flags)
 
     }
 
-#ifdef HAVE_GETADDRINFO
   memset (&hints, 0, sizeof (hints));
   hints.ai_socktype = SOCK_STREAM;
   hints.ai_flags = AI_CANONNAME;
@@ -1087,34 +1082,6 @@ socket_connection (char *host, int flags)
     }
   freeaddrinfo (res);
 
-#else /* !HAVE_GETADDRINFO */
-  do
-    {
-      hostent = gethostbyname (host);
-      try_count++;
-      if ((! hostent) && ((h_errno != TRY_AGAIN) || (try_count == 5)))
-	{
-	  strcpy (pop_error, "Could not determine POP server's address");
-	  return (-1);
-	}
-    } while (! hostent);
-
-  while (*hostent->h_addr_list)
-    {
-      memcpy (&addr.sin_addr, *hostent->h_addr_list, hostent->h_length);
-      if (! connect (sock, (struct sockaddr *) &addr, sizeof (addr)))
-	break;
-      hostent->h_addr_list++;
-    }
-  connect_ok = *hostent->h_addr_list != NULL;
-  if (! connect_ok)
-    {
-      realhost = alloca (strlen (hostent->h_name) + 1);
-      strcpy (realhost, hostent->h_name);
-    }
-
-#endif /* !HAVE_GETADDRINFO */
-
 #define CONNECT_ERROR "Could not connect to POP server: "
 
   if (! connect_ok)
diff --git a/src/conf_post.h b/src/conf_post.h
index 2788abf..b2eb2a2 100644
--- a/src/conf_post.h
+++ b/src/conf_post.h
@@ -122,7 +122,6 @@ typedef bool bool_bf;
 char *_getpty();
 #endif
 #define INET6 /* Needed for struct sockaddr_in6.  */
-#undef HAVE_GETADDRINFO /* IRIX has getaddrinfo but not struct addrinfo.  */
 #endif /* IRIX6_5 */
 
 #ifdef MSDOS
diff --git a/src/process.c b/src/process.c
index d83e2d2..9a4bedf 100644
--- a/src/process.c
+++ b/src/process.c
@@ -3430,21 +3430,6 @@ connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses)
 
 }
 
-#ifndef HAVE_GETADDRINFO
-static Lisp_Object
-conv_numerical_to_lisp (unsigned char *number, int length, int port)
-{
-  Lisp_Object address = Fmake_vector (make_number (length + 1), Qnil);
-  struct Lisp_Vector *p = XVECTOR (address);
-
-  p->contents[length] = make_number (port);
-  for (int i = 0; i < length; i++)
-    p->contents[i] = make_number (number[i]);
-
-  return address;
-}
-#endif
-
 /* Create a network stream/datagram client/server process.  Treated
    exactly like a normal process when reading and writing.  Primary
    differences are in status display and process deletion.  A network
@@ -3615,11 +3600,9 @@ usage: (make-network-process &rest ARGS)  */)
   Lisp_Object proc;
   Lisp_Object contact;
   struct Lisp_Process *p;
-#if defined HAVE_GETADDRINFO || defined HAVE_GETADDRINFO_A
   const char *portstring;
   ptrdiff_t portstringlen ATTRIBUTE_UNUSED;
   char portbuf[INT_BUFSIZE_BOUND (EMACS_INT)];
-#endif
 #ifdef HAVE_LOCAL_SOCKETS
   struct sockaddr_un address_un;
 #endif
@@ -3690,7 +3673,7 @@ usage: (make-network-process &rest ARGS)  */)
   tem = Fplist_get (contact, QCfamily);
   if (NILP (tem))
     {
-#if defined (HAVE_GETADDRINFO) && defined (AF_INET6)
+#ifdef AF_INET6
       family = AF_UNSPEC;
 #else
       family = AF_INET;
@@ -3762,7 +3745,6 @@ usage: (make-network-process &rest ARGS)  */)
     }
 #endif
 
-#if defined HAVE_GETADDRINFO || defined HAVE_GETADDRINFO_A
   if (!NILP (host))
     {
       /* SERVICE can either be a string or int.
@@ -3784,7 +3766,6 @@ usage: (make-network-process &rest ARGS)  */)
 	  portstringlen = SBYTES (service);
 	}
     }
-#endif
 
 #ifdef HAVE_GETADDRINFO_A
   if (!NILP (host) && !NILP (Fplist_get (contact, QCnowait)))
@@ -3816,7 +3797,6 @@ usage: (make-network-process &rest ARGS)  */)
     }
 #endif /* HAVE_GETADDRINFO_A */
 
-#ifdef HAVE_GETADDRINFO
   /* If we have a host, use getaddrinfo to resolve both host and service.
      Otherwise, use getservbyname to lookup the service.  */
 
@@ -3860,7 +3840,6 @@ usage: (make-network-process &rest ARGS)  */)
 
       goto open_socket;
     }
-#endif /* HAVE_GETADDRINFO */
 
   /* We end up here if getaddrinfo is not defined, or in case no hostname
      has been specified (e.g. for a local server process).  */
@@ -3899,47 +3878,6 @@ usage: (make-network-process &rest ARGS)  */)
       xsignal1 (Qerror, CALLN (Fformat, unknown_service, service));
     }
 
-#ifndef HAVE_GETADDRINFO
-  if (!NILP (host))
-    {
-      struct hostent *host_info_ptr;
-      unsigned char *addr;
-      int addrlen;
-
-      /* gethostbyname may fail with TRY_AGAIN, but we don't honor that,
-	 as it may `hang' Emacs for a very long time.  */
-      immediate_quit = 1;
-      QUIT;
-
-#ifdef HAVE_RES_INIT
-      res_init ();
-#endif
-
-      host_info_ptr = gethostbyname ((const char *) SDATA (host));
-      immediate_quit = 0;
-
-      if (host_info_ptr)
-	{
-	  addr = (unsigned char *) host_info_ptr->h_addr;
-	  addrlen = host_info_ptr->h_length;
-	}
-      else
-	/* Attempt to interpret host as numeric inet address.  This
-	   only works for IPv4 addresses. */
-	{
-	  unsigned long numeric_addr = inet_addr (SSDATA (host));
-
-	  if (numeric_addr == -1)
-	    error ("Unknown host \"%s\"", SDATA (host));
-
-	  addr = (unsigned char *) &numeric_addr;
-	  addrlen = 4;
-	}
-
-      ip_addresses = list1 (conv_numerical_to_lisp (addr, addrlen, port));
-    }
-#endif /* not HAVE_GETADDRINFO */
-
  open_socket:
 
   if (!NILP (buffer))

^ permalink raw reply related	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-02-29  7:07                                               ` Paul Eggert
@ 2016-02-29 15:52                                                 ` Eli Zaretskii
  2016-02-29 19:01                                                   ` Paul Eggert
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2016-02-29 15:52 UTC (permalink / raw)
  To: Paul Eggert; +Cc: jussi, emacs-devel

> Cc: jussi@aprikoodi.fi, emacs-devel@gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Sun, 28 Feb 2016 23:07:38 -0800
> 
> >> The Gnulib getaddrinfo module is supposed to work on MS-Windows. If Emacs used
> >> >the Gnulib getaddrinfo module, the mainline Emacs code could be simplified by
> >> >assuming that getaddrinfo works.
> 
> > But the non-getaddrinfo parts are not conditioned on MS-Windows in any
> > way.  What about other systems that might be using them?
> 
> Sorry, you've lost me.  The non-getaddrinfo parts of Gnulib?  Of Emacs?

Of Emacs, of course.

> For what it's worth, the Gnulib getaddrinfo module is supposed to work on a wide 
> variety of systems lacking getaddrinfo, not just on MS-Windows.

I was talking about systems other than Windows.  Do we know which ones
of them still use the non-getaddrinfo code?

I see that we have calls to something named res_init there, and we
even have a configure-time test for that.  What is that about?  Gnulib
doesn't have that, and it's certainly not for the MS-Windows build.

> I'm sure you mean something straightforward, it's just that I'm not getting it.

Sorry for being unclear.

> What I was thinking was that we add the Gnulib getaddrinfo module, and apply 
> something like the attached (untested) patch.

Thanks.  I don't object to this, but I don't think we can use this on
Windows.  The current w32 code in Emacs wraps each network-related
function with a wrapper that tracks sockets and file descriptors they
use, translates socket errors to errno values, and does other
important stuff.  The code also arranges for dynamically loading the
socket library only when actually needed.  So replacing just one
function will certainly not work well, and replacing them all sounds
like a lot of work for very little gain.

So I think a better way forward would be to implement getaddrinfo
wrapper in w32.c, complete with the fallback we have in process.c (and
maybe also borrowing some ideas from Gnulib).  When this is done, we
can install your patch for whatever other systems which still don't
have getaddrinfo (if there are such systems that we still support).

Writing such a getaddrinfo wrapper is easy, and I expect it to be done
soon enough, so please wait with your patch until then.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-02-29 15:52                                                 ` Eli Zaretskii
@ 2016-02-29 19:01                                                   ` Paul Eggert
  2016-03-05 10:16                                                     ` Eli Zaretskii
  0 siblings, 1 reply; 63+ messages in thread
From: Paul Eggert @ 2016-02-29 19:01 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: jussi, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 2418 bytes --]

On 02/29/2016 07:52 AM, Eli Zaretskii wrote:
> I was talking about systems other than Windows. Do we know which ones 
> of them still use the non-getaddrinfo code?

The Gnulib documentation mentions HP-UX 11.11, IRIX 6.5, OSF/1 5.1, 
Solaris 7, Cygwin 1.5.x, mingw, MSVC 9, Interix 3.5, BeOS. Of the 
non-MS-Windows ports, Emacs should run on HP-UX 11, Solaris 7, and 
(assuming --with-wide-int) IRIX 6.5. Of these only HP-UX 11.11 (aka 
HP-UX 11i) is still a viable platform. The base system lacks 
getaddrinfo, but there is an optional addon to support getaddrinfo (it's 
part of IPv6 support)

> I see that we have calls to something named res_init there, and we 
> even have a configure-time test for that. What is that about? Gnulib 
> doesn't have that, and it's certainly not for the MS-Windows build.

res_init originally had to do with the ancient (pre-2000) BIND 
interfaces that were not thread-safe. Emacs doesn't use those so we 
don't need to worry about them. More recently, res_init was used to kick 
glibc into re-reading /etc/resolv.conf. That has been obsolete for years 
too, with the emergence of nscd. Nowadays calling res_init merely slows 
Emacs down so Emacs should stop doing it, and I installed the attached 
patch into master.

> The current w32 code in Emacs wraps each network-related function with 
> a wrapper that tracks sockets and file descriptors they use, 
> translates socket errors to errno values, and does other important 
> stuff. The code also arranges for dynamically loading the socket 
> library only when actually needed. So replacing just one function will 
> certainly not work well, and replacing them all sounds like a lot of 
> work for very little gain. So I think a better way forward would be to 
> implement getaddrinfo wrapper in w32.c, complete with the fallback we 
> have in process.c (and maybe also borrowing some ideas from Gnulib).

Gnulib also tracks file descriptors in its substitute functions, I 
presume for similar reasons. At some point perhaps this should be 
unified with what Emacs does, but obviously this is not high priority.

> When this is done, we can install your patch for whatever other 
> systems which still don't have getaddrinfo (if there are such systems 
> that we still support). Writing such a getaddrinfo wrapper is easy, 
> and I expect it to be done soon enough, so please wait with your patch 
> until then. 

Sounds good.

[-- Attachment #2: 0001-Stop-calling-res_init.patch --]
[-- Type: application/x-patch, Size: 5456 bytes --]

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-02-29 19:01                                                   ` Paul Eggert
@ 2016-03-05 10:16                                                     ` Eli Zaretskii
  2016-03-08  2:57                                                       ` Paul Eggert
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2016-03-05 10:16 UTC (permalink / raw)
  To: Paul Eggert; +Cc: jussi, emacs-devel

> Cc: jussi@aprikoodi.fi, emacs-devel@gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Mon, 29 Feb 2016 11:01:31 -0800
> 
> > When this is done, we can install your patch for whatever other 
> > systems which still don't have getaddrinfo (if there are such systems 
> > that we still support). Writing such a getaddrinfo wrapper is easy, 
> > and I expect it to be done soon enough, so please wait with your patch 
> > until then. 
> 
> Sounds good.

This is now done on master.

I hope I didn't break Cygwin-w32 and MinGW64 builds; if I did, the
users of the respective ports are encouraged to report that to the bug
tracker.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-03-05 10:16                                                     ` Eli Zaretskii
@ 2016-03-08  2:57                                                       ` Paul Eggert
  2016-03-08  4:46                                                         ` Clément Pit--Claudel
  0 siblings, 1 reply; 63+ messages in thread
From: Paul Eggert @ 2016-03-08  2:57 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: jussi, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 567 bytes --]

Eli Zaretskii wrote:
>>> > >When this is done, we can install your patch for whatever other
>>> > >systems which still don't have getaddrinfo (if there are such systems
>>> > >that we still support). Writing such a getaddrinfo wrapper is easy,
>>> > >and I expect it to be done soon enough, so please wait with your patch
>>> > >until then.
>> >
>> >Sounds good.
> This is now done on master.

OK, thanks, I installed into master the attached patch, which simplifies the 
Emacs C code by assuming getaddrinfo on non-Microsoftish hosts. This should be 
safe nowadays.

[-- Attachment #2: 0001-Assume-getaddrinfo-in-C-code.txt --]
[-- Type: text/plain, Size: 13022 bytes --]

From 536fea6a831f8052883cbe210f15834dc9c4ca5a Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Mon, 7 Mar 2016 18:54:25 -0800
Subject: [PATCH] Assume getaddrinfo in C code
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* admin/CPP-DEFINES, configure.ac: Remove HAVE_GETADDRINFO, HAVE_H_ERRNO.
All uses removed.
* doc/lispref/processes.texi (Network, Network Processes), etc/NEWS:
Say that port numbers can be integer strings.
* lib-src/pop.c (h_errno) [!WINDOWSNT && !HAVE_H_ERRNO]: Remove decl.
(socket_connection): Assume HAVE_GETADDRINFO.
* lisp/mpc.el (mpc--proc-connect):
* lisp/net/network-stream.el (open-network-stream):
It’s now OK to use integer strings as port numbers.
* src/process.c (conv_numerical_to_lisp) [!HAVE_GETADDRINFO]: Remove.
(Fmake_network_process): Assume HAVE_GETADDRINFO.
---
 admin/CPP-DEFINES          |  2 --
 configure.ac               | 16 +----------
 doc/lispref/processes.texi |  8 ++++--
 etc/NEWS                   |  9 +++---
 lib-src/pop.c              | 39 --------------------------
 lisp/mpc.el                |  5 +---
 lisp/net/network-stream.el |  4 +--
 src/process.c              | 68 +++-------------------------------------------
 8 files changed, 17 insertions(+), 134 deletions(-)

diff --git a/admin/CPP-DEFINES b/admin/CPP-DEFINES
index 9064053..d9df152 100644
--- a/admin/CPP-DEFINES
+++ b/admin/CPP-DEFINES
@@ -147,7 +147,6 @@ HAVE_FUTIMES
 HAVE_FUTIMESAT
 HAVE_GAI_STRERROR
 HAVE_GCONF
-HAVE_GETADDRINFO
 HAVE_GETDELIM
 HAVE_GETGRENT
 HAVE_GETHOSTNAME
@@ -184,7 +183,6 @@ HAVE_GTK_WIDGET_GET_WINDOW
 HAVE_GTK_WIDGET_SET_HAS_WINDOW
 HAVE_GTK_WINDOW_SET_HAS_RESIZE_GRIP
 HAVE_G_TYPE_INIT
-HAVE_H_ERRNO
 HAVE_IFADDRS_H
 HAVE_IMAGEMAGICK
 HAVE_INET_SOCKETS
diff --git a/configure.ac b/configure.ac
index 61287d7..940a1e2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3701,20 +3701,6 @@ fi
 AC_SUBST(LIBXML2_LIBS)
 AC_SUBST(LIBXML2_CFLAGS)
 
-# If netdb.h doesn't declare h_errno, we must declare it by hand.
-# On MinGW, that is provided by nt/inc/sys/socket.h and w32.c.
-if test "${opsys}" = "mingw32"; then
-  emacs_cv_netdb_declares_h_errno=yes
-fi
-AC_CACHE_CHECK(whether netdb declares h_errno,
-	       emacs_cv_netdb_declares_h_errno,
-[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <netdb.h>]],
-  [[return h_errno;]])],
-  emacs_cv_netdb_declares_h_errno=yes, emacs_cv_netdb_declares_h_errno=no)])
-if test $emacs_cv_netdb_declares_h_errno = yes; then
-  AC_DEFINE(HAVE_H_ERRNO, 1, [Define to 1 if netdb.h declares h_errno.])
-fi
-
 # Check for mail-locking functions in a "mail" library.  Probably this should
 # have the same check as for liblockfile below.
 AC_CHECK_LIB(mail, maillock, have_mail=yes, have_mail=no)
@@ -3803,7 +3789,7 @@ AC_CHECK_FUNCS(accept4 fchdir gethostname \
 getrusage get_current_dir_name \
 lrand48 random rint \
 select getpagesize setlocale newlocale \
-getrlimit setrlimit shutdown getaddrinfo \
+getrlimit setrlimit shutdown \
 pthread_sigmask strsignal setitimer \
 sendto recvfrom getsockname getpeername getifaddrs freeifaddrs \
 gai_strerror sync \
diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi
index 79cebaa..8d3df55 100644
--- a/doc/lispref/processes.texi
+++ b/doc/lispref/processes.texi
@@ -2128,7 +2128,8 @@ Network
 
 The arguments @var{host} and @var{service} specify where to connect to;
 @var{host} is the host name (a string), and @var{service} is the name of
-a defined network service (a string) or a port number (an integer).
+a defined network service (a string) or a port number (an integer like
+@code{80} or an integer string like @code{"80"}).
 
 The remaining arguments @var{parameters} are keyword/argument pairs
 that are mainly relevant to encrypted connections:
@@ -2352,8 +2353,9 @@ Network Processes
 
 @item :service @var{service}
 @var{service} specifies a port number to connect to; or, for a server,
-the port number to listen on.  It should be a service name that
-translates to a port number, or an integer specifying the port number
+the port number to listen on.  It should be a service name like
+@samp{"http"} that translates to a port number, or an integer like @samp{80}
+or an integer string like @samp{"80"} that specifies the port number
 directly.  For a server, it can also be @code{t}, which means to let
 the system select an unused port number.
 
diff --git a/etc/NEWS b/etc/NEWS
index 4328761..b651b9e 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -74,11 +74,10 @@ to deal with asynchronous sockets is to avoid interacting with them
 until they have changed status to "run".  This is most easily done
 from a process sentinel.
 
-** `make-network-stream' has always allowed :service to be specified
-as a "number string" (i.e., :service "993") when using gethostbyname,
-but has required using a real number (i.e., :service 993) on systems
-without gethostbyname.  This difference has now been eliminated, and
-you can use "number strings" on all systems.
+** ‘make-network-process’ and ‘open-network-stream’ sometimes allowed
+:service to be an integer string (e.g., :service "993") and sometimes
+required an integer (e.g., :service 993).  This difference has been
+eliminated, and integer strings work everywhere.
 
 ** It is possible to disable attempted recovery on fatal signals
 
diff --git a/lib-src/pop.c b/lib-src/pop.c
index 21d7215..9839934 100644
--- a/lib-src/pop.c
+++ b/lib-src/pop.c
@@ -102,12 +102,6 @@ extern char *krb_realmofhost (/* char * */);
 #endif /* ! KERBEROS5 */
 #endif /* KERBEROS */
 
-#ifndef WINDOWSNT
-#ifndef HAVE_H_ERRNO
-extern int h_errno;
-#endif
-#endif
-
 static int socket_connection (char *, int);
 static int pop_getline (popserver, char **);
 static int sendline (popserver, const char *);
@@ -972,13 +966,9 @@ static int have_winsock = 0;
 static int
 socket_connection (char *host, int flags)
 {
-#ifdef HAVE_GETADDRINFO
   struct addrinfo *res, *it;
   struct addrinfo hints;
   int ret;
-#else /* !HAVE_GETADDRINFO */
-  struct hostent *hostent;
-#endif
   struct servent *servent;
   struct sockaddr_in addr;
   char found_port = 0;
@@ -1065,7 +1055,6 @@ socket_connection (char *host, int flags)
 
     }
 
-#ifdef HAVE_GETADDRINFO
   memset (&hints, 0, sizeof (hints));
   hints.ai_socktype = SOCK_STREAM;
   hints.ai_flags = AI_CANONNAME;
@@ -1097,34 +1086,6 @@ socket_connection (char *host, int flags)
     }
   freeaddrinfo (res);
 
-#else /* !HAVE_GETADDRINFO */
-  do
-    {
-      hostent = gethostbyname (host);
-      try_count++;
-      if ((! hostent) && ((h_errno != TRY_AGAIN) || (try_count == 5)))
-	{
-	  strcpy (pop_error, "Could not determine POP server's address");
-	  return (-1);
-	}
-    } while (! hostent);
-
-  while (*hostent->h_addr_list)
-    {
-      memcpy (&addr.sin_addr, *hostent->h_addr_list, hostent->h_length);
-      if (! connect (sock, (struct sockaddr *) &addr, sizeof (addr)))
-	break;
-      hostent->h_addr_list++;
-    }
-  connect_ok = *hostent->h_addr_list != NULL;
-  if (! connect_ok)
-    {
-      realhost = alloca (strlen (hostent->h_name) + 1);
-      strcpy (realhost, hostent->h_name);
-    }
-
-#endif /* !HAVE_GETADDRINFO */
-
 #define CONNECT_ERROR "Could not connect to POP server: "
 
   if (! connect_ok)
diff --git a/lisp/mpc.el b/lisp/mpc.el
index 20e4bc8..aa7fee6 100644
--- a/lisp/mpc.el
+++ b/lisp/mpc.el
@@ -265,10 +265,7 @@ mpc--proc-connect
       (let ((v (match-string 3 host)))
         (setq host (match-string 2 host))
         (when (and (stringp v) (not (string= "" v)))
-          (setq port
-                (if (string-match "[^[:digit:]]" v)
-                    (string-to-number v)
-                  v)))))
+          (setq port v))))
     (when (file-name-absolute-p host)
       ;; Expand file name because `file-name-absolute-p'
       ;; considers paths beginning with "~" as absolute
diff --git a/lisp/net/network-stream.el b/lisp/net/network-stream.el
index f919efb..5ddaef5 100644
--- a/lisp/net/network-stream.el
+++ b/lisp/net/network-stream.el
@@ -65,8 +65,8 @@ open-network-stream
  Process output goes at end of that buffer.  BUFFER may be nil,
  meaning that the process is not associated with any buffer.
 HOST is the name or IP address of the host to connect to.
-SERVICE is the name of the service desired, or an integer specifying
- a port number to connect to.
+SERVICE is the name of the service desired, or an integer or
+ integer string specifying a port number to connect to.
 
 The remaining PARAMETERS should be a sequence of keywords and
 values:
diff --git a/src/process.c b/src/process.c
index 69f5e1d..359cd21 100644
--- a/src/process.c
+++ b/src/process.c
@@ -3429,21 +3429,6 @@ connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses)
 
 }
 
-#ifndef HAVE_GETADDRINFO
-static Lisp_Object
-conv_numerical_to_lisp (unsigned char *number, int length, int port)
-{
-  Lisp_Object address = Fmake_vector (make_number (length + 1), Qnil);
-  struct Lisp_Vector *p = XVECTOR (address);
-
-  p->contents[length] = make_number (port);
-  for (int i = 0; i < length; i++)
-    p->contents[i] = make_number (number[i]);
-
-  return address;
-}
-#endif
-
 /* Create a network stream/datagram client/server process.  Treated
    exactly like a normal process when reading and writing.  Primary
    differences are in status display and process deletion.  A network
@@ -3479,9 +3464,8 @@ host, and only clients connecting to that address will be accepted.
 
 :service SERVICE -- SERVICE is name of the service desired, or an
 integer specifying a port number to connect to.  If SERVICE is t,
-a random port number is selected for the server.  (If Emacs was
-compiled with getaddrinfo, a port number can also be specified as a
-string, e.g. "80", as well as an integer.  This is not portable.)
+a random port number is selected for the server.  A port number can
+be specified as an integer string, e.g., "80", as well as an integer.
 
 :type TYPE -- TYPE is the type of connection.  The default (nil) is a
 stream type connection, `datagram' creates a datagram type connection,
@@ -3614,11 +3598,9 @@ usage: (make-network-process &rest ARGS)  */)
   Lisp_Object proc;
   Lisp_Object contact;
   struct Lisp_Process *p;
-#if defined HAVE_GETADDRINFO || defined HAVE_GETADDRINFO_A
   const char *portstring;
   ptrdiff_t portstringlen ATTRIBUTE_UNUSED;
   char portbuf[INT_BUFSIZE_BOUND (EMACS_INT)];
-#endif
 #ifdef HAVE_LOCAL_SOCKETS
   struct sockaddr_un address_un;
 #endif
@@ -3689,7 +3671,7 @@ usage: (make-network-process &rest ARGS)  */)
   tem = Fplist_get (contact, QCfamily);
   if (NILP (tem))
     {
-#if defined (HAVE_GETADDRINFO) && defined (AF_INET6)
+#ifdef AF_INET6
       family = AF_UNSPEC;
 #else
       family = AF_INET;
@@ -3761,7 +3743,6 @@ usage: (make-network-process &rest ARGS)  */)
     }
 #endif
 
-#if defined HAVE_GETADDRINFO || defined HAVE_GETADDRINFO_A
   if (!NILP (host))
     {
       /* SERVICE can either be a string or int.
@@ -3783,7 +3764,6 @@ usage: (make-network-process &rest ARGS)  */)
 	  portstringlen = SBYTES (service);
 	}
     }
-#endif
 
 #ifdef HAVE_GETADDRINFO_A
   if (!NILP (host) && !NILP (Fplist_get (contact, QCnowait)))
@@ -3815,7 +3795,6 @@ usage: (make-network-process &rest ARGS)  */)
     }
 #endif /* HAVE_GETADDRINFO_A */
 
-#ifdef HAVE_GETADDRINFO
   /* If we have a host, use getaddrinfo to resolve both host and service.
      Otherwise, use getservbyname to lookup the service.  */
 
@@ -3855,10 +3834,8 @@ usage: (make-network-process &rest ARGS)  */)
 
       goto open_socket;
     }
-#endif /* HAVE_GETADDRINFO */
 
-  /* We end up here if getaddrinfo is not defined, or in case no hostname
-     has been specified (e.g. for a local server process).  */
+  /* No hostname has been specified (e.g., a local server process).  */
 
   if (EQ (service, Qt))
     port = 0;
@@ -3894,43 +3871,6 @@ usage: (make-network-process &rest ARGS)  */)
       xsignal1 (Qerror, CALLN (Fformat, unknown_service, service));
     }
 
-#ifndef HAVE_GETADDRINFO
-  if (!NILP (host))
-    {
-      struct hostent *host_info_ptr;
-      unsigned char *addr;
-      int addrlen;
-
-      /* gethostbyname may fail with TRY_AGAIN, but we don't honor that,
-	 as it may `hang' Emacs for a very long time.  */
-      immediate_quit = 1;
-      QUIT;
-
-      host_info_ptr = gethostbyname ((const char *) SDATA (host));
-      immediate_quit = 0;
-
-      if (host_info_ptr)
-	{
-	  addr = (unsigned char *) host_info_ptr->h_addr;
-	  addrlen = host_info_ptr->h_length;
-	}
-      else
-	/* Attempt to interpret host as numeric inet address.  This
-	   only works for IPv4 addresses. */
-	{
-	  unsigned long numeric_addr = inet_addr (SSDATA (host));
-
-	  if (numeric_addr == -1)
-	    error ("Unknown host \"%s\"", SDATA (host));
-
-	  addr = (unsigned char *) &numeric_addr;
-	  addrlen = 4;
-	}
-
-      ip_addresses = list1 (conv_numerical_to_lisp (addr, addrlen, port));
-    }
-#endif /* not HAVE_GETADDRINFO */
-
  open_socket:
 
   if (!NILP (buffer))
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 63+ messages in thread

* Re: [PATCH] Override Windows default Win-* key combinations when using Emacs
  2016-03-08  2:57                                                       ` Paul Eggert
@ 2016-03-08  4:46                                                         ` Clément Pit--Claudel
  0 siblings, 0 replies; 63+ messages in thread
From: Clément Pit--Claudel @ 2016-03-08  4:46 UTC (permalink / raw)
  To: emacs-devel


[-- Attachment #1.1: Type: text/plain, Size: 165 bytes --]

On 03/07/2016 09:57 PM, Paul Eggert wrote:
> This should be safe nowadays.

Was this a joke about CVE-2015-7547? https://access.redhat.com/articles/2161461 :)


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 63+ messages in thread

end of thread, other threads:[~2016-03-08  4:46 UTC | newest]

Thread overview: 63+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-05 12:51 [PATCH] Override Windows default Win-* key combinations when using Emacs Jussi Lahdenniemi
2016-01-05 13:54 ` Herring, Davis
2016-01-05 17:05   ` Eli Zaretskii
2016-01-05 19:32     ` Jussi Lahdenniemi
2016-01-05 17:05 ` Eli Zaretskii
2016-01-05 19:03   ` Rasmus
2016-01-05 19:17     ` Eli Zaretskii
2016-01-05 19:31       ` Jussi Lahdenniemi
     [not found]     ` <<83d1tf4z0h.fsf@gnu.org>
2016-01-05 19:45       ` Drew Adams
2016-01-05 19:41   ` Jussi Lahdenniemi
2016-01-05 20:01     ` Eli Zaretskii
2016-01-09 19:58   ` Jussi Lahdenniemi
2016-01-11 18:54     ` Eli Zaretskii
2016-01-12 11:16       ` Jussi Lahdenniemi
2016-01-12 15:08         ` covici
2016-01-13  5:07           ` Jussi Lahdenniemi
2016-01-12 15:54         ` Eli Zaretskii
2016-01-13  5:31           ` Jussi Lahdenniemi
2016-01-13 15:49             ` Eli Zaretskii
2016-01-13  9:16           ` Jussi Lahdenniemi
2016-01-13 11:28             ` Jussi Lahdenniemi
2016-01-13 15:57               ` Eli Zaretskii
2016-01-14 12:49                 ` Jussi Lahdenniemi
2016-01-14 17:10                   ` Jussi Lahdenniemi
2016-01-14 18:07                     ` Eli Zaretskii
2016-01-14 18:15                   ` Eli Zaretskii
2016-01-15  6:56                     ` Jussi Lahdenniemi
2016-01-15  7:52                       ` Jussi Lahdenniemi
2016-01-15  8:08                         ` Windows 9X crash (was: [PATCH] Override Windows default Win-* key combinations when using Emacs) Eli Zaretskii
2016-01-15  9:35                           ` Windows 9X crash Jussi Lahdenniemi
2016-01-15 10:18                             ` Eli Zaretskii
2016-01-15 10:31                               ` Fabrice Popineau
2016-01-15 10:33                               ` Jussi Lahdenniemi
2016-01-16  9:15                                 ` Eli Zaretskii
2016-01-15  9:47                           ` Windows 9X crash (was: [PATCH] Override Windows default Win-* key combinations when using Emacs) Fabrice Popineau
2016-01-15  9:56                             ` Windows 9X crash Jussi Lahdenniemi
2016-01-15 10:19                               ` Eli Zaretskii
2016-01-15  9:23                         ` [PATCH] Override Windows default Win-* key combinations when using Emacs Yuri Khan
2016-01-16  9:58                     ` Eli Zaretskii
2016-01-16 11:00                       ` Jussi Lahdenniemi
2016-01-16 11:41                         ` Eli Zaretskii
2016-02-03 13:59                         ` Jussi Lahdenniemi
2016-02-03 15:42                           ` Eli Zaretskii
2016-02-26 10:55                             ` Eli Zaretskii
2016-02-26 10:59                               ` Jussi Lahdenniemi
2016-02-27 11:34                                 ` Eli Zaretskii
2016-02-28  8:42                                   ` Paul Eggert
2016-02-28 15:50                                     ` Eli Zaretskii
2016-02-28 20:03                                       ` Paul Eggert
2016-02-28 20:10                                         ` Eli Zaretskii
2016-02-28 23:27                                           ` Paul Eggert
2016-02-29  3:31                                             ` Eli Zaretskii
2016-02-29  7:07                                               ` Paul Eggert
2016-02-29 15:52                                                 ` Eli Zaretskii
2016-02-29 19:01                                                   ` Paul Eggert
2016-03-05 10:16                                                     ` Eli Zaretskii
2016-03-08  2:57                                                       ` Paul Eggert
2016-03-08  4:46                                                         ` Clément Pit--Claudel
2016-02-28 23:33                                         ` John Wiegley
2016-02-27  2:11                               ` Lars Ingebrigtsen
2016-02-27  7:47                                 ` Eli Zaretskii
2016-02-28  4:40                                   ` Lars Ingebrigtsen
2016-01-13 15:53             ` Eli Zaretskii
     [not found] <<568BBC58.50702@aprikoodi.fi>

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).