diff -u --recursive --new-file dosemu0.53pl47/ChangeLog dosemu0.53pl48/ChangeLog
--- dosemu0.53pl47/ChangeLog	Fri Mar  3 18:06:07 1995
+++ dosemu0.53pl48/ChangeLog	Tue Mar  7 21:26:18 1995
@@ -1,3 +1,41 @@
+Tue Mar 06	1995
+
+-	Release pl48
+-	Latest from Marty (need to test serial)
+-	Scott adds new timer code
+-	Latest DPMI
+-	Latest Slang, uses ^^ instead of ^@.
+-	Beginning of keyboard split.
+-	Alistairs UNIX power additions:
+OK - This version of unix.exe allows you to interrogate UNIX environment 
+variables and then execute a program contained within AND you can now pass
+programs to DOSEMU to execute.
+
+Basics:
+
+Passing a command to DOSEMU:
+============================
+	dos -E "command to be passed to DOSEMU" ....
+	....
+	C:\> unix.exe -e
+  	>> RUNS command to be passed to DOSEMU <<
+
+Executing the contents of an UNIX Environment Variable:
+=======================================================
+	C:\> unix.exe -e ENV_VAR_NAME
+	>> RUNS COMMAND NAMED IN env_var_name <<
+
+  NB ENV_VAR_NAME will probably need to be in CAPITALS !
+
+Running a UNIX Command:
+=======================
+  (As Before...)
+	C:\ unix.exe ls -l /dev
+	>> RUNS "ls -l /dev" under Linux .... <<
+
+----------
+Alistair
+
 Fri Mar 03	1995
 
 -	Release pl47.
diff -u --recursive --new-file dosemu0.53pl47/DANG_CONFIG dosemu0.53pl48/DANG_CONFIG
--- dosemu0.53pl47/DANG_CONFIG	Sat Jan 14 11:28:03 1995
+++ dosemu0.53pl48/DANG_CONFIG	Fri Mar  3 20:41:20 1995
@@ -3,7 +3,7 @@
 #
 
 # BASEDIR sets a path fragment which is prepended to _all_ paths.
-BASEDIR: 	../dosemu0.53pl36/
+BASEDIR: 	../dosemu0.60/
 
 # GROUPs are formed from :
 # <group_name> <summary_file> <file1> ... <fileN>
diff -u --recursive --new-file dosemu0.53pl47/Makefile dosemu0.53pl48/Makefile
--- dosemu0.53pl47/Makefile	Wed Mar  1 19:16:47 1995
+++ dosemu0.53pl48/Makefile	Tue Mar  7 21:28:25 1995
@@ -124,7 +124,7 @@
 EMUVER  =   0.53
 export EMUVER
 VERNUM  =   0x53
-PATCHL  =   47
+PATCHL  =   48
 LIBDOSEMU = libdosemu$(EMUVER)pl$(PATCHL)
 
 # DON'T CHANGE THIS: this makes libdosemu start high enough to be safe. 
@@ -171,7 +171,7 @@
 
 OPTIONALSUBDIRS =examples v-net syscallmgr emumod ipxutils
 
-LIBSUBDIRS= dosemu timer mfs video init keyboard mouse $(NET) $(IPX) drivers
+LIBSUBDIRS= video dosemu timer mfs init keyboard mouse $(NET) $(IPX) drivers
 
 ifdef DPMI
 LIBSUBDIRS+= dpmi
@@ -222,6 +222,7 @@
 # does this work if you do make -C <some dir>
 TOPDIR  := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
 INCDIR     = -I$(TOPDIR)/include  -I$(LINUX_INCLUDE)
+INCDIR += -I$(TOPDIR)/timer -I$(TOPDIR)/dpmi
 ifndef USE_SLANG
 INCDIR  += -I$(NCURSES_INC)
 endif
@@ -392,7 +393,7 @@
 	$(LD) $(LDFLAGS) -N -o $@ $^ $(addprefix -L,$(LIBPATH)) -L. \
 		$(TCNTRL) $(XLIBS)
 
-$(LIBDOSEMU): 	emu.o data.o # dossubdirs
+$(LIBDOSEMU): 	emu.o data.o dos2linux/dos2linux.o # dossubdirs
 	$(LD) $(LDFLAGS) $(MAGIC) -Ttext $(LIBSTART) -o $(LIBDOSEMU) \
 	   -nostdlib $^ $(addprefix -L,$(LIBPATH)) -L. $(SHLIBS) \
 	    $(addprefix -l, $(LIBS)) bios/bios.o $(XLIBS) $(TCNTRL) -lc 
@@ -507,6 +508,8 @@
 dist:: $(CFILES) $(HFILES) $(SFILES) $(OFILES) $(BFILES) include/config.h
 	install -d $(DISTPATH)
 	install -d $(DISTPATH)/lib
+	install -d $(DISTPATH)/dos2linux
+	cp -a dos2linux/*.[ch] $(DISTPATH)/dos2linux
 	cp -a dosemu.xpm libslang.a $(CFILES) $(HFILES) $(SFILES) $(OFILES) $(BFILES) $(DISTPATH)
 	cp -a TODO $(DISTPATH)/.todo
 	cp -a TODO.JES $(DISTPATH)/.todo.jes
@@ -540,11 +543,11 @@
 
 .PHONY: $(CLEANDIRS)
 $(CLEANDIRS):
-	$(MAKE) -C $(subst .clean,,$@) clean CLEANING=true
+	-@$(MAKE) -C $(subst .clean,,$@) clean CLEANING=true
 
 .PHONY: $(REALCLEANDIRS)
 $(REALCLEANDIRS):
-	$(MAKE) -C $(subst .realclean,,$@) realclean CLEANING=true
+	-@$(MAKE) -C $(subst .realclean,,$@) realclean CLEANING=true
 
 
 
diff -u --recursive --new-file dosemu0.53pl47/bios/bios.S dosemu0.53pl48/bios/bios.S
--- dosemu0.53pl47/bios/bios.S	Mon Feb 27 19:27:54 1995
+++ dosemu0.53pl48/bios/bios.S	Tue Mar  7 18:52:36 1995
@@ -508,6 +508,9 @@
 	.globl	CISH(DPMI_return_from_dos)
 CISH(DPMI_return_from_dos):
 	hlt
+	.globl	CISH(DPMI_return_from_dos_exec) /* for bcc.h */
+CISH(DPMI_return_from_dos_exec):
+	hlt
 	.globl	CISH(DPMI_return_from_dosint)
 CISH(DPMI_return_from_dosint):
 	FILL_OPCODE(256,hlt)
@@ -651,11 +654,7 @@
 	mov	bx, #LASTSCAN_SEG	/* get segment of LASTSCAN_ADDR	*/
 	push	bx
 	pop	ds
-#ifndef NEW_PIC				/* next 2 lines not needed?	*/
-	xor	cx,cx
-	inc	cx
-#endif
-			/* LASTSCAN_OFF = 0x20f2 = pseudo 8042 output	*/
+/* LASTSCAN_OFF = 0x20f2 = pseudo 8042 output	*/
 	mov	bx,#LASTSCAN_OFF
 	mov	ax,[bx]			/* "read" keyboard controller	*/
 
diff -u --recursive --new-file dosemu0.53pl47/commands/unix.c dosemu0.53pl48/commands/unix.c
--- dosemu0.53pl47/commands/unix.c	Fri Mar  3 18:06:19 1995
+++ dosemu0.53pl48/commands/unix.c	Tue Mar  7 21:32:32 1995
@@ -3,9 +3,63 @@
 #include <dos.h>
 
 
+/* AM - Needed by TC to compile ... */
+#include <stdlib.h>
+#include <process.h>
+
+int check_for_DOSEMU(void);
+void usage (char *name);
+send_command(int argc, char **argv);
+void do_execute_dos (int argc, char **argv);
+void do_set_dosenv (int agrc, char **argv);
 
+
 int main(int argc, char **argv)
 {
+  if (!check_for_DOSEMU ()) {
+    printf ("This Command can only be used under DOSEMU.\n");
+    exit (-1);
+  }
+  
+  if (*argv[1] == '-') {
+    /* Got a switch */
+    switch ((argv[1])[1]) {
+    case 'e':
+    case 'E':
+      /* EXECUTE dos command*/
+      do_execute_dos (argc-2, argv+2);
+      break;
+    case 's':
+    case 'S':
+      /* SETENV */
+      do_set_dosenv (argc-2, argv+2);
+      break;
+    default:
+      usage(argv[0]);
+    }
+  }
+    
+  send_command (argc, argv);
+
+  return (0);
+}
+
+
+void usage (char *name)
+{
+  puts ("Usage:\n======\n");
+  printf ("\t%s -e [ENVVAR]\n", name);
+  puts("\t\tExecute the command given in the Linux Environment variable\n");
+  puts("\t\t\"ENVVAR\". If not given, use the argument to the -E flag\n");
+  puts("\t\tof DOSEMU\n");
+  printf ("\t%s command [arg1 ...]\n", name);
+  puts("\t\tExecute the linux command with the arguments given.\n");
+
+  exit(-1);
+}
+
+send_command(int argc, char **argv)
+{
     static char command_line[256] = "";
     struct REGPACK preg;
 
@@ -20,10 +74,112 @@
 
     printf("Effective commandline: %s\n", command_line);
 
-    preg.r_ax = 0xfe;
-    preg.r_dx = &command_line;
+    preg.r_ax = 0x50;
+    preg.r_dx = (unsigned int) &command_line;
     preg.r_es = _DS;
     intr(0xe6, &preg);
 
     return(0);
 }
+
+
+int check_for_DOSEMU()
+{
+    struct REGPACK preg;
+
+    preg.r_ax = 0x00;
+    intr(0xe6, &preg);
+
+    if (preg.r_ax == 0xAA55) {
+      /* In DOSEMU - MAJOR number in BX */
+      return (preg.r_bx);
+    } else {
+      /* NOT in DOSEMU */
+      return (0);
+    }
+}
+
+void do_execute_dos (int argc, char **argv)
+{
+  char data[256];
+  struct REGPACK preg;
+
+  if (argc == 0) {
+    data[0] = '\0';
+    preg.r_ax = 0x51;
+  } else {
+    strcpy (data, argv[0]);
+    preg.r_ax = 0x52;
+  }
+
+  /* Store the string address in the registers */
+  preg.r_dx = (unsigned int) &data;
+  preg.r_es = _DS;
+  
+  intr(0xe6, &preg);
+
+  if (! preg.r_ax) {
+    /* SUCCESFUL */
+    printf ("About to Execute : %s\n", data);
+
+#ifdef GIBBER
+	execvp (data, argv);   /* Search path - and replace ourselves ... */
+
+    /* - unsuccesful exec ... */
+    puts ("EXEC failed.\n");
+#endif /* GIBBER */
+
+	if (system (data)) {
+		/* SYSTEM failed ... */
+		fprintf (stderr, "SYSTEM failed ....(%d)", errno);
+		exit (-1);
+	}
+
+	exit (0);
+  } else {
+    /* UNSUCESSFUL */
+    puts ("FAILED to get DATA from DOSEMU.\n");
+
+    exit (-1);
+  }
+
+}
+
+void do_set_dosenv (int argc, char **argv)
+{
+  struct REGPACK preg;
+
+  char data[256];
+
+  puts ("This option (-s, set DOS environment) is not available at the moment.\n");
+  puts ("Please try again later. Whilst you are waiting, please help yourself\n");
+  puts ("to the Lemon scented napkins.\n");
+
+  if (argc == 0) {
+	data[0] = '\0';
+  } else {
+    strcpy (data, argv[0]);
+  }
+
+  preg.r_ax = 0x52;
+
+  /* Store the string address in the registers */
+  preg.r_dx = (unsigned int) &data;
+  preg.r_es = _DS;
+  
+  intr(0xe6, &preg);
+
+  if (! preg.r_ax) {
+    /* SUCCESFUL */
+    puts ("In the meantime, the environment variable would have been set to :\n");
+    puts (data);
+
+  } else {
+    /* UNSUCCESFUL */
+    printf ("Anyway, the lookup failed ...(%d)\n", _AX);
+    
+  }
+  exit (-1);
+}
+
+
diff -u --recursive --new-file dosemu0.53pl47/data.c dosemu0.53pl48/data.c
--- dosemu0.53pl47/data.c	Sat Feb 25 19:48:56 1995
+++ dosemu0.53pl48/data.c	Tue Mar  7 21:22:50 1995
@@ -16,6 +16,7 @@
 #include "video.h"
 #include "mouse.h"
 #include "bios.h"
-#include "dpmi/dpmi.h"
+#include "dpmi.h"
 #include "shared.h"
-#include "timer/pic.h"
+#include "pic.h"
+#include "disks.h"
diff -u --recursive --new-file dosemu0.53pl47/dos2linux/dos2linux.c dosemu0.53pl48/dos2linux/dos2linux.c
--- dosemu0.53pl47/dos2linux/dos2linux.c
+++ dosemu0.53pl48/dos2linux/dos2linux.c	Tue Mar  7 18:35:47 1995
@@ -0,0 +1,232 @@
+/*
+ * 
+ * DANG_BEGIN_MODULE
+ *
+ * This file contains a simple system for passing information through to
+ * DOSEMU from the Linux side. It does not allow dynamic message passing,
+ * but it intended to provide useful information for the DOS user.
+ * 
+ * As such, the current set of implemented commands are :
+ * GET_USER_ENVVAR and GET_COMMAND
+ *
+ * These are made available to the DOSEMU by using the DOS_HELPER interrupt
+ * (Currently 0xE6) and writing a string into a location passed to this 
+ * interrupt handler using the registers. In the case of GET_USER_ENVVAR the
+ * string also contains the name of the environment variable to interrogate.
+ * (The string is overwritten with the reply).
+ *
+ * DANG_END_MODULE
+ *
+ * DANG_BEGIN_CHANGELOG
+ * DANG_END_CHANGELOG
+ */
+
+/* JAMES - Can you edit the CHANGELOG into place for me please ???!! 8-) */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+
+/* #include "dos2linux.h" */
+#include "../include/emu.h"
+
+#define GET_USER_ENVVAR      0x52
+#define GET_USER_COMMAND     0x51
+#define EXEC_USER_COMMAND    0x50
+
+#define MAX_DOS_COMMAND_LEN  256
+
+char misc_dos_command[MAX_DOS_COMMAND_LEN + 1];
+
+int misc_e6_envvar (char *str)
+{
+  char *tmp;
+
+  g_printf ("Environment Variable Check : %s", str);
+
+  tmp = getenv (str);
+
+  if (tmp == NULL)
+  {
+    str[0] = '\0';
+
+    g_printf (" is undefined\n");
+
+    return 1;
+  } else {
+    strcpy (str, tmp);
+
+    g_printf (" is %s\n", str);
+
+    return 0;
+  }
+
+  /* doesn't get this far */
+}
+
+
+int misc_e6_commandline (char *str)
+{
+
+  g_printf ("Command Line Check : ");
+
+  if (misc_dos_command == NULL)
+  {
+    str[0] = '\0';
+
+    g_printf ("%s\n", str);
+
+    return 1;
+  } else {
+    strcpy (str, misc_dos_command);
+
+    g_printf ("%s\n", str);
+
+    return 0;
+  }
+
+  /* doesn't get this far */
+}
+
+
+void misc_e6_store_command (char *str)
+{
+  strcpy (misc_dos_command, str);
+
+  g_printf ("Storing Command : %s\n", misc_dos_command);
+}
+
+
+#ifdef FORK_DEBUG
+#warning USING FORK DEBUG
+/* system to debug through forks...
+ * If used, setenv FORKDEBUG to stop child on fork call
+ */
+static int fork_debug(void)
+{
+	int retval;
+
+	retval = fork();
+
+	if(retval == 0) {
+		/* child -- maybe stop */
+		if(getenv("FORKDEBUG")) {
+			printf("stopping %d\n", getpid());
+			raise(SIGSTOP);
+		}
+	}
+	return retval;
+}
+#define fork	fork_debug
+#endif
+
+
+/*
+ * 2/9/1995, Erik Mouw (j.a.k.mouw@et.tudelft.nl):
+ *
+ * DANG_BEGIN_FUNCTION run_unix_command
+ *
+ * arguments: string with command to execute
+ *
+ * returns: nothing
+ *
+ * description:
+ *  Runs a command and prints the (stdout) output on the dosemu screen.
+ *
+ * DANG_END_FUNCTION
+ *
+ *
+ * This function forks a child process (don't worry, it doesn't take 
+ * much memory, read the fork manpage) and creates a pipe between the 
+ * parent and the child. The child redirects stdout to the write side 
+ * of the pipe and executes the command, the parents reads the read 
+ * side of the pipe and prints the command output on the dosemu screen. 
+ * system() is used to execute the command because this function uses a 
+ * shell (/bin/sh -c command), so nice things like this work: 
+ *
+ * C:\>unix ls -CF /usr/src/dosemu/video/*.[ch]
+ *
+ * Even output redirection works, but you have to quote the command in 
+ * dosemu:
+ *
+ * C:\>unix "ps aux | grep dos > /msdos/c/unixcmd.txt"
+ *
+ * DOS output redirection doesn't work, p_dos_str() uses direct video 
+ * memory access (I think).
+ *
+ * Be prepared to kill the child from a telnet session or a terminal 
+ * on /dev/ttyS? when you start an interactive command!
+ *
+ */
+void run_unix_command(char *buffer)
+{
+      /* DANG_FIXME Calls to "system" are unsafe when setuid .... - AM */
+
+#ifdef SIMPLE_FORK
+	/* unix command is in a null terminate buffer pointed to by ES:DX. */
+      system(buffer);
+
+#else
+    int p[2];
+    int pid, status, retval;
+    char buf;
+    
+    /* create a pipe */
+    if(pipe(p)!=0)
+    {
+        g_printf("run_unix_command(): pipe() failed\n");
+        return;
+    }
+    
+    /* fork child */
+    pid=fork();
+    if(pid==-1) /* failed */
+    {
+        g_printf("run_unix_command(): fork() failed\n");
+        return;
+    }
+    else if(pid==0) /* child */
+    {
+        close(p[0]);		/* close read side of the pipe */
+        close(1);		/* close stdout */
+        if(dup(p[1])!=1)	/* copy write side of the pipe to stdout */
+        {
+            /* hmm, I wonder if the next line works ok... */
+            g_printf("run_unix_command() (child): dup() failed\n");
+            _exit(-1);
+        }
+            
+        retval=system(buffer);	/* execute command */
+        close(p[1]);		/* close write side of the pipe */
+        _exit(retval);
+    }
+    else /* parent */
+    {
+        close(p[1]);		/* close write side of the pipe */
+        
+        /* read bytes until an error occurs */
+        /* no big buffer here, because speed is not important */
+        /* if speed *is* important, switch to another virtual console! */
+        while(read(p[0], &buf, 1)==1)
+        {
+            p_dos_str("%c", buf);	/* print character */
+        }
+        
+        /* kill the child (to be sure (s)he (?) is really dead) */
+        if(kill(pid, SIGTERM)!=0)
+            kill(pid, SIGKILL);
+            
+        close(p[0]);		/* close read side of the pipe */
+        waitpid(pid, &status, WUNTRACED);
+        /* print child exitcode. not perfect */
+        g_printf("run_unix_command() (parent): child exit code: %i\n",
+            WEXITSTATUS(&status));
+    }
+#endif
+}
diff -u --recursive --new-file dosemu0.53pl47/dos2linux/dos2linux.h dosemu0.53pl48/dos2linux/dos2linux.h
--- dosemu0.53pl47/dos2linux/dos2linux.h
+++ dosemu0.53pl48/dos2linux/dos2linux.h	Tue Mar  7 18:34:14 1995
@@ -0,0 +1,17 @@
+/* dos2linux.h
+ * 
+ * Function prototypes for the DOSEMU/LINUX interface
+ *
+ */
+
+#ifndef DOS2LINUX_H
+#define DOS2LINUX_H
+
+extern int misc_e6_envvar (char *str);
+
+extern int misc_e6_commandline (char *str);
+extern void misc_e6_store_command (char *str);
+
+extern void run_unix_command (char *buffer);
+
+#endif /* DOS2LINUX_H */
diff -u --recursive --new-file dosemu0.53pl47/dosemu/disks.c dosemu0.53pl48/dosemu/disks.c
--- dosemu0.53pl47/dosemu/disks.c	Sat Jan 14 11:29:17 1995
+++ dosemu0.53pl48/dosemu/disks.c	Tue Mar  7 21:23:46 1995
@@ -24,8 +24,6 @@
 #include "emu.h"
 #include "disks.h"
 
-extern config_t config;
-extern int fatalerr;
 
 #define FDISKS config.fdisks
 #define HDISKS config.hdisks
@@ -45,7 +43,18 @@
   ioctl(dp->fdesc, FDFLUSH, 0)
 #endif
 
-struct disk_fptr disk_fptrs[NUM_DTYPES] =
+/* NOTE: the "header" element in the structure above can (and will) be
+ * negative. This facilitates treating partitions as disks (i.e. using
+ * /dev/hda1 with a simulated partition table) by adjusting out the
+ * simulated partition table offset...
+ */
+
+struct disk_fptr {
+  void (*autosense) (struct disk *);
+  void (*setup) (struct disk *);
+};
+
+static struct disk_fptr disk_fptrs[NUM_DTYPES] =
 {
   {image_auto, image_setup},
   {hdisk_auto, hdisk_setup},
@@ -53,28 +62,6 @@
   {partition_auto, partition_setup}
 };
 
-/*
- * Array of disk structures for floppies...
- */
-struct disk disktab[MAX_FDISKS];
-
-/*
- * Array of disk structures for hard disks...
- *
- * Can be whole hard disks, dos extended partitions (containing one or
- * more partitions) or their images (files)
- */
-
-struct disk hdisktab[MAX_HDISKS];
-
-/*
- * Special bootdisk which can be temporarily swapped out for drive A,
- * during the boot process.  The idea is to boot off the bootdisk, and
- * then have the autoexec.bat swap out the boot disk for the "real"
- * drive A.
- */
-struct disk bootdisk;
-int use_bootdisk = 0;
 
 /* read_sectors
  *
diff -u --recursive --new-file dosemu0.53pl47/dosemu/dosio.c dosemu0.53pl48/dosemu/dosio.c
--- dosemu0.53pl47/dosemu/dosio.c	Sat Feb 25 17:53:11 1995
+++ dosemu0.53pl48/dosemu/dosio.c	Sun Mar  5 20:07:46 1995
@@ -276,7 +276,6 @@
 
 extern void DOSEMUMouseEvents(void);
 
-inline void scan_to_buffer(void);
 extern void xms_init(void);
 extern void video_memory_setup(void);
 extern void dump_kbuffer(void);
diff -u --recursive --new-file dosemu0.53pl47/dosemu/int.c dosemu0.53pl48/dosemu/int.c
--- dosemu0.53pl47/dosemu/int.c	Wed Mar  1 19:16:48 1995
+++ dosemu0.53pl48/dosemu/int.c	Tue Mar  7 18:34:14 1995
@@ -18,6 +18,8 @@
 #include "bios.h"
 #include "xms.h"
 #include "int.h"
+#include "../dos2linux/dos2linux.h"
+
 #ifdef USING_NET
 #include "ipx.h"
 #endif
@@ -26,6 +28,8 @@
 #include "../dpmi/dpmi.h"
 #endif
 
+extern void scan_to_buffer(void);
+
 /*
    This flag will be set when doing video routines so that special
    access can be given
@@ -66,132 +70,6 @@
     run_int(i);
 }
 
-#ifdef FORK_DEBUG
-#warning USING FORK DEBUG
-/* system to debug through forks...
- * If used, setenv FORKDEBUG to stop child on fork call
- */
-static int fork_debug(void)
-{
-	int retval;
-
-	retval = fork();
-
-	if(retval == 0) {
-		/* child -- maybe stop */
-		if(getenv("FORKDEBUG")) {
-			printf("stopping %d\n", getpid());
-			raise(SIGSTOP);
-		}
-	}
-	return retval;
-}
-#define fork	fork_debug
-#endif
-
-
-/*
- * 2/9/1995, Erik Mouw (j.a.k.mouw@et.tudelft.nl):
- *
- * DANG_BEGIN_FUNCTION run_unix_command
- *
- * arguments: string with command to execute
- *
- * returns: nothing
- *
- * description:
- *  Runs a command and prints the (stdout) output on the dosemu screen.
- *
- * DANG_END_FUNCTION
- *
- *
- * This function forks a child process (don't worry, it doesn't take 
- * much memory, read the fork manpage) and creates a pipe between the 
- * parent and the child. The child redirects stdout to the write side 
- * of the pipe and executes the command, the parents reads the read 
- * side of the pipe and prints the command output on the dosemu screen. 
- * system() is used to execute the command because this function uses a 
- * shell (/bin/sh -c command), so nice things like this work: 
- *
- * C:\>unix ls -CF /usr/src/dosemu/video/*.[ch]
- *
- * Even output redirection works, but you have to quote the command in 
- * dosemu:
- *
- * C:\>unix "ps aux | grep dos > /msdos/c/unixcmd.txt"
- *
- * DOS output redirection doesn't work, p_dos_str() uses direct video 
- * memory access (I think).
- *
- * Be prepared to kill the child from a telnet session or a terminal 
- * on /dev/ttyS? when you start an interactive command!
- *
- */
-static void run_unix_command(const char *buffer)
-{
-#ifdef SIMPLE_FORK
-	/* unix command is in a null terminate buffer pointed to by ES:DX. */
-      system(buffer);
-
-#else
-    int p[2];
-    int pid, status, retval;
-    char buf;
-    
-    /* create a pipe */
-    if(pipe(p)!=0)
-    {
-        g_printf("run_unix_command(): pipe() failed\n");
-        return;
-    }
-    
-    /* fork child */
-    pid=fork();
-    if(pid==-1) /* failed */
-    {
-        g_printf("run_unix_command(): fork() failed\n");
-        return;
-    }
-    else if(pid==0) /* child */
-    {
-        close(p[0]);		/* close read side of the pipe */
-        close(1);		/* close stdout */
-        if(dup(p[1])!=1)	/* copy write side of the pipe to stdout */
-        {
-            /* hmm, I wonder if the next line works ok... */
-            g_printf("run_unix_command() (child): dup() failed\n");
-            _exit(-1);
-        }
-            
-        retval=system(buffer);	/* execute command */
-        close(p[1]);		/* close write side of the pipe */
-        _exit(retval);
-    }
-    else /* parent */
-    {
-        close(p[1]);		/* close write side of the pipe */
-        
-        /* read bytes until an error occurs */
-        /* no big buffer here, because speed is not important */
-        /* if speed *is* important, switch to another virtual console! */
-        while(read(p[0], &buf, 1)==1)
-        {
-            p_dos_str("%c", buf);	/* print character */
-        }
-        
-        /* kill the child (to be sure (s)he (?) is really dead) */
-        if(kill(pid, SIGTERM)!=0)
-            kill(pid, SIGKILL);
-            
-        close(p[0]);		/* close read side of the pipe */
-        waitpid(pid, &status, WUNTRACED);
-        /* print child exitcode. not perfect */
-        g_printf("run_unix_command() (parent): child exit code: %i\n",
-            WEXITSTATUS(&status));
-    }
-#endif
-}
-
 /* returns 1 if dos_helper() handles it, 0 otherwise */
 static int dos_helper(void)
 {
@@ -279,8 +157,7 @@
 
   case 6:			/* Do inline int09 insert_into_keybuffer() */
     k_printf("Doing INT9 insert_into_keybuffer() bx=0x%04x\n", LWORD(ebx));
-    set_keyboard_bios();
-    insert_into_keybuffer();
+    scan_to_buffer();
     break;
 
   case 8:
@@ -375,6 +252,24 @@
       break;
     }
 
