]> code.delx.au - gnu-emacs/blobdiff - src/msdos.c
(message2_nolog): Fix arg types.
[gnu-emacs] / src / msdos.c
index 9291dd08f2628611278d303430a9091bf2248c59..5e9b9a1253ca1c19ead037141a650364e7d08ab7 100644 (file)
@@ -1,5 +1,5 @@
-/* MS-DOS specific C utilities.
-   Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+/* MS-DOS specific C utilities.          -*- coding: raw-text -*-
+   Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -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
 
@@ -148,6 +157,17 @@ mouse_off ()
     }
 }
 
+static void
+mouse_get_xy (int *x, int *y)
+{
+  union REGS regs;
+
+  regs.x.ax = 0x0003;
+  int86 (0x33, &regs, &regs);
+  *x = regs.x.cx / 8;
+  *y = regs.x.dx / 8;
+}
+
 void
 mouse_moveto (x, y)
      int x, y;
@@ -194,17 +214,6 @@ mouse_released (b, xp, yp)
   return (regs.x.bx != 0);
 }
 
-static void
-mouse_get_xy (int *x, int *y)
-{
-  union REGS regs;
-
-  regs.x.ax = 0x0003;
-  int86 (0x33, &regs, &regs);
-  *x = regs.x.cx / 8;
-  *y = regs.x.dx / 8;
-}
-
 void
 mouse_get_pos (f, insist, bar_window, part, x, y, time)
      FRAME_PTR *f;
@@ -214,17 +223,18 @@ mouse_get_pos (f, insist, bar_window, part, x, y, time)
      unsigned long *time;
 {
   int ix, iy;
-  union REGS regs;
+  Lisp_Object frame, tail;
+
+  /* Clear the mouse-moved flag for every frame on this display.  */
+  FOR_EACH_FRAME (tail, frame)
+    XFRAME (frame)->mouse_moved = 0;
 
-  regs.x.ax = 0x0003;
-  int86 (0x33, &regs, &regs);
   *f = selected_frame;
   *bar_window = Qnil;
   mouse_get_xy (&ix, &iy);
-  selected_frame->mouse_moved = 0;
-  *x = make_number (ix);
-  *y = make_number (iy);
   *time = event_timestamp ();
+  *x = make_number (mouse_last_x = ix);
+  *y = make_number (mouse_last_y = iy);
 }
 
 static void
@@ -298,6 +308,31 @@ struct x_output the_only_x_display;
 /* This is never dereferenced.  */
 Display *x_current_display;
 
+/* Support for DOS/V (allows Japanese characters to be displayed on
+   standard, non-Japanese, ATs).  Only supported for DJGPP v2 and later.  */
+
+/* Holds the address of the text-mode screen buffer.  */
+static unsigned long screen_old_address = 0;
+/* Segment and offset of the virtual screen.  If 0, DOS/V is NOT loaded.  */
+static unsigned short screen_virtual_segment = 0;
+static unsigned short screen_virtual_offset = 0;
+
+#if __DJGPP__ > 1
+/* Update the screen from a part of relocated DOS/V screen buffer which
+   begins at OFFSET and includes COUNT characters.  */
+static void
+dosv_refresh_virtual_screen (int offset, int count)
+{
+  __dpmi_regs regs;
+
+  regs.h.ah = 0xff;    /* update relocated screen */
+  regs.x.es = screen_virtual_segment;
+  regs.x.di = screen_virtual_offset + offset;
+  regs.x.cx = count;
+  __dpmi_int (0x10, &regs);
+}
+#endif
+
 static
 dos_direct_output (y, x, buf, len)
      int y;
