STDWIN 0.9.6 patches, part 3/5

Guido van Rossum guido at cwi.nl
Fri Jun 7 23:32:04 AEST 1991


Archive-name: stdwin0.9.6/patch3

*** 0.9.5/Ports/mac/stdwin.c	Thu Feb 21 10:54:56 1991
--- stdwin/Ports/mac/stdwin.c	Tue May 28 22:27:01 1991
***************
*** 11,16 ****
--- 11,24 ----
  #endif
  
  
+ /* Parameters for top left corner choice algorithm in wopen() */
+ 
+ #define LEFT	20	/* Initial left */
+ #define TOP	40	/* Initial top */
+ #define HINCR	20	/* Increment for left */
+ #define VINCR	16	/* Increment for top */
+ 
+ 
  /* GLOBAL DATA. */
  
  			/* XXX choose less obvious names */
***************
*** 17,25 ****
  GrafPtr screen;		/* The Mac Window Manager's GrafPort */
  TEXTATTR wattr;		/* Current or default text attributes */
  
! static int def_left= LEFT;
! static int def_top= TOP;
! static int def_width, def_height;
  
  
  /* INITIALIZATION AND TERMINATION. */
--- 25,38 ----
  GrafPtr screen;		/* The Mac Window Manager's GrafPort */
  TEXTATTR wattr;		/* Current or default text attributes */
  
! static int def_left = 0;
! static int def_top = 0;
! static int def_width = 0;
! static int def_height = 0;
! static int def_horscroll = 0;
! static int def_verscroll = 1;
! static int next_left = LEFT;	/* For default placement algorithm */
! static int next_top = TOP;
  
  
  /* INITIALIZATION AND TERMINATION. */
***************
*** 85,91 ****
  #ifdef MPW
  	set_open_hook(std_open_hook);
  #endif
- 	wsetdefwinsize(0, 0);
  	set_watch();
  }
  
--- 98,103 ----
***************
*** 101,107 ****
  	Rect r;
  	r= screen->portRect;
  	*pwidth= r.right - r.left;
! 	*pheight= r.bottom - r.top;
  }
  
  void
--- 113,119 ----
  	Rect r;
  	r= screen->portRect;
  	*pwidth= r.right - r.left;
! 	*pheight= r.bottom - r.top - MENUBARHEIGHT;
  }
  
  void
***************
*** 108,120 ****
  wgetscrmm(pmmwidth, pmmheight)
  	int *pmmwidth, *pmmheight;
  {
! 	Rect r;
! 	r= screen->portRect;
  	/* XXX Three pixels/mm is an approximation of the truth at most */
! 	*pmmwidth= (r.right - r.left) / 3;
! 	*pmmheight= (r.bottom - r.top) / 3;
  }
  
  /* Routine called by "Resume" button in bomb box (passed to InitDialogs).
     I have yet to see a program crash where an attempted exit to the
     Finder caused any harm, so I think it's safe.
--- 120,139 ----
  wgetscrmm(pmmwidth, pmmheight)
  	int *pmmwidth, *pmmheight;
  {
! 	int width, height;
! 	wgetscrsize(&width, &height);
  	/* XXX Three pixels/mm is an approximation of the truth at most */
! 	*pmmwidth= width / 3;
! 	*pmmheight= height / 3;
  }
  
+ int
+ wgetmouseconfig()
+ {
+ 	return WM_BUTTON1 | WM_SHIFT | WM_META | WM_LOCK | WM_OPTION;
+ 	/* XXX Should figure out if we have a Control button as well */
+ }
+ 
  /* Routine called by "Resume" button in bomb box (passed to InitDialogs).
     I have yet to see a program crash where an attempted exit to the
     Finder caused any harm, so I think it's safe.
***************
*** 126,131 ****
--- 145,151 ----
  	ExitToShell();
  }
  
+ 
  /* WINDOWS. */
  
  /* Find the WINDOW pointer corresponding to a WindowPtr. */
***************
*** 154,186 ****
  {
  	WINDOW *win= ALLOC(WINDOW);
  	Rect r;
  	
  	if (win == NULL) {
! 		dprintf("wopen: ALLOC failed"); /* XXX */
  		return NULL;
  	}
! 
! 	/* Find a nice position for the window. */
! 	if (def_left + def_width + BAR + LSLOP + RSLOP
! 			> screen->portRect.right) {
! 		def_left= LEFT;
! 		CLIPMAX(def_left, screen->portRect.right -
! 			(def_width + BAR + LSLOP + RSLOP));
! 		CLIPMIN(def_left, 0);
  	}
! 	if (def_top + def_height + BAR > screen->portRect.bottom) {
! 		def_top= TOP;
! 		CLIPMAX(def_top, screen->portRect.bottom -
! 			(def_height + BAR));
! 		CLIPMIN(def_top, MENUBARHEIGHT + TITLEBARHEIGHT);
  	}
  	
! 	SetRect(&r, def_left, def_top,
! 		def_left+def_width + BAR + LSLOP + RSLOP,
! 		def_top+def_height + BAR);
! 	def_left += HINCR;
! 	def_top += VINCR;
  	
  	win->w= NewWindow((Ptr)NULL, &r, PSTRING(title), TRUE, zoomDocProc,
  		(WindowPtr)(-1), TRUE, 0L);
  	SetWRefCon(win->w, (long)win);
--- 174,270 ----
  {
  	WINDOW *win= ALLOC(WINDOW);
  	Rect r;
+ 	int width, height;		/* As seen by the user */
+ 	int tot_width, tot_height;	/* Including slop & scroll bars */
+ 	int left, top;			/* Window corner as seen by the user */
  	
  	if (win == NULL) {
! 		dprintf("wopen: ALLOC failed");
  		return NULL;
  	}
! 	
! 	/* Determine window size.
! 	   If the program specified a size, use that, within reason --
! 	   sizes are clipped to 0x7000 to avoid overflow in QuickDraw's
! 	   calculations.
! 	   Otherwise, use two-third of the screen size, but at most
! 	   512x342 (to avoid creating gigantic windows by default on
! 	   large screen Macs). */
! 	
! 	if (def_width <= 0) {
! 		width = screen->portRect.right * 2/3;
! 		CLIPMAX(width, 512);
  	}
! 	else {
! 		width = def_width;
! 		CLIPMAX(width, 0x7000);
  	}
+ 	if (def_horscroll)
+ 		CLIPMIN(width, 3*BAR);
+ 	tot_width = width + LSLOP + RSLOP;
+ 	if (def_verscroll)
+ 		tot_width += BAR;
  	
! 	if (def_height <= 0) {
! 		height= screen->portRect.bottom * 2/3;
! 		CLIPMAX(height, 342);
! 	}
! 	else {
! 		height = def_height;
! 		CLIPMAX(height, 0x7000);
! 	}
! 	if (def_verscroll)
! 		CLIPMIN(height, 3*BAR);
! 	tot_height = height;
! 	if (def_horscroll)
! 		tot_height += BAR;
  	
+ 	/* Determine window position.
+ 	   It the program specified a position, use that, but make sure
+ 	   that at least a small piece of the title bar is visible --
+ 	   so the user can recover a window that "fell off the screen".
+ 	   Exception: the title bar may hide completely under the menu
+ 	   bar, since this is the only way to get an (almost) full
+ 	   screen window.
+ 	   Otherwise, place the window a little to the right and below
+ 	   the last window placed; it it doesn't fit, move it up.
+ 	   With default placement, the window will never hide under the
+ 	   title bar. */
+ 	
+ 	if (def_left <= 0) {
+ 		left = next_left;
+ 		if (left + tot_width >= screen->portRect.right) {
+ 			left = LEFT;
+ 			CLIPMAX(left, screen->portRect.right - tot_width);
+ 			CLIPMIN(left, 0);
+ 		}
+ 	}
+ 	else {
+ 		left = def_left - LSLOP;
+ 		CLIPMAX(left, screen->portRect.right - BAR);
+ 		CLIPMIN(left, BAR - tot_width);
+ 	}
+ 	
+ 	if (def_top <= 0) {
+ 		top = next_top;
+ 		if (top + tot_height >= screen->portRect.bottom) {
+ 			top = TOP;
+ 			CLIPMAX(top, screen->portRect.bottom - tot_height);
+ 			CLIPMIN(top, MENUBARHEIGHT + TITLEBARHEIGHT);
+ 		}
+ 	}
+ 	else {
+ 		top = def_top;
+ 		CLIPMAX(top, screen->portRect.bottom);
+ 		CLIPMIN(top, MENUBARHEIGHT);
+ 	}
+ 	
+ 	next_left = left + HINCR;
+ 	next_top = top + VINCR;
+ 	
+ 	/* Create the window now and initialize its attributes */
+ 	
+ 	SetRect(&r, left, top, left + tot_width, top + tot_height);
  	win->w= NewWindow((Ptr)NULL, &r, PSTRING(title), TRUE, zoomDocProc,
  		(WindowPtr)(-1), TRUE, 0L);
  	SetWRefCon(win->w, (long)win);
***************
*** 197,205 ****
  	win->orgv= 0;
  	win->timer= 0;
  	win->cursor = NULL;
  	
  	initmbar(&win->mbar);
! 	makescrollbars(win);
  	
  	return win;
  }
--- 281,295 ----
  	win->orgv= 0;
  	win->timer= 0;
  	win->cursor = NULL;
+ 	win->fgcolor = _w_fgcolor;
+ 	win->bgcolor = _w_bgcolor;
  	
+ 	SetPort(win->w);
+ 	_w_usefgcolor(win->fgcolor);
+ 	_w_usebgcolor(win->bgcolor);
+ 	
  	initmbar(&win->mbar);
! 	makescrollbars(win, def_horscroll, def_verscroll);
  	
  	return win;
  }
***************
*** 230,235 ****
--- 320,345 ----
  }
  
  void
+ wgetwinpos(win, ph, pv)
+ 	WINDOW *win;
+ 	int *ph, *pv;
+ {
+ 	Point p;
+ 	GrafPtr saveport;
+ 	
+ 	GetPort(&saveport);
+ 	
+ 	SetPort(win->w);
+ 	p.h = win->w->portRect.left + LSLOP;
+ 	p.v = win->w->portRect.top;
+ 	LocalToGlobal(&p);
+ 	*ph = p.h;
+ 	*pv = p.v;
+ 	
+ 	SetPort(saveport);
+ }
+ 
+ void
  wsettitle(win, title)
  	WINDOW *win;
  	char *title;
***************
*** 272,282 ****
  wsetdefwinpos(h, v)
  	int h, v;
  {
! 	/* XXX Sanity checks? Change interaction with wopen()? */
! 	if (h > 0)
! 		def_left = h;
! 	if (v > 0)
! 		def_top = v;
  }
  
  void
--- 382,389 ----
  wsetdefwinpos(h, v)
  	int h, v;
  {
! 	def_left = h;
! 	def_top = v;
  }
  
  void
***************
*** 291,312 ****
  wsetdefwinsize(width, height)
  	int width, height;
  {
- 	/* XXX Shouldn't this be done by wopen() instead? */
- 	if (width <= 0) {
- 		width= screen->portRect.right * 2/3;
- 		CLIPMAX(width, 512);
- 	}
- 	CLIPMAX(width, screen->portRect.right - BAR - LSLOP - RSLOP);
- 	CLIPMIN(width, MIN_WIDTH);
- 	
- 	if (height <= 0) {
- 		height= screen->portRect.bottom * 2/3;
- 		CLIPMAX(height, 342);
- 	}
- 	CLIPMAX(height, screen->portRect.bottom
- 		- MENUBARHEIGHT - TITLEBARHEIGHT - BAR);
- 	CLIPMIN(height, MIN_HEIGHT);
- 	
  	def_width= width;
  	def_height= height;
  }
--- 398,403 ----
***************
*** 320,327 ****
  }
  
  void
! wsetactive(win)
! 	WINDOW *win;
  {
! 	SelectWindow(win->w);
  }
--- 411,427 ----
  }
  
  void
! wsetdefscrollbars(hor, ver)
! 	int hor, ver;
  {
! 	def_horscroll = hor;
! 	def_verscroll = ver;
! }
! 
! void
! wgetdefscrollbars(phor, pver)
! 	int *phor, *pver;
! {
! 	*phor = def_horscroll;
! 	*pver = def_verscroll;
  }
*** 0.9.5/Ports/msdos/README	Thu Feb 28 11:30:38 1991
--- stdwin/Ports/msdos/README	Tue Apr 23 15:56:24 1991
***************
*** 1,4 ****
  Sorry, there is no real STDWIN port for MS-DOS yet.  What you can is
! to port the alfa version with the help of the file "ptrm.c" in this
  directory, which is a substitute (using the MS-DOS console driver) for
! the VTRM module used by the alfa version for all its tty I/O.
--- 1,5 ----
  Sorry, there is no real STDWIN port for MS-DOS yet.  What you can is
! to port the alfa version with the help of the file "vtrm.c" in this
  directory, which is a substitute (using the MS-DOS console driver) for
! the VTRM module used by the alfa version for all its tty I/O (the UNIX
! version of vtrm.c is in ../vtrm).
*** 0.9.5/Ports/msdos/dir.c	Wed Jun 24 13:40:34 1987
--- stdwin/Ports/msdos/dir.c	Tue Apr 23 15:56:39 1991
***************
*** 1,28 ****
  /*
   * MS-DOS version of UNIX directory access package.
   * (opendir, readdir, closedir).
   */
  
! #include <sys/types.h>
! #include <sys/stat.h>
! #include <errno.h>
  #include <dos.h>
! extern int errno;
! #define MAXPATH 64
! 
  #include "dir.h"
- static char *firstf();
- static char *nextf();
  
  typedef int bool;
! #define TRUE 1
! #define FALSE 0
  #define EOS '\0'
- #define NULL 0
  
! static char dirpath[MAXPATH+1]= "";
! static bool busy= FALSE;
  
  /*
   * Open a directory.
   * This MS-DOS version allows only one directory to be open at a time.
--- 1,38 ----
+ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1990. */
+ 
  /*
   * MS-DOS version of UNIX directory access package.
   * (opendir, readdir, closedir).
   */
  
! #include <stdio.h>
! #include <ctype.h>
! #include <string.h>
  #include <dos.h>
! #include <errno.h>
! #include <sys\types.h>
! #include <sys\stat.h>
  #include "dir.h"
  
+ #define Visible
+ #define Hidden static
+ #define Procedure
+ 
  typedef int bool;
! 
! #define Yes ((bool) 1)
! #define No  ((bool) 0)
! 
! #define MAXPATH 64
  #define EOS '\0'
  
! extern int errno;
! Hidden char *firstf();
! Hidden char *nextf();
  
+ Hidden char dirpath[MAXPATH+1] = "";
+ Hidden bool busy = No;
+ 
  /*
   * Open a directory.
   * This MS-DOS version allows only one directory to be open at a time.
***************
*** 30,153 ****
   * Then it only saves the file name and returns a pointer to it.
   */
  
! char *
! opendir(path)
! 	char *path;
  {
  	struct stat buffer;
  
  	if (dirpath[0] != EOS) {
! 		 errno= EMFILE;
  		 return NULL; /* Only one directory can be open at a time */
  	}
  	if (stat(path, &buffer) == -1)
  		return NULL; /* Directory doesn't exist */
  	if ((buffer.st_mode & S_IFMT) != S_IFDIR) {
! 		errno= ENOENT;
  		return NULL; /* Not a directory */
  	}
  	strcpy(dirpath, path);
! 	path= dirpath + strlen(dirpath);
  	if (path > dirpath && path[-1] != ':' && path[-1] != '/' &&
  			path[-1] != '\\')
  		*path++ = '\\';
  	strcpy(path, "*.*");
! 	busy= FALSE; /* Tell readdir this is the first time */
! 	return dirpath;
  }
  
  /*
-  * Close a directory.
-  * We must clear the first char of dirpath to signal opendir that
-  * no directory is open.
-  */
- 
- closedir(dirp)
- 	char *dirp;
- {
- 	dirp[0]= EOS;
- }
- 
- /*
   * Read the next directory entry.
   */
  
! struct direct *
! readdir(dp)
! 	char *dp;
  {
  	static struct direct buffer;
  	char *p;
  
  	if (!busy)
! 		p= firstf(dp);
  	else
! 		p= nextf();
! 	busy= (p != NULL);
  	if (!busy)
  		return NULL;
  	strcpy(buffer.d_name, p);
! 	buffer.d_namlen= strlen(p);
  	return &buffer;
  }
  
  
  /*
!  * Low-level implementation -- access to DOS system calls FIRST and NEXT.
   */
  
! static char dta[64]; /* Device Transfer Area */
  
! /* File attributes */
! #define READONLY	0x01
! #define HIDDEN		0x02
! #define SYSTEM		0x04
! #define VOLUMEID	0x08
! #define DIRECTORY	0x10
! #define ARCHIVE		0x20
  
! #define MATCHATTR	(HIDDEN|SYSTEM|DIRECTORY)
  
! static char *
! firstf(pat)
!     char *pat;
  {
!     int flags;
!     union REGS regs;
!     struct SREGS segregs;
  
!     setdta(dta);
  
!     segread(&segregs);
!     regs.h.ah = 0x4e;
!     regs.x.cx = MATCHATTR;
  #ifdef M_I86LM /* Large Model -- far pointers */
!     regs.x.dx = FP_OFF(pat);
!     segregs.ds = FP_SEG(pat);
  #else
!     regs.x.dx = (int) pat;
  #endif
!     flags= intdosx(&regs, &regs, &segregs);
!     if (regs.x.cflag)
! 	return NULL;
!     fixfile();
!     return dta + 30;
  }
  
! static char *
! nextf()
  {
!     int flags;
!     union REGS regs;
  
!     setdta(dta);
  
!     regs.h.ah = 0x4f;
!     flags= intdos(&regs, &regs);
!     if (regs.x.cflag)
! 	return NULL;
!     fixfile();
!     return dta + 30;
  }
  
  /*
--- 40,151 ----
   * Then it only saves the file name and returns a pointer to it.
   */
  
! Visible DIR *opendir(path)
!      char *path;
  {
  	struct stat buffer;
  
  	if (dirpath[0] != EOS) {
! 		 errno = EMFILE;
  		 return NULL; /* Only one directory can be open at a time */
  	}
  	if (stat(path, &buffer) == -1)
  		return NULL; /* Directory doesn't exist */
  	if ((buffer.st_mode & S_IFMT) != S_IFDIR) {
! 		errno = ENOENT;
  		return NULL; /* Not a directory */
  	}
  	strcpy(dirpath, path);
! 	path = dirpath + strlen(dirpath);
  	if (path > dirpath && path[-1] != ':' && path[-1] != '/' &&
  			path[-1] != '\\')
  		*path++ = '\\';
  	strcpy(path, "*.*");
! 	busy = No; /* Tell readdir this is the first time */
! 	return (DIR *) dirpath;
  }
  
  /*
   * Read the next directory entry.
   */
  
! Visible struct direct *readdir(dp)
!      char *dp;
  {
  	static struct direct buffer;
  	char *p;
  
  	if (!busy)
! 		p = firstf((char *)dp);
  	else
! 		p = nextf();
! 	busy = (p != NULL);
  	if (!busy)
  		return NULL;
  	strcpy(buffer.d_name, p);
! 	buffer.d_namlen = strlen(p);
  	return &buffer;
  }
  
  
  /*
!  * Close a directory.
!  * We must clear the first char of dirpath to signal opendir that
!  * no directory is open.
   */
  
! Visible Procedure closedir(dirp)
!      DIR *dirp;
! {
! 	dirp[0] = EOS;
! }
  
! /*
!  * Low-level implementation -- access to DOS system calls FIRST and NEXT.
!  */
  
! Hidden char dta[64]; /* Device Transfer Area */
  
! #define DIRATTR 0x10
! 
! Hidden char *firstf(pat)
!      char *pat;
  {
! 	static int flags;
! 	union REGS regs;
! 	struct SREGS segregs;
  
! 	setdta(dta);
  
! 	segread(&segregs);
! 	regs.h.ah = 0x4e;
! 	regs.x.cx = DIRATTR;
  #ifdef M_I86LM /* Large Model -- far pointers */
! 	regs.x.dx = FP_OFF(pat);
! 	segregs.ds = FP_SEG(pat);
  #else
! 	regs.x.dx = (int) pat;
  #endif
! 	flags = intdosx(&regs, &regs, &segregs);
! 	if (regs.x.cflag)
! 	  return NULL;
! 	fixfile();
! 	return dta + 30;
  }
  
! Hidden char *nextf()
  {
! 	int flags;
! 	union REGS regs;
  
! 	setdta(dta);
  
! 	regs.h.ah = 0x4f;
! 	flags = intdos(&regs, &regs);
! 	if (regs.x.cflag)
! 	  return NULL;
! 	fixfile();
! 	return dta + 30;
  }
  
  /*
***************
*** 154,166 ****
   * Convert the file name in the Device Transfer Area to lower case.
   */
  
! static
! fixfile()
  {
  	char *cp;
  
! 	for (cp= dta+30; *cp != EOS; ++cp)
! 		*cp= tolower(*cp);
  }
  
  /*
--- 152,163 ----
   * Convert the file name in the Device Transfer Area to lower case.
   */
  
! Hidden Procedure fixfile()
  {
  	char *cp;
  
! 	for (cp = dta+30; *cp != EOS; ++cp)
! 	  *cp = tolower(*cp);
  }
  
  /*
***************
*** 167,186 ****
   * Tell MS-DOS where the Device Transfer Area is.
   */
  
! static
! setdta(dta)
!     char *dta;
  {
!     union REGS regs;
!     struct SREGS segregs;
  
!     segread(&segregs);
!     regs.h.ah = 0x1a;
  #ifdef M_I86LM /* Large Model -- far pointers */
!     regs.x.dx = FP_OFF(dta);
!     segregs.ds = FP_SEG(dta);
  #else
!     regs.x.dx = (int) dta;
  #endif
!     intdosx(&regs, &regs, &segregs);
  }
--- 164,182 ----
   * Tell MS-DOS where the Device Transfer Area is.
   */
  
! Hidden Procedure setdta(dta)
!      char *dta;
  {
! 	union REGS regs;
! 	struct SREGS segregs;
  
! 	segread(&segregs);
! 	regs.h.ah = 0x1a;
  #ifdef M_I86LM /* Large Model -- far pointers */
! 	regs.x.dx = FP_OFF(dta);
! 	segregs.ds = FP_SEG(dta);
  #else
! 	regs.x.dx = (int) dta;
  #endif
! 	intdosx(&regs, &regs, &segregs);
  }
*** 0.9.5/Ports/msdos/dir.h	Wed Jun 24 13:38:30 1987
--- stdwin/Ports/msdos/dir.h	Tue Apr 23 15:56:53 1991
***************
*** 1,3 ****
--- 1,5 ----
+ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1990. */
+ 
  /*
   * Interface for MS-DOS version of UNIX directory access package.
   * (opendir, readdir, closedir).
***************
*** 10,14 ****
  
  typedef char DIR;
  
! DIR *opendir();
! struct direct *readdir();
--- 12,17 ----
  
  typedef char DIR;
  
! extern DIR *opendir();
! extern struct direct *readdir();
! extern closedir();
*** 0.9.5/Ports/msdos/lib.	Fri Sep  4 16:17:13 1987
--- stdwin/Ports/msdos/lib.	Tue Apr 23 15:57:05 1991
***************
*** 24,32 ****
  
  style.obj:
  
! PTRM=		ptrm.obj
  
! ptrm.obj:
  
  ALFA=		bind.obj draw.obj event.obj keymap.obj measure.obj \
  		menu.obj scroll.obj stdwin.obj syswin.obj
--- 24,32 ----
  
  style.obj:
  
! VTRM=		vtrm.obj
  
! vtrm.obj:
  
  ALFA=		bind.obj draw.obj event.obj keymap.obj measure.obj \
  		menu.obj scroll.obj stdwin.obj syswin.obj
***************
*** 49,52 ****
  
  syswin.obj: alfa.h
  
! ALL=		$(TOOLS) $(TEXTEDIT) $(PTRM) $(ALFA)
--- 49,52 ----
  
  syswin.obj: alfa.h
  
! ALL=		$(TOOLS) $(TEXTEDIT) $(VTRM) $(ALFA)
*** /dev/null	Fri Jun  7 14:31:40 1991
--- stdwin/Ports/msdos/vtrm.c	Tue Apr 23 15:52:28 1991
***************
*** 0 ****
--- 1,1137 ----
+ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1991. */
+ 
+ /*
+  * ibm Pc virtual TeRMinal package.
+  *
+  * (Under reconstruction by Guido!)
+  *
+  * An implementation of the VTRM interface for MS-DOS machines.
+  *
+  * This code supports two modes of accessing the screen.
+  * The first one (BIOS) will be used, unless the user overwrites this
+  * by setting the SCREEN environment variable.
+  * This variable can also be used to convey a screen size that differs
+  * from the default 25 lines and 80 columns. See below.
+  *
+  * The two modes are:
+  *
+  * 1) IBM BIOS interrupt 10 hex, video io.
+  *    (See IBM PC XT Technical Reference 6936833, May 1983,
+  *     Appendix A, pages A46-A47).
+  *    This is what you really want to use, since it's the only one that
+  *    can decently scroll. It cannot insert or delete characters, so
+  *    most optimisations from the unix version of vtrm.c are useless
+  *    and taken out.
+  *    Unfortunately, not every PC-compatible machine supports this BIOS
+  *    interrupt, so for these unlucky souls there is the following escape:
+  *
+  * 2) The ANSI.SYS driver.
+  *    (See IBM MS-DOS 6936839, Jan 1983, Version 2.00, Chapter 13.)
+  *    (Some compatibles don't have a separate ANSI.SYS driver but do the
+  *    same escape interpretation by default.)
+  *    This works reasonably, apart from scrolling downward, or part of
+  *    the screen, which is clumsy.
+  *    (The ANSI standard provides an escape sequence for scrolling
+  *    but ANSI.SYS does not support it, nor any other way of scrolling.)
+  *
+  * The rest of the interface is the same as described in the unix version,
+  * with the following exceptions:
+  *    - to ease coding for ansi scrolls, the terminal is supposed to
+  *	contain blanks at positions that were not written yet;
+  *	the unknown rubbish that is initially on the screen can
+  *	only be cleared by the caller by scrolling the whole screen up
+  *	by one or more lines;
+  *    - the number of lines on the terminal is assumed to be 25;
+  *	the number of columns is (1) determined by a BIOS function, or
+  *	(2) assumed to be 80 for ANSI;
+  *	the user can overwrite this by setting the environment variable:
+  *
+  *		SET SCREEN=BIOS y x
+  *	or
+  *		SET SCREEN=ANSI y x
+  *
+  *	where x and y are the number of lines and columns respectively.
+  *
+  * The lines and columns of our virtual terminal are numbered
+  *	y = {0...lines-1} from top to bottom, and
+  *	x = {0...cols-1} from left to right,
+  * respectively.
+  *
+  * The Visible Procedures in this package are as described in the unix version.
+  *
+  */
+ 
+ /* Includes: */
+ 
+ #include <stdio.h>
+ #include <ctype.h>
+ #include <string.h>
+ #include <dos.h>
+ #include <fcntl.h>
+ #include <io.h>
+ #include "vtrm.h"
+ 
+ /* Style definitions: */
+ 
+ #define Visible
+ #define Hidden static
+ #define Procedure
+ 
+ typedef int bool;
+ typedef char *string;
+ typedef short intlet;
+ 
+ #define Yes ((bool) 1)
+ #define No  ((bool) 0)
+ 
+ /* Forward declarations: */
+ 
+ extern char *malloc();
+ 
+ /* Data definitions: */
+ 
+ #ifdef VTRMTRACE
+ #define TRACEFILE "TRACE.TRM"
+ Hidden FILE *vtrmfp= (FILE *) NULL;
+ #endif
+ 
+ #define STDIN_HANDLE 0
+ 
+ #define Undefined (-1)
+ 
+ #define Min(a,b) ((a) <= (b) ? (a) : (b))
+ 
+ /* terminal status */
+ 
+ Hidden int started = No;
+ 
+ Hidden int scr_mode = 0;
+ #define ANSI 'A'
+ #define BIOS 'B'
+ 
+ #define Nlines	25
+ #define Ncols	80
+ Hidden int lines = Nlines;
+ Hidden int cols = Ncols;
+ Hidden int flags = 0;
+ 
+ /* current standout mode */
+ #define Off	PLAIN
+ #define On	STANDOUT
+ Hidden int so_mode = Off;
+ 
+ /* current cursor position */
+ Hidden intlet cur_y = Undefined, cur_x = Undefined;
+ 
+ /* "linedata[y][x]" holds the char on the terminal,
+  * "linemode[y][x]" the STANDOUT bit.
+  * The STANDOUT bit tells whether the character is standing out.
+  * "lenline[y]" holds the length of the line.
+  * (Partially) empty lines are distinghuished by "lenline[y] < cols".
+  * Unknown chars will be ' ', so the scrolling routines for ANSI
+  * can use "unwritten" chars (with indent > 0 in trmputdata).
+  * To make the optimising compare in putline fail, lenline[y] is initially 0.
+  * The latter implies that if a line is first addressed with trmputdata,
+  * any rubbish that is on the screen beyond the data that gets put, will
+  * remain there.
+  */
+ 
+ Hidden char 	**linedata = 0;
+ Hidden char 	**linemode = 0;
+ 
+ Hidden intlet *lenline = 0;
+ 
+ /* To compare the mode part of the line when the
+  * mode parameter of trmputdata == NULL, we use the following:
+  */
+ Hidden char plain[1]= {PLAIN};
+ 
+ /* Make the cursor invisible when trmsync() tries to move outside the screen */
+ Hidden bool no_cursor = No;
+ 
+ /*
+  * Starting, Ending and (fatal) Error.
+  */
+ 
+ Hidden bool wasbreak;
+ 
+ /*
+  * Initialization call.
+  * Determine terminal mode.
+  * Start up terminal and internal administration.
+  * Return Yes if succeeded, No if trouble (which doesn't apply here).
+  */
+ 
+ Visible int trmstart(plines, pcols, pflags)
+      int *plines;
+      int *pcols;
+      int *pflags;
+ {
+ 	static char setup = No;
+ 	int err;
+ 
+ #ifdef VTRMTRACE
+ 	if (!started) vtrmfp= fopen(TRACEFILE, vtrmfp ? "a" : "w");
+ 	if (vtrmfp) fprintf(vtrmfp, "\ttrmstart(&li, &co, &fl);\n");
+ #endif
+ 
+ 	if (started)
+ 		return TE_TWICE;
+ 
+ 	if (!setup) {
+ 		err = set_screen_up();
+ 		if (err != TE_OK)
+ 			return err;
+ 		setup = Yes;
+ 	}
+ 
+ 	err = start_trm();		/* internal administration */
+ 	if (err != TE_OK)
+ 		return err;
+ 
+ 	*plines = lines;
+ 	*pcols = cols;
+ 	*pflags = flags;
+ 
+ 	setmode(STDIN_HANDLE, O_BINARY); /* Don't translate CRLF to LF */
+ 	setraw(STDIN_HANDLE, Yes);
+ 	wasbreak = getbreak(); /* Save BREAK status; restore when done */
+ 	setbreak(No);
+ 
+ 	started = Yes;
+ 	return TE_OK;
+ }
+ 
+ Hidden int set_screen_up()
+ {
+ 	int height;
+ 	int width;
+ 	int get_screen_env();
+ 	int get_cols();
+ 
+ 	height = width = 0;
+ 	scr_mode = get_screen_env(&height, &width);
+ 
+ 	switch (scr_mode) {
+ 	case BIOS:
+ 	case TE_OK:
+ 		cols = get_cols();
+ 		flags = HAS_STANDOUT|CAN_SCROLL;
+ 		break;
+ 	case ANSI:
+ 		flags = HAS_STANDOUT;
+ 		break;
+ 	default:
+ 		return scr_mode; /* Error flag */
+ 	}
+ 
+ 	/* allow x and y in environment variable SCREEN to override */
+ 	if (height > 0)
+ 		lines = height;
+ 	if (width > 0)
+ 		cols = width;
+ 	return TE_OK;
+ }
+ 
+ Hidden int get_screen_env(pheight, pwidth)
+      int *pheight;
+      int *pwidth;
+ {
+ 	string s;
+ 	int mode;
+ 	char screrr;
+ 	string getenv();
+ 	string strip();
+ 	string skip();
+ 
+ 	screrr = No;
+ 	s = getenv("SCREEN");
+ 	if (s == NULL)
+ 		return BIOS;
+ 
+ 	s = strip(s);
+ 	switch (*s) {
+ 	case '\0':
+ 		return BIOS;
+ 	case 'a':
+ 		mode = ANSI;
+ 		s = skip(s, "ansi");
+ 		break;
+ 	case 'A':
+ 		mode = ANSI;
+ 		s = skip(s, "ANSI");
+ 		break;
+ 	case 'b':
+ 		mode = BIOS;
+ 		s = skip(s, "bios");
+ 		break;
+ 	case 'B':
+ 		mode = BIOS;
+ 		s = skip(s, "BIOS");
+ 		break;
+ 	default:
+ 		mode = BIOS;
+ 		screrr = Yes;
+ 	}
+ 
+ 	/* *pheight and *pwidth were set to 0 above */
+ 	s = strip(s);
+ 	while (isdigit(*s)) {
+ 		*pheight = *pheight * 10 + (*s++ - '0');
+ 	}
+ 	s = strip(s);
+ 	while (isdigit(*s)) {
+ 		*pwidth = *pwidth * 10 + (*s++ -'0');
+ 	}
+ 	s = strip(s);
+ 	if (screrr || *s != '\0')
+ 		return TE_BADSCREEN;
+ 
+ 	return mode;
+ }
+ 
+ Hidden string strip(s)
+      string s;
+ {
+ 	while (*s == ' ' || *s == '\t')
+ 		++s;
+ 	return s;
+ }
+ 
+ Hidden string skip(s, pat)
+      string s;
+      string pat;
+ {
+ 	while (*s && *s == *pat)
+ 		++s, ++pat;
+ 	return s;
+ }
+ 
+ /* initialise internal administration */
+ 
+ Hidden int start_trm()
+ {
+ 	register int y;
+ 
+ 	if (linedata == NULL) {
+ 		if ((linedata = (char**) malloc(lines * sizeof(char*))) == NULL)
+ 			return TE_NOMEM;
+ 		for (y = 0; y < lines; y++) {
+ 			if ((linedata[y] = (char*) malloc(cols * sizeof(char))) == NULL)
+ 				return TE_NOMEM;
+ 		}
+ 	}
+ 	if (linemode == NULL) {
+ 		if ((linemode = (char**) malloc(lines * sizeof(char*))) == NULL)
+ 			return TE_NOMEM;
+ 		for (y = 0; y < lines; y++) {
+ 			if ((linemode[y] = (char*) malloc(cols * sizeof(char))) == NULL)
+ 				return TE_NOMEM;
+ 		}
+ 	}
+ 	if (lenline == 0) {
+ 		if ((lenline = (intlet *) malloc(lines * sizeof(intlet))) == NULL)
+ 			return TE_NOMEM;
+ 	}
+ 		
+ 	trmundefined();
+ 	return TE_OK;
+ }
+ 
+ /*
+  * Termination call.
+  * Beware that it might be called by a catched interrupt even in the middle
+  * of trmstart()!
+  */
+ 
+ Visible Procedure trmend()
+ {
+ #ifdef VTRMTRACE
+ 	if (vtrmfp) fprintf(vtrmfp, "\ttrmend();\n");
+ #endif
+ 	if (started && so_mode != Off)
+ 		standend();
+ 	if (scr_mode == ANSI) {
+ 		fflush(stdout);
+ 	}
+ 	/* Always turn off RAW mode -- it is unlikely that anybody
+ 	   would want to interface to COMMAND.COM in raw mode.
+ 	   This way, if you were accidentally left in RAW mode
+ 	   because of a crash, it will go away if you re-enter. */
+ 	setraw(STDIN_HANDLE, No);
+ 	setbreak(wasbreak);
+ 
+ 	started = No;
+ #ifdef VTRMTRACE
+ 	if (vtrmfp) fclose(vtrmfp);
+ #endif
+ }
+ 
+ /*
+  * Set all internal statuses to undefined, especially the contents of
+  * the screen, so a hard redraw will not be optimised to heaven.
+  */
+ 
+ Visible Procedure trmundefined()
+ {
+ 	register int y, x;
+ #ifdef VTRMTRACE
+ 	if (vtrmfp) fprintf(vtrmfp, "\ttrmundefined();\n");
+ #endif
+ 
+ 	cur_y = cur_x = Undefined;
+ 	so_mode = Undefined;
+ 
+ 	for (y = 0; y < lines; y++) {
+ 		for (x = 0; x < cols; x++) {
+ 			linedata[y][x] = ' ';
+ 			linemode[y][x] = PLAIN;
+ 		}
+ 			/* they may get printed in scrolling */
+ 		lenline[y] = cols;
+ 	}
+ }
+ 
+ #ifdef VTRMTRACE
+ 
+ Hidden Procedure check_started(m)
+      char *m;
+ {
+ 	if (!started) {
+ 		trmend();
+ 		if (vtrmfp) fprintf(vtrmfp, "Not started: %s\n", m);
+ 		exit(TE_TWICE);
+ 	}
+ }
+ #else
+ 
+ #define check_started(m) /*empty*/
+ 
+ #endif
+ 
+ /*
+  * Sensing the cursor.
+  * (NOT IMPLEMENTED, since there is no way to locally move the cursor.)
+  */
+ 
+ /*
+  * Sense the current (y, x) cursor position, after a possible manual
+  * change by the user with local cursor motions.
+  * If the terminal cannot be asked for the current cursor position,
+  * or if the string returned by the terminal is garbled,
+  * the position is made Undefined.
+  */
+ Visible Procedure trmsense(sense, format, py, px)
+      string sense;
+      string format;
+      int *py;
+      int *px;
+ {
+ #ifdef VTRMTRACE
+ 	if (vtrmfp) fprintf(vtrmfp, "\ttrmsense(&yy, &xx);\n");
+ #endif
+ 	check_started("trmsense called outside trmstart/trmend");
+ 
+ /*	*py = *px = Undefined;
+  *
+  *
+  *	if (flags&CAN_SENSE && getpos(py, px)) {
+  *		if (*py < 0 || lines <= *py || *px < 0 || cols <= *px)
+  *			*py = *px = Undefined;
+  *	}
+  */
+ 	*py = *px= Undefined;
+ }
+ 
+ /*
+  * Putting data on the screen.
+  */
+ 
+ /*
+  * Fill screen area with given "data".
+  * Characters for which the corresponding chars in "mode" have the value
+  * STANDOUT must be put in inverse video.
+  */
+ Visible Procedure trmputdata(yfirst, ylast, indent, data, mode)
+      int yfirst;
+      int ylast;
+      register int indent;
+      register string data;
+      string mode;
+ {
+ 	register int y;
+ 	int x, len, lendata, space;
+ 
+ #ifdef VTRMTRACE
+ 	if (vtrmfp) fprintf(vtrmfp, "\ttrmputdata(%d, %d, %d, \"%s\");\n",
+ 				yfirst, ylast, indent, data);
+ #endif
+ 	check_started("trmputdata called outside trmstart/trmend");
+ 
+ 	if (yfirst < 0)
+ 		yfirst = 0;
+ 	if (ylast >= lines)
+ 		ylast = lines-1;
+ 	space = cols*(ylast-yfirst+1) - indent;
+ 	if (space <= 0)
+ 		return;
+ 	yfirst += indent/cols;
+ 	indent %= cols;
+ 	y = yfirst;
+ 	if (data) {
+ 		x = indent;
+ 		lendata = strlen(data);
+ 		if (ylast == lines-1 && lendata >= space)
+ 			lendata = space - 1;
+ 		len = Min(lendata, cols-x);
+ 		while (/*** len > 0 && ***/ y <= ylast) {
+ 			put_line(y, x, data, mode, len);
+ 			y++;
+ 			lendata -= len;
+ 			if (lendata > 0) {
+ 				x = 0;
+ 				data += len;
+ 				if (mode != NULL)
+ 					mode += len;
+ 				len = Min(lendata, cols);
+ 			}
+ 			else
+ 				break;
+ 		}
+ 	}
+ 	if (y <= ylast)
+ 		clear_lines(y, ylast);
+ }
+ 
+ /*
+  * We will try to get the picture:
+  *
+  *		    op>>>>>>>>>>>op				       oq
+  *		    ^		 ^				       ^
+  *	     <xskip><-----m1----><---------------od-------------------->
+  *   OLD:   "You're in a maze of twisty little pieces of code, all alike"
+  *   NEW:	   "in a maze of little twisting pieces of code, all alike"
+  *		    <-----m1----><----------------nd--------------------->
+  *		    ^		 ^					 ^
+  *		    np>>>>>>>>>>>np					 nq
+  * where
+  *	op, oq, np, nq are pointers to start and end of Old and New data,
+  * and
+  *	xskip = length of indent to be skipped,
+  *	m1 = length of Matching part at start,
+  *	od = length of Differing end on screen,
+  *	nd = length of Differing end in data to be put.
+  */
+ Hidden int put_line(y, xskip, data, mode, len)
+      int y;
+      int xskip;
+      string data;
+      string mode;
+      int len;
+ {
+ 	register char *op, *oq, *mp;
+ 	char *np, *nq, *mo;
+ 	int m1, od, nd, delta;
+ 
+ 	/* Bugfix GvR 19-June-87: */
+ 	while (lenline[y] < xskip) {
+ 		linedata[y][lenline[y]] = ' ';
+ 		linemode[y][lenline[y]] = PLAIN;
+ 		lenline[y]++;
+ 	}
+ 	
+ 	/* calculate the magic parameters */
+ 	op = &linedata[y][xskip];
+ 	oq = &linedata[y][lenline[y]-1];
+ 	mp = &linemode[y][xskip];
+ 	np = data;
+ 	nq = data + len - 1;
+ 	mo = (mode != NULL ? mode : plain);
+ 	m1 = 0;
+ 	while (*op == *np && *mp == *mo && op <= oq && np <= nq) {
+ 		op++, np++, mp++, m1++;
+ 		if (mode != NULL) mo++;
+ 	}
+ 	od = oq - op + 1;
+ 	nd = nq - np + 1;
+ 	/* now we have the picture above */
+ 
+ 	if (od==0 && nd==0)
+ 		return;
+ 
+ 	delta = nd - od;
+ 	move(y, xskip + m1);
+ 	if (nd > 0) {
+ 		mo= (mode != NULL ? mode+(np-data) : NULL);
+ 		put_str(np, mo, nd);
+ 	}
+ 	if (delta < 0) {
+ 		clr_to_eol();
+ 		return;
+ 	}
+ 	lenline[y] = xskip + len;
+ 	if (cur_x == cols) {
+ 		cur_y++;
+ 		cur_x = 0;
+ 	}
+ }
+ 
+ /*
+  * Scrolling (part of) the screen up (or down, dy<0).
+  */
+ 
+ Visible Procedure trmscrollup(yfirst, ylast, by)
+      register int yfirst;
+      register int ylast;
+      register int by;
+ {
+ #ifdef VTRMTRACE
+ 	if (vtrmfp) fprintf(vtrmfp, "\ttrmscrollup(%d, %d, %d);\n", yfirst, ylast, by);
+ #endif
+ 	check_started("trmscrollup called outside trmstart/trmend");
+ 
+ 	if (by == 0)
+ 		return;
+ 
+ 	if (yfirst < 0)
+ 		yfirst = 0;
+ 	if (ylast >= lines)
+ 		ylast = lines-1;
+ 
+ 	if (yfirst > ylast)
+ 		return;
+ 
+ 	if (so_mode != Off)
+ 		standend();
+ 
+ 	if (by > 0 && yfirst + by > ylast
+ 	    ||
+ 	    by < 0 && yfirst - by > ylast)
+ 	{
+ 		clear_lines(yfirst, ylast);
+ 		return;
+ 	}
+ 
+ 	switch (scr_mode) {
+ 	case BIOS:
+ 		biosscrollup(yfirst, ylast, by);
+ 		break;
+ 	case ANSI:
+ 		if (by > 0 && yfirst == 0) {
+ 			lf_scroll(ylast, by);
+ 		}
+ 		else if (by > 0) {
+ 			move_lines(yfirst+by, yfirst, ylast-yfirst+1-by, 1);
+ 			clear_lines(ylast-by+1, ylast);
+ 		}
+ 		else {
+ 			move_lines(ylast+by, ylast, ylast-yfirst+1+by, -1);
+ 			clear_lines(yfirst, yfirst-by-1);
+ 		}
+ 		break;
+ 	}
+ }
+ 
+ /*
+  * Synchronization, move cursor to given position (or previous if < 0).
+  */
+ 
+ Visible Procedure trmsync(y, x)
+      int y;
+      int x;
+ {
+ #ifdef VTRMTRACE
+ 	if (vtrmfp) fprintf(vtrmfp, "\ttrmsync(%d, %d);\n", y, x);
+ #endif
+ 	check_started("trmsync called outside trmstart/trmend");
+ 
+ 	if (0 <= y && y < lines && 0 <= x && x < cols) {
+ 		move(y, x);
+ 	}
+ 	fflush(stdout);
+ }
+ 
+ /*
+  * Send a bell, visible if possible.
+  */
+ 
+ Visible Procedure trmbell() {
+ #ifdef VTRMTRACE
+ 	if (vtrmfp) fprintf(vtrmfp, "\ttrmbell();\n");
+ #endif
+ 	check_started("trmbell called outside trmstart/trmend");
+ 	ring_bell();
+ }
+ 
+ /*
+  * Now for the real work: here are all low level routines that really
+  * differ for BIOS or ANSI mode.
+  */
+ 
+ /*
+  * BIOS video io is called by generating an 8086 software interrupt,
+  * using lattice's int86() function.
+  * To ease coding, all routines fill in the apropriate parameters in regs,
+  * and then call bios10(code), where code is to be placed in ah.
+  */
+ 
+ Hidden union REGS regs, outregs;
+ 
+ /* A macro for speed  */
+ #define bios10(code) (regs.h.ah = (code), int86(0x10, &regs, &regs))
+ #define nbios10(code) (regs.h.ah = (code), int86(0x10, &regs, &outregs))
+ 
+ /* Video attributes: (see the BASIC manual) (used for standout mode) */
+ 
+ Hidden int video_attr;
+ #define V_NORMAL 7
+ #define V_STANDOUT (7<<4)
+ 
+ /* Some BIOS only routines */
+ 
+ Hidden get_cols()
+ {
+ 	bios10(15);
+ 	return regs.h.ah;
+ }
+ 
+ /*
+  * ANSI escape sequences
+  */
+ #define A_CUP	"\033[%d;%dH"   /* cursor position */
+ #define A_SGR0	"\033[0m"       /* set graphics rendition to normal */
+ #define A_SGR7	"\033[7m"       /* set graphics rendition to standout */
+ #define A_ED	"\033[2J"       /* erase display (and cursor home) */
+ #define A_EL	"\033[K"        /* erase (to end of) line */
+ 
+ /*
+  * The following routine is the time bottleneck, I believe!
+  */
+ 
+ Hidden Procedure put_str(data, mode, n)
+      char *data;
+      char *mode;
+      int n;
+ {
+ 	register char c, mo, so;
+ 
+ 	so = so_mode;
+ 	if (scr_mode == BIOS) {
+ 		regs.x.cx = 1;	/* repition count */
+ 		regs.h.bh = 0;	/* page number */
+ 		regs.h.bl = video_attr;
+ 		while (--n >= 0) {
+ 			c = *data++;
+ 			mo= (mode != NULL ? *mode++ : PLAIN);
+ 			if (mo != so) {
+ 				so= mo;
+ 				so ? standout() : standend();
+ 				regs.h.bl = video_attr;
+ 			}
+ 			regs.h.al = c /* &CHAR */;
+ 			nbios10(9);
+ 			if (cur_x >= cols-1) {
+ 				linedata[cur_y][cols-1] = c;
+ 				linemode[cur_y][cols-1] = mo;
+ 				continue;
+ 			}
+ 			regs.h.dh = cur_y;
+ 			regs.h.dl = cur_x + 1;
+ 			nbios10(2);
+ 			linedata[cur_y][cur_x] = c;
+ 			linemode[cur_y][cur_x]= mo;
+ 			cur_x++;
+ 		}
+ 	}
+ 	else {
+ 		while (--n >= 0) {
+ 			c = *data++;
+ 			mo= (mode != NULL ? *mode++ : PLAIN);
+ 			if (mo != so) {
+ 				so= mo;
+ 				so ? standout() : standend();
+ 			}
+ 			putch(c);
+ 			linedata[cur_y][cur_x] = c;
+ 			linemode[cur_y][cur_x]= mo;
+ 			cur_x++;
+ 		}
+ 	}
+ }
+ 
+ /*
+  * Move to position y,x on the screen
+  */
+ 
+ Hidden Procedure move(y, x)
+      int y;
+      int x;
+ {
+ 	if (scr_mode != BIOS && cur_y == y && cur_x == x)
+ 		return;
+ 	switch (scr_mode) {
+ 	case BIOS:
+ 		regs.h.dh = y;
+ 		regs.h.dl = x;
+ 		regs.h.bh = 0; /* Page; must be 0 for graphics */
+ 		bios10(2);
+ 		break;
+ 	case ANSI:
+ 		cprintf(A_CUP, y+1, x+1);
+ 		break;
+ 	}
+ 	cur_y = y;
+ 	cur_x = x;
+ }
+ 
+ Hidden Procedure standout()
+ {
+ 	so_mode = On;
+ 	switch (scr_mode) {
+ 	case BIOS:
+ 		video_attr = V_STANDOUT;
+ 		break;
+ 	case ANSI:
+ 		cputs(A_SGR7);
+ 		break;
+ 	}
+ }
+ 
+ Hidden Procedure standend()
+ {
+ 	so_mode = Off;
+ 	switch (scr_mode) {
+ 	case BIOS:
+ 		video_attr = V_NORMAL;
+ 		break;
+ 	case ANSI:
+ 		cputs(A_SGR0);
+ 		break;
+ 	}
+ }
+ 
+ Hidden Procedure clear_lines(yfirst, ylast)
+      int yfirst;
+      int ylast;
+ {
+ 	register int y;
+ 
+ 	if (scr_mode == BIOS) {
+ 		regs.h.al = 0;	/* scroll with al = 0 means blank window */
+ 		regs.h.ch = yfirst;
+ 		regs.h.cl = 0;
+ 		regs.h.dh = ylast;
+ 		regs.h.dl = cols-1;
+ 		regs.h.bh = V_NORMAL;
+ 		bios10(6);
+ 		for (y = yfirst; y <= ylast; y++)
+ 			lenline[y] = 0;
+ 		return;
+ 	}
+ 	/* scr_mode == ANSI */
+ 	if (yfirst == 0 && ylast == lines-1) {
+ 		if (so_mode == On)
+ 			standend();
+ 		move(0, 0);		/* since some ANSI'd don't move */
+ 		cputs(A_ED);
+ 		cur_y = cur_x = 0;
+ 		for (y = yfirst; y < ylast; y++)
+ 			lenline[y] = 0;
+ 		return;
+ 	}
+ 	for (y = yfirst; y <= ylast; y++) {
+ 		if (lenline[y] > 0) {
+ 			move(y, 0);
+ 			clr_to_eol();
+ 		}
+ 	}
+ }
+ 
+ Hidden Procedure clr_to_eol()
+ {
+ 	if (so_mode == On)
+ 		standend();
+ 	switch (scr_mode) {
+ 	case BIOS:
+ 		regs.h.bh = 0;	/* page */
+ 		regs.x.cx = lenline[cur_y] - cur_x;
+ 		regs.h.al = ' ';
+ 		regs.h.bl = V_NORMAL;
+ 		bios10(9);
+ 		break;
+ 	case ANSI:
+ 		cputs(A_EL);
+ 		break;
+ 	}
+ 	lenline[cur_y] = cur_x;
+ }
+ 
+ /* scrolling for BIOS */
+ 
+ Hidden Procedure biosscrollup(yfirst, ylast, by)
+      int yfirst;
+      int ylast;
+      int by;
+ {
+ 	regs.h.al = (by < 0 ? -by : by);
+ 	regs.h.ch = yfirst;
+ 	regs.h.cl = 0;
+ 	regs.h.dh = ylast;
+ 	regs.h.dl = cols-1;
+ 	regs.h.bh= V_NORMAL;
+ 	bios10(by < 0 ? 7 : 6);
+ 	cur_y = cur_x = Undefined;
+ 	if (by > 0)
+ 		scr_lines(yfirst, ylast, by, 1);
+ 	else
+ 		scr_lines(ylast, yfirst, -by, -1);
+ }
+ 
+ /* Reset internal administration accordingly */
+ 
+ Hidden Procedure scr_lines(yfrom, yto, n, dy)
+      int yfrom;
+      int yto;
+      int n;
+      int dy;
+ {
+ 	register int y, x;
+ 	char *savedata;
+ 	char *savemode;
+ 
+ 	while (n-- > 0) {
+ 		savedata = linedata[yfrom];
+ 		savemode= linemode[yfrom];
+ 		for (y = yfrom; y != yto; y += dy) {
+ 			linedata[y] = linedata[y+dy];
+ 			linemode[y] = linemode[y+dy];
+ 			lenline[y] = lenline[y+dy];
+ 		}
+ 		linedata[yto] = savedata;
+ 		linemode[yto] = savemode;
+ 		for (x = 0; x < cols; x++ ) {
+ 			linedata[yto][x] = ' ';
+ 			linemode[yto][x] = PLAIN;
+ 		}
+ 		lenline[yto] = 0;
+ 	}
+ }
+ 
+ Hidden Procedure lf_scroll(yto, by)
+      int yto;
+      int by;
+ {
+ 	register int n = by;
+ 
+ 	move(lines-1, 0);
+ 	while (n-- > 0) {
+ 		putch('\n');
+ 	}
+ 	scr_lines(0, lines-1, by, 1);
+ 	move_lines(lines-1-by, lines-1, lines-1-yto, -1);
+ 	clear_lines(yto-by+1, yto);
+ }
+ 
+ /* for dumb scrolling, uses and updates internal administration */
+ 
+ Hidden Procedure move_lines(yfrom, yto, n, dy)
+      int yfrom;
+      int yto;
+      int n;
+      int dy;
+ {
+ 	while (n-- > 0) {
+ 		put_line(yto, 0, linedata[yfrom], linemode[yfrom], lenline[yfrom]);
+ 		yfrom += dy;
+ 		yto += dy;
+ 	}
+ }
+ 
+ Hidden Procedure ring_bell()
+ {
+ 	switch (scr_mode) {
+ 	case BIOS:
+ 		regs.h.al = '\007';
+ 		regs.h.bl = V_NORMAL;
+ 		bios10(14);
+ 		break;
+ 	case ANSI:
+ 		putch('\007');
+ 		break;
+ 	}
+ }
+ 
+ /*
+  * Show the current internal statuses of the screen on vtrmfp.
+  * For debugging only.
+  */
+ 
+ #ifdef SHOW
+ Visible Procedure trmshow(s)
+      char *s;
+ {
+ 	int y, x;
+ 
+ 	if (!vtrmfp)
+ 		return;
+ 	fprintf(vtrmfp, "<<< %s >>>\n", s);
+ 	for (y = 0; y < lines; y++) {
+ 		for (x = 0; x <= lenline[y] /*** && x < cols ***/ ; x++) {
+ 			fputc(linedata[y][x], vtrmfp);
+ 		}
+ 		fputc('\n', vtrmfp);
+ 		for (x = 0; x <= lenline[y] && x < cols-1; x++) {
+ 			if (linemode[y][x] == STANDOUT)
+ 				fputc('-', vtrmfp);
+ 			else
+ 				fputc(' ', vtrmfp);
+ 		}
+ 		fputc('\n', vtrmfp);
+ 	}
+ 	fprintf(vtrmfp, "CUR_Y = %d, CUR_X = %d.\n", cur_y, cur_x);
+ 	fflush(vtrmfp);
+ }
+ #endif
+ 
+ /*
+  * Interrupt handling.
+  *
+  * (This has not properly been tested, nor is it clear that
+  * this interface is what we want.  Anyway, it's here for you
+  * to experiment with.  What does it do, you may ask?
+  * Assume an interactive program which reads its characters
+  * through trminput.  Assume ^C is the interrupt character.
+  * Normally, ^C is treated just like any other character: when
+  * typed, it turns up in the input.  The program may understand
+  * input ^C as "quit from the current mode".
+  * Occasionally, the program goes into a long period of computation.
+  * Now it would be uninterruptible, except if it calls a routine,
+  * say pollinterrupt(), at times in its computational loop;
+  * pollinterrupt() magically looks ahead in the input queue, 
+  * via trmavail() and trminput(), and if it sees a ^C, discards all input
+  * before that point and returns Yes.  It also sets a flag, so that
+  * the interupt "sticks around" until either trminput or trmavail
+  * is called.  It is undefined whether typing ^C several times in
+  * a row is seen as one interrupt, or an interrupt followed by input
+  * of ^C's.  A program should be prepared for either.)
+  */
+ 
+ #ifdef NOT_USED
+ 
+ extern bool intrflag;
+ 
+ bool trminterrupt()
+ {
+ 	/* Force a check for ^C which will call handler. */
+ 	/* (This does a ^C check even if stdin is in RAW mode. */
+ 	(void) kbhit();
+ 	return intrflag;
+ }
+ 
+ #endif /* NOT_USED */
+ 
+ 
+ /* Definitions for DOS function calls. */
+ 
+ #define IOCTL		0x44
+ #define IOCTL_GETDATA	0x4400
+ #define IOCTL_SETDATA	0x4401
+ #define DEVICEBIT	0x80
+ #define RAWBIT		0x20
+ 
+ #define BREAKCK		0x33
+ #define GET		0x00
+ #define SET		0x01
+ 
+ #define IOCTL_GETSTS	0x4406
+ 
+ /*
+  * Terminal input without echo.
+  */
+ 
+ Visible int trminput()
+ {
+ 	char c;
+ 
+ #ifdef NOT_USED
+ 	intrflag= No;
+ #endif
+ 	/* Assume stdin is in RAW mode; this turns echo and ^C checks off. */
+ 	if (read(STDIN_HANDLE, &c, 1) < 1)
+ 		return -1;
+ 	else
+ 		return c;
+ }
+ 
+ /*
+  * Check for character available.
+  *
+  */
+ 
+ Visible bool trmavail()
+ {
+ #ifdef NOT_USED
+ 	intrflag= No;
+ #endif
+ 	regs.x.ax = IOCTL_GETSTS;
+ 	regs.x.bx = STDIN_HANDLE;
+ 	intdos(&regs, &regs);
+ 	if (regs.x.cflag)
+ 		return -1; /* Error */
+ 	return regs.h.al != 0;
+ }
+ 
+ /* Issue an IOCTL to turn RAW for a device on or off. */
+ 
+ Hidden Procedure setraw(handle, raw)
+      int handle;
+      bool raw;
+ {
+ 	regs.x.ax = IOCTL_GETDATA;
+ 	regs.x.bx = handle;
+ 	intdos(&regs, &regs);
+ 	if (regs.x.cflag || !(regs.h.dl & DEVICEBIT))
+ 		return; /* Error or not a device -- ignore it */
+ 	regs.h.dh = 0;
+ 	if (raw)
+ 		regs.h.dl |= RAWBIT;
+ 	else
+ 		regs.h.dl &= ~RAWBIT;
+ 	regs.x.ax = IOCTL_SETDATA;
+ 	intdos(&regs, &regs);
+ 	/* Ignore errors */
+ }
+ 
+ /* Get the raw bit of a device. */
+ 
+ Hidden int getraw(handle)
+      int handle;
+ {
+ 	regs.x.ax = IOCTL_GETDATA;
+ 	regs.x.bx = handle;
+ 	intdos(&regs, &regs);
+ 	return !regs.x.cflag &&
+ 		(regs.h.dh & (DEVICEBIT|RAWBIT)) == (DEVICEBIT|RAWBIT);
+ }
+ 
+ /* Set the break status. */
+ 
+ Hidden Procedure setbreak(on)
+      bool on;
+ {
+ 	bdos(BREAKCK, on, SET);
+ }
+ 
+ /* Get the break status. */
+ 
+ Hidden int getbreak()
+ {
+ 	regs.x.ax = (BREAKCK << 8) | GET;
+ 	intdos(&regs, &regs);
+ 	return regs.h.dl;
+ }
+ 
+ Visible int trmsuspend()
+ {
+ 	return spawnlp(P_WAIT, "COMMAND.COM", NULL) == 0;
+ }
*** /dev/null	Fri Jun  7 14:31:40 1991
--- stdwin/Ports/vtrm/os.h	Tue May 14 13:45:59 1991
***************
*** 0 ****
--- 1,33 ----
+ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1991. */
+ 
+ /* Auto-configuration file for vtrm.
+    Edit this if you have portability problems. */
+ 
+ #include <stdio.h>
+ #include <ctype.h>
+ #include <string.h>		/* Or <strings.h> for 4.2 BSD */
+ 
+ /* is this a termio system ? */
+ #ifdef SYSV
+ #define HAS_TERMIO
+ #endif
+ 
+ /* 4.2 BSD select() system call available ? */
+ #ifndef SYSV
+ #define HAS_SELECT
+ #endif
+ 
+ /* can #include <signal.h> ? */
+ #define SIGNAL
+ 
+ #ifdef SIGNAL
+ #define SIGTYPE void
+ /* type returned by signal handler function: (used to be int) */
+ #endif
+ 
+ /* can #include <setjmp.h> ? */
+ #define SETJMP
+ 
+ /* VOID is used in casts only, for quieter lint */
+ /* make it empty if your compiler doesn't have void */
+ #define VOID (void)
*** 0.9.5/Ports/x11/dialog.c	Thu Oct 18 13:58:40 1990
--- stdwin/Ports/x11/dialog.c	Wed Apr  3 22:10:08 1991
***************
*** 3,8 ****
--- 3,16 ----
  #include "x11.h"
  #include "llevent.h"
  
+ /* Forward static function declarations */
+ 
+ static int dialog _ARGS((char *, char *, int, int, int));
+ static void addbutton _ARGS((int, char *, int, bool, int, int, int, int));
+ static int dialogeventloop _ARGS((int));
+ static int charcode _ARGS((XKeyEvent *));
+ static bool addchar _ARGS((int));
+ 
  /* The kinds of dialogs we know */
  
  #define MESSAGEKIND	0
***************
*** 76,81 ****
--- 84,97 ----
  static int promptwidth;
  static int buttonwidth;
  
+ /* Forward static function declarations */
+ 
+ static bool buttonevent _ARGS((struct button *, XEvent *));
+ static void drawbutton _ARGS((struct button *));
+ static void hilitebutton _ARGS((struct button *, bool));
+ static void gettext _ARGS((char *, int));
+ static void killbuttons _ARGS((void));
+ 
  /* Dialog routine.
     Create the window and subwindows, then engage in interaction.
     Return the proper return value for waskync or waskstr.
***************
*** 191,200 ****
  	
  	/* Create the box window and its GC */
  	
! 	fg= _wgetpixel("menuForeground", "Foreground",
! 						BlackPixelOfScreen(_ws));
! 	bg= _wgetpixel("menuBackground", "Background",
! 						WhitePixelOfScreen(_ws));
  	box.border= 2*IBORDER;
  	(void) _wcreate(&box, RootWindowOfScreen(_ws), 0, FALSE, fg, bg);
  	_wsaveunder(&box, True);
--- 207,214 ----
  	
  	/* Create the box window and its GC */
  	
! 	fg = _wgetpixel("menuForeground", "MenuForeground", _w_fgcolor);
! 	bg = _wgetpixel("menuBackground", "MenuBackground", _w_bgcolor);
  	box.border= 2*IBORDER;
  	(void) _wcreate(&box, RootWindowOfScreen(_ws), 0, FALSE, fg, bg);
  	_wsaveunder(&box, True);
***************
*** 201,206 ****
--- 215,221 ----
  	XSelectInput(_wd, box.wid,
  		ExposureMask|KeyPressMask|StructureNotifyMask);
  	b_gc= _wgcreate(box.wid, _wf->fid, fg, bg);
+ 	XSetPlaneMask(_wd, b_gc, fg ^ bg);
  	
  	/* Keep window managers happy:
  	   a name for WM's that insist on displaying a window title;
***************
*** 330,336 ****
  
  /* Add a command button */
  
! static
  addbutton(type, text, ret, def, x, y, width, height)
  	int type;
  	char *text;
--- 345,351 ----
  
  /* Add a command button */
  
! static void
  addbutton(type, text, ret, def, x, y, width, height)
  	int type;
  	char *text;
***************
*** 559,565 ****
  
  /* Draw procedure to draw a command button or text item */
  
! static
  drawbutton(bp)
  	struct button *bp;
  {
--- 574,580 ----
  
  /* Draw procedure to draw a command button or text item */
  
! static void
  drawbutton(bp)
  	struct button *bp;
  {
***************
*** 590,596 ****
  
  /* Highlight or unhighlight a command button */
  
! static
  hilitebutton(bp, hilite)
  	struct button *bp;
  	bool hilite;
--- 605,611 ----
  
  /* Highlight or unhighlight a command button */
  
! static void
  hilitebutton(bp, hilite)
  	struct button *bp;
  	bool hilite;
***************
*** 604,610 ****
  
  /* Extract the text from the text item */
  
! static
  gettext(buf, len)
  	char *buf;
  	int len;
--- 619,625 ----
  
  /* Extract the text from the text item */
  
! static void
  gettext(buf, len)
  	char *buf;
  	int len;
***************
*** 619,625 ****
  
  /* Destroy all buttons and associated data structures */
  
! static
  killbuttons()
  {
  	int i;
--- 634,640 ----
  
  /* Destroy all buttons and associated data structures */
  
! static void
  killbuttons()
  {
  	int i;
*** 0.9.5/Ports/x11/draw.c	Thu Oct 18 13:58:40 1990
--- stdwin/Ports/x11/draw.c	Tue May 14 13:47:44 1991
***************
*** 6,29 ****
  
  static Window wid;
  static GC gc;
! static unsigned long fg, bg;
  
- /* Start using the given Window ID, GC, fg and bg.
-    (I had hoped to use this from the Dialog and Menu modules,
-    but this hope didn't come true.) */
- 
- static void
- _wusewgc(awid, agc, afg, abg)
- 	Window awid;
- 	GC agc;
- 	unsigned long afg, abg;
- {
- 	wid= awid;
- 	gc= agc;
- 	fg= afg;
- 	bg= abg;
- }
- 
  /* Put the current font's ID in the current GC, if non-null.
     Called by _wfontswitch. */
  
--- 6,13 ----
  
  static Window wid;
  static GC gc;
! COLOR _w_fgcolor, _w_bgcolor;
  
  /* Put the current font's ID in the current GC, if non-null.
     Called by _wfontswitch. */
  
***************
*** 43,48 ****
--- 27,33 ----
     should occur. */
  
  static TEXTATTR saveattr;
+ static COLOR savefgcolor, savebgcolor;
  
  void
  wbegindrawing(win)
***************
*** 51,58 ****
  	_wtrace(4, "wbegindrawing(win = 0x%lx)", (long)win);
  	if (wid != 0)
  		_werror("recursive wbegindrawing");
! 	_wusewgc(win->wa.wid, win->gca, win->fga, win->bga);
  	saveattr= wattr;
  	wsettextattr(&win->attr);
  	if (win->caretshown)
  		_winvertcaret(win); /* Hide caret temporarily */
--- 36,50 ----
  	_wtrace(4, "wbegindrawing(win = 0x%lx)", (long)win);
  	if (wid != 0)
  		_werror("recursive wbegindrawing");
! 	savefgcolor = _w_fgcolor;
! 	savebgcolor = _w_bgcolor;
  	saveattr= wattr;
+ 	wid = win->wa.wid;
+ 	gc = win->gca;
+ 	_w_fgcolor = win->fga;
+ 	_w_bgcolor = win->bga;
+ 	XSetForeground(_wd, gc, (unsigned long) _w_fgcolor);
+ 	XSetBackground(_wd, gc, (unsigned long) _w_bgcolor);
  	wsettextattr(&win->attr);
  	if (win->caretshown)
  		_winvertcaret(win); /* Hide caret temporarily */
***************
*** 68,76 ****
  	if (wid != win->wa.wid)
  		_werror("wrong call to enddrawing");
  	else {
  		if (win->caretshown)
  			_winvertcaret(win); /* Put it back on */
! 		_wusewgc((Window)0, (GC)0, 0L, 0L); /* Clear all */
  		wsettextattr(&saveattr);
  		XFlush(_wd);
  	}
--- 60,74 ----
  	if (wid != win->wa.wid)
  		_werror("wrong call to enddrawing");
  	else {
+ 		wnoclip();
  		if (win->caretshown)
  			_winvertcaret(win); /* Put it back on */
! 		_w_fgcolor = savefgcolor;
! 		_w_bgcolor = savebgcolor;
! 		XSetForeground(_wd, gc, (unsigned long) _w_fgcolor);
! 		XSetBackground(_wd, gc, (unsigned long) _w_bgcolor);
! 		wid = 0;
! 		gc = 0;
  		wsettextattr(&saveattr);
  		XFlush(_wd);
  	}
***************
*** 230,237 ****
--- 228,237 ----
  	_wtrace(7, "wxorline((h1,v1)=(%d,%d), (h2,v2)=(%d,%d))",
  		h1, v1, h2, v2);
  	XSetFunction(_wd, gc, GXinvert);
+ 	XSetPlaneMask(_wd, gc, _w_fgcolor ^ _w_bgcolor);
  	XDrawLine(_wd, wid, gc, h1, v1, h2, v2);
  	XSetFunction(_wd, gc, GXcopy);
+ 	XSetPlaneMask(_wd, gc, AllPlanes);
  }
  
  /* Draw a rectangle *inside* the given coordinate box */
***************
*** 259,267 ****
  	   Can't set function to GXclear because it doesn't work
  	   with color.  So we fill with the background color. */
  	
! 	XSetForeground(_wd, gc, bg);
  	XFillRectangle(_wd, wid, gc, left, top, right-left, bottom-top);
! 	XSetForeground(_wd, gc, fg);
  }
  
  /* Invert the bits in the given rectangle.
--- 259,267 ----
  	   Can't set function to GXclear because it doesn't work
  	   with color.  So we fill with the background color. */
  	
! 	XSetForeground(_wd, gc, (unsigned long) _w_bgcolor);
  	XFillRectangle(_wd, wid, gc, left, top, right-left, bottom-top);
! 	XSetForeground(_wd, gc, (unsigned long) _w_fgcolor);
  }
  
  /* Invert the bits in the given rectangle.
***************
*** 275,282 ****
  	
  	if (left >= right || top >= bottom)
  		return;
! 	
  	_winvert(wid, gc, left, top, right-left, bottom-top);
  }
  
  /* Paint a given rectangle black */
--- 275,287 ----
  	
  	if (left >= right || top >= bottom)
  		return;
! 
! 	/* _winvert assumes the plane mask is the XOR of fg and bg color;
! 	   this is no longer standard now we support colors... */
! 
! 	XSetPlaneMask(_wd, gc, _w_fgcolor ^ _w_bgcolor);
  	_winvert(wid, gc, left, top, right-left, bottom-top);
+ 	XSetPlaneMask(_wd, gc, AllPlanes);
  }
  
  /* Paint a given rectangle black */
***************
*** 318,327 ****
  	int radius;
  {
  	_wtrace(7, "wdrawcircle(h=%d, v=%d, radius=%d)", h, v, radius);
! 	XDrawArc(_wd, wid, gc, h-radius, v-radius, 2*radius, 2*radius,
  		0, 360*64);
  }
  
  /* Draw an elliptical arc.
     The begin and end angles are specified in degrees (I'm not sure this
     is a good idea, but I don't like X's degrees*64 either...).
--- 323,360 ----
  	int radius;
  {
  	_wtrace(7, "wdrawcircle(h=%d, v=%d, radius=%d)", h, v, radius);
! 	XDrawArc(_wd, wid, gc, h-radius, v-radius, 2*radius-1, 2*radius-1,
  		0, 360*64);
  }
  
+ /* Fill a circle with given center and radius */
+ 
+ void
+ wfillcircle(h, v, radius)
+ 	int h, v;
+ 	int radius;
+ {
+ 	_wtrace(7, "wfillcircle(h=%d, v=%d, radius=%d)", h, v, radius);
+ 	XFillArc(_wd, wid, gc, h-radius, v-radius, 2*radius-1, 2*radius-1,
+ 		0, 360*64);
+ }
+ 
+ /* Invert a circle with given center and radius */
+ 
+ void
+ wxorcircle(h, v, radius)
+ 	int h, v;
+ 	int radius;
+ {
+ 	_wtrace(7, "wfillcircle(h=%d, v=%d, radius=%d)", h, v, radius);
+ 	XSetFunction(_wd, gc, GXinvert);
+ 	XSetPlaneMask(_wd, gc, _w_fgcolor ^ _w_bgcolor);
+ 	XFillArc(_wd, wid, gc, h-radius, v-radius, 2*radius-1, 2*radius-1,
+ 		0, 360*64);
+ 	XSetFunction(_wd, gc, GXcopy);
+ 	XSetPlaneMask(_wd, gc, AllPlanes);
+ }
+ 
  /* Draw an elliptical arc.
     The begin and end angles are specified in degrees (I'm not sure this
     is a good idea, but I don't like X's degrees*64 either...).
***************
*** 336,345 ****
  {
  	_wtrace(7, "wdrawelarc(%d, %d, %d, %d, %d, %d)",
  		h, v, hhalf, vhalf, angle1, angle2);
! 	XDrawArc(_wd, wid, gc, h-hhalf, v-vhalf, 2*hhalf, 2*vhalf,
  		angle1*64, angle2*64);
  }
  
  /* Clip drawing output to a rectangle. */
  
  void
--- 369,449 ----
  {
  	_wtrace(7, "wdrawelarc(%d, %d, %d, %d, %d, %d)",
  		h, v, hhalf, vhalf, angle1, angle2);
! 	XDrawArc(_wd, wid, gc, h-hhalf, v-vhalf, 2*hhalf-1, 2*vhalf-1,
  		angle1*64, angle2*64);
  }
  
+ /* Fill an elliptical arc segment */
+ 
+ void
+ wfillelarc(h, v, hhalf, vhalf, angle1, angle2)
+ 	int h, v;		/* Center */
+ 	int hhalf, vhalf;	/* Half axes */
+ 	int angle1, angle2;	/* Begin, end angle */
+ {
+ 	_wtrace(7, "wfillelarc(%d, %d, %d, %d, %d, %d)",
+ 		h, v, hhalf, vhalf, angle1, angle2);
+ 	XFillArc(_wd, wid, gc, h-hhalf, v-vhalf, 2*hhalf-1, 2*vhalf-1,
+ 		angle1*64, angle2*64);
+ }
+ 
+ /* Invert an elliptical arc segment */
+ 
+ void
+ wxorelarc(h, v, hhalf, vhalf, angle1, angle2)
+ 	int h, v;		/* Center */
+ 	int hhalf, vhalf;	/* Half axes */
+ 	int angle1, angle2;	/* Begin, end angle */
+ {
+ 	_wtrace(7, "wfillelarc(%d, %d, %d, %d, %d, %d)",
+ 		h, v, hhalf, vhalf, angle1, angle2);
+ 	XSetFunction(_wd, gc, GXinvert);
+ 	XSetPlaneMask(_wd, gc, _w_fgcolor ^ _w_bgcolor);
+ 	XFillArc(_wd, wid, gc, h-hhalf, v-vhalf, 2*hhalf-1, 2*vhalf-1,
+ 		angle1*64, angle2*64);
+ 	XSetFunction(_wd, gc, GXcopy);
+ 	XSetPlaneMask(_wd, gc, AllPlanes);
+ }
+ 
+ /* Draw n-1 lines connecting n points */
+ 
+ void
+ wdrawpoly(n, points)
+ 	int n;
+ 	POINT *points;
+ {
+ 	_wtrace(7, "wdrawpoly(%d, ...)", n);
+ 	XDrawLines(_wd, wid, gc, (XPoint *)points, n, CoordModeOrigin);
+ }
+ 
+ /* Fill a polygon given by n points (may be self-intersecting) */
+ 
+ void
+ wfillpoly(n, points)
+ 	int n;
+ 	POINT *points;
+ {
+ 	_wtrace(7, "wfillpoly(%d, ...)", n);
+ 	XFillPolygon(_wd, wid, gc, (XPoint *)points, n,
+ 		     Complex, CoordModeOrigin);
+ }
+ 
+ /* Invert a polygon given by n points (may be self-intersecting) */
+ 
+ void
+ wxorpoly(n, points)
+ 	int n;
+ 	POINT *points;
+ {
+ 	_wtrace(7, "wfillpoly(%d, ...)", n);
+ 	XSetFunction(_wd, gc, GXinvert);
+ 	XSetPlaneMask(_wd, gc, _w_fgcolor ^ _w_bgcolor);
+ 	XFillPolygon(_wd, wid, gc, (XPoint *)points, n,
+ 		     Complex, CoordModeOrigin);
+ 	XSetFunction(_wd, gc, GXcopy);
+ 	XSetPlaneMask(_wd, gc, AllPlanes);
+ }
+ 
  /* Clip drawing output to a rectangle. */
  
  void
***************
*** 362,365 ****
--- 466,518 ----
  wnoclip()
  {
  	XSetClipMask(_wd, gc, None);
+ }
+ 
+ 
+ /* Color stuff. */
+ 
+ void
+ _w_initcolors()
+ {
+ 	_w_fgcolor = _wgetpixel("foreground", "Foreground",
+ 						BlackPixelOfScreen(_ws));
+ 	_w_bgcolor = _wgetpixel("background", "Background",
+ 						WhitePixelOfScreen(_ws));
+ 	
+ 	/* Swap the pixel values if 'reverse' specified */
+ 	if (_wgetbool("reverse", "Reverse", 0)) {
+ 		unsigned long temp= _w_fgcolor;
+ 		_w_fgcolor = _w_bgcolor;
+ 		_w_bgcolor = temp;
+ 	}
+ }
+ 
+ COLOR
+ wgetfgcolor()
+ {
+ 	return _w_fgcolor;
+ }
+ 
+ COLOR
+ wgetbgcolor()
+ {
+ 	return _w_bgcolor;
+ }
+ 
+ void
+ wsetfgcolor(color)
+ 	COLOR color;
+ {
+ 	_w_fgcolor = color;
+ 	if (gc != 0)
+ 		XSetForeground(_wd, gc, (unsigned long) _w_fgcolor);
+ }
+ 
+ void
+ wsetbgcolor(color)
+ 	COLOR color;
+ {
+ 	_w_bgcolor = color;
+ 	if (gc != 0)
+ 		XSetBackground(_wd, gc, (unsigned long) _w_bgcolor);
  }



More information about the Alt.sources mailing list