comparison src/nt.c @ 611:38db05db9cb5

[xemacs-hg @ 2001-06-08 12:21:09 by ben] ------ gc-in-window-procedure fixes ------ alloc.c: Create "post-gc actions", to avoid those dreaded "GC during window procedure" problems. event-msw.c: Abort, clean and simple, when GC in window procedure. We want to flush these puppies out. glyphs-msw.c: Use a post-gc action when destroying subwindows. lisp.h: Declare register_post_gc_action(). scrollbar-msw.c: Use a post-gc action when unshowing scrollbar windows, if in gc. redisplay.c: Add comment about the utter evilness of what's going down here. ------ cygwin setitimer fixes ------ Makefile.in.in: Compile profile.c only when HAVE_SETITIMER. nt.c: Style fixes. nt.c: Move setitimer() emulation to win32.c, because Cygwin needs it too. profile.c: Make sure we don't compile if no setitimer(). Use qxe_setitimer() instead of just plain setitimer(). signal.c: Define qxe_setitimer() as an encapsulation around setitimer() -- call setitimer() directly unless Cygwin or MS Win, in which case we use our simulated version in win32.c. systime.h: Prototype mswindows_setitimer() and qxe_setitimer(). Long comment about "qxe" and the policy regarding encapsulation. win32.c: Move setitimer() emulation here, so Cygwin can use it. Rename a couple of functions and variables to be longer and more descriptive. In setitimer_helper_proc(), send the signal using either mswindows_raise() or (on Cygwin) kill(). If for some reason we are still getting lockups, we'll change the kill() to directly invoke the signal handlers. ------ windows shell fixes ------ callproc.c, ntproc.c: Comments about how these two files must die. callproc.c: On MS Windows, init shell-file-name from SHELL, then COMSPEC, not just COMSPEC. (more correct and closer to FSF.) Don't force a value for SHELL into the environment. (Comments added to explain why not.) nt.c: Don't shove a fabricated SHELL into the environment. See above. ------ misc fixes ------ glyphs-shared.c: Style correction. xemacs-faq.texi: Merge in the rest of Hrvoje's Windows FAQ. Redo section 7 to update current reality and add condensed versions of new changes for 21.1 and 21.4. (Not quite done for 21.4.) Lots more Windows updates. process.el: Need to quote a null argument, too. From Dan Holmsand. startup.el: startup.el: Call MS Windows init function. win32-native.el: Correct comments at top. Correctly handle passing arguments to Cygwin programs and to bash. Fix quoting of zero-length arguments (from Dan Holmsand). Set shell-command-switch based on shell-file-name, which in turn comes from env var SHELL.
author ben
date Fri, 08 Jun 2001 12:21:27 +0000
parents 47823c2cf014
children 023b83f4e54b
comparison
equal deleted inserted replaced
610:45ba69404a1f 611:38db05db9cb5
1 /* Utility and Unix shadow routines for XEmacs on Windows NT. 1 /* Utility and Unix shadow routines for XEmacs on MS Windows.
2 Copyright (C) 1994, 1995 Free Software Foundation, Inc. 2 Copyright (C) 1994, 1995 Free Software Foundation, Inc.
3 3
4 This file is part of XEmacs. 4 This file is part of XEmacs.
5 5
6 XEmacs is free software; you can redistribute it and/or modify it 6 XEmacs is free software; you can redistribute it and/or modify it
246 * With XEmacs, setting $HOME is deprecated. 246 * With XEmacs, setting $HOME is deprecated.
247 */ 247 */
248 if (getenv ("HOME") == NULL) 248 if (getenv ("HOME") == NULL)
249 putenv ("HOME=c:/"); 249 putenv ("HOME=c:/");
250 #endif 250 #endif
251 if (getenv ("SHELL") == NULL) 251
252 putenv ((GetVersion () & 0x80000000) ? "SHELL=command" : "SHELL=cmd"); 252 /* Set dir from environment variables. */
253
254 /* Set dir and shell from environment variables. */
255 strcpy (the_passwd.pw_dir, (char *)get_home_directory()); 253 strcpy (the_passwd.pw_dir, (char *)get_home_directory());
256 strcpy (the_passwd.pw_shell, getenv ("SHELL")); 254 /* We used to set pw_shell here, but the order is wrong (SHELL gets
255 init in callproc.c, called later in the init process) and pw_shell
256 is not used anywhere. */
257 } 257 }
258 258
259 /* Normalize filename by converting all path separators to 259 /* Normalize filename by converting all path separators to
260 the specified separator. Also conditionally convert upper 260 the specified separator. Also conditionally convert upper
261 case path name components to lower case. */ 261 case path name components to lower case. */
1825 unsigned signal_block_mask = 0; 1825 unsigned signal_block_mask = 0;
1826 1826
1827 /* Signal pending mask: bit set to 1 means sig is pending */ 1827 /* Signal pending mask: bit set to 1 means sig is pending */
1828 unsigned signal_pending_mask = 0; 1828 unsigned signal_pending_mask = 0;
1829 1829
1830 mswindows_sighandler mswindows_sigset (int nsig, mswindows_sighandler handler) 1830 mswindows_sighandler
1831 mswindows_sigset (int nsig, mswindows_sighandler handler)
1831 { 1832 {
1832 /* We delegate some signals to the system function */ 1833 /* We delegate some signals to the system function */
1833 if (nsig == SIGFPE || nsig == SIGABRT || nsig == SIGINT) 1834 if (nsig == SIGFPE || nsig == SIGABRT || nsig == SIGINT)
1834 return signal (nsig, handler); 1835 return signal (nsig, handler);
1835 1836
1845 signal_handlers[nsig] = handler; 1846 signal_handlers[nsig] = handler;
1846 return old_handler; 1847 return old_handler;
1847 } 1848 }
1848 } 1849 }
1849 1850
1850 int mswindows_sighold (int nsig) 1851 int
1852 mswindows_sighold (int nsig)
1851 { 1853 {
1852 if (nsig < 0 || nsig > SIG_MAX) 1854 if (nsig < 0 || nsig > SIG_MAX)
1853 return errno = EINVAL; 1855 return errno = EINVAL;
1854 1856
1855 signal_block_mask |= sigmask(nsig); 1857 signal_block_mask |= sigmask (nsig);
1856 return 0; 1858 return 0;
1857 } 1859 }
1858 1860
1859 int mswindows_sigrelse (int nsig) 1861 int
1862 mswindows_sigrelse (int nsig)
1860 { 1863 {
1861 if (nsig < 0 || nsig > SIG_MAX) 1864 if (nsig < 0 || nsig > SIG_MAX)
1862 return errno = EINVAL; 1865 return errno = EINVAL;
1863 1866
1864 signal_block_mask &= ~sigmask(nsig); 1867 signal_block_mask &= ~sigmask (nsig);
1865 1868
1866 if (signal_pending_mask & sigmask(nsig)) 1869 if (signal_pending_mask & sigmask (nsig))
1867 mswindows_raise (nsig); 1870 mswindows_raise (nsig);
1868 1871
1869 return 0; 1872 return 0;
1870 } 1873 }
1871 1874
1872 int mswindows_sigpause (int nsig) 1875 int
1873 { 1876 mswindows_sigpause (int nsig)
1874 /* This is currently not called, because the only 1877 {
1875 call to sigpause inside XEmacs is with SIGCHLD 1878 /* This is currently not called, because the only call to sigpause
1876 parameter. Just in case, we put an assert here, 1879 inside XEmacs is with SIGCHLD parameter. Just in case, we put an
1877 so anyone who will add a call to sigpause will 1880 assert here, so anyone adds a call to sigpause will be surprised
1878 be surprised (or surprise someone else...) */ 1881 (or surprise someone else...) */
1879 assert (0); 1882 assert (0);
1880 return 0; 1883 return 0;
1881 } 1884 }
1882 1885
1883 int mswindows_raise (int nsig) 1886 int
1887 mswindows_raise (int nsig)
1884 { 1888 {
1885 /* We delegate some raises to the system routine */ 1889 /* We delegate some raises to the system routine */
1886 if (nsig == SIGFPE || nsig == SIGABRT || nsig == SIGINT) 1890 if (nsig == SIGFPE || nsig == SIGABRT || nsig == SIGINT)
1887 return raise (nsig); 1891 return raise (nsig);
1888 1892
1889 if (nsig < 0 || nsig > SIG_MAX) 1893 if (nsig < 0 || nsig > SIG_MAX)
1890 return errno = EINVAL; 1894 return errno = EINVAL;
1891 1895
1892 /* If the signal is blocked, remember to issue later */ 1896 /* If the signal is blocked, remember to issue later */
1893 if (signal_block_mask & sigmask(nsig)) 1897 if (signal_block_mask & sigmask (nsig))
1894 { 1898 {
1895 signal_pending_mask |= sigmask(nsig); 1899 signal_pending_mask |= sigmask (nsig);
1896 return 0; 1900 return 0;
1897 } 1901 }
1898 1902
1899 if (signal_handlers[nsig] == SIG_IGN) 1903 if (signal_handlers[nsig] == SIG_IGN)
1900 return 0; 1904 return 0;
1901 1905
1902 if (signal_handlers[nsig] != SIG_DFL) 1906 if (signal_handlers[nsig] != SIG_DFL)
1903 { 1907 {
1904 (*signal_handlers[nsig])(nsig); 1908 (*signal_handlers[nsig]) (nsig);
1905 return 0; 1909 return 0;
1906 } 1910 }
1907 1911
1908 /* Default signal actions */ 1912 /* Default signal actions */
1909 if (nsig == SIGALRM || nsig == SIGPROF) 1913 if (nsig == SIGALRM || nsig == SIGPROF)
1910 exit (3); 1914 exit (3);
1911 1915
1912 /* Other signals are ignored by default */ 1916 /* Other signals are ignored by default */
1913 return 0; 1917 return 0;
1914 }
1915
1916 /*--------------------------------------------------------------------*/
1917 /* Async timers */
1918 /*--------------------------------------------------------------------*/
1919
1920 /* We emulate two timers, one for SIGALRM, another for SIGPROF.
1921
1922 itimerproc() function has an implementation limitation: it does
1923 not allow to set *both* interval and period. If an attempt is
1924 made to set both, and then they are unequal, the function
1925 asserts.
1926
1927 Minimum timer resolution on Win32 systems varies, and is greater
1928 than or equal than 1 ms. The resolution is always wrapped not to
1929 attempt to get below the system defined limit.
1930 */
1931
1932 /* Timer precision, denominator of one fraction: for 100 ms
1933 interval, request 10 ms precision
1934 */
1935 const int timer_prec = 10;
1936
1937 /* Last itimervals, as set by calls to setitimer */
1938 static struct itimerval it_alarm;
1939 static struct itimerval it_prof;
1940
1941 /* Timer IDs as returned by MM */
1942 MMRESULT tid_alarm = 0;
1943 MMRESULT tid_prof = 0;
1944
1945 static void CALLBACK timer_proc (UINT uID, UINT uMsg, DWORD dwUser,
1946 DWORD dw1, DWORD dw2)
1947 {
1948 /* Just raise a signal indicated by dwUser parameter */
1949 mswindows_raise (dwUser);
1950 }
1951
1952 /* Divide time in ms specified by IT by DENOM. Return 1 ms
1953 if division results in zero */
1954 static UINT period (const struct itimerval* it, UINT denom)
1955 {
1956 static TIMECAPS time_caps;
1957
1958 UINT res;
1959 const struct timeval* tv =
1960 (it->it_value.tv_sec == 0 && it->it_value.tv_usec == 0)
1961 ? &it->it_interval : &it->it_value;
1962
1963 /* Zero means stop timer */
1964 if (tv->tv_sec == 0 && tv->tv_usec == 0)
1965 return 0;
1966
1967 /* Convert to ms and divide by denom */
1968 res = (tv->tv_sec * 1000 + (tv->tv_usec + 500) / 1000) / denom;
1969
1970 /* Converge to minimum timer resolution */
1971 if (time_caps.wPeriodMin == 0)
1972 timeGetDevCaps (&time_caps, sizeof(time_caps));
1973
1974 if (res < time_caps.wPeriodMin)
1975 res = time_caps.wPeriodMin;
1976
1977 return res;
1978 }
1979
1980 static int setitimer_helper (const struct itimerval* itnew,
1981 struct itimerval* itold, struct itimerval* itcurrent,
1982 MMRESULT* tid, DWORD sigkind)
1983 {
1984 UINT delay, resolution, event_type;
1985
1986 /* First stop the old timer */
1987 if (*tid)
1988 {
1989 timeKillEvent (*tid);
1990 timeEndPeriod (period (itcurrent, timer_prec));
1991 *tid = 0;
1992 }
1993
1994 /* Return old itimerval if requested */
1995 if (itold)
1996 *itold = *itcurrent;
1997
1998 *itcurrent = *itnew;
1999
2000 /* Determine if to start new timer */
2001 delay = period (itnew, 1);
2002 if (delay)
2003 {
2004 resolution = period (itnew, timer_prec);
2005 event_type = (itnew->it_value.tv_sec == 0 && itnew->it_value.tv_usec == 0)
2006 ? TIME_ONESHOT : TIME_PERIODIC;
2007 timeBeginPeriod (resolution);
2008 *tid = timeSetEvent (delay, resolution, timer_proc, sigkind, event_type);
2009 }
2010
2011 return !delay || *tid;
2012 }
2013
2014 int setitimer (int kind, const struct itimerval* itnew,
2015 struct itimerval* itold)
2016 {
2017 /* In this version, both interval and value are allowed
2018 only if they are equal. */
2019 assert ((itnew->it_value.tv_sec == 0 && itnew->it_value.tv_usec == 0)
2020 || (itnew->it_interval.tv_sec == 0 && itnew->it_interval.tv_usec == 0)
2021 || (itnew->it_value.tv_sec == itnew->it_interval.tv_sec &&
2022 itnew->it_value.tv_usec == itnew->it_interval.tv_usec));
2023
2024 if (kind == ITIMER_REAL)
2025 return setitimer_helper (itnew, itold, &it_alarm, &tid_alarm, SIGALRM);
2026 else if (kind == ITIMER_PROF)
2027 return setitimer_helper (itnew, itold, &it_prof, &tid_prof, SIGPROF);
2028 else
2029 return errno = EINVAL;
2030 } 1918 }
2031 1919
2032 1920
2033 /*--------------------------------------------------------------------*/ 1921 /*--------------------------------------------------------------------*/
2034 /* Memory-mapped files */ 1922 /* Memory-mapped files */
2319 2207
2320 /* Close the system structures associated with the given file. */ 2208 /* Close the system structures associated with the given file. */
2321 void 2209 void
2322 close_file_data (file_data *p_file) 2210 close_file_data (file_data *p_file)
2323 { 2211 {
2324 UnmapViewOfFile (p_file->file_base); 2212 UnmapViewOfFile (p_file->file_base);
2325 CloseHandle (p_file->file_mapping); 2213 CloseHandle (p_file->file_mapping);
2326 CloseHandle (p_file->file); 2214 CloseHandle (p_file->file);
2327 } 2215 }
2328 2216
2329 void 2217 void
2330 vars_of_nt (void) 2218 vars_of_nt (void)
2331 { 2219 {