ftp.nice.ch/pub/next/unix/editor/elvis-2.0.N.bs.tar.gz#/elvis-2.0.N.bs/oswin32/tcaphelp.c

This is tcaphelp.c in view mode; [Download] [Up]

/* oswin32/tcaphelp.c */

char id_tcaphelp[] = "$Id: tcaphelp.c,v 2.18 1996/09/18 20:37:17 steve Exp $";

#include "elvis.h"
#if defined(GUI_TERMCAP) || defined(GUI_OPEN)
# define CHAR CHAR_nt
# define BOOLEAN BOOLEAN_nt
# include <windows.h>
# include <fcntl.h>
# include <io.h>
# include <signal.h>
# undef CHAR
# undef BOOLEAN
# define SMART_LINE_WRAP 1

/* This file includes low-level tty control functions used by the termcap
 * user interface.  These are:
 *	ttyinit()		- remember the initial serial line configuration
 *	ttyraw()		- switch to the mode that elvis runs it
 *	ttynormal()		- switch back to the mode saved by ttyinit()
 *	ttyread(buf,len,timeout)- read characters, possibly with timeout
 *	ttywrite(buf,len)	- write characters
 *	ttytermtype()		- return the name of the terminal type
 *	ttysize()		- determine the terminal size
 *
 * Also, it contains a small terminal emulator to be used when TERM=bios.
 */


/* This variable is defined in guitcap.c */
extern long ttycaught;

static void catchsig(int signo);

/* This variable is used to indicate that the BIOS interface is being used */
static BOOLEAN	useconsole = True;
static HANDLE	inConsole, outConsole, myConsole, console;
static CONSOLE_SCREEN_BUFFER_INFO consinfo;
static DWORD	inMode, outMode;
static int	prevWidth, prevHeight;
static BOOLEAN	resized;
static WORD	origattr;
static WORD	attr;	/* attribute byte for writing subsequent text */

/* The codepage option stores the code page */
static OPTVAL win32val[1];
#define o_codepage	win32val[0].value.number
static int setcp(OPTDESC *opt, OPTVAL *val, CHAR *newval)
{
	UINT	newcp = atol(newval);
	if (!newcp && newval[0] != '0')
	{
		msg(MSG_ERROR, "[s]$1 requires a numeric value", opt->longname);
		return -1;
	}
	if (!SetConsoleOutputCP(newcp) || !SetConsoleCP(newcp))
	{
		msg(MSG_ERROR, "[sd]invalid $1 $2", opt->longname, (long)newcp);
		return -1;
	}
	o_codepage = newcp;
	return 1;
}
static OPTDESC win32desc[] =
{
	{"codepage", "cpg",	optnstring,	setcp}
};


/* This function catches signals, especially SIGINT */
static void catchsig(signo)
	int	signo;
{
	ttycaught |= (1 << signo);
}


/* remember the original terminal settings */
void ttyinit()
{
	SECURITY_ATTRIBUTES	sec;
	COORD			size;
	COORD			home;
	DWORD			dummy;

	/* get handles of the console */
	inConsole = GetStdHandle(STD_INPUT_HANDLE);
	assert(inConsole != INVALID_HANDLE_VALUE);
	outConsole = GetStdHandle(STD_OUTPUT_HANDLE);
	assert(outConsole != INVALID_HANDLE_VALUE);

	/* remember the original modes of those handles */
	GetConsoleMode(inConsole, &inMode);
	GetConsoleMode(outConsole, &outMode);

	/* create a new console buffer, the same size as the window */
	GetConsoleScreenBufferInfo(outConsole, &consinfo);
	sec.nLength = sizeof(sec);
	sec.lpSecurityDescriptor = NULL;
	sec.bInheritHandle = FALSE;
	myConsole = CreateConsoleScreenBuffer(
			GENERIC_READ | GENERIC_WRITE,
			FILE_SHARE_READ | FILE_SHARE_WRITE,
			&sec,
			CONSOLE_TEXTMODE_BUFFER,
			NULL);
	assert(myConsole != INVALID_HANDLE_VALUE);

	/* set the codepage option */
	o_codepage = GetConsoleOutputCP();
	SetConsoleCP((UINT)o_codepage);
	optinsert("win32", QTY(win32val), win32desc, win32val);

	/* change the new buffer's size to match the current buffer's window */
	prevWidth = size.X = consinfo.srWindow.Right - consinfo.srWindow.Left + 1;
	prevHeight = size.Y = consinfo.srWindow.Bottom - consinfo.srWindow.Top + 1;
	SetConsoleScreenBufferSize(myConsole, size);

	/* make the default colors of the new console buffer be the same as the
	 * old console buffer.
	 */
	attr = origattr = consinfo.wAttributes;
	SetConsoleTextAttribute(myConsole, attr);
	home.X = home.Y = 0;
	FillConsoleOutputAttribute(myConsole, attr, size.X * size.Y, home, &dummy);
	FillConsoleOutputCharacter(myConsole, ' ', size.X * size.Y, home, &dummy);
}


/* switch to the tty state that elvis runs in */
void ttyraw(erasekey)
	char	*erasekey;	/* where to store the ERASE key */
{
	DWORD	newmode;

	if (useconsole)
	{
		/* recheck the console handles, just in case! */
		inConsole = GetStdHandle(STD_INPUT_HANDLE);
		assert(inConsole != INVALID_HANDLE_VALUE);
		outConsole = GetStdHandle(STD_OUTPUT_HANDLE);
		assert(outConsole != INVALID_HANDLE_VALUE);

		/* switch to "raw" mode, and allow the window to be resized */
		newmode = ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT | ENABLE_WRAP_AT_EOL_OUTPUT;
		SetConsoleMode(inConsole, newmode);
		SetConsoleMode(outConsole, newmode|ENABLE_PROCESSED_OUTPUT);
		SetConsoleMode(myConsole, newmode);
	}
	else
	{
		/* switch to binary mode */
		_setmode(1, _O_BINARY);
	}

	/* trap ^C signals */
	signal(SIGINT, catchsig);
}


/* switch back to the original tty state */
void ttynormal()
{
	if (useconsole)
	{
		/* switch back to the original mode */
		SetConsoleMode(inConsole, inMode);
		SetConsoleMode(outConsole, outMode);
	}
	else
	{
		/* switch to text mode */
		_setmode(1, _O_TEXT);
	}
}


/* This function switches between screen buffers. */
static void switchcsbi(HANDLE which)
{
	/* if no change, then do nothing */
	if (which == console)
		return;

	/* switch to the requested console */
	SetConsoleActiveScreenBuffer(which);
	console = which;
}


/* Read from keyboard, with timeout.  Since Win32 apparently can't read with
 * timeout, this function simulates a timeout immediately if timeouts are
 * allowed within 0.5 seconds, and waits forever for a keystroke if timeouts
 * are either disabled, or are allowed in more that 0.5 seconds.  Also,
 * if the console is resized it returns -1 to simulate a SIGWINCH signal.
 * After a mouse event, it returns -2 so that windows can be redrawn.
 */
int ttyread(buf, len, timeout)
	char	*buf;	/* where to place the input characters */
	int	len;	/* maximum number of characters to read */
	int	timeout;/* timeout (0 for none) */
{
	INPUT_RECORD event[5];/* buffer, holds an input record */
	DWORD	mode;	/* Console mode */
	DWORD	nevents;/* number of events read into event[] */
	int	e;	/* for counting through event[] */
	int	got;	/* character counter, for keystrokes */
static	DWORD	prevmb;	/* previous mouse button state */
	DWORD	press;	/* bitmap of new button presses */
	GUIWIN	*gw;	/* window where mouse event happened */
static	GUIWIN	*selgw;	/* window where selection is taking place */
	int	y, x;	/* coordinates of mouse within "gw" window */
static	BOOLEAN	justpressed;/* between a press and the start of a drag */
static	int	prevy, prevx;/* cell where originally pressed */
static	BOOLEAN	justdbl;/* between double-click & bogus single-click */

	/* reset the "ttycaught" variable */
	signal(SIGINT, catchsig);
	ttycaught = 0;

	/* if timeouts are allowed within 0.5 seconds, then return 0
	 * immediately unless there's already a keystroke waiting.
	 */
	if (timeout > 0
	 && timeout <= 5
	 && (!useconsole || (PeekConsoleInput(inConsole, event, 1, &nevents)
			     && nevents == 0)))
	{
		return 0;
	}

	/* if resized since last read, then return -1 to simulate the value
	 * that UNIX's read() call would return after a SIGWINCH.
	 */
	if (resized)
	{
		resized = False;
		return -1;
	}

	/* if not using console, then just read from stdin */
	if (!useconsole)
	{
		return fread(buf, len, sizeof(char), stdin);
	}

	/* initialize the mouse variables */
	gw = NULL;

	/* disallow SIGINT while in loop */
	GetConsoleMode(inConsole, &mode);
	SetConsoleMode(inConsole, mode & ~ENABLE_PROCESSED_INPUT);
	signal(SIGINT, catchsig); /* just in case of bad timing! */

	/* get at least one event.  The only events we pay attention to are
	 * window events (resizing), keyboard events, and mouse events.
	 */
	got = nevents = 0;
	do
	{
		/* remove the event from the input queue */
		if (nevents > 0)
		{
			for (e = 0; e < nevents; e++)
				event[e] = event[e + 1];
		}
		else if (!ReadConsoleInput(inConsole, event, QTY(event), &nevents))
		{
			/* How could ReadConsoleInput() fail? */
			return -1;
		}

		/* process the event */
		switch (event[0].EventType)
		{
		  case KEY_EVENT:
			if (event[0].Event.KeyEvent.bKeyDown)
			{
				for (x = event[0].Event.KeyEvent.wRepeatCount;
				     x > 0 && got + 2 < QTY(buf);
				     x--)
				{
					if (event[0].Event.KeyEvent.uChar.AsciiChar)
					{
						buf[got++] = event[0].Event.KeyEvent.uChar.AsciiChar;
					}
					else if (3 == (char)event[0].Event.KeyEvent.wVirtualScanCode)
					{
						/* Ctrl-2 should be a NUL character */
						buf[got++] = '\0';
					}
					else if (7 == (char)event[0].Event.KeyEvent.wVirtualScanCode)
					{
						/* Ctrl-6 should be a ^^ character */
						buf[got++] = ELVCTRL('^');
					}
					else if (!strchr("68*:\x1d", (char)event[0].Event.KeyEvent.wVirtualScanCode))
					{
						buf[got++] = '#';
						buf[got++] = (char)event[0].Event.KeyEvent.wVirtualScanCode;
					}
				}
			}
			break;

		  case MOUSE_EVENT:
			/* Ignore if no buttons pressed.  Also, ignore anything
			 * after a double-click until button is released.
			 */
			if (justdbl)
			{
				prevmb = event[0].Event.MouseEvent.dwButtonState;
				if (prevmb == 0)
					justdbl = False;
				break;
			}
			else if (event[0].Event.MouseEvent.dwButtonState == 0
				&& prevmb == 0)
			{
				break;
			}

			/* Figure out which window the event occurred in */
			gw = ttywindow(event[0].Event.MouseEvent.dwMousePosition.Y,
				       event[0].Event.MouseEvent.dwMousePosition.X,
				       &y, &x);
			if (!gw || (selgw && selgw != gw))
				break;
			press = (event[0].Event.MouseEvent.dwButtonState & ~prevmb);
			prevmb = event[0].Event.MouseEvent.dwButtonState;

			/* Make the window become the current window */
			(*gui->focusgw)(gw);
			eventfocus(gw);

			/* process the event */
			if (event[0].Event.MouseEvent.dwEventFlags & DOUBLE_CLICK)
			{
				/* DOUBLE CLICK */
				if (event[0].Event.MouseEvent.dwButtonState & 1)
					eventclick(gw, y, x, CLICK_TAG);
				else
					eventclick(gw, y, x, CLICK_UNTAG);
				SetConsoleMode(inConsole, mode);
				selgw = NULL;
				justdbl = True;
				return -2;
			}
			if ((event[0].Event.MouseEvent.dwEventFlags & MOUSE_MOVED) != 0 && justpressed && (x != prevx || y != prevy))
			{
				/* starting a draw-through */
				switch (event[0].Event.MouseEvent.dwButtonState)
				{
				  case 1:
					eventclick(gw, prevy, prevx, CLICK_SELCHAR);
					break;

				  case 2:
					eventclick(gw, prevy, prevx, CLICK_SELLINE);
					break;

				  default:
					eventclick(gw, prevy, prevx, CLICK_SELRECT);
				}
				justpressed = False;
			}
			else if (press != 0)
			{
				/* button was pressed */
				if (press & 1)
					eventclick(gw, y, x, CLICK_CANCEL);
				justpressed = True;
				selgw = gw;
			}
			else if (prevmb == 0)
			{
				/* last button released */
				selgw = NULL;
			}

			/* move the cursor to follow the mouse */
			eventclick(gw, y, x, CLICK_MOVE);
			prevx = x;
			prevy = y;
			SetConsoleMode(inConsole, mode);
			return -2;

		  case WINDOW_BUFFER_SIZE_EVENT:
			/* Return -1 to simulate the EINTR error that a UNIX
			 * read() function would have after SIGWINCH arrived.
			 * Discard any preceding keystokes.
			 */
			SetConsoleMode(inConsole, mode);
			return -1;
		}

		/* one event finished */
		nevents--;

	} while (got == 0 || (got < len - 2 &&
		(nevents > 0 ||
			(PeekConsoleInput(inConsole, event, 1, &e) && e > 0))));
	SetConsoleMode(inConsole, mode);
	return got;
}


/* write characters out to the screen */
void ttywrite(buf, len)
	char		*buf;	/* buffer, holds characters to be written */
	int		len;	/* number of characters in buf */
{
 static int	   arg[9];	/* arguments to escape sequence */
 static int	   argno = -1;	/* -1 normally, else index of escape sequence argument */
 static COORD	   coord;	/* coordinates of cursor position */
 static BOOLEAN	   bgset = False;/* has the background color been set? */
 static BOOLEAN	   boldset = False;/* has the foreground brightness been set? */
	SMALL_RECT rect;	/* source for inserting/deleting/scrolling */
	COORD	   dest;	/* destination for inserting/deletingi/scrolling */
	CHAR_INFO  ci;		/* fill info */
	DWORD	   qty;		/* number of characters to fill */
	CONSOLE_CURSOR_INFO cci;/* cursor shape */
	int	   i, j;
	long	   dummy;

	/* if not using a WIN32 console, then just write the characters to stdout */
	if (!useconsole || gui != &guitermcap)
	{
		_write(1, buf, len);
		return;
	}

	/* handle each character separately */
	for (i = 0; i < len; i++)
	{
		if (buf[i] == '\033')
		{
			/* start an escape sequence */
			for (j = 0; j < QTY(arg); j++)
				arg[j] = 0;
			argno = 0;
		}
		else if (console == outConsole && argno == -1)
		{
			/* most characters written literally to shell console */
			for (j = 1; j < len && buf[i + j] != '\033'; j++)
			{
			}
			WriteConsole(console, &buf[i], j, &dummy, NULL);
			i += j - 1; /* "- 1" because of "i++" at top of loop */
		}
		else if (buf[i] == '\007')
		{
			/* write the bell character */
			WriteConsole(console, &buf[i], 1, &dummy, NULL);
		}
		else if (buf[i] == '\b')
		{
			coord.X--;
			if (coord.X < 0)
			{
				coord.X += consinfo.dwSize.X;
				if (coord.Y > 0)
					coord.Y--;
			}
			SetConsoleCursorPosition(console, coord);
		}
		else if (buf[i] == '\n')
		{
			if (coord.Y + 1 < consinfo.dwSize.Y)
			{
				/* move cursor down on line */
				coord.Y++;
				SetConsoleCursorPosition(console, coord);
			}
			else
			{
				/* scroll screen upward one line */
				rect.Top = 1;
				rect.Left = 0;
				rect.Bottom = consinfo.dwSize.Y;
				rect.Right = consinfo.dwSize.X;
				dest.X = 0;
				dest.Y = 0;
				ci.Char.AsciiChar = ' ';
				ci.Attributes = attr;
				ScrollConsoleScreenBuffer(console, &rect, NULL, dest, &ci);
			}
		}
		else if (buf[i] == '\r')
		{
			coord.X = 0;
			SetConsoleCursorPosition(console, coord);
		}
		else if ((unsigned)buf[i] < ' ')
		{
			/* other control characters have no effect */
		}
		else if (argno < 0)
		{
			/* normal character */

			/* count consecutive normal characters */
			for (j = 1; i + j < len && buf[i + j] >= ' '; j++)
			{
			}

			/* write the normal characters all at once. Note
			 * that the attribute is set on myConsole, regardless
			 * of which console buffer is currently active.
			 */
			SetConsoleCursorPosition(console, coord);
			SetConsoleTextAttribute(myConsole, attr);
			WriteConsole(console, &buf[i], j, &dummy, NULL);

			/* move "i" past all but the last character.  The "i++"
			 * in the for() loop will take care of that last one.
			 */
			i += j - 1;

			/* figure out where the cursor belongs after that. */
#ifdef SMART_LINE_WRAP
			while (coord.X + j > consinfo.dwSize.X)
			{
				coord.Y++;
				j -= consinfo.dwSize.X;
			}
			coord.X += j;
			if (coord.X == consinfo.dwSize.X)
				coord.X--;
#else /* dumb line wrap */
			while (coord.X + j >= consinfo.dwSize.X)
			{
				coord.Y++;
				j -= consinfo.dwSize.X;
			}
			coord.X += j;
#endif
			/* check for scrolling */
			j = coord.Y - consinfo.dwSize.Y + 1;
			if (j > 0)
			{
				/* scroll screen upward "j" lines */
				rect.Top = j;
				rect.Left = 0;
				rect.Bottom = consinfo.dwSize.Y;
				rect.Right = consinfo.dwSize.X;
				dest.X = 0;
				dest.Y = 0;
				ci.Char.AsciiChar = ' ';
				ci.Attributes = attr;
				ScrollConsoleScreenBuffer(outConsole, &rect, NULL, dest, &ci);

				/* this leaves the cursor on the last row */
				coord.Y = consinfo.dwSize.Y - 1;
			}
		}
		else
		{
			/* in an escape sequence... */
			switch (buf[i])
			{
			  case '[':
			  case '?':
				/* ignored */
				break;

			  case ';':
				/* advance to next argument */
				argno++;
				break;

			  case '0':
			  case '1':
			  case '2':
			  case '3':
			  case '4':
			  case '5':
			  case '6':
			  case '7':
			  case '8':
			  case '9':
				/* incorporate this digit into current arg */
				arg[argno] = arg[argno] * 10 + buf[i] - '0';
				break;

			  case 'A':
				j = (arg[0] ? arg[0] : 1);
				if (coord.Y >= j)
					coord.Y -= j;
				SetConsoleCursorPosition(console, coord);
				argno = -1;
				break;

			  case 'B':
				j = (arg[0] ? arg[0] : 1);
				if (coord.Y + j < consinfo.dwSize.Y)
					coord.Y += j;
				SetConsoleCursorPosition(console, coord);
				argno = -1;
				break;

			  case 'C':
				j = (arg[0] ? arg[0] : 1);
				if (coord.X + j < consinfo.dwSize.X)
					coord.X += j;
				SetConsoleCursorPosition(console, coord);
				argno = -1;
				break;

			  case 'D':
				j = (arg[0] ? arg[0] : 1);
				if (coord.X >= j)
					coord.X -= j;
				SetConsoleCursorPosition(console, coord);
				argno = -1;
				break;

			  case 'H':
				/* move the cursor */
				coord.X = (arg[1] ? arg[1] - 1 : 0);
				coord.Y = (arg[0] ? arg[0] - 1 : 0);
				SetConsoleCursorPosition(console, coord);
				argno = -1;
				break;

			  case 'J':
				/* clear the screen */
				qty = consinfo.dwSize.X - coord.X +
					consinfo.dwSize.X * (consinfo.dwSize.Y - 1 - coord.Y);
				if (qty > 0)
				{
					FillConsoleOutputCharacter(console, ' ', qty, coord, &dummy);
					FillConsoleOutputAttribute(console, attr, qty, coord, &dummy);
				}
				argno = -1;
				break;

			  case 'K':
				/* clear to end-of-line */
				qty = consinfo.dwSize.X - coord.X;
				if (qty > 0)
				{
					FillConsoleOutputCharacter(console, ' ', qty, coord, &dummy);
					if (console == myConsole)
					{
						FillConsoleOutputAttribute(console, attr, qty, coord, &dummy);
					}
				}
				argno = -1;
				break;

			  case 'L':
				/* insert j lines */
				j = arg[0] ? arg[0] : 1;
				rect.Top = coord.Y;
				rect.Left = 0;
				rect.Bottom = consinfo.dwSize.Y - j;
				rect.Right = consinfo.dwSize.X;
				dest.X = 0;
				dest.Y = coord.Y + j;
				ci.Char.AsciiChar = ' ';
				ci.Attributes = attr;
				ScrollConsoleScreenBuffer(console, &rect, NULL, dest, &ci);
				argno = -1;
				break;

			  case 'M':
				/* delete j lines */
				j = arg[0] ? arg[0] : 1;
				rect.Top = coord.Y + j;
				rect.Left = 0;
				rect.Bottom = consinfo.dwSize.Y;
				rect.Right = consinfo.dwSize.X;
				dest.X = 0;
				dest.Y = coord.Y;
				ci.Char.AsciiChar = ' ';
				ci.Attributes = attr;
				ScrollConsoleScreenBuffer(console, &rect, NULL, dest, &ci);
				argno = -1;
				break;

			  case 'h':
				if (arg[0] == 1)
				{
					switchcsbi(myConsole);
				}
				else if (arg[0] == 12)
				{
					cci.dwSize = 50;
					cci.bVisible = True;
					SetConsoleCursorInfo(myConsole, &cci);
				}
				argno = -1;
				break;
				
			  case 'l':
				if (arg[0] == 1)
				{
					switchcsbi(outConsole);
				}
				else if (arg[0] == 12)
				{
					cci.dwSize = 20;
					cci.bVisible = True;
					SetConsoleCursorInfo(myConsole, &cci);
				}
				argno = -1;
				break;

			  case 'm':
				for (j = 0; j <= argno; j++)
				{
					switch (arg[j])
					{
					  case 0:
						attr = origattr;
						bgset = False;
						boldset = False;
						break;

					  case 1:
						if (attr == origattr
						 && (attr & FOREGROUND_INTENSITY) != 0)
							attr |= FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE;
						else
							attr |= FOREGROUND_INTENSITY;
						boldset = True;
						break;

					  case 4:
						if (!bgset)
							attr ^= BACKGROUND_RED;
						break;

					  case 7:
						attr ^= FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE
							| BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE;
						if (!boldset)
							attr &= ~FOREGROUND_INTENSITY;
						break;

					  case 30: 
					  case 31:
					  case 32:
					  case 33:
					  case 34:
					  case 35:
					  case 36:
					  case 37:
						attr &= ~(FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);
						if (!boldset)
							attr &= ~FOREGROUND_INTENSITY;
						if ((arg[j] - 30) & 1)
							attr |= FOREGROUND_RED;
						if ((arg[j] - 30) & 2)
							attr |= FOREGROUND_GREEN;
						if ((arg[j] - 30) & 4)
							attr |= FOREGROUND_BLUE;
						break;

					  case 40:
					  case 41:
					  case 42:
					  case 43:
					  case 44:
					  case 45:
					  case 46:
					  case 47:
						attr &= ~(BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE);
						if ((arg[j] - 40) & 1)
							attr |= BACKGROUND_RED;
						if ((arg[j] - 40) & 2)
							attr |= BACKGROUND_GREEN;
						if ((arg[j] - 40) & 4)
							attr |= BACKGROUND_BLUE;
						bgset = True;
						break;
					}
				}

				/* note that we always set the attribute of
				 * myConsole, regardless of which console buffer
				 * is currently active.
				 */
				SetConsoleTextAttribute(myConsole, attr);
				argno = -1;
				break;

			  default:
				/* does it look like the end of an unrecognized command? */
				if ((buf[i] & 0x40) != 0)
				{
					argno = -1;
				}
			}
		}
	}

}


/* determine the terminal type */
char *ttytermtype()
{
	char	*type;

	type = getenv("TERM");
	if (!type)
		type = TTY_DEFAULT;

	/* are we using the console? */
	useconsole = !strcmp(type, "console");
	if (useconsole)
	{
		inConsole = GetStdHandle(STD_INPUT_HANDLE);
		if (inConsole == INVALID_HANDLE_VALUE)
		{
			AllocConsole();
			inConsole = GetStdHandle(STD_INPUT_HANDLE);
		}
		outConsole = GetStdHandle(STD_OUTPUT_HANDLE);
		assert(inConsole != INVALID_HANDLE_VALUE);
	}
	return type;
}


/* This function gets the window size. */
BOOLEAN ttysize(linesptr, colsptr)
	int	*linesptr;	/* where to store the number of rows */
	int	*colsptr;	/* where to store the number of columns */
{
	SMALL_RECT size;

	if (!useconsole)
		return False;

	/* Get the console buffer size */
	if (!GetConsoleScreenBufferInfo(myConsole, &consinfo))
		return False;
	prevHeight = *linesptr = consinfo.dwSize.Y;
	prevWidth = *colsptr = consinfo.dwSize.X;

	/* make the window as large as the console buffer */
	size.Top = 0;
	size.Left = 0;
	size.Bottom = *linesptr - 1;
	size.Right = *colsptr - 1;
	(void)SetConsoleWindowInfo(myConsole, TRUE, &size);
	return True;
}


/* Check for signs of boredom from user, so we can abort a time-consuming
 * operation.  Here we check to see if SIGINT has been caught recently.
 * Returns True to abort an operation, or False to continue it.
 */
BOOLEAN ttypoll(reset)
	BOOLEAN reset;
{
	return (BOOLEAN)((ttycaught & (1 << SIGINT)) != 0);
}
#endif /* GUI_TERMCAP */

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.