merge emacs-23
[bpt/emacs.git] / lib-src / emacsclient.c
index 1981278..6b7c7c3 100644 (file)
@@ -1,6 +1,6 @@
 /* Client process that communicates with GNU Emacs acting as server.
    Copyright (C) 1986, 1987, 1994, 1999, 2000, 2001, 2002, 2003, 2004,
-                 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+                 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -41,7 +41,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #else /* !WINDOWSNT */
 
-# include <sys/types.h>
+# include "syswait.h"
 
 # ifdef HAVE_INET_SOCKETS
 #  include <netinet/in.h>
@@ -54,6 +54,10 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 # define CLOSE_SOCKET close
 # define INITIALIZE()
 
+# ifndef WCONTINUED
+#  define WCONTINUED 8
+# endif
+
 #endif /* !WINDOWSNT */
 
 #undef signal
@@ -336,7 +340,7 @@ w32_get_resource (predefined, key, type)
 /*
   getenv wrapper for Windows
 
-  This is needed to duplicate Emacs's behavior, which is to look for enviroment
+  This is needed to duplicate Emacs's behavior, which is to look for environment
   variables in the registry if they don't appear in the environment.
 */
 char *
@@ -388,6 +392,33 @@ w32_getenv (envvar)
   return NULL;
 }
 
+void
+w32_set_user_model_id ()
+{
+  HMODULE shell;
+  HRESULT (WINAPI * set_user_model) (wchar_t * id);
+
+  /* On Windows 7 and later, we need to set the user model ID
+     to associate emacsclient launched files with Emacs frames
+     in the UI.  */
+  shell = LoadLibrary("shell32.dll");
+  if (shell)
+    {
+      set_user_model
+       = (void *) GetProcAddress (shell,
+                                  "SetCurrentProcessExplicitAppUserModelID");
+      /* If the function is defined, then we are running on Windows 7
+        or newer, and the UI uses this to group related windows
+        together.  Since emacs, runemacs, emacsclient are related, we
+        want them grouped even though the executables are different,
+        so we need to set a consistent ID between them.  */
+      if (set_user_model)
+       set_user_model (L"GNU.Emacs");
+
+      FreeLibrary (shell);
+    }
+}
+
 int
 w32_window_app ()
 {
@@ -570,7 +601,15 @@ decode_options (argc, argv)
      inconvenient.  So we force users to use "--display $DISPLAY" if
      they want Emacs to connect to their current display.  */
   if (!current_frame && !tty && !display)
-    display = egetenv ("DISPLAY");
+    {
+      display = egetenv ("DISPLAY");
+#ifdef NS_IMPL_COCOA
+      /* Under Cocoa, we don't really use displays the same way as in X,
+         so provide a dummy. */
+      if (!display || strlen (display) == 0)
+        display = "ns";
+#endif
+    }
 
   /* A null-string display is invalid.  */
   if (display && strlen (display) == 0)
@@ -616,21 +655,22 @@ The following OPTIONS are accepted:\n\
                        use the current Emacs frame\n\
 -e, --eval             Evaluate the FILE arguments as ELisp expressions\n\
 -n, --no-wait          Don't wait for the server to return\n\
--d, --display=DISPLAY  Visit the file in the given display\n"
+-d DISPLAY, --display=DISPLAY\n\
+                       Visit the file in the given display\n"
 #ifndef NO_SOCKETS_IN_FILE_SYSTEM
-"-s, --socket-name=FILENAME\n\
+"-s SOCKET, --socket-name=SOCKET\n\
                        Set filename of the UNIX socket for communication\n"
 #endif
-"-f, --server-file=FILENAME\n\
+"-f SERVER, --server-file=SERVER\n\
                        Set filename of the TCP authentication file\n\
--a, --alternate-editor=EDITOR\n\
+-a EDITOR, --alternate-editor=EDITOR\n\
                        Editor to fallback to if the server is not running\n"
-#ifdef WINDOWSNT
+#ifndef WINDOWSNT
 "                      If EDITOR is the empty string, start Emacs in daemon\n\
                        mode and try connecting again\n"
-#endif /* WINDOWSNT */
+#endif /* not WINDOWSNT */
 "\n\
-Report bugs to bug-gnu-emacs@gnu.org.\n", progname);
+Report bugs with M-x report-emacs-bug.\n", progname);
   exit (EXIT_SUCCESS);
 }
 
