(highlight-save-buffer-state): New macro.
[bpt/emacs.git] / nt / cmdproxy.c
index 312d6f6..631570b 100644 (file)
@@ -1,5 +1,6 @@
 /* Proxy shell designed for use with Emacs on Windows 95 and NT.
 /* Proxy shell designed for use with Emacs on Windows 95 and NT.
-   Copyright (C) 1997 Free Software Foundation, Inc.
+   Copyright (C) 1997, 2001, 2002, 2003, 2004, 2005,
+      2006, 2007, 2008  Free Software Foundation, Inc.
 
    Accepts subset of Unix sh(1) command-line options, for compatability
    with elisp code written for Unix.  When possible, executes external
 
    Accepts subset of Unix sh(1) command-line options, for compatability
    with elisp code written for Unix.  When possible, executes external
@@ -16,7 +17,7 @@ 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
 
 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 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -26,8 +27,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 #include <windows.h>
 
 
 #include <windows.h>
 
@@ -158,6 +159,7 @@ get_next_token (char * buf, char ** pSrc)
          if (p[0] == escape_char && escape_char != '"')
            {
              escape_char_run++;
          if (p[0] == escape_char && escape_char != '"')
            {
              escape_char_run++;
+             p++;
              continue;
            }
          else if (p[0] == '"')
              continue;
            }
          else if (p[0] == '"')
@@ -229,7 +231,7 @@ search_dir (char *dir, char *exec, int bufsize, char *buffer)
   int i, rc;
 
   /* Search the directory for the program.  */
   int i, rc;
 
   /* Search the directory for the program.  */
-  for (i = 0; i < n_exts; i++) 
+  for (i = 0; i < n_exts; i++)
     {
       rc = SearchPath (dir, exec, exts[i], bufsize, buffer, &dummy);
       if (rc > 0)
     {
       rc = SearchPath (dir, exec, exts[i], bufsize, buffer, &dummy);
       if (rc > 0)
@@ -239,7 +241,7 @@ search_dir (char *dir, char *exec, int bufsize, char *buffer)
   return 0;
 }
 
   return 0;
 }
 
-/* Return the absolute name of executable file PROG, including 
+/* Return the absolute name of executable file PROG, including
    any file extensions.  If an absolute name for PROG cannot be found,
    return NULL.  */
 char *
    any file extensions.  If an absolute name for PROG cannot be found,
    return NULL.  */
 char *
@@ -271,18 +273,18 @@ make_absolute (char *prog)
        return NULL;
     }
 
        return NULL;
     }
 
-  if (GetCurrentDirectory (MAX_PATH, curdir) <= 0) 
+  if (GetCurrentDirectory (MAX_PATH, curdir) <= 0)
     return NULL;
 
   /* Relative path; search in current dir. */
     return NULL;
 
   /* Relative path; search in current dir. */
-  if (strpbrk (prog, "\\")) 
+  if (strpbrk (prog, "\\"))
     {
       if (search_dir (curdir, prog, MAX_PATH, absname) > 0)
        return strdup (absname);
     {
       if (search_dir (curdir, prog, MAX_PATH, absname) > 0)
        return strdup (absname);
-      else 
+      else
        return NULL;
     }
        return NULL;
     }
-  
+
   /* Just filename; search current directory then PATH.  */
   path = alloca (strlen (getenv ("PATH")) + strlen (curdir) + 2);
   strcpy (path, curdir);
   /* Just filename; search current directory then PATH.  */
   path = alloca (strlen (getenv ("PATH")) + strlen (curdir) + 2);
   strcpy (path, curdir);
@@ -303,7 +305,7 @@ make_absolute (char *prog)
 
       /* Move to the next directory.  */
       path = p + 1;
 
       /* Move to the next directory.  */
       path = p + 1;
-    } 
+    }
 
   return NULL;
 }
 
   return NULL;
 }
@@ -321,7 +323,7 @@ setup_argv (void)
   char * cmdline = GetCommandLine ();
   int arg_bytes = 0;
 
   char * cmdline = GetCommandLine ();
   int arg_bytes = 0;
 
-  
+
 }
 #endif
 
 }
 #endif
 
@@ -369,7 +371,7 @@ console_event_handler (DWORD event)
 /* Change from normal usage; return value indicates whether spawn
    succeeded or failed - program return code is returned separately.  */
 int
 /* Change from normal usage; return value indicates whether spawn
    succeeded or failed - program return code is returned separately.  */
 int
-spawn (char * progname, char * cmdline, int * retcode)
+spawn (char * progname, char * cmdline, char * dir, int * retcode)
 {
   BOOL success = FALSE;
   SECURITY_ATTRIBUTES sec_attrs;
 {
   BOOL success = FALSE;
   SECURITY_ATTRIBUTES sec_attrs;
@@ -383,12 +385,12 @@ spawn (char * progname, char * cmdline, int * retcode)
   sec_attrs.nLength = sizeof (sec_attrs);
   sec_attrs.lpSecurityDescriptor = NULL;
   sec_attrs.bInheritHandle = FALSE;
   sec_attrs.nLength = sizeof (sec_attrs);
   sec_attrs.lpSecurityDescriptor = NULL;
   sec_attrs.bInheritHandle = FALSE;
-  
+
   memset (&start, 0, sizeof (start));
   start.cb = sizeof (start);
 
   if (CreateProcess (progname, cmdline, &sec_attrs, NULL, TRUE,
   memset (&start, 0, sizeof (start));
   start.cb = sizeof (start);
 
   if (CreateProcess (progname, cmdline, &sec_attrs, NULL, TRUE,
-                    0, envblock, NULL, &start, &child))
+                    0, envblock, dir, &start, &child))
   {
     success = TRUE;
     /* wait for completion and pass on return code */
   {
     success = TRUE;
     /* wait for completion and pass on return code */
@@ -432,12 +434,16 @@ main (int argc, char ** argv)
   int num_pass_through_args;
   char modname[MAX_PATH];
   char path[MAX_PATH];
   int num_pass_through_args;
   char modname[MAX_PATH];
   char path[MAX_PATH];
+  char dir[MAX_PATH];
 
 
   interactive = TRUE;
 
   SetConsoleCtrlHandler ((PHANDLER_ROUTINE) console_event_handler, TRUE);
 
 
 
   interactive = TRUE;
 
   SetConsoleCtrlHandler ((PHANDLER_ROUTINE) console_event_handler, TRUE);
 
+  if (!GetCurrentDirectory (sizeof (dir), dir))
+    fail ("error: GetCurrentDirectory failed\n");
+
   /* We serve double duty: we can be called either as a proxy for the
      real shell (that is, because we are defined to be the user shell),
      or in our role as a helper application for running DOS programs.
   /* We serve double duty: we can be called either as a proxy for the
      real shell (that is, because we are defined to be the user shell),
      or in our role as a helper application for running DOS programs.
@@ -453,16 +459,33 @@ main (int argc, char ** argv)
   if (!GetModuleFileName (NULL, modname, sizeof (modname)))
     fail ("error: GetModuleFileName failed\n");
 
   if (!GetModuleFileName (NULL, modname, sizeof (modname)))
     fail ("error: GetModuleFileName failed\n");
 
+  /* Change directory to location of .exe so startup directory can be
+     deleted.  */
+  progname = strrchr (modname, '\\');
+  *progname = '\0';
+  SetCurrentDirectory (modname);
+  *progname = '\\';
+
+  /* Due to problems with interaction between API functions that use "OEM"
+     codepage vs API functions that use the "ANSI" codepage, we need to
+     make things consistent by choosing one and sticking with it.  */
+  SetConsoleCP (GetACP());
+  SetConsoleOutputCP (GetACP());
+
   /* Although Emacs always sets argv[0] to an absolute pathname, we
      might get run in other ways as well, so convert argv[0] to an
   /* Although Emacs always sets argv[0] to an absolute pathname, we
      might get run in other ways as well, so convert argv[0] to an
-     absolute name before comparing to the module name.  */
+     absolute name before comparing to the module name.  Don't get
+     caught out by mixed short and long names.  */
+  GetShortPathName (modname, modname, sizeof (modname));
+  path[0] = '\0';
   if (!SearchPath (NULL, argv[0], ".exe", sizeof (path), path, &progname)
   if (!SearchPath (NULL, argv[0], ".exe", sizeof (path), path, &progname)
+      || !GetShortPathName (path, path, sizeof (path))
       || stricmp (modname, path) != 0)
     {
       /* We are being used as a helper to run a DOS app; just pass
         command line to DOS app without change.  */
       /* TODO: fill in progname.  */
       || stricmp (modname, path) != 0)
     {
       /* We are being used as a helper to run a DOS app; just pass
         command line to DOS app without change.  */
       /* TODO: fill in progname.  */
-      if (spawn (NULL, GetCommandLine (), &rc))
+      if (spawn (NULL, GetCommandLine (), dir, &rc))
        return rc;
       fail ("Could not run %s\n", GetCommandLine ());
     }
        return rc;
       fail ("Could not run %s\n", GetCommandLine ());
     }
@@ -510,7 +533,7 @@ main (int argc, char ** argv)
              if (cmdline)
                warn ("warning: %s ignored because of -c\n", *argv);
            }
              if (cmdline)
                warn ("warning: %s ignored because of -c\n", *argv);
            }
-         else if (((*argv)[1] == 'e' || (*argv[1] == 'E')) && ((*argv)[2] == ':'))
+         else if (((*argv)[1] == 'e' || (*argv)[1] == 'E') && ((*argv)[2] == ':'))
            {
              int requested_envsize = atoi (*argv + 3);
              /* Enforce a reasonable minimum size, as above.  */
            {
              int requested_envsize = atoi (*argv + 3);
              /* Enforce a reasonable minimum size, as above.  */
@@ -583,6 +606,7 @@ main (int argc, char ** argv)
     {
       char * p;
       int    extra_arg_space = 0;
     {
       char * p;
       int    extra_arg_space = 0;
+      int    run_command_dot_com;
 
       progname = getenv ("COMSPEC");
       if (!progname)
 
       progname = getenv ("COMSPEC");
       if (!progname)
@@ -594,6 +618,10 @@ main (int argc, char ** argv)
       if (progname == NULL || strchr (progname, '\\') == NULL)
        fail ("error: the program %s could not be found.\n", getenv ("COMSPEC"));
 
       if (progname == NULL || strchr (progname, '\\') == NULL)
        fail ("error: the program %s could not be found.\n", getenv ("COMSPEC"));
 
+      /* Need to set environment size when running command.com.  */
+      run_command_dot_com =
+       (stricmp (strrchr (progname, '\\'), "command.com") == 0);
+
       /* Work out how much extra space is required for
          pass_through_args.  */
       for (argv = pass_through_args; *argv != NULL; ++argv)
       /* Work out how much extra space is required for
          pass_through_args.  */
       for (argv = pass_through_args; *argv != NULL; ++argv)
@@ -620,8 +648,7 @@ main (int argc, char ** argv)
          for (argv = pass_through_args; *argv != NULL; ++argv)
            p += wsprintf (p, " %s", *argv);
 
          for (argv = pass_through_args; *argv != NULL; ++argv)
            p += wsprintf (p, " %s", *argv);
 
-         if (GetVersion () & 0x80000000)
-           /* Set environment size to something reasonable on Windows 95.  */
+         if (run_command_dot_com)
            wsprintf(p, " /e:%d /c %s", envsize, cmdline);
          else
            wsprintf(p, " /c %s", cmdline);
            wsprintf(p, " /e:%d /c %s", envsize, cmdline);
          else
            wsprintf(p, " /c %s", cmdline);
@@ -629,12 +656,10 @@ main (int argc, char ** argv)
        }
       else
        {
        }
       else
        {
-         if (GetVersion () & 0x80000000)
+         if (run_command_dot_com)
            {
              /* Provide dir arg expected by command.com when first
            {
              /* Provide dir arg expected by command.com when first
-                started interactively (the "command search path").
-                cmd.exe does not require it, but accepts it silently -
-                presumably other DOS compatible shells do the same.  To
+                started interactively (the "command search path").  To
                 avoid potential problems with spaces in command dir
                 (which cannot be quoted - command.com doesn't like it),
                 we always use the 8.3 form.  */
                 avoid potential problems with spaces in command dir
                 (which cannot be quoted - command.com doesn't like it),
                 we always use the 8.3 form.  */
@@ -644,7 +669,6 @@ main (int argc, char ** argv)
              *(++p) = '\0';
            }
          else
              *(++p) = '\0';
            }
          else
-           /* Dir arg not needed on NT.  */
            path[0] = '\0';
 
          cmdline = p = alloca (strlen (progname) + extra_arg_space +
            path[0] = '\0';
 
          cmdline = p = alloca (strlen (progname) + extra_arg_space +
@@ -658,8 +682,7 @@ main (int argc, char ** argv)
          for (argv = pass_through_args; *argv != NULL; ++argv)
            p += wsprintf (p, " %s", *argv);
 
          for (argv = pass_through_args; *argv != NULL; ++argv)
            p += wsprintf (p, " %s", *argv);
 
-         if (GetVersion () & 0x80000000)
-           /* Set environment size to something reasonable on Windows 95.  */
+         if (run_command_dot_com)
            wsprintf (p, " /e:%d", envsize);
        }
     }
            wsprintf (p, " /e:%d", envsize);
        }
     }
@@ -670,7 +693,7 @@ main (int argc, char ** argv)
   if (!cmdline)
     cmdline = progname;
 
   if (!cmdline)
     cmdline = progname;
 
-  if (spawn (progname, cmdline, &rc))
+  if (spawn (progname, cmdline, dir, &rc))
     return rc;
 
   if (!need_shell)
     return rc;
 
   if (!need_shell)
@@ -683,3 +706,6 @@ main (int argc, char ** argv)
 
   return 0;
 }
 
   return 0;
 }
+
+/* arch-tag: 88678d93-07ac-4e2f-ad63-d4a740ca69ac
+   (do not change this comment) */