]> code.delx.au - gnu-emacs/blobdiff - src/msdos.c
(substitute-key-definition): Fix previous change.
[gnu-emacs] / src / msdos.c
index 9291dd08f2628611278d303430a9091bf2248c59..94b75a5efc30c8920c9b3eabdbcbe8ef90bac1a9 100644 (file)
@@ -33,12 +33,16 @@ Boston, MA 02111-1307, USA.  */
 #include <sys/time.h>
 #include <dos.h>
 #include <errno.h>
+#include <string.h>     /* for bzero and string functions */
 #include <sys/stat.h>    /* for _fixpath */
+#include <unistd.h>     /* for chdir, dup, dup2, etc. */
 #if __DJGPP__ >= 2
 #include <fcntl.h>
+#include <io.h>                 /* for setmode */
 #include <dpmi.h>       /* for __dpmi_xxx stuff */
 #include <sys/farptr.h>         /* for _farsetsel, _farnspokeb */
 #include <libc/dosio.h>  /* for _USE_LFN */
+#include <conio.h>      /* for cputs */
 #endif
 
 #include "dosfns.h"
@@ -62,9 +66,14 @@ Boston, MA 02111-1307, USA.  */
 #define _USE_LFN 0
 #endif
 
+#ifndef _dos_ds
+#define _dos_ds _go32_info_block.selector_for_linear_memory
+#endif
+
 #if __DJGPP__ > 1
 
 #include <signal.h>
+#include "syssignal.h"
 
 #ifndef SYSTEM_MALLOC
 
@@ -370,17 +379,39 @@ ScreenVisualBell (void)
 
 #ifndef HAVE_X_WINDOWS
 
+static int blink_bit = -1;     /* the state of the blink bit at startup */
+
 /* Enable bright background colors.  */
 static void
 bright_bg (void)
 {
   union REGS regs;
 
+  /* Remember the original state of the blink/bright-background bit.
+     It is stored at 0040:0065h in the BIOS data area.  */
+  if (blink_bit == -1)
+    blink_bit = (_farpeekb (_dos_ds, 0x465) & 0x20) == 0x20;
+
   regs.h.bl = 0;
   regs.x.ax = 0x1003;
   int86 (0x10, &regs, &regs);
 }
 
+/* Disable bright background colors (and enable blinking) if we found
+   the video system in that state at startup.  */
+static void
+maybe_enable_blinking (void)
+{
+  if (blink_bit == 1)
+    {
+      union REGS regs;
+
+      regs.h.bl = 1;
+      regs.x.ax = 0x1003;
+      int86 (0x10, &regs, &regs);
+    }
+}
+
 /* Set the screen dimensions so that it can show no less than
    ROWS x COLS frame.  */
 
@@ -701,7 +732,6 @@ IT_cmgoto (f)
       && XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top) <= new_pos_Y)
     {
       new_pos_X = FRAME_DESIRED_GLYPHS (f)->used[new_pos_Y];
-      FRAME_CURSOR_X (f) = new_pos_X;
       update_cursor_pos = 1;
     }
 