@@ -306,6 +341,8 @@ dos_direct_output (y, x, buf, len)
      int len;
 {
   int t = (int) ScreenPrimary + 2 * (x + y * screen_size_X);
+  int t0 = t;
+  int l0 = len;
 
 #if (__DJGPP__ < 2)
   while (--len >= 0) {
@@ -316,6 +353,9 @@ dos_direct_output (y, x, buf, len)
   /* This is faster.  */
   for (_farsetsel (_dos_ds); --len >= 0; t += 2, buf++)
     _farnspokeb (t, *buf);
+
+  if (screen_virtual_segment)
+    dosv_refresh_virtual_screen (t0, l0);
 #endif
 }
 #endif
@@ -370,17 +410,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.  */
 
@@ -510,6 +572,11 @@ dos_set_window_size (rows, cols)
 
   /* Enable bright background colors.  */
   bright_bg ();
+
+  /* FIXME: I'm not sure the above will run at all on DOS/V.  But let's
+     be defensive anyway.  */
+  if (screen_virtual_segment)
+    dosv_refresh_virtual_screen (0, *cols * *rows);
 }
 
 /* If we write a character in the position where the mouse is,
@@ -560,7 +627,8 @@ IT_set_face (int face)
   else
     fp = intern_face (selected_frame, FRAME_COMPUTED_FACES (foo)[face]);
   if (termscript)
-    fprintf (termscript, "<FACE:%d:%d>", FACE_FOREGROUND (fp), FACE_BACKGROUND (fp));
+    fprintf (termscript, "<FACE %d: %d/%d>",
+            face, FACE_FOREGROUND (fp), FACE_BACKGROUND (fp));
   screen_face = face;
   ScreenAttrib = (FACE_BACKGROUND (fp) << 4) | FACE_FOREGROUND (fp);
 }
@@ -571,6 +639,7 @@ IT_write_glyphs (GLYPH *str, int len)
   int newface;
   int ch, l = len;
   unsigned char *buf, *bp;
+  int offset = 2 * (new_pos_X + screen_size_X * new_pos_Y);
 
   if (len == 0) return;
   
@@ -591,8 +660,9 @@ IT_write_glyphs (GLYPH *str, int len)
     }
 
   mouse_off_maybe ();
-  dosmemput (buf, 2 * len, 
-            (int)ScreenPrimary + 2 * (new_pos_X + screen_size_X * new_pos_Y));
+  dosmemput (buf, 2 * len, (int)ScreenPrimary + offset);
+  if (screen_virtual_segment)
+    dosv_refresh_virtual_screen (offset, len);
   new_pos_X += len;
 }
 
@@ -601,6 +671,7 @@ IT_clear_end_of_line (first_unused)
 {
   char *spaces, *sp;
   int i, j;
+  int offset = 2 * (new_pos_X + screen_size_X * new_pos_Y);
 
   IT_set_face (0);
   if (termscript)
@@ -615,8 +686,9 @@ IT_clear_end_of_line (first_unused)
     }
 
   mouse_off_maybe ();
-  dosmemput (spaces, i, 
-            (int)ScreenPrimary + 2 * (new_pos_X + screen_size_X * new_pos_Y));
+  dosmemput (spaces, i, (int)ScreenPrimary + offset);
+  if (screen_virtual_segment)
+    dosv_refresh_virtual_screen (offset, i / 2);
 }
 
 static
@@ -627,6 +699,8 @@ IT_clear_screen (void)
   IT_set_face (0);
   mouse_off ();
   ScreenClear ();
+  if (screen_virtual_segment)
+    dosv_refresh_virtual_screen (0, screen_size);
   new_pos_X = new_pos_Y = 0;
 }
 
@@ -667,6 +741,8 @@ IT_display_cursor (int on)
       ScreenSetCursor (-1, -1);
       cursor_cleared = 1;
     }
+  if (screen_virtual_segment)
+    dosv_refresh_virtual_screen (2 * (current_pos_X + screen_size_X * current_pos_Y), 1);
 }
 
 /* Emacs calls cursor-movement functions a lot when it updates the
@@ -701,7 +777,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;
     }
 
@@ -752,60 +827,20 @@ IT_update_end ()
 {
 }
 
-/* This was more or less copied from xterm.c
-
-   Nowadays, the corresponding function under X is `x_set_menu_bar_lines_1'
-   on xfns.c  */
-
-static void
-IT_set_menu_bar_lines (window, n)
-     Lisp_Object window;
-     int n;
-{
-  struct window *w = XWINDOW (window);
-
-  XSETFASTINT (w->last_modified, 0);
-  XSETFASTINT (w->last_overlay_modified, 0);
-  XSETFASTINT (w->top, XFASTINT (w->top) + n);
-  XSETFASTINT (w->height, XFASTINT (w->height) - n);
-
-  /* Handle just the top child in a vertical split.  */
-  if (!NILP (w->vchild))
-    IT_set_menu_bar_lines (w->vchild, n);
-
-  /* Adjust all children in a horizontal split.  */
-  for (window = w->hchild; !NILP (window); window = w->next)
-    {
-      w = XWINDOW (window);
-      IT_set_menu_bar_lines (window, n);
-    }
-}
-
-/* This was copied from xfns.c  */
-
+/* set-window-configuration on window.c needs this.  */
 void
 x_set_menu_bar_lines (f, value, oldval)
      struct frame *f;
      Lisp_Object value, oldval;
 {
-  int nlines;
-  int olines = FRAME_MENU_BAR_LINES (f);
-
-  /* Right now, menu bars don't work properly in minibuf-only frames;
-     most of the commands try to apply themselves to the minibuffer
-     frame itslef, and get an error because you can't switch buffers
-     in or split the minibuffer window.  */
-  if (FRAME_MINIBUF_ONLY_P (f))
-    return;
+  set_menu_bar_lines (f, value, oldval);
+}
 