@@ -1209,7 +1249,21 @@ set_local_socket ()
       {
        tmpdir = egetenv ("TMPDIR");
        if (!tmpdir)
-         tmpdir = "/tmp";
+          {
+#ifdef DARWIN_OS
+#ifndef _CS_DARWIN_USER_TEMP_DIR
+#define _CS_DARWIN_USER_TEMP_DIR 65537
+#endif
+            size_t n = confstr (_CS_DARWIN_USER_TEMP_DIR, NULL, (size_t) 0);
+            if (n > 0)
+              {
+                tmpdir = alloca (n);
+                confstr (_CS_DARWIN_USER_TEMP_DIR, tmpdir, n);
+              }
+            else
+#endif
+              tmpdir = "/tmp";
+          }
        socket_name = alloca (strlen (tmpdir) + strlen (server_name)
                              + EXTRA_SPACE);
        sprintf (socket_name, "%s/emacs%d/%s",
@@ -1402,22 +1456,23 @@ w32_find_emacs_process (hWnd, lParam)
 void
 w32_give_focus ()
 {
-  HMODULE hUser32;
+  HANDLE user32;
 
   /* It shouldn't happen when dealing with TCP sockets.  */
   if (!emacs_pid) return;
 
-  if (!(hUser32 = LoadLibrary ("user32.dll"))) return;
+  user32 = GetModuleHandle ("user32.dll");
+
+  if (!user32)
+    return;
 
   /* Modern Windows restrict which processes can set the foreground window.
      emacsclient can allow Emacs to grab the focus by calling the function
      AllowSetForegroundWindow.  Unfortunately, older Windows (W95, W98 and
      NT) lack this function, so we have to check its availability.  */
-  if ((set_fg = GetProcAddress (hUser32, "AllowSetForegroundWindow"))
-      && (get_wc = GetProcAddress (hUser32, "RealGetWindowClassA")))
+  if ((set_fg = GetProcAddress (user32, "AllowSetForegroundWindow"))
+      && (get_wc = GetProcAddress (user32, "RealGetWindowClassA")))
     EnumWindows (w32_find_emacs_process, (LPARAM) 0);
-
-  FreeLibrary (hUser32);
 }
 #endif
 
@@ -1429,23 +1484,31 @@ start_daemon_and_retry_set_socket (void)
 #ifndef WINDOWSNT
   pid_t dpid;
   int status;
-  pid_t p;
 
   dpid = fork ();
 
   if (dpid > 0)
     {
-      p = waitpid (dpid, &status, WUNTRACED | WCONTINUED);
+      pid_t w;
+      w = waitpid (dpid, &status, WUNTRACED | WCONTINUED);
 
-      /* Try connecting again, the daemon should have started by
-        now.  */
-      message (TRUE, "daemon should have started, trying to connect again\n", dpid);
+      if ((w == -1) || !WIFEXITED (status) || WEXITSTATUS(status))
+       {
+         message (TRUE, "Error: Could not start the Emacs daemon\n");
+         exit (EXIT_FAILURE);
+       }
+
+      /* Try connecting, the daemon should have started by now.  */
+      message (TRUE, "Emacs daemon should have started, trying to connect again\n");
       if ((emacs_socket = set_socket (1)) == INVALID_SOCKET)
-       message (TRUE, "Cannot connect even after starting the daemon\n");
+       {
+         message (TRUE, "Error: Cannot connect even after starting the Emacs daemon\n");
+         exit (EXIT_FAILURE);
+       }
     }
   else if (dpid < 0)
     {
-      fprintf (stderr, "Cannot fork!\n");
+      fprintf (stderr, "Error: Cannot fork!\n");
       exit (1);
     }
   else
@@ -1480,6 +1543,12 @@ main (argc, argv)
   main_argv = argv;
   progname = argv[0];
 
+#ifdef WINDOWSNT
+  /* On Windows 7 and later, we need to explicitly associate emacsclient
+     with emacs so the UI behaves sensibly.  */
+  w32_set_user_model_id ();
+#endif
+
   /* Process options.  */
   decode_options (argc, argv);
 
@@ -1519,10 +1588,6 @@ main (argc, argv)
       }
     else
       fail ();
-#ifndef WINDOWSNT
-  else
-    fail ();
-#endif
 
   cwd = get_current_dir_name ();
   if (cwd == 0)
@@ -1550,11 +1615,11 @@ main (argc, argv)
           quote_argument (emacs_socket, environ[i]);
           send_to_emacs (emacs_socket, " ");
         }
-      send_to_emacs (emacs_socket, "-dir ");
-      quote_argument (emacs_socket, cwd);
-      send_to_emacs (emacs_socket, "/");
-      send_to_emacs (emacs_socket, " ");
     }
+  send_to_emacs (emacs_socket, "-dir ");
+  quote_argument (emacs_socket, cwd);
+  send_to_emacs (emacs_socket, "/");
+  send_to_emacs (emacs_socket, " ");
 
  retry:
   if (nowait)
@@ -1597,7 +1662,6 @@ main (argc, argv)
     {
       for (i = optind; i < argc; i++)
        {
-          int relative = 0;
 
          if (eval)
             {
@@ -1619,19 +1683,16 @@ main (argc, argv)
                   send_to_emacs (emacs_socket, " ");
                   continue;
                 }
-              else
-                relative = 1;
             }
-         else if (! file_name_absolute_p (argv[i]))
-#ifndef WINDOWSNT
-           relative = 1;
-#else
-           /* Call GetFullPathName so filenames of the form X:Y, where X is
-              a valid drive designator, are interpreted as drive:path, not
-              file:stream, and treated as absolute.
-              The user can still pass a file:stream if desired (for example,
-              .\X:Y), but it is not very useful, as Emacs currently does a
-              very bad job of dealing with NTFS streams. */
+#ifdef WINDOWSNT
+         else if (! file_name_absolute_p (argv[i])
+                  && (isalpha (argv[i][0]) && argv[i][1] == ':'))
+           /* Windows can have a different default directory for each
+              drive, so the cwd passed via "-dir" is not sufficient
+              to account for that.
+              If the user uses <drive>:<relpath>, we hence need to be
+              careful to expand <relpath> with the default directory
+              corresponding to <drive>.  */
            {
              char *filename = (char *) xmalloc (MAX_PATH);
              DWORD size;
@@ -1640,19 +1701,11 @@ main (argc, argv)
              if (size > 0 && size < MAX_PATH)
                argv[i] = filename;
              else
-               {
-                 relative = 1;
-                 free (filename);
-               }
+               free (filename);
            }
 #endif
 
           send_to_emacs (emacs_socket, "-file ");
-          if (relative)
-            {
-              quote_argument (emacs_socket, cwd);
-              send_to_emacs (emacs_socket, "/");
-            }
           quote_argument (emacs_socket, argv[i]);
           send_to_emacs (emacs_socket, " ");
         }