@@ -813,10 +843,6 @@ x_set_menu_bar_lines (f, value, oldval)
 static
 IT_set_terminal_modes (void)
 {
-  char *colors;
-  FRAME_PTR f;
-  struct face *fp;
-
   if (termscript)
     fprintf (termscript, "\n<SET_TERM>");
   highlight = 0;
@@ -870,6 +896,10 @@ IT_reset_terminal_modes (void)
     return;
   
   mouse_off ();
+
+  /* Leave the video system in the same state as we found it,
+     as far as the blink/bright-background bit is concerned.  */
+  maybe_enable_blinking ();
  
   /* We have a situation here.
      We cannot just do ScreenUpdate(startup_screen_buffer) because
@@ -944,7 +974,7 @@ IT_set_frame_parameters (f, alist)
              FRAME_FOREGROUND_PIXEL (f) = new_color;
              redraw = 1;
              if (termscript)
-               fprintf (termscript, "<FGCOLOR %d>\n", new_color);
+               fprintf (termscript, "<FGCOLOR %lu>\n", new_color);
            }
        }
       else if (EQ (prop, intern ("background-color")))
@@ -955,7 +985,7 @@ IT_set_frame_parameters (f, alist)
              FRAME_BACKGROUND_PIXEL (f) = new_color;
              redraw = 1;
              if (termscript)
-               fprintf (termscript, "<BGCOLOR %d>\n", new_color);
+               fprintf (termscript, "<BGCOLOR %lu>\n", new_color);
            }
        }
       else if (EQ (prop, intern ("menu-bar-lines")))
@@ -964,12 +994,17 @@ IT_set_frame_parameters (f, alist)
 
   if (redraw)
     {
+      extern void recompute_basic_faces (FRAME_PTR);
+      extern void redraw_frame (FRAME_PTR);
+
       recompute_basic_faces (f);
       if (f == selected_frame)
        redraw_frame (f);
     }
 }
 
+extern void init_frame_faces (FRAME_PTR);
+
 #endif /* !HAVE_X_WINDOWS */
 
 
@@ -1138,6 +1173,7 @@ static struct keyboard_layout_list
 
 static struct dos_keyboard_map *keyboard;
 static int keyboard_map_all;
+static int international_keyboard;
 
 int
 dos_set_keyboard (code, always)
@@ -1145,6 +1181,13 @@ dos_set_keyboard (code, always)
      int always;
 {
   int i;
+  union REGS regs;
+
+  /* See if Keyb.Com is installed (for international keyboard support).  */
+  regs.x.ax = 0xad80;
+  int86 (0x2f, &regs, &regs);
+  if (regs.h.al == 0xff)
+    international_keyboard = 1;
 
   /* Initialize to US settings, for countries that don't have their own.  */
   keyboard = keyboard_layout_list[0].keyboard_map;
@@ -1452,6 +1495,13 @@ dos_get_modifiers (keymask)
              mask |= SUPER_P;
              modifiers |= super_modifier;
            }
+         else if (!international_keyboard)
+           {
+             /* If Keyb.Com is NOT installed, let Right Alt behave
+                like the Left Alt.  */
+             mask &= ~ALT_GR_P;
+             mask |= ALT_P;
+           }
        }
       
       if (regs.h.ah & 1)               /* Left CTRL pressed ? */
@@ -1517,6 +1567,8 @@ and then the scan code.")
 
 /* Get a char from keyboard.  Function keys are put into the event queue.  */
 
+extern void kbd_buffer_store_event (struct input_event *);
+
 static int
 dos_rawgetc ()
 {
@@ -1594,7 +1646,19 @@ dos_rawgetc ()
       
       if (c == 0)
        {
-         if (code & Alt)
+        /* We only look at the keyboard Ctrl/Shift/Alt keys when
+           Emacs is ready to read a key.  Therefore, if they press
+           `Alt-x' when Emacs is busy, by the time we get to
+           `dos_get_modifiers', they might have already released the
+           Alt key, and Emacs gets just `x', which is BAD.
+           However, for keys with the `Map' property set, the ASCII
+           code returns zero iff Alt is pressed.  So, when we DON'T
+           have to support international_keyboard, we don't have to
+           distinguish between the left and  right Alt keys, and we
+           can set the META modifier for any keys with the `Map'
+           property if they return zero ASCII code (c = 0).  */
+        if ( (code & Alt)
+             || ( (code & 0xf000) == Map && !international_keyboard))
            modifiers |= meta_modifier;
          if (code & Ctrl)
            modifiers |= ctrl_modifier;
@@ -2070,6 +2134,12 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
   /* Just in case we got here without a mouse present...  */
   if (have_mouse <= 0)
     return XM_IA_SELECT;
+  /* Don't allow non-positive x0 and y0, lest the menu will wrap
+     around the display.  */
+  if (x0 <= 0)
+    x0 = 1;
+  if (y0 <= 0)
+    y0 = 1;
 
   state = alloca (menu->panecount * sizeof (struct IT_menu_state));
   screensize = screen_size * 2;
@@ -2318,7 +2388,6 @@ crlf_to_lf (n, buf)
   unsigned char *np = buf;
   unsigned char *startp = buf;
   unsigned char *endp = buf + n;
-  unsigned char c;
 
   if (n == 0)
     return n;
@@ -2567,7 +2636,6 @@ The argument object is never altered--the value is a copy.")
   (filename)
      Lisp_Object filename;
 {
-  char *fname;
   Lisp_Object tem;
 
   if (! STRINGP (filename))
@@ -2882,7 +2950,7 @@ run_msdos_command (argv, dir, tempin, tempout, temperr)
   char *saveargv1, *saveargv2, **envv, *lowcase_argv0, *pa, *pl;
   char oldwd[MAXPATHLEN + 1]; /* Fixed size is safe on MSDOS.  */
   int msshell, result = -1;
-  int in, out, inbak, outbak, errbak;
+  int inbak, outbak, errbak;
   int x, y;
   Lisp_Object cmd;
 
@@ -2996,6 +3064,11 @@ run_msdos_command (argv, dir, tempin, tempout, temperr)
       mouse_init ();
       mouse_moveto (x, y);
     }
+
+  /* Some programs might change the meaning of the highest bit of the
+     text attribute byte, so we get blinking characters instead of the
+     bright background colors.  Restore that.  */
+  bright_bg ();
   
  done:
   chdir (oldwd);
@@ -3089,14 +3162,123 @@ int kill (x, y) int x, y; { return -1; }
 nice (p) int p; {}
 void volatile pause () {}
 sigsetmask (x) int x; { return 0; }
+sigblock (mask) int mask; { return 0; } 
 #endif
 
 request_sigio () {}
 setpgrp () {return 0; }
 setpriority (x,y,z) int x,y,z; { return 0; }
-sigblock (mask) int mask; { return 0; } 
 unrequest_sigio () {}
 
+#if __DJGPP__ > 1
+
+#ifdef POSIX_SIGNALS
+
+/* Augment DJGPP library POSIX signal functions.  This is needed
+   as of DJGPP v2.01, but might be in the library in later releases. */
+
+#include <libc/bss.h>
+
+/* A counter to know when to re-initialize the static sets.  */
+static int sigprocmask_count = -1;
+
+/* Which signals are currently blocked (initially none).  */
+static sigset_t current_mask;
+
+/* Which signals are pending (initially none).  */
+static sigset_t pending_signals;
+
+/* Previous handlers to restore when the blocked signals are unblocked.  */
+typedef void (*sighandler_t)(int);
+static sighandler_t prev_handlers[320];
+
+/* A signal handler which just records that a signal occured
+   (it will be raised later, if and when the signal is unblocked).  */
+static void
+sig_suspender (signo)
+     int signo;
+{
+  sigaddset (&pending_signals, signo);
+}
+
+int
+sigprocmask (how, new_set, old_set)
+     int how;
+     const sigset_t *new_set;
+     sigset_t *old_set;
+{
+  int signo;
+  sigset_t new_mask;
+
+  /* If called for the first time, initialize.  */
+  if (sigprocmask_count != __bss_count)
+    {
+      sigprocmask_count = __bss_count;
+      sigemptyset (&pending_signals);
+      sigemptyset (&current_mask);
+      for (signo = 0; signo < 320; signo++)
+       prev_handlers[signo] = SIG_ERR;
+    }
+
+  if (old_set)
+    *old_set = current_mask;
+
+  if (new_set == 0)
+    return 0;
+
+  if (how != SIG_BLOCK && how != SIG_UNBLOCK && how != SIG_SETMASK)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  sigemptyset (&new_mask);
+
+  /* DJGPP supports upto 320 signals.  */
+  for (signo = 0; signo < 320; signo++)
+    {
+      if (sigismember (&current_mask, signo))
+       sigaddset (&new_mask, signo);
+      else if (sigismember (new_set, signo) && how != SIG_UNBLOCK)
+       {
+         sigaddset (&new_mask, signo);
+
+         /* SIGKILL is silently ignored, as on other platforms.  */
+         if (signo != SIGKILL && prev_handlers[signo] == SIG_ERR)
+           prev_handlers[signo] = signal (signo, sig_suspender);
+       }
+      if ((   how == SIG_UNBLOCK
+             && sigismember (&new_mask, signo)
+             && sigismember (new_set, signo))
+         || (how == SIG_SETMASK
+             && sigismember (&new_mask, signo)
+             && !sigismember (new_set, signo)))
+       {
+         sigdelset (&new_mask, signo);
+         if (prev_handlers[signo] != SIG_ERR)
+           {
+             signal (signo, prev_handlers[signo]);
+             prev_handlers[signo] = SIG_ERR;
+           }
+         if (sigismember (&pending_signals, signo))
+           {
+             sigdelset (&pending_signals, signo);
+             raise (signo);
+           }
+       }
+    }
+  current_mask = new_mask;
+  return 0;
+}
+
+#else /* not POSIX_SIGNALS */
+
+sigsetmask (x) int x; { return 0; }
+sigblock (mask) int mask; { return 0; } 
+
+#endif /* not POSIX_SIGNALS */
+#endif /* __DJGPP__ > 1 */
+
 #ifndef HAVE_SELECT
 #include "sysselect.h"