-  if (INTEGERP (value))
-    nlines = XINT (value);
-  else
-    nlines = 0;
+/* This was copied from xfns.c  */
 
-  FRAME_MENU_BAR_LINES (f) = nlines;
-  IT_set_menu_bar_lines (f->root_window, nlines - olines);
-}
+Lisp_Object Qbackground_color;
+Lisp_Object Qforeground_color;
+extern Lisp_Object Qtitle;
 
 /* IT_set_terminal_modes is called when emacs is started,
    resumed, and whenever the screen is redrawn!  */
@@ -813,10 +848,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;
@@ -836,12 +867,40 @@ IT_set_terminal_modes (void)
   startup_screen_size_Y = screen_size_Y;
   startup_screen_attrib = ScreenAttrib;
 
+#if __DJGPP__ > 1
+  /* Is DOS/V (or any other RSIS software which relocates
+     the screen) installed?  */
+  {
+    unsigned short es_value;
+    __dpmi_regs regs;
+
+    regs.h.ah = 0xfe;  /* get relocated screen address */
+    if (ScreenPrimary == 0xb0000UL || ScreenPrimary == 0xb8000UL)
+      regs.x.es = (ScreenPrimary >> 4) & 0xffff;
+    else if (screen_old_address) /* already switched to Japanese mode once */
+      regs.x.es = (screen_old_address >> 4) & 0xffff;
+    else
+      regs.x.es = ScreenMode () == 7 ? 0xb000 : 0xb800;
+    regs.x.di = 0;
+    es_value = regs.x.es;
+    __dpmi_int (0x10, &regs);
+
+    if (regs.x.es != es_value && regs.x.es != (ScreenPrimary >> 4) & 0xffff)
+      {
+       screen_old_address = ScreenPrimary;
+       screen_virtual_segment = regs.x.es;
+       screen_virtual_offset  = regs.x.di;
+       ScreenPrimary = (screen_virtual_segment << 4) + screen_virtual_offset;
+      }
+  }
+#endif /* __DJGPP__ > 1 */
+
   ScreenGetCursor (&startup_pos_Y, &startup_pos_X);
   ScreenRetrieve (startup_screen_buffer = xmalloc (screen_size * 2));
 
   if (termscript)
     fprintf (termscript, "<SCREEN SAVED (dimensions=%dx%d)>\n",
-             screen_size_X, screen_size_Y);
+            screen_size_X, screen_size_Y);
 
   bright_bg ();
 }
@@ -870,6 +929,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
@@ -885,6 +948,8 @@ IT_reset_terminal_modes (void)
 
   ScreenAttrib = startup_screen_attrib;
   ScreenClear ();
+  if (screen_virtual_segment)
+    dosv_refresh_virtual_screen (0, screen_size);
 
   if (update_row_len > saved_row_len)
     update_row_len = saved_row_len;
@@ -898,6 +963,9 @@ IT_reset_terminal_modes (void)
   while (current_rows--)
     {
       dosmemput (saved_row, update_row_len, display_row_start);
+      if (screen_virtual_segment)
+       dosv_refresh_virtual_screen (display_row_start - ScreenPrimary,
+                                    update_row_len / 2);
       saved_row         += saved_row_len;
       display_row_start += to_next_row;
     }
@@ -907,6 +975,9 @@ IT_reset_terminal_modes (void)
     cursor_pos_Y = startup_pos_Y;
 
   ScreenSetCursor (cursor_pos_Y, cursor_pos_X);
+  if (screen_virtual_segment)
+    dosv_refresh_virtual_screen (2*(cursor_pos_X+cursor_pos_Y*screen_size_X),
+                                1);
   xfree (startup_screen_buffer);
 
   term_setup_done = 0;
@@ -923,20 +994,38 @@ IT_set_frame_parameters (f, alist)
      Lisp_Object alist;
 {
   Lisp_Object tail;
+  int length = XINT (Flength (alist));
+  int i;
+  Lisp_Object *parms
+    = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
+  Lisp_Object *values
+    = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
   int redraw;
   extern unsigned long load_color ();
 
   redraw = 0;
+
+  /* Extract parm names and values into those vectors.  */
+  i = 0;
   for (tail = alist; CONSP (tail); tail = Fcdr (tail))
     {
-      Lisp_Object elt, prop, val;
+      Lisp_Object elt;
 
       elt = Fcar (tail);
-      prop = Fcar (elt);
-      val = Fcdr (elt);
-      CHECK_SYMBOL (prop, 1);
+      parms[i] = Fcar (elt);
+      CHECK_SYMBOL (parms[i], 1);
+      values[i] = Fcdr (elt);
+      i++;
+    }
+
+
+  /* Now process them in reverse of specified order.  */
+  for (i--; i >= 0; i--)
+    {
+      Lisp_Object prop = parms[i];
+      Lisp_Object val  = values[i];
 
-      if (EQ (prop, intern ("foreground-color")))
+      if (EQ (prop, Qforeground_color))
        {
          unsigned long new_color = load_color (f, val);
          if (new_color != ~0)
@@ -944,10 +1033,10 @@ 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")))
+      else if (EQ (prop, Qbackground_color))
        {
          unsigned long new_color = load_color (f, val);
          if (new_color != ~0)
@@ -955,21 +1044,41 @@ 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")))
-       x_set_menu_bar_lines (f, val, 0);
+      else if (EQ (prop, Qtitle))
+       {
+         x_set_title (f, val);
+         if (termscript)
+           fprintf (termscript, "<TITLE: %s>\n", XSTRING (val)->data);
+       }
+      else if (EQ (prop, intern ("reverse")) && EQ (val, Qt))
+       {
+         unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
+
+         FRAME_FOREGROUND_PIXEL (f) = FRAME_BACKGROUND_PIXEL (f);
+         FRAME_BACKGROUND_PIXEL (f) = fg;
+         if (termscript)
+           fprintf (termscript, "<INVERSE-VIDEO>\n");
+       }
+      store_frame_param (f, prop, val);
+
     }
 
   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 */
 
 
@@ -1001,7 +1110,10 @@ internal_terminal_init ()
 
   Vwindow_system = intern ("pc");
   Vwindow_system_version = make_number (1);
+
+  /* If Emacs was dumped on DOS/V machine, forget the stale VRAM address.  */
+  screen_old_address = 0;
+
   bzero (&the_only_x_display, sizeof the_only_x_display);
   the_only_x_display.background_pixel = 7; /* White */
   the_only_x_display.foreground_pixel = 0; /* Black */
@@ -1056,7 +1168,7 @@ dos_get_saved_screen (screen, rows, cols)
   *screen = startup_screen_buffer;
   *cols = startup_screen_size_X;
   *rows = startup_screen_size_Y;
-  return 1;
+  return *screen != (char *)0;
 #else
   return 0;
 #endif  
@@ -1138,6 +1250,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 +1258,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 +1572,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 +1644,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 +1723,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 +2211,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;
@@ -2166,6 +2313,8 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
                          statecount--;
                          mouse_off ();
                          ScreenUpdate (state[statecount].screen_behind);
+                         if (screen_virtual_segment)
+                           dosv_refresh_virtual_screen (0, screen_size);
                          xfree (state[statecount].screen_behind);
                        }
                    if (i == statecount - 1 && state[i].menu->submenu[dy])
@@ -2201,6 +2350,8 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
 
   mouse_off ();
   ScreenUpdate (state[0].screen_behind);
+  if (screen_virtual_segment)
+    dosv_refresh_virtual_screen (0, screen_size);
   while (statecount--)
     xfree (state[statecount].screen_behind);
   IT_display_cursor (1);       /* turn cursor back on */
@@ -2318,7 +2469,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 +2717,6 @@ The argument object is never altered--the value is a copy.")
   (filename)
      Lisp_Object filename;
 {
-  char *fname;
   Lisp_Object tem;
 
   if (! STRINGP (filename))
@@ -2616,10 +2765,12 @@ init_environment (argc, argv, skip_args)
   while (len > 0 && root[len] != '/' && root[len] != ':')
     len--;
   root[len] = '\0';
-  if (len > 4 && strcmp (root + len - 4, "/bin") == 0)
+  if (len > 4
+      && (strcmp (root + len - 4, "/bin") == 0
+         || strcmp (root + len - 4, "/src") == 0)) /* under a debugger */
     root[len - 4] = '\0';
   else
-    strcpy (root, "c:/emacs");  /* Only under debuggers, I think.  */
+    strcpy (root, "c:/emacs");  /* let's be defensive */
   len = strlen (root);
   strcpy (emacsroot, root);
 
@@ -2882,7 +3033,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 +3147,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 +3245,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"
 
@@ -3264,6 +3529,10 @@ abort ()
   ScreenSetCursor (10, 0);
   cputs ("\r\n\nEmacs aborted!\r\n");
 #if __DJGPP__ > 1
+#if __DJGPP__ == 2 && __DJGPP_MINOR__ < 2
+  if (screen_virtual_segment)
+    dosv_refresh_virtual_screen (2 * 10 * screen_size_X, 4 * screen_size_X);
+#endif /* __DJGPP_MINOR__ < 2 */
   /* Generate traceback, so we could tell whodunit.  */
   signal (SIGINT, SIG_DFL);
   __asm__ __volatile__ ("movb $0x1b,%al;call ___djgpp_hw_exception");
@@ -3272,10 +3541,38 @@ abort ()
 }
 #endif
 
+/* The following two are required so that customization feature
+   won't complain about unbound variables.  */
+#ifndef HAVE_X_WINDOWS
+/* Search path for bitmap files (xfns.c).  */
+Lisp_Object Vx_bitmap_file_path;
+#endif
+#ifndef subprocesses
+/* Nonzero means delete a process right away if it exits (process.c).  */
+static int delete_exited_processes;
+#endif
+
 syms_of_msdos ()
 {
   recent_doskeys = Fmake_vector (make_number (NUM_RECENT_DOSKEYS), Qnil);
   staticpro (&recent_doskeys);
+#ifndef HAVE_X_WINDOWS
+  DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
+    "List of directories to search for bitmap files for X.");
+  Vx_bitmap_file_path = decode_env_path ((char *) 0, ".");
+
+  /* The following two are from xfns.c:  */
+  Qbackground_color = intern ("background-color");
+  staticpro (&Qbackground_color);
+  Qforeground_color = intern ("foreground-color");
+  staticpro (&Qforeground_color);
+#endif
+#ifndef subprocesses
+  DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes,
+    "*Non-nil means delete processes immediately when they exit.\n\
+nil means don't delete them until `list-processes' is run.");
+  delete_exited_processes = 0;
+#endif
 
   defsubr (&Srecent_doskeys);
   defsubr (&Smsdos_long_file_names);