]> code.delx.au - gnu-emacs/blobdiff - lib-src/emacsclient.c
Add 2010 to copyright years.
[gnu-emacs] / lib-src / emacsclient.c
index 56e8b5b98592d1bfba7e74977cbffa503aaf3f16..550072900f0d442734bb302f6358a0df5505f430 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 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
@@ -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);
 }
 
@@ -1402,22 +1442,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 +1470,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 +1529,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,8 +1574,6 @@ main (argc, argv)
       }
     else
       fail ();
-  else
-    fail ();
 
   cwd = get_current_dir_name ();
   if (cwd == 0)
@@ -1548,11 +1601,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)
@@ -1595,7 +1648,6 @@ main (argc, argv)
     {
       for (i = optind; i < argc; i++)
        {
-          int relative = 0;
 
          if (eval)
             {
@@ -1617,19 +1669,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;
@@ -1638,19 +1687,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, " ");
         }