Merge from trunk.
[bpt/emacs.git] / lib-src / emacsclient.c
index 251f358..2af139a 100644 (file)
@@ -129,6 +129,9 @@ char **main_argv;
 /* Nonzero means don't wait for a response from Emacs.  --no-wait.  */
 int nowait = 0;
 
+/* Nonzero means don't print messages for successful operations.  --quiet. */
+int quiet = 0;
+
 /* Nonzero means args are expressions to be evaluated.  --eval.  */
 int eval = 0;
 
@@ -157,6 +160,10 @@ const char *server_file = NULL;
 /* PID of the Emacs server process.  */
 int emacs_pid = 0;
 
+/* If non-NULL, a string that should form a frame parameter alist to
+   be used for the new frame */
+const char *frame_parameters = NULL;
+
 static void print_help_and_exit (void) NO_RETURN;
 static void fail (void) NO_RETURN;
 
@@ -164,6 +171,7 @@ static void fail (void) NO_RETURN;
 struct option longopts[] =
 {
   { "no-wait", no_argument,       NULL, 'n' },
+  { "quiet",   no_argument,       NULL, 'q' },
   { "eval",    no_argument,       NULL, 'e' },
   { "help",    no_argument,       NULL, 'H' },
   { "version", no_argument,       NULL, 'V' },
@@ -171,6 +179,7 @@ struct option longopts[] =
   { "nw",      no_argument,       NULL, 't' },
   { "create-frame", no_argument,   NULL, 'c' },
   { "alternate-editor", required_argument, NULL, 'a' },
+  { "frame-parameters", required_argument, NULL, 'F' },
 #ifndef NO_SOCKETS_IN_FILE_SYSTEM
   { "socket-name",     required_argument, NULL, 's' },
 #endif
@@ -214,10 +223,8 @@ xmalloc (unsigned int size)
 #define IS_DEVICE_SEP(_c_) ((_c_) == DEVICE_SEP)
 #endif
 #endif
-#ifndef IS_ANY_SEP
-#define IS_ANY_SEP(_c_) (IS_DIRECTORY_SEP (_c_))
-#endif
 
+char *get_current_dir_name (void);
 
 /* Return the current working directory.  Returns NULL on errors.
    Any other returned value must be freed with free.  This is used
@@ -293,6 +300,20 @@ get_current_dir_name (void)
 
 #ifdef WINDOWSNT
 
+/* Like strdup but get a fatal error if memory is exhausted. */
+
+char *
+xstrdup (const char *s)
+{
+  char *result = strdup (s);
+  if (result == NULL)
+    {
+      perror ("strdup");
+      exit (EXIT_FAILURE);
+    }
+  return result;
+}
+
 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
 
 /* Retrieve an environment variable from the Emacs subkeys of the registry.
@@ -328,9 +349,11 @@ w32_get_resource (HKEY predefined, char *key, LPDWORD type)
 /*
   getenv wrapper for Windows
 
-  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.
-*/
+  Value is allocated on the heap, and can be free'd.
+
+  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 *
 w32_getenv (char *envvar)
 {
@@ -338,15 +361,16 @@ w32_getenv (char *envvar)
   DWORD dwType;
 
   if (value = getenv (envvar))
-    /* Found in the environment.  */
-    return value;
+    /* Found in the environment.  strdup it, because values returned
+       by getenv cannot be free'd.  */
+    return xstrdup (value);
 
   if (! (value = w32_get_resource (HKEY_CURRENT_USER, envvar, &dwType)) &&
       ! (value = w32_get_resource (HKEY_LOCAL_MACHINE, envvar, &dwType)))
     {
       /* "w32console" is what Emacs on Windows uses for tty-type under -nw.  */
       if (strcmp (envvar, "TERM") == 0)
-       return "w32console";
+       return xstrdup ("w32console");
       /* Found neither in the environment nor in the registry.  */
       return NULL;
     }
@@ -466,6 +490,7 @@ ttyname (int fd)
 
 /* Display a normal or error message.
    On Windows, use a message box if compiled as a Windows app.  */
+static void message (int, const char *, ...) ATTRIBUTE_FORMAT_PRINTF (2, 3);
 static void
 message (int is_error, const char *format, ...)
 {
@@ -506,9 +531,9 @@ decode_options (int argc, char **argv)
     {
       int opt = getopt_long_only (argc, argv,
 #ifndef NO_SOCKETS_IN_FILE_SYSTEM
-                            "VHnea:s:f:d:tc",
+                            "VHneqa:s:f:d:F:tc",
 #else
-                            "VHnea:f:d:tc",
+                            "VHneqa:f:d:F:tc",
 #endif
                             longopts, 0);
 
@@ -552,6 +577,10 @@ decode_options (int argc, char **argv)
          eval = 1;
          break;
 
+       case 'q':
+         quiet = 1;
+         break;
+
        case 'V':
          message (FALSE, "emacsclient %s\n", VERSION);
          exit (EXIT_SUCCESS);
@@ -575,6 +604,10 @@ decode_options (int argc, char **argv)
          print_help_and_exit ();
          break;
 
+        case 'F':
+          frame_parameters = optarg;
+          break;
+
        default:
          message (TRUE, "Try `%s --help' for more information\n", progname);
          exit (EXIT_FAILURE);
@@ -619,6 +652,14 @@ decode_options (int argc, char **argv)
 an empty string");
       exit (EXIT_FAILURE);
     }
+
+  /* TTY frames not supported on Windows.  Continue using GUI rather than
+     forcing the user to change their command-line.  This is required since
+     tty is set above if certain options are given and $DISPLAY is not set,
+     which is not obvious to users.  */
+  if (tty)
+      tty = 0;
+
 #endif /* WINDOWSNT */
 }
 
@@ -641,8 +682,11 @@ The following OPTIONS are accepted:\n\
 -nw, -t, --tty                 Open a new Emacs frame on the current terminal\n\
 -c, --create-frame     Create a new frame instead of trying to\n\
                        use the current Emacs frame\n\
+-F ALIST, --frame-parameters=ALIST\n\
+                       Set the parameters of a new frame\n\
 -e, --eval             Evaluate the FILE arguments as ELisp expressions\n\
 -n, --no-wait          Don't wait for the server to return\n\
+-q, --quiet            Don't display messages on success\n\
 -d DISPLAY, --display=DISPLAY\n\
                        Visit the file in the given display\n\
 --parent-id=ID          Open in parent window ID, via XEmbed\n"
@@ -969,7 +1013,7 @@ set_tcp_socket (void)
   if (! get_server_config (&server, auth_string))
     return INVALID_SOCKET;
 
-  if (server.sin_addr.s_addr != inet_addr ("127.0.0.1"))
+  if (server.sin_addr.s_addr != inet_addr ("127.0.0.1") && !quiet)
     message (FALSE, "%s: connected to remote socket at %s\n",
              progname, inet_ntoa (server.sin_addr));
 
@@ -1073,7 +1117,7 @@ find_tty (const char **tty_type, const char **tty_name, int noabort)
    0 - success: none of the above */
 
 static int
-socket_status (char *name)
+socket_status (const char *name)
 {
   struct stat statbfr;
 
@@ -1090,7 +1134,7 @@ socket_status (char *name)
 /* A signal handler that passes the signal to the Emacs process.
    Useful for SIGWINCH.  */
 
-static SIGTYPE
+static void
 pass_signal_to_emacs (int signalnum)
 {
   int old_errno = errno;
@@ -1105,7 +1149,7 @@ pass_signal_to_emacs (int signalnum)
 /* Signal handler for SIGCONT; notify the Emacs process that it can
    now resume our tty frame.  */
 
-static SIGTYPE
+static void
 handle_sigcont (int signalnum)
 {
   int old_errno = errno;
@@ -1131,7 +1175,7 @@ handle_sigcont (int signalnum)
    reality, we may get a SIGTSTP on C-z.  Handling this signal and
    notifying Emacs about it should get things under control again. */
 
-static SIGTYPE
+static void
 handle_sigtstp (int signalnum)
 {
   int old_errno = errno;
@@ -1497,7 +1541,7 @@ start_daemon_and_retry_set_socket (void)
 int
 main (int argc, char **argv)
 {
-  int rl, needlf = 0;
+  int rl = 0, needlf = 0;
   char *cwd, *str;
   char string[BUFSIZ+1];
   int null_socket_name IF_LINT ( = 0);
@@ -1605,6 +1649,13 @@ main (int argc, char **argv)
       send_to_emacs (emacs_socket, " ");
     }
 
+  if (frame_parameters && !current_frame)
+    {
+      send_to_emacs (emacs_socket, "-frame-parameters ");
+      quote_argument (emacs_socket, frame_parameters);
+      send_to_emacs (emacs_socket, " ");
+    }
+
   /* If using the current frame, send tty information to Emacs anyway.
      In daemon mode, Emacs may need to occupy this tty if no other
      frame is available.  */
@@ -1695,7 +1746,7 @@ main (int argc, char **argv)
   send_to_emacs (emacs_socket, "\n");
 
   /* Wait for an answer. */
-  if (!eval && !tty && !nowait)
+  if (!eval && !tty && !nowait && !quiet)
     {
       printf ("Waiting for Emacs...");
       needlf = 2;