+  case 0x50:
+    /* run the unix command in es:dx (a null terminated buffer) */
+    g_printf("Running Unix Command\n");
+    run_unix_command(SEG_ADR((char *), es, dx));
+    break;   
+
+  case 0x51:
+    /* Get DOS command from UNIX in es:dx (a null terminated buffer) */
+    g_printf("Locating DOS Command\n");
+    LWORD(eax) = misc_e6_commandline(SEG_ADR((char *), es, dx));
+    break;   
+
+  case 0x52:
+    /* Interrogate the UNIX environment in es:dx (a null terminated buffer) */
+    g_printf("Interrogating UNIX Environment\n");
+    LWORD(eax) = misc_e6_envvar(SEG_ADR((char *), es, dx));
+    break;   
+
 #ifdef IPX
   case 0x7a:
     if (config.ipxsup) {
@@ -384,12 +279,6 @@
     break;
 #endif
 
-  case 0xfe:
-    /* run the unix command in es:dx (a null terminated buffer) */
-    g_printf("Running Unix Command\n");
-    run_unix_command(SEG_ADR((char *), es, dx));
-    break;   
-
   case 0xff:
     if (LWORD(eax) == 0xffff) {
       /* terminate code is in bx */
@@ -399,6 +288,28 @@
     }
     break;
 
+/*
+ * DANG_BEGIN_REMARK
+ * The Helper Interrupt uses the following groups:
+ * 
+ * 0x00      - Check for DOSEMU
+ * 0x01-0x11 - Initialisation functions & Debugging
+ * 0x12      - Set hogthreshold (aka garrot?)
+ * 0x20      - MFS functions
+ * 0x21-0x22 - EMS functions
+ * 0x28      - Garrot Functions for use with the mouse
+ * 0x30      - Whether to use the BOOTDISK predicate
+ * 0x33      - Mouse Functions
+ * 0x40      - CD-ROM functions
+ * 0x50-0x52 - DOSEMU/Linux communications
+ * 0x7a      - IPX functions
+ * 0xff      - Terminate DOSEMU
+ *
+ * There are (as yet) no guidelines on choosing areas for new functions.
+ * DANG_END_REMARK
+ */
+
+
   default:
     error("ERROR: bad dos helper function: AX=0x%04x\n", LWORD(eax));
     return 0;
@@ -1278,7 +1189,7 @@
   if (current_interrupt == 0x09) {
     k_printf("Int9 set\n");
     /* If another program does a keybaord read on port 0x60, we'll know */
-    parent_nextscan();
+    read_next_scancode_from_queue();
   }
 
   /* call user startup function...don't run interrupt if returns -1 */
diff -u --recursive --new-file dosemu0.53pl47/dosemu/serial.c dosemu0.53pl48/dosemu/serial.c
--- dosemu0.53pl47/dosemu/serial.c	Sat Feb 25 18:38:01 1995
+++ dosemu0.53pl48/dosemu/serial.c	Tue Mar  7 21:24:08 1995
@@ -147,17 +147,16 @@
 #include "serial.h"
 #include "mouse.h"
 #if NEW_PIC==2   /*  add includes for NEW_PIC */
-#include "../timer/bitops.h"
-#include "../timer/pic.h"
+#include "bitops.h"
+#include "pic.h"
 #else
 extern void queue_hard_int(int i, void (*), void (*));
 #endif
-extern config_t config;
 
 serial_t com[MAX_SER];
 #if NEW_PIC==2
-int tx_timer[MAX_SER];
-int br_divisor[MAX_SER];
+static int tx_timer[MAX_SER];
+static int br_divisor[MAX_SER];
 #endif
 /* The following are positive constants that adjust the soonness of the next
  * receive or transmit interrupt in FIFO mode.  These are a little
@@ -171,6 +170,7 @@
  * DELTA_BIT   returns 'outbit' if 'inbit' changed between bytes 'old' and 'new'
  * TRAIL_EDGE  returns 'outbit' if 'inbit' is on in 'old' and off in 'new'
  */
+#if 0
 #define CONVERT_BIT(testbyte,inbit,outbit) ((testbyte & inbit) ? outbit : 0)
 #define DELTA_BIT(old,new,inbit,outbit) \
                  ((old ^ new) & inbit) ? outbit : 0
@@ -177,12 +177,35 @@
 #define TRAIL_EDGE(old,new,inbit,outbit) \
                   ((old & inbit) > (new & inbit)) ? outbit : 0
 
-inline int get_msr(int num);
-inline void transmit_engine(int num);
-inline void receive_engine(int num);
-inline void interrupt_engine(int num);
+#else
+static inline int CONVERT_BIT(int testbyte, int inbit, int outbit)
+{
+	if(testbyte & inbit) 
+		return outbit;
+	return 0;
+}
+
+static inline int DELTA_BIT(int old, int new, int inbit, int output)
+{
+	if((old ^ new) & inbit) 	
+		return output;
+	else	return 0;
+}
+
+static inline int TRAIL_EDGE(int old, int new, int inbit,  int outbit)
+{
+	if((old & inbit) > (new  & inbit)) 
+		return outbit;
+	else	return 0;
+}
+#endif
+	
+int get_msr(int num);
+void transmit_engine(int num);
+void receive_engine(int num);
+void interrupt_engine(int num);
 #if NEW_PIC==2
-void pic_serial_run();
+void pic_serial_run(void);
 #endif
 
 /*************************************************************************/
@@ -192,7 +215,7 @@
 /* This function flushes the internal unix receive buffer,
  * up to 10 KB at a time.  [num = port]
  */
-inline void
+static void
 buffer_dump(int num)
 {
   u_char bytes[1024];
@@ -206,7 +229,7 @@
 /* This function checks for newly received data and fills the UART
  * FIFO (16550 mode) or receive register (16450 mode).  [num = port]
  */
-inline void
+static void
 uart_fill(int num)
 {
   static u_char bytes[RX_FIFO_SIZE];
@@ -262,7 +285,7 @@
  * done on initialization, and when changing from 16450 to 16550 mode, and
  * vice versa.  [num = port, fifo = flags to indicate which fifos to clear]
  */ 
-inline void 
+static void 
 uart_clear_fifo(int num, int fifo)
 {
   /* Should clearing a UART cause a THRE interrupt if it's enabled? XXXXXX */
@@ -303,11 +326,11 @@
  * stored in the Line Control Register (com[].LCR) and the Baudrate
  * Divisor Latch Registers (com[].dlm and com[].dll)     [num = port]
  */
-void
+static void
 ser_termios(int num)
 {
-  static speed_t baud;
-  static int rounddiv;
+  speed_t baud;
+  int rounddiv;
 
   /* The following is the same as (com[num].dlm * 256) + com[num].dll */
 #define DIVISOR ((com[num].dlm<<8)|com[num].dll)
@@ -444,7 +467,7 @@
 /* This function opens the serial port for DOSEMU.  Normally called only
  * by do_ser_init below.   [num = port, return = file descriptor]
  */
-int
+static int
 ser_open(int num)
 {
   s_printf("SER%d: Running ser_open, fd=%d\n",num, com[num].fd);
@@ -463,7 +486,7 @@
 /* This function closes the serial port for DOSEMU.  Normally called 
  * only by do_ser_init below.   [num = port, return = file error code]
  */
-int
+static int
 ser_close(int num)
 {
   static int i;
@@ -486,7 +509,7 @@
  * and the emulated UART's initialization state, and open/initialize the 
  * serial line.   [num = port]
  */
-void
+static void
 do_ser_init(int num)
 {
   int data = 0;
@@ -694,7 +717,7 @@
  * (Also, this silly function name needs to be changed soon.)
  */
 void
-child_close_mouse()
+child_close_mouse(void)
 {
   static u_char i, rtrn;
   if ( !config.usesX ){
@@ -721,7 +744,7 @@
  * (Also, this silly function name needs to be changed soon.)
  */
 void
-child_open_mouse()
+child_open_mouse(void)
 {
   static u_char i;
   if ( ! config.usesX ){
@@ -749,7 +772,7 @@
  * actual reads from the serial line) or loopback code.  This function
  * usually runs through the do_serial_in routine.    [num = port]
  */
-inline int
+static int
 get_rx(int num)
 {
   static int val;
@@ -814,7 +837,7 @@
  * before executing the Received Data Ready ISR (Interrupt Service Routine).
  * [intnum = software interrupt number]
  */
-int
+static int
 beg_rxint(int intnum)
 {
   static u_char num;
@@ -837,7 +860,7 @@
 /* This function is the post-interrupt initialization called right after
  * the Received Data Ready ISR.   [intnum = software interrupt number]
  */ 
-int
+static int
 end_rxint(int intnum)
 {
   static u_char num;
@@ -863,13 +886,14 @@
  * One of the bit is actually a trailing edge bit (for the ring indicator)
  * instead of a delta bit.    [oldmsr = old value, newmsr = new value]
  */
-inline int
+static inline int
 msr_delta(int oldmsr, int newmsr)
 {
   /* There were some errors (compiler bug?  Formula too complex?) when I tried
   ** to put all four DELTA_BIT & TRAIL_EDGE in the same variable assignment.
   */
-  static int delta;
+  int delta;
+
   delta  = DELTA_BIT(oldmsr, newmsr, UART_MSR_CTS, UART_MSR_DCTS);
   delta |= DELTA_BIT(oldmsr, newmsr, UART_MSR_DSR, UART_MSR_DDSR);
   delta |= TRAIL_EDGE(oldmsr, newmsr, UART_MSR_RI, UART_MSR_TERI);
@@ -882,10 +906,11 @@
  * and does the expected UART operation whenever the MSR is read.
  * [num = port]
  */
-inline int
+static int
 get_msr(int num)
 {
-  static int val;
+  int val;
+
   val = com[num].MSR;				/* Save old MSR value */
   com[num].MSR &= UART_MSR_STAT; 		/* Clear delta bits */
   com[num].int_type &= ~MS_INTR;		/* No MSI needed anymore */
@@ -901,10 +926,11 @@
 /* This function is the pre-interrupt initialization called right before
  * the Modem Status ISR.   [intnum = software interrupt number]
  */ 
-int
+static int
 beg_msi(int intnum)
 {
-  static u_char num;
+  u_char num;
+
   num = irq_source_num[intnum];		/* port number that caused int */
   com[num].int_type &= ~MS_INTR;	/* Prevent further MSI occurances */
   com[num].IIR = (com[num].IIR & UART_IIR_FIFO) | UART_IIR_MSI;
@@ -918,10 +944,11 @@
 /* This function is the post-interrupt initialization called right after
  * the Modem Status ISR.   [intnum = software interrupt number]
  */ 
-int
+static int
 end_msi(int intnum)
 {
-  static u_char num;
+  u_char num;
+
   num = irq_source_num[intnum];		/* Port that had caused int */
   com[num].int_type &= ~MS_INTR;	/* MSI interrupt finished. */
   #if SUPER_DBG > 1
@@ -941,10 +968,11 @@
  * and does the expected UART operation whenever the LSR is read.
  * [num = port]
  */
-inline int
+static int
 get_lsr(int num)
 {
-  static int val;
+  int val;
+
   val = com[num].LSR;			/* Save old LSR value */
   com[num].int_type &= ~LS_INTR;	/* Clear line stat int flag */
   com[num].LSR &= ~UART_LSR_ERR;	/* Clear error bits */
@@ -960,10 +988,11 @@
 /* This function is the pre-interrupt initialization called right before
  * the Receiver Line Status ISR.   [intnum = software interrupt number]
  */ 
-int
+static int
 beg_lsi(int intnum)
 {
-  static u_char num;
+  u_char num;
+
   num = irq_source_num[intnum];		/* Port that caused interrupt */
   com[num].int_type &= ~LS_INTR;	/* No more interrupt needed */
   com[num].IIR = (com[num].IIR & UART_IIR_FIFO) | UART_IIR_RLSI;
@@ -977,10 +1006,11 @@
 /* This function is the post-interrupt initialization called right after
  * the Receiver Line Status ISR.   [intnum = software interrupt number]
  */ 
-int
+static int
 end_lsi(int intnum)
 {
-  static u_char num;
+  u_char num;
+
   num = irq_source_num[intnum];		/* Port that caused interrupt */
   #if SUPER_DBG > 1
     s_printf("SER%d: ---END---Line Status Interrupt\n",num);
@@ -1001,7 +1031,7 @@
  * transmit FIFO. (or receive fifo if in Loopback test mode)
  * [num = port, val = character to transmit]
  */
-inline void
+static void
 put_tx(int num, int val)
 {
   static int rtrn;
@@ -1105,10 +1135,11 @@
 /* This function is the pre-interrupt initialization called right before
  * the Transmit Holding Reg Empty ISR.  [intnum = software interrupt number]
  */ 
-int
+static int
 beg_txint(int intnum)
 {                  
-  static u_char num;
+  u_char num;
+
   num = irq_source_num[intnum];		/* Port that caused interrupt */
   com[num].int_type &= ~TX_INTR;	/* No more interrupt needed */
   com[num].tx_timeout = 0;		/* Reset xmit counter */
@@ -1124,10 +1155,11 @@
 /* This function is the post-interrupt initialization called right after
  * the Transmit Holding Reg Empty ISR.  [intnum = software interrupt number]
  */ 
-int
+static int
 end_txint(int intnum)
 {
-  static u_char num;
+  u_char num;
+
   num = irq_source_num[intnum];		/* Port that caused interrupt */
   #if SUPER_DBG > 1
     s_printf("SER%d: ---END---Transmit Interrupt\n",num);
@@ -1147,7 +1179,7 @@
 /* This function handles writes to the FCR (FIFO Control Register).
  * [num = port, val = new value to write to FCR]
  */
-inline void
+static void
 put_fcr(int num, int val)
 {
   val &= 0xcf;				/* bits 4,5 are reserved. */
@@ -1203,7 +1235,7 @@
 /* This function handles writes to the LCR (Line Control Register).
  * [num = port, val = new value to write to LCR]
  */
-inline void
+static void
 put_lcr(int num, int val)
 {
   com[num].LCR = val;			/* Set new LCR value */
@@ -1225,7 +1257,7 @@
 /* This function handles writes to the MCR (Modem Control Register).
  * [num = port, val = new value to write to MCR]
  */
-inline void
+static void
 put_mcr(int num, int val)
 {
   static int newmsr, delta;
@@ -1289,7 +1321,7 @@
 /* This function handles writes to the LSR (Line Status Register).
  * [num = port, val = new value to write to LSR]
  */
-inline void
+static void
 put_lsr(int num, int val) 
 {
   com[num].LSR = val & 0x1F;			/* Bits 6 to 8 are ignored */
@@ -1319,7 +1351,7 @@
 /* This function handles writes to the MSR (Modem Status Register).
  * [num = port, val = new value to write to MSR]
  */
-inline void
+static inline void
 put_msr(int num, int val)
 {
   com[num].MSR = (com[num].MSR & UART_MSR_STAT) | (val & UART_MSR_DELTA);
@@ -1341,7 +1373,7 @@
  * the base port (ie 0x3F8) to the base port plus seven (ie 0x3FF).
  * [num = abritary port number for serial line, address = I/O port address]
  */
-inline int
+int
 do_serial_in(int num, int address)
 {
   static int val;
@@ -1443,7 +1475,7 @@
  * [num = abritary port number for serial line, address = I/O port address,
  * val = value to write to I/O port address]
  */
-inline int
+int
 do_serial_out(int num, int address, int val)
 {
   switch (address - com[num].base_port) {
@@ -1646,7 +1678,7 @@
  * and checking if it's time to generate a hardware interrupt (RDI).
  * [num = port]
  */
-inline void
+static void
 receive_engine(int num)		/* Internal 16550 Receive emulation */ 
 {
   /* Occasional stack overflows occured when "uart_fill" done inside intr */
@@ -1681,8 +1713,8 @@
  * 10 bits/character, this will be br_divisor times chars/second.
  * If I ever get ambitious, I'll get this to adapt to other character sizes.
  */
-inline void
-age_transmit_queues()
+static void
+age_transmit_queues(void)
 {
   s_printf("SER: ageing serial transmit queues\n");
   s_printf("SER: pic_irr=%x, pic_isr=%x\n",pic_irr, pic_isr);
@@ -1724,7 +1756,7 @@
  * of the XMIT FIFO/THR register, and checking if it's time to generate
  * a hardware interrupt (THRI).    [num = port]
  */
-inline void
+static void
 transmit_engine(int num)      /* Internal 16550 Transmission emulation */
 {
   static int rtrn;
@@ -1783,11 +1815,13 @@
  * and updating the MSR, and checking if it's time to generate a hardware
  * interrupt (MSI).    [num = port]
  */
-inline void
+static void
 modstat_engine(int num)		/* Internal Modem Status processing */ 
 {
+	/* why static? */
   static int control;
-  static int newmsr, delta;
+  int newmsr, delta;
+
   control = 0;
 
   if (!(com[num].MCR & UART_MCR_LOOP)) {	/* Not in Loopback mode */
@@ -1836,7 +1870,7 @@
  * especially for applications that are extremely fussy about interrupt 
  * occuring at the right time.    [num = port]
  */
-inline void
+static void
 interrupt_engine(int num)
 {
 u_char tmp;
@@ -1956,7 +1990,7 @@
  * especially for applications that are extremely fussy about interrupt 
  * occuring at the right time.    [num = port]
  */
-inline void
+static void
 interrupt_engine(int num)
 {
   /* Quit if all interrupts disabled, DLAB high, interrupt pending, or */
@@ -2034,7 +2068,7 @@
  * for speed optimization purposes.  (In this function, and for the 
  * TIMEOUT_TX, TIMEOUT_RX values)
  */
-inline void
+void
 serial_run(void)	
 {
   static int i;
@@ -2068,6 +2102,3 @@
   }
   return;
 }
-#if NEW_PIC==0
-#undef NEW_PIC
-#endif
diff -u --recursive --new-file dosemu0.53pl47/dosemu/signal.c dosemu0.53pl48/dosemu/signal.c
--- dosemu0.53pl47/dosemu/signal.c	Sat Feb 25 17:53:19 1995
+++ dosemu0.53pl48/dosemu/signal.c	Tue Mar  7 19:53:51 1995
@@ -84,6 +84,7 @@
   SETSIG(SIGKILL, leavedos);
 #endif
   SETSIG(SIGQUIT, sigquit);
+  SETSIG(SIGWINCH, gettermcap); /* Adjust window sizes in DOS */
 /*
   SETSIG(SIGUNUSED, timint);
 */
@@ -162,7 +163,6 @@
   static volatile int running = 0;
   static volatile inalrm = 0;
   static int partials = 0;
-  static u_char timals = 0;
 #if VIDEO_CHECK_DIRTY
   static int update_pending = 0;
 #endif
@@ -173,7 +173,7 @@
      X_handle_events();
 #endif
 
-#if 0
+#if 1
 #ifdef USING_NET
   /* check for available packets on the packet driver interface */
   /* (timeout=0, so it immediately returns when none are available) */
@@ -258,26 +258,7 @@
     AESTimerTick();
 #endif
 
-  if (++timals == TIMER_DIVISOR) {
-    timals = 0;
-    /* update the Bios Data Area timer dword if interrupts enabled */
-/*    if (REG(eflags) & VIF)
-      timer_tick();*/
-    if (config.timers) {
-      h_printf("starting timer int 8...\n");
-#ifndef NEW_PIC
-      if (!do_hard_int(8))
-	h_printf("CAN'T DO TIMER INT 8...IF CLEAR\n");
-#else
-#if NEW_PIC==2
-      age_transmit_queues();
-#endif
-      pic_request(PIC_IRQ0);
-#endif
-    }
-    else
-      h_printf("NOT CONFIG.TIMERS\n");
-  }
+  timer_tick();
 
   if (not_use_sigio)
     io_select(fds_no_sigio);
@@ -311,7 +292,9 @@
 inline void SIGNAL_save( void (*signal_call)() ) {
   signal_queue[SIGNAL_tail].signal_handler=signal_call;
   SIGNAL_tail = (SIGNAL_tail + 1) % MAX_SIG_QUEUE_SIZE;
+#ifdef DPMI
   if (!in_dpmi)
+#endif
     REG(eflags) |= VIP;
 }
 
diff -u --recursive --new-file dosemu0.53pl47/dosemu/sigsegv.c dosemu0.53pl48/dosemu/sigsegv.c
--- dosemu0.53pl47/dosemu/sigsegv.c	Sat Feb 25 20:56:58 1995
+++ dosemu0.53pl48/dosemu/sigsegv.c	Tue Mar  7 21:23:46 1995
@@ -159,11 +159,11 @@
 #include "video.h"
 
 #ifdef NEW_PIC
-#include "../timer/pic.h"
+#include "pic.h"
 #endif
 
 #ifdef DPMI
-#include "../dpmi/dpmi.h"
+#include "dpmi.h"
 #endif
 
 #ifdef USING_NET
@@ -188,163 +188,6 @@
 extern int s3_8514_base;
 static u_short microsoft_port_check = 0;
 
-/* 
- * Copied adverbatim from Mach code, please be aware of their 
- * copyright in mfs.c
- */
-static int timer_interrupt_rate = 55;
-static int min_timer_milli_pause = 16;
-static int timer_milli_pause = 55;
-
-static int timer0_read_latch_value = 0;
-static int timer0_read_latch_value_orig = 0;
-static int timer0_latched_value = 0;
-static int timer0_new_value = 0;
-static boolean_t latched_counter_msb = FALSE;
-
-void update_timers(void);
-/* ??? */
-static u_long milliseconds_since_boot;
-
-#if 1
-static int do_40(in_out, val)
-	boolean_t in_out;
-	int val;
-{
-	int ret;
-
-	if (in_out) {  /* true => in, false => out */
-
-		update_timers();
-		if (timer0_latched_value == 0) {
-			timer0_latched_value = timer_interrupt_rate*850;
-		}
-		switch (timer0_read_latch_value) {
-			case 0x30:
-				ret = timer0_latched_value&0xf;
-				timer0_read_latch_value = 0x20;
-				break;
-			case 0x10:
-				ret = timer0_latched_value&0xf;
-				timer0_read_latch_value = 0x0;
-				break;
-			case 0x20:
-				ret = (timer0_latched_value&0xf0)>>8;
-				timer0_read_latch_value = 0x0;
-				timer0_latched_value = 0;
-				break;
-			case 0x0:
-				if (latched_counter_msb) {
-					ret = 
-					(milliseconds_since_boot >> 8) & 0xff;
-				} else {
-					ret = milliseconds_since_boot & 0xff;
-				}
-				latched_counter_msb = !latched_counter_msb;
-				break;
-
-		}
-		i_printf("PORT: do_40, in = 0x%x\n",ret);
-	} else {
-		switch (timer0_read_latch_value) {
-			case 0x0:
-			case 0x30:
-				timer0_new_value = val;
-				timer0_read_latch_value = 0x20;
-				break;
-			case 0x10:
-				timer0_new_value = val;
-				timer0_read_latch_value = 0x0;
-				break;
-			case 0x20:
-				timer0_new_value |= (val<<8);
-				timer0_read_latch_value = 0x0;
-				break;
-		}
-		i_printf("PORT: do_40, out = 0x%x\n",val);
-		if (timer0_read_latch_value == 0) {
-			timer0_read_latch_value=timer0_read_latch_value_orig;
-			if (timer0_new_value == 0) timer0_new_value = 64*1024;
-			timer_interrupt_rate = ((timer0_new_value)/1193);
-			if (timer_interrupt_rate < min_timer_milli_pause) {
-				int i;
-				if (timer_interrupt_rate == 0) 
-					timer_interrupt_rate = 1;
-				for (i = 1; i<=min_timer_milli_pause;i++) {
-				    if (i*timer_interrupt_rate >= 
-						min_timer_milli_pause){
-				    	timer_milli_pause = i*
-						timer_interrupt_rate;
-					break;
-				    }
-				}
-			} else {
-				timer_milli_pause = timer_interrupt_rate;
-			}
-			i_printf("timer_interrupt_rate = %d\n",
-					  timer_interrupt_rate);
-			i_printf("timer_milli_pause = %d\n",
-					  timer_milli_pause);
-		}
-	}
-	return(ret);
-}
-
-#endif
-#if 0
-/* return value of port -- what happens when output?  Stack trash? */
-static int do_42(in_out, val)
-	boolean_t in_out;
-	int val;
-{
-	int ret;
-	if (in_out) {  /* true => in, false => out */
-		ioperm(0x42,1,1);
-		ret = port_in(0x42);
-		ioperm(0x42,1,0);
-		i_printf( "PORT: do_42, in = 0x%x\n",ret);
-	} else {
-		ioperm(0x42,1,1);
-		port_out(val, 0x42);
-		ioperm(0x42,1,0);
-		i_printf( "PORT: do_42, out = 0x%x\n",val);
-	}
-	return(ret);
-}
-
-#endif
-
-static int do_43(boolean_t in_out, int val)
-{
-	int ret;
-	
-	if (in_out) {  /* true => in, false => out */
-		i_printf( "PORT: do_43, in = 0x%x\n",ret);
-	} else {
-		i_printf( "PORT: do_43, out = 0x%x\n",val);
-		switch(val>>6) {
-			case 0:
-				timer0_read_latch_value = (val&0x30);
-				timer0_read_latch_value_orig = (val&0x30);
-				if (timer0_read_latch_value == 0) {
-					latched_counter_msb = FALSE;
-				}
-				break;
-			case 2:
-#if 0
-				ioperm(0x43,1,1);
-				port_out(val, 0x43);
-				ioperm(0x43,1,0);
-#else
-				safe_port_out_byte(0x43, val);
-#endif
-				i_printf( "PORT: Really do_43\n");
-				break;
-		}
-	}
-	return(ret);
-}
-
 /*
  * DANG_BEGIN_FUNCTION inb(int port)
  *
@@ -452,7 +295,7 @@
     break;
 
 #define COUNTER 2
-#if 0 /*Nov-21-94*/
+#if 1 /*Nov-21-94*/
   case 0x40:
     r = do_40(1, 0);
     break;
@@ -799,37 +642,6 @@
   }
 
 }
-
-
-
-/* time of boot */
-static struct timeval initial_time;
-
-void initialize_timers(void)
-{
-
-	gettimeofday(&initial_time, NULL);
-}
-
-	
-/* not sure what adder does -- get time in relation to inital time and
- * convert to milliseocnds
- */
-static void update_timers(void) {
-  static unsigned long adder=0;
-  struct timeval tp;
-
-  gettimeofday(&tp, NULL);
-
-  milliseconds_since_boot = (tp.tv_sec - initial_time.tv_sec)*1000;
-  milliseconds_since_boot += (tp.tv_usec - initial_time.tv_usec)/1000;
-  milliseconds_since_boot += adder;
-
-  adder = (adder + 1) % 20;
-  i_printf("Timers updated: %x\n", milliseconds_since_boot);
-
-}
- 
 
 /*
  * DANG_BEGIN_FUNCTION vm86_GP_fault();
diff -u --recursive --new-file dosemu0.53pl47/dosemu/timers.c dosemu0.53pl48/dosemu/timers.c
--- dosemu0.53pl47/dosemu/timers.c	Sat Feb 25 18:37:51 1995
+++ dosemu0.53pl48/dosemu/timers.c	Tue Mar  7 18:19:29 1995
@@ -1,8 +1,25 @@
-#define TIMERS_C
-/* timers.c
- *     for dosemu 0.48+
- *     Robert Sanders, gt8134b@prism.gatech.edu
+/*
+ * DANG_BEGIN_MODULE
+ * 
+ * There is some old Mach code in here.  Please be aware of their copyright
+ * in mfs.c
+ * 
+ * This code will actually generate 18.2 interrupts/second.  It will even
+ * happily attempt to generate faster clocks, right up to the point where
+ * it chokes.  Since the absolute best case timing we can get out of Linux
+ * is 100Hz, figure that anything approaching or exceeding that isn't going
+ * to work well.  (The code will attempt to generate up to 10Khz interrupts
+ * per second at the moment.  Too bad that would probably overflow all
+ * internal queues really fast. :)
+ *
+ * Incidentally, this code almost works.  There seems to be some oddness
+ * reading values from port 0x40 which cause, for example, the delay(x)
+ * function in Borland C++ to take x or 2x msecs.  Or Norton's SI to return
+ * a variety of values.  Many kudos to the one who figures this one out or
+ * who finds me a timer chip reference online.
  *
+ * DANG_END_MODULE
+ *
  * $Date: 1995/02/25 22:37:51 $
  * $Source: /home/src/dosemu0.60/dosemu/RCS/timers.c,v $
  * $Revision: 2.4 $
@@ -75,31 +92,119 @@
 #include <linux/time.h>
 #include "emu.h"
 #include "timers.h"
+#include "int.h"
+#ifdef NEW_PIC
+#include "../timer/pic.h"
+#endif
+
+#define CLOCK_TICK_RATE   1193180     /* underlying clock rate in HZ */
+
+static int timer_interrupt_rate = 55;
 
-extern config_t config;
-extern int ignore_segv;
+static int timer0_read_latch_value = 0;
+static int timer0_read_latch_value_orig = 0;
+static int timer0_latched_value = 0;
+static int timer0_new_value = 0;
+static boolean_t latched_counter_msb = FALSE;
+static int timer0_cntr_latch = 0;
 
-void
-timer_tick(void)
+static u_long timer_latch0;           /* current timer port 0 latch value */
+static u_long timer_div;              /* used by timer int code */
+static struct timeval clock0;         /* start time of port 0 timer */
+static u_long timer_pops;             /* number of times the timer's popped */
+static u_long timer_value0;           /* current read timer port 0 value */
+
+/*
+ * DANG_BEGIN_FUNCTION set_timer_latch0
+ *
+ * description:
+ *  DOS programs latch values into port 0x40 to change the timer interrupt
+ *  rate.  This procedure calculates the values to attemp to generate the
+ *  requested interrupt rate.
+ *
+ * DANG_END_FUNCTION
+ */
+static void set_timer_latch0(u_long latch_value)
 {
-  unsigned long *ticks = BIOS_TICK_ADDR;
-  unsigned char *overflow = TICK_OVERFLOW_ADDR;
+  timer_pops    = 0;
+  gettimeofday(&clock0, NULL);
+
+  if (latch_value == 0)
+    latch_value = 0x10000;
+  timer_latch0  = latch_value;
+  timer_div     = (latch_value * 10000) / CLOCK_TICK_RATE;
+  if (timer_div == 0)
+    timer_div = 1;
+
+  i_printf("timer_interrupt_rate requested %.3g Hz, granted %.3g Hz\n",
+           CLOCK_TICK_RATE / (double)latch_value, 10000.0 / timer_div);
+}
+
+/*
+ * DANG_BEGIN_FUNCTION initialize_timers
+ *
+ * description:  ensure the 0x40 port timer is initially set correctly
+ *
+ * DANG_END_FUNCTION
+ */
+void initialize_timers(void)
+{
+   set_timer_latch0(0x10000);
+}
+
+/*
+ * DANG_BEGIN_FUNCTION initialize_timers
+ *
+ * description:
+ *  Every time we get a TIMER signal from Linux, this procedure is called.
+ *  It checks to see if we should queue a timer interrupt based on the
+ *  current values.
+ *
+ *  NOTE:  this code is liable to overflow after about ~111 hours without
+ *         having the timer port reset.
+ *
+ * DANG_END_FUNCTION
+ */
+void timer_tick(void)
+{
+  static u_char timals = 0;
+
+  if (config.timers) {
+    struct timeval tp;
+    u_long cur_count;
+
+    gettimeofday(&tp, NULL);
+
+    /* compute the number of 100usecs since we started */
+    cur_count  = (tp.tv_sec - clock0.tv_sec) * 10000;
+    cur_count += (tp.tv_usec - clock0.tv_usec) / 100;
 
-  /* excuse the inaccuracies, I'll do this better later...this simulates
-   * an (very) roughly 20 Hz timer increment rate...cheesy, but it's okay.
-   * I used 22 instead of 18 not only for the roundoff error, but
-   * because of the latency problem with 1x10^6/UPDATE < 18
-   */
-  (*ticks) += (22 / FREQ);
-  /*  warn("TIMER: updated count to %d\n", *ticks); */
-  if (*ticks == 0) {
-    h_printf("TIMER: 24 hours overflow!\n");
-    (*overflow)++;
+    /* compute the correspond number of timer ticks */
+    cur_count /= timer_div;
+
+    /* add any missing timer events to the queue */
+    while (timer_pops < cur_count) {
+      timer_value0++;
+
+      h_printf("starting timer int 8...\n");
+#ifndef NEW_PIC
+      if (!do_hard_int(8))
+	h_printf("CAN'T DO TIMER INT 8...IF CLEAR\n");
+#else
+#if NEW_PIC==2
+      age_transmit_queues();
+#endif
+      pic_request(PIC_IRQ0);
+#endif
+
+      timer_pops++;
+    }
   }
+  else
+    h_printf("NOT CONFIG.TIMERS\n");
 }
 
-void
-set_ticks(unsigned long new)
+void set_ticks(unsigned long new)
 {
   unsigned long *ticks = BIOS_TICK_ADDR;
   unsigned char *overflow = TICK_OVERFLOW_ADDR;
@@ -111,4 +216,112 @@
   ignore_segv--;
 }
 
-#undef TIMERS_C
+int do_40(boolean_t in_out, int val)
+{
+  int ret;
+
+  if (in_out) {  /* true => in, false => out */
+    if (timer0_latched_value == 0) {
+      timer0_latched_value = timer_div*850;
+    }
+    switch (timer0_read_latch_value) {
+      case 0x30:
+        ret = timer0_latched_value&0xf;
+	timer0_read_latch_value = 0x20;
+	break;
+      case 0x10:
+	ret = timer0_latched_value&0xf;
+	timer0_read_latch_value = 0x0;
+	break;
+      case 0x20:
+	ret = (timer0_latched_value&0xf0)>>8;
+	timer0_read_latch_value = 0x0;
+	timer0_latched_value = 0;
+	break;
+      case 0x0:
+	if (latched_counter_msb) {
+	  ret = (timer0_cntr_latch >> 8) & 0xff;
+	} else {
+	  timer0_cntr_latch = timer_value0;
+	  ret = timer0_cntr_latch & 0xff;
+	}
+	latched_counter_msb = !latched_counter_msb;
+	break;
+      }
+    i_printf("PORT: do_40, in = 0x%x\n",ret);
+  } else {
+    switch (timer0_read_latch_value) {
+      case 0x0:
+      case 0x30:
+        timer0_new_value = val;
+	timer0_read_latch_value = 0x20;
+	break;
+      case 0x10:
+	timer0_new_value = val;
+	timer0_read_latch_value = 0x0;
+	break;
+      case 0x20:
+	timer0_new_value |= (val<<8);
+	timer0_read_latch_value = 0x0;
+	break;
+      }
+    i_printf("PORT: do_40, out = 0x%x\n",val);
+    if (timer0_read_latch_value == 0)
+      set_timer_latch0(timer0_new_value);
+  }
+  return(ret);
+}
+
+#if 0
+/* return value of port -- what happens when output?  Stack trash? */
+int do_42(in_out, val)
+	boolean_t in_out;
+	int val;
+{
+	int ret;
+	if (in_out) {  /* true => in, false => out */
+		ioperm(0x42,1,1);
+		ret = port_in(0x42);
+		ioperm(0x42,1,0);
+		i_printf( "PORT: do_42, in = 0x%x\n",ret);
+	} else {
+		ioperm(0x42,1,1);
+		port_out(val, 0x42);
+		ioperm(0x42,1,0);
+		i_printf( "PORT: do_42, out = 0x%x\n",val);
+	}
+	return(ret);
+}
+
+#endif
+
+int do_43(boolean_t in_out, int val)
+{
+  int ret;
+	
+  if (in_out) {  /* true => in, false => out */
+    i_printf( "PORT: do_43, in = 0x%x\n",ret);
+  } else {
+    i_printf( "PORT: do_43, out = 0x%x\n",val);
+    switch(val>>6) {
+    case 0:
+      timer0_read_latch_value = (val&0x30);
+      timer0_read_latch_value_orig = (val&0x30);
+      if (timer0_read_latch_value == 0) {
+	latched_counter_msb = FALSE;
+      }
+      break;
+    case 2:
+#if 0
+      ioperm(0x43,1,1);
+      port_out(val, 0x43);
+      ioperm(0x43,1,0);
+#else
+      safe_port_out_byte(0x43, val);
+#endif
+      i_printf( "PORT: Really do_43\n");
+      break;
+    }
+  }
+  return(ret);
+}
diff -u --recursive --new-file dosemu0.53pl47/dpmi/bcc.h dosemu0.53pl48/dpmi/bcc.h
--- dosemu0.53pl47/dpmi/bcc.h	Mon Feb 27 19:27:55 1995
+++ dosemu0.53pl48/dpmi/bcc.h	Tue Mar  7 18:52:36 1995
@@ -1,5 +1,7 @@
-/* bugy-bcc.c	-- Dong Liu <dliu@ricenjit.edu> Sat Feb 11 1995
- * 
+/* bcc.h      -- Dong Liu <dliu@rice.njit.edu> Sat Feb 11 1995
+ *
+ * Special hacks for running Borland\'s C++ compiler.
+ *
  * $Log: bcc.h,v $
  * Revision 1.1  1995/02/25  21:54:01  root
  * Initial revision
@@ -41,6 +43,14 @@
     unsigned short code_alias;
 } dpmiload_mem_info;
 
+/* the bits of flags of dpmiload_mem_info */
+#define SEGMENT_DATA        0x1
+#define SEGMENT_VALID       0x2
+#define SEGMENT_DOS         0x4
+#define SEGMENT_MOVABLE     0x10
+#define SEGMENT_PRELOAD     0x40
+#define SEGMENT_DISCARDABLE 0x1000
+
 /* used when bcc passing a DTA higher than 1MB */
 static void * DTA_over_1MB;
 static void * DTA_under_1MB;
@@ -56,7 +66,8 @@
 static inline int SetSelector(unsigned short, unsigned long,
                               unsigned long, unsigned char, unsigned char,
                               unsigned char, unsigned char);
-
+static inline void save_pm_regs();
+static inline void restore_pm_regs();
 
 /* fortunately when dpmiload.exe calling dpmi_get_entry_point, ES=PSP */
 /* so, we check the enviroment segment to see if it is real dpmiload.exe*/
@@ -94,29 +105,196 @@
 /* copy them back when back from real mode interrupt. Should consider */
 /* use mmap for speed, but how =(? */
 
-
-#define MAP_SEGMENT
-#ifdef MAP_SEGMENT
-
 static unsigned short DS_MAPPED;
 static unsigned short ES_MAPPED;
-
+static char READ_DS_COPIED;
 static inline int
 bcc_pre_extender(struct sigcontext_struct *scp, int intr)
 {
+    DS_MAPPED = 0;
+    ES_MAPPED = 0;
     /* first see if we don\'t need to go to real mode */
     switch (intr) {
     case 0x21:
+	SAVED_REGS = REGS;
 	switch (_HI(ax)) {
 	case 0x25:		/* set vector */
-	    Interrupt_Table[current_client][_LO(bx)].selector = _ds;
-	    Interrupt_Table[current_client][_LO(bx)].offset = _edx;
+	    Interrupt_Table[current_client][_LO(ax)].selector = _ds;
+	    Interrupt_Table[current_client][_LO(ax)].offset = _edx;
+	    D_printf("BCC: int 21,ax=0x%04x, ds=0x%04x. dx=0x%04x\n",
+		     _LWORD(eax), _ds, _LWORD(edx));
 	    return 1;
 	case 0x35:	/* Get Interrupt Vector */
-	    _es = Interrupt_Table[current_client][_LO(bx)].selector;
-	    _ebx = Interrupt_Table[current_client][_LO(bx)].offset;
+	    _es = Interrupt_Table[current_client][_LO(ax)].selector;
+	    _ebx = Interrupt_Table[current_client][_LO(ax)].offset;
+	    D_printf("BCC: int 21,ax=0x%04x, es=0x%04x. bx=0x%04x\n",
+		     _LWORD(eax), _es, _LWORD(ebx));
 	    return 1;
+	case 0x1a:		/* set DTA */
+	    if ( Segments[ _ds >> 3].base_addr > 0xffff0) {
+		D_printf("DPMI: bcc passing pointer > 1MB to dos set DTA\n"); 
+		
+		DTA_over_1MB = (void *)GetSegmentBaseAddress(_ds)
+		                                   + _LWORD(edx); 
+		REG(ds) = DPMI_private_data_segment+DPMI_private_paragraphs+
+		                  0x2000;
+		REG(edx)=0;
+		DTA_under_1MB = (void *)(REG(ds) << 4);
+	    } else
+		DTA_over_1MB = 0;
+	    return 0;
+	case 0x4b:		/* EXEC */
+	    D_printf("BCC: call dos exec.\n");
+	    /* we must copy all data from higher 1MB to lower 1MB */
+	    {
+		unsigned short segment =
+		    DPMI_private_data_segment+DPMI_private_paragraphs;
+		void *p;
+		unsigned short sel,off;
+		
+		if ( Segments[ _ds >> 3].base_addr > 0xffff0) {
+		    /* must copy command line */
+		    REG(ds) = segment;
+		    REG(edx) = 0;
+		    p = (void *)GetSegmentBaseAddress(_ds) +
+			_LWORD(edx);
+		    strcpy((char *)(REG(ds)<<4), p);
+		    segment += (strlen(p)>>4) + 1;
+		}
+		if ( Segments[ _es >> 3].base_addr > 0xffff0) {
+		    /* must copy parameter block */
+		    REG(es) = segment;
+		    REG(ebx) = 0;
+		    memcpy((void *)(REG(es)<<4),
+			   (void*)GetSegmentBaseAddress(_es) + _LWORD(ebx),
+			   0x20);
+		    segment += 2;
+		}
+		/* now the envrionment segment */
+		sel = *(unsigned short *)((REG(es)<<4)+LWORD(ebx));
+		if (Segments[sel>>3].base_addr> 0xffff0) {
+		    *(unsigned short *)((REG(es)<<4)+LWORD(ebx)) =
+			segment;
+		    memcpy((void *)(segment <<4),           /* 4K envr. */
+			   (void *)GetSegmentBaseAddress(sel),
+			   0x1000);
+		    segment += 0x100;
+		} else 
+		    *(unsigned short *)((REG(es)<<4)+LWORD(ebx)) =
+			GetSegmentBaseAddress(sel)>>4;
+
+		/* now the tail of the command line */
+		off = *(unsigned short *)((REG(es)<<4)+LWORD(ebx)+2);
+		sel = *(unsigned short *)((REG(es)<<4)+LWORD(ebx)+4);
+		if (Segments[sel>>3].base_addr > 0xffff0) {
+		    *(unsigned short *)((REG(es)<<4)+LWORD(ebx)+4)
+			= segment;
+		    *(unsigned short *)((REG(es)<<4)+LWORD(ebx)+2) = 0;
+		    memcpy((void *)(segment<<4),
+			   (void *)GetSegmentBaseAddress(sel) + off,
+			   0x80);
+		} else
+		    *(unsigned short *)((REG(es)<<4)+LWORD(ebx)+4)
+			= GetSegmentBaseAddress(sel)>>4;
+
+		/* make tow FCB\'s zero */
+		*(unsigned long *)((REG(es)<<4)+LWORD(ebx)+6) = 0;
+		*(unsigned long *)((REG(es)<<4)+LWORD(ebx)+0xA) = 0;
+	    }
+	    REG(eip) = DPMI_OFF + HLT_OFF(DPMI_return_from_dos_exec);
+	    /* save context for child exits */
+	    memcpy(&dpmi_stack_frame[current_client], scp,
+		   sizeof(struct sigcontext_struct));
+	    save_pm_regs();
+	    return 0;
+	case 0x50:		/* set PSP */
+	    if (((LWORD(ebx) & 0x7) == 0x7) &&
+		((LWORD(ebx) >> 3) < MAX_SELECTORS) &&
+		Segments[LWORD(ebx) >> 3].used) {
+		unsigned short envp;
+
+		REG(ebx) = (long) GetSegmentBaseAddress(LWORD(ebx)) >> 4;
+		envp = *(unsigned short *)(((char *)(LWORD(ebx)<<4)) + 0x2c);
+		if (((envp & 0x7 == 0x7) &&
+		     ((envp >> 3) < MAX_SELECTORS) &&
+		     Segments[envp >> 3].used))
+		    *(unsigned short *)(((char *)(LWORD(ebx)<<4))+0x2c) =
+			(long) GetSegmentBaseAddress(envp) >> 4;
+	    }
+	    return 0;
+	case 0x39:		/* mkdir */
+	case 0x3a:		/* rmdir */
+	case 0x3b:		/* chdir */
+	case 0x3c:		/* creat */
+	case 0x3d:		/* Dos OPEN */
+	case 0x41:		/* unlink */
+	case 0x43:		/* change attr */
+	case 0x4e:		/* find first */
+	case 0x4f:		/* find next */
+	    if ( Segments[ _ds >> 3].base_addr > 0xffff0) {
+		D_printf("DPMI: bcc passing ASCIIZ > 1MB to dos\n"); 
+		REG(ds) = DPMI_private_data_segment+DPMI_private_paragraphs;
+		strcpy((void *)((REG(ds) << 4)+LWORD(edx)),
+		       (void *)GetSegmentBaseAddress(_ds)+_LWORD(edx));
+	    }
+	    return 0;
+	case 0x3f:		/* dos read */
+	    /* bcc sometime pass address > 1MB to dos to read, so */
+	    /* frist read to our buffer, then copy it to client */
+	    if ( Segments[ _ds >> 3].base_addr > 0xffff0) {
+		D_printf("DPMI: bcc passing pointer > 1MB to dos read\n"); 
+		S_REG(ds) = _ds;
+		REG(ds) = DPMI_private_data_segment+DPMI_private_paragraphs;
+		REG(edx) = 0;
+		READ_DS_COPIED = 1;
+	    } else
+		READ_DS_COPIED = 0;
+	    return 0;
+	case 0x40:		/* DOS Write */
+	    if ( Segments[ _ds >> 3].base_addr > 0xffff0)
+		D_printf("DPMI: bcc passing pointer > 1MB to dos write\n"); 
+	    S_REG(ds) = _ds;
+	    REG(ds) = DPMI_private_data_segment+DPMI_private_paragraphs;
+	    REG(edx) = 0;
+	    memcpy((void *)(REG(ds) << 4),
+		   (void *)GetSegmentBaseAddress(S_REG(ds))+S_LWORD(edx),
+		   LWORD(ecx));
+	    return 0;
+	case 0x01 ... 0x08:	/* These are dos functions which */
+	case 0x0b ... 0x0e:	/* are not required memory copy. */
+	case 0x19:
+	case 0x2a ... 0x2e:
+	case 0x30 ... 0x31:
+	case 0x33:
+	case 0x36 ... 0x37:
+	case 0x3e:
+	case 0x42:
+	case 0x45 ... 0x46:
+	case 0x48 ... 0x4a:
+	case 0x4d:
+	    return 0;
+	}
+	break;
+    case 0x08:			/* timer, hardware */
+    case 0x09:			/* keyborad HW */
+	return 0;
+    case 0x10:			/* video */
+	switch (_HI(ax)) {
+	case 0x00 ... 0x0f:
+	    return 0;
 	}
+	break;
+    case 0x11:			/* bios equipment flags */
+    case 0x12:			/* bios memory */
+    case 0x16:			/* keyboard */
+    case 0x17:			/* printer */
+    case 0x1c:			/* BIOS timer */
+    case 0x23:			/* DOS Ctrl-C */
+    case 0x24:			/* DOS critical error */
+    case 0x28:			/* DOS idle */
+	return 0;
+    default:
+	break;
     }
 
     /* envetually, we should use mmap, now just copy it */
@@ -144,13 +322,7 @@
 
     switch (intr) {
     case 0x21:
-	SAVED_REGS = REGS;
 	switch (HI(ax)) {
-	case 0x50:		/* set PSP */
-	    if (((LWORD(ebx) >> 3) < MAX_SELECTORS) &&
-		Segments[LWORD(ebx) >> 3].used)
-		REG(ebx) = (long) GetSegmentBaseAddress(LWORD(ebx)) >> 4;
-	    break;
 	}
     }
     return 0;
@@ -157,6 +329,27 @@
 }
 
 static inline
+bcc_post_exec()
+{
+    /* restore parent\'s context */
+    restore_pm_regs();
+    dpmi_stack_frame[current_client].eflags = 0x0202 | (0x0dd5 & REG(eflags));
+    dpmi_stack_frame[current_client].eax = REG(eax);
+    dpmi_stack_frame[current_client].ebx = REG(ebx);
+    dpmi_stack_frame[current_client].ecx = REG(ecx);
+    dpmi_stack_frame[current_client].edx = REG(edx);
+    dpmi_stack_frame[current_client].esi = REG(esi);
+    dpmi_stack_frame[current_client].edi = REG(edi);
+    dpmi_stack_frame[current_client].ebp = REG(ebp);
+
+    if (LWORD(eflags) & CF) {
+	dpmi_stack_frame[current_client].edx = S_REG(edx);
+	dpmi_stack_frame[current_client].ebx = S_REG(ebx);
+    }
+    return;
+}
+
+static inline
 bcc_post_extender(int intr)
 {
     if (DS_MAPPED) {
@@ -196,159 +389,6 @@
 	    dpmi_stack_frame[current_client].eax =
 		ConvertSegmentToDescriptor(LWORD(eax));
 	    break;
-	case 0x51:		/* get PSP */
-	case 0x62:
-	    {/* convert environment pointer to a descriptor*/
-		unsigned short envp, psp;
-		psp = LWORD(ebx);
-#if 0		
-		envp = *(unsigned short *)(((char *)(psp<<4))+0x2c);
-		envp = ConvertSegmentToDescriptor(envp);
-		*(unsigned short *)(((char *)(psp<<4))+0x2c) = envp;
-#endif 		
-		dpmi_stack_frame[current_client].ebx = ConvertSegmentToDescriptor(psp);
-	    }
-	    return;
-	case 0x34:	/* Get Address of InDOS Flag */
-	    if (!(dpmi_stack_frame[current_client].es =
-		  ConvertSegmentToDescriptor(REG(es))))
-		D_printf("DPMI: can't allocate descriptor for InDOS pointer\n");
-	    return;
-	case 0x5d:
-	    if (S_LO(ax) == 0x06) /* get address of DOS swappable area */
-				/*        -> DS:SI                     */
-		dpmi_stack_frame[current_client].ds = ConvertSegmentToDescriptor(REG(ds));
-	    return;
-	default:
-	    return;
-	}
-	break;
-    default:
-	return;
-    }
-}
-
-#else /* MAP_SEGMENT */    
-
-static inline
-bcc_pre_extender(struct sigcontext_struct *scp, int intr)
-{
-    switch (intr) {
-    case 0x21:
-	SAVED_REGS = REGS;
-	switch (HI(ax)) {
-	case 0x09:		/* Dos print string */
-	    if ( Segments[ _ds >> 3].base_addr > 0xffff0) {
-		void *des , *src, *p;
-
-		D_printf("DPMI: bcc passing pointer > 1MB to dos print\n");
-
-		REG(ds) = DPMI_private_data_segment+DPMI_private_paragraphs;
-
-		des = (void *)((REG(ds) << 4)+LWORD(edx));
-		src = (void *)GetSegmentBaseAddress(_ds)+_LWORD(edx);
-		
-		p = memchr(src, '$',  0xffff);
-		if (!p) 
-		    *(char  *)des = '$';
-		else
-		    memcpy(des, src, p - src + 1);
-	    }
-	    return;
-	case 0x1a:		/* set DTA */
-	    if ( Segments[ _ds >> 3].base_addr > 0xffff0) {
-		D_printf("DPMI: bcc passing pointer > 1MB to dos set DTA\n"); 
-		
-		DTA_over_1MB = (void *)GetSegmentBaseAddress(_ds)
-		                                   + _LWORD(edx); 
-		REG(ds) = DPMI_private_data_segment+DPMI_private_paragraphs+
-		                  0x1000 - 0x8;
-		REG(edx)=0;
-		DTA_under_1MB = (void *)(REG(ds) << 4);
-	    } else
-		DTA_over_1MB = 0;
-	    return;
-	case 0x50:		/* set PSP */
-	    if (((LWORD(ebx) >> 3) < MAX_SELECTORS) &&
-		Segments[LWORD(ebx) >> 3].used)
-		REG(ebx) = (long) GetSegmentBaseAddress(LWORD(ebx)) >> 4;
-	    return;
-	case 0x39:		/* mkdir */
-	case 0x3a:		/* rmdir */
-	case 0x3b:		/* chdir */
-	case 0x3c:		/* creat */
-	case 0x3d:		/* Dos OPEN */
-	case 0x41:		/* unlink */
-	case 0x43:		/* change attr */
-	case 0x4e:		/* find first */
-	case 0x4f:		/* find next */
-	    if ( Segments[ _ds >> 3].base_addr > 0xffff0) {
-		D_printf("DPMI: bcc passing ASCIIZ > 1MB to dos\n"); 
-		REG(ds) = DPMI_private_data_segment+DPMI_private_paragraphs;
-		strcpy((void *)((REG(ds) << 4)+LWORD(edx)),
-		       (void *)GetSegmentBaseAddress(_ds)+_LWORD(edx));
-	    }
-	    return;
-	case 0x3f:		/* dos read */
-	    /* bcc sometime pass address > 1MB to dos to read, so */
-	    /* frist read to our buffer, then copy it to client */
-	    if ( Segments[ _ds >> 3].base_addr > 0xffff0)
-		D_printf("DPMI: bcc passing pointer > 1MB to dos read\n"); 
-	    S_REG(ds) = _ds;
-	    REG(ds) = DPMI_private_data_segment+DPMI_private_paragraphs;
-	    REG(edx) = 0;
-	    return;
-	case 0x40:		/* DOS Write */
-	    if ( Segments[ _ds >> 3].base_addr > 0xffff0)
-		D_printf("DPMI: bcc passing pointer > 1MB to dos write\n"); 
-	    S_REG(ds) = _ds;
-	    REG(ds) = DPMI_private_data_segment+DPMI_private_paragraphs;
-	    REG(edx) = 0;
-	    memcpy((void *)(REG(ds) << 4),
-		   (void *)GetSegmentBaseAddress(S_REG(ds))+S_LWORD(edx),
-		   LWORD(ecx));
-	    return;
-	case 0x47:		/* dos getcwd */
-	    /* bcc sometime pass address > 1MB to dos to read, so */
-	    /* frist read to our buffer, then copy it to client */
-	    if ( Segments[ _ds >> 3].base_addr > 0xffff0)
-		D_printf("DPMI: bcc passing pointer > 1MB to dos getcwd\n"); 
-	    S_REG(ds) = _ds;
-	    REG(ds) = DPMI_private_data_segment+DPMI_private_paragraphs;
-	    return;
-	}
-	break;
-    case 0x3f:			/* for gdb */
-	D_printf("DPMI: int $0x3f called\n");
-	break;
-    }
-}
-
-static inline
-bcc_post_extender(int intr)
-{
-    switch (intr) {
-    case 0x21:
-	switch (S_HI(ax)) {
-	case 0x1a:		/* set DTA */
-	    dpmi_stack_frame[current_client].edx = S_REG(edx);
-	    break;
-	case 0x2f:		/* GET DTA */
-	    dpmi_stack_frame[current_client].es =
-	               ConvertSegmentToDescriptor(REG(es));
-	    break;
-	case 0x38:
-	    if (S_LO(ax) == 0x00) { /* get contry info */
-		dpmi_stack_frame[current_client].ds =
-	               ConvertSegmentToDescriptor(REG(ds));
-	    }
-	    break;
-	case 0x48:		/* allocate memory */
-	    if (LWORD(eflags) & CF)
-		break;
-	    dpmi_stack_frame[current_client].eax =
-		ConvertSegmentToDescriptor(LWORD(eax));
-	    break;
 	case 0x4e:		/* find first */
 	case 0x4f:		/* find next */
 	    if (LWORD(eflags) & CF)
@@ -380,21 +420,19 @@
 		dpmi_stack_frame[current_client].ds = ConvertSegmentToDescriptor(REG(ds));
 	    return;
 	case 0x3f:
-	    dpmi_stack_frame[current_client].edx = S_REG(edx);
-	    if (LWORD(eflags) & CF)
-		return;
-	    memcpy((void *)(GetSegmentBaseAddress(S_REG(ds)) + S_LWORD(edx)),
-			    (void *)(REG(ds) << 4), LWORD(eax));
+	    if (READ_DS_COPIED) {
+		dpmi_stack_frame[current_client].edx = S_REG(edx);
+		if (LWORD(eflags) & CF)
+		    return;
+		memcpy((void *)(GetSegmentBaseAddress(S_REG(ds)) +
+				S_LWORD(edx)),
+				(void *)(REG(ds) << 4), LWORD(eax));
+	    }
+	    READ_DS_COPIED = 0;
 	    break;
 	case 0x40:
 	    dpmi_stack_frame[current_client].edx = S_REG(edx);
 	    break;
-	case 0x47:		/* getcwd */
-	    if (LWORD(eflags) & CF)
-		return;
-	    strcpy((char *)(GetSegmentBaseAddress(S_REG(ds)) + S_LWORD(esi)),
-			    (char *)(REG(ds) << 4)+ LWORD(esi));
-	    return;
 	default:
 	    return;
 	}
@@ -403,7 +441,6 @@
 	return;
     }
 }
-#endif /* MAP_SEGMENT */
 
 static inline int
 bcc_SetDescriptor(struct sigcontext_struct *scp)
@@ -426,34 +463,36 @@
     lp++;
     base_addr |= (*lp & 0xFF000000) | ((*lp << 16) & 0x00FF0000);
     limit |= (*lp & 0x000F0000);
-
+ 
+#if 1
     /* this is getting ridiculous, dpmiload.exe sometime uses a */
     /* selector (DS) as the higher 16-value of a descriptor when making */
     /* dpmi service 0x000c call, I dont what it want here */
     desc = ((base_addr>>16)&0xffff);
-#if 1
     if ((desc == _ds) && ((base_addr&0xffff) == _LWORD(esi))) {
 	dpmiload_mem_info *info = (dpmiload_mem_info *)(
 	    GetSegmentBaseAddress(_ds) + _LWORD(esi));
 
-	D_printf("DPMI: bcc uses ds:si as base address\n");
-#if 0
-	if (info -> handle == 0)  /* no need to setdescriptor */
-	    return 0;
-	base_addr = info->linear_address;
-	limit = info->size;
-#endif
-	base_addr = Segments[_ds>>3].base_addr;
-	limit = info->size;
 	fix_code_alias = 0;
-    }
-#else
-    desc = desc>>3;
-    if((desc < MAX_SELECTORS) && Segments[desc].used &&
-       (Segments[desc].limit <= 0xffff) &&
-       (Segments[desc].is_big==0) &&
-       (Segments[desc].is_32 == DPMIclient_is_32)) {
-	base_addr = Segments[desc].base_addr + (base_addr&0xffff);
+
+	/* after we figure out that ds:si is the segment info block, */
+	/* we make all segments fixed, preload and non-discardable */
+	D_printf("DPMI: bcc uses ds:si as base address flags 0x%04x\n", info->flags);
+	/* make sure it is a valid memory block info struct */
+	if(((info->flags & SEGMENT_DOS) == 0)
+	   /*   && ((info->flags & SEGMENT_DATA) == 0)*/
+	   && (info->code_selector == selector)) {
+	    /* make all segment fixed, preload and non-discardable, */
+	    /* because memory is not the issue here :=) */
+	    if (info -> flags & SEGMENT_MOVABLE)
+		info -> flags &= ~SEGMENT_MOVABLE;
+	    if ((info -> flags & SEGMENT_PRELOAD) == 0)
+		info -> flags |= SEGMENT_PRELOAD;
+	    if (info -> flags & SEGMENT_DISCARDABLE)
+		info -> flags &= ~SEGMENT_DISCARDABLE;
+	}
+
+	base_addr = GetSegmentBaseAddress(_ds);
     }
 #endif    
     if (SetSelector(selector, base_addr, limit, (*lp >> 22) & 1,
@@ -501,6 +540,8 @@
     }
 }
 
+static char decode_use_16bit;
+static char use_prefix;
 static inline unsigned char *
 decode_8e_index(struct sigcontext_struct *scp, unsigned char *prefix,
 		int rm)
@@ -507,49 +548,49 @@
 {
     switch (rm) {
     case 0:
-	if (prefix)
+	if (use_prefix)
 	    return prefix + _LWORD(ebx) + _LWORD(esi);
 	else
 	    return (unsigned char *)(GetSegmentBaseAddress(_ds)+
 				     _LWORD(ebx) + _LWORD(esi));
     case 1:
-	if (prefix)
+	if (use_prefix)
 	    return prefix + _LWORD(ebx) + _LWORD(edi);
 	else
 	    return (unsigned char *)(GetSegmentBaseAddress(_ds)+
 				     _LWORD(ebx) + _LWORD(edi));
     case 2:
-	if (prefix)
+	if (use_prefix)
 	    return prefix + _LWORD(ebp) + _LWORD(esi);
 	else
 	    return (unsigned char *)(GetSegmentBaseAddress(_ss)+
 				     _LWORD(ebp) + _LWORD(esi));
     case 3:
-	if (prefix)
+	if (use_prefix)
 	    return prefix + _LWORD(ebp) + _LWORD(edi);
 	else
 	    return (unsigned char *)(GetSegmentBaseAddress(_ss)+
 				     _LWORD(ebp) + _LWORD(edi));
     case 4:
-	if (prefix)
+	if (use_prefix)
 	    return prefix + _LWORD(esi);
 	else
 	    return (unsigned char *)(GetSegmentBaseAddress(_ds)+
 				     _LWORD(esi));
     case 5:
-	if (prefix)
+	if (use_prefix)
 	    return prefix + _LWORD(edi);
 	else
 	    return (unsigned char *)(GetSegmentBaseAddress(_ds)+
 				     _LWORD(edi));
     case 6:
-	if (prefix)
+	if (use_prefix)
 	    return prefix + _LWORD(ebp);
 	else
 	    return (unsigned char *)(GetSegmentBaseAddress(_ss)+
 				     _LWORD(ebp));
     case 7:
-	if (prefix)
+	if (use_prefix)
 	    return prefix + _LWORD(ebx);
 	else
 	    return (unsigned char *)(GetSegmentBaseAddress(_ds)+
@@ -564,25 +605,31 @@
 
     csp = (unsigned char *) SEL_ADR(_cs, _eip);
 
-    prefix = 0;
+    use_prefix = 0;
     switch (*csp) {
     case 0x2e:
 	prefix = (unsigned char *)GetSegmentBaseAddress(_cs);
+	use_prefix = 1;
 	break;
     case 0x36:
 	prefix = (unsigned char *)GetSegmentBaseAddress(_ss);
+	use_prefix = 1;
 	break;
     case 0x3e:
 	prefix = (unsigned char *)GetSegmentBaseAddress(_ds);
+	use_prefix = 1;
 	break;
     case 0x26:
 	prefix = (unsigned char *)GetSegmentBaseAddress(_es);
+	use_prefix = 1;
 	break;
     case 0x64:
 	prefix = (unsigned char *)GetSegmentBaseAddress(_fs);
+	use_prefix = 1;
 	break;
     case 0x65:
 	prefix = (unsigned char *)GetSegmentBaseAddress(_gs);
+	use_prefix = 1;
 	break;
     }
     return prefix;
@@ -600,15 +647,12 @@
     unsigned char mod, rm, reg;
     int len = 0;
 
+    if (!decode_use_16bit)	/*  32bit decode not implmented yet*/
+	return 0;
     csp = (unsigned char *) SEL_ADR(_cs, _eip);
 
-    if ((Segments[_cs>>3].is_32) && (*csp == 0x66)) { /* Operand-Size prefix */
-	csp++;
-	len++;
-    }
-
     prefix = check_prefix(scp);
-    if (prefix) {
+    if (use_prefix) {
 	csp++;
 	len++;
     }
@@ -625,7 +669,7 @@
     switch (mod) {
     case 0:
 	if (rm == 6) {		/* disp16 */
-	    if(prefix)
+	    if(use_prefix)
 		*src = *(unsigned short *)(prefix +
 					   (int)(*(short *)(csp+1)));
 	    else
@@ -637,7 +681,7 @@
 	break;
     case 1:			/* disp8 */
 	*src = *(unsigned short *)(decode_8e_index(scp, prefix, rm) +
-				   (int)(*(csp+1)));
+				   (int)(*(char *)(csp+1)));
 	len++;
 	break;
     case 2:			/* disp16 */
@@ -688,10 +732,12 @@
     unsigned offset;
     int len = 0;
 
+    if (!decode_use_16bit)	/*  32bit decode not implmented yet*/
+	return 0;
     csp = (unsigned char *) SEL_ADR(_cs, _eip);
 
     prefix = check_prefix(scp);
-    if (prefix) {
+    if (use_prefix) {
 	csp++;
 	len++;
     }
@@ -716,7 +762,7 @@
     switch (mod) {
     case 0:
 	if (rm == 6) {		/* disp16 */
-	    if(prefix)
+	    if(use_prefix)
 		lp = (unsigned long *)(prefix +
 					   (int)(*(short *)(csp+1)));
 	    else
@@ -728,7 +774,7 @@
 	break;
     case 1:			/* disp8 */
 	lp = (unsigned long *)(decode_8e_index(scp, prefix, rm) +
-				   (int)(*(csp+1)));
+				   (int)(*(char *)(csp+1)));
 	len++;
 	break;
     case 2:			/* disp16 */
@@ -782,18 +828,43 @@
 {
     unsigned char *csp;
     unsigned short *ssp;
-    int len ;
+    int len ,size_prfix;
+    unsigned long old_eip;
 
+    old_eip = _eip;
+    csp = (unsigned char *) SEL_ADR(_cs, _eip);
+    size_prfix = 0;
+    if (Segments[_cs>>3].is_32) {
+	if (*csp == 0x66) { /* Operand-Size prefix */
+	    csp++;
+	    _eip++;
+	    decode_use_16bit = 1;
+	    size_prfix = 1;
+	} else
+	    decode_use_16bit = 0;
+    } else {
+	if (*csp == 0x66) { /* Operand-Size prefix */
+	    csp++;
+	    _eip++;
+	    decode_use_16bit = 0;
+	    size_prfix = 1;
+	} else
+	    decode_use_16bit = 1;
+    }
+	
     /* first try mov sreg, .. */
-    if ((len = decode_8e(scp, segment, sreg)))
-	return len;
+    if ((len = decode_8e(scp, segment, sreg))) {
+	_eip = old_eip;
+	return len + size_prfix;
+    }
     /* then try lds, les ... */
-    if ((len = decode_load_descriptor(scp, segment, sreg)))
-	return len;
+    if ((len = decode_load_descriptor(scp, segment, sreg))) {
+	_eip = old_eip;
+	return len+size_prfix;
+    }
 
     /* then try pop sreg */
     len = 0;
-    csp = (unsigned char *) SEL_ADR(_cs, _eip);
     ssp = (unsigned short *) SEL_ADR(_ss, _esp);
     switch (*csp) {
     case 0x1f:			/* pop ds */
@@ -800,19 +871,19 @@
 	len = 1;
 	*segment = *ssp;
 	*sreg = DS_INDEX;
-	_esp += 2;
+	_esp += decode_use_16bit ? 2 : 4;
 	break;
     case 0x07:			/* pop es */
 	len = 1;
 	*segment = *ssp;
 	*sreg = ES_INDEX;
-	_esp += 2;
+	_esp += decode_use_16bit ? 2 : 4;
 	break;
     case 0x17:			/* pop ss */
 	len = 1;
 	*segment = *ssp;
 	*sreg = SS_INDEX;
-	_esp += 2;
+	_esp += decode_use_16bit ? 2 : 4;
 	break;
     case 0x0f:		/* two byte opcode */
 	csp++;
@@ -821,17 +892,21 @@
 	    len = 2;
 	    *segment = *ssp;
 	    *sreg = FS_INDEX;
-	    _esp += 2;
+	    _esp += decode_use_16bit ? 2 : 4;
 	    break;
 	case 0xa9:		/* pop gs */
 	    len = 2;
 	    *segment = *ssp;
 	    *sreg = FS_INDEX;
-	    _esp += 2;
+	    _esp += decode_use_16bit ? 2 : 4;
 	break;
 	}
     }
-    return len;
+    _eip = old_eip;
+    if (len)
+	return len+size_prfix;
+    else
+	return 0;
 }
 	
     
@@ -883,6 +958,18 @@
 	    _es += 8;
 	    fix_alias=1;
 	}
+	/* see if bcc want use GDT 0 */
+	if (_ds == 0) {
+	    D_printf("BCC: try to use use gdt 0 as ds\n");
+	    _ds = ConvertSegmentToDescriptor(0);
+	    fix_alias = 1;
+	}
+	if (_es == 0) {
+	    D_printf("BCC: try to use use gdt 0 as es\n");
+	    _es = ConvertSegmentToDescriptor(0);
+	    fix_alias = 1;
+	}
+	    
 	return fix_alias;
     }
 
@@ -897,7 +984,8 @@
 
     base_addr = ((unsigned long)segment) << 4;
     for(desc=0; desc < MAX_SELECTORS; desc++)
-	if (Segments[desc].base_addr == base_addr)
+	if ((Segments[desc].base_addr == base_addr)&&
+	    Segments[desc].used)
 	    break;
 
 #if 0    
diff -u --recursive --new-file dosemu0.53pl47/dpmi/dpmi.c dosemu0.53pl48/dpmi/dpmi.c
--- dosemu0.53pl47/dpmi/dpmi.c	Mon Feb 27 19:27:55 1995
+++ dosemu0.53pl48/dpmi/dpmi.c	Tue Mar  7 18:52:36 1995
@@ -148,10 +148,6 @@
 #define BCC_HACK
 #endif
 
-/* define CLIENT_USE_GDT_40, to work around some bugy client */
-/* (like  dos4gw :=(. ) want to use gdt 0x40 to access bios area */
-#define CLIENT_USE_GDT_40
-
 #include "dpmi.h"
 #include "bios.h"
 #include "config.h"
@@ -178,7 +174,7 @@
 
 static char *pm_stack; /* locked protected mode stack */
 
-static dpmi_pm_block *pm_block_root;
+static dpmi_pm_block *pm_block_root[DPMI_MAX_CLIENTS];
 static unsigned long pm_block_handle_used; /* tracking handle */
 
 static char RCSdpmi[] = "$Header: /home/src/dosemu0.60/dpmi/RCS/dpmi.c,v 2.11 1995/02/25 21:54:02 root Exp $";
@@ -202,6 +198,10 @@
 #include "bcc.h"
 #endif /* BCC_HACK */
 
+/* define CLIENT_USE_GDT_40, to work around some bugy client */
+/* (like  dos4gw :=(. ) want to use gdt 0x40 to access bios area */
+#define CLIENT_USE_GDT_40
+
 _syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount)
 
 inline int get_ldt(void *buffer)
@@ -405,10 +405,8 @@
    if (bcc_check_dpmiload(old_es)) {
      in_bcc = 1;
      D_printf("DPMI: we are running Borland DOS extender\n");
-     LWORD(esi) += 0x2000;
-   } else
-     if (!in_dpmires)
-      in_bcc = 0;
+     LWORD(esi) += 0x2008;
+   } 
 
 #endif /* BCC_HACK */
 }
@@ -697,8 +695,8 @@
     dpmi_pm_block *p = malloc(sizeof(dpmi_pm_block));
     if(!p)
 	return NULL;
-    p -> next =	pm_block_root;	/* add it to list */
-    pm_block_root = p;
+    p -> next =	pm_block_root[current_client];	/* add it to list */
+    pm_block_root[current_client] = p;
     return p;
 }
 /* free_pm_block free a dpmi_pm_block struct and delete it from list */
@@ -706,12 +704,12 @@
 {
     dpmi_pm_block *tmp;
     if (!p) return -1;
-    if (p == pm_block_root) {
-	pm_block_root = p -> next;
+    if (p == pm_block_root[current_client]) {
+	pm_block_root[current_client] = p -> next;
 	free(p);
 	return 0;
     }
-    for(tmp = pm_block_root; tmp; tmp = tmp -> next)
+    for(tmp = pm_block_root[current_client]; tmp; tmp = tmp -> next)
 	if (tmp -> next == p)
 	    break;
     if (!tmp) return -1;
@@ -723,7 +721,7 @@
 static inline dpmi_pm_block *lookup_pm_block(unsigned long h)
 {
     dpmi_pm_block *tmp;
-    for(tmp = pm_block_root; tmp; tmp = tmp -> next)
+    for(tmp = pm_block_root[current_client]; tmp; tmp = tmp -> next)
 	if (tmp -> handle == h)
 	    return tmp;
     return 0;
@@ -1165,17 +1163,6 @@
   if (in_dpmi==1) {
     if (ldt_buffer) free(ldt_buffer);
     if (pm_stack) free(pm_stack);
-    if (pm_block_root) {
-        dpmi_pm_block *p = pm_block_root;
-        while(p) {
-          dpmi_pm_block *tmp;
-	  if (p->base)
-	      free(p->base);
-          tmp = p->next;
-	  free(p);
-	  p = tmp;
-        }
-    }
 #ifdef BCC_HACK
     in_bcc = 0;
 #endif /* BCC_HACK */
@@ -1188,10 +1175,23 @@
         Segments[i>>3].used = 0;
     }
   }
+  if (pm_block_root[current_client]) {
+     dpmi_pm_block *p = pm_block_root[current_client];
+     while(p) {
+       dpmi_pm_block *tmp;
+       if (p->base)
+	  free(p->base);
+       tmp = p->next;
+       free(p);
+       p = tmp;
+     }
+  }
   in_dpmi_dos_int = 1;
   in_dpmi--;
   in_win31 = 0;
+#if 0
   dpmi_cli();
+#endif
   memcpy(scp, &dpmi_stack_frame[current_client], sizeof(struct sigcontext_struct));
   REG(cs) = DPMI_SEG;
   REG(eip) = DPMI_OFF + HLT_OFF(DPMI_return_from_dos);
@@ -1421,7 +1421,6 @@
     memset(ldt_buffer,0xff,LDT_ENTRIES*LDT_ENTRY_SIZE);
     modify_ldt(0, ldt_buffer, MAX_SELECTORS*LDT_ENTRY_SIZE);
 
-    pm_block_root = 0;
     pm_block_handle_used = 1;
 /*
  * DANG_BEGIN_NEWIDEA
@@ -1551,6 +1550,7 @@
   in_win31 = 0;
   in_dpmi_dos_int = 0;
   in_sigsegv--;
+  pm_block_root[current_client] = 0;
   memset((void *)(&realModeCallBack[current_client][0]), 0,
 	 sizeof(RealModeCallBack)*0x10);
   dpmi_stack_frame[current_client].eip	= my_ip;
@@ -1570,6 +1570,8 @@
   dpmi_stack_frame[current_client].edi = REG(edi);
   dpmi_stack_frame[current_client].ebp = REG(ebp);
 
+  if (in_dpmi>1) return; /* return immediately to the main loop */
+
   for (; (!fatalerr && in_dpmi) ;) {
     run_dpmi();
     run_irqs();
@@ -1595,10 +1597,16 @@
 void dpmi_sigio(struct sigcontext_struct *scp)
 {
   if (_cs != UCODESEL){
+#if 0
     if (dpmi_eflags & IF) {
       D_printf("DPMI: return to dosemu code for handling signals\n");
       Return_to_dosemu_code(scp);
-   } else dpmi_eflags |= VIP;
+    } else dpmi_eflags |= VIP;
+#else
+/* DANG_FIXTHIS We shouldn't return to dosemu code if IF=0, but it helps - WHY? */
+    D_printf("DPMI: return to dosemu code for handling signals\n");
+    Return_to_dosemu_code(scp);
+#endif
   }
 }
 
@@ -2161,6 +2169,16 @@
     restore_rm_regs();
     in_dpmi_dos_int = 0;
 
+#ifdef BCC_HACK    
+  } else if (lina == (unsigned char *) (DPMI_ADD + HLT_OFF(DPMI_return_from_dos_exec))) {
+
+    D_printf("BCC: Return from DOS exec\n");
+    bcc_post_exec();
+
+    restore_rm_regs();
+    in_dpmi_dos_int = 0;
+
+#endif
   } else if ((lina>=(unsigned char *)(DPMI_ADD + HLT_OFF(DPMI_return_from_dosint))) &&
 	     (lina <(unsigned char *)(DPMI_ADD + HLT_OFF(DPMI_return_from_dosint)+256)) ) {
     int intr = (int)(lina) - DPMI_ADD-HLT_OFF(DPMI_return_from_dosint);
diff -u --recursive --new-file dosemu0.53pl47/dpmi/dpmi.h dosemu0.53pl48/dpmi/dpmi.h
--- dosemu0.53pl47/dpmi/dpmi.h	Mon Feb 27 19:27:55 1995
+++ dosemu0.53pl48/dpmi/dpmi.h	Tue Mar  7 18:52:36 1995
@@ -68,7 +68,7 @@
     unsigned int	used;		/* Segment in use by client # */
 } SEGDESC;
 
-#define MAX_SELECTORS	0x0400
+#define MAX_SELECTORS	0x0800
 #define MODIFY_LDT_CONTENTS_DATA        0
 #define MODIFY_LDT_CONTENTS_STACK       1
 #define MODIFY_LDT_CONTENTS_CODE        2
diff -u --recursive --new-file dosemu0.53pl47/emu.c dosemu0.53pl48/emu.c
--- dosemu0.53pl47/emu.c	Sat Feb 25 18:38:10 1995
+++ dosemu0.53pl48/emu.c	Tue Mar  7 18:21:06 1995
@@ -496,6 +496,7 @@
 #include <limits.h>
 #include <getopt.h>
 #include <assert.h>
+#include <linux/vt.h>
 
 #include <linux/fd.h>
 #include <linux/hdreg.h>
@@ -902,7 +903,7 @@
     run_irqs();      /*  trigger any hardware interrupts requested */
 #endif
     serial_run();
-#if 1
+#if 0
 #ifdef USING_NET
     /* check for available packets on the packet driver interface */
     /* (timeout=0, so it immediately returns when none are available) */
@@ -1135,3 +1136,73 @@
     not_use_sigio++;
   }
 }
+
+#if 1
+int
+do_ioctl(int fd, int req, int param3)
+{
+  int tmp;
+
+  if (in_sighandler && in_ioctl) {
+    k_printf("KBD: do_ioctl(): in ioctl %d 0x%04x 0x%04x.\nqueuing: %d 0x%04x 0x%04x\n",
+	     curi.fd, curi.req, curi.param3, fd, req, param3);
+    queue_ioctl(fd, req, param3);
+    errno = EDEADLOCK;
+#ifdef SYNC_ALOT
+    fflush(stdout);
+    sync();			/* for safety */
+#endif
+    return -1;
+  }
+  else {
+    in_ioctl = 1;
+    curi.fd = fd;
+    curi.req = req;
+    curi.param3 = param3;
+    if (iq.queued) {
+      k_printf("KBD: detected queued ioctl in do_ioctl(): %d 0x%04x 0x%04x\n",
+	       iq.fd, iq.req, iq.param3);
+    }
+    k_printf("KBD: IOCTL fd=0x%x, req=0x%x, param3=0x%x\n", fd, req, param3);
+    tmp = ioctl(fd, req, param3);
+    in_ioctl = 0;
+    return tmp;
+  }
+}
+
+int
+queue_ioctl(int fd, int req, int param3)
+{
+  if (iq.queued) {
+    error("ioctl already queued: %d 0x%04x 0x%04x\n", iq.fd, iq.req,
+	  iq.param3);
+    return 1;
+  }
+  iq.fd = fd;
+  iq.req = req;
+  iq.param3 = param3;
+  iq.queued = 1;
+
+  return 0;			/* success */
+}
+
+void
+do_queued_ioctl(void)
+{
+  if (iq.queued) {
+    iq.queued = 0;
+    do_ioctl(iq.fd, iq.req, iq.param3);
+  }
+}
+
+void
+activate(int con_num)
+{
+  if (in_ioctl) {
+    k_printf("KBD: can't ioctl for activate, in a signal handler\n");
+    do_ioctl(kbd_fd, VT_ACTIVATE, con_num);
+  }
+  else
+    do_ioctl(kbd_fd, VT_ACTIVATE, con_num);
+}
+#endif
diff -u --recursive --new-file dosemu0.53pl47/include/bios.h dosemu0.53pl48/include/bios.h
--- dosemu0.53pl47/include/bios.h	Fri Mar  3 18:06:34 1995
+++ dosemu0.53pl48/include/bios.h	Tue Mar  7 21:32:49 1995
@@ -234,6 +234,7 @@
 void DPMI_dummy_end();
 void DPMI_dpmi_init();
 void DPMI_return_from_dos();
+void DPMI_return_from_dos_exec(); /* for bcc.h */
 void DPMI_return_from_dosint();
 void DPMI_return_from_realmode();
 void DPMI_return_from_dos_memory();
diff -u --recursive --new-file dosemu0.53pl47/include/disks.h dosemu0.53pl48/include/disks.h
--- dosemu0.53pl47/include/disks.h	Fri Mar  3 18:06:34 1995
+++ dosemu0.53pl48/include/disks.h	Tue Mar  7 21:32:49 1995
@@ -1,9 +1,12 @@
 /* for Linux DOS emulator
  *   Robert Sanders, gt8134b@prism.gatech.edu
+ * $Id$
+ *
  */
 #ifndef DISKS_H
 #define DISKS_H
 
+#include "extern.h"
 #define PART_INFO_START		0x1be	/* offset in MBR for partition table */
 #define PART_INFO_LEN   	0x10	/* size of each partition record */
 #define PART_SIG		0x55aa	/* magic signature */
@@ -47,6 +50,7 @@
   struct partition part_info;	/* neato partition info */
 };
 
+#if 0
 /* NOTE: the "header" element in the structure above can (and will) be
  * negative. This facilitates treating partitions as disks (i.e. using
  * /dev/hda1 with a simulated partition table) by adjusting out the
@@ -58,11 +62,9 @@
   void (*setup) (struct disk *);
 };
 
-#ifndef DISKS_C
-extern
 #endif
-struct disk_fptr disk_fptrs[];
 
+
 /* this header appears only in hdimage files
  */
 struct image_header {
@@ -86,10 +88,28 @@
 #define MAX_HDISKS 8
 #define SECTOR_SIZE		512
 
-extern struct disk disktab[MAX_FDISKS];
-extern struct disk hdisktab[MAX_HDISKS];
-extern struct disk bootdisk;
-extern int use_bootdisk;
+/*
+ * Array of disk structures for floppies...
+ */ 
+EXTERN struct disk disktab[MAX_FDISKS];
+
+/*
+ * Array of disk structures for hard disks...
+ *
+ * Can be whole hard disks, dos extended partitions (containing one or
+ * more partitions) or their images (files)
+ */
+EXTERN struct disk hdisktab[MAX_HDISKS];
+
+/*
+ * Special bootdisk which can be temporarily swapped out for drive A,
+ * during the boot process.  The idea is to boot off the bootdisk, and
+ * then have the autoexec.bat swap out the boot disk for the "real"
+ * drive A.
+ */
+EXTERN struct disk bootdisk;
+
+EXTERN int use_bootdisk INIT(0);
 
 #if 1
 #define DISK_OFFSET(dp,h,s,t) \
diff -u --recursive --new-file dosemu0.53pl47/include/video.h dosemu0.53pl48/include/video.h
--- dosemu0.53pl47/include/video.h	Fri Mar  3 18:06:37 1995
+++ dosemu0.53pl48/include/video.h	Tue Mar  7 21:32:50 1995
@@ -6,6 +6,7 @@
 
 typedef struct { byte end, start; } cshape;
 
+extern void gettermcap(int);
 
 /* if you set this to 1, the video memory dirty bit will be checked 
    before updating the screen.
diff -u --recursive --new-file dosemu0.53pl47/init/Makefile dosemu0.53pl48/init/Makefile
--- dosemu0.53pl47/init/Makefile	Sat Feb 25 18:00:18 1995
+++ dosemu0.53pl48/init/Makefile	Tue Mar  7 21:23:12 1995
@@ -37,7 +37,7 @@
 	$(LEX) -i $< 
 
 clean::
-	-rm -f  parser.[ch] lex.yy.cc
+	-rm -f  parser.[ch] lex.yy.c
 # how do we generate dependcies?
 
 
diff -u --recursive --new-file dosemu0.53pl47/init/config.c dosemu0.53pl48/init/config.c
--- dosemu0.53pl47/init/config.c	Wed Mar  1 18:50:58 1995
+++ dosemu0.53pl48/init/config.c	Tue Mar  7 18:34:14 1995
@@ -17,6 +17,8 @@
 #include "bios.h"
 #include "kversion.h"
 
+#include "../dos2linux/dos2linux.h"
+
 /* XXX - the mem size of 734 is much more dangerous than 704.
  * 704 is the bottom of 0xb0000 memory.  use that instead?
  */
@@ -207,7 +209,7 @@
      
   opterr = 0;
   confname = CONFIG_FILE;
-  while ((c = getopt(argc, argv, "ABCcF:kM:D:P:VNtsgx:Km234e:dXY:Z:")) != EOF) {
+  while ((c = getopt(argc, argv, "ABCcF:kM:D:P:VNtsgx:Km234e:E:dXY:Z:")) != EOF) {
 	  switch (c) {
 	  case 'F':
 		  confname = optarg;
@@ -230,7 +232,7 @@
 
   optind = 0;
   opterr = 0;
-  while ((c = getopt(argc, argv, "ABCcF:kM:D:P:v:VNtT:sgx:Km234e:dXY:Z:")) != EOF) {
+  while ((c = getopt(argc, argv, "ABCcF:kM:D:P:v:VNtT:sgx:Km234e:dXY:Z:E:")) != EOF) {
     switch (c) {
     case 'F':			/* previously parsed config file argument */
     case 'd':
@@ -364,6 +366,11 @@
     case '4':
       g_printf("CPU set to 486\n");
       vm86s.cpu_type = CPU_486;
+      break;
+
+    case 'E':
+      g_printf("DOS command given on command line\n");
+      misc_e6_store_command (optarg);
       break;
 
     case '?':
diff -u --recursive --new-file dosemu0.53pl47/init/init.c dosemu0.53pl48/init/init.c
--- dosemu0.53pl47/init/init.c	Wed Mar  1 19:16:48 1995
+++ dosemu0.53pl48/init/init.c	Sun Mar  5 21:50:18 1995
@@ -456,6 +456,7 @@
     error("ERROR: can't open keyboard\n");
     leavedos(19);
   }
+  keyboard_flags_init();
   if (!config.vga)
     config.allowvideoportaccess = 0;
  
diff -u --recursive --new-file dosemu0.53pl47/keyboard/Makefile dosemu0.53pl48/keyboard/Makefile
--- dosemu0.53pl47/keyboard/Makefile	Sun Feb  5 12:53:37 1995
+++ dosemu0.53pl48/keyboard/Makefile	Tue Mar  7 21:31:54 1995
@@ -10,7 +10,7 @@
 XOBJS  = Xkeyb.o
 endif
 
-CFILES = keymaps.c keyboard.c 
+CFILES = keymaps.c keyboard.c
 DEPENDS= keymaps.d keyboard.d
 HFILES = 
 # XSRC   = XKeyb.c
@@ -19,11 +19,11 @@
 
 # Insert all source- and header-files here.
 
-ALL = $(CFILES) $(HFILES) $(XFILES) slang-keyboard.c
+ALL = $(CFILES) $(HFILES) $(XFILES) slang-keyboard.c keyboard-server.c keyboard-client.c Makefile.john
 
 # All object-files are included here.
 
-OBJS = keymaps.o keyboard.o $(XOBJS)
+OBJS = keymaps.o keyboard.o $(XOBJS) 
 
 
 all: lib
diff -u --recursive --new-file dosemu0.53pl47/keyboard/Makefile.john dosemu0.53pl48/keyboard/Makefile.john
--- dosemu0.53pl47/keyboard/Makefile.john
+++ dosemu0.53pl48/keyboard/Makefile.john	Tue Mar  7 21:24:40 1995
@@ -0,0 +1,33 @@
+#
+# This is the Makefile for the keyboard-subdirectory of the DOS-emulator
+# for Linux.
+#
+
+SUBDIR=keyboard
+
+ifdef X_SUPPORT
+XFILES = Xkeyb.c
+XOBJS  = Xkeyb.o
+endif
+
+CFILES = keymaps.c keyboard-server.c keyboard-client.c
+DEPENDS= keymaps.d keyboard-server.d keyboard-client.d
+HFILES = 
+# XSRC   = XKeyb.c
+
+CFLAGS+= $(USE_SLANG)
+
+# Insert all source- and header-files here.
+
+ALL = $(CFILES) $(HFILES) $(XFILES) slang-keyboard.c
+
+# All object-files are included here.
+
+OBJS = keymaps.o keyboard-server.o keyboard-client.o $(XOBJS) 
+
+
+all: lib
+
+install:
+
+include ../Makefile.common
diff -u --recursive --new-file dosemu0.53pl47/keyboard/Xkeyb.c dosemu0.53pl48/keyboard/Xkeyb.c
--- dosemu0.53pl47/keyboard/Xkeyb.c	Sat Feb 25 18:38:30 1995
+++ dosemu0.53pl48/keyboard/Xkeyb.c	Sun Mar  5 20:27:25 1995
@@ -175,15 +175,15 @@
    X_printf("put_key(0x%X,'%c'=%d)\n",scan,charcode>=0x20?charcode:'?',charcode);
    
    if (charcode!=-1) {
-      DOS_setscan((charcode<<8) | scan);
+      add_scancode_to_queue((charcode<<8) | scan);
    }
    else {
       if (scan & 0xFF00) {
 	 child_set_flags(scan>>8);
-	 DOS_setscan(scan>>8);
+	 add_scancode_to_queue(scan>>8);
       } 
       child_set_flags(scan&0xff);
-      DOS_setscan(scan&0xff);
+      add_scancode_to_queue(scan&0xff);
    }
 }
 
@@ -200,7 +200,7 @@
    while (scan) {
       code = released ? (scan & 0xff) | 0x80 : (scan & 0xff);
       child_set_flags(code);
-      DOS_setscan(code);
+      add_scancode_to_queue(code);
       scan >>= 8;	 
    }
 }
diff -u --recursive --new-file dosemu0.53pl47/keyboard/keyboard-client.c dosemu0.53pl48/keyboard/keyboard-client.c
--- dosemu0.53pl47/keyboard/keyboard-client.c
+++ dosemu0.53pl48/keyboard/keyboard-client.c	Tue Mar  7 19:51:52 1995
@@ -0,0 +1,565 @@
+/* dosmemulator, Matthias Lautner 
+ * 
+ * DANG_BEGIN_MODULE
+ *
+ * This handles the keyboard.
+ *
+ * Two keyboard modes are handled 'raw' and 'xlate'. 'Raw' works with
+ * codes as sent out by the kernel and 'xlate' uses plain ASCII as used over
+ * serial lines. The mapping for different languages & the two ALT-keys is
+ * done here, but the definitions are elsewhere. Only the default (US)
+ * keymap is stored here.
+ *
+ * DANG_END_MODULE
+ *
+ *
+ * DANG_BEGIN_CHANGELOG
+ *
+ * $Date: $
+ * $Source: $
+ * $Revision:$
+ * $State: $
+ * $Log: $
+ * DANG_END_CHANGELOG
+ */
+
+#ifdef USE_SLANG
+#define USE_SLANG_KEYS
+#endif
+
+#include <unistd.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <linux/vt.h>
+#include <linux/kd.h>
+#include <linux/time.h>
+#include <sys/stat.h>
+
+#include "emu.h"
+#include "memory.h"
+#include "termio.h"
+#include "shared.h"
+#include "vc.h"
+
+static int tty_raw(int);
+inline void child_set_flags(int);
+static void keyboard_handling_init(void);
+static void clear_raw_mode();
+extern void clear_console_video();
+extern void clear_consoleX_video();
+extern void clear_process_control();
+static void set_raw_mode();
+void set_leds();
+extern void set_leds_area();
+extern void add_scancode_to_queue(u_short);
+extern void activate(int);
+extern int terminal_initialize();
+extern void terminal_close();
+void convascii(int *);
+
+static unsigned int queue;
+
+#define put_queue(psc) (queue = psc)
+
+void getKeys();
+
+void child_set_flags(int sc);
+
+void child_set_kbd_flag(int),
+ child_clr_kbd_flag(int);
+int child_kbd_flag(int);
+extern int kbd_flag(int); 
+
+/* initialize these in keyboard_init()! */
+unsigned int child_kbd_flags = 0;
+
+static int altchar = 0;
+
+static int  old_kbd_flags = -1;		/* flags for STDIN before our fcntl */
+
+int kbcount = 0;
+unsigned char kbbuf[KBBUF_SIZE], *kbp, erasekey;
+static struct termios oldtermios;	/* original terminal modes */
+
+#if 0
+int
+do_ioctl(int fd, int req, int param3)
+{
+  int tmp;
+
+  if (in_sighandler && in_ioctl) {
+    k_printf("KBD: do_ioctl(): in ioctl %d 0x%04x 0x%04x.\nqueuing: %d 0x%04x 0x%04x\n",
+	     curi.fd, curi.req, curi.param3, fd, req, param3);
+    queue_ioctl(fd, req, param3);
+    errno = EDEADLOCK;
+#ifdef SYNC_ALOT
+    fflush(stdout);
+    sync();			/* for safety */
+#endif
+    return -1;
+  }
+  else {
+    in_ioctl = 1;
+    curi.fd = fd;
+    curi.req = req;
+    curi.param3 = param3;
+    if (iq.queued) {
+      k_printf("KBD: detected queued ioctl in do_ioctl(): %d 0x%04x 0x%04x\n",
+	       iq.fd, iq.req, iq.param3);
+    }
+    k_printf("KBD: IOCTL fd=0x%x, req=0x%x, param3=0x%x\n", fd, req, param3);
+    tmp = ioctl(fd, req, param3);
+    in_ioctl = 0;
+    return tmp;
+  }
+}
+
+int
+queue_ioctl(int fd, int req, int param3)
+{
+  if (iq.queued) {
+    error("ioctl already queued: %d 0x%04x 0x%04x\n", iq.fd, iq.req,
+	  iq.param3);
+    return 1;
+  }
+  iq.fd = fd;
+  iq.req = req;
+  iq.param3 = param3;
+  iq.queued = 1;
+
+  return 0;			/* success */
+}
+
+void
+do_queued_ioctl(void)
+{
+  if (iq.queued) {
+    iq.queued = 0;
+    do_ioctl(iq.fd, iq.req, iq.param3);
+  }
+}
+
+void
+activate(int con_num)
+{
+  if (in_ioctl) {
+    k_printf("KBD: can't ioctl for activate, in a signal handler\n");
+    do_ioctl(kbd_fd, VT_ACTIVATE, con_num);
+  }
+  else
+    do_ioctl(kbd_fd, VT_ACTIVATE, con_num);
+}
+#endif
+
+void
+keyboard_close(void)
+{
+  if (kbd_fd != -1) {
+
+    if (config.console_keyb) {
+      k_printf("KBD: keyboard_close:clear raw keyb\n");
+      clear_raw_mode();
+    }
+    if (config.console_video) {
+      k_printf("KBD: keyboard_close:clear console video\n");
+      clear_console_video();
+    }
+    if (config.usesX) {
+      v_printf("CloseKeyboard:clear console video\n");
+      clear_consoleX_video();
+    }
+
+    if ((config.console_keyb || config.console_video) && !config.usesX) {
+      k_printf("KBD: keyboard_close: clear process control\n");
+      clear_process_control();
+    }
+
+    fcntl(kbd_fd, F_SETFL, old_kbd_flags);
+    tcsetattr(kbd_fd, TCSANOW, &oldtermios);
+
+    close(kbd_fd);
+    kbd_fd = -1;
+  }
+}
+
+static struct termios save_termios;
+
+static void
+print_termios(struct termios term)
+{
+  k_printf("KBD: TERMIOS Structure:\n");
+  k_printf("KBD: 	c_iflag=%x\n", term.c_iflag);
+  k_printf("KBD: 	c_oflag=%x\n", term.c_oflag);
+  k_printf("KBD: 	c_cflag=%x\n", term.c_cflag);
+  k_printf("KBD: 	c_lflag=%x\n", term.c_lflag);
+  k_printf("KBD: 	c_line =%x\n", term.c_line);
+}
+
+extern void scr_state_init(void);
+
+/*
+ * DANG_BEGIN_FUNCTION keyboard_init
+ *
+ * description:
+ *  Initialize the keyboard to DOSEMU deafaults plus those requested
+ *  in the configs if allowable.
+ *
+ * DANG_END_FUNCTION
+ */
+int
+keyboard_init(void)
+{
+  struct termios newtermio;	/* new terminal modes */
+  struct stat chkbuf;
+  int major, minor;
+
+  if (!config.X) {
+     if (config.usesX) {
+	kbd_fd = dup(keypipe);
+     }
+     else {
+	kbd_fd = STDIN_FILENO;
+     }
+
+     if (kbd_fd < 0) {
+	error("ERROR: Couldn't duplicate STDIN !\n");
+	return -1;
+     }
+     
+     old_kbd_flags = fcntl(kbd_fd, F_GETFL);
+     fcntl(kbd_fd, F_SETFL, O_RDONLY | O_NONBLOCK);
+     
+     if (use_sigio && !config.kbd_tty) {
+       k_printf("KBD: Using SIGIO\n");
+       add_to_io_select(kbd_fd, 1);
+     } else {
+       k_printf("KBD: Not using SIGIO\n");
+       add_to_io_select(kbd_fd, 0);
+     }
+
+     fstat(kbd_fd, &chkbuf);
+     major = chkbuf.st_rdev >> 8;
+     minor = chkbuf.st_rdev & 0xff;
+  } else
+     major = minor = 0;
+
+  scr_state_init();
+
+  if (!config.usesX) {
+    /* console major num is 4, minor 64 is the first serial line */
+    if ((major == 4) && (minor < 64))
+      scr_state.console_no = minor;	/* get minor number */
+    else {
+      if (config.console_keyb || config.console_video)
+	error("ERROR: STDIN not a console-can't do console modes!\n");
+      scr_state.console_no = 0;
+      config.console_keyb = 0;
+      config.console_video = 0;
+      config.mapped_bios = 0;
+      config.vga = 0;
+      config.graphics = 0;
+      if (config.speaker == SPKR_NATIVE)
+        config.speaker = SPKR_EMULATED;
+    }
+  }
+  else {
+    scr_state.console_no = 0;
+  }
+
+  if (!config.X && tcgetattr(kbd_fd, &oldtermios) < 0) {
+    error("ERROR: Couldn't tcgetattr(STDIN,...) !\n");
+    /* close(kbd_fd); kbd_fd = -1; return -1; <------ XXXXXXX Remove this */
+  }
+
+/*
+ * DANG_BEGIN_REMARK
+ *
+ *  Code is called at start up to set up the terminal line for non-raw
+ *  mode.
+ *
+ * DANG_END_REMARK
+ */
+  if (!config.X) {
+     newtermio = oldtermios;
+     newtermio.c_iflag &= (ISTRIP | IGNBRK | IXON | IXOFF);	/* (IXON|IXOFF|IXANY|ISTRIP|IGNBRK);*/
+     /* newtermio.c_oflag &= ~OPOST;
+     newtermio.c_cflag &= ~(HUPCL); */
+     newtermio.c_cflag &= ~(CLOCAL | CSIZE | PARENB);
+     newtermio.c_cflag |= CS8;
+     newtermio.c_lflag &= 0;                  /* ISIG */
+     newtermio.c_cc[VMIN] = 1;
+     newtermio.c_cc[VTIME] = 0;
+     erasekey = newtermio.c_cc[VERASE];
+     cfgetispeed(&newtermio);
+     cfgetospeed(&newtermio);
+     if (tcsetattr(kbd_fd, TCSANOW, &newtermio) < 0) {
+	error("ERROR: Couldn't tcsetattr(STDIN,TCSANOW,...) !\n");
+     }
+  }
+  child_kbd_flags = 0;
+
+  keyboard_handling_init();
+
+  dbug_printf("TERMIO: $Header: /home/src/dosemu0.60/keyboard/RCS/keyboard.c,v 1.3 1995/02/25 22:38:32 root Exp root $\n");
+
+  return 0;
+}
+
+static void
+clear_raw_mode(void)
+{
+#ifdef X_SUPPORT
+   if (config.X)
+      return;
+#endif
+  do_ioctl(kbd_fd, KDSKBMODE, K_XLATE);
+  if (tcsetattr(kbd_fd, TCSAFLUSH, &save_termios) < 0) {
+    k_printf("KBD: Resetting Keyboard to K_XLATE mode failed.\n");
+    return;
+  }
+}
+
+static void
+set_raw_mode(void)
+{
+#ifdef X_SUPPORT
+   if (config.X)
+      return;
+#endif
+  k_printf("KBD: Setting keyboard to RAW mode\n");
+  if (!config.console_video)
+    fprintf(stderr, "\nKBD: Entering RAW mode for DOS!\n");
+  do_ioctl(kbd_fd, KDSKBMODE, K_RAW);
+  tty_raw(kbd_fd);
+}
+
+static int
+tty_raw(int fd)
+{
+  struct termios buf;
+
+#ifdef X_SUPPORT
+   if (config.X)
+      return 0;
+#endif
+  if (tcgetattr(fd, &save_termios) < 0)
+    return (-1);
+
+  buf = save_termios;
+
+  buf.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
+  buf.c_iflag &= ~(IMAXBEL | IGNBRK | IGNCR | IGNPAR | BRKINT | INLCR | ICRNL | INPCK | ISTRIP | IXON | IUCLC | IXANY | IXOFF | IXON);
+  buf.c_cflag &= ~(CSIZE | PARENB);
+  buf.c_oflag &= ~(OCRNL | OLCUC | ONLCR | OPOST);
+  buf.c_cflag |= CS8;
+  buf.c_cc[VMIN] = 1;
+  buf.c_cc[VTIME] = 0;
+
+  if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &buf) < 0) {
+    k_printf("KBD: Setting to RAW mode failed.\n");
+    return (-1);
+  }
+  if (tcgetattr(fd, &buf) < 0) {
+    k_printf("Termios ERROR\n");
+  }
+  k_printf("KBD: Setting TERMIOS Structure.\n");
+  print_termios(buf);
+
+  return (0);
+}
+
+void
+add_key_depress(u_short scan) {
+    if (scan < 0x80 && scan > 0) {
+      k_printf("Adding Key-Release\n");
+      add_scancode_to_queue(scan | 0x80);
+    }
+}
+
+#ifdef USE_SLANG_KEYS
+#include "slang-keyboard.c"
+#endif
+
+void
+getKeys(void)
+{
+  int cc;
+
+  if (config.console_keyb) {	/* Keyboard at the console */
+    if (scr_state.current != 1) {
+	k_printf("KBD: Not current screen!\n");
+	return;
+    }
+    kbcount = 0;
+    kbp = kbbuf;
+
+    cc = RPT_SYSCALL(read(kbd_fd, &kbp[kbcount], KBBUF_SIZE - 1));
+    k_printf("KBD: cc found %d characters (Raw)\n", cc);
+    if (cc == -1)
+      return;
+
+    if (cc > 0) {
+      int i;
+
+      for (i = 0; i < cc; i++) {
+	k_printf("KEY: readcode: %d \n", kbp[kbcount + i]);
+	child_set_flags(kbp[kbcount + i]);
+	add_scancode_to_queue(kbp[kbcount + i]);
+	k_printf("KBD: cc pushing %d'th character\n", i);
+      }
+    }
+  }
+  else {			/* Not keyboard at the console (not config.console_keyb) */
+     do_slang_getkeys ();
+  }
+}
+
+void
+child_set_flags(int sc)
+{
+  switch (sc) {
+  case 0xe0:
+  case 0xe1:
+    child_set_kbd_flag(4);
+    return;
+  case 0x2a:
+    if (!child_kbd_flag(4))
+      child_set_kbd_flag(1);
+    child_clr_kbd_flag(4);
+    return;
+  case 0x36:
+    child_set_kbd_flag(1);
+    child_clr_kbd_flag(4);
+    return;
+  case 0x1d:
+  case 0x10:
+    child_set_kbd_flag(2);
+    child_clr_kbd_flag(4);
+    return;
+  case 0x38:
+    if (!child_kbd_flag(4))
+      child_set_kbd_flag(3);
+    child_clr_kbd_flag(4);
+    return;
+  case 0xaa:
+    if (!child_kbd_flag(4))
+      child_clr_kbd_flag(1);
+    child_clr_kbd_flag(4);
+    return;
+  case 0xb6:
+    child_clr_kbd_flag(4);
+    child_clr_kbd_flag(1);
+    return;
+  case 0x9d:
+  case 0x90:
+    child_clr_kbd_flag(4);
+    child_clr_kbd_flag(2);
+    return;
+  case 0xb8:
+    child_clr_kbd_flag(3);
+    child_clr_kbd_flag(4);
+    return;
+  case 0x3b:
+  case 0x3c:
+  case 0x3d:
+  case 0x3e:
+  case 0x3f:
+  case 0x40:
+  case 0x41:
+  case 0x42:
+  case 0x43:
+  case 0x44:
+  case 0x57:
+  case 0x58:
+    child_clr_kbd_flag(4);
+    if ( !config.X && 
+	 (child_kbd_flag(3) && child_kbd_flag(2) && !child_kbd_flag(1)) ) {
+      int fnum = sc - 0x3a;
+
+      k_printf("KDB: Doing VC switch\n");
+      if (fnum > 10)
+	fnum -= 0x12;		/* adjust if f11 or f12 */
+
+/* can't just do the ioctl() here, as ReadKeyboard will probably have
+ * been called from a signal handler, and ioctl() is not reentrant.
+ * hence the delay until out of the signal handler...
+ */
+      child_clr_kbd_flag(3);
+      child_clr_kbd_flag(2);
+      activate(fnum);
+      return;
+    }
+    return;
+  case 0x51:
+    if ( !config.X &&
+	 (child_kbd_flag(2) && child_kbd_flag(3) && !child_kbd_flag(1)) ) {
+      dbug_printf("ctrl-alt-pgdn\n");
+      leavedos(42);
+    }
+    child_clr_kbd_flag(4);
+    return;
+  default:
+    child_clr_kbd_flag(4);
+    return;
+  }
+}
+
+static void
+keyboard_handling_init(void)
+{
+  scr_state.current = 1;
+
+  if (config.console_keyb) {
+    set_raw_mode();
+  }
+
+  if (config.X)
+     return;
+  if (-1 == init_slang_keymaps ())
+    {
+       error ("ERROR: Unable to initialize S-Lang keymaps.\n");
+       leavedos (31);
+    }
+}
+
+void
+set_leds()
+{
+  unsigned int led_state = 0;
+
+  if (kbd_flag(KF_SCRLOCK)) {
+    led_state |= (1 << LED_SCRLOCK);
+  }
+  if (kbd_flag(KF_NUMLOCK)) {
+    led_state |= (1 << LED_NUMLOCK);
+  }
+  if (kbd_flag(KF_CAPSLOCK)) {
+    led_state |= (1 << LED_CAPSLOCK);
+  }
+
+  k_printf("KBD: SET_LEDS() called\n");
+  do_ioctl(kbd_fd, KDSETLED, led_state);
+}
+
+/* These are added to allow the CHILD process to keep its own flags on keyboard
+   status */
+
+void
+child_set_kbd_flag(int flag)
+{
+  child_kbd_flags |= (1 << flag);
+}
+
+void
+child_clr_kbd_flag(int flag)
+{
+  child_kbd_flags &= ~(1 << flag);
+}
+
+int
+child_kbd_flag(int flag)
+{
+  return ((child_kbd_flags >> flag) & 1);
+}
+
diff -u --recursive --new-file dosemu0.53pl47/keyboard/keyboard-server.c dosemu0.53pl48/keyboard/keyboard-server.c
--- dosemu0.53pl47/keyboard/keyboard-server.c
+++ dosemu0.53pl48/keyboard/keyboard-server.c	Sun Mar  5 23:37:43 1995
@@ -0,0 +1,1036 @@
+/* dosmemulator, Matthias Lautner
+ *
+ * DANG_BEGIN_MODULE
+ *
+ * This handles the keyboard.
+ *
+ * Two keyboard modes are handled 'raw' and 'xlate'. 'Raw' works with
+ * codes as sent out by the kernel and 'xlate' uses plain ASCII as used over
+ * serial lines. The mapping for different languages & the two ALT-keys is
+ * done here, but the definitions are elsewhere. Only the default (US)
+ * keymap is stored here.
+ *
+ * DANG_END_MODULE
+ *
+ *
+ * DANG_BEGIN_CHANGELOG
+ *
+ * $$
+ * $Source:$
+ * $Revision:$
+ * $State:$
+ * $Log: $
+ * DANG_END_CHANGELOG
+ */
+
+#include <linux/kd.h>
+
+#include "emu.h"
+#include "memory.h"
+#include "termio.h"
+#include "shared.h"
+#include "dosio.h"
+#include "mouse.h"
+#include "bios.h"
+#include "../timer/pic.h"
+
+static unsigned int convscanKey (unsigned char);
+void dump_kbuffer (void);
+void read_next_scancode_from_queue (void);
+void convascii (int *);
+unsigned int convscanKey (unsigned char);
+
+/* Was a toggle key already port in'd */
+static u_char ins_stat = 0;
+static u_char scroll_stat = 0;
+static u_char num_stat = 0;
+static u_char caps_stat = 0;
+
+static unsigned int queue;
+#define put_queue(psc) (queue = psc)
+
+static void sysreq (unsigned int), ctrl (unsigned int), alt (unsigned int),
+  Unctrl (unsigned int), unalt (unsigned int), lshift (unsigned int), unlshift (unsigned int),
+  rshift (unsigned int), unrshift (unsigned int), caps (unsigned int),
+  uncaps (unsigned int), ScrollLock (unsigned int), unscroll (unsigned int),
+  num (unsigned int), unnum (unsigned int), unins (unsigned int), do_self (unsigned int),
+  cursor (unsigned int), func (unsigned int), slash (unsigned int), star (unsigned int),
+  enter (unsigned int), minus (unsigned int), plus (unsigned int), backspace (unsigned int),
+  Tab (unsigned int), none (unsigned int), spacebar (unsigned int);
+
+void set_leds_area (void);
+
+void set_kbd_flag (int), clr_kbd_flag (int), chg_kbd_flag (int),
+  set_key_flag (int), clr_key_flag (int), chg_key_flag (int);
+int kbd_flag (int), key_flag (int);
+
+static int altchar = 0;
+
+typedef void (*fptr) (unsigned int);
+static const fptr key_table[] =
+{
+  none, do_self, do_self, do_self,	/* 00-03 s0 esc 1 2 */
+  do_self, do_self, do_self, do_self,	/* 04-07 3 4 5 6 */
+  do_self, do_self, do_self, do_self,	/* 08-0B 7 8 9 0 */
+  do_self, do_self, backspace, Tab,	/* 0C-0F + ' bs tab */
+  do_self, do_self, do_self, do_self,	/* 10-13 q w e r */
+  do_self, do_self, do_self, do_self,	/* 14-17 t y u i */
+  do_self, do_self, do_self, do_self,	/* 18-1B o p } ^ */
+  enter, ctrl, do_self, do_self,/* 1C-1F enter ctrl a s */
+  do_self, do_self, do_self, do_self,	/* 20-23 d f g h */
+  do_self, do_self, do_self, do_self,	/* 24-27 j k l | */
+  do_self, do_self, lshift, do_self,	/* 28-2B { para lshift , */
+  do_self, do_self, do_self, do_self,	/* 2C-2F z x c v */
+  do_self, do_self, do_self, do_self,	/* 30-33 b n m , */
+  do_self, slash, rshift, star,	/* 34-37 . / rshift * */
+  alt, spacebar, caps, func,	/* 38-3B alt sp caps f1 */
+  func, func, func, func,	/* 3C-3F f2 f3 f4 f5 */
+  func, func, func, func,	/* 40-43 f6 f7 f8 f9 */
+  func, num, ScrollLock, cursor,/* 44-47 f10 num scr home */
+  cursor, cursor, minus, cursor,/* 48-4B up pgup - left */
+  cursor, cursor, plus, cursor,	/* 4C-4F n5 right + end */
+  cursor, cursor, cursor, cursor,	/* 50-53 dn pgdn ins del */
+  sysreq, none, do_self, func,	/* 54-57 sysreq ? < f11 */
+  func, none, none, none,	/* 58-5B f12 ? ? ? */
+  none, none, none, none,	/* 5C-5F ? ? ? ? */
+  none, none, none, none,	/* 60-63 ? ? ? ? */
+  none, none, none, none,	/* 64-67 ? ? ? ? */
+  none, none, none, none,	/* 68-6B ? ? ? ? */
+  none, none, none, none,	/* 6C-6F ? ? ? ? */
+  none, none, none, none,	/* 70-73 ? ? ? ? */
+  none, none, none, none,	/* 74-77 ? ? ? ? */
+  none, none, none, none,	/* 78-7B ? ? ? ? */
+  none, none, none, none,	/* 7C-7F ? ? ? ? */
+  none, none, none, none,	/* 80-83 ? br br br */
+  none, none, none, none,	/* 84-87 br br br br */
+  none, none, none, none,	/* 88-8B br br br br */
+  none, none, none, none,	/* 8C-8F br br br br */
+  none, none, none, none,	/* 90-93 br br br br */
+  none, none, none, none,	/* 94-97 br br br br */
+  none, none, none, none,	/* 98-9B br br br br */
+  none, Unctrl, none, none,	/* 9C-9F br unctrl br br */
+  none, none, none, none,	/* A0-A3 br br br br */
+  none, none, none, none,	/* A4-A7 br br br br */
+  none, none, unlshift, none,	/* A8-AB br br unlshift br */
+  none, none, none, none,	/* AC-AF br br br br */
+  none, none, none, none,	/* B0-B3 br br br br */
+  none, none, unrshift, none,	/* B4-B7 br br unrshift br */
+  unalt, none, uncaps, none,	/* B8-BB unalt br uncaps br */
+  none, none, none, none,	/* BC-BF br br br br */
+  none, none, none, none,	/* C0-C3 br br br br */
+  none, unnum, unscroll, none,	/* C4-C7 br br br br */
+  none, none, none, none,	/* C8-CB br br br br */
+  none, none, none, none,	/* CC-CF br br br br */
+  none, none, unins, none,	/* D0-D3 br br unins br */
+  none, none, none, none,	/* D4-D7 br br br br */
+  none, none, none, none,	/* D8-DB br ? ? ? */
+  none, none, none, none,	/* DC-DF ? ? ? ? */
+  none, none, none, none,	/* E0-E3 e0 e1 ? ? */
+  none, none, none, none,	/* E4-E7 ? ? ? ? */
+  none, none, none, none,	/* E8-EB ? ? ? ? */
+  none, none, none, none,	/* EC-EF ? ? ? ? */
+  none, none, none, none,	/* F0-F3 ? ? ? ? */
+  none, none, none, none,	/* F4-F7 ? ? ? ? */
+  none, none, none, none,	/* F8-FB ? ? ? ? */
+  none, none, none, none	/* FC-FF ? ? ? ? */
+};
+
+
+void
+keybuf_clear (void)
+{
+  WRITE_WORD (KBD_HEAD, READ_WORD (KBD_START));
+  WRITE_WORD (KBD_TAIL, READ_WORD (KBD_START));
+  dump_kbuffer ();
+}
+
+/* InsKeyboard
+ *  returns 1 if a character could be inserted into Kbuffer
+ */
+static int
+InsKeyboard (unsigned short scancode)
+{
+  unsigned short nextpos;
+
+  /* First of all compute the position of the new tail pointer */
+  if ((nextpos = READ_WORD (KBD_TAIL) + 2) >= READ_WORD (KBD_END))
+    nextpos = READ_WORD (KBD_START);
+  if (nextpos == READ_WORD (KBD_HEAD))
+    {				/* queue full ? */
+      if (scancode == 0x2e03)
+	{
+	  keybuf_clear ();
+	  k_printf ("KBD: Buffer cleared for ctrl-break\n");
+	  WRITE_BYTE (0x471, 0x80);	/* ctrl-break flag */
+	  WRITE_WORD (BIOS_DATA_PTR (READ_WORD (KBD_START)), 0);
+	  return (1);
+	}
+      return (0);
+    }
+
+  WRITE_WORD (BIOS_DATA_PTR (READ_WORD (KBD_TAIL)), scancode);
+  WRITE_WORD (KBD_TAIL, nextpos);
+
+  return 1;
+}
+
+void
+dump_kbuffer (void)
+{
+  int i;
+  unsigned short *ptr = BIOS_DATA_PTR (READ_WORD (KBD_START));
+
+  k_printf ("KEYBUFFER DUMP: 0x%02x 0x%02x\n",
+	    READ_WORD (KBD_HEAD) - READ_WORD (KBD_START), READ_WORD (KBD_TAIL) - READ_WORD (KBD_START));
+  for (i = 0; i < 16; i++)
+    k_printf ("%04x ", (unsigned int) READ_WORD (ptr + i));
+  k_printf ("\n");
+}
+
+/***************************************************************
+ * this was copied verbatim from the Linux kernel (keyboard.c) *
+ * and then modified unscrupously by hackers on the team       *
+ ***************************************************************/
+
+static unsigned char resetid = 0;
+static unsigned char firstid = 0;
+
+static unsigned int
+convscanKey (unsigned char scancode)
+{
+  static unsigned char rep = 0xff;
+
+  k_printf ("KBD: convscanKey scancode = 0x%04x\n", scancode);
+
+  if (scancode == 0xe0)
+    {
+      set_key_flag (KKF_E0);
+      set_key_flag (KKF_FIRSTID);
+      set_key_flag (KKF_READID);
+      resetid = 1;
+      firstid = 0;
+    }
+  else if (scancode == 0xe1)
+    {
+      set_key_flag (KKF_E1);
+      set_key_flag (KKF_FIRSTID);
+      set_key_flag (KKF_READID);
+      resetid = 1;
+      firstid = 0;
+    }
+
+  if (scancode == 0xe0 || scancode == 0xe1)
+    return (0);
+  /*
+	 *  The keyboard maintains its own internal caps lock and num lock
+	 *  statuses. In caps lock mode E0 AA precedes make code and E0 2A
+	 *  follows break code. In num lock mode, E0 2A precedes make
+	 *  code and E0 AA follows break code. We do our own book-keeping,
+	 *  so we will just ignore these.
+	 */
+  if (key_flag (KKF_E0) && (scancode == 0x2a || scancode == 0xaa))
+    {
+      clr_key_flag (KKF_E0);
+      clr_key_flag (KKF_E1);
+      clr_key_flag (KKF_FIRSTID);
+      resetid = 0;
+      firstid = 0;
+      return (0);
+    }
+  /*
+	 *  Repeat a key only if the input buffers are empty or the
+	 *  characters get echoed locally. This makes key repeat usable
+	 *  with slow applications and unders heavy loads.
+	 */
+
+  rep = scancode;
+  queue = 0;
+  key_table[scancode] (scancode);
+
+  k_printf ("KBD: resetid = %d firstid = %d\n", resetid, firstid);
+  if (resetid)
+    {
+      if (firstid)
+	clr_key_flag (KKF_FIRSTID);
+      clr_key_flag (KKF_READID);
+      resetid = firstid = 0;
+    }
+
+  clr_key_flag (KKF_E0);
+  clr_key_flag (KKF_E1);
+
+  return (queue);
+}
+
+static void
+ctrl (unsigned int sc)
+{
+  if (key_flag (KKF_E0))
+    {
+      set_key_flag (KKF_RCTRL);
+    }
+  else
+    set_kbd_flag (EKF_LCTRL);
+
+  set_kbd_flag (KF_CTRL);
+}
+
+static void
+alt (unsigned int sc)
+{
+  if (key_flag (KKF_E0))
+    {
+      set_key_flag (KKF_RALT);
+    }
+  else
+    set_kbd_flag (EKF_LALT);
+
+  set_kbd_flag (KF_ALT);
+}
+
+static void
+Unctrl (unsigned int sc)
+{
+  if (key_flag (KKF_E0))
+    {
+      clr_key_flag (KKF_RCTRL);
+    }
+  else
+    clr_kbd_flag (EKF_LCTRL);
+
+  if (!kbd_flag (EKF_LCTRL) && !key_flag (KKF_RCTRL))
+    clr_kbd_flag (KF_CTRL);
+}
+
+static void
+unalt (unsigned int sc)
+{
+  /*  if (!resetid) { */
+  if (key_flag (KKF_E0))
+    {
+      clr_key_flag (KKF_RALT);
+    }
+  else
+    clr_kbd_flag (EKF_LALT);
+
+  if (!(kbd_flag (EKF_LALT) && key_flag (KKF_RALT)))
+    {
+      clr_kbd_flag (KF_ALT);
+
+      /* this is for hold-alt-and-keypad entry method */
+      if (altchar)
+	{
+	  /* perhaps anding with 0xff is incorrect.  how about
+		     * filtering out anything > 255?
+		     */
+	  put_queue (altchar & 0xff);	/* just the ASCII */
+	}
+      altchar = 0;
+    }
+  /* } */
+}
+
+static void
+lshift (unsigned int sc)
+{
+  set_kbd_flag (KF_LSHIFT);
+}
+
+static void
+unlshift (unsigned int sc)
+{
+  if (!resetid)
+    {
+      clr_kbd_flag (KF_LSHIFT);
+    }
+}
+
+static void
+rshift (unsigned int sc)
+{
+  set_kbd_flag (KF_RSHIFT);
+}
+
+static void
+unrshift (unsigned int sc)
+{
+  if (!resetid)
+    {
+      clr_kbd_flag (KF_RSHIFT);
+    }
+}
+
+static void
+caps (unsigned int sc)
+{
+  if (kbd_flag (KKF_RCTRL) && kbd_flag (EKF_LCTRL))
+    {
+      keyboard_mouse = keyboard_mouse ? 0 : 1;
+      m_printf ("MOUSE: toggled keyboard mouse %s\n",
+		keyboard_mouse ? "on" : "off");
+      return;
+    }
+  else
+    {
+      set_kbd_flag (EKF_CAPSLOCK);
+      if (!caps_stat)
+	{
+	  if (keepkey)
+	    {
+	      chg_kbd_flag (KF_CAPSLOCK);	/* toggle; this means SET/UNSET */
+	    }
+	  set_leds_area ();
+	  caps_stat = 1;
+	}
+    }
+}
+
+static void
+uncaps (unsigned int sc)
+{
+  if (!resetid)
+    {
+      clr_kbd_flag (EKF_CAPSLOCK);
+      caps_stat = 0;
+    }
+}
+
+static void
+sysreq (unsigned int sc)
+{
+  g_printf ("Regs requested: SYSREQ\n");
+  show_regs (__FILE__, __LINE__);
+}
+
+static void
+ScrollLock (unsigned int sc)
+{
+  if (key_flag (KKF_E0))
+    {
+      k_printf ("KBD: ctrl-break!\n");
+      WRITE_BYTE (0x471, 0x80);	/* ctrl-break flag */
+      WRITE_WORD (KBD_HEAD, READ_WORD (KBD_START));
+      WRITE_WORD (KBD_TAIL, READ_WORD (KBD_START));
+      WRITE_WORD (BIOS_DATA_PTR (READ_WORD (KBD_START)), 0);
+      return;
+    }
+  else if (kbd_flag (KKF_RCTRL))
+    show_ints (0, 0x33);
+  else if (kbd_flag (KKF_RALT))
+    show_regs (__FILE__, __LINE__);
+  else if (kbd_flag (KF_RSHIFT))
+    {
+      warn ("timer int 8 requested...\n");
+#ifdef NEW_PIC
+      pic_request (PIC_IRQ0);
+#else
+      do_hard_int (8);
+#endif
+    }
+  else if (kbd_flag (KF_LSHIFT))
+    {
+      warn ("keyboard int 9 requested...\n");
+      dump_kbuffer ();
+    }
+  else
+    {
+      set_kbd_flag (EKF_SCRLOCK);
+      if (!scroll_stat)
+	{
+	  if (keepkey)
+	    {
+	      chg_kbd_flag (KF_SCRLOCK);
+	    }
+	  set_leds_area ();
+	  scroll_stat = 1;
+	}
+    }
+}
+
+static void
+unscroll (unsigned int sc)
+{
+  clr_kbd_flag (EKF_SCRLOCK);
+  scroll_stat = 0;
+}
+
+static void
+num (unsigned int sc)
+{
+  static int lastpause = 0;
+
+  if (kbd_flag (EKF_LCTRL))
+    {
+      k_printf ("KBD: PAUSE!\n");
+      if (lastpause)
+	{
+	  I_printf ("KBD: waking server up!\n");
+#if 0
+	  dos_unpause ();
+#endif
+	  lastpause = 0;
+	}
+      else
+	{
+	  I_printf ("KBD: putting server to sleep!\n");
+#if 0
+	  dos_pause ();
+#endif
+	  lastpause = 1;
+	}
+    }
+  else
+    {
+      set_kbd_flag (EKF_NUMLOCK);
+      if (!num_stat)
+	{
+	  k_printf ("KBD: NUMLOCK!\n");
+	  if (keepkey)
+	    {
+	      chg_kbd_flag (KF_NUMLOCK);
+	    }
+	  k_printf ("KBD: kbd=%d\n", kbd_flag (KF_NUMLOCK));
+	  set_leds_area ();
+	  num_stat = 1;
+	}
+    }
+}
+
+static void
+unnum (unsigned int sc)
+{
+  num_stat = 0;
+  clr_kbd_flag (EKF_NUMLOCK);
+}
+
+void
+get_leds()
+{
+  unsigned int led_state = 0;
+
+  do_ioctl(kbd_fd, KDGETLED, (int) &led_state);
+
+  if (led_state & (1 << LED_SCRLOCK)) {
+    set_kbd_flag(KF_SCRLOCK);
+  }
+  else {
+    clr_kbd_flag(KF_SCRLOCK);
+  }
+  if (led_state & (1 << LED_NUMLOCK)) {
+    set_kbd_flag(KF_NUMLOCK);
+  }
+  else {
+    clr_kbd_flag(KF_NUMLOCK);
+  }
+  if (led_state & (1 << LED_CAPSLOCK)) {
+    set_kbd_flag(KF_CAPSLOCK);
+  }
+  else {
+    clr_kbd_flag(KF_CAPSLOCK);
+  }
+  k_printf("KBD: GET LEDS key 96 0x%02x, 97 0x%02x, kbc1 0x%02x, kbc2 0x%02x\n",
+	   READ_BYTE(0x496), READ_BYTE(0x497), READ_BYTE(0x417), READ_BYTE(0x418));
+}
+
+void
+keyboard_flags_init(void){
+    WRITE_WORD(KBDFLAG_ADDR, 0);
+    WRITE_WORD(KEYFLAG_ADDR, 0);
+    get_leds();
+    set_key_flag(KKF_KBD102);
+}
+
+void
+set_leds_area ()
+{
+  unsigned int led_state = 0;
+
+  if (kbd_flag (KF_SCRLOCK))
+    {
+      set_key_flag (KKF_SCRLOCK);
+    }
+  else
+    clr_key_flag (KKF_SCRLOCK);
+  if (kbd_flag (KF_NUMLOCK))
+    {
+      set_key_flag (KKF_NUMLOCK);
+    }
+  else
+    clr_key_flag (KKF_NUMLOCK);
+  if (kbd_flag (KF_CAPSLOCK))
+    {
+      set_key_flag (KKF_CAPSLOCK);
+    }
+  else
+    clr_key_flag (KKF_CAPSLOCK);
+
+  k_printf ("KBD: SET_LEDS_AREA() called\n");
+  if(config.console_keyb){
+	set_leds();
+  }
+}
+
+static void
+do_self (unsigned int sc)
+{
+  unsigned char ch;
+
+  if (kbd_flag (KF_ALT))
+    {
+      /* On a german keyboard the Left-Alt- (Alt-) and the Right-Alt-
+       (Alt-Gr-) Keys are different. The keys pressed with AltGr
+       return the codes defined in keymaps.c in the alt_map.
+       Pressed with the Left-Alt-Key they return the normal symbol
+       with the alt-modifier. I've tested this with the 4DOS-Alias-
+       Command.                  hein@tlaloc.in.tu-clausthal.de       */
+      if (config.keyboard == KEYB_DE_LATIN1)
+	{
+	  if (kbd_flag (EKF_LALT))	/* Left-Alt-Key pressed ?            */
+	    ch = config.alt_map[0];	/* Return Key with Alt-modifier      */
+	  else			/* otherwise (this is Alt-Gr)        */
+	    ch = config.alt_map[sc];	/* Return key from alt_map          */
+	}
+      else			/* or no DE_LATIN1-keyboard          */
+	ch = config.alt_map[sc];/* Return key from alt_map           */
+
+      if ((sc >= 2) && (sc <= 0xb))	/* numbers */
+	sc += 0x76;
+      else if (sc == 0xd)
+	sc = 0x83;		/* = */
+      else if (sc == 0xc)
+	sc = 0x82;		/* - */
+    }
+
+  else if (kbd_flag (KF_LSHIFT) || kbd_flag (KF_RSHIFT) ||
+	   kbd_flag (KF_CTRL))
+    ch = config.shift_map[sc];
+  else
+    ch = config.key_map[sc];
+
+  if (kbd_flag (KF_CTRL) || kbd_flag (KF_CAPSLOCK))
+    if ((ch >= 'a' && ch <= 'z') || (ch >= 224 && ch <= 254))
+      ch -= 32;
+
+  if (kbd_flag (KF_CTRL))	/* ctrl */
+    ch &= 0x1f;
+
+  k_printf ("KBD: sc=%02x, ch=%02x\n", sc, ch);
+
+  put_queue ((sc << 8) | ch);
+}
+
+static void
+spacebar (unsigned int sc)
+{
+  put_queue (0x3920);
+}
+
+/* 0x47-0x53, indexed by sc-0x47 , goes like:
+ * home, up, pgup, kp -, left, kp 5, right, kp +, end, down, pgdn, ins, del
+ */
+unsigned short ctrl_cursor[] =
+{
+  0x7700, 0x8d00, 0x8400, 0x8e00, 0x7300, 0x8f00, 0x7400,
+  0, 0x7500, 0x9100, 0x7600, 0x9200, 0x9300
+};
+
+unsigned short alt_cursor[] =
+{
+  0x9700, 0x9800, 0x9900, 0x4a00, 0x9b00, 0, 0x9d00, 0x4e00, 0x9f00, 0xa000,
+  0xa100, 0xa200, 0xa300
+};
+
+unsigned short shift_cursor[] =
+{
+  0x4737, 0x4838, 0x4939, 0x4a2d, 0x4b34, 0x0000, 0x4d36, 0x4e2b, 0x4f31,
+  0x5032, 0x5133, 0x5230, 0x532e
+};
+
+static void
+unins (unsigned int sc)
+{
+  ins_stat = 0;
+}
+
+static void
+cursor (unsigned int sc)
+{
+  int old_sc;
+
+  old_sc = sc;
+
+  if (sc < 0x47 || sc > 0x53)
+    return;
+
+  /* do dos_ctrl_alt_del on C-A-Del and C-A-PGUP */
+  if (kbd_flag (KF_CTRL) && kbd_flag (KF_ALT))
+    {
+      if (sc == 0x53 /*del*/  || sc == 0x49 /*pgup*/ )
+	dos_ctrl_alt_del ();
+      if (sc == 0x51)
+	{			/*pgdn*/
+	  k_printf ("KBD: ctrl-alt-pgdn taking her down!\n");
+	  leavedos (0);
+	}
+    }
+
+  /* if the arrow keys, or home end, do keyboard mouse */
+  if ((keyboard_mouse) && (sc == 0x50 || sc == 0x4b || sc == 0x48 ||
+			   sc == 0x4d || sc == 0x47 || sc == 0x4f))
+    {
+      mouse_keyboard (sc);
+      return;
+    }
+
+  if (sc == 0x52)
+    {
+      if (!ins_stat)
+	{
+	  chg_kbd_flag (KF_INSERT);
+	  ins_stat = 1;
+	}
+      else
+	return;
+    }
+
+  sc -= 0x47;
+
+  /* ENHANCED CURSOR KEYS:  only ctrl and alt may modify them.
+   */
+  if (key_flag (KKF_E0))
+    {
+      if (kbd_flag (KF_ALT))
+	put_queue (alt_cursor[sc]);
+      else if (kbd_flag (KF_CTRL))
+	put_queue (ctrl_cursor[sc]);
+      else
+	put_queue (old_sc << 8);
+      return;
+    }
+
+  /* everything below this must be a keypad key, as the check for KKF_E0
+   * above filters out enhanced cursor (gray) keys
+   */
+
+  /* this is the hold-alt-and-type numbers thing */
+  if (kbd_flag (KF_ALT))
+    {
+      int digit;
+
+      if ((digit = config.num_table[sc] - '0') <= 9)	/* is a number */
+	altchar = altchar * 10 + digit;
+    }
+  else if (kbd_flag (KF_CTRL))
+    put_queue (ctrl_cursor[sc]);
+  else if (kbd_flag (KF_NUMLOCK) || kbd_flag (KF_LSHIFT)
+	   || kbd_flag (KF_RSHIFT))
+    put_queue ((old_sc << 8) | config.num_table[sc]);
+  else
+    put_queue (old_sc << 8);
+}
+
+static void
+backspace (unsigned int sc)
+{
+  /* should be perfect */
+  if (kbd_flag (KF_CTRL))
+    put_queue (0x0e7f);
+  else if (kbd_flag (KF_ALT))
+    put_queue (0x0e00);
+  else
+    put_queue (0x0e08);
+}
+
+static void
+Tab (unsigned int sc)
+{
+  if (kbd_flag (KF_CTRL))
+    put_queue (0x9400);
+  else if (kbd_flag (KF_ALT))
+    put_queue (0xa500);
+  else if (kbd_flag (KF_LSHIFT) || kbd_flag (KF_RSHIFT))
+    put_queue (sc << 8);
+  else
+    put_queue (sc << 8 | config.key_map[sc]);
+}
+
+static void
+func (unsigned int sc)
+{
+  int fnum = sc - 0x3a;
+
+  if (fnum > 10)
+    fnum -= 0xc;		/* adjust if f11 or f12 */
+
+  /* this checks for the VC-switch key sequence */
+  if (kbd_flag (EKF_LALT) && !key_flag (KKF_RALT) && !kbd_flag (KF_RSHIFT)
+      && !kbd_flag (KF_LSHIFT) && kbd_flag (EKF_LCTRL))
+    {
+      clr_kbd_flag (EKF_LALT);
+      clr_kbd_flag (KF_ALT);
+      clr_kbd_flag (EKF_LCTRL);
+      clr_kbd_flag (KF_CTRL);
+      return;
+    }
+
+  /* FCH (Fkey CHoose):   returns a if n is f11 or f12, else it returns b
+ * PC scancodes for fkeys are "orthogonal" except F11 and F12.
+ */
+
+#define FCH(n,a,b) ((n <= 10) ? a : b)
+
+  k_printf ("KBD: sc=%x, fnum=%x\n", sc, fnum);
+
+  if (kbd_flag (KF_LSHIFT) || kbd_flag (KF_RSHIFT))
+    put_queue ((sc + FCH (fnum, 0x19, 0x30)) << 8);
+
+  else if (kbd_flag (KF_CTRL))
+    put_queue ((sc + FCH (fnum, 0x23, 0x32)) << 8);
+
+  else if (kbd_flag (KF_ALT))
+    put_queue ((sc + FCH (fnum, 0x2d, 0x34)) << 8);
+
+  else
+    put_queue (FCH (fnum, sc, (sc + 0x2e)) << 8);
+}
+
+static void
+slash (unsigned int sc)
+{
+  if (!key_flag (KKF_E0))
+    {
+      do_self (sc);
+    }
+  else
+    put_queue (sc << 8 | '/');
+}
+
+static void
+star (unsigned int sc)
+{
+  do_self (sc);
+}
+
+static void
+enter (unsigned int sc)
+{
+  if (kbd_flag (KF_CTRL))
+    put_queue (sc << 8 | 0x0a);
+  else if (kbd_flag (KF_ALT))
+    put_queue (0xa600);
+  else
+    put_queue (sc << 8 | 0x0d);
+}
+
+static void
+minus (unsigned int sc)
+{
+  do_self (sc);
+}
+
+static void
+plus (unsigned int sc)
+{
+  do_self (sc);
+}
+
+static void
+none (unsigned int sc)
+{
+}
+
+/**************** key-area-related functions **************/
+/* we  no longer ignore any changes a user program has made...this
+ * is good.  Now, we can let users mess around
+ * with our ALT flags, as we use no longer use those to change consoles.
+ */
+
+void
+set_kbd_flag (int flag)
+{
+  WRITE_WORD (KBDFLAG_ADDR, READ_WORD (KBDFLAG_ADDR) | (1 << flag));
+}
+
+void
+clr_kbd_flag (int flag)
+{
+  WRITE_WORD (KBDFLAG_ADDR, READ_WORD (KBDFLAG_ADDR) & ~(1 << flag));
+}
+
+void
+chg_kbd_flag (int flag)
+{
+  WRITE_WORD (KBDFLAG_ADDR, READ_WORD (KBDFLAG_ADDR) ^ (1 << flag));
+}
+
+int
+kbd_flag (int flag)
+{
+  return ((READ_WORD (KBDFLAG_ADDR) >> flag) & 1);
+}
+
+/* These are added to allow DOSEMU process to keep its own flags
+   on keyboard status */
+
+/* these are the KEY flags */
+void
+set_key_flag (int flag)
+{
+  WRITE_WORD (KEYFLAG_ADDR, READ_WORD (KEYFLAG_ADDR) | (1 << flag));
+}
+
+void
+clr_key_flag (int flag)
+{
+  WRITE_WORD (KEYFLAG_ADDR, READ_WORD (KEYFLAG_ADDR) & ~(1 << flag));
+}
+
+void
+chg_key_flag (int flag)
+{
+  WRITE_WORD (KEYFLAG_ADDR, READ_WORD (KEYFLAG_ADDR) ^ (1 << flag));
+}
+
+int
+key_flag (int flag)
+{
+  return ((READ_WORD (KEYFLAG_ADDR) >> flag) & 1);
+}
+
+/************* end of key-related functions *************/
+
+#define SCANQ_LEN 100
+static u_short *scan_queue;
+static int *scan_queue_start;
+static int *scan_queue_end;
+static int next_scancode;
+
+
+void
+shared_keyboard_init (void)
+{
+  (u_char *) scan_queue = shared_qf_memory + SHARED_KEYBOARD_OFFSET + 8;
+  (u_char *) scan_queue_start = shared_qf_memory + SHARED_KEYBOARD_OFFSET;
+  (u_char *) scan_queue_end = shared_qf_memory + SHARED_KEYBOARD_OFFSET + 4;
+  *scan_queue_start = 0;
+  *scan_queue_end = 0;
+}
+
+#ifdef NEW_PIC
+/* This is used to run the keyboard interrupt */
+void
+do_irq1 (void)
+{
+  read_next_scancode_from_queue ();
+  /* reschedule if queue not empty */
+  if (*scan_queue_start != *scan_queue_end)
+    {
+      k_printf ("KBD: Requesting next keyboard interrupt startstop %d:%d\n",
+		*scan_queue_start, *scan_queue_end);
+      pic_request (PIC_IRQ1);
+      keys_ready = 0;
+    }
+  do_irq ();			/* do dos interrupt */
+  keys_ready = 0;
+}
+
+#endif
+
+void
+set_keyboard_bios (void)
+{
+  int scan;
+
+  if (config.keybint)
+    {
+      next_scancode = convscanKey(HI (ax));
+    }
+  else
+    next_scancode = convscanKey(next_scancode);
+#ifdef NEW_PIC
+  keys_ready = 0;		/* flag character as read	*/
+#endif
+  k_printf ("set keybaord bios next_scancode = 0x%04\n", next_scancode);
+}
+
+void
+insert_into_keybuffer (void)
+{
+  /* int15 fn=4f will reset CF if scan key is not to be used */
+  /*  if (!config.keybint || LWORD(eflags) & CF) */
+  if (!config.keybint || READ_FLAGS () & CF)
+    keepkey = 1;
+  else
+    keepkey = 0;
+
+  if (next_scancode && keepkey)
+    {
+      k_printf ("KBD: putting key in buffer\n");
+      if (InsKeyboard (next_scancode))
+	dump_kbuffer ();
+      else
+	error ("ERROR: InsKeyboard could not put key into buffer!\n");
+    }
+}
+void
+scan_to_buffer (void)
+{
+  k_printf ("scan_to_buffer LASTSCAN_ADD = 0x%04x\n", READ_WORD (LASTSCAN_ADD));
+  set_keyboard_bios ();
+  insert_into_keybuffer ();
+}
+
+void
+add_scancode_to_queue (u_short scan)
+{
+  k_printf ("KBD: Adding scancode to scan_queue: scan %04x, startq=%d, endq=%d\n", scan, *scan_queue_start, *scan_queue_end);
+  scan_queue[*scan_queue_end] = scan;
+  *scan_queue_end = (*scan_queue_end + 1) % SCANQ_LEN;
+  if (config.keybint)
+    {
+      k_printf ("Hard queue\n");
+#ifdef NEW_PIC
+      pic_request (PIC_IRQ1);
+#else
+      do_hard_int (9);
+#endif
+    }
+  else
+    {
+      k_printf ("NOT Hard queue\n");
+      read_next_scancode_from_queue ();
+      scan_to_buffer ();
+#ifdef NEW_PIC
+      keys_ready = 0;
+#endif
+    }
+}
+
+
+void
+read_next_scancode_from_queue (void)
+{
+#ifndef NEW_PIC
+  keys_ready = 0;
+#else
+  if (!keys_ready)
+    {				/* make sure last character has been read */
+#endif
+      if (*scan_queue_start != *scan_queue_end)
+	{
+	  keys_ready = 1;
+	  next_scancode = scan_queue[*scan_queue_start];
+	  if (*scan_queue_start != *scan_queue_end)
+	    *scan_queue_start = (*scan_queue_start + 1) % SCANQ_LEN;
+	  WRITE_WORD (LASTSCAN_ADD, next_scancode);
+	}
+#ifdef NEW_PIC
+    }
+#endif
+  else
+    k_printf ("KBD: read_next_scancode key not Read!\n");
+
+  k_printf ("KBD: Nextscan key 96 0x%02x, 97 0x%02x, kbc1 0x%02x, kbc2 0x%02x\n",
+	    *(u_char *) 0x496, *(u_char *) 0x497, *(u_char *) 0x417, *(u_char *) 0x418);
+  k_printf ("start=%d, end=%d, LASTSCAN=%x\n", *scan_queue_start, *scan_queue_end, READ_WORD (LASTSCAN_ADD));
+}
diff -u --recursive --new-file dosemu0.53pl47/keyboard/keyboard.c dosemu0.53pl48/keyboard/keyboard.c
--- dosemu0.53pl47/keyboard/keyboard.c	Wed Mar  1 19:16:48 1995
+++ dosemu0.53pl48/keyboard/keyboard.c	Tue Mar  7 19:52:25 1995
@@ -209,7 +209,7 @@
 extern void clear_process_control();
 void set_raw_mode();
 void get_leds();
-extern void DOS_setscan(u_short);
+extern void read_next_scancode_from_queue(u_short);
 void activate(int);
 extern int terminal_initialize();
 extern void terminal_close();
@@ -579,31 +579,6 @@
 
 #endif /* NOT USE_SLANG_KEYS */
 
-static void
-gettermcap(void)
-{
-  char *garb;
-  struct winsize ws;		/* buffer for TIOCSWINSZ */
-#ifndef USE_SLANG_KEYS
-  struct funkeystruct *fkp;
-#endif
-  li = LI;
-  co = CO;
-  if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) >= 0) {
-    li = ws.ws_row;
-    co = ws.ws_col;
-  }
-
-  if (li == 0 || co == 0) {
-    error("ERROR: unknown window sizes li=%d  co=%d, setting to 80x25\n", li, co);
-    li = 25;
-    co = 80;
-  }
-  else
-    v_printf("VID: Setting windows size to li=%d, co=%d\n", li, co);
-   
-}
-
 void
 keyboard_close(void)
 {
@@ -648,6 +623,8 @@
   k_printf("KBD: 	c_line =%x\n", term.c_line);
 }
 
+extern void scr_state_init(void);
+
 /*
  * DANG_BEGIN_FUNCTION keyboard_init
  *
@@ -694,11 +671,14 @@
   } else
      major = minor = 0;
 
+  scr_state_init();
+#if 0
   scr_state.vt_allow = 0;
   scr_state.vt_requested = 0;
   scr_state.mapped = 0;
   scr_state.pageno = 0;
   scr_state.virt_address = PAGE_ADDR(0);
+#endif
 
   if (!config.usesX) {
     /* console major num is 4, minor 64 is the first serial line */
@@ -861,7 +841,7 @@
       for (i = 0; i < cc; i++) {
 	k_printf("KEY: readcode: %d \n", kbp[kbcount + i]);
 	child_set_flags(kbp[kbcount + i]);
-	DOS_setscan(kbp[kbcount + i]);
+	read_next_scancode_from_queue(kbp[kbcount + i]);
 	k_printf("KBD: cc pushing %d'th character\n", i);
       }
     }
@@ -870,8 +850,7 @@
 
 #ifdef USE_SLANG_KEYS
      do_slang_getkeys ();
-#endif
-#ifndef USE_SLANG_KEYS
+#else
     if (kbcount == 0)
       kbp = kbbuf;
     else if (kbp > &kbbuf[(KBBUF_SIZE * 3) / 5]) {
@@ -1056,7 +1035,7 @@
 	  kbcount -= i;
 	  *cc -= i;
 	  kbp += i;
-	  DOS_setscan(fkp->code);
+	  read_next_scancode_from_queue(fkp->code);
 	  return;
 	}
       }
@@ -1066,7 +1045,7 @@
     if (kbcount == 1) {
       kbcount--;
       (*cc)--;
-      DOS_setscan((highscan[*kbp] << 8) + (unsigned char) *kbp++);
+      read_next_scancode_from_queue((highscan[*kbp] << 8) + (unsigned char) *kbp++);
       return;
     }
 
@@ -1075,7 +1054,7 @@
   else if (*kbp >= 128) {
     for (fkp = xfunkey; fkp->code; fkp++) {
       if ((unsigned char) (*kbp) == fkp->esc[0]) {
-	DOS_setscan(fkp->code);
+	read_next_scancode_from_queue(fkp->code);
 	break;
       }
     }
@@ -1089,7 +1068,7 @@
     kbcount--;
     (*cc)--;
     kbp++;
-    DOS_setscan(((unsigned char) highscan[8] << 8) + (unsigned char) 8);
+    read_next_scancode_from_queue(((unsigned char) highscan[8] << 8) + (unsigned char) 8);
     return;
   }
 
@@ -1099,7 +1078,7 @@
   if ((unsigned char) *kbp < 0x80)
     i |= (unsigned char) *kbp;
 
-  DOS_setscan(i);
+  read_next_scancode_from_queue(i);
   kbcount--;
   (*cc)--;
   kbp++;
@@ -1115,30 +1094,24 @@
   unsigned short nextpos;
 
   /* First of all compute the position of the new tail pointer */
-#if 0
-  if ((nextpos = KBD_Tail + 2) >= KBD_End)
-    nextpos = KBD_Start;
-  if (nextpos == KBD_Head)	/* queue full ? */
-    return (0);
-#endif
   if ((nextpos = READ_WORD(KBD_TAIL) + 2) >= READ_WORD(KBD_END))
     nextpos = READ_WORD(KBD_START);
-  if (nextpos == READ_WORD(KBD_HEAD))	/* queue full ? */
+  if (nextpos == READ_WORD(KBD_HEAD)){	/* queue full ? */
+     if(scancode == 0x2e03) {
+        WRITE_BYTE(0x471, 0x80);    /* ctrl-break flag */
+        WRITE_WORD(KBD_HEAD, READ_WORD(KBD_START));
+        WRITE_WORD(KBD_TAIL, READ_WORD(KBD_START));
+        WRITE_WORD(BIOS_DATA_PTR(READ_WORD(KBD_START)), 0);
+        k_printf("KBD: cntrl-C received\n");
+     	return (1);
+     }
+     putchar('\007');
      return (0);
-
+  }
 
-  ignore_segv++;
-#if 0
-  /* *((unsigned short *) BIOS_DATA_PTR(KBD_Tail)) = scancode;*/
-  WRITE_WORD(BIOS_DATA_PTR(KBD_Tail), scancode);
-  KBD_Tail = nextpos;
-#endif
   WRITE_WORD(BIOS_DATA_PTR(READ_WORD(KBD_TAIL)), scancode);
   WRITE_WORD(KBD_TAIL, nextpos);
 
-  ignore_segv--;
-
-  /* dump_kbuffer(); */
   return 1;
 }
 
@@ -1815,73 +1788,6 @@
     put_queue(FCH(fnum, sc, (sc + 0x2e)) << 8);
 }
 
-void
-activate(int con_num)
-{
-  if (in_ioctl) {
-    k_printf("KBD: can't ioctl for activate, in a signal handler\n");
-    do_ioctl(kbd_fd, VT_ACTIVATE, con_num);
-  }
-  else
-    do_ioctl(kbd_fd, VT_ACTIVATE, con_num);
-}
-
-int
-do_ioctl(int fd, int req, int param3)
-{
-  int tmp;
-
-  if (in_sighandler && in_ioctl) {
-    k_printf("KBD: do_ioctl(): in ioctl %d 0x%04x 0x%04x.\nqueuing: %d 0x%04x 0x%04x\n",
-	     curi.fd, curi.req, curi.param3, fd, req, param3);
-    queue_ioctl(fd, req, param3);
-    errno = EDEADLOCK;
-#ifdef SYNC_ALOT
-    fflush(stdout);
-    sync();			/* for safety */
-#endif
-    return -1;
-  }
-  else {
-    in_ioctl = 1;
-    curi.fd = fd;
-    curi.req = req;
-    curi.param3 = param3;
-    if (iq.queued) {
-      k_printf("KBD: detected queued ioctl in do_ioctl(): %d 0x%04x 0x%04x\n",
-	       iq.fd, iq.req, iq.param3);
-    }
-    tmp = ioctl(fd, req, param3);
-    in_ioctl = 0;
-    return tmp;
-  }
-}
-
-int
-queue_ioctl(int fd, int req, int param3)
-{
-  if (iq.queued) {
-    error("ioctl already queued: %d 0x%04x 0x%04x\n", iq.fd, iq.req,
-	  iq.param3);
-    return 1;
-  }
-  iq.fd = fd;
-  iq.req = req;
-  iq.param3 = param3;
-  iq.queued = 1;
-
-  return 0;			/* success */
-}
-
-void
-do_queued_ioctl(void)
-{
-  if (iq.queued) {
-    iq.queued = 0;
-    do_ioctl(iq.fd, iq.req, iq.param3);
-  }
-}
-
 static void
 slash(unsigned int sc)
 {
@@ -2029,7 +1935,7 @@
 /* This is used to run the keyboard interrupt */
 void
 do_irq1(void) {
-   parent_nextscan();
+   add_scancode_to_queue();
   /* reschedule if queue not empty */
   if (*scan_queue_start!=*scan_queue_end) { 
     k_printf("KBD: Requesting next keyboard interrupt startstop %d:%d\n", 
@@ -2045,7 +1951,6 @@
 
 void
 scan_to_buffer(void) {
-/*  k_printf("scan_to_buffer LASTSCAN_ADD = 0x%04x\n", *LASTSCAN_ADD); */
   k_printf("scan_to_buffer LASTSCAN_ADD = 0x%04x\n", READ_WORD(LASTSCAN_ADD));
   set_keyboard_bios();
   insert_into_keybuffer();
@@ -2052,7 +1957,7 @@
 }
 
 void
-DOS_setscan(u_short scan)
+read_next_scancode_from_queue(u_short scan)
 {
   k_printf("DOS got set scan %04x, startq=%d, endq=%d\n", scan, *scan_queue_start, *scan_queue_end);
   scan_queue[*scan_queue_end] = scan;
@@ -2067,7 +1972,7 @@
   }
   else {
     k_printf("NOT Hard queue\n");
-    parent_nextscan();
+    add_scancode_to_queue();
     scan_to_buffer();
 #ifdef NEW_PIC
  /*   *LASTSCAN_ADD=1; */
@@ -2074,15 +1979,24 @@
     keys_ready = 0;
 #endif
   }
+  add_key_depress(scan );
+
+}
+
+void
+add_key_depress(u_short scan){
   if (!config.console_keyb && !config.X) {
     static u_short tmp_scan;
     tmp_scan = scan & 0xff00;
     if (tmp_scan < 0x8000 && tmp_scan > 0) {
       k_printf("Adding Key-Release\n");
-      DOS_setscan(scan | 0x8000);
+      read_next_scancode_from_queue(scan | 0x8000);
     }
   }
+}
 
+void
+keyboard_flags_init(void){
 }
 
 static int lastchr;
@@ -2176,7 +2090,7 @@
 }
 
 void
-parent_nextscan(void)
+add_scancode_to_queue(void)
 {
 #ifndef NEW_PIC
   keys_ready = 0;
diff -u --recursive --new-file dosemu0.53pl47/keyboard/slang-keyboard.c dosemu0.53pl48/keyboard/slang-keyboard.c
--- dosemu0.53pl47/keyboard/slang-keyboard.c	Wed Mar  1 22:32:20 1995
+++ dosemu0.53pl48/keyboard/slang-keyboard.c	Tue Mar  7 19:13:59 1995
@@ -1,12 +1,6 @@
 #include "../include/slang.h"
 
-/* These need to be made user definable */
-static char *Alt_Shiftkey = "^@a";
-static char *Sticky_Alt_Shiftkey = "^@A";
-static char *Ctrl_Shiftkey = "^@c";
-static char *Sticky_Ctrl_Shiftkey = "^@C";
-static char *Shift_Shiftkey = "^@s";
-static char *Sticky_Shift_Shiftkey = "^@S";
+unsigned char DOSemu_Slang_Escape_Character = 30;
 
 char *DOSemu_Keyboard_Keymap_Prompt = NULL;
 int DOSemu_Terminal_Scroll = 0;
@@ -14,6 +8,7 @@
 
 extern void dos_slang_redraw (void);
 extern void dos_slang_suspend (void);
+extern void dos_slang_smart_set_mono (void);
 
 /* The goal of the routines here is simple: to allow SHIFT, ALT, and CONTROL
  * keys to be used with a remote terminal.  The way this is accomplished is 
@@ -35,8 +30,8 @@
 
 typedef struct
 {
-   unsigned char keystr[8];
-   unsigned int scan_code;
+   unsigned char keystr[10];
+   unsigned long scan_code;
 }
 Keymap_Scan_Type;
 
@@ -56,6 +51,8 @@
 #define HELP_SCAN_CODE 0x10024
 #define RESET_SCAN_CODE 0x10025
 
+#define SET_MONO_SCAN_CODE 0x10026
+
 static Keymap_Scan_Type Normal_Map [] =
 {
    /* These are the F1 - F12 keys for terminals without them. */
@@ -75,8 +72,8 @@
    {"1",	0x0231},   	       /* 1 */
    {"!",	0x0221},	       /* ! */
    {"2",	0x0332},	       /* 2 */
-   {"@",	0x0340},	       /* @ */
-   {"^@^@",	0x0300},	       /* ^@ */
+   {"@",	0x0340},               /* @ */
+   /* {"^@",	0x0300}, */	       /* ^@ --- handled below. */
    {"3",	0x0433},	       /* 3 */
    {"#",	0x0423},	       /* # */
    {"4",	0x0534},	       /* 4 */
@@ -615,14 +612,86 @@
 SLKeyMap_List_Type *The_Ctrl_KeyMap;
 SLKeyMap_List_Type *The_Shift_KeyMap;
 
+static unsigned char Esc_Char;
+int define_key (unsigned char *key, unsigned long scan, SLKeyMap_List_Type *m)
+{
+   unsigned char buf[16], k1;
+   
+   if (*key == '^')
+     {
+	k1 = key[1];
+	if (k1 == Esc_Char) return 0;  /* ^Esc_Char is not defined here */
+	if (k1 == '@')
+	  {
+	     strcpy ((char *) buf, (char *) key);
+	     buf[1] = Esc_Char;
+	     key = buf;
+	  }
+     }
+   return SLang_define_key1 (key, (VOID *) scan, SLKEY_F_INTRINSIC, m);
+}
+
+/* The entries with 0x0000 are not going to be used by any sane person. */
+unsigned long Ctrl_Char_Scan_Codes[32] = 
+{
+   0x0300,			       /* ^@ */
+   0x1E01,			       /* ^A */
+   0x3002,			       /* ^B */
+   0x2E03,			       /* ^C */
+   0x2004,			       /* ^D */
+   0x1205,			       /* ^E */
+   0x2106,			       /* ^F */
+   0x2207,			       /* ^G */
+   0x2308,			       /* ^H */
+   0x0F09,			       /* TAB */
+   0x240A,			       /* ^J */
+   0x250B,			       /* ^K */
+   0x260C,			       /* ^L */
+   0x0000,			       /* ^M --- RETURN-- Not used.*/
+   0x310E,			       /* ^N */
+   0x180F,			       /* ^O */
+   0x2510,			       /* ^P */
+   0x1011,			       /* ^Q */
+   0x1312,			       /* ^R */
+   0x1F13,			       /* ^S */
+   0x1414,			       /* ^T */
+   0x1615,			       /* ^U */
+   0x2F16,			       /* ^V */
+   0x1117,			       /* ^W */
+   0x2D18,			       /* ^X */
+   0x1519,			       /* ^Y */
+   0x2C1A,			       /* ^Z */
+   0x0000,			       /* ^[ --- ESC --- Not used. */
+   0x2B1C,			       /* ^\\ */
+   0x1B1D,			       /* ^] */
+   0x071E,			       /* ^^ */
+   0x0C1F			       /* ^_ */
+};
 
+	
 static int init_slang_keymaps (void)
 {
    char *str;
    SLKeyMap_List_Type *kmaps[4], *m;
    Keymap_Scan_Type *scans[4], *k;
+   unsigned char buf[5];
    int i;
+   unsigned long esc_scan;
+   
+   /* Do some sanity checking */
+   if (DOSemu_Slang_Escape_Character >= 32)
+     DOSemu_Slang_Escape_Character = 0;
+   
+   esc_scan = Ctrl_Char_Scan_Codes[DOSemu_Slang_Escape_Character];
+   if (esc_scan == 0) 
+     {
+	DOSemu_Slang_Escape_Character = 0;
+	esc_scan = Ctrl_Char_Scan_Codes[0];
+     }
+   
+   Esc_Char = DOSemu_Slang_Escape_Character + '@';
    
+   
    if (The_Normal_KeyMap != NULL) return 0;
    
    if ((NULL == (The_Normal_KeyMap = SLang_create_keymap ("Normal", NULL)))
@@ -641,37 +710,48 @@
 	k = scans[i]; m = kmaps[i];
 	while ((str = k->keystr), (*str != 0))
 	  {
-	     SLang_define_key1 (str, (VOID *) k->scan_code, SLKEY_F_INTRINSIC, m);
+	     define_key (str, k->scan_code, m);
 	     k++;
 	  }
 
 	/* Now setup the shift modifier keys in each of the keymaps.  */
-	SLang_define_key1 (Alt_Shiftkey, (VOID *) ALT_KEY_SCAN_CODE, SLKEY_F_INTRINSIC, m);
-	SLang_define_key1 (Ctrl_Shiftkey, (VOID *) CTRL_KEY_SCAN_CODE, SLKEY_F_INTRINSIC, m);
-	SLang_define_key1 (Shift_Shiftkey, (VOID *) SHIFT_KEY_SCAN_CODE, SLKEY_F_INTRINSIC, The_Normal_KeyMap);
-	
-	SLang_define_key1 (Sticky_Alt_Shiftkey, (VOID *) STICKY_ALT_KEY_SCAN_CODE, SLKEY_F_INTRINSIC, m);
-	SLang_define_key1 (Sticky_Ctrl_Shiftkey, (VOID *) STICKY_CTRL_KEY_SCAN_CODE, SLKEY_F_INTRINSIC, m);
-	SLang_define_key1 (Sticky_Shift_Shiftkey, (VOID *) STICKY_SHIFT_KEY_SCAN_CODE, SLKEY_F_INTRINSIC, The_Normal_KeyMap);
-	
-	SLang_define_key1 ("^@?", (VOID *) HELP_SCAN_CODE, SLKEY_F_INTRINSIC, The_Normal_KeyMap);
-	SLang_define_key1 ("^@h", (VOID *) HELP_SCAN_CODE, SLKEY_F_INTRINSIC, The_Normal_KeyMap);
-	
-	SLang_define_key1 ("^@^R", (VOID *) REDRAW_SCAN_CODE, SLKEY_F_INTRINSIC, The_Normal_KeyMap);
-	SLang_define_key1 ("^@^L", (VOID *) REDRAW_SCAN_CODE, SLKEY_F_INTRINSIC, The_Normal_KeyMap);
-	SLang_define_key1 ("^@^Z", (VOID *) SUSPEND_SCAN_CODE, SLKEY_F_INTRINSIC, The_Normal_KeyMap);
-	SLang_define_key1 ("^@ ", (VOID *) RESET_SCAN_CODE, SLKEY_F_INTRINSIC, The_Normal_KeyMap);
-	
-	SLang_define_key1 ("^@\033[A", (VOID *) SCROLL_UP_SCAN_CODE, SLKEY_F_INTRINSIC, The_Normal_KeyMap);
-	SLang_define_key1 ("^@\033OA", (VOID *) SCROLL_UP_SCAN_CODE, SLKEY_F_INTRINSIC, The_Normal_KeyMap);
-	SLang_define_key1 ("^@U", (VOID *) SCROLL_UP_SCAN_CODE, SLKEY_F_INTRINSIC, The_Normal_KeyMap);
-	
-	SLang_define_key1 ("^@\033[B", (VOID *) SCROLL_DOWN_SCAN_CODE, SLKEY_F_INTRINSIC, The_Normal_KeyMap);
-	SLang_define_key1 ("^@\033OB", (VOID *) SCROLL_DOWN_SCAN_CODE, SLKEY_F_INTRINSIC, The_Normal_KeyMap);
-	SLang_define_key1 ("^@D", (VOID *) SCROLL_DOWN_SCAN_CODE, SLKEY_F_INTRINSIC, The_Normal_KeyMap);
+	define_key ("^@a", ALT_KEY_SCAN_CODE, m);
+	define_key ("^@c", CTRL_KEY_SCAN_CODE, m);
+	define_key ("^@s", SHIFT_KEY_SCAN_CODE, m);
+	
+	define_key ("^@A", STICKY_ALT_KEY_SCAN_CODE, m);
+	define_key ("^@C", STICKY_CTRL_KEY_SCAN_CODE, m);
+	define_key ("^@S", STICKY_SHIFT_KEY_SCAN_CODE, m);
+	
+	define_key ("^@?", HELP_SCAN_CODE, m);
+	define_key ("^@h", HELP_SCAN_CODE, m);
+	
+	define_key ("^@^R", REDRAW_SCAN_CODE, m);
+	define_key ("^@^L", REDRAW_SCAN_CODE, m);
+	define_key ("^@^Z", SUSPEND_SCAN_CODE, m);
+	define_key ("^@ ", RESET_SCAN_CODE, m);
+	define_key ("^@B", SET_MONO_SCAN_CODE, m);
+	
+	define_key ("^@\033[A", SCROLL_UP_SCAN_CODE, m);
+	define_key ("^@\033OA", SCROLL_UP_SCAN_CODE, m);
+	define_key ("^@U", SCROLL_UP_SCAN_CODE, m);
+	
+	define_key ("^@\033[B", SCROLL_DOWN_SCAN_CODE, m);
+	define_key ("^@\033OB", SCROLL_DOWN_SCAN_CODE, m);
+	define_key ("^@D", SCROLL_DOWN_SCAN_CODE, m);
 	
 	if (SLang_Error) return -1;
      }
+   
+   /* Now add one more for the esc character so that sending it twice
+    * sends it.
+    */
+   buf[0] = '^'; buf[1] = Esc_Char; 
+   buf[2] = '^'; buf[3] = Esc_Char; 
+   buf[4] = 0;
+   SLang_define_key1 (buf, (VOID *) esc_scan, SLKEY_F_INTRINSIC, The_Normal_KeyMap);
+   if (SLang_Error) return -1;
+   return 0;
 }
 
 
@@ -779,7 +859,8 @@
 		   * wants esc.
 		   */
 		  if (sltermio_input_pending ()) return;
-		  DOS_setscan ((unsigned short) 0x011B);
+		  add_scancode_to_queue ((unsigned short) (scan >> 8));
+		  add_key_depress((scan>>8));
 		  key = NULL;
 		  /* drop on through to the return for the undefined key below. */
 	       }
@@ -811,7 +892,9 @@
 	if (scan < ALT_KEY_SCAN_CODE)
 	  {
 	     if (sticky == 0) map = The_Normal_KeyMap;
-	     DOS_setscan ((unsigned short) scan);
+  	     add_scancode_to_queue ((unsigned short) (scan >> 8));
+	     add_key_depress((scan>>8));
+
 	     continue;
 	  }
 	
@@ -882,6 +965,10 @@
 	     map = The_Normal_KeyMap;
 	     DOSemu_Slang_Show_Help = 0;
 	     DOSemu_Terminal_Scroll = 0;
+	     break;
+
+	   case SET_MONO_SCAN_CODE:
+	     dos_slang_smart_set_mono ();
 	     break;
 	  }
 	
Binary files dosemu0.53pl47/periph/hdinfo and dosemu0.53pl48/periph/hdinfo differ
Binary files dosemu0.53pl47/periph/mkhdimage and dosemu0.53pl48/periph/mkhdimage differ
Binary files dosemu0.53pl47/periph/putrom and dosemu0.53pl48/periph/putrom differ
diff -u --recursive --new-file dosemu0.53pl47/video/int10.c dosemu0.53pl48/video/int10.c
--- dosemu0.53pl47/video/int10.c	Wed Mar  1 19:16:48 1995
+++ dosemu0.53pl48/video/int10.c	Tue Mar  7 21:11:04 1995
@@ -236,7 +236,6 @@
     break;
 
   default:          /* Printable character */
-    /* CHAR(SCREEN_ADR(s) + ypos*co + xpos) = ch; */
     WRITE_BYTE(SCREEN_ADR(s) + ypos*co + xpos, ch);
     xpos++;
     set_dirty(s);
@@ -249,9 +248,6 @@
   if (ypos == li) {
     ypos--;
     bios_scroll(0,0,co-1,li-1,1,newline_att);
-/*
-    scrollup(0, 0, co - 1, li - 1, 1, newline_att);
-*/
   }
   set_bios_cursor_x_position(s, xpos);
   set_bios_cursor_y_position(s, ypos);
@@ -586,7 +582,7 @@
 
   case 0x0f:			/* get video mode */
 #if USE_DUALMON
-    if (IS_SCREENMODE_MDA) LWORD(eax) = (CO << 8) | READ_BYTE(BIOS_VIDEO_MODE);
+    if (IS_SCREENMODE_MDA) LWORD(eax) = (co << 8) | READ_BYTE(BIOS_VIDEO_MODE);
     else 
 #endif
     LWORD(eax) = (co << 8) | video_mode;
diff -u --recursive --new-file dosemu0.53pl47/video/terminal.slang.c dosemu0.53pl48/video/terminal.slang.c
--- dosemu0.53pl47/video/terminal.slang.c	Tue Feb 28 15:08:40 1995
+++ dosemu0.53pl48/video/terminal.slang.c	Tue Mar  7 21:16:30 1995
@@ -23,6 +23,8 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/ioctl.h>
+#include <termios.h>
 
 #include "bios.h"
 #include "emu.h"
@@ -53,8 +55,12 @@
  *      001          000           Underline
  *     anything else is invalid.
  */    
-static int Attribute_Map[256];		       /* if negative, char is invisible */
+static int BW_Attribute_Map[256];
+static int Color_Attribute_Map[256];
 
+static int *Attribute_Map;
+/* if negative, char is invisible */
+
 extern char *DOSemu_Keyboard_Keymap_Prompt;
 extern int DOSemu_Terminal_Scroll;
 extern int DOSemu_Slang_Show_Help;
@@ -76,6 +82,72 @@
 	leavedos (32);
 }
 
+
+void get_screen_size (void)
+{
+  struct winsize ws;		/* buffer for TIOCSWINSZ */
+
+   SLtt_Screen_Rows = 0;
+   SLtt_Screen_Cols = 0;
+   if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) >= 0) 
+     {
+	SLtt_Screen_Rows = ws.ws_row;
+	SLtt_Screen_Cols = ws.ws_col;
+     }
+   if ((SLtt_Screen_Rows <= 0) 
+       || (SLtt_Screen_Cols <= 0))
+     {
+	SLtt_Screen_Cols = 80;
+	SLtt_Screen_Rows = 24;
+     }
+   Rows = SLtt_Screen_Rows;
+   Columns = SLtt_Screen_Cols;
+}
+
+static void set_char_set (int cs)
+{
+   int i;
+   switch (cs)
+     {
+      case CHARSET_FULLIBM:
+	error("WARNING: 'charset fullibm' doesn't work.  Use 'charset ibm' instead.\n");
+	/* The_Charset = charset_fullibm; */
+	/* drop */
+      case CHARSET_IBM:     	
+	The_Charset = charset_ibm;
+	Use_IBM_Codes = 1;
+ 	SLsmg_Display_Eight_Bit = 0x80;
+	break;
+	
+      case CHARSET_LATIN:
+      default:
+	if (Use_IBM_Codes) 
+	  {
+	     SLtt_write_string ("\n\033(B\033(B\r         \r");
+	  }
+	SLsmg_Display_Eight_Bit = 160;
+	Use_IBM_Codes = 0;
+	The_Charset = charset_latin;
+	break; 
+     }
+   
+   /* The fact is that this code is used to talk to a terminal.  Control 
+    * sequences 0-31 and 128-159 are reserved for the terminal.  Here I fixup 
+    * the character set map to reflect this fact (only if not ibmpc codes).
+    */
+   
+   if (!Use_IBM_Codes) for (i = 0; i < 256; i++)
+     {
+	if ((The_Charset[i] & 0x7F) < 32) The_Charset[i] |= 32;
+     }
+   
+    /* The following turns on the IBM character set mode of virtual console
+     * The same code is echoed twice, then just in case the escape code
+     * not recognized and was printed, erase it with spaces.
+     */
+   if (Use_IBM_Codes) SLtt_write_string ("\033(U\033(U\r        \r");
+}
+
 /* The following initializes the terminal.  This should be called at the
  * startup of DOSEMU if it's running in terminal mode.
  */ 
@@ -82,7 +154,7 @@
 int
 terminal_initialize()
 {
-   SLtt_Char_Type sltt_attr, fg, bg, attr;
+   SLtt_Char_Type sltt_attr, fg, bg, attr, color_sltt_attr, bw_sltt_attr;
    int is_color = config.term_color, i;
    int rotate[8];
    
@@ -107,87 +179,67 @@
    
    SLang_Exit_Error_Hook = sl_exit_error;
    SLtt_get_terminfo ();
-   SLtt_Screen_Rows = li;
-   SLtt_Screen_Cols = co;
+   
+   get_screen_size ();
 
    /* Now set the variables li and co back to their dos defaults. */
+#if 0
    li = Rows;
    co = Columns;
+#endif
    
    SLtt_Use_Blink_For_ACS = 1;
    SLtt_Blink_Mode = 1;
+   
    SLtt_Use_Ansi_Colors = is_color;
    
+   if (is_color) Attribute_Map = Color_Attribute_Map;
+   else Attribute_Map = BW_Attribute_Map;
+     
    if (!SLsmg_init_smg ())
      sl_exit_error ("Unable to initialze SMG routines.");
    
    for (attr = 0; attr < 256; attr++)
      {
-	Attribute_Map[attr] = attr;
+	BW_Attribute_Map[attr] = Color_Attribute_Map[attr] = attr;
+	BW_Attribute_Map[attr] = 0;
+	
 	sltt_attr = 0;
 	if (attr & 0x80) sltt_attr |= SLTT_BLINK_MASK;
 	if (attr & 0x08) sltt_attr |= SLTT_BOLD_MASK;
+	
+	bw_sltt_attr = color_sltt_attr = sltt_attr;
+	
 	bg = (attr >> 4) & 0x07;
 	fg = (attr & 0x07);
-	if (is_color)
-	  {
-	     sltt_attr |= (rotate[bg] << 16) | (rotate[fg] << 8);
-	     SLtt_set_color_object (attr, sltt_attr);
-	  }
-	else
+	
+	/* color information */
+	color_sltt_attr |= (rotate[bg] << 16) | (rotate[fg] << 8);
+	SLtt_set_color_object (attr, color_sltt_attr);
+	
+	/* Monochrome information */
+	if ((fg == 0x01) && (bg == 0x00)) bw_sltt_attr |= SLTT_ULINE_MASK;
+	if (bg & 0x7) bw_sltt_attr |= SLTT_REV_MASK;
+	else if (fg == 0)
 	  {
-	     if ((fg == 0x01) && (bg == 0x00)) sltt_attr |= SLTT_ULINE_MASK;
-	     if (bg & 0x7) sltt_attr |= SLTT_REV_MASK;
-	     else if (fg == 0)
-	       {
-		  /* Invisible */
-		  Attribute_Map[attr] = -attr;
-	       }
-	     SLtt_set_mono (attr, NULL, sltt_attr);
+	     /* Invisible */
+	     BW_Attribute_Map [attr] = -attr;
 	  }
+	
+	SLtt_set_mono (attr, NULL, bw_sltt_attr);
      }
    
    /* object 0 is special.  It is normal video.  Lets fix that now. */   
-   Attribute_Map[0x7] = 0;
-   if (is_color) SLtt_set_color_object (0, 0x000700);
-   else SLtt_set_mono (0, NULL, 0x000700);
-   
-   SLsmg_refresh ();
+   BW_Attribute_Map[0x7] = Color_Attribute_Map[0x7] = 0;
    
-   switch (config.term_charset) 
-     {
-      case CHARSET_FULLIBM:
-	error("WARNING: 'charset fullibm' doesn't work.  Use 'charset ibm' instead.\n");
-	/* The_Charset = charset_fullibm; */
-	/* drop */
-      case CHARSET_IBM:     	
-	The_Charset = charset_ibm;
-	Use_IBM_Codes = 1;
- 	SLsmg_Display_Eight_Bit = 0x80;
-	break;
-	
-      case CHARSET_LATIN:
-      default:
-	The_Charset = charset_latin;
-	break; 
-     }
+   SLtt_set_color_object (0, 0x000700);
+   SLtt_set_mono (0, NULL, 0x000700);
    
-   /* The fact is that this code is used to talk to a terminal.  Control 
-    * sequences 0-31 and 128-159 are reserved for the terminal.  Here I fixup 
-    * the character set map to reflect this fact (only if not ibmpc codes).
+   SLsmg_refresh ();
+   /* This goes after the refresh because it might try 
+    * resetting the character set.
     */
-   
-   if (!Use_IBM_Codes) for (i = 0; i < 256; i++)
-     {
-	if ((The_Charset[i] & 0x7F) < 32) The_Charset[i] |= 32;
-     }
-   
-    /* The following turns on the IBM character set mode of virtual console
-     * The same code is echoed twice, then just in case the escape code
-     * not recognized and was printed, erase it with spaces.
-     */
-   if (Use_IBM_Codes) SLtt_write_string ("\033(U\033(U\r        \r");
-
+   set_char_set (config.term_charset);
    return 0;
 }
 
@@ -221,8 +273,7 @@
 static char *Help[] = 
 {
    "Function Keys:",
-   "    F1: ^@1      F2: ^@2    ...     F9: ^@9    F10: ^@0",
-   "",
+   "    F1: ^@1      F2: ^@2    ...     F9: ^@9    F10: ^@0   F11: ^@-   F12: ^@=",
    "Key Modifiers:",
    "    ^@s : SHIFT KEY        ^@S : STICKY SHIFT KEY",
    "    ^@a : ALT KEY          ^@A : STICKY ALT KEY",
@@ -231,17 +282,18 @@
    "  Examples:",
    "    Pressing ^@s followed by ^@3 results in SHIFT-F3.",
    "    Pressing ^@C Up Up Up ^@C results in Ctrl-Up Ctrl-Up Ctrl-Up.",
-   "",
    "Miscellaneous:",
    "    ^@^R : Redraw display      ^@^L : Redraw the display.",
-   "    ^@^Z : Suspend dosemu",
-   "    ^@ Up Arrow: Pan the display Up.",
-   "    ^@ Dn Arrow: Pan the display Dn.",
+   "    ^@^Z : Suspend dosemu      ^@b  : Select BEST monochrome mode.",    
+   "    ^@ Up Arrow: Force the top of DOS screen to be displayed.",
+   "    ^@ Dn Arrow: Force the bottom of DOS screen to be displayed.",
    "    ^@ Space: Reset Sticky keys and Panning to automatic panning mode.",
-   "    ^@? or ^@h:  SHow this help screen.",
+   "    ^@? or ^@h:  Show this help screen.",
    "    ^@^@:  Send the ^@ character to dos.",
+   " The default panning mode is such that the cursor will always remain visible.",
    "",
-   "            PRESS THE SPACE BAR TO CONTINUE",
+   "Note: The actual control character to use may not be ^@.",
+   "PRESS THE SPACE BAR TO CONTINUE---------",
    NULL
 };
 
@@ -402,7 +454,55 @@
     */
 }
 
+
+void dos_slang_smart_set_mono (void)
+{
+   int i, max_attr;
+   unsigned int attr_count [256], max_count;
+   register unsigned short *s, *smax;
+   
+   Attribute_Map = BW_Attribute_Map;
+   s = screen_adr;
+   smax = s + Rows * Columns;
+   
+   for (i = 0; i < 256; i++) attr_count[i] = 0;
+   
+   while (s < smax)
+     {
+	attr_count[*s >> 8] += 1;
+	s++;
+     }
    
+   max_attr = 0;
+   max_count = 0;
+   
+   for (i = 0; i < 256; i++)
+     {
+	Attribute_Map[i] = 1;
+	if (attr_count[i] > max_count) 
+	  {
+	     max_attr = i;
+	     max_count = attr_count[i];
+	  }
+     }
+   
+   SLtt_normal_video ();
+   
+   Attribute_Map [max_attr] = 0;
+   SLtt_Use_Ansi_Colors = 0;
+   
+   SLtt_set_mono (1, NULL, SLTT_REV_MASK);
+   SLtt_set_mono (0, NULL, 0);
+   
+   memset ((unsigned char *) prev_screen, 0xFF, 
+	   2 * SLtt_Screen_Rows * SLtt_Screen_Cols);
+   
+   set_char_set (CHARSET_LATIN);
+   
+   SLsmg_cls ();
+}
+
+
 
 
 #define term_setmode NULL
diff -u --recursive --new-file dosemu0.53pl47/video/vc.c dosemu0.53pl48/video/vc.c
--- dosemu0.53pl47/video/vc.c	Sat Feb 25 17:54:25 1995
+++ dosemu0.53pl48/video/vc.c	Sun Mar  5 23:41:17 1995
@@ -1199,4 +1199,3 @@
   }
 #endif
 }
-
diff -u --recursive --new-file dosemu0.53pl47/video/video.c dosemu0.53pl48/video/video.c
--- dosemu0.53pl47/video/video.c	Sat Feb 25 17:54:28 1995
+++ dosemu0.53pl48/video/video.c	Tue Mar  7 21:20:11 1995
@@ -19,6 +19,8 @@
 #if 0
 #include "hgc.h"
 #endif
+#include "termio.h"
+#include "vc.h"
 
 extern void open_kmem();      /* from vc.c */
 extern void set_process_control();
@@ -79,12 +81,12 @@
 
   if (!Video->is_mapped) {
      /* allocate screen buffer for non-console video compare speedup */
-     prev_screen = (ushort *)malloc(CO * MAX_LINES * 2);
+     prev_screen = (ushort *)malloc(co * MAX_LINES * 2);
      if (prev_screen==NULL) {
         error("could not malloc prev_screen\n");
         leavedos(99);
      }
-     v_printf("SCREEN saves at: %p of %d size\n", prev_screen, CO * LI * 2);
+     v_printf("SCREEN saves at: %p of %d size\n", prev_screen, co * li * 2);
 /* 
  * DANG_BEGIN_REMARK
  * Here the sleeping lion will be awoken and eat much of CPU time !!!
@@ -114,6 +116,15 @@
   return 0;
 }
 
+void
+scr_state_init(void){
+  scr_state.vt_allow = 0;
+  scr_state.vt_requested = 0;
+  scr_state.mapped = 0;
+  scr_state.pageno = 0;
+  scr_state.virt_address = PAGE_ADDR(0);
+}
+
 void video_close() {
   v_printf("VID: video_close() called\n");
   if (Video && Video->close) {
@@ -237,8 +248,15 @@
   }
 }
 
-static void
-gettermcap(void)
+void 
+set_video_bios_size(void){
+  WRITE_WORD(BIOS_SCREEN_COLUMNS, co);     /* chars per line */
+  WRITE_BYTE(BIOS_ROWS_ON_SCREEN_MINUS_1, li - 1); /* lines on screen - 1 */
+  WRITE_WORD(BIOS_VIDEO_MEMORY_USED, TEXT_SIZE);   /* size of video regen area in bytes */
+}
+
+void
+gettermcap(int i)
 {
   char *garb;
   struct winsize ws;		/* buffer for TIOCSWINSZ */
@@ -252,21 +270,19 @@
 
   if (li == 0 || co == 0) {
     error("ERROR: unknown window sizes li=%d  co=%d, setting to 80x25\n", li, co);
-    li = 25;
-    co = 80;
+    li = LI;
+    co = CO;
   }
   else
     v_printf("VID: Setting windows size to li=%d, co=%d\n", li, co);
+  get_screen_size();
+  set_video_bios_size();
 }
 
 void
 video_config_init(void) {
 
-  gettermcap();
-#if 0
-  li = 25;
-  co = 80;
-#endif
+  gettermcap(0);
 
   switch (config.cardtype) {
   case CARD_MDA:
@@ -335,9 +351,7 @@
   WRITE_BYTE(BIOS_VDU_CONTROL, 9);	/* current 3x8 (x=b or d) value */
 
   WRITE_BYTE(BIOS_VIDEO_MODE, video_mode); /* video mode */
-  WRITE_WORD(BIOS_SCREEN_COLUMNS, CO);     /* chars per line */
-  WRITE_BYTE(BIOS_ROWS_ON_SCREEN_MINUS_1, LI - 1); /* lines on screen - 1 */
-  WRITE_WORD(BIOS_VIDEO_MEMORY_USED, TEXT_SIZE);   /* size of video regen area in bytes */
+  set_video_bios_size();
   WRITE_WORD(BIOS_VIDEO_MEMORY_ADDRESS, 0);/* offset of current page in buffer */
 
   WRITE_WORD(BIOS_FONT_HEIGHT, 16);
