DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T t

⟦569243c2c⟧ TextFile

    Length: 7468 (0x1d2c)
    Types: TextFile
    Names: »ttyio.c«

Derivation

└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
    └─ ⟦this⟧ »EUUGD11/euug-87hel/sec1/micrognu/sys/vms/ttyio.c« 

TextFile

/*
 * Name:	MicroGnuEmacs
 *		VAX/VMS terminal I/O.
 *		o 16-Apr-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic
 *		  Turn off TTSYNC so ^S and ^Q are sent to program.
 *		  To get this back, compile with -DFLOWCONTROL
 *		o 10-Jul-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic
 *		  Add setttysize(), typeahead() and panic() for Gnu v30
 */
#include	"def.h"

#include	<stsdef.h>
#include	<ssdef.h>
#include	<descrip.h>
#include	<iodef.h>
#include	<ttdef.h>
#include	<tt2def.h>

#define	NIBUF	128			/* Probably excessive.		*/
#define	NOBUF	512			/* Not too big for 750/730.	*/
#define	EFN	0			/* Event flag			*/

char	obuf[NOBUF];			/* Output buffer		*/
int	nobuf;				/* # of bytes in above		*/
char	ibuf[NIBUF];			/* Input buffer			*/
int	nibuf;				/* # of bytes in above		*/
int	ibufi;				/* Read index			*/
int	oldmode[3];			/* Old TTY mode bits		*/
int	newmode[3];			/* New TTY mode bits		*/
short	iochan;				/* TTY I/O channel		*/
int	nrow;				/* Terminal size, rows.		*/
int	ncol;				/* Terminal size, columns.	*/
short	ospeed;				/* Terminal output speed	*/
					/* for termcap library		*/

/*
 * This routines gets called once, to set up the
 * terminal channel.
 * On VMS we find the translation of the SYS$COMMAND:
 * logical name, assign a channel to it, and set it raw.
 */

ttopen()
{
	struct	dsc$descriptor	idsc;
	struct	dsc$descriptor	odsc;
	char	oname[40];
	int	iosb[2];
	int	status;

	odsc.dsc$a_pointer = "SYS$COMMAND";
	odsc.dsc$w_length  = strlen(odsc.dsc$a_pointer);
	odsc.dsc$b_dtype   = DSC$K_DTYPE_T;
	odsc.dsc$b_class   = DSC$K_CLASS_S;
	idsc.dsc$b_dtype   = DSC$K_DTYPE_T;
	idsc.dsc$b_class   = DSC$K_CLASS_S;
	do {
		idsc.dsc$a_pointer = odsc.dsc$a_pointer;
		idsc.dsc$w_length  = odsc.dsc$w_length;
		odsc.dsc$a_pointer = &oname[0];
		odsc.dsc$w_length  = sizeof(oname);
		status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc);
		if (status!=SS$_NORMAL && status!=SS$_NOTRAN)
			exit(status);
		if (oname[0] == 0x1B) {
			odsc.dsc$a_pointer += 4;
			odsc.dsc$w_length  -= 4;
		}
	} while (status == SS$_NORMAL);
	status = SYS$ASSIGN(&odsc, &iochan, 0, 0);
	if (status != SS$_NORMAL)
		exit(status);
	status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0,
			  oldmode, sizeof(oldmode), 0, 0, 0, 0);
	if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
		exit(status);

	nrow = (oldmode[1]>>24) & 0xFF;		/* Terminal length.	*/
	if (nrow > NROW)
		nrow = NROW;
	ncol = (oldmode[0]>>16) & 0xFFFF;	/* Width.		*/
	if (ncol > NCOL)
		ncol = NCOL;
	ospeed = (iosb[0]>>24) & 0xFF;		/* Speed (for termcap)	*/
	newmode[0] = oldmode[0];		/* Only in version 4.	*/
#ifdef	FLOWCONTROL
	newmode[1] = oldmode[1] | TT$M_NOECHO | TT$M_TTSYNC;
#else
	newmode[1] = (oldmode[1] | TT$M_NOECHO) & ~TT$M_TTSYNC;
#endif
	newmode[2] = oldmode[2] | TT2$M_PASTHRU;
	status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
			  newmode, sizeof(newmode), 0, 0, 0, 0);

	if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
		exit(status);
}

/*
 * This function gets called just
 * before we go back home to the command interpreter.
 * On VMS it puts the terminal back in a reasonable state.
 */
ttclose()
{
	int	status;
	int	iosb[2];

	ttflush();
	status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
	         oldmode, sizeof(oldmode), 0, 0, 0, 0);
	if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
		exit(status);
	status = SYS$DASSGN(iochan);
	if (status != SS$_NORMAL)
		exit(status);
}

/*
 * Write a character to the display.
 * On VMS, terminal output is buffered, and
 * we just put the characters in the big array,
 * after checking for overflow.
 */
