summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dosfns.c215
-rw-r--r--src/dosfns.h23
-rw-r--r--src/m/=dos386.h112
-rw-r--r--src/msdos.c1067
-rw-r--r--src/msdos.h45
-rw-r--r--src/s/msdos.h219
6 files changed, 1681 insertions, 0 deletions
diff --git a/src/dosfns.c b/src/dosfns.c
new file mode 100644
index 00000000000..82af5adb9c2
--- /dev/null
+++ b/src/dosfns.c
@@ -0,0 +1,215 @@
+/* MS-DOS specific Lisp utilities. Coded by Manabu Higashida, 1991.
+ Major changes May-July 1993 Morten Welinder (only 10% original code left)
+ Copyright (C) 1991, 1993 Free Software Foundation, Inc.
+
+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
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "config.h"
+
+#ifdef MSDOS
+/* The entire file is within this conditional */
+
+#include <stdio.h>
+#include <dos.h>
+#include "lisp.h"
+#include "buffer.h"
+#include "termchar.h"
+#include "termhooks.h"
+#include "frame.h"
+#include "dosfns.h"
+#include "msdos.h"
+
+static void
+mode_resetsize ()
+{
+ Fset_screen_width (ScreenCols (), Qnil);
+ Fset_screen_height (ScreenRows (), Qnil);
+}
+
+DEFUN ("mode25", Fmode25, Smode25, 0, 0, "",
+ "Set the number of rows to 25.")
+ ()
+{
+ union REGS regs;
+
+ if (have_mouse) Mouse_off ();
+ regs.x.ax = 3;
+ int86 (0x10, &regs, &regs);
+ regs.x.ax = 0x1101;
+ regs.h.bl = 0;
+ int86 (0x10, &regs, &regs);
+ regs.x.ax = 0x1200;
+ regs.h.bl = 32;
+ int86 (0x10, &regs, &regs);
+ regs.x.ax = 3;
+ int86 (0x10, &regs, &regs);
+ mode_resetsize ();
+ Frecenter (Qnil);
+ Fredraw_display ();
+ if (have_mouse) Mouse_init ();
+}
+
+DEFUN ("mode4350", Fmode4350, Smode4350, 0, 0, "",
+ "Set the number of rows to 43 (EGA) or 50 (VGA).")
+ ()
+{
+ union REGS regs;
+
+ if (have_mouse) Mouse_off ();
+ regs.x.ax = 3;
+ int86 (0x10, &regs, &regs);
+ regs.x.ax = 0x1112;
+ regs.h.bl = 0;
+ int86 (0x10, &regs, &regs);
+ regs.x.ax = 0x1200;
+ regs.h.bl = 32;
+ int86 (0x10, &regs, &regs);
+ regs.x.ax = 0x0100;
+ regs.x.cx = 7;
+ int86 (0x10, &regs, &regs);
+ mode_resetsize ();
+ Frecenter (Qnil);
+ Fredraw_display ();
+ if (have_mouse) Mouse_init ();
+}
+
+DEFUN ("int86", Fint86, Sint86, 2, 2, 0,
+ "Call specific MSDOS interrupt number INTERRUPT with REGISTERS.\n\
+Return the updated REGISTER vector.\n\
+\n\
+INTERRUPT should be an integer in the range 0 to 255.\n\
+REGISTERS should be a vector produced by `make-register' and\n\
+`set-register-value'.")
+ (intno, regs)
+ Lisp_Object intno, regs;
+{
+ register int i;
+ int no;
+ union REGS inregs, outregs;
+ Lisp_Object val;
+
+ CHECK_NUMBER (intno, 0);
+ no = (unsigned long) XINT (intno);
+ CHECK_VECTOR (regs, 1);
+ if (no < 0 || no > 0xff || XVECTOR (regs)-> size != 8)
+ return Qnil;
+ for (i = 0; i < 8; i++)
+ CHECK_NUMBER (XVECTOR (regs)->contents[i], 1);
+
+ inregs.x.ax = (unsigned long) XFASTINT (XVECTOR (regs)->contents[0]);
+ inregs.x.bx = (unsigned long) XFASTINT (XVECTOR (regs)->contents[1]);
+ inregs.x.cx = (unsigned long) XFASTINT (XVECTOR (regs)->contents[2]);
+ inregs.x.dx = (unsigned long) XFASTINT (XVECTOR (regs)->contents[3]);
+ inregs.x.si = (unsigned long) XFASTINT (XVECTOR (regs)->contents[4]);
+ inregs.x.di = (unsigned long) XFASTINT (XVECTOR (regs)->contents[5]);
+ inregs.x.cflag = (unsigned long) XFASTINT (XVECTOR (regs)->contents[6]);
+ inregs.x.flags = (unsigned long) XFASTINT (XVECTOR (regs)->contents[7]);
+
+ int86 (no, &inregs, &outregs);
+
+ XVECTOR (regs)->contents[0] = make_number (outregs.x.ax);
+ XVECTOR (regs)->contents[1] = make_number (outregs.x.bx);
+ XVECTOR (regs)->contents[2] = make_number (outregs.x.cx);
+ XVECTOR (regs)->contents[3] = make_number (outregs.x.dx);
+ XVECTOR (regs)->contents[4] = make_number (outregs.x.si);
+ XVECTOR (regs)->contents[5] = make_number (outregs.x.di);
+ XVECTOR (regs)->contents[6] = make_number (outregs.x.cflag);
+ XVECTOR (regs)->contents[7] = make_number (outregs.x.flags);
+
+ return regs;
+}
+
+int dos_country_code;
+int dos_codepage;
+Lisp_Object Vdos_version;
+
+void
+init_dosfns ()
+{
+ union REGS regs;
+ _go32_dpmi_seginfo info;
+ _go32_dpmi_registers dpmiregs;
+
+ get_lim_data (); /* why the hell isn't this called elsewhere? */
+
+ regs.x.ax = 0x3000;
+ intdos (&regs, &regs);
+ Vdos_version = Fcons (make_number (regs.h.al), make_number (regs.h.ah));
+
+ /* Obtain the country code by calling Dos via Dpmi. Don't rely on GO32. */
+ info.size = (34 + 15) / 16;
+ if (_go32_dpmi_allocate_dos_memory (&info))
+ dos_country_code = 1;
+ else
+ {
+ dpmiregs.x.ax = 0x3800;
+ dpmiregs.x.ds = info.rm_segment;
+ dpmiregs.x.dx = 0;
+ dpmiregs.x.ss = dpmiregs.x.sp = 0;
+ _go32_dpmi_simulate_int (0x21, &dpmiregs);
+ dos_country_code = dpmiregs.x.bx;
+ _go32_dpmi_free_dos_memory (&info);
+ }
+
+ regs.x.ax = 0x6601;
+ intdos (&regs, &regs);
+ if (regs.x.cflag)
+ /* Estimate code page from country code */
+ switch (dos_country_code)
+ {
+ case 45: /* Denmark */
+ case 47: /* Norway */
+ dos_codepage = 865;
+ break;
+ default:
+ /* US */
+ dos_codepage = 437;
+ }
+ else
+ dos_codepage = regs.x.bx & 0xffff;
+}
+
+/*
+ * Define everything
+ */
+syms_of_dosfns ()
+{
+ defsubr (&Smode25);
+ defsubr (&Smode4350);
+ defsubr (&Sint86);
+
+ DEFVAR_INT ("dos-country-code", &dos_country_code,
+ "The country code returned by Dos when Emacs was started.\n\
+Usually this is the international telephone prefix.");
+
+ DEFVAR_INT ("dos-codepage", &dos_codepage,
+ "The codepage active when Emacs was started.\n\
+The following are known:
+ 437 US
+ 850 Multilingual
+ 852 Slavic/Latin II
+ 857 Turkish
+ 860 Portugal
+ 861 Iceland
+ 863 Canada (French)
+ 865 Norway/Denmark");
+
+ DEFVAR_LISP ("dos-version", &Vdos_version,
+ "The (MAJOR . MINOR) Dos version (subject to modification with setver).");
+}
+#endif /* MSDOS */
diff --git a/src/dosfns.h b/src/dosfns.h
new file mode 100644
index 00000000000..f27b344bb5c
--- /dev/null
+++ b/src/dosfns.h
@@ -0,0 +1,23 @@
+/* MS-DOS specific Lisp utilities interface.
+ Coded by Manabu Higashida, 1991.
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+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
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+extern int dos_country_code;
+extern int dos_codepage;
+extern Lisp_Object Vdos_version;
diff --git a/src/m/=dos386.h b/src/m/=dos386.h
new file mode 100644
index 00000000000..defd8f1036e
--- /dev/null
+++ b/src/m/=dos386.h
@@ -0,0 +1,112 @@
+/* Machine description file for MS-DOS
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+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
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Note: lots of stuff here was taken from m-dos386.h in demacs. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+#define INTBITS 32 /* Number of bits in an int */
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+/* #define BIG_ENDIAN */
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+/* #define NO_ARG_ARRAY */
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+/* #define WORD_MACHINE */
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ Ones defined so far include vax, m68000, ns16000, pyramid,
+ orion, tahoe, APOLLO and many others */
+
+#define INTEL386
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+/* #define LOAD_AVE_TYPE long */
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+/* #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) */
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+/* #define CANNOT_DUMP */
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES */
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+#define HAVE_ALLOCA
+#define alloca(x) __builtin_alloca(x)
+
+/* Define NO_REMAP if memory segmentation makes it not work well
+ to change the boundary between the text section and data section
+ when Emacs is dumped. If you define this, the preloaded Lisp
+ code will not be sharable; but that's better than failing completely. */
+
+#define NO_REMAP
+
+/* We need a little extra space, see ../../lisp/loadup.el */
+#define PURESIZE 210000
diff --git a/src/msdos.c b/src/msdos.c
new file mode 100644
index 00000000000..d0937cf763b
--- /dev/null
+++ b/src/msdos.c
@@ -0,0 +1,1067 @@
+/* MS-DOS specific C utilities. Coded by Morten Welinder 1993
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+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
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Note: some of the stuff here was taken from end of sysdep.c in demacs. */
+
+#include "config.h"
+
+#ifdef MSDOS
+#include "lisp.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <dos.h>
+#include "dosfns.h"
+#include "msdos.h"
+#include "systime.h"
+#include "termhooks.h"
+#include "frame.h"
+#include <go32.h>
+#include <pc.h>
+#include <ctype.h>
+/* #include <process.h> */
+/* Damn that local process.h! Instead we can define P_WAIT ourselves. */
+#define P_WAIT 1
+
+static int break_stat; /* BREAK check mode status. */
+static int stdin_stat; /* stdin IOCTL status. */
+static int extended_kbd; /* 101 (102) keyboard present. */
+
+int have_mouse; /* Mouse present? */
+static int mouse_last_x;
+static int mouse_last_y;
+
+/* Turn off Dos' Ctrl-C checking and inhibit interpretation of control chars
+ by Dos. Determine the keyboard type. */
+int
+dos_ttraw ()
+{
+ union REGS inregs, outregs;
+
+ inregs.h.ah = 0xc0;
+ int86 (0x15, &inregs, &outregs);
+ extended_kbd = (!outregs.x.cflag) && (outregs.h.ah == 0);
+
+ break_stat = getcbrk ();
+ setcbrk (0);
+ install_ctrl_break_check ();
+ have_mouse = Mouse_init1 ();
+
+ inregs.x.ax = 0x4400; /* Get IOCTL status. */
+ inregs.x.bx = 0x00; /* 0 = stdin. */
+ intdos (&inregs, &outregs);
+ stdin_stat = outregs.h.dl;
+
+ inregs.x.dx = (outregs.x.dx | 0x0020) & 0x0027; /* raw mode */
+ inregs.h.al = 0x01;
+ intdos (&inregs, &outregs);
+ return !outregs.x.cflag;
+}
+
+/* Restore status of standard input and Ctrl-C checking. */
+int
+dos_ttcooked ()
+{
+ union REGS inregs, outregs;
+
+ setcbrk (break_stat);
+ if (have_mouse) Mouse_off ();
+
+ inregs.x.ax = 0x4401; /* Set IOCTL status. */
+ inregs.x.bx = 0x00; /* 0 = stdin. */
+ inregs.x.dx = stdin_stat;
+ intdos (&inregs, &outregs);
+ return !outregs.x.cflag;
+}
+
+static unsigned short
+ibmpc_translate_map[] =
+{
+ /* --------------- 00 to 0f --------------- */
+ 0, /* Ctrl Break */
+ 0xff1b, /* Escape */
+ 0xffb1, /* Keypad 1 */
+ 0xffb2, /* Keypad 2 */
+ 0xffb3, /* Keypad 3 */
+ 0xffb4, /* Keypad 4 */
+ 0xffb5, /* Keypad 5 */
+ 0xffb6, /* Keypad 6 */
+ 0xffb7, /* Keypad 7 */
+ 0xffb8, /* Keypad 8 */
+ 0xffb9, /* Keypad 9 */
+ 0xffb0, /* Keypad 0 */
+ '-', '=',
+ 0xff08, /* Backspace */
+ 0xff74, /* (Shift) Tab [Tab doesn't use this table] */
+
+ /* --------------- 10 to 1f --------------- */
+ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']',
+ 0xff8d, /* Keypad Enter */
+ 0, /* Ctrl */
+ 'a', 's',
+
+ /* --------------- 20 to 2f --------------- */
+ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',
+ 0, /* Left shift */
+ '\\', 'z', 'x', 'c', 'v',
+
+ /* --------------- 30 to 3f --------------- */
+ 'b', 'n', 'm', ',', '.',
+ 0xffaf, /* Grey / */
+ 0, /* Right shift */
+ 0xffaa, /* Grey * */
+ 0, /* Alt */
+ ' ',
+ 0, /* Caps Lock */
+ 0xffbe, /* F1 */
+ 0xffbf, /* F2 */
+ 0xffc0, /* F3 */
+ 0xffc1, /* F4 */
+ 0xffc2, /* F5 */
+
+ /* --------------- 40 to 4f --------------- */
+ 0xffc3, /* F6 */
+ 0xffc4, /* F7 */
+ 0xffc5, /* F8 */
+ 0xffc6, /* F9 */
+ 0xffc7, /* F10 */
+ 0, /* Num Lock */
+ 0, /* Scroll Lock */
+ 0xff50, /* Home */
+ 0xff52, /* Up */
+ 0xff55, /* Page Up */
+ 0xffad, /* Grey - */
+ 0xff51, /* Left */
+ 0xffb5, /* Keypad 5 */
+ 0xff53, /* Right */
+ 0xffab, /* Grey + */
+ 0xff57, /* End */
+
+ /* --------------- 50 to 5f --------------- */
+ 0xff54, /* Down */
+ 0xff56, /* Page Down */
+ 0xff63, /* Insert */
+ 0xffff, /* Delete */
+ 0xffbe, /* (Shift) F1 */
+ 0xffbf, /* (Shift) F2 */
+ 0xffc0, /* (Shift) F3 */
+ 0xffc1, /* (Shift) F4 */
+ 0xffc2, /* (Shift) F5 */
+ 0xffc3, /* (Shift) F6 */
+ 0xffc4, /* (Shift) F7 */
+ 0xffc5, /* (Shift) F8 */
+ 0xffc6, /* (Shift) F9 */
+ 0xffc7, /* (Shift) F10 */
+ 0xffbe, /* (Ctrl) F1 */
+ 0xffbf, /* (Ctrl) F2 */
+
+ /* --------------- 60 to 6f --------------- */
+ 0xffc0, /* (Ctrl) F3 */
+ 0xffc1, /* (Ctrl) F4 */
+ 0xffc2, /* (Ctrl) F5 */
+ 0xffc3, /* (Ctrl) F6 */
+ 0xffc4, /* (Ctrl) F7 */
+ 0xffc5, /* (Ctrl) F8 */
+ 0xffc6, /* (Ctrl) F9 */
+ 0xffc7, /* (Ctrl) F10 */
+ 0xffbe, /* (Alt) F1 */
+ 0xffbf, /* (Alt) F2 */
+ 0xffc0, /* (Alt) F3 */
+ 0xffc1, /* (Alt) F4 */
+ 0xffc2, /* (Alt) F5 */
+ 0xffc3, /* (Alt) F6 */
+ 0xffc4, /* (Alt) F7 */
+ 0xffc5, /* (Alt) F8 */
+
+ /* --------------- 70 to 7f --------------- */
+ 0xffc6, /* (Alt) F9 */
+ 0xffc7, /* (Alt) F10 */
+ 0xff6d, /* (Ctrl) Sys Rq */
+ 0xff51, /* (Ctrl) Left */
+ 0xff53, /* (Ctrl) Right */
+ 0xff57, /* (Ctrl) End */
+ 0xff56, /* (Ctrl) Page Down */
+ 0xff50, /* (Ctrl) Home */
+ '1', '2', '3', '4', '5', '6', '7', '8', /* (Alt) */
+
+ /* --------------- 80 to 8f --------------- */
+ '9', '0', '-', '=', /* (Alt) */
+ 0xff55, /* (Ctrl) Page Up */
+ 0xffc8, /* F11 */
+ 0xffc9, /* F12 */
+ 0xffc8, /* (Shift) F11 */
+ 0xffc9, /* (Shift) F12 */
+ 0xffc8, /* (Ctrl) F11 */
+ 0xffc9, /* (Ctrl) F12 */
+ 0xffc8, /* (Alt) F11 */
+ 0xffc9, /* (Alt) F12 */
+ 0xff52, /* (Ctrl) Up */
+ 0xffae, /* (Ctrl) Grey - */
+ 0xffb5, /* (Ctrl) Keypad 5 */
+
+ /* --------------- 90 to 9f --------------- */
+ 0xffab, /* (Ctrl) Grey + */
+ 0xff54, /* (Ctrl) Down */
+ 0xff63, /* (Ctrl) Insert */
+ 0xffff, /* (Ctrl) Delete */
+ 0xff09, /* (Ctrl) Tab */
+ 0xffaf, /* (Ctrl) Grey / */
+ 0xffaa, /* (Ctrl) Grey * */
+ 0xff50, /* (Alt) Home */
+ 0xff52, /* (Alt) Up */
+ 0xff55, /* (Alt) Page Up */
+ 0, /* NO KEY */
+ 0xff51, /* (Alt) Left */
+ 0, /* NO KEY */
+ 0xff53, /* (Alt) Right */
+ 0, /* NO KEY */
+ 0xff57, /* (Alt) End */
+
+ /* --------------- a0 to af --------------- */
+ 0xff54, /* (Alt) Down */
+ 0xff56, /* (Alt) Page Down */
+ 0xff63, /* (Alt) Insert */
+ 0xffff, /* (Alt) Delete */
+ 0xffaf, /* (Alt) Grey / */
+ 0xff09, /* (Alt) Tab */
+ 0xff0d /* (Alt) Enter */
+};
+
+/* Get a char from keyboard. Function keys are put into the event queue. */
+static int
+dos_rawgetc ()
+{
+ struct input_event event;
+ struct timeval tv;
+ union REGS regs;
+ int ctrl_p, alt_p, shift_p;
+
+ /* Calculate modifier bits */
+ regs.h.ah = extended_kbd ? 0x12 : 0x02;
+ int86 (0x16, &regs, &regs);
+ ctrl_p = ((regs.h.al & 4) != 0);
+ shift_p = ((regs.h.al & 3) != 0);
+ alt_p = ((extended_kbd ? (regs.h.ah & 2) : (regs.h.al & 8)) != 0);
+
+ while (kbhit ())
+ {
+ union REGS regs;
+ register unsigned char c;
+ int sc, code;
+
+ regs.h.ah = extended_kbd ? 0x10 : 0x00;
+ int86 (0x16, &regs, &regs);
+ c = regs.h.al;
+ sc = regs.h.ah;
+
+ /* Determine from the scan code if a keypad key was pressed. */
+ if (c >= '0' && c <= '9' && sc > 0xb)
+ sc = (c == '0') ? 0xb : (c - '0' + 1), c = 0;
+ else if (sc == 0xe0)
+ {
+ switch (c)
+ {
+ case 10: /* Ctrl Enter */
+ case 13:
+ sc = 0x1c;
+ break;
+ case '.': /* Decimal point or decimal comma */
+ case ',':
+ sc = 0x53;
+ break;
+ case '/':
+ sc = 0x35;
+ break;
+ default:
+ sc = 0;
+ };
+ c = 0;
+ }
+
+ if (c == 0
+ || c == ' '
+ || alt_p
+ || (ctrl_p && shift_p)
+ || (c == 0xe0 && sc != 0) /* Pseudo-key */
+ || sc == 0x37 /* Grey * */
+ || sc == 0x4a /* Grey - */
+ || sc == 0x4e /* Grey + */
+ || sc == 0x0e) /* Back space *key*, not Ctrl-h */
+ {
+ if (sc >= (sizeof (ibmpc_translate_map) / sizeof (short)))
+ code = 0;
+ else
+ code = ibmpc_translate_map[sc];
+ if (code != 0)
+ {
+ if (code >= 0x100)
+ {
+ event.kind = non_ascii_keystroke;
+ event.code = code & 0xff;
+ }
+ else
+ {
+ /* Don't return S- if we don't have to. */
+ if (code >= 'a' && code <= 'z')
+ {
+ c = shift_p ? toupper (code) : code;
+ shift_p = 0;
+ }
+ else
+ if (c == 0) c = code;
+ event.kind = ascii_keystroke;
+ event.code = c;
+ }
+ event.modifiers
+ = (shift_p ? shift_modifier : 0)
+ + (ctrl_p ? ctrl_modifier : 0)
+ + (alt_p ? meta_modifier : 0);
+ /* EMACS == Enter Meta Alt Control Shift */
+ event.frame_or_window = selected_frame;
+ gettimeofday (&tv, NULL);
+ event.timestamp = tv.tv_usec;
+ kbd_buffer_store_event (&event);
+ }
+ } else
+ return c;
+ }
+
+ if (have_mouse)
+ {
+ int but, press, x, y, ok;
+
+ /* Check for mouse movement *before* buttons. */
+ Mouse_check_moved ();
+
+ for (but = 0; but < NUM_MOUSE_BUTTONS; but++)
+ for (press = 0; press < 2; press++)
+ {
+ if (press)
+ ok = Mouse_pressed (but, &x, &y);
+ else
+ ok = Mouse_released (but, &x, &y);
+ if (ok)
+ {
+ event.kind = mouse_click;
+ event.code = but;
+ event.modifiers
+ = (shift_p ? shift_modifier : 0)
+ + (ctrl_p ? ctrl_modifier : 0)
+ + (alt_p ? meta_modifier : 0)
+ + (press ? down_modifier : up_modifier);
+ event.x = x;
+ event.y = y;
+ event.frame_or_window = selected_frame;
+ gettimeofday (&tv, NULL);
+ event.timestamp = tv.tv_usec;
+ kbd_buffer_store_event (&event);
+ }
+ }
+ }
+
+ return -1;
+}
+
+static int prev_get_char = -1;
+
+/* Return 1 if a key is ready to be read without suspending execution. */
+dos_keysns ()
+{
+ if (prev_get_char != -1)
+ return 1;
+ else
+ return ((prev_get_char = dos_rawgetc ()) != -1);
+}
+
+/* Read a key. Return -1 if no key is ready. */
+dos_keyread ()
+{
+ if (prev_get_char != -1)
+ {
+ int c = prev_get_char;
+ prev_get_char = -1;
+ return c;
+ }
+ else
+ return dos_rawgetc ();
+}
+
+/* Hostnames for a pc are not really funny, but they are used in change log
+ so we emulate the best we can. */
+gethostname (p, size)
+ char *p;
+ int size;
+{
+ char *q = egetenv ("HOSTNAME");
+
+ if (!q) q = "pc";
+ strcpy (p, q);
+ return 0;
+}
+
+/* Destructively turn backslashes into slashes. */
+void
+dostounix_filename (p)
+ register char *p;
+{
+ while (*p)
+ {
+ if (*p == '\\')
+ *p = '/';
+ p++;
+ }
+}
+
+/* Destructively turn slashes into backslashes. */
+void
+unixtodos_filename (p)
+ register char *p;
+{
+ while (*p)
+ {
+ if (*p == '/')
+ *p = '\\';
+ p++;
+ }
+}
+
+/* Get the default directory for a given drive. 0=def, 1=A, 2=B, ... */
+int
+getdefdir (drive, dst)
+ int drive;
+ char *dst;
+{
+ union REGS regs;
+
+ *dst++ = '/';
+ regs.h.dl = drive;
+ regs.x.si = (int) dst;
+ regs.h.ah = 0x47;
+ intdos (&regs, &regs);
+ return !regs.x.cflag;
+}
+
+/* Remove all CR's that are followed by a LF. */
+int
+crlf_to_lf (n, buf)
+ register int n;
+ register unsigned char *buf;
+{
+ unsigned char *np = buf;
+ unsigned char *startp = buf;
+ unsigned char *endp = buf + n;
+ unsigned char c;
+
+ if (n == 0)
+ return n;
+ while (buf < endp)
+ {
+ if (*buf == 0x0d)
+ {
+ if (*(++buf) != 0x0a)
+ *np++ = 0x0d;
+ }
+ else
+ *np++ = *buf++;
+ }
+ return np - startp;
+}
+
+
+/* Run command as specified by ARGV in directory DIR.
+ The command is run with input from TEMPIN and output to file TEMPOUT. */
+int
+run_msdos_command (argv, dir, tempin, tempout)
+ unsigned char **argv;
+ Lisp_Object dir;
+ int tempin, tempout;
+{
+ char *saveargv1, *saveargv2, **envv;
+ char oldwd[MAXPATHLEN + 1]; /* Fixed size is safe on MSDOS. */
+ int msshell, result = -1;
+ int in, out, inbak, outbak, errbak;
+ Lisp_Object cmd;
+
+ /* Get current directory as MSDOS cwd is not per-process. */
+ getwd (oldwd);
+
+ cmd = Ffile_name_nondirectory (build_string (argv[0]));
+ msshell = !NILP (Fmember (cmd, Fsymbol_value (intern ("msdos-shells"))))
+ && !strcmp ("-c", argv[1]);
+ if (msshell)
+ {
+ saveargv1 = argv[1];
+ argv[1] = "/c";
+ if (argv[2])
+ {
+ saveargv2 = argv[2];
+ unixtodos_filename (argv[2] = strdup (argv[2]));
+ }
+ }
+
+ /* Build the environment array. */
+ {
+ extern Lisp_Object Vprocess_environment;
+ Lisp_Object tmp, lst = Vprocess_environment;
+ int i, len = XFASTINT (Flength (lst));
+
+ envv = alloca ((len + 1) * sizeof (char *));
+ for (i = 0; i < len; i++)
+ {
+ tmp = Fcar (lst);
+ lst = Fcdr (lst);
+ CHECK_STRING (tmp, 0);
+ envv[i] = alloca (XSTRING (tmp)->size + 1);
+ strcpy (envv[i], XSTRING (tmp)->data);
+ }
+ envv[len] = (char *) 0;
+ }
+
+ if (XTYPE (dir) == Lisp_String)
+ chdir (XSTRING (dir)->data);
+ inbak = dup (0);
+ outbak = dup (1);
+ errbak = dup (2);
+ if (inbak < 0 || outbak < 0 || errbak < 0)
+ goto done; /* Allocation might fail due to lack of descriptors. */
+ dup2 (tempin, 0);
+ dup2 (tempout, 1);
+ dup2 (tempout, 2);
+ dos_ttcooked ();
+ result = spawnve (P_WAIT, argv[0], argv, envv);
+ dos_ttraw ();
+ dup2 (inbak, 0);
+ dup2 (outbak, 1);
+ dup2 (errbak, 2);
+
+ done:
+ chdir (oldwd);
+ if (msshell)
+ {
+ argv[1] = saveargv1;
+ if (argv[2])
+ {
+ free (argv[2]);
+ argv[2] = saveargv2;
+ }
+ }
+ return result;
+}
+
+
+croak (badfunc)
+ char *badfunc;
+{
+ fprintf (stderr, "%s not yet implemented\r\n", badfunc);
+ reset_sys_modes ();
+ exit (1);
+}
+
+/* A list of unimplemented functions that we silently ignore. */
+unsigned alarm (s) unsigned s; {}
+fork () { return 0; }
+int kill (x, y) int x, y; { return -1; }
+nice (p) int p; {}
+void volatile pause () {}
+request_sigio () {}
+setpgrp () {return 0; }
+setpriority (x,y,z) int x,y,z; { return 0; }
+sigsetmask (x) int x; { return 0; }
+unrequest_sigio () {}
+
+#ifdef chdir
+#undef chdir
+#endif
+
+int
+sys_chdir (path)
+ const char* path;
+{
+ int len = strlen (path);
+ char *tmp = (char *) alloca (len + 1);
+ /* Gotta do this extern here due to the corresponding #define: */
+ extern int chdir ();
+
+ if (*path && path[1] == ':' && (getdisk () != tolower (path[0]) - 'a'))
+ setdisk (tolower (path[0]) - 'a');
+
+ strcpy (tmp, path);
+ if (strcmp (path, "/") && strcmp (path + 1, ":/") && (path[len - 1] == '/'))
+ tmp[len - 1] = 0;
+ return chdir (tmp);
+}
+
+/* Sleep SECS. If KBDOK also return immediately if a key is pressed. */
+void
+sleep_or_kbd_hit (secs, kbdok)
+ int secs, kbdok;
+{
+ long clnow, clthen;
+ struct timeval t;
+
+ gettimeofday (&t, NULL);
+ clnow = t.tv_sec * 100 + t.tv_usec / 10000;
+ clthen = clnow + (100 * secs);
+
+ do
+ {
+ gettimeofday (&t, NULL);
+ clnow = t.tv_sec * 100 + t.tv_usec / 10000;
+ if (kbdok && detect_input_pending ())
+ return;
+ }
+ while (clnow < clthen);
+}
+
+/* Define a lot of environment variables if not already defined. Don't
+ remove anything unless you know what you're doing -- lots of code will
+ break if one or more of these are missing. */
+void
+init_environment (argc, argv, skip_args)
+ int argc;
+ char **argv;
+ int skip_args;
+{
+ char *s, *t;
+
+ /* We default HOME to the directory from which Emacs was started, but with
+ a "/bin" suffix removed. */
+ s = argv[0];
+ t = alloca (strlen (s) + 1);
+ strcpy (t, s);
+ s = t + strlen (t);
+ while (s != t && *s != '/' && *s != ':') s--;
+ if (s == t)
+ t = "c:/emacs"; /* When run under debug32. */
+ else
+ {
+ if (*s == ':') s++;
+ *s = 0;
+ if (s - 4 >= t && strcmp (s - 4, "/bin") == 0)
+ s[strlen (s) - 4] = 0;
+ }
+ setenv ("HOME", t, 0);
+
+ /* We set EMACSPATH to ~/bin (expanded) */
+ s = getenv ("HOME");
+ t = strcpy (alloca (strlen (s) + 6), s);
+ if (s[strlen (s) - 1] != '/') strcat (t, "/");
+ strcat (t, "bin");
+ setenv ("EMACSPATH", t, 0);
+
+ /* I don't expect anybody to ever use other terminals so the internal
+ terminal is the default. */
+ setenv ("TERM", "internal", 0);
+
+ /* SHELL is a bit tricky -- COMSPEC is the closest we come, but we must
+ downcase it and mirror the backslashes. */
+ s = getenv ("COMSPEC");
+ if (!s) s = "c:/command.com";
+ t = alloca (strlen (s) + 1);
+ strcpy (t, s);
+ strlwr (t);
+ dostounix_filename (t);
+ setenv ("SHELL", t, 0);
+
+ /* PATH is also downcased and backslashes mirrored. */
+ s = getenv ("PATH");
+ if (!s) s = "";
+ t = alloca (strlen (s) + 3);
+ /* Current directory is always considered part of MsDos's path but it is
+ not normally mentioned. Now it is. */
+ strcat (strcpy (t, ".;"), s);
+ strlwr (t);
+ dostounix_filename (t); /* Not a single file name, but this should work. */
+ setenv ("PATH", t, 1);
+
+ /* In some sense all dos users have root privileges, so... */
+ setenv ("USER", "root", 0);
+ setenv ("NAME", getenv ("USER"), 0);
+
+ /* Time zone determined from country code. To make this possible, the
+ country code may not span more than one time zone. In other words,
+ in the USA, you lose. */
+ switch (dos_country_code)
+ {
+ case 31: /* Belgium */
+ case 32: /* The Netherlands */
+ case 33: /* France */
+ case 34: /* Spain */
+ case 36: /* Hungary */
+ case 38: /* Yugoslavia (or what's left of it?) */
+ case 39: /* Italy */
+ case 41: /* Switzerland */
+ case 42: /* Tjekia */
+ case 45: /* Denmark */
+ case 46: /* Sweden */
+ case 47: /* Norway */
+ case 48: /* Poland */
+ case 49: /* Germany */
+ /* Daylight saving from last Sunday in March to last Sunday in
+ September, both at 2AM. */
+ setenv ("TZ", "MET-01METDST-02,M3.5.0/02:00,M9.5.0/02:00", 0);
+ break;
+ case 44: /* United Kingdom */
+ case 351: /* Portugal */
+ case 354: /* Iceland */
+ setenv ("TZ", "GMT+00", 0);
+ break;
+ case 81: /* Japan */
+ case 82: /* Korea */
+ setenv ("TZ", "???-09", 0);
+ break;
+ case 90: /* Turkey */
+ case 358: /* Finland */
+ case 972: /* Israel */
+ setenv ("TZ", "EET-02", 0);
+ break;
+ }
+ tzset ();
+}
+
+/* Flash the screen as a substitute for BEEPs. */
+
+static unsigned char _xorattr;
+
+void
+visible_bell (xorattr)
+ unsigned char xorattr;
+{
+ _xorattr = xorattr;
+ asm (" pushl %eax
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ movl $1,%edx
+visible_bell_0:
+ movl _ScreenPrimary,%eax
+ call dosmemsetup
+ movl %eax,%ebx
+ call _ScreenRows
+ movl %eax,%ecx
+ call _ScreenCols
+ imull %eax,%ecx
+ movb (__xorattr),%al
+ incl %ebx
+visible_bell_1:
+ xorb %al,%gs:(%ebx)
+ addl $2,%ebx
+ decl %ecx
+ jne visible_bell_1
+ decl %edx
+ jne visible_bell_3
+visible_bell_2:
+ movzwl %ax,%eax
+ movzwl %ax,%eax
+ movzwl %ax,%eax
+ movzwl %ax,%eax
+ decw %cx
+ jne visible_bell_2
+ jmp visible_bell_0
+visible_bell_3:
+ popl %edx
+ popl %ecx
+ popl %ebx
+ popl %eax");
+}
+
+static int internal_terminal = 0;
+#undef fflush
+
+int
+internal_flush (f)
+ FILE *f;
+{
+ static int x;
+ static int y;
+ char c, *cp;
+ int count, i;
+
+ if (internal_terminal && f == stdout)
+ {
+ if (have_mouse) Mouse_off ();
+ cp = stdout->_base;
+ count = stdout->_ptr - stdout->_base;
+ while (count > 0)
+ {
+ switch (c = *cp++)
+ {
+ case 27:
+ switch (*cp++)
+ {
+ case '@':
+ y = *cp++;
+ x = *cp++;
+ count -= 4;
+ break;
+ case 'A':
+ ScreenAttrib = *cp++;
+ count -= 3;
+ break;
+ case 'B':
+ visible_bell (*cp++);
+ count -= 3;
+ break;
+ case 'C':
+ ScreenClear ();
+ x = y = 0;
+ count -= 2;
+ break;
+ case 'E':
+ for (i = ScreenCols () - 1; i >= x; i--)
+ ScreenPutChar (' ', ScreenAttrib, i, y);
+ count -= 2;
+ break;
+ case 'R':
+ x++;
+ count -= 2;
+ break;
+ case 'U':
+ y--;
+ count -= 2;
+ break;
+ case 'X':
+ ScreenAttrib ^= *cp++;
+ count -= 3;
+ break;
+ default:
+ count -= 2;
+ }
+ break;
+ case 8:
+ x--;
+ count--;
+ break;
+ case 13:
+ x = 0;
+ count--;
+ break;
+ case 10:
+ y++;
+ count--;
+ break;
+ default:
+ ScreenPutChar (c, ScreenAttrib, x++, y);
+ count--;
+ }
+ }
+ fpurge (stdout);
+ ScreenSetCursor (y, x);
+ if (have_mouse) Mouse_on ();
+ }
+ else
+ /* This is a call to the original fflush. */
+ fflush (f);
+}
+
+/* Do we need the internal terminal? */
+void
+internal_terminal_init ()
+{
+ char *term = getenv ("TERM");
+
+ internal_terminal
+ = (!noninteractive) && term && !strcmp (term, "internal");
+}
+
+/* These must be global. */
+static _go32_dpmi_seginfo ctrl_break_vector;
+static _go32_dpmi_registers ctrl_break_regs;
+static int ctrlbreakinstalled = 0;
+
+/* Interrupt level detection of Ctrl-Break. Don't do anything fancy here! */
+void
+ctrl_break_func (regs)
+ _go32_dpmi_registers *regs;
+{
+ Vquit_flag = Qt;
+}
+
+void
+install_ctrl_break_check ()
+{
+ if (!ctrlbreakinstalled)
+ {
+ /* Don't press Ctrl-Break if you don't have either DPMI or Emacs
+ was compiler with Djgpp 1.11 maintenance level 2 or later! */
+ ctrlbreakinstalled = 1;
+ ctrl_break_vector.pm_offset = (int) ctrl_break_func;
+ _go32_dpmi_allocate_real_mode_callback_iret (&ctrl_break_vector,
+ &ctrl_break_regs);
+ _go32_dpmi_set_real_mode_interrupt_vector (0x1b, &ctrl_break_vector);
+ }
+}
+
+
+/* Mouse routines under devellopment follow. Coordinates are in screen
+ positions and zero based. Mouse buttons are numbered from left to
+ right and also zero based. */
+
+static int mouse_button_translate[NUM_MOUSE_BUTTONS];
+static int mouse_button_count;
+
+void
+mouse_init ()
+{
+ union REGS regs;
+
+ regs.x.ax = 0x0007;
+ regs.x.cx = 0;
+ regs.x.dx = 8 * (ScreenCols () - 1);
+ int86 (0x33, &regs, &regs);
+
+ regs.x.ax = 0x0008;
+ regs.x.cx = 0;
+ regs.x.dx = 8 * (ScreenRows () - 1);
+ int86 (0x33, &regs, &regs);
+
+ mouse_moveto (ScreenCols () - 1, ScreenRows () - 1);
+ mouse_on ();
+}
+
+void
+mouse_on ()
+{
+ union REGS regs;
+
+ regs.x.ax = 0x0001;
+ int86 (0x33, &regs, &regs);
+}
+
+void
+mouse_off ()
+{
+ union REGS regs;
+
+ regs.x.ax = 0x0002;
+ int86 (0x33, &regs, &regs);
+}
+
+void
+mouse_moveto (x, y)
+ int x, y;
+{
+ union REGS regs;
+
+ regs.x.ax = 0x0004;
+ mouse_last_x = regs.x.cx = x * 8;
+ mouse_last_y = regs.x.dx = y * 8;
+ int86 (0x33, &regs, &regs);
+}
+
+int
+mouse_pressed (b, xp, yp)
+ int b, *xp, *yp;
+{
+ union REGS regs;
+
+ if (b >= mouse_button_count)
+ return 0;
+ regs.x.ax = 0x0005;
+ regs.x.bx = mouse_button_translate[b];
+ int86 (0x33, &regs, &regs);
+ if (regs.x.bx)
+ *xp = regs.x.cx / 8, *yp = regs.x.dx /8;
+ return (regs.x.bx != 0);
+}
+
+int
+mouse_released (b, xp, yp)
+ int b, *xp, *yp;
+{
+ union REGS regs;
+
+ if (b >= mouse_button_count)
+ return 0;
+ regs.x.ax = 0x0006;
+ regs.x.bx = mouse_button_translate[b];
+ int86 (0x33, &regs, &regs);
+ if (regs.x.bx)
+ *xp = regs.x.cx / 8, *yp = regs.x.dx / 8;
+ return (regs.x.bx != 0);
+}
+
+void
+mouse_get_pos (f, bar_window, part, x, y, time)
+ FRAME_PTR *f;
+ Lisp_Object *bar_window, *x, *y;
+ enum scroll_bar_part *part;
+ unsigned long *time;
+{
+ union REGS regs;
+ struct timeval tv;
+
+ regs.x.ax = 0x0003;
+ int86 (0x33, &regs, &regs);
+ *f = selected_frame;
+ *bar_window = Qnil;
+ gettimeofday (&tv, NULL);
+ *x = make_number (regs.x.cx / 8);
+ *y = make_number (regs.x.dx / 8);
+ *time = tv.tv_usec;
+ mouse_moved = 0;
+}
+
+void
+mouse_check_moved ()
+{
+ union REGS regs;
+
+ regs.x.ax = 0x0003;
+ int86 (0x33, &regs, &regs);
+ if (regs.x.cx != mouse_last_x || regs.x.dx != mouse_last_y)
+ {
+ mouse_moved = 1;
+ mouse_last_x = regs.x.cx;
+ mouse_last_y = regs.x.dx;
+ }
+}
+
+int
+mouse_init1 ()
+{
+ union REGS regs;
+ int present;
+
+ regs.x.ax = 0x0021;
+ int86 (0x33, &regs, &regs);
+ present = internal_terminal && (regs.x.ax & 0xffff) == 0xffff;
+ if (present)
+ {
+ if (regs.x.bx == 3)
+ {
+ mouse_button_count = 3;
+ mouse_button_translate[0] = 0; /* Left */
+ mouse_button_translate[1] = 2; /* Middle */
+ mouse_button_translate[2] = 1; /* Right */
+ }
+ else
+ {
+ mouse_button_count = 2;
+ mouse_button_translate[0] = 0;
+ mouse_button_translate[1] = 1;
+ }
+ mouse_position_hook = &mouse_get_pos;
+ mouse_init ();
+ }
+ return present;
+}
+
+#endif /* MSDOS */
diff --git a/src/msdos.h b/src/msdos.h
new file mode 100644
index 00000000000..bf3030c00df
--- /dev/null
+++ b/src/msdos.h
@@ -0,0 +1,45 @@
+/* MS-DOS specific C utilities, interface.
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+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
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <time.h>
+#include <dpmi.h>
+
+int dos_ttraw ();
+int dos_ttcooked ();
+int getdefdir (int, char*);
+void unixtodos_filename (char *);
+void dostounix_filename (char *);
+void sleep_or_kbd_hit (int, int);
+void init_environment ();
+void internal_terminal_init ();
+#ifndef _stdio_h_
+int internal_flush (FILE *);
+#endif
+void ctrl_break_func (_go32_dpmi_registers *);
+void install_ctrl_break_check ();
+
+extern int have_mouse;
+int mouse_init1 ();
+void mouse_init ();
+void mouse_on ();
+void mouse_off ();
+void mouse_moveto (int, int);
+void mouse_check_moved ();
+int mouse_pressed (int, int *, int *);
+int mouse_released (int, int *, int *);
diff --git a/src/s/msdos.h b/src/s/msdos.h
new file mode 100644
index 00000000000..10c15ee682e
--- /dev/null
+++ b/src/s/msdos.h
@@ -0,0 +1,219 @@
+/* System description file for MS-DOS
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+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
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Note: lots of stuff here was taken from s-msdos.h in demacs. */
+
+
+/*
+ * Define symbols to identify the version of Unix this is.
+ * Define all the symbols that apply correctly.
+ */
+
+/* #define UNIPLUS */
+/* #define USG5 */
+/* #define USG */
+/* #define HPUX */
+/* #define UMAX */
+/* #define BSD4_1 */
+/* #define BSD4_2 */
+/* #define BSD4_3 */
+/* #define BSD */
+/* #define VMS */
+#ifndef MSDOS
+#define MSDOS
+#endif
+#undef BSD
+#undef VMS
+
+/* SYSTEM_TYPE should indicate the kind of system you are using.
+ It sets the Lisp variable system-type. */
+
+#define SYSTEM_TYPE "ms-dos"
+
+#define SYMS_SYSTEM syms_of_dosfns()
+
+/* NOMULTIPLEJOBS should be defined if your system's shell
+ does not have "job control" (the ability to stop a program,
+ run some other program, then continue the first one). */
+
+#define NOMULTIPLEJOBS
+
+/* Emacs can read input using SIGIO and buffering characters itself,
+ or using CBREAK mode and making C-g cause SIGINT.
+ The choice is controlled by the variable interrupt_input.
+ Define INTERRUPT_INPUT to make interrupt_input = 1 the default (use SIGIO)
+
+ SIGIO can be used only on systems that implement it (4.2 and 4.3).
+ CBREAK mode has two disadvatages
+ 1) At least in 4.2, it is impossible to handle the Meta key properly.
+ I hear that in system V this problem does not exist.
+ 2) Control-G causes output to be discarded.
+ I do not know whether this can be fixed in system V.
+
+ Another method of doing input is planned but not implemented.
+ It would have Emacs fork off a separate process
+ to read the input and send it to the true Emacs process
+ through a pipe.
+*/
+
+/* #define INTERRUPT_INPUT */
+
+/* Letter to use in finding device name of first pty,
+ if system supports pty's. 'a' means it is /dev/ptya0 */
+
+/* #define FIRST_PTY_LETTER 'a' */
+
+/*
+ * Define HAVE_TIMEVAL if the system supports the BSD style clock values.
+ * Look in <sys/time.h> for a timeval structure.
+ */
+
+#define HAVE_TIMEVAL
+
+/*
+ * Define HAVE_SELECT if the system supports the `select' system call.
+ */
+
+/* #define HAVE_SELECT */
+
+/*
+ * Define HAVE_PTYS if the system supports pty devices.
+ */
+
+/* #define HAVE_PTYS */
+
+/*
+ * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
+ * The 4.2 opendir, etc., library functions.
+ */
+
+/* #define NONSYSTEM_DIR_LIBRARY */
+
+#define SYSV_SYSTEM_DIR
+
+/* Define this symbol if your system has the functions bcopy, etc. */
+
+#define BSTRING
+
+/* subprocesses should be defined if you want to
+ have code for asynchronous subprocesses
+ (as used in M-x compile and M-x shell).
+ This is generally OS dependent, and not supported
+ under most USG systems. */
+
+#undef subprocesses
+
+/* If your system uses COFF (Common Object File Format) then define the
+ preprocessor symbol "COFF". */
+
+#define COFF
+
+/* define MAIL_USE_FLOCK if the mailer uses flock
+ to interlock access to /usr/spool/mail/$USER.
+ The alternative is that a lock file named
+ /usr/spool/mail/$USER.lock. */
+
+/* #define MAIL_USE_FLOCK */
+
+/* Define CLASH_DETECTION if you want lock files to be written
+ so that Emacs can tell instantly when you try to modify
+ a file that someone else has modified in his Emacs. */
+
+/* #define CLASH_DETECTION */
+
+/* Here, on a separate page, add any special hacks needed
+ to make Emacs work on this system. For example,
+ you might define certain system call names that don't
+ exist on your system, or that do different things on
+ your system and must be used only through an encapsulation
+ (Which you should place, by convention, in sysdep.c). */
+
+/* Some compilers tend to put everything declared static
+ into the initialized data area, which becomes pure after dumping Emacs.
+ On these systems, you must #define static as nothing to foil this.
+ Note that emacs carefully avoids static vars inside functions. */
+
+/* #define static */
+
+/* we use djgcc's malloc */
+/* #define SYSTEM_MALLOC */
+/* setjmp and longjmp can safely replace _setjmp and _longjmp,
+ but they will run slower. */
+
+#define _setjmp setjmp
+#define _longjmp longjmp
+
+#define NO_MODE_T
+
+/* we can use dj's getpagesize() */
+#define HAVE_GETPAGESIZE
+
+/* New chdir () routine. */
+#ifdef chdir
+#undef chdir
+#endif
+#define chdir sys_chdir
+
+#define LIBS_SYSTEM -lpc
+
+/* This somehow needs to be defined even though we use COFF. */
+#define TEXT_START -1
+
+#define ORDINARY_LINK
+
+/* command.com does not under stand `...` so we define this. */
+#define LIB_GCC -Lgcc
+#define DONT_NEED_ENVIRON
+#define SEPCHAR ';'
+
+#define NULL_DEVICE "nul"
+#define EXEC_SUFFIXES ".exe:.com:.bat:"
+
+#define O_RDONLY 0x0001
+#define O_WRONLY 0x0002
+#define O_RDWR 0x0004
+#define O_CREAT 0x0100
+#define O_TRUNC 0x0200
+#define O_EXCL 0x0400
+#define O_APPEND 0x0800
+#define O_TEXT 0x4000
+#define O_BINARY 0x8000
+
+#define HAVE_INVERSE_HYPERBOLIC
+#define FLOAT_CHECK_DOMAIN
+
+/* When $TERM is "internal" then this is substituted: */
+#define INTERNAL_TERMINAL "pc|bios|IBM PC with colour display:\
+:co#80:li#25:km:\
+:cm=\E@%.%.:\
+:do=^J:le=^H:up=\EU:ri=\ER:\
+:ti=\EA\027:te=\EA\007\EE:\
+:so=\EA\077:se=\EA\027:\
+:ms:mb=\EX\200:md=\EX\010:mk=\EA\161:me=\EA\027:\
+:cl=\EC:ce=\EE:\
+:vb=\EB\140:bl=:"
+#define fflush internal_flush
+
+/* Define this to a function (Fdowncase, Fupcase) if your file system
+ likes that */
+#define FILE_SYSTEM_CASE Fdowncase
+
+/* MSDOS doesn't really have this function. */
+#define getppid() 1