(U+7EBB): Unify RUI6-E123; add `<-simplified@CN/misc' for U+7D35.
[chise/xemacs-chise.git.1] / src / nt.c
index 0824e2a..1e26fbb 100644 (file)
--- a/src/nt.c
+++ b/src/nt.c
@@ -1,4 +1,4 @@
-/* Utility and Unix shadow routines for XEmacs on Windows NT.
+/* Utility and Unix shadow routines for XEmacs on MS Windows.
    Copyright (C) 1994, 1995 Free Software Foundation, Inc.
 
 This file is part of XEmacs.
    Copyright (C) 1994, 1995 Free Software Foundation, Inc.
 
 This file is part of XEmacs.
@@ -28,6 +28,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #define getwd _getwd
 #include "lisp.h"
 #undef getwd
 #define getwd _getwd
 #include "lisp.h"
 #undef getwd
+#include "buffer.h"
 
 #include "systime.h"
 #include "syssignal.h"
 
 #include "systime.h"
 #include "syssignal.h"
@@ -246,12 +247,12 @@ init_user_info (void)
   if (getenv ("HOME") == NULL)
     putenv ("HOME=c:/");
 #endif
   if (getenv ("HOME") == NULL)
     putenv ("HOME=c:/");
 #endif
-  if (getenv ("SHELL") == NULL)
-    putenv ((GetVersion () & 0x80000000) ? "SHELL=command" : "SHELL=cmd");
 
 
-  /* Set dir and shell from environment variables. */
+  /* Set dir from environment variables. */
   strcpy (the_passwd.pw_dir, (char *)get_home_directory());
   strcpy (the_passwd.pw_dir, (char *)get_home_directory());
-  strcpy (the_passwd.pw_shell, getenv ("SHELL"));
+  /* We used to set pw_shell here, but the order is wrong (SHELL gets
+     init in callproc.c, called later in the init process) and pw_shell
+     is not used anywhere. */
 }
 
 /* Normalize filename by converting all path separators to
 }
 
 /* Normalize filename by converting all path separators to
@@ -505,7 +506,7 @@ request_sigio (void)
 }
 #endif /* 0 */
 
 }
 #endif /* 0 */
 
-#define REG_ROOT "SOFTWARE\\GNU\\XEmacs"
+#define REG_ROOT "SOFTWARE\\XEmacs\\XEmacs"
 
 LPBYTE 
 nt_get_resource (char *key, LPDWORD lpdwtype)
 
 LPBYTE 
 nt_get_resource (char *key, LPDWORD lpdwtype)
@@ -628,16 +629,16 @@ init_environment (void)
      renaming or deleting directories.  (We also don't call chdir when
      running subprocesses for the same reason.)  */
   if (!GetCurrentDirectory (MAXPATHLEN, startup_dir))
      renaming or deleting directories.  (We also don't call chdir when
      running subprocesses for the same reason.)  */
   if (!GetCurrentDirectory (MAXPATHLEN, startup_dir))
-    abort ();
+    ABORT ();
 
   {
     char *p;
     char modname[MAX_PATH];
 
     if (!GetModuleFileName (NULL, modname, MAX_PATH))
 
   {
     char *p;
     char modname[MAX_PATH];
 
     if (!GetModuleFileName (NULL, modname, MAX_PATH))
-      abort ();
+      ABORT ();
     if ((p = strrchr (modname, '\\')) == NULL)
     if ((p = strrchr (modname, '\\')) == NULL)
-      abort ();
+      ABORT ();
     *p = 0;
 
     SetCurrentDirectory (modname);
     *p = 0;
 
     SetCurrentDirectory (modname);
@@ -1177,12 +1178,11 @@ sys_rename (const char * oldname, const char * newname)
 #endif /* 0 */
 
 static FILETIME utc_base_ft;
 #endif /* 0 */
 
 static FILETIME utc_base_ft;
+static long double utc_base;
 static int init = 0;
 
 #if 0
 
 static int init = 0;
 
 #if 0
 
-static long double utc_base;
-
 time_t
 convert_time (FILETIME ft)
 {
 time_t
 convert_time (FILETIME ft)
 {
@@ -1216,11 +1216,6 @@ convert_time (FILETIME ft)
 }
 #else
 
 }
 #else
 
-#if defined(MINGW) && CYGWIN_VERSION_DLL_MAJOR <= 21
-#define LowPart u.LowPart
-#define HighPart u.HighPart
-#endif
-
 static LARGE_INTEGER utc_base_li;
 
 time_t
 static LARGE_INTEGER utc_base_li;
 
 time_t
@@ -1361,7 +1356,7 @@ generate_inode_val (const char * name)
      doesn't resolve aliasing due to subst commands, or recognize hard
      links.  */
   if (!win32_get_long_filename ((char *)name, fullname, MAX_PATH))
      doesn't resolve aliasing due to subst commands, or recognize hard
      links.  */
   if (!win32_get_long_filename ((char *)name, fullname, MAX_PATH))
-    abort ();
+    ABORT ();
 
   parse_root (fullname, &p);
   /* Normal Win32 filesystems are still case insensitive. */
 
   parse_root (fullname, &p);
   /* Normal Win32 filesystems are still case insensitive. */
@@ -1421,7 +1416,7 @@ mswindows_fstat (int desc, struct stat * buf)
     }
   else
     {
     }
   else
     {
-      buf->st_nlink = info.nNumberOfLinks;
+      buf->st_nlink = (short) info.nNumberOfLinks;
       /* Might as well use file index to fake inode values, but this
         is not guaranteed to be unique unless we keep a handle open
         all the time (even then there are situations where it is
       /* Might as well use file index to fake inode values, but this
         is not guaranteed to be unique unless we keep a handle open
         all the time (even then there are situations where it is
@@ -1432,9 +1427,9 @@ mswindows_fstat (int desc, struct stat * buf)
 
   /* MSVC defines _ino_t to be short; other libc's might not.  */
   if (sizeof (buf->st_ino) == 2)
 
   /* MSVC defines _ino_t to be short; other libc's might not.  */
   if (sizeof (buf->st_ino) == 2)
-    buf->st_ino = fake_inode ^ (fake_inode >> 16);
+    buf->st_ino = (unsigned short) (fake_inode ^ (fake_inode >> 16));
   else
   else
-    buf->st_ino = fake_inode;
+    buf->st_ino = (unsigned short) fake_inode;
 
   /* consider files to belong to current user */
   buf->st_uid = 0;
 
   /* consider files to belong to current user */
   buf->st_uid = 0;
@@ -1454,9 +1449,9 @@ mswindows_fstat (int desc, struct stat * buf)
 
   /* determine rwx permissions */
   if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
 
   /* determine rwx permissions */
   if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
-    permission = _S_IREAD;
+    permission = _S_IREAD | _S_IEXEC;
   else
   else
-    permission = _S_IREAD | _S_IWRITE;
+    permission = _S_IREAD | _S_IEXEC |_S_IWRITE;
   
   if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
     permission |= _S_IEXEC;
   
   if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
     permission |= _S_IEXEC;
@@ -1479,6 +1474,7 @@ mswindows_stat (const char * path, struct stat * buf)
   int permission;
   int len;
   int rootdir = FALSE;
   int permission;
   int len;
   int rootdir = FALSE;
+  int errm;
 
   if (path == NULL || buf == NULL)
     {
 
   if (path == NULL || buf == NULL)
     {
@@ -1501,13 +1497,16 @@ mswindows_stat (const char * path, struct stat * buf)
   rootdir = (path >= name + len - 1
             && (IS_DIRECTORY_SEP (*path) || *path == 0));
   name = strcpy ((char *)alloca (len + 2), name);
   rootdir = (path >= name + len - 1
             && (IS_DIRECTORY_SEP (*path) || *path == 0));
   name = strcpy ((char *)alloca (len + 2), name);
-
+  errm = SetErrorMode (SEM_FAILCRITICALERRORS
+                      | SEM_NOOPENFILEERRORBOX);
   if (rootdir)
     {
       if (!IS_DIRECTORY_SEP (name[len-1]))
        strcat (name, "\\");
   if (rootdir)
     {
       if (!IS_DIRECTORY_SEP (name[len-1]))
        strcat (name, "\\");
+
       if (GetDriveType (name) < 2)
        {
       if (GetDriveType (name) < 2)
        {
+         SetErrorMode (errm);
          errno = ENOENT;
          return -1;
        }
          errno = ENOENT;
          return -1;
        }
@@ -1537,14 +1536,15 @@ mswindows_stat (const char * path, struct stat * buf)
        }
       else
        {
        }
       else
        {
-      fh = FindFirstFile (name, &wfd);
-      if (fh == INVALID_HANDLE_VALUE)
-       {
-         errno = ENOENT;
-         return -1;
+         fh = FindFirstFile (name, &wfd);
+         if (fh == INVALID_HANDLE_VALUE)
+           {
+             SetErrorMode (errm);
+             errno = ENOENT;
+             return -1;
+           }
+         FindClose (fh);
        }
        }
-      FindClose (fh);
-    }
     }
 
   if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
     }
 
   if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
@@ -1590,6 +1590,7 @@ mswindows_stat (const char * path, struct stat * buf)
        }
       else
        {
        }
       else
        {
+         SetErrorMode (errm);
          errno = EACCES;
          return -1;
        }
          errno = EACCES;
          return -1;
        }
@@ -1602,6 +1603,8 @@ mswindows_stat (const char * path, struct stat * buf)
       fake_inode = 0;
     }
 
       fake_inode = 0;
     }
 
+  SetErrorMode (errm);
+
 #if 0
   /* Not sure if there is any point in this.  */
   if (!NILP (Vwin32_generate_fake_inodes))
 #if 0
   /* Not sure if there is any point in this.  */
   if (!NILP (Vwin32_generate_fake_inodes))
@@ -1618,7 +1621,7 @@ mswindows_stat (const char * path, struct stat * buf)
   buf->st_ino = (unsigned short) (fake_inode ^ (fake_inode >> 16));
 
   /* consider files to belong to current user */
   buf->st_ino = (unsigned short) (fake_inode ^ (fake_inode >> 16));
 
   /* consider files to belong to current user */
-  buf->st_uid = buf->st_gid = nt_fake_unix_uid;
+  buf->st_uid = buf->st_gid = (short) nt_fake_unix_uid;
 
   /* volume_info is set indirectly by map_win32_filename */
   buf->st_dev = volume_info.serialnum;
 
   /* volume_info is set indirectly by map_win32_filename */
   buf->st_dev = volume_info.serialnum;
@@ -1635,22 +1638,12 @@ mswindows_stat (const char * path, struct stat * buf)
 
   /* determine rwx permissions */
   if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
 
   /* determine rwx permissions */
   if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
-    permission = _S_IREAD;
+    permission = _S_IREAD | _S_IEXEC;
   else
   else
-    permission = _S_IREAD | _S_IWRITE;
+    permission = _S_IREAD | _S_IEXEC |_S_IWRITE;
   
   if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
     permission |= _S_IEXEC;
   
   if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
     permission |= _S_IEXEC;
-  else
-    {
-      char * p = strrchr (name, '.');
-      if (p != NULL &&
-         (stricmp (p, ".exe") == 0 ||
-          stricmp (p, ".com") == 0 ||
-          stricmp (p, ".bat") == 0 ||
-          stricmp (p, ".cmd") == 0))
-       permission |= _S_IEXEC;
-    }
 
   buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
 
 
   buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
 
@@ -1829,7 +1822,8 @@ unsigned signal_block_mask = 0;
 /* Signal pending mask: bit set to 1 means sig is pending */
 unsigned signal_pending_mask = 0;
 
 /* Signal pending mask: bit set to 1 means sig is pending */
 unsigned signal_pending_mask = 0;
 
-mswindows_sighandler mswindows_sigset (int nsig, mswindows_sighandler handler)
+mswindows_sighandler
+mswindows_sigset (int nsig, mswindows_sighandler handler)
 {
   /* We delegate some signals to the system function */
   if (nsig == SIGFPE || nsig == SIGABRT || nsig == SIGINT)
 {
   /* We delegate some signals to the system function */
   if (nsig == SIGFPE || nsig == SIGABRT || nsig == SIGINT)
@@ -1849,40 +1843,43 @@ mswindows_sighandler mswindows_sigset (int nsig, mswindows_sighandler handler)
   }
 }
   
   }
 }
   
-int mswindows_sighold (int nsig)
+int
+mswindows_sighold (int nsig)
 {
   if (nsig < 0 || nsig > SIG_MAX)
     return errno = EINVAL;
 
 {
   if (nsig < 0 || nsig > SIG_MAX)
     return errno = EINVAL;
 
-  signal_block_mask |= sigmask(nsig);
+  signal_block_mask |= sigmask (nsig);
   return 0;
 }
 
   return 0;
 }
 
-int mswindows_sigrelse (int nsig)
+int
+mswindows_sigrelse (int nsig)
 {
   if (nsig < 0 || nsig > SIG_MAX)
     return errno = EINVAL;
 
 {
   if (nsig < 0 || nsig > SIG_MAX)
     return errno = EINVAL;
 
-  signal_block_mask &= ~sigmask(nsig);
+  signal_block_mask &= ~sigmask (nsig);
 
 
-  if (signal_pending_mask & sigmask(nsig))
+  if (signal_pending_mask & sigmask (nsig))
     mswindows_raise (nsig);
 
   return 0;
 }
 
     mswindows_raise (nsig);
 
   return 0;
 }
 
-int mswindows_sigpause (int nsig)
+int
+mswindows_sigpause (int nsig)
 {
 {
-  /* This is currently not called, because the only
-     call to sigpause inside XEmacs is with SIGCHLD
-     parameter. Just in case, we put an assert here,
-     so anyone who will add a call to sigpause will
-     be surprised (or surprise someone else...) */
+  /* This is currently not called, because the only call to sigpause
+     inside XEmacs is with SIGCHLD parameter. Just in case, we put an
+     assert here, so anyone adds a call to sigpause will be surprised
+     (or surprise someone else...) */
   assert (0);
   return 0;
 }
 
   assert (0);
   return 0;
 }
 
-int mswindows_raise (int nsig)
+int
+mswindows_raise (int nsig)
 {
   /* We delegate some raises to the system routine */
   if (nsig == SIGFPE || nsig == SIGABRT || nsig == SIGINT)
 {
   /* We delegate some raises to the system routine */
   if (nsig == SIGFPE || nsig == SIGABRT || nsig == SIGINT)
@@ -1892,9 +1889,9 @@ int mswindows_raise (int nsig)
     return errno = EINVAL;
 
   /* If the signal is blocked, remember to issue later */
     return errno = EINVAL;
 
   /* If the signal is blocked, remember to issue later */
-  if (signal_block_mask & sigmask(nsig))
+  if (signal_block_mask & sigmask (nsig))
     {
     {
-      signal_pending_mask |= sigmask(nsig);
+      signal_pending_mask |= sigmask (nsig);
       return 0;
     }
 
       return 0;
     }
 
@@ -1903,7 +1900,7 @@ int mswindows_raise (int nsig)
 
   if (signal_handlers[nsig] != SIG_DFL)
     {
 
   if (signal_handlers[nsig] != SIG_DFL)
     {
-      (*signal_handlers[nsig])(nsig);
+      (*signal_handlers[nsig]) (nsig);
       return 0;
     }
 
       return 0;
     }
 
@@ -1915,122 +1912,6 @@ int mswindows_raise (int nsig)
   return 0;
 }
 
   return 0;
 }
 
-/*--------------------------------------------------------------------*/
-/* Async timers                                                       */
-/*--------------------------------------------------------------------*/
-
-/* We emulate two timers, one for SIGALRM, another for SIGPROF.
-
-   itimerproc() function has an implementation limitation: it does
-   not allow to set *both* interval and period. If an attempt is
-   made to set both, and then they are unequal, the function
-   asserts.
-
-   Minimum timer resolution on Win32 systems varies, and is greater
-   than or equal than 1 ms. The resolution is always wrapped not to
-   attempt to get below the system defined limit.
-   */
-
-/* Timer precision, denominator of one fraction: for 100 ms
-   interval, request 10 ms precision
-   */
-const int timer_prec = 10;
-
-/* Last itimervals, as set by calls to setitimer */
-static struct itimerval it_alarm;
-static struct itimerval it_prof;
-
-/* Timer IDs as returned by MM */
-MMRESULT tid_alarm = 0;
-MMRESULT tid_prof = 0;
-
-static void CALLBACK timer_proc (UINT uID, UINT uMsg, DWORD dwUser,
-                                DWORD dw1, DWORD dw2)
-{
-  /* Just raise a signal indicated by dwUser parameter */
-  mswindows_raise (dwUser);
-}
-
-/* Divide time in ms specified by IT by DENOM. Return 1 ms
-   if division results in zero */
-static UINT period (const struct itimerval* it, UINT denom)
-{
-  static TIMECAPS time_caps;
-
-  UINT res;
-  const struct timeval* tv = 
-    (it->it_value.tv_sec == 0 && it->it_value.tv_usec == 0)
-    ? &it->it_interval : &it->it_value;
-  
-  /* Zero means stop timer */
-  if (tv->tv_sec == 0 && tv->tv_usec == 0)
-    return 0;
-  
-  /* Convert to ms and divide by denom */
-  res = (tv->tv_sec * 1000 + (tv->tv_usec + 500) / 1000) / denom;
-  
-  /* Converge to minimum timer resolution */
-  if (time_caps.wPeriodMin == 0)
-      timeGetDevCaps (&time_caps, sizeof(time_caps));
-
-  if (res < time_caps.wPeriodMin)
-    res = time_caps.wPeriodMin;
-
-  return res;
-}
-
-static int setitimer_helper (const struct itimerval* itnew,
-                            struct itimerval* itold, struct itimerval* itcurrent,
-                            MMRESULT* tid, DWORD sigkind)
-{
-  UINT delay, resolution, event_type;
-
-  /* First stop the old timer */
-  if (*tid)
-    {
-      timeKillEvent (*tid);
-      timeEndPeriod (period (itcurrent, timer_prec));
-      *tid = 0;
-    }
-
-  /* Return old itimerval if requested */
-  if (itold)
-    *itold = *itcurrent;
-
-  *itcurrent = *itnew;
-
-  /* Determine if to start new timer */
-  delay = period (itnew, 1);
-  if (delay)
-    {
-      resolution = period (itnew, timer_prec);
-      event_type = (itnew->it_value.tv_sec == 0 && itnew->it_value.tv_usec == 0)
-       ? TIME_ONESHOT : TIME_PERIODIC;
-      timeBeginPeriod (resolution);
-      *tid = timeSetEvent (delay, resolution, timer_proc, sigkind, event_type);
-    }
-
-  return !delay || *tid;
-}
-int setitimer (int kind, const struct itimerval* itnew,
-              struct itimerval* itold)
-{
-  /* In this version, both interval and value are allowed
-     only if they are equal. */
-  assert ((itnew->it_value.tv_sec == 0 && itnew->it_value.tv_usec == 0)
-         || (itnew->it_interval.tv_sec == 0 && itnew->it_interval.tv_usec == 0)
-         || (itnew->it_value.tv_sec == itnew->it_interval.tv_sec &&
-             itnew->it_value.tv_usec == itnew->it_interval.tv_usec));
-
-  if (kind == ITIMER_REAL)
-    return setitimer_helper (itnew, itold, &it_alarm, &tid_alarm, SIGALRM);
-  else if (kind == ITIMER_PROF)
-    return setitimer_helper (itnew, itold, &it_prof, &tid_prof, SIGPROF);
-  else
-    return errno = EINVAL;
-}
-
 \f
 /*--------------------------------------------------------------------*/
 /*                        Memory-mapped files                         */
 \f
 /*--------------------------------------------------------------------*/
 /*                        Memory-mapped files                         */
@@ -2242,13 +2123,90 @@ mswindows_executable_type (const char * filename, int * is_dos_app,
   close_file_data (&executable);
 }
 
   close_file_data (&executable);
 }
 
+static void
+convert_from_time_t (time_t time, FILETIME * pft)
+{
+  long double tmp;
+
+  if (!init)
+    {
+      /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
+      SYSTEMTIME st;
+
+      st.wYear = 1970;
+      st.wMonth = 1;
+      st.wDay = 1;
+      st.wHour = 0;
+      st.wMinute = 0;
+      st.wSecond = 0;
+      st.wMilliseconds = 0;
+
+      SystemTimeToFileTime (&st, &utc_base_ft);
+      utc_base = (long double) utc_base_ft.dwHighDateTime
+       * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
+      init = 1;
+    }
+
+  /* time in 100ns units since 1-Jan-1601 */
+  tmp = (long double) time * 1e7 + utc_base;
+  pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024));
+  pft->dwLowDateTime = (DWORD) (tmp - (4096.0 * 1024 * 1024) *
+                                pft->dwHighDateTime);
+}
+
+int
+mswindows_utime (Lisp_Object path, struct utimbuf *times)
+{
+  struct utimbuf deftime;
+#if 0
+  HANDLE fh;
+#endif
+  static FILETIME mtime;
+  static FILETIME atime;
+  Extbyte *filename;
+
+  if (times == NULL)
+    {
+      deftime.modtime = deftime.actime = time (NULL);
+      times = &deftime;
+    }
+
+  LISP_STRING_TO_EXTERNAL (path, filename, Qmswindows_tstr);
+  /* APA: SetFileTime fails to set mtime correctly (always 1-Jan-1970) */
+#if 0
+  /* Need write access to set times.  */
+  fh = CreateFile (filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
+                  0, OPEN_EXISTING, 0, NULL);
+  if (fh)
+    {
+      convert_from_time_t (times->actime, &atime);
+      convert_from_time_t (times->modtime, &mtime);
+      if (!SetFileTime (fh, NULL, &atime, &mtime))
+       {
+         CloseHandle (fh);
+         errno = EACCES;
+         return -1;
+       }
+      CloseHandle (fh);
+    }
+  else
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  return 0;
+#else
+  return utime (filename, times);
+#endif
+}
+
 /* Close the system structures associated with the given file.  */
 void
 close_file_data (file_data *p_file)
 {
 /* Close the system structures associated with the given file.  */
 void
 close_file_data (file_data *p_file)
 {
-    UnmapViewOfFile (p_file->file_base);
-    CloseHandle (p_file->file_mapping);
-    CloseHandle (p_file->file);
+  UnmapViewOfFile (p_file->file_base);
+  CloseHandle (p_file->file_mapping);
+  CloseHandle (p_file->file);
 }
 
 void
 }
 
 void