ttputc(c)
{
	if (nobuf >= NOBUF)
		ttflush();
	obuf[nobuf++] = c;
}

/*
 * This function does the real work of
 * flushing out buffered I/O on VMS. All
 * we do is blast out the block with a write call. No status
 * checking is done on the write, because there isn't anything
 * clever that can be done, and because you will see the
 * error as a messed up screen.
 */
ttflush()
{
	int	iosb[2];

	if (nobuf != 0) {
		SYS$QIOW(EFN, iochan, IO$_WRITELBLK|IO$M_NOFORMAT,
		iosb, 0, 0, obuf, nobuf, 0, 0, 0, 0);
		nobuf = 0;
	}
}

/*
 * Read a character from the terminal,
 * performing no editing and doing no echo at all.
 * More complex in VMS that almost anyplace else,
 * which figures.
 */
ttgetc()
{
	int	status;
	int	iosb[2];
	int	term[2];

	term[0] = 0;
	term[1] = 0;
	while (ibufi >= nibuf) {
		ibufi   = 0;
		status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED,
			 iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0);
		if (status != SS$_NORMAL)
			continue;
		status = iosb[0] & 0xFFFF;
		if (status!=SS$_NORMAL && status!=SS$_TIMEOUT)
			continue;
		nibuf = (iosb[0]>>16) + (iosb[1]>>16);
		if (nibuf == 0) {
			status = SYS$QIOW(EFN, iochan, IO$_READLBLK,
				iosb, 0, 0, ibuf, 1, 0, term, 0, 0);
			if (status != SS$_NORMAL)
				continue;
			if ((iosb[0]&0xFFFF) != SS$_NORMAL)
				continue;
			nibuf = (iosb[0]>>16) + (iosb[1]>>16);
		}
	}
	return (ibuf[ibufi++] & 0xFF);
}

/*
 * Internal check for new terminal size.
 * Do this *before* setting terminal modes, so
 * the size changes are kept when.
 */
ckttysize()
{
	int status, mode[3], iosb[2], wid, len;

	status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0,
			  mode, sizeof(mode), 0, 0, 0, 0);
	if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
		panic("ckttsize: can't sense terminal modes!");

	/* save new page length */
	len = (mode[1] >> 24) & 0xFF;
	oldmode[1] = (oldmode[1] & 0x00FFFFFF) | (len << 24);
	newmode[1] = (newmode[1] & 0x00FFFFFF) | (len << 24);

	/* save new page width */
	wid = (mode[0] >> 16) & 0xFF;
	oldmode[0] = (oldmode[0] & 0x0000FFFF) | (wid << 16);
	newmode[0] = (newmode[0] & 0x0000FFFF) | (wid << 16);
}

/*
 * Tell Emacs how big the terminal is now,
 * making sure the page size is in the range
 * 1..NROW.
 */

setttysize()
{
	nrow = (newmode[1]>>24) & 0xFF;		/* Length.		*/
	if (nrow > NROW)
		nrow = NROW;

	ncol = (newmode[0]>>16) & 0xFFFF;	/* Width.		*/
	if (ncol > NCOL)
		ncol = NCOL;
}

/*
 * Return the number of characters in the
 * typeahead buffer.
 */

typeahead()
{
	int	status, SYS$QIOW(), iosb[2], mode[2];

	status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE|IO$M_TYPEAHDCNT,
			iosb, 0, 0, mode, sizeof(mode), 0, 0, 0, 0);
	if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
		exit(status);
	return (mode[0] & 0xFFFF);	/* # characters in typeahead buf */
}

#ifdef	DPROMPT
/*
 * Attempt to read for one character.  Return TRUE if the
 * read times out after 2 seconds, return immediately with
 * FALSE if the user enters something.
 */
ttwait()
{
	int	status;
	int	iosb[2];
	int	term[2];

	term[0] = 0;			/* no termination characters for read */
	term[1] = 0;
	while (ibufi >= nibuf) {	/* anything in the buffer?	*/
		ibufi   = 0;		/* nope, read 1 char w/timeout	*/
		status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED,
			 iosb, 0, 0, ibuf, 1, 2, term, 0, 0);
		if (status != SS$_NORMAL)
			continue;		/* did read succeed ?	     */
		status = iosb[0] & 0xFFFF;	/* yes, get secondary status */
		if (status!=SS$_NORMAL && status!=SS$_TIMEOUT)
			continue;		/* try again if bad	     */
		nibuf = (iosb[0]>>16) + (iosb[1]>>16);/* store # chars read  */
		if (status == SS$_TIMEOUT)
			return (TRUE);		/* the read timed out	     */
	}
	return (FALSE);				/* read did not time out     */
}
#endif	DPROMPT

/*
 * Just exit, as quickly as we can.
 */

panic(s)
char *s;
{
	fprintf(stderr,"panic: %s\n", s);
	ttclose();	/* set the terminal back to sane state... */
	abort();
}