X11R4 xterm for the 6000 (BIG long message 9707 lines)

/100000 root at johnbob.uucp
Sat Nov 10 08:43:58 AEST 1990


Here are the files that need to be changed to compile the X11R4 MIT xterm
on the 6000.  You will need to get the rest of the source to xterm and also
get your own R4 libraries.  No Makefile is included.  You will have to make
one from the Imakefile or modify an existing one.  You should make sure the
"-DAIXV3" flag is turned on.


John Harvey	Austin, Texas
AT HOME  ...!sequoia!johnbob!jph  OR
...!uunet!cs.utexas.edu!execu!sequoia!johnbob!jph
AT WORK  johnbob at ausvmq  OR  john at johnbob  OR  johnbob at austin
         @cs.utexas.edu:ibmchs!auschs!johnbob.austin.ibm.com!john  OR
...!uunet!cs.utexas.edu!ibmaus!auschs!johnbob.austin.ibm.com!john
The full path is needed for network hopping.
I don't speak for anybody.  Not even myself.





---- Cut Here and unpack ----
#!/bin/sh
# This is a shell archive (shar 3.10)
# made 11/09/1990 21:26 UTC by root at AIX 
# Source directory /athens/r4v3xterm
#
# existing files will NOT be overwritten
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#   1336 -rw-r--r-- DECkeysym.h
#  40037 -rw-r--r-- Tekproc.c
#  35966 -rw-r--r-- button.c
#  79193 -rw-r--r-- charproc.c
#   7257 -rw-r--r-- input.c
#  69202 -rw-r--r-- main.c
#  19514 -rw-r--r-- misc.c
#
touch 2>&1 | fgrep '[-amc]' > /tmp/s3_touch$$
if [ -s /tmp/s3_touch$$ ]
then
	TOUCH=can
else
	TOUCH=cannot
fi
rm -f /tmp/s3_touch$$
# ============= DECkeysym.h ==============
if test -f DECkeysym.h; then echo "File DECkeysym.h exists"; else
sed 's/^X//' << 'SHAR_EOF' > DECkeysym.h &&
X/* $XConsortium: DECkeysym.h,v 1.2 88/09/06 15:55:54 jim Exp $ */
X
X/***********************************************************
XCopyright 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
Xand the Massachusetts Institute of Technology, Cambridge, Massachusetts.
X
X                        All Rights Reserved
X
XPermission to use, copy, modify, and distribute this software and its 
Xdocumentation for any purpose and without fee is hereby granted, 
Xprovided that the above copyright notice appear in all copies and that
Xboth that copyright notice and this permission notice appear in 
Xsupporting documentation, and that the names of Digital or MIT not be
Xused in advertising or publicity pertaining to distribution of the
Xsoftware without specific, written prior permission.  
X
XDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
XALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
XDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
XANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
XWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
XARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
XSOFTWARE.
X
X******************************************************************/
X
X#define DXK_Remove	0x1000FF00   /* Remove */
SHAR_EOF
chmod 0644 DECkeysym.h || echo "restore of DECkeysym.h fails"
if [ $TOUCH = can ]
then
    touch -am 1109132690 DECkeysym.h
fi
fi
# ============= Tekproc.c ==============
if test -f Tekproc.c; then echo "File Tekproc.c exists"; else
sed 's/^X//' << 'SHAR_EOF' > Tekproc.c &&
X/*
X * $XConsortium: Tekproc.c,v 1.77 89/12/22 11:37:41 jim Exp $
X *
X * Warning, there be crufty dragons here.
X */
X
X
X#include <X11/copyright.h>
X
X#ifdef AIXV3
X#include <time.h>
X#endif
X
X/*
X * Copyright 1988 Massachusetts Institute of Technology
X * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
X *
X *                         All Rights Reserved
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Digital Equipment
X * Corporation not be used in advertising or publicity pertaining to
X * distribution of the software without specific, written prior permission.
X *
X *
X * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
X * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
X * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
X * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
X * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
X * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
X * SOFTWARE.
X */
X
X/* Tekproc.c */
X
X#include <X11/Xos.h>
X#include "ptyx.h"
X#include <X11/Xatom.h>
X#include <X11/Xutil.h>
X#include <X11/cursorfont.h>
X#include <X11/StringDefs.h>
X#include <X11/Shell.h>
X#include <X11/Xmu/CharSet.h>
X#include "Tekparse.h"
X#include <stdio.h>
X#ifdef umips
X# ifndef SYSTYPE_SYSV
X# include <sgtty.h>
X# endif /* not SYSTYPE_SYSV */
X#else
X# ifndef CRAY
X#  include <sgtty.h>
X# endif
X#endif /* umips */
X#include <ctype.h>
X#include <errno.h>
X#include <setjmp.h>
X#include <pwd.h>
X#include "data.h"
X#include "error.h"
X#include "menu.h"
X
X#if !defined(EWOULDBLOCK) && defined(EAGAIN)
X#define EWOULDBLOCK EAGAIN
X#endif
X
Xextern void exit();
Xextern long time();
X
X#define TekColormap DefaultColormap( screen->display, \
X				    DefaultScreen(screen->display) )
X#define DefaultGCID DefaultGC(screen->display, DefaultScreen(screen->display))->gid
X
X/* Tek defines */
X
X#define	BEL		07
X#define	CANCEL		030
X#define	DOTDASHEDLINE	2
X#define	DOTTEDLINE	1
X#define	EAST		01
X#define	ETX		03
X#define	LINEMASK	07
X#define	LONGDASHEDLINE	4
X#define	MARGIN1		0
X#define	MARGIN2		1
X#define MAX_PTS		150
X#define MAX_VTX		300
X#define	NAK		025
X#define	NORTH		04
X#define	PENDOWN		1
X#define	PENUP		0
X#define	SHORTDASHEDLINE	3
X#define	SOLIDLINE	0
X#define	SOUTH		010
X#define	TEKBOTTOMPAD	23
X#define	TEKDEFHEIGHT	565
X#define	TEKDEFWIDTH	750
X#define	TEKHEIGHT	3072
X#define	TEKHOME		((TekChar[screen->page.fontsize].nlines - 1)\
X			 * TekChar[screen->page.fontsize].vsize)
X#define	TEKMINHEIGHT	452
X#define	TEKMINWIDTH	600
X#define	TEKTOPPAD	34
X#define	TEKWIDTH	4096
X#define	TEXT_BUF_SIZE	256
X#define	WEST		02
X
X#define	TekMove(x,y)	screen->cur_X = x; screen->cur_Y = y
X#define	input()		Tinput()
X#define	unput(c)	*Tpushback++ = c
X
X#ifndef lint
Xstatic char rcs_id[] = "$XConsortium: Tekproc.c,v 1.77 89/12/22 11:37:41 jim Exp $";
X#endif	/* lint */
X
Xextern Widget toplevel;
X
Xstatic XPoint *T_box[TEKNUMFONTS] = {
X	T_boxlarge,
X	T_box2,
X	T_box3,
X	T_boxsmall,
X};
Xstatic struct Tek_Char {
X	int hsize;	/* in Tek units */
X	int vsize;	/* in Tek units */
X	int charsperline;
X	int nlines;
X} TekChar[TEKNUMFONTS] = {
X	{56, 88, 74, 35},	/* large */
X	{51, 82, 81, 38},	/* #2 */
X	{34, 53, 121, 58},	/* #3 */
X	{31, 48, 133, 64},	/* small */
X};
X
Xstatic Cursor GINcursor;
Xstatic XSegment *line_pt;
Xstatic int nplot;
Xstatic TekLink Tek0;
Xstatic jmp_buf Tekjump;
Xstatic TekLink *TekRecord;
Xstatic XSegment *Tline;
X
Xextern int Talptable[];
Xextern int Tbestable[];
Xextern int Tbyptable[];
Xextern int Tesctable[];
Xextern int Tipltable[];
Xextern int Tplttable[];
Xextern int Tpttable[];
Xextern int Tspttable[];
X
Xstatic int *curstate = Talptable;
Xstatic int *Tparsestate = Talptable;
X
X/* event handlers */
Xextern void HandleKeyPressed(), HandleEightBitKeyPressed();
Xextern void HandleStringEvent();
Xextern void HandleEnterWindow();
Xextern void HandleLeaveWindow();
Xextern void HandleFocusChange();
Xextern void HandleSecure();
Xextern void HandleGINInput();
Xextern void HandleCreateMenu(), HandlePopupMenu();
X
Xstatic char defaultTranslations[] = "\
X       ~Meta<KeyPress>: 	insert-seven-bit()	\n\
X        Meta<KeyPress>: 	insert-eight-bit()\n\
X Ctrl ~Meta<Btn1Down>:          popup-menu(mainMenu) \n\
X Ctrl ~Meta <Btn2Down>:         popup-menu(tekMenu) \n\
X Shift ~Meta<Btn1Down>:         gin-press(L) \n\
X       ~Meta<Btn1Down>:         gin-press(l) \n\
X Shift ~Meta<Btn2Down>:         gin-press(M) \n\
X       ~Meta<Btn2Down>:         gin-press(m) \n\
X Shift ~Meta<Btn3Down>:         gin-press(R) \n\
X       ~Meta<Btn3Down>:         gin-press(r)";
X
X
Xstatic XtActionsRec actionsList[] = { 
X    { "string",	HandleStringEvent },
X    { "insert",	HandleKeyPressed },	/* alias for insert-seven-bit */
X    { "insert-seven-bit",	HandleKeyPressed },
X    { "insert-eight-bit",	HandleEightBitKeyPressed },
X    { "gin-press",		HandleGINInput },
X    { "secure", 		HandleSecure },
X    { "create-menu",		HandleCreateMenu },
X    { "popup-menu",		HandlePopupMenu },
X    /* menu actions */
X    { "allow-send-events",	HandleAllowSends },
X    { "set-visual-bell",	HandleVisualBell },
X    { "set-logging",		HandleLogging },
X    { "redraw",			HandleRedraw },
X    { "send-signal",		HandleSendSignal },
X    { "quit",			HandleQuit },
X    { "set-scrollbar",		HandleScrollbar },
X    { "set-jumpscroll",		HandleJumpscroll },
X    { "set-reverse-video",	HandleReverseVideo },
X    { "set-autowrap",		HandleAutoWrap },
X    { "set-reversewrap",	HandleReverseWrap },
X    { "set-autolinefeed",	HandleAutoLineFeed },
X    { "set-appcursor",		HandleAppCursor },
X    { "set-appkeypad",		HandleAppKeypad },
X    { "set-scroll-on-key",	HandleScrollKey },
X    { "set-scroll-on-tty-output",	HandleScrollTtyOutput },
X    { "set-allow132",		HandleAllow132 },
X    { "set-cursesemul",		HandleCursesEmul },
X    { "set-marginbell",		HandleMarginBell },
X    { "set-altscreen",		HandleAltScreen },
X    { "soft-reset",		HandleSoftReset },
X    { "hard-reset",		HandleHardReset },
X    { "set-terminal-type",	HandleSetTerminalType },
X    { "set-visibility",		HandleVisibility },
X    { "set-tek-text",		HandleSetTekText },
X    { "tek-page",		HandleTekPage },
X    { "tek-reset",		HandleTekReset },
X    { "tek-copy",		HandleTekCopy },
X};
X
Xstatic Dimension defOne = 1;
X
Xstatic XtResource resources[] = {
X    {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
X	 XtOffset(Widget, core.width), XtRDimension, (caddr_t)&defOne},
X    {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
X	 XtOffset(Widget, core.height), XtRDimension, (caddr_t)&defOne},
X    {"fontLarge", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
X       XtOffset(TekWidget, tek.Tfont[TEK_FONT_LARGE]),
X       XtRString, "9x15"},
X    {"font2", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
X       XtOffset(TekWidget, tek.Tfont[TEK_FONT_2]),
X       XtRString, "6x13"},
X    {"font3", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
X       XtOffset(TekWidget, tek.Tfont[TEK_FONT_3]),
X       XtRString, "8x13"},
X    {"fontSmall", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
X       XtOffset(TekWidget, tek.Tfont[TEK_FONT_SMALL]),
X       XtRString, "6x10"},
X    {"initialFont", "InitialFont", XtRString, sizeof(char *),
X       XtOffset(TekWidget, tek.initial_font),
X       XtRString, "large"},
X};
X
Xstatic void TekInitialize(), TekRealize(), TekConfigure();
Xvoid TekExpose();
X
XWidgetClassRec tekClassRec = {
X  {
X/* core_class fields */	
X    /* superclass	  */	(WidgetClass) &widgetClassRec,
X    /* class_name	  */	"Tek4014",
X    /* widget_size	  */	sizeof(TekWidgetRec),
X    /* class_initialize   */    NULL,
X    /* class_part_initialize */ NULL,
X    /* class_inited       */	FALSE,
X    /* initialize	  */	TekInitialize,
X    /* initialize_hook    */    NULL,				
X    /* realize		  */	TekRealize,
X    /* actions		  */	actionsList,
X    /* num_actions	  */	XtNumber(actionsList),
X    /* resources	  */	resources,
X    /* num_resources	  */	XtNumber(resources),
X    /* xrm_class	  */	NULLQUARK,
X    /* compress_motion	  */	TRUE,
X    /* compress_exposure  */	TRUE,
X    /* compress_enterleave */   TRUE,
X    /* visible_interest	  */	FALSE,
X    /* destroy		  */	NULL,
X    /* resize		  */	TekConfigure,
X    /* expose		  */	TekExpose,
X    /* set_values	  */	NULL,
X    /* set_values_hook    */    NULL,
X    /* set_values_almost  */    NULL,
X    /* get_values_hook    */    NULL,
X    /* accept_focus	  */	NULL,
X    /* version            */    XtVersion,
X    /* callback_offsets   */    NULL,
X    /* tm_table           */    defaultTranslations,
X    /* query_geometry     */    XtInheritQueryGeometry,
X    /* display_accelerator*/    XtInheritDisplayAccelerator,
X    /* extension          */    NULL
X  }
X};
X#define tekWidgetClass ((WidgetClass)&tekClassRec)
X
Xstatic Boolean Tfailed = FALSE;
X
XTekWidget CreateTekWidget ()
X{
X    Widget tekshellwidget;
X    extern Arg ourTopLevelShellArgs[];
X    extern int number_ourTopLevelShellArgs;
X
X    /* this causes the Initialize method to be called */
X    tekshellwidget = XtCreatePopupShell ("tektronix", topLevelShellWidgetClass,
X					 toplevel, ourTopLevelShellArgs, 
X					 number_ourTopLevelShellArgs);
X
X    /* this causes the Realize method to be called */
X    tekWidget = (TekWidget) XtCreateManagedWidget ("tek4014", tekWidgetClass,
X						   tekshellwidget, NULL, 0);
X    return (tekWidget);
X}
X
X
Xint TekInit ()
X{
X    if (Tfailed) return (0);
X    if (tekWidget) return (1);
X    if (CreateTekWidget()) {
X	return (1);
X    }
X    return (0);
X}
X
XTekparse()
X{
X	register TScreen *screen = &term->screen;
X	register int c, x, y;
X	char ch;
X	int Tinput();
X
X	for( ; ; )
X		switch(Tparsestate[c = input()]) {
X		 case CASE_REPORT:
X			/* report address */
X			if(screen->TekGIN) {
X				TekGINoff();
X				TekEnqMouse(0);
X			} else {
X				c = 064;	/* has hard copy unit */
X				if(screen->margin == MARGIN2)
X					c |= 02;
X				TekEnq(c, screen->cur_X, screen->cur_Y);
X			}
X			TekRecord->ptr[-1] = NAK; /* remove from recording */
X			Tparsestate = curstate;
X			break;
X
X		 case CASE_VT_MODE:
X			/* special return to vt102 mode */
X			Tparsestate = curstate;
X			TekRecord->ptr[-1] = NAK; /* remove from recording */
X			if(screen->logging) {
X				FlushLog(screen);
X				screen->logstart = buffer;
X			}
X			return;
X
X		 case CASE_SPT_STATE:
X			/* Enter Special Point Plot mode */
X			if(screen->TekGIN)
X				TekGINoff();
X			Tparsestate = curstate = Tspttable;
X			break;
X
X		 case CASE_GIN:
X			/* Do Tek GIN mode */
X			screen->TekGIN = &TekRecord->ptr[-1];
X				/* Set cross-hair cursor raster array */
X			if (GINcursor = 
X			    make_colored_cursor (XC_tcross, screen->mousecolor,
X						 screen->mousecolorback))
X				XDefineCursor (screen->display, TShellWindow,
X					       GINcursor);
X			Tparsestate = Tbyptable;	/* Bypass mode */
X			break;
X
X		 case CASE_BEL:
X			/* BEL */
X			if(screen->TekGIN)
X				TekGINoff();
X			if(!TekRefresh)
X				Bell();
X			Tparsestate = curstate;	/* clear bypass condition */
X			break;
X
X		 case CASE_BS:
X			/* BS */
X			if(screen->TekGIN)
X				TekGINoff();
X			Tparsestate = curstate;	/* clear bypass condition */
X			TCursorBack();
X			break;
X
X		 case CASE_PT_STATE:
X			/* Enter Tek Point Plot mode */
X			if(screen->TekGIN)
X				TekGINoff();
X			Tparsestate = curstate = Tpttable;
X			break;
X
X		 case CASE_PLT_STATE:
X			/* Enter Tek Plot mode */
X			if(screen->TekGIN)
X				TekGINoff();
X			Tparsestate = curstate = Tplttable;
X			if((c = input()) == BEL)
X				screen->pen = PENDOWN;
X			else {
X				unput(c);
X				screen->pen = PENUP;
X			}
X			break;
X
X		 case CASE_TAB:
X			/* HT */
X			if(screen->TekGIN)
X				TekGINoff();
X			Tparsestate = curstate;	/* clear bypass condition */
X			TCursorForward();
X			break;
X
X		 case CASE_IPL_STATE:
X			/* Enter Tek Incremental Plot mode */
X			if(screen->TekGIN)
X				TekGINoff();
X			Tparsestate = curstate = Tipltable;
X			break;
X
X		 case CASE_ALP_STATE:
X			/* Enter Tek Alpha mode from any other mode */
X			if(screen->TekGIN)
X				TekGINoff();
X			/* if in one of graphics states, move alpha cursor */
X			if(nplot > 0)	/* flush line Tbuffer */
X				TekFlush();
X			Tparsestate = curstate = Talptable;
X			break;
X
X		 case CASE_UP:
X			/* cursor up */
X			if(screen->TekGIN)
X				TekGINoff();
X			Tparsestate = curstate;	/* clear bypass condition */
X			TCursorUp();
X			break;
X
X		 case CASE_COPY:
X			/* make copy */
X			if(screen->TekGIN)
X				TekGINoff();
X			TekCopy();
X			TekRecord->ptr[-1] = NAK; /* remove from recording */
X			Tparsestate = curstate;	/* clear bypass condition */
X			break;
X
X		 case CASE_PAGE:
X			/* Page Function */
X			if(screen->TekGIN)
X				TekGINoff();
X			TekPage();	/* clear bypass condition */
X			break;
X
X		 case CASE_BES_STATE:
X			/* Byp: an escape char */
X			Tparsestate = Tbestable;
X			break;
X
X		 case CASE_BYP_STATE:
X			/* set bypass condition */
X			Tparsestate = Tbyptable;
X			break;
X
X		 case CASE_IGNORE:
X			/* Esc: totally ignore CR, ESC, LF, ~ */
X			break;
X
X		 case CASE_ASCII:
X			/* Select ASCII char set */
X			/* ignore for now */
X			Tparsestate = curstate;
X			break;
X
X		 case CASE_APL:
X			/* Select APL char set */
X			/* ignore for now */
X			Tparsestate = curstate;
X			break;
X
X		 case CASE_CHAR_SIZE: 
X			/* character size selector */
X		        TekSetGCFont (screen->cur.fontsize = (c & 03));
X			Tparsestate = curstate;
X			break;
X
X		 case CASE_BEAM_VEC:
X			/* beam and vector selector */
X			/* only line types */
X			if((c &= LINEMASK) != screen->cur.linetype) {
X				if(nplot > 0)
X					TekFlush();
X				screen->cur.linetype = c;
X			}
X			Tparsestate = curstate;
X			break;
X
X		 case CASE_CURSTATE:
X			Tparsestate = curstate;
X			break;
X
X		 case CASE_PENUP:
X			/* Ipl: penup */
X			screen->pen = PENUP;
X			break;
X
X		 case CASE_PENDOWN:
X			/* Ipl: pendown */
X			screen->pen = PENDOWN;
X			break;
X
X		 case CASE_IPL_POINT:
X			/* Ipl: point */
X			x = screen->cur_X;
X			y = screen->cur_Y;
X			if(c & NORTH)
X				y++;
X			else if(c & SOUTH)
X				y--;
X			if(c & EAST)
X				x++;
X			else if(c & WEST)
X				x--;
X			if(screen->pen == PENDOWN)
X				TekDraw(x, y);
X			else
X				TekMove(x, y);
X			break;
X
X		 case CASE_PLT_VEC:
X			/* Plt: vector */
X			unput(c);
X			if(getpoint()) {
X				if(screen->pen == PENDOWN)
X					TekDraw(screen->cur.x, screen->cur.y);
X				else
X					TekMove(screen->cur.x, screen->cur.y);
X				screen->pen = PENDOWN;
X			}
X			break;
X
X		 case CASE_PT_POINT:
X			/* Pt: point */
X			unput(c);
X			if(getpoint()) {
X				TekMove(screen->cur.x, screen->cur.y);
X				TekDraw(screen->cur.x, screen->cur.y);
X			}
X			break;
X
X		 case CASE_SPT_POINT:
X			/* Spt: point */
X			/* ignore intensity character in c */
X			if(getpoint()) {
X				TekMove(screen->cur.x, screen->cur.y);
X				TekDraw(screen->cur.x, screen->cur.y);
X			}
X			break;
X
X		 case CASE_CR:
X			/* CR */
X			if(screen->TekGIN)
X				TekGINoff();
X			if(nplot > 0)	/* flush line Tbuffer */
X				TekFlush();
X			screen->cur_X = screen->margin == MARGIN1 ? 0 :
X			 TEKWIDTH / 2;
X			Tparsestate = curstate = Talptable;
X			break;
X
X		 case CASE_ESC_STATE:
X			/* ESC */
X			Tparsestate = Tesctable;
X			break;
X
X		 case CASE_LF:
X			/* LF */
X			if(screen->TekGIN)
X				TekGINoff();
X			TCursorDown();
X			if (!TekRefresh && (screen->display->qlen > 0 ||
X					    GetBytesAvailable (screen->display->fd) > 0))
X			  xevents();
X			break;
X
X		 case CASE_SP:
X			/* SP */
X			TCursorForward();
X			break;
X
X		 case CASE_PRINT:
X			/* printable character */
X			ch = c;
X			c = screen->cur.fontsize;
X
X			XDrawString(
X			    screen->display,
X			    TWindow(screen), 
X			    screen->TnormalGC,
X			    (int)(screen->cur_X * TekScale(screen)) + screen->border,
X			    (int)((TEKHEIGHT + TEKTOPPAD - screen->cur_Y) * TekScale(screen)) + screen->border,
X			    &ch,
X			    1);
X			TCursorForward();
X			break;
X		 case CASE_OSC:
X			/* do osc escape */
X			do_osc(Tinput);
X			Tparsestate = curstate;
X			break;
X		}
X}			
X
XTekSetGCFont (size)
X    int size;  /* TEK_FONT_{LARGE,2,3,SMALL} */
X    {
X    register TScreen *screen = &term->screen;
X    Font fid = tekWidget->tek.Tfont[size]->fid;
X    if (fid == DefaultGCID) 
X       /* we didn't succeed in opening a real font
X	  for this size.  Instead, use server default. */
X       XCopyGC (screen->display,
X	  DefaultGC(screen->display, DefaultScreen(screen->display)),
X	  GCFont, screen->TnormalGC);
X   else
X       XSetFont (screen->display, screen->TnormalGC, fid);
X    }
X
Xstatic int rcnt;
Xstatic char *rptr;
Xstatic int Tselect_mask;
X
XTinput()
X{
X	register TScreen *screen = &term->screen;
X	register int i;
X	register TekLink *tek;
X	extern char *malloc();
X
X	if(Tpushback > Tpushb)
X		return(*--Tpushback);
X	if(TekRefresh) {
X		if(rcnt-- > 0)
X			return(*rptr++);
X		if(tek = TekRefresh->next) {
X			TekRefresh = tek;
X			rcnt = tek->count - 1;
X			rptr = tek->data;
X			return(*rptr++);
X		}
X		TekRefresh = (TekLink *)0;
X		longjmp(Tekjump, 1);
X	}
Xagain:
X	if(Tbcnt-- <= 0) {
X		if(nplot > 0)	/* flush line Tbuffer */
X			TekFlush();
X		Tselect_mask = pty_mask;	/* force a read */
X		for( ; ; ) {
X#ifdef CRAY
X			struct timeval crocktimeout;
X			crocktimeout.tv_sec = 0;
X			crocktimeout.tv_usec = 0;
X			(void) select (max_plus1, &Tselect_mask, (int *) NULL,
X				       (int *) NULL, &crocktimeout);
X#endif
X			if(Tselect_mask & pty_mask) {
X				if(screen->logging)
X					FlushLog(screen);
X				if((Tbcnt = read(screen->respond,
X				 Tbptr = Tbuffer, BUF_SIZE)) < 0) {
X					if(errno == EIO)
X						Cleanup (0);
X					else if(errno != EWOULDBLOCK)
X						Panic(
X				 "Tinput:read returned unexpected error (%d)\n",
X						 errno);
X				} else if(Tbcnt == 0)
X					Panic("input: read returned zero\n", 0);
X				else {
X					break;
X				}
X			}
X			if (Ttoggled && curstate == Talptable) {
X				TCursorToggle(TOGGLE);
X				Ttoggled = FALSE;
X			}
X			if(QLength(screen->display))
X				Tselect_mask = X_mask;
X			else {
X				XFlush(screen->display);
X				Tselect_mask = Select_mask;
X				if((i = select(max_plus1, &Tselect_mask,
X					(int *)NULL, (int *)NULL,
X					(struct timeval *)NULL)) < 0){
X					if (errno != EINTR)
X						SysError(ERROR_TSELECT);
X					continue;
X				}
X			}
X			if(Tselect_mask & X_mask) {
X				xevents();
X				if(Tbcnt > 0)
X					goto again;
X			}
X		}
X		Tbcnt--;
X		if (!Ttoggled && curstate == Talptable) {
X			TCursorToggle(TOGGLE);
X			Ttoggled = TRUE;
X		}
X	}
X	if((tek = TekRecord)->count >= TEK_LINK_BLOCK_SIZE) {
X		if((TekRecord = tek->next = (TekLink *)malloc(sizeof(TekLink)))
X		 == (TekLink *)0)
X			Panic("Tinput: malloc error (%d)\n", errno);
X		tek = tek->next;
X		tek->next = (TekLink *)0;
X		tek->count = 0;
X		tek->ptr = tek->data;
X	}
X	tek->count++;
X	return(*tek->ptr++ = *Tbptr++);
X}
X
X/* this should become the Tek Widget's Resize proc */
Xstatic void TekConfigure(w)
X    Widget w;
X{
X    register TScreen *screen = &term->screen;
X    register int border = 2 * screen->border;
X    register double d;
X
X    if (TWindow(screen)) XClearWindow(screen->display, TWindow(screen));
X    TWidth(screen) = w->core.width - border;
X    THeight(screen) = w->core.height - border;
X    TekScale(screen) = (double)TWidth(screen) / TEKWIDTH;
X    if((d = (double)THeight(screen) / (TEKHEIGHT + TEKTOPPAD + TEKBOTTOMPAD))
X       < TekScale(screen))
X      TekScale(screen) = d;
X    TFullWidth(screen) = w->core.width;
X    TFullHeight(screen) = w->core.height;
X}
X
X/* this should become the Tek Widget's Expose proc */
X/* need to use compress_events = TRUE so you don't need to 
X   look at the "count" in the exposure event ! */
X/*ARGSUSED*/
Xvoid TekExpose(w, event, region)
XWidget w;
XXExposeEvent *event;
XRegion region;
X{
X	register TScreen *screen = &term->screen;
X
X#ifdef lint
X	region = region;
X#endif
X	if(!Ttoggled)
X	    TCursorToggle(CLEAR);
X	Ttoggled = TRUE;
X	Tpushback = Tpushb;
X	screen->cur_X = 0;
X	screen->cur_Y = TEKHOME;
X	screen->cur = screen->page;
X        TekSetGCFont (screen->cur.fontsize);
X	screen->margin = MARGIN1;
X	if(screen->TekGIN) {
X		screen->TekGIN = NULL;
X		TekGINoff();
X	}
X	TekRefresh = &Tek0;
X	rptr = TekRefresh->data;
X	rcnt = TekRefresh->count;
X	Tparsestate = curstate = Talptable;
X	if(!screen->waitrefresh)
X		dorefresh();
X}
X
Xdorefresh()
X{
X	register TScreen *screen = &term->screen;
X	static Cursor wait_cursor = None;
X
X	if (wait_cursor == None)
X            wait_cursor = make_colored_cursor (XC_watch, screen->mousecolor,
X					       screen->mousecolorback);
X        XDefineCursor(screen->display, TShellWindow, wait_cursor);
X	XFlush(screen->display);
X	if(!setjmp(Tekjump))
X		Tekparse();
X	XDefineCursor(screen->display, TShellWindow,
X	 (screen->TekGIN && GINcursor) ? GINcursor : screen->arrow);
X}
X
XTekPage()
X{
X	register TScreen *screen = &term->screen;
X	register TekLink *tek, *tek2;
X
X	XClearWindow(screen->display, TWindow(screen));
X	screen->cur_X = 0;
X	screen->cur_Y = TEKHOME;
X	screen->margin = MARGIN1;
X	screen->page = screen->cur;
X	if(screen->TekGIN)
X		TekGINoff();
X	tek = TekRecord = &Tek0;
X	tek->count = 0;
X	tek->ptr = tek->data;
X	if(tek = tek->next)
X		do {
X			tek2 = tek->next;
X			free((char *)tek);
X		} while(tek = tek2);
X	TekRecord->next = (TekLink *)0;
X	TekRefresh = (TekLink *)0;
X	Ttoggled = TRUE;
X	Tparsestate = curstate = Talptable;	/* Tek Alpha mode */
X}
X
X#define	EXTRABITS	017
X#define	FIVEBITS	037
X#define	HIBITS		(FIVEBITS << SHIFTHI)
X#define	LOBITS		(FIVEBITS << SHIFTLO)
X#define	SHIFTHI		7
X#define	SHIFTLO		2
X#define	TWOBITS		03
X
Xgetpoint()
X{
X	register int c, x, y, e, lo_y = 0;
X	register TScreen *screen = &term->screen;
X
X	x = screen->cur.x;
X	y = screen->cur.y;
X	for( ; ; ) {
X		if((c = input()) < ' ') {	/* control character */
X			unput(c);
X			return(0);
X		}
X		if(c < '@') {	/* Hi X or Hi Y */
X			if(lo_y) {	/* seen a Lo Y, so this must be Hi X */
X				x &= ~HIBITS;
X				x |= (c & FIVEBITS) << SHIFTHI;
X				continue;
X			}
X			/* else Hi Y */
X			y &= ~HIBITS;
X			y |= (c & FIVEBITS) << SHIFTHI;
X			continue;
X		}
X		if(c < '`') {	/* Lo X */
X			x &= ~LOBITS;
X			x |= (c & FIVEBITS) << SHIFTLO;
X			screen->cur.x = x;
X			screen->cur.y = y;
X			return(1);	/* OK */
X		}
X		/* else Lo Y */
X		if(lo_y) {	/* seen a Lo Y, so other must be extra bits */
X			e = (y >> SHIFTLO) & EXTRABITS;
X			x &= ~TWOBITS;
X			x |= e & TWOBITS;
X			y &= ~TWOBITS;
X			y |= (e >> SHIFTLO) & TWOBITS;
X		}
X		y &= ~LOBITS;
X		y |= (c & FIVEBITS) << SHIFTLO;
X		lo_y++;
X	}
X}
X
XTCursorBack()
X{
X	register TScreen *screen = &term->screen;
X	register struct Tek_Char *t;
X	register int x, l;
X
X	x = ( screen->cur_X -=
X		(t = &TekChar[screen->cur.fontsize])->hsize
X	    );
X
X	if(screen->margin == MARGIN1 && x < 0 || screen->margin == MARGIN2
X	 && x < TEKWIDTH / 2) {
X		if((l = (screen->cur_Y + (t->vsize - 1)) / t->vsize + 1) >=
X		 t->nlines) {
X			screen->margin = !screen->margin;
X			l = 0;
X		}
X		screen->cur_Y = l * t->vsize;
X		screen->cur_X = (t->charsperline - 1) * t->hsize;
X	}
X}
X
XTCursorForward()
X{
X	register TScreen *screen = &term->screen;
X	register struct Tek_Char *t;
X	register int l;
X
X	if( ( screen->cur_X +=
X		( t = &TekChar[screen->cur.fontsize])->hsize
X	    ) > TEKWIDTH
X	  ) {
X		if((l = screen->cur_Y / t->vsize - 1) < 0) {
X			screen->margin = !screen->margin;
X			l = t->nlines - 1;
X		}
X		screen->cur_Y = l * t->vsize;
X		screen->cur_X = screen->margin == MARGIN1 ? 0 : TEKWIDTH / 2;
X	}
X}
X
XTCursorUp()
X{
X	register TScreen *screen = &term->screen;
X	register struct Tek_Char *t;
X	register int l;
X
X	t = &TekChar[screen->cur.fontsize];
X
X	if((l = (screen->cur_Y + (t->vsize - 1)) / t->vsize + 1) >= t->nlines) {
X		l = 0;
X		if((screen->margin = !screen->margin) != MARGIN1) {
X			if(screen->cur_X < TEKWIDTH / 2)
X				screen->cur_X += TEKWIDTH / 2;
X		} else if(screen->cur_X >= TEKWIDTH / 2)
X			screen->cur_X -= TEKWIDTH / 2;
X	}
X	screen->cur_Y = l * t->vsize;
X}
X
XTCursorDown()
X{
X	register TScreen *screen = &term->screen;
X	register struct Tek_Char *t;
X	register int l;
X
X	t = &TekChar[screen->cur.fontsize];
X
X	if((l = screen->cur_Y / t->vsize - 1) < 0) {
X		l = t->nlines - 1;
X		if((screen->margin = !screen->margin) != MARGIN1) {
X			if(screen->cur_X < TEKWIDTH / 2)
X				screen->cur_X += TEKWIDTH / 2;
X		} else if(screen->cur_X >= TEKWIDTH / 2)
X			screen->cur_X -= TEKWIDTH / 2;
X	}
X	screen->cur_Y = l * t->vsize;
X}
X
XTekDraw (x, y)
Xint x, y;
X{
X	register TScreen *screen = &term->screen;
X
X	if(nplot == 0 || T_lastx != screen->cur_X || T_lasty != screen->cur_Y) {
X		/*
X		 * We flush on each unconnected line segment if the line
X		 * type is not solid.  This solves a bug in X when drawing
X		 * points while the line type is not solid.
X		 */
X		if(nplot > 0 && screen->cur.linetype != SOLIDLINE)
X			TekFlush();
X	}
X	AddToDraw(screen->cur_X, screen->cur_Y, x, y);
X	T_lastx = screen->cur_X = x;
X	T_lasty = screen->cur_Y = y;
X}
X
XAddToDraw(x1, y1, x2, y2)
Xint x1, y1, x2, y2;
X{
X	register TScreen *screen = &term->screen;
X	register XSegment *lp;
X
X	if(nplot >= MAX_PTS) {
X		TekFlush();
X	}
X	lp = line_pt++;
X	lp->x1 = x1 = x1 * TekScale(screen) + screen->border;
X	lp->y1 = y1 = (TEKHEIGHT + TEKTOPPAD - y1) * TekScale(screen) +
X	 screen->border;
X	lp->x2 = x2 = x2 * TekScale(screen) + screen->border;
X	lp->y2 = y2 = (TEKHEIGHT + TEKTOPPAD - y2) * TekScale(screen) +
X	 screen->border;
X	nplot++;
X}
X
XTekFlush ()
X{
X	register TScreen *screen = &term->screen;
X
X	XDrawSegments(screen->display, TWindow(screen), 
X		((screen->cur.linetype == SOLIDLINE)?  screen->TnormalGC :
X		 screen->linepat[screen->cur.linetype - 1]),
X		 Tline, nplot);
X	nplot = 0;
X	line_pt = Tline;
X}
X
XTekGINoff()
X{
X	register TScreen *screen = &term->screen;
X	
X	XDefineCursor(screen->display, TShellWindow, screen->arrow);
X	if(GINcursor)
X		XFreeCursor(screen->display, GINcursor);
X	if(screen->TekGIN) {
X		*screen->TekGIN = CANCEL;	/* modify recording */
X		screen->TekGIN = NULL;
X	}
X}
X
XTekEnqMouse(c)
Xint c;
X{
X	register TScreen *screen = &term->screen;
X	int mousex, mousey, rootx, rooty;
X	unsigned int mask; /* XQueryPointer */
X	Window root, subw;
X
X	XQueryPointer(
X	    screen->display, TWindow(screen), 
X	    &root, &subw,
X	    &rootx, &rooty,
X	    &mousex, &mousey,
X	    &mask);
X	if((mousex = (mousex - screen->border) / TekScale(screen)) < 0)
X		mousex = 0;
X	else if(mousex >= TEKWIDTH)
X		mousex = TEKWIDTH - 1;
X	if((mousey = TEKHEIGHT + TEKTOPPAD - (mousey - screen->border) /
X	     TekScale(screen)) < 0)
X		mousey = 0;
X	else if(mousey >= TEKHEIGHT)
X		mousey = TEKHEIGHT - 1;
X	TekEnq(c, mousex, mousey);
X}
X
XTekEnq (status, x, y)
Xint status;
Xregister int x, y;
X{
X	register TScreen *screen = &term->screen;
X	int pty = screen->respond;
X	char cplot [5];
X
X	/* Translate x and y to Tektronix code */
X	cplot[1] = 040 | ((x >> SHIFTHI) & FIVEBITS);
X	cplot[2] = 040 | ((x >> SHIFTLO) & FIVEBITS);
X	cplot[3] = 040 | ((y >> SHIFTHI) & FIVEBITS);
X	cplot[4] = 040 | ((y >> SHIFTLO) & FIVEBITS);
X	if(cplot[0] = status)
X		write (pty, cplot, 5);
X	else
X		write (pty, &cplot[1], 4);
X}
X
XTekRun()
X{
X	register TScreen *screen = &term->screen;
X	register int i;
X	
X	if(!TWindow(screen) && !TekInit()) {
X		if(VWindow(screen)) {
X			screen->TekEmu = FALSE;
X			return;
X		}
X		Exit(ERROR_TINIT);
X	}
X	if(!screen->Tshow) {
X	    XtRealizeWidget (tekWidget->core.parent);
X	    set_tek_visibility (TRUE);
X	} 
X	update_vttekmode();
X	update_vtshow();
X	update_tekshow();
X	set_tekhide_sensitivity();
X
X	Tpushback = Tpushb;
X	Tbptr = Tbuffer;
X	for(i = Tbcnt = bcnt ; i > 0 ; i--)
X		*Tbptr++ = *bptr++;
X	Tbptr = Tbuffer;
X	Ttoggled = TRUE;
X	if(!setjmp(Tekend))
X		Tekparse();
X	if(!Ttoggled) {
X		TCursorToggle(TOGGLE);
X		Ttoggled = TRUE;
X	}
X	screen->TekEmu = FALSE;
X}
X
X#define DOTTED_LENGTH 2
X#define DOT_DASHED_LENGTH 4
X#define SHORT_DASHED_LENGTH 2
X#define LONG_DASHED_LENGTH 2
X
Xstatic int dash_length[TEKNUMLINES] = {
X	DOTTED_LENGTH,
X	DOT_DASHED_LENGTH,
X	SHORT_DASHED_LENGTH,
X	LONG_DASHED_LENGTH,
X};
X
Xstatic unsigned char dotted[DOTTED_LENGTH] = {3, 1};
Xstatic unsigned char dot_dashed[DOT_DASHED_LENGTH] = {3, 4, 3, 1};
Xstatic unsigned char short_dashed[SHORT_DASHED_LENGTH] = {4, 4};
Xstatic unsigned char long_dashed[LONG_DASHED_LENGTH] = {4, 7};
X
Xstatic unsigned char *dashes[TEKNUMLINES] = {
X	dotted,
X	dot_dashed,
X	short_dashed,
X	long_dashed,
X};
X
X
X
X/*
X * The following is called the create the tekWidget
X */
X
Xstatic void TekInitialize(request, new)
X    Widget request, new;
X{
X   /* look for focus related events on the shell, because we need
X    * to care about the shell's border being part of our focus.
X    */
X    XtAddEventHandler(XtParent(new), EnterWindowMask, FALSE,
X		      HandleEnterWindow, (caddr_t)NULL);
X    XtAddEventHandler(XtParent(new), LeaveWindowMask, FALSE,
X		      HandleLeaveWindow, (caddr_t)NULL);
X    XtAddEventHandler(XtParent(new), FocusChangeMask, FALSE,
X		      HandleFocusChange, (caddr_t)NULL);
X}
X
X
Xstatic void TekRealize (gw, valuemaskp, values)
X    Widget gw;
X    XtValueMask *valuemaskp;
X    XSetWindowAttributes *values;
X{
X    TekWidget tw = (TekWidget) gw;
X    register TScreen *screen = &term->screen;
X    register int i;
X    register TekLink *tek;
X    register double d;
X    register int border = 2 * screen->border;
X    int pr;
X    XGCValues gcv;
X    int winX, winY, width, height;
X    XSizeHints sizehints;
X    char Tdefault[32];
X    extern char *malloc();
X
X    tw->core.border_pixel = term->core.border_pixel;
X
X    for (i = 0; i < TEKNUMFONTS; i++) {
X	if (!tw->tek.Tfont[i]) 
X	  tw->tek.Tfont[i] = XQueryFont (screen->display, DefaultGCID);
X	tw->tek.tobaseline[i] = tw->tek.Tfont[i]->ascent;
X    }
X
X    if((Tbuffer = (Char *)malloc(BUF_SIZE)) == NULL ||
X       (Tpushb = (Char *)malloc(10)) == NULL ||
X       (Tline = (XSegment *)malloc(MAX_VTX * sizeof(XSegment))) == NULL) {
X	fprintf (stderr, "%s: Not enough core for Tek mode\n", xterm_name);
X	goto mallocfailed;
X    }
X
X    screen->xorplane = 1;
X
X    screen->Tbackground = term->core.background_pixel;
X    screen->Tforeground = screen->foreground;
X    screen->Tcursorcolor = screen->foreground;
X
X    if (term->misc.T_geometry == NULL) {
X	int defwidth, defheight;
X
X	if (term->misc.tekSmall) {
X	    defwidth = TEKMINWIDTH;
X	    defheight = TEKMINHEIGHT;
X	} else {
X	    defwidth = TEKDEFWIDTH;
X	    defheight = TEKDEFHEIGHT;
X	}
X	sprintf (Tdefault, "=%dx%d", defwidth + border, defheight + border);
X	term->misc.T_geometry = Tdefault;
X    }
X
X    winX = 1;
X    winY = 1;
X    width = TEKDEFWIDTH + border;
X    height = TEKDEFHEIGHT + border;
X
X    pr = XParseGeometry(term->misc.T_geometry, &winX, &winY, (unsigned int *)&width, (unsigned int *)&height);
X    if ((pr & XValue) && (pr & XNegative))
X      winX += DisplayWidth(screen->display, DefaultScreen(screen->display))
X                        - width - (term->core.parent->core.border_width * 2);
X    if ((pr & YValue) && (pr & YNegative))
X      winY += DisplayHeight(screen->display, DefaultScreen(screen->display))
X	- height - (term->core.parent->core.border_width * 2);
X  
X    /* set up size hints */
X    sizehints.min_width = TEKMINWIDTH + border;
X    sizehints.min_height = TEKMINHEIGHT + border;
X    sizehints.width_inc = 1;
X    sizehints.height_inc = 1;
X    sizehints.flags = PMinSize|PResizeInc;
X    sizehints.x = winX;
X    sizehints.y = winY;
X    if ((XValue&pr) || (YValue&pr)) {
X	sizehints.flags |= USSize|USPosition;
X	sizehints.flags |= PWinGravity;
X	switch (pr & (XNegative | YNegative)) {
X	  case 0:
X	    sizehints.win_gravity = NorthWestGravity;
X	    break;
X	  case XNegative:
X	    sizehints.win_gravity = NorthEastGravity;
X	    break;
X	  case YNegative:
X	    sizehints.win_gravity = SouthWestGravity;
X	    break;
X	  default:
X	    sizehints.win_gravity = SouthEastGravity;
X	    break;
X	}
X    } else {
X	sizehints.flags |= PSize;
X    }
X    sizehints.width = width;
X    sizehints.height = height;
X    if ((WidthValue&pr) || (HeightValue&pr))
X      sizehints.flags |= USSize;
X    else sizehints.flags |= PSize;
X
X    (void) XtMakeResizeRequest ((Widget) tw, width, height,
X				&tw->core.width, &tw->core.height);
X
X    /* XXX This is bogus.  We are parsing geometries too late.  This
X     * is information that the shell widget ought to have before we get
X     * realized, so that it can do the right thing.
X     */
X    if (sizehints.flags & USPosition)
X      XMoveWindow (XtDisplay(tw), tw->core.parent->core.window,
X		   sizehints.x, sizehints.y);
X
X    XSetWMNormalHints (XtDisplay(tw), tw->core.parent->core.window,
X		       &sizehints);
X
X    values->win_gravity = NorthWestGravity;
X    values->background_pixel = screen->Tbackground;
X
X    if((tw->core.window = TWindow(screen) = 
X	XCreateWindow (screen->display,
X		       tw->core.parent->core.window,
X		       tw->core.x, tw->core.y,
X		       tw->core.width, tw->core.height, tw->core.border_width,
X		       (int) tw->core.depth,
X		       InputOutput, CopyFromParent,
X		       ((*valuemaskp)|CWBackPixel|CWWinGravity),
X		       values)) == NULL) {
X	fprintf(stderr, "%s: Can't create Tek window\n", xterm_name);
X	free((char *)Tline);
X      mallocfailed:
X	if(Tpushb) free((char *)Tpushb);
X	if(Tbuffer) free((char *)Tbuffer);
X	Tfailed = TRUE;
X	return;
X    }
X
X    screen->Tbox = T_box;
X
X    TFullWidth(screen) = width;
X    TFullHeight(screen) = height;
X    TWidth(screen) = width - border;
X    THeight(screen) = height - border;
X    TekScale(screen) = (double)TWidth(screen) / TEKWIDTH;
X    if((d = (double)THeight(screen) / (TEKHEIGHT + TEKTOPPAD +
X				       TEKBOTTOMPAD)) < TekScale(screen))
X      TekScale(screen) = d;
X    
X
X    screen->cur.fontsize = TEK_FONT_LARGE;
X    if (tw->tek.initial_font) {
X	char *s = tw->tek.initial_font;
X
X	XmuCopyISOLatin1Lowered (s, s);
X	if (strcmp (s, "large") == 0)
X	  screen->cur.fontsize = TEK_FONT_LARGE;
X	else if (strcmp (s, "2") == 0 || strcmp (s, "two") == 0)
X	  screen->cur.fontsize = TEK_FONT_2;
X	else if (strcmp (s, "3") == 0 || strcmp (s, "three") == 0)
X	  screen->cur.fontsize = TEK_FONT_3;
X	else if (strcmp (s, "small") == 0)
X	  screen->cur.fontsize = TEK_FONT_SMALL;
X    }
X
X    gcv.graphics_exposures = TRUE;	/* default */
X    gcv.font = tw->tek.Tfont[screen->cur.fontsize]->fid;
X    gcv.foreground = screen->Tforeground;
X    gcv.background = screen->Tbackground;
X    
X    /* if font wasn't successfully opened, then gcv.font will contain
X       the Default GC's ID, meaning that we must use the server default font. 
X     */
X    TEKgcFontMask = (gcv.font == DefaultGCID) ? 0 : GCFont;
X    screen->TnormalGC = XCreateGC (screen->display, TWindow(screen), 
X				   (TEKgcFontMask|GCGraphicsExposures|
X				    GCForeground|GCBackground), &gcv);
X
X    gcv.function = GXinvert;
X    gcv.plane_mask = screen->xorplane = (screen->Tbackground ^
X					 screen->Tcursorcolor);
X    screen->TcursorGC = XCreateGC (screen->display, TWindow(screen), 
X				   (GCFunction|GCPlaneMask), &gcv);
X
X    gcv.foreground = screen->Tforeground;
X    gcv.line_style = LineOnOffDash;
X    for(i = 0 ; i < TEKNUMLINES ; i++) {
X	screen->linepat[i] = XCreateGC (screen->display, TWindow(screen),
X					(GCForeground|GCLineStyle), &gcv); 
X	XSetDashes (screen->display, screen->linepat[i], 0,
X		    (char *) dashes[i], dash_length[i]);
X    }
X
X    TekBackground(screen);
X
X    screen->margin = MARGIN1;		/* Margin 1		*/
X    screen->TekGIN = FALSE;			/* GIN off		*/
X
X
X    XDefineCursor(screen->display, TShellWindow, screen->pointer_cursor);
X
X    {	/* there's gotta be a better way... */
X	static Arg args[] = {
X	    {XtNtitle, NULL},
X	    {XtNiconName, NULL},
X	};
X	char *icon_name, *title, *tek_icon_name, *tek_title;
X
X	args[0].value = (XtArgVal)&icon_name;
X	args[1].value = (XtArgVal)&title;
X	XtGetValues (tw->core.parent, args, 2);
X	tek_icon_name = XtMalloc(strlen(icon_name)+7);
X	strcpy(tek_icon_name, icon_name);
X	strcat(tek_icon_name, "(Tek)");
X	tek_title = XtMalloc(strlen(title)+7);
X	strcpy(tek_title, title);
X	strcat(tek_title, "(Tek)");
X	args[0].value = (XtArgVal)tek_icon_name;
X	args[1].value = (XtArgVal)tek_title;
X	XtSetValues (tw->core.parent, args, 2);
X	XtFree( tek_icon_name );
X	XtFree( tek_title );
X    }
X
X    tek = TekRecord = &Tek0;
X    tek->next = (TekLink *)0;
X    tek->count = 0;
X    tek->ptr = tek->data;
X    Tpushback = Tpushb;
X    Tbptr = Tbuffer;
X    screen->cur_X = 0;
X    screen->cur_Y = TEKHOME;
X    line_pt = Tline;
X    Ttoggled = TRUE;
X    screen->page = screen->cur;
X    return;
X}
X
Xvoid TekSetFontSize (gw, newitem)
X    Widget gw;
X    int newitem;
X{
X    register TScreen *screen = &term->screen;
X    int oldsize = screen->cur.fontsize;
X    int newsize = MI2FS(newitem);
X    
X    if (oldsize == newsize) return;
X    if (!Ttoggled) TCursorToggle(TOGGLE);
X    set_tekfont_menu_item (oldsize, FALSE);
X    TekSetGCFont (newsize);
X    screen->cur.fontsize = newsize;
X    set_tekfont_menu_item (newsize, TRUE);
X    if (!Ttoggled) TCursorToggle(TOGGLE);
X}
X
XTekReverseVideo(screen)
Xregister TScreen *screen;
X{
X	register int i;
X	XGCValues gcv;
X	 
X
X	i = screen->Tbackground;
X	screen->Tbackground = screen->Tforeground;
X	screen->Tforeground = i;
X	
X	XSetForeground(screen->display, screen->TnormalGC, 
X	 screen->Tforeground);
X	XSetBackground(screen->display, screen->TnormalGC, 
X	 screen->Tbackground);
X
X	if (tekWidget) {
X	    if (tekWidget->core.border_pixel == screen->Tbackground) {
X		tekWidget->core.border_pixel = screen->Tforeground;
X		tekWidget->core.parent->core.border_pixel =
X		  screen->Tforeground;
X		if (tekWidget->core.parent->core.window)
X		  XSetWindowBorder (screen->display,
X				    tekWidget->core.parent->core.window,
X				    tekWidget->core.border_pixel);
X	    }
X	}
X
X	for(i = 0 ; i < TEKNUMLINES ; i++) {
X		XSetForeground(screen->display, screen->linepat[i], 
X		 screen->Tforeground);
X	}
X
X	screen->Tcursorcolor = screen->Tforeground;
X
X	gcv.plane_mask = screen->xorplane = (screen->Tbackground ^
X					     screen->Tcursorcolor);
X	XChangeGC (screen->display, screen->TcursorGC, GCPlaneMask, &gcv);
X	TekBackground(screen);
X}
X
XTekBackground(screen)
Xregister TScreen *screen;
X{
X	if(TWindow(screen))
X		XSetWindowBackground(screen->display, TWindow(screen), 
X		 screen->Tbackground);
X}
X
X/*
X * Toggles cursor on or off at cursor position in screen.
X */
XTCursorToggle(toggle)
Xint toggle;
X{
X	register TScreen *screen = &term->screen;
X	register int c, x, y;
X	unsigned int cellwidth, cellheight;
X
X	if (!screen->Tshow) return;
X
X	c = screen->cur.fontsize;
X	cellwidth = (unsigned) tekWidget->tek.Tfont[c]->max_bounds.width;
X	cellheight = (unsigned) (tekWidget->tek.Tfont[c]->ascent + 
X				 tekWidget->tek.Tfont[c]->descent);
X
X	x = (screen->cur_X * TekScale(screen)) + screen->border;
X	y = ((TEKHEIGHT + TEKTOPPAD - screen->cur_Y) * TekScale(screen)) +
X	 screen->border - tekWidget->tek.tobaseline[c];
X	if (toggle) {
X	   if (screen->select || screen->always_highlight) 
X		XFillRectangle(
X		    screen->display, TWindow(screen), screen->TcursorGC,
X		    x, y, cellwidth, cellheight);
X	  else { /* fix to use different GC! */
X		  screen->Tbox[c]->x = x;
X		  screen->Tbox[c]->y = y ;
X		  XDrawLines(screen->display, TWindow(screen), 
X		    screen->TcursorGC,
X		    screen->Tbox[c], NBOX, CoordModePrevious);
X	   }
X	} else {
X	   if (screen->select || screen->always_highlight) 
X		XClearArea(screen->display, TWindow(screen), x, y,
X			   cellwidth, cellheight, FALSE);
X	   else { 
X		  screen->Tbox[c]->x = x;
X		  screen->Tbox[c]->y = y ;
X		  XDrawLines(screen->display, TWindow(screen), 
X		    screen->TcursorGC,
X		    screen->Tbox[c], NBOX, CoordModePrevious);
X	   }
X	}
X}
X
Xvoid TekSimulatePageButton (reset)
X    Bool reset;
X{
X    register TScreen *screen = &term->screen;
X
X    if (reset) {
X/*      bzero ((char *)&curmodes, sizeof(Tmodes));             */
X	bzero ((char *) &screen->cur, sizeof screen->cur);
X    }
X    TekRefresh = (TekLink *)0;
X/*    screen->cur = curmodes; */
X    TekPage ();
X    screen->cur_X = 0;
X    screen->cur_Y = TEKHOME;
X}
X
X
XTekCopy()
X{
X	register TekLink *Tp;
X	register int fd;
X	register TScreen *screen = &term->screen;
X	register struct tm *tp;
X	long l;
X	char buf[32];
X
X	time(&l);
X	tp = localtime(&l);
X	sprintf(buf, "COPY%02d-%02d-%02d.%02d:%02d:%02d", tp->tm_year,
X	 tp->tm_mon, tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec);
X	if(access(buf, F_OK) >= 0) {	/* file exists */
X		if(access(buf, W_OK) < 0) {
X			Bell();
X			return;
X		}
X	} else if(access(".", W_OK) < 0) {	/* can't write in directory */
X		Bell();
X		return;
X	}
X	if((fd = open(buf, O_WRONLY | O_CREAT | O_TRUNC, 0644)) < 0) {
X		Bell();
X		return;
X	}
X	chown(buf, screen->uid, screen->gid);
X	sprintf(buf, "\033%c\033%c", screen->page.fontsize + '8',
X	 screen->page.linetype + '`');
X	write(fd, buf, 4);
X	Tp = &Tek0; 
X	do
X		write(fd, (char *)Tp->data, Tp->count);
X	while(Tp = Tp->next);
X	close(fd);
X}
X
X
X
SHAR_EOF
chmod 0644 Tekproc.c || echo "restore of Tekproc.c fails"
if [ $TOUCH = can ]
then
    touch -am 1109132690 Tekproc.c
fi
fi
# ============= button.c ==============
if test -f button.c; then echo "File button.c exists"; else
sed 's/^X//' << 'SHAR_EOF' > button.c &&
X/*
X *	$XConsortium: button.c,v 1.50 90/03/05 11:46:57 keith Exp $
X */
X
X
X#include <X11/copyright.h>
X
X/*
X * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
X *
X *                         All Rights Reserved
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Digital Equipment
X * Corporation not be used in advertising or publicity pertaining to
X * distribution of the software without specific, written prior permission.
X *
X *
X * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
X * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
X * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
X * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
X * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
X * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
X * SOFTWARE.
X */
X
X/*
Xbutton.c	Handles button events in the terminal emulator.
X		does cut/paste operations, change modes via menu,
X		passes button events through to some applications.
X				J. Gettys.
X*/
X#ifndef lint
Xstatic char rcs_id[] = "$XConsortium: button.c,v 1.50 90/03/05 11:46:57 keith Exp $";
X#endif	/* lint */
X
X#include "ptyx.h"		/* Xlib headers included here. */
X#include <X11/Xatom.h>
X#include <stdio.h>
X#include <setjmp.h>
X#include <ctype.h>
X
X#include <X11/Xmu/Atoms.h>
X#include <X11/Xmu/StdSel.h>
X
X#include "data.h"
X#include "error.h"
X#include "menu.h"
X
Xextern char *malloc();
X
X#define KeyState(x) (((x) & (ShiftMask|ControlMask)) + (((x) & Mod1Mask) ? 2 : 0))
X    /* adds together the bits:
X        shift key -> 1
X        meta key  -> 2
X        control key -> 4 */
X  
X#define TEXTMODES 4
X#define NBUTS 3
X#define DIRS 2
X#define UP 1
X#define DOWN 0
X#define SHIFTS 8		/* three keys, so eight combinations */
X#define	Coordinate(r,c)		((r) * (term->screen.max_col+1) + (c))
X
Xchar *SaveText();
Xextern EditorButton();
X
Xextern char *xterm_name;
Xextern Bogus();
X
Xstatic PointToRowCol();
X
Xextern XtermWidget term;
X
X/* Selection/extension variables */
X
X/* Raw char position where the selection started */
Xstatic int rawRow, rawCol;
X
X/* Selected area before CHAR, WORD, LINE selectUnit processing */
Xstatic int startRRow, startRCol, endRRow, endRCol = 0;
X
X/* Selected area after CHAR, WORD, LINE selectUnit processing */
Xstatic int startSRow, startSCol, endSRow, endSCol = 0;
X
X/* Valid rows for selection clipping */
Xstatic int firstValidRow, lastValidRow;
X
X/* Start, end of extension */
Xstatic int startERow, startECol, endERow, endECol;
X
X/* Saved values of raw selection for extend to restore to */
Xstatic int saveStartRRow, saveStartRCol, saveEndRRow, saveEndRCol;
X
X/* Multi-click handling */
Xstatic int numberOfClicks = 0;
Xstatic long int lastButtonUpTime = 0;
Xtypedef int SelectUnit;
X#define SELECTCHAR 0
X#define SELECTWORD 1
X#define SELECTLINE 2
X#define NSELECTUNITS 3
Xstatic SelectUnit selectUnit;
X
X/* Send emacs escape code when done selecting or extending? */
Xstatic int replyToEmacs;
X
X
XBoolean SendMousePosition(w, event)
XWidget w;
XXEvent* event;
X{
X    register TScreen *screen = &((XtermWidget)w)->screen;
X    static TrackDown();
X    
X    if (screen->send_mouse_pos == 0) return False;
X
X    if (event->type != ButtonPress && event->type != ButtonRelease)
X	return False;
X
X#define KeyModifiers \
X    (event->xbutton.state & (ShiftMask | LockMask | ControlMask | Mod1Mask | \
X			     Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask ))
X
X#define ButtonModifiers \
X    (event->xbutton.state & (ShiftMask | LockMask | ControlMask | Mod1Mask | \
X			     Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask ))
X
X    switch (screen->send_mouse_pos) {
X      case 1: /* X10 compatibility sequences */
X
X	if (KeyModifiers == 0) {
X	    if (event->type == ButtonPress)
X		EditorButton(event);
X	    return True;
X	}
X	return False;
X
X      case 2: /* DEC vt200 compatible */
X
X	if (KeyModifiers == 0 || KeyModifiers == ControlMask) {
X	    EditorButton(event);
X	    return True;
X	}
X	return False;
X
X      case 3: /* DEC vt200 hilite tracking */
X	if (  event->type == ButtonPress &&
X	      KeyModifiers == 0 &&
X	      event->xbutton.button == Button1 ) {
X	    TrackDown(event);
X	    return True;
X	}
X	if (KeyModifiers == 0 || KeyModifiers == ControlMask) {
X	    EditorButton(event);
X	    return True;
X	}
X	/* fall through */
X
X      default:
X	return False;
X    }
X#undef KeyModifiers
X}
X
X
X/*ARGSUSED*/
Xvoid HandleSelectExtend(w, event, params, num_params)
XWidget w;
XXEvent *event;			/* must be XMotionEvent */
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X	register TScreen *screen = &((XtermWidget)w)->screen;
X	int row, col;
X
X	screen->selection_time = event->xmotion.time;
X	switch (eventMode) {
X		case LEFTEXTENSION :
X		case RIGHTEXTENSION :
X			PointToRowCol (event->xmotion.y, event->xmotion.x, 
X				       &row, &col);
X			ExtendExtend (row, col);
X			break;
X		case NORMAL :
X			/* will get here if send_mouse_pos != 0 */
X		        break;
X	}
X}
X
X
X/*ARGSUSED*/
Xstatic void do_select_end (w, event, params, num_params, use_cursor_loc)
XWidget w;
XXEvent *event;			/* must be XButtonEvent */
XString *params;			/* selections */
XCardinal *num_params;
XBool use_cursor_loc;
X{
X	((XtermWidget)w)->screen.selection_time = event->xbutton.time;
X	switch (eventMode) {
X		case NORMAL :
X		        (void) SendMousePosition(w, event);
X			break;
X		case LEFTEXTENSION :
X		case RIGHTEXTENSION :
X			EndExtend(event, params, *num_params, use_cursor_loc);
X			break;
X	}
X}
X
X
Xvoid HandleSelectEnd(w, event, params, num_params)
XWidget w;
XXEvent *event;			/* must be XButtonEvent */
XString *params;			/* selections */
XCardinal *num_params;
X{
X	do_select_end (w, event, params, num_params, False);
X}
X
X
Xvoid HandleKeyboardSelectEnd(w, event, params, num_params)
XWidget w;
XXEvent *event;			/* must be XButtonEvent */
XString *params;			/* selections */
XCardinal *num_params;
X{
X	do_select_end (w, event, params, num_params, True);
X}
X
X
X
X
Xstruct _SelectionList {
X    String *params;
X    Cardinal count;
X    Time time;
X};
X
X
Xstatic void _GetSelection(w, time, params, num_params)
XWidget w;
XTime time;
XString *params;			/* selections in precedence order */
XCardinal num_params;
X{
X    static void SelectionReceived();
X    Atom selection;
X    int buffer;
X
X    XmuInternStrings(XtDisplay(w), params, (Cardinal)1, &selection);
X    switch (selection) {
X      case XA_CUT_BUFFER0: buffer = 0; break;
X      case XA_CUT_BUFFER1: buffer = 1; break;
X      case XA_CUT_BUFFER2: buffer = 2; break;
X      case XA_CUT_BUFFER3: buffer = 3; break;
X      case XA_CUT_BUFFER4: buffer = 4; break;
X      case XA_CUT_BUFFER5: buffer = 5; break;
X      case XA_CUT_BUFFER6: buffer = 6; break;
X      case XA_CUT_BUFFER7: buffer = 7; break;
X      default:	       buffer = -1;
X    }
X    if (buffer >= 0) {
X	register TScreen *screen = &((XtermWidget)w)->screen;
X	int inbytes;
X	unsigned long nbytes;
X	int fmt8 = 8;
X	Atom type = XA_STRING;
X	char *line = XFetchBuffer(screen->display, &inbytes, buffer);
X	nbytes = (unsigned long) inbytes;
X	if (nbytes > 0)
X	    SelectionReceived(w, NULL, &selection, &type, (caddr_t)line,
X			      &nbytes, &fmt8);
X	else if (num_params > 1)
X	    _GetSelection(w, time, params+1, num_params-1);
X    } else {
X	struct _SelectionList* list;
X	if (--num_params) {
X	    list = XtNew(struct _SelectionList);
X	    list->params = params + 1;
X	    list->count = num_params;
X	    list->time = time;
X	} else list = NULL;
X	XtGetSelectionValue(w, selection, XA_STRING, SelectionReceived,
X			    (caddr_t)list, time);
X    }
X}
X
X
X/* ARGSUSED */
Xstatic void SelectionReceived(w, client_data, selection, type,
X			      value, length, format)
XWidget w;
Xcaddr_t client_data;
XAtom *selection, *type;
Xcaddr_t value;
Xunsigned long *length;
Xint *format;
X{
X    int pty = ((XtermWidget)w)->screen.respond;	/* file descriptor of pty */
X    register char *lag, *cp, *end;
X    char *line = (char*)value;
X				  
X    if (*type == 0 /*XT_CONVERT_FAIL*/ || *length == 0) {
X	struct _SelectionList* list = (struct _SelectionList*)client_data;
X	if (list != NULL) {
X	    _GetSelection(w, list->time, list->params, list->count);
X	    XtFree(client_data);
X	}
X	return;
X    }
X
X    end = &line[*length];
X    lag = line;
X    for (cp = line; cp != end; cp++)
X	{
X	    if (*cp != '\n') continue;
X	    *cp = '\r';
X	    v_write(pty, lag, cp - lag + 1);
X	    lag = cp + 1;
X	}
X    if (lag != end)
X	v_write(pty, lag, end - lag);
X
X    XtFree(client_data);
X    XtFree(value);
X}
X
X
XHandleInsertSelection(w, event, params, num_params)
XWidget w;
XXEvent *event;			/* assumed to be XButtonEvent* */
XString *params;			/* selections in precedence order */
XCardinal *num_params;
X{
X    if (SendMousePosition(w, event)) return;
X    _GetSelection(w, event->xbutton.time, params, *num_params);
X}
X
X
XSetSelectUnit(buttonDownTime, defaultUnit)
Xunsigned long buttonDownTime;
XSelectUnit defaultUnit;
X{
X/* Do arithmetic as integers, but compare as unsigned solves clock wraparound */
X	if ((long unsigned)((long int)buttonDownTime - lastButtonUpTime)
X	 > term->screen.multiClickTime) {
X		numberOfClicks = 1;
X		selectUnit = defaultUnit;
X	} else {
X		++numberOfClicks;
X		selectUnit = ((selectUnit + 1) % NSELECTUNITS);
X	}
X}
X
Xstatic void do_select_start (w, event, startrow, startcol)
XWidget w;
XXEvent *event;			/* must be XButtonEvent* */
Xint startrow, startcol;
X{
X	if (SendMousePosition(w, event)) return;
X	SetSelectUnit(event->xbutton.time, SELECTCHAR);
X	replyToEmacs = FALSE;
X	StartSelect(startrow, startcol);
X}
X
X/* ARGSUSED */
XHandleSelectStart(w, event, params, num_params)
XWidget w;
XXEvent *event;			/* must be XButtonEvent* */
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X	register TScreen *screen = &((XtermWidget)w)->screen;
X	int startrow, startcol;
X
X	firstValidRow = 0;
X	lastValidRow  = screen->max_row;
X	PointToRowCol(event->xbutton.y, event->xbutton.x, &startrow, &startcol);
X	do_select_start (w, event, startrow, startcol);
X}
X
X
X/* ARGSUSED */
XHandleKeyboardSelectStart(w, event, params, num_params)
XWidget w;
XXEvent *event;			/* must be XButtonEvent* */
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X	register TScreen *screen = &((XtermWidget)w)->screen;
X
X	do_select_start (w, event, screen->cursor_row, screen->cursor_col);
X}
X
X
Xstatic TrackDown(event)
Xregister XButtonEvent *event;
X{
X	int startrow, startcol;
X
X	SetSelectUnit(event->time, SELECTCHAR);
X	if (numberOfClicks > 1 ) {
X		PointToRowCol(event->y, event->x, &startrow, &startcol);
X		replyToEmacs = TRUE;
X		StartSelect(startrow, startcol);
X	} else {
X		waitingForTrackInfo = 1;
X		EditorButton(event);
X	}
X}
X
X
X#define boundsCheck(x)	if (x < 0) \
X			    x = 0; \
X			else if (x >= screen->max_row) \
X			    x = screen->max_row;
X
XTrackMouse(func, startrow, startcol, firstrow, lastrow)
Xint func, startrow, startcol, firstrow, lastrow;
X{
X	TScreen *screen = &term->screen;
X
X	if (!waitingForTrackInfo) {	/* Timed out, so ignore */
X		return;
X	}
X	waitingForTrackInfo = 0;
X	if (func == 0) return;
X	boundsCheck (startrow)
X	boundsCheck (firstrow)
X	boundsCheck (lastrow)
X	firstValidRow = firstrow;
X	lastValidRow  = lastrow;
X	replyToEmacs = TRUE;
X	StartSelect(startrow, startcol);
X}
X
XStartSelect(startrow, startcol)
Xint startrow, startcol;
X{
X	TScreen *screen = &term->screen;
X
X	if (screen->cursor_state)
X	    HideCursor ();
X	if (numberOfClicks == 1) {
X		/* set start of selection */
X		rawRow = startrow;
X		rawCol = startcol;
X		
X	} /* else use old values in rawRow, Col */
X
X	saveStartRRow = startERow = rawRow;
X	saveStartRCol = startECol = rawCol;
X	saveEndRRow   = endERow   = rawRow;
X	saveEndRCol   = endECol   = rawCol;
X	if (Coordinate(startrow, startcol) < Coordinate(rawRow, rawCol)) {
X		eventMode = LEFTEXTENSION;
X		startERow = startrow;
X		startECol = startcol;
X	} else {
X		eventMode = RIGHTEXTENSION;
X		endERow = startrow;
X		endECol = startcol;
X	}
X	ComputeSelect(startERow, startECol, endERow, endECol, False);
X
X}
X
XEndExtend(event, params, num_params, use_cursor_loc)
XXEvent *event;			/* must be XButtonEvent */
XString *params;			/* selections */
XCardinal num_params;
XBool use_cursor_loc;
X{
X	int	row, col;
X	TScreen *screen = &term->screen;
X	char line[9];
X
X	if (use_cursor_loc) {
X	    row = screen->cursor_row;
X	    col = screen->cursor_col;
X	} else {
X	    PointToRowCol(event->xbutton.y, event->xbutton.x, &row, &col);
X	}
X	ExtendExtend (row, col);
X	lastButtonUpTime = event->xbutton.time;
X	if (startSRow != endSRow || startSCol != endSCol) {
X		if (replyToEmacs) {
X			if (rawRow == startSRow && rawCol == startSCol 
X			 && row == endSRow && col == endSCol) {
X			 	/* Use short-form emacs select */
X				strcpy(line, "\033[t");
X				line[3] = ' ' + endSCol + 1;
X				line[4] = ' ' + endSRow + 1;
X				v_write(screen->respond, line, 5);
X			} else {
X				/* long-form, specify everything */
X				strcpy(line, "\033[T");
X				line[3] = ' ' + startSCol + 1;
X				line[4] = ' ' + startSRow + 1;
X				line[5] = ' ' + endSCol + 1;
X				line[6] = ' ' + endSRow + 1;
X				line[7] = ' ' + col + 1;
X				line[8] = ' ' + row + 1;
X				v_write(screen->respond, line, 9);
X			}
X			TrackText(0, 0, 0, 0);
X		}
X	}
X	SelectSet(event, params, num_params);
X	eventMode = NORMAL;
X}
X
XHandleSelectSet(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X	SelectSet (event, params, *num_params);
X}
X
XSelectSet (event, params, num_params)
XXEvent	*event;
XString	*params;
XCardinal    num_params;
X{
X	/* Only do select stuff if non-null select */
X	if (startSRow != endSRow || startSCol != endSCol) {
X		SaltTextAway(startSRow, startSCol, endSRow, endSCol,
X			     params, num_params);
X	} else
X		DisownSelection(term);
X}
X
X#define Abs(x)		((x) < 0 ? -(x) : (x))
X
X/* ARGSUSED */
Xstatic void do_start_extend (w, event, params, num_params, use_cursor_loc)
XWidget w;
XXEvent *event;			/* must be XButtonEvent* */
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
XBool use_cursor_loc;
X{
X	TScreen *screen = &((XtermWidget)w)->screen;
X	int row, col, coord;
X
X	if (SendMousePosition(w, event)) return;
X	firstValidRow = 0;
X	lastValidRow  = screen->max_row;
X	SetSelectUnit(event->xbutton.time, selectUnit);
X	replyToEmacs = FALSE;
X
X	if (numberOfClicks == 1) {
X		/* Save existing selection so we can reestablish it if the guy
X		   extends past the other end of the selection */
X		saveStartRRow = startERow = startRRow;
X		saveStartRCol = startECol = startRCol;
X		saveEndRRow   = endERow   = endRRow;
X		saveEndRCol   = endECol   = endRCol;
X	} else {
X		/* He just needed the selection mode changed, use old values. */
X		startERow = startRRow = saveStartRRow;
X		startECol = startRCol = saveStartRCol;
X		endERow   = endRRow   = saveEndRRow;
X		endECol   = endRCol   = saveEndRCol;
X
X	}
X	if (use_cursor_loc) {
X	    row = screen->cursor_row;
X	    col = screen->cursor_col;
X	} else {
X	    PointToRowCol(event->xbutton.y, event->xbutton.x, &row, &col);
X	}
X	coord = Coordinate(row, col);
X
X	if (Abs(coord - Coordinate(startSRow, startSCol))
X	     < Abs(coord - Coordinate(endSRow, endSCol))
X	    || coord < Coordinate(startSRow, startSCol)) {
X	 	/* point is close to left side of selection */
X		eventMode = LEFTEXTENSION;
X		startERow = row;
X		startECol = col;
X	} else {
X	 	/* point is close to left side of selection */
X		eventMode = RIGHTEXTENSION;
X		endERow = row;
X		endECol = col;
X	}
X	ComputeSelect(startERow, startECol, endERow, endECol, True);
X}
X
XExtendExtend (row, col)
Xint row, col;
X{
X	int coord = Coordinate(row, col);
X	
X	if (eventMode == LEFTEXTENSION 
X	 && (coord + (selectUnit!=SELECTCHAR)) > Coordinate(endSRow, endSCol)) {
X		/* Whoops, he's changed his mind.  Do RIGHTEXTENSION */
X		eventMode = RIGHTEXTENSION;
X		startERow = saveStartRRow;
X		startECol = saveStartRCol;
X	} else if (eventMode == RIGHTEXTENSION
X	 && coord < Coordinate(startSRow, startSCol)) {
X	 	/* Whoops, he's changed his mind.  Do LEFTEXTENSION */
X		eventMode = LEFTEXTENSION;
X		endERow   = saveEndRRow;
X		endECol   = saveEndRCol;
X	}
X	if (eventMode == LEFTEXTENSION) {
X		startERow = row;
X		startECol = col;
X	} else {
X		endERow = row;
X		endECol = col;
X	}
X	ComputeSelect(startERow, startECol, endERow, endECol, False);
X}
X
X
Xvoid HandleStartExtend(w, event, params, num_params)
XWidget w;
XXEvent *event;			/* must be XButtonEvent* */
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X    do_start_extend (w, event, params, num_params, False);
X}
X
Xvoid HandleKeyboardStartExtend(w, event, params, num_params)
XWidget w;
XXEvent *event;			/* must be XButtonEvent* */
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X    do_start_extend (w, event, params, num_params, True);
X}
X
X
X
X
X
XScrollSelection(screen, amount)
Xregister TScreen* screen;
Xregister int amount;
X{
X    register int minrow = -screen->savedlines;
X
X    /* Sent by scrollbar stuff, so amount never takes selection out of
X       saved text */
X
X    /* XXX - the preceeding is false; cat /etc/termcap (or anything
X       larger than the number of saved lines plus the screen height) and then
X       hit extend select */
X
X    startRRow += amount; endRRow += amount;
X    startSRow += amount; endSRow += amount;
X    rawRow += amount;
X    screen->startHRow += amount;
X    screen->endHRow += amount;
X
X    if (startRRow < minrow) {
X	startRRow = minrow;
X	startRCol = 0;
X    }
X    if (endRRow < minrow) {
X	endRRow = minrow;
X        endRCol = 0;
X    }
X    if (startSRow < minrow) {
X	startSRow = minrow;
X	startSCol = 0;
X    }
X    if (endSRow < minrow) {
X	endSRow = minrow;
X	endSCol = 0;
X    }
X    if (rawRow < minrow) {
X	rawRow = minrow;
X	rawCol = 0;
X    }
X    if (screen->startHRow < minrow) {
X	screen->startHRow = minrow;
X	screen->startHCol = 0;
X    }
X    if (screen->endHRow < minrow) {
X	screen->endHRow = minrow;
X	screen->endHCol = 0;
X    }
X    screen->startHCoord = Coordinate (screen->startHRow, screen->startHCol);
X    screen->endHCoord = Coordinate (screen->endHRow, screen->endHCol);
X}
X
X
X/*ARGSUSED*/
XResizeSelection (screen, rows, cols)
X    TScreen *screen;
X    int rows, cols;
X{
X    rows--;				/* decr to get 0-max */
X    cols--;
X
X    if (startRRow > rows) startRRow = rows;
X    if (startSRow > rows) startSRow = rows;
X    if (endRRow > rows) endRRow = rows;
X    if (endSRow > rows) endSRow = rows;
X    if (rawRow > rows) rawRow = rows;
X
X    if (startRCol > cols) startRCol = cols;
X    if (startSCol > cols) startSCol = cols;
X    if (endRCol > cols) endRCol = cols;
X    if (endSCol > cols) endSCol = cols;
X    if (rawCol > cols) rawCol = cols;
X}
X
Xstatic PointToRowCol(y, x, r, c)
Xregister int y, x;
Xint *r, *c;
X/* Convert pixel coordinates to character coordinates.
X   Rows are clipped between firstValidRow and lastValidRow.
X   Columns are clipped between to be 0 or greater, but are not clipped to some
X       maximum value. */
X{
X	register TScreen *screen = &term->screen;
X	register row, col;
X
X	row = (y - screen->border) / FontHeight(screen);
X	if(row < firstValidRow)
X		row = firstValidRow;
X	else if(row > lastValidRow)
X		row = lastValidRow;
X	col = (x - screen->border - screen->scrollbar) / FontWidth(screen);
X	if(col < 0)
X		col = 0;
X	else if(col > screen->max_col+1) {
X		col = screen->max_col+1;
X	}
X	*r = row;
X	*c = col;
X}
X
Xint LastTextCol(row)
Xregister int row;
X{
X	register TScreen *screen =  &term->screen;
X	register int i;
X	register Char *ch;
X
X	for(i = screen->max_col,
X	 ch = screen->buf[2 * (row + screen->topline)] + i ;
X	 i > 0 && (*ch == ' ' || *ch == 0); ch--, i--);
X	return(i);
X}	
X
Xstatic int charClass[128] = {
X/* NUL  SOH  STX  ETX  EOT  ENQ  ACK  BEL */
X    32,   1,   1,   1,   1,   1,   1,   1,
X/*  BS   HT   NL   VT   NP   CR   SO   SI */
X     1,  32,   1,   1,   1,   1,   1,   1,
X/* DLE  DC1  DC2  DC3  DC4  NAK  SYN  ETB */
X     1,   1,   1,   1,   1,   1,   1,   1,
X/* CAN   EM  SUB  ESC   FS   GS   RS   US */
X     1,   1,   1,   1,   1,   1,   1,   1,
X/*  SP    !    "    #    $    %    &    ' */
X    32,  33,  34,  35,  36,  37,  38,  39,
X/*   (    )    *    +    ,    -    .    / */
X    40,  41,  42,  43,  44,  45,  46,  47,
X/*   0    1    2    3    4    5    6    7 */
X    48,  48,  48,  48,  48,  48,  48,  48,
X/*   8    9    :    ;    <    =    >    ? */
X    48,  48,  58,  59,  60,  61,  62,  63,
X/*   @    A    B    C    D    E    F    G */
X    64,  48,  48,  48,  48,  48,  48,  48,
X/*   H    I    J    K    L    M    N    O */
X    48,  48,  48,  48,  48,  48,  48,  48,
X/*   P    Q    R    S    T    U    V    W */ 
X    48,  48,  48,  48,  48,  48,  48,  48,
X/*   X    Y    Z    [    \    ]    ^    _ */
X    48,  48,  48,  91,  92,  93,  94,  48,
X/*   `    a    b    c    d    e    f    g */
X    96,  48,  48,  48,  48,  48,  48,  48,
X/*   h    i    j    k    l    m    n    o */
X    48,  48,  48,  48,  48,  48,  48,  48,
X/*   p    q    r    s    t    u    v    w */
X    48,  48,  48,  48,  48,  48,  48,  48,
X/*   x    y    z    {    |    }    ~  DEL */
X    48,  48,  48, 123, 124, 125, 126,   1};
X
X
Xint SetCharacterClassRange (low, high, value)
X    register int low, high;		/* in range of [0..127] */
X    register int value;			/* arbitrary */
X{
X
X    if (low < 0 || high > 127 || high < low) return (-1);
X
X    for (; low <= high; low++) charClass[low] = value;
X
X    return (0);
X}
X
X
XComputeSelect(startRow, startCol, endRow, endCol, extend)
Xint startRow, startCol, endRow, endCol;
XBool extend;
X{
X	register TScreen *screen = &term->screen;
X	register Char *ptr;
X	register int length;
X	register int class;
X	int osc = startSCol;
X
X	if (Coordinate(startRow, startCol) <= Coordinate(endRow, endCol)) {
X		startSRow = startRRow = startRow;
X		startSCol = startRCol = startCol;
X		endSRow   = endRRow   = endRow;
X		endSCol   = endRCol   = endCol;
X	} else {	/* Swap them */
X		startSRow = startRRow = endRow;
X		startSCol = startRCol = endCol;
X		endSRow   = endRRow   = startRow;
X		endSCol   = endRCol   = startCol;
X	}	
X
X	switch (selectUnit) {
X		case SELECTCHAR :
X			if (startSCol > (LastTextCol(startSRow) + 1)) {
X				startSCol = 0;
X				startSRow++;
X			}
X			if (endSCol > (LastTextCol(endSRow) + 1)) {
X				endSCol = 0;
X				endSRow++;
X			}
X			break;
X		case SELECTWORD :
X			if (startSCol > (LastTextCol(startSRow) + 1)) {
X				startSCol = 0;
X				startSRow++;
X			} else {
X				ptr = screen->buf[2*(startSRow+screen->topline)]
X				 + startSCol;
X				class = charClass[*ptr];
X				do {
X					--startSCol;
X					--ptr;
X				} while (startSCol >= 0
X				 && charClass[*ptr] == class);
X				++startSCol;
X			}
X			if (endSCol > (LastTextCol(endSRow) + 1)) {
X				endSCol = 0;
X				endSRow++;
X			} else {
X				length = LastTextCol(endSRow);
X				ptr = screen->buf[2*(endSRow+screen->topline)]
X				 + endSCol;
X				class = charClass[*ptr];
X				do {
X					++endSCol;
X					++ptr;
X				} while (endSCol <= length
X				 && charClass[*ptr] == class);
X				/* Word select selects if pointing to any char
X				   in "word", especially in that it includes
X				   the last character in a word.  So no --endSCol
X				   and do special eol handling */
X				if (endSCol > length+1) {
X					endSCol = 0;
X					++endSRow;
X				}
X			}
X			break;
X		case SELECTLINE :
X			if (term->screen.cutToBeginningOfLine) {
X			    startSCol = 0;
X			} else if (!extend) {
X			    startSCol = osc;
X			}
X			if (term->screen.cutNewline) {
X			    endSCol = 0;
X			    ++endSRow;
X			} else {
X			    endSCol = LastTextCol(endSRow) + 1;
X			}
X			break;
X	}
X
X	TrackText(startSRow, startSCol, endSRow, endSCol);
X	return;
X}
X
X
XTrackText(frow, fcol, trow, tcol)
Xregister int frow, fcol, trow, tcol;
X/* Guaranteed (frow, fcol) <= (trow, tcol) */
X{
X	register int from, to;
X	register TScreen *screen = &term->screen;
X	int old_startrow, old_startcol, old_endrow, old_endcol;
X
X	/* (frow, fcol) may have been scrolled off top of display */
X	if (frow < 0)
X		frow = fcol = 0;
X	/* (trow, tcol) may have been scrolled off bottom of display */
X	if (trow > screen->max_row+1) {
X		trow = screen->max_row+1;
X		tcol = 0;
X	}
X	old_startrow = screen->startHRow;
X	old_startcol = screen->startHCol;
X	old_endrow = screen->endHRow;
X	old_endcol = screen->endHCol;
X	if (frow == old_startrow && fcol == old_startcol &&
X	    trow == old_endrow   && tcol == old_endcol) return;
X	screen->startHRow = frow;
X	screen->startHCol = fcol;
X	screen->endHRow   = trow;
X	screen->endHCol   = tcol;
X	from = Coordinate(frow, fcol);
X	to = Coordinate(trow, tcol);
X	if (to <= screen->startHCoord || from > screen->endHCoord) {
X	    /* No overlap whatsoever between old and new hilite */
X	    ReHiliteText(old_startrow, old_startcol, old_endrow, old_endcol);
X	    ReHiliteText(frow, fcol, trow, tcol);
X	} else {
X	    if (from < screen->startHCoord) {
X		    /* Extend left end */
X		    ReHiliteText(frow, fcol, old_startrow, old_startcol);
X	    } else if (from > screen->startHCoord) {
X		    /* Shorten left end */
X		    ReHiliteText(old_startrow, old_startcol, frow, fcol);
X	    }
X	    if (to > screen->endHCoord) {
X		    /* Extend right end */
X		    ReHiliteText(old_endrow, old_endcol, trow, tcol);
X	    } else if (to < screen->endHCoord) {
X		    /* Shorten right end */
X		    ReHiliteText(trow, tcol, old_endrow, old_endcol);
X	    }
X	}
X	screen->startHCoord = from;
X	screen->endHCoord = to;
X}
X
XReHiliteText(frow, fcol, trow, tcol)
Xregister int frow, fcol, trow, tcol;
X/* Guaranteed that (frow, fcol) <= (trow, tcol) */
X{
X	register TScreen *screen = &term->screen;
X	register int i;
X
X	if (frow < 0)
X	    frow = fcol = 0;
X	else if (frow > screen->max_row)
X	    return;		/* nothing to do, since trow >= frow */
X
X	if (trow < 0)
X	    return;		/* nothing to do, since frow <= trow */
X	else if (trow > screen->max_row) {
X	    trow = screen->max_row;
X	    tcol = screen->max_col+1;
X	}
X	if (frow == trow && fcol == tcol)
X		return;
X
X	if(frow != trow) {	/* do multiple rows */
X		if((i = screen->max_col - fcol + 1) > 0) {     /* first row */
X		    ScrnRefresh(screen, frow, fcol, 1, i, True);
X		}
X		if((i = trow - frow - 1) > 0) {		       /* middle rows*/
X		    ScrnRefresh(screen, frow+1, 0,i, screen->max_col+1, True);
X		}
X		if(tcol > 0 && trow <= screen->max_row) {      /* last row */
X		    ScrnRefresh(screen, trow, 0, 1, tcol, True);
X		}
X	} else {		/* do single row */
X		ScrnRefresh(screen, frow, fcol, 1, tcol - fcol, True);
X	}
X}
X
XSaltTextAway(crow, ccol, row, col, params, num_params)
X/*register*/ int crow, ccol, row, col;
XString *params;			/* selections */
XCardinal num_params;
X/* Guaranteed that (crow, ccol) <= (row, col), and that both points are valid
X   (may have row = screen->max_row+1, col = 0) */
X{
X	register TScreen *screen = &term->screen;
X	register int i, j = 0;
X	char *line, *lp;
X	static _OwnSelection();
X
X	if (crow == row && ccol > col) {
X	    int tmp = ccol;
X	    ccol = col;
X	    col = tmp;
X	}
X
X	--col;
X	/* first we need to know how long the string is before we can save it*/
X
X	if ( row == crow ) j = Length(screen, crow, ccol, col);
X	else {	/* two cases, cut is on same line, cut spans multiple lines */
X		j += Length(screen, crow, ccol, screen->max_col) + 1;
X		for(i = crow + 1; i < row; i++) 
X			j += Length(screen, i, 0, screen->max_col) + 1;
X		if (col >= 0)
X			j += Length(screen, row, 0, col);
X	}
X	
X	/* now get some memory to save it in */
X
X	if (screen->selection_size <= j) {
X	    if((line = malloc((unsigned) j + 1)) == (char *)NULL)
X		SysError(ERROR_BMALLOC2);
X	    XtFree(screen->selection);
X	    screen->selection = line;
X	    screen->selection_size = j + 1;
X	} else line = screen->selection;
X	if (!line || j < 0) return;
X
X	line[j] = '\0';		/* make sure it is null terminated */
X	lp = line;		/* lp points to where to save the text */
X	if ( row == crow ) lp = SaveText(screen, row, ccol, col, lp);
X	else {
X		lp = SaveText(screen, crow, ccol, screen->max_col, lp);
X		*lp ++ = '\n';	/* put in newline at end of line */
X		for(i = crow +1; i < row; i++) {
X			lp = SaveText(screen, i, 0, screen->max_col, lp);
X			*lp ++ = '\n';
X			}
X		if (col >= 0)
X			lp = SaveText(screen, row, 0, col, lp);
X	}
X	*lp = '\0';		/* make sure we have end marked */
X	
X	screen->selection_length = j;
X	_OwnSelection(term, params, num_params);
X}
X
Xstatic Boolean ConvertSelection(w, selection, target,
X				type, value, length, format)
XWidget w;
XAtom *selection, *target, *type;
Xcaddr_t *value;
Xunsigned long *length;
Xint *format;
X{
X    Display* d = XtDisplay(w);
X    XtermWidget xterm = (XtermWidget)w;
X
X    if (xterm->screen.selection == NULL) return False; /* can this happen? */
X
X    if (*target == XA_TARGETS(d)) {
X	Atom* targetP;
X	Atom* std_targets;
X	unsigned long std_length;
X	XmuConvertStandardSelection(
X		    w, xterm->screen.selection_time, selection,
X		    target, type, (caddr_t*)&std_targets, &std_length, format
X		   );
X	*length = std_length + 5;
X	*value = (caddr_t)XtMalloc(sizeof(Atom)*(*length));
X	targetP = *(Atom**)value;
X	*targetP++ = XA_STRING;
X	*targetP++ = XA_TEXT(d);
X	*targetP++ = XA_COMPOUND_TEXT(d);
X	*targetP++ = XA_LENGTH(d);
X	*targetP++ = XA_LIST_LENGTH(d);
X	bcopy((char*)std_targets, (char*)targetP, sizeof(Atom)*std_length);
X	XtFree((char*)std_targets);
X	*type = XA_ATOM;
X	*format = 32;
X	return True;
X    }
X
X    if (*target == XA_STRING ||
X	*target == XA_TEXT(d) ||
X	*target == XA_COMPOUND_TEXT(d)) {
X	if (*target == XA_COMPOUND_TEXT(d))
X	    *type = *target;
X	else
X	    *type = XA_STRING;
X	*value = xterm->screen.selection;
X	*length = xterm->screen.selection_length;
X	*format = 8;
X	return True;
X    }
X    if (*target == XA_LIST_LENGTH(d)) {
X	*value = XtMalloc(4);
X	if (sizeof(long) == 4)
X	    *(long*)*value = 1;
X	else {
X	    long temp = 1;
X	    bcopy( ((char*)&temp)+sizeof(long)-4, (char*)*value, 4);
X	}
X	*type = XA_INTEGER;
X	*length = 1;
X	*format = 32;
X	return True;
X    }
X    if (*target == XA_LENGTH(d)) {
X	*value = XtMalloc(4);
X	if (sizeof(long) == 4)
X	    *(long*)*value = xterm->screen.selection_length;
X	else {
X	    long temp = xterm->screen.selection_length;
X	    bcopy( ((char*)&temp)+sizeof(long)-4, (char*)*value, 4);
X	}
X	*type = XA_INTEGER;
X	*length = 1;
X	*format = 32;
X	return True;
X    }
X    if (XmuConvertStandardSelection(w, xterm->screen.selection_time, selection,
X				    target, type, value, length, format))
X	return True;
X
X    /* else */
X    return False;
X
X}
X
X
Xstatic void LoseSelection(w, selection)
X  Widget w;
X  Atom *selection;
X{
X    register TScreen* screen = &((XtermWidget)w)->screen;
X    register Atom* atomP;
X    int i;
X    for (i = 0, atomP = screen->selection_atoms;
X	 i < screen->selection_count; i++, atomP++)
X    {
X	if (*selection == *atomP) *atomP = (Atom)0;
X	switch (*atomP) {
X	  case XA_CUT_BUFFER0:
X	  case XA_CUT_BUFFER1:
X	  case XA_CUT_BUFFER2:
X	  case XA_CUT_BUFFER3:
X	  case XA_CUT_BUFFER4:
X	  case XA_CUT_BUFFER5:
X	  case XA_CUT_BUFFER6:
X	  case XA_CUT_BUFFER7:	*atomP = (Atom)0;
X	}
X    }
X
X    for (i = screen->selection_count; i; i--) {
X	if (screen->selection_atoms[i-1] != 0) break;
X    }
X    screen->selection_count = i;
X
X    for (i = 0, atomP = screen->selection_atoms;
X	 i < screen->selection_count; i++, atomP++)
X    {
X	if (*atomP == (Atom)0) {
X	    *atomP = screen->selection_atoms[--screen->selection_count];
X	}
X    }
X
X    if (screen->selection_count == 0)
X	TrackText(0, 0, 0, 0);
X}
X
X
X/* ARGSUSED */
Xstatic void SelectionDone(w, selection, target)
XWidget w;
XAtom *selection, *target;
X{
X    /* empty proc so Intrinsics know we want to keep storage */
X}
X
X
Xstatic /* void */ _OwnSelection(term, selections, count)
Xregister XtermWidget term;
XString *selections;
XCardinal count;
X{
X    Atom* atoms = term->screen.selection_atoms;
X    int i;
X    Boolean have_selection = False;
X
X    if (term->screen.selection_length < 0) return;
X
X    if (count > term->screen.sel_atoms_size) {
X	XtFree((char*)atoms);
X	atoms = (Atom*)XtMalloc(count*sizeof(Atom));
X	term->screen.selection_atoms = atoms;
X	term->screen.sel_atoms_size = count;
X    }
X    XmuInternStrings( XtDisplay((Widget)term), selections, count, atoms );
X    for (i = 0; i < count; i++) {
X	int buffer;
X	switch (atoms[i]) {
X	  case XA_CUT_BUFFER0: buffer = 0; break;
X	  case XA_CUT_BUFFER1: buffer = 1; break;
X	  case XA_CUT_BUFFER2: buffer = 2; break;
X	  case XA_CUT_BUFFER3: buffer = 3; break;
X	  case XA_CUT_BUFFER4: buffer = 4; break;
X	  case XA_CUT_BUFFER5: buffer = 5; break;
X	  case XA_CUT_BUFFER6: buffer = 6; break;
X	  case XA_CUT_BUFFER7: buffer = 7; break;
X	  default:	       buffer = -1;
X	}
X	if (buffer >= 0)
X	    XStoreBuffer( XtDisplay((Widget)term), term->screen.selection,
X			  term->screen.selection_length, buffer );
X	else if (!replyToEmacs) {
X	    have_selection |=
X		XtOwnSelection( (Widget)term, atoms[i],
X			    term->screen.selection_time,
X			    ConvertSelection, LoseSelection, SelectionDone );
X	}
X    }
X    if (!replyToEmacs)
X	term->screen.selection_count = count;
X    if (!have_selection)
X	TrackText(0, 0, 0, 0);
X}
X
X/* void */ DisownSelection(term)
Xregister XtermWidget term;
X{
X    Atom* atoms = term->screen.selection_atoms;
X    Cardinal count = term->screen.selection_count;
X    int i;
X
X    for (i = 0; i < count; i++) {
X	int buffer;
X	switch (atoms[i]) {
X	  case XA_CUT_BUFFER0: buffer = 0; break;
X	  case XA_CUT_BUFFER1: buffer = 1; break;
X	  case XA_CUT_BUFFER2: buffer = 2; break;
X	  case XA_CUT_BUFFER3: buffer = 3; break;
X	  case XA_CUT_BUFFER4: buffer = 4; break;
X	  case XA_CUT_BUFFER5: buffer = 5; break;
X	  case XA_CUT_BUFFER6: buffer = 6; break;
X	  case XA_CUT_BUFFER7: buffer = 7; break;
X	  default:	       buffer = -1;
X	}
X	if (buffer < 0)
X	    XtDisownSelection( (Widget)term, atoms[i],
X			       term->screen.selection_time );
X    }
X    term->screen.selection_count = 0;
X    term->screen.startHRow = term->screen.startHCol = 0;
X    term->screen.endHRow = term->screen.endHCol = 0;
X}
X
X
X/* returns number of chars in line from scol to ecol out */
Xint Length(screen, row, scol, ecol)
Xregister int row, scol, ecol;
Xregister TScreen *screen;
X{
X	register Char *ch;
X
X	ch = screen->buf[2 * (row + screen->topline)];
X	while (ecol >= scol && (ch[ecol] == ' ' || ch[ecol] == 0))
X	    ecol--;
X	return (ecol - scol + 1);
X}
X
X/* copies text into line, preallocated */
Xchar *SaveText(screen, row, scol, ecol, lp)
Xint row;
Xint scol, ecol;
XTScreen *screen;
Xregister char *lp;		/* pointer to where to put the text */
X{
X	register int i = 0;
X	register Char *ch = screen->buf[2 * (row + screen->topline)];
X	register int c;
X
X	if ((i = Length(screen, row, scol, ecol)) == 0) return(lp);
X	ecol = scol + i;
X	for (i = scol; i < ecol; i++) {
X		if ((c = ch[i]) == 0)
X			c = ' ';
X		else if(c < ' ') {
X			if(c == '\036')
X				c = '#';
X			else
X				c += 0x5f;
X		} else if(c == 0x7f)
X			c = 0x5f;
X		*lp++ = c;
X	}
X	return(lp);
X}
X
XEditorButton(event)
Xregister XButtonEvent *event;
X{
X	register TScreen *screen = &term->screen;
X	int pty = screen->respond;
X	char line[6];
X	register unsigned row, col;
X	int button; 
X
X	button = event->button - 1; 
X
X	row = (event->y - screen->border) 
X	 / FontHeight(screen);
X	col = (event->x - screen->border - screen->scrollbar)
X	 / FontWidth(screen);
X	(void) strcpy(line, "\033[M");
X	if (screen->send_mouse_pos == 1) {
X		line[3] = ' ' + button;
X	} else {
X		line[3] = ' ' + (KeyState(event->state) << 2) + 
X			((event->type == ButtonPress)? button:3);
X	}
X	line[4] = ' ' + col + 1;
X	line[5] = ' ' + row + 1;
X	v_write(pty, line, 6);
X}
X
X
X/*ARGSUSED*/
Xvoid HandleGINInput (w, event, param_list, nparamsp)
X    Widget w;
X    XEvent *event;
X    String *param_list;
X    Cardinal *nparamsp;
X{
X    if (term->screen.TekGIN && *nparamsp == 1) {
X	int c = param_list[0][0];
X	switch (c) {
X	  case 'l': case 'm': case 'r':
X	  case 'L': case 'M': case 'R':
X	    break;
X	  default:
X	    Bell ();			/* let them know they goofed */
X	    c = 'l';			/* provide a default */
X	}
X	TekEnqMouse (c | 0x80);
X	TekGINoff();
X    } else {
X	Bell ();
X    }
X}
X
X
X/* ARGSUSED */
Xvoid HandleSecure(w, event, params, param_count)
X    Widget w;
X    XEvent *event;		/* unused */
X    String *params;		/* [0] = volume */
X    Cardinal *param_count;	/* 0 or 1 */
X{
X    Time time = CurrentTime;
X
X    if ((event->xany.type == KeyPress) ||
X	(event->xany.type == KeyRelease))
X	time = event->xkey.time;
X    else if ((event->xany.type == ButtonPress) ||
X	     (event->xany.type == ButtonRelease))
X      time = event->xbutton.time;
X    DoSecureKeyboard (time);
X}
SHAR_EOF
chmod 0644 button.c || echo "restore of button.c fails"
if [ $TOUCH = can ]
then
    touch -am 1109132690 button.c
fi
fi
# ============= charproc.c ==============
if test -f charproc.c; then echo "File charproc.c exists"; else
sed 's/^X//' << 'SHAR_EOF' > charproc.c &&
X/*
X * $XConsortium: charproc.c,v 1.123 90/03/12 10:30:21 jim Exp $
X */
X
X
X#include <X11/copyright.h>
X#include <X11/Xlib.h>
X#include <X11/Xatom.h>
X#include <X11/Xmu/Atoms.h>
X
X/*
X * Copyright 1988 Massachusetts Institute of Technology
X * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
X *
X *                         All Rights Reserved
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Digital Equipment
X * Corporation not be used in advertising or publicity pertaining to
X * distribution of the software without specific, written prior permission.
X *
X *
X * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
X * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
X * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
X * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
X * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
X * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
X * SOFTWARE.
X */
X
X
X/* charproc.c */
X
X#ifdef att
X#ifndef STREAMSCONN
X#define STREAMSCONN
X#endif
X#endif
X
X#include <stdio.h>
X#include <X11/Xos.h>
X#ifndef CRAY
X#include <sgtty.h>
X#endif
X#include <ctype.h>
X#include <errno.h>
X#include <setjmp.h>
X#if defined(macII) || defined(CRAY)
X#undef FIOCLEX					/* redefined from sgtty.h */
X#undef FIONCLEX					/* redefined from sgtty.h */
X#endif
X#include "ptyx.h"
X#include "VTparse.h"
X#include "data.h"
X#include <X11/Xutil.h>
X#include "error.h"
X#include "main.h"
X#include <X11/cursorfont.h>
X#include <X11/StringDefs.h>
X#include "menu.h"
X
X#if !defined(EWOULDBLOCK) && defined(EAGAIN)
X#define EWOULDBLOCK EAGAIN
X#endif
X
Xextern Widget toplevel;
Xextern void exit(), bcopy();
Xstatic void VTallocbuf();
X
X#define	DEFAULT		-1
X#define	TEXT_BUF_SIZE	256
X#define TRACKTIMESEC	4L
X#define TRACKTIMEUSEC	0L
X
X#define XtNalwaysHighlight	"alwaysHighlight"
X#define	XtNboldFont		"boldFont"
X#define	XtNc132			"c132"
X#define XtNcharClass		"charClass"
X#define	XtNcurses		"curses"
X#define	XtNcursorColor		"cursorColor"
X#define XtNcutNewline		"cutNewline"
X#define XtNcutToBeginningOfLine	"cutToBeginningOfLine"
X#define XtNeightBitInput	"eightBitInput"
X#define XtNgeometry		"geometry"
X#define XtNtekGeometry		"tekGeometry"
X#define	XtNinternalBorder	"internalBorder"
X#define	XtNjumpScroll		"jumpScroll"
X#define	XtNlogFile		"logFile"
X#define	XtNlogging		"logging"
X#define	XtNlogInhibit		"logInhibit"
X#define	XtNloginShell		"loginShell"
X#define	XtNmarginBell		"marginBell"
X#define	XtNpointerColor		"pointerColor"
X#define XtNpointerColorBackground "pointerColorBackground"
X#define	XtNpointerShape		"pointerShape"
X#define XtNmultiClickTime	"multiClickTime"
X#define	XtNmultiScroll		"multiScroll"
X#define	XtNnMarginBell		"nMarginBell"
X#define	XtNreverseWrap		"reverseWrap"
X#define	XtNsaveLines		"saveLines"
X#define	XtNscrollBar		"scrollBar"
X#define XtNscrollTtyOutput	"scrollTtyOutput"
X#define	XtNscrollKey		"scrollKey"
X#define XtNscrollLines		"scrollLines"
X#define XtNscrollPos    	"scrollPos"
X#define	XtNsignalInhibit	"signalInhibit"
X#define	XtNtekInhibit		"tekInhibit"
X#define XtNtekSmall		"tekSmall"
X#define	XtNtekStartup		"tekStartup"
X#define XtNtiteInhibit		"titeInhibit"
X#define	XtNvisualBell		"visualBell"
X#define XtNallowSendEvents	"allowSendEvents"
X
X#define XtCAlwaysHighlight	"AlwaysHighlight"
X#define	XtCC132			"C132"
X#define XtCCharClass		"CharClass"
X#define	XtCCurses		"Curses"
X#define XtCCutNewline		"CutNewline"
X#define XtCCutToBeginningOfLine	"CutToBeginningOfLine"
X#define XtCEightBitInput	"EightBitInput"
X#define XtCGeometry		"Geometry"
X#define	XtCJumpScroll		"JumpScroll"
X#define	XtCLogfile		"Logfile"
X#define	XtCLogging		"Logging"
X#define	XtCLogInhibit		"LogInhibit"
X#define	XtCLoginShell		"LoginShell"
X#define	XtCMarginBell		"MarginBell"
X#define XtCMultiClickTime	"MultiClickTime"
X#define	XtCMultiScroll		"MultiScroll"
X#define	XtCColumn		"Column"
X#define	XtCReverseWrap		"ReverseWrap"
X#define XtCSaveLines		"SaveLines"
X#define	XtCScrollBar		"ScrollBar"
X#define XtCScrollLines		"ScrollLines"
X#define XtCScrollPos     	"ScrollPos"
X#define	XtCScrollCond		"ScrollCond"
X#define	XtCSignalInhibit	"SignalInhibit"
X#define	XtCTekInhibit		"TekInhibit"
X#define XtCTekSmall		"TekSmall"
X#define	XtCTekStartup		"TekStartup"
X#define XtCTiteInhibit		"TiteInhibit"
X#define	XtCVisualBell		"VisualBell"
X#define XtCAllowSendEvents	"AllowSendEvents"
X
X#define	doinput()		(bcnt-- > 0 ? *bptr++ : in_put())
X
X#ifndef lint
Xstatic char rcs_id[] = "$XConsortium: charproc.c,v 1.123 90/03/12 10:30:21 jim Exp $";
X#endif	/* lint */
X
Xstatic int nparam;
Xstatic ANSI reply;
Xstatic int param[NPARAM];
X
Xstatic unsigned long ctotal;
Xstatic unsigned long ntotal;
Xstatic jmp_buf vtjmpbuf;
X
Xextern int groundtable[];
Xextern int csitable[];
Xextern int dectable[];
Xextern int eigtable[];
Xextern int esctable[];
Xextern int iestable[];
Xextern int igntable[];
Xextern int scrtable[];
Xextern int scstable[];
X
X
X/* event handlers */
Xextern void HandleKeyPressed(), HandleEightBitKeyPressed();
Xextern void HandleStringEvent();
Xextern void HandleEnterWindow();
Xextern void HandleLeaveWindow();
Xextern void HandleFocusChange();
Xstatic void HandleKeymapChange();
Xextern void HandleInsertSelection();
Xextern void HandleSelectStart(), HandleKeyboardSelectStart();
Xextern void HandleSelectExtend(), HandleSelectSet();
Xextern void HandleSelectEnd(), HandleKeyboardSelectEnd();
Xextern void HandleStartExtend(), HandleKeyboardStartExtend();
Xstatic void HandleBell();
Xstatic void HandleIgnore();
Xextern void HandleSecure();
Xextern void HandleScrollForward();
Xextern void HandleScrollBack();
Xextern void HandleCreateMenu(), HandlePopupMenu();
Xextern void HandleSetFont();
Xextern void SetVTFont();
X
X/*
X * NOTE: VTInitialize zeros out the entire ".screen" component of the 
X * XtermWidget, so make sure to add an assignment statement in VTInitialize() 
X * for each new ".screen" field added to this resource list.
X */
X
X/* Defaults */
Xstatic  Boolean	defaultFALSE	   = FALSE;
Xstatic  Boolean	defaultTRUE	   = TRUE;
Xstatic  int	defaultBorderWidth = DEFBORDERWIDTH;
Xstatic  int	defaultIntBorder   = DEFBORDER;
Xstatic  int	defaultSaveLines   = SAVELINES;
Xstatic	int	defaultScrollLines = SCROLLLINES;
Xstatic  int	defaultNMarginBell = N_MARGINBELL;
Xstatic  int	defaultMultiClickTime = MULTICLICKTIME;
Xstatic	char *	_Font_Selected_ = "yes";  /* string is arbitrary */
X
X/*
X * Warning, the following must be kept under 1024 bytes or else some 
X * compilers (particularly AT&T 6386 SVR3.2) will barf).  Workaround is to
X * declare a static buffer and copy in at run time (the the Athena text widget
X * does).  Yuck.
X */
Xstatic char defaultTranslations[] =
X"\
X  Shift <KeyPress> Prior:	scroll-back(1,halfpage) \n\
X  Shift <KeyPress> Next:	scroll-forw(1,halfpage) \n\
X  Shift <KeyPress> Select:	select-cursor-start() select-cursor-end(PRIMARY, CUT_BUFFER0) \n\
X  Shift <KeyPress> Insert:	insert-selection(PRIMARY, CUT_BUFFER0) \n\
X       ~Meta<KeyPress>: 	insert-seven-bit()	\n\
X        Meta<KeyPress>: 	insert-eight-bit()	\n\
X Ctrl ~Meta<Btn1Down>:          popup-menu(mainMenu) \n\
X      ~Meta <Btn1Down>:		select-start()	\n\
X      ~Meta <Btn1Motion>:	select-extend() \n\
X Ctrl ~Meta <Btn2Down>:         popup-menu(vtMenu) \n\
X~Ctrl ~Meta <Btn2Down>:		ignore()	\n\
X~Ctrl ~Meta <Btn2Up>:		insert-selection(PRIMARY, CUT_BUFFER0) \n\
X Ctrl ~Meta <Btn3Down>:         popup-menu(fontMenu) \n\
X~Ctrl ~Meta <Btn3Down>:		start-extend()	\n\
X      ~Meta <Btn3Motion>:	select-extend()	\n\
X~Ctrl ~Meta <BtnUp>:		select-end(PRIMARY, CUT_BUFFER0) \n\
X	    <BtnDown>:		bell(0)		\
X";
X
Xstatic XtActionsRec actionsList[] = { 
X    { "bell",		  HandleBell },
X    { "create-menu",	  HandleCreateMenu },
X    { "ignore",		  HandleIgnore },
X    { "insert",		  HandleKeyPressed },  /* alias for insert-seven-bit */
X    { "insert-seven-bit", HandleKeyPressed },
X    { "insert-eight-bit", HandleEightBitKeyPressed },
X    { "insert-selection", HandleInsertSelection },
X    { "keymap", 	  HandleKeymapChange },
X    { "popup-menu",	  HandlePopupMenu },
X    { "secure",		  HandleSecure },
X    { "select-start",	  HandleSelectStart },
X    { "select-extend",	  HandleSelectExtend },
X    { "select-end",	  HandleSelectEnd },
X    { "select-set",	  HandleSelectSet },
X    { "select-cursor-start",	  HandleKeyboardSelectStart },
X    { "select-cursor-end",	  HandleKeyboardSelectEnd },
X    { "set-vt-font",	  HandleSetFont },
X    { "start-extend",	  HandleStartExtend },
X    { "start-cursor-extend",	  HandleKeyboardStartExtend },
X    { "string",		  HandleStringEvent },
X    { "scroll-forw",	  HandleScrollForward },
X    { "scroll-back",	  HandleScrollBack },
X    /* menu actions */
X    { "allow-send-events",	HandleAllowSends },
X    { "set-visual-bell",	HandleVisualBell },
X    { "set-logging",		HandleLogging },
X    { "redraw",			HandleRedraw },
X    { "send-signal",		HandleSendSignal },
X    { "quit",			HandleQuit },
X    { "set-scrollbar",		HandleScrollbar },
X    { "set-jumpscroll",		HandleJumpscroll },
X    { "set-reverse-video",	HandleReverseVideo },
X    { "set-autowrap",		HandleAutoWrap },
X    { "set-reversewrap",	HandleReverseWrap },
X    { "set-autolinefeed",	HandleAutoLineFeed },
X    { "set-appcursor",		HandleAppCursor },
X    { "set-appkeypad",		HandleAppKeypad },
X    { "set-scroll-on-key",	HandleScrollKey },
X    { "set-scroll-on-tty-output",	HandleScrollTtyOutput },
X    { "set-allow132",		HandleAllow132 },
X    { "set-cursesemul",		HandleCursesEmul },
X    { "set-marginbell",		HandleMarginBell },
X    { "set-altscreen",		HandleAltScreen },
X    { "soft-reset",		HandleSoftReset },
X    { "hard-reset",		HandleHardReset },
X    { "set-terminal-type",	HandleSetTerminalType },
X    { "set-visibility",		HandleVisibility },
X    { "set-tek-text",		HandleSetTekText },
X    { "tek-page",		HandleTekPage },
X    { "tek-reset",		HandleTekReset },
X    { "tek-copy",		HandleTekCopy },
X};
X
Xstatic XtResource resources[] = {
X{XtNfont, XtCFont, XtRString, sizeof(char *),
X	XtOffset(XtermWidget, misc.f_n), XtRString,
X	DEFFONT},
X{XtNboldFont, XtCFont, XtRString, sizeof(char *),
X	XtOffset(XtermWidget, misc.f_b), XtRString,
X	DEFBOLDFONT},
X{XtNc132, XtCC132, XtRBoolean, sizeof(Boolean),
X	XtOffset(XtermWidget, screen.c132),
X	XtRBoolean, (caddr_t) &defaultFALSE},
X{XtNcharClass, XtCCharClass, XtRString, sizeof(char *),
X	XtOffset(XtermWidget, screen.charClass),
X	XtRString, (caddr_t) NULL},
X{XtNcurses, XtCCurses, XtRBoolean, sizeof(Boolean),
X	XtOffset(XtermWidget, screen.curses),
X	XtRBoolean, (caddr_t) &defaultFALSE},
X{XtNcutNewline, XtCCutNewline, XtRBoolean, sizeof(Boolean),
X	XtOffset(XtermWidget, screen.cutNewline),
X	XtRBoolean, (caddr_t) &defaultTRUE},
X{XtNcutToBeginningOfLine, XtCCutToBeginningOfLine, XtRBoolean, sizeof(Boolean),
X	XtOffset(XtermWidget, screen.cutToBeginningOfLine),
X	XtRBoolean, (caddr_t) &defaultTRUE},
X{XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
X	XtOffset(XtermWidget, core.background_pixel),
X	XtRString, "XtDefaultBackground"},
X{XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
X	XtOffset(XtermWidget, screen.foreground),
X	XtRString, "XtDefaultForeground"},
X{XtNcursorColor, XtCForeground, XtRPixel, sizeof(Pixel),
X	XtOffset(XtermWidget, screen.cursorcolor),
X	XtRString, "XtDefaultForeground"},
X{XtNeightBitInput, XtCEightBitInput, XtRBoolean, sizeof(Boolean),
X	XtOffset(XtermWidget, screen.eight_bits), 
X	XtRBoolean, (caddr_t) &defaultTRUE},
X{XtNgeometry,XtCGeometry, XtRString, sizeof(char *),
X	XtOffset(XtermWidget, misc.geo_metry),
X	XtRString, (caddr_t) NULL},
X{XtNalwaysHighlight,XtCAlwaysHighlight,XtRBoolean,
X        sizeof(Boolean),XtOffset(XtermWidget, screen.always_highlight),
X        XtRBoolean, (caddr_t) &defaultFALSE},
X{XtNtekGeometry,XtCGeometry, XtRString, sizeof(char *),
X	XtOffset(XtermWidget, misc.T_geometry),
X	XtRString, (caddr_t) NULL},
X{XtNinternalBorder,XtCBorderWidth,XtRInt, sizeof(int),
X	XtOffset(XtermWidget, screen.border),
X	XtRInt, (caddr_t) &defaultIntBorder},
X{XtNjumpScroll, XtCJumpScroll, XtRBoolean, sizeof(Boolean),
X	XtOffset(XtermWidget, screen.jumpscroll),
X	XtRBoolean, (caddr_t) &defaultTRUE},
X{XtNlogFile, XtCLogfile, XtRString, sizeof(char *),
X	XtOffset(XtermWidget, screen.logfile),
X	XtRString, (caddr_t) NULL},
X{XtNlogging, XtCLogging, XtRBoolean, sizeof(Boolean),
X	XtOffset(XtermWidget, misc.log_on),
X	XtRBoolean, (caddr_t) &defaultFALSE},
X{XtNlogInhibit, XtCLogInhibit, XtRBoolean, sizeof(Boolean),
X	XtOffset(XtermWidget, misc.logInhibit),
X	XtRBoolean, (caddr_t) &defaultFALSE},
X{XtNloginShell, XtCLoginShell, XtRBoolean, sizeof(Boolean),
X	XtOffset(XtermWidget, misc.login_shell),
X	XtRBoolean, (caddr_t) &defaultFALSE},
X{XtNmarginBell, XtCMarginBell, XtRBoolean, sizeof(Boolean),
X	XtOffset(XtermWidget, screen.marginbell),
X	XtRBoolean, (caddr_t) &defaultFALSE},
X{XtNpointerColor, XtCForeground, XtRPixel, sizeof(Pixel),
X	XtOffset(XtermWidget, screen.mousecolor),
X	XtRString, "XtDefaultForeground"},
X{XtNpointerColorBackground, XtCBackground, XtRPixel, sizeof(Pixel),
X	XtOffset(XtermWidget, screen.mousecolorback),
X	XtRString, "XtDefaultBackground"},
X{XtNpointerShape,XtCCursor, XtRCursor, sizeof(Cursor),
X	XtOffset(XtermWidget, screen.pointer_cursor),
X	XtRString, (caddr_t) "xterm"},
X{XtNmultiClickTime,XtCMultiClickTime, XtRInt, sizeof(int),
X	XtOffset(XtermWidget, screen.multiClickTime),
X	XtRInt, (caddr_t) &defaultMultiClickTime},
X{XtNmultiScroll,XtCMultiScroll, XtRBoolean, sizeof(Boolean),
X	XtOffset(XtermWidget, screen.multiscroll),
X	XtRBoolean, (caddr_t) &defaultFALSE},
X{XtNnMarginBell,XtCColumn, XtRInt, sizeof(int),
X	XtOffset(XtermWidget, screen.nmarginbell),
X	XtRInt, (caddr_t) &defaultNMarginBell},
X{XtNreverseVideo,XtCReverseVideo,XtRBoolean, sizeof(Boolean),
X	XtOffset(XtermWidget, misc.re_verse),
X	XtRBoolean, (caddr_t) &defaultFALSE},
X{XtNreverseWrap,XtCReverseWrap, XtRBoolean, sizeof(Boolean),
X	XtOffset(XtermWidget, misc.reverseWrap),
X	XtRBoolean, (caddr_t) &defaultFALSE},
X{XtNsaveLines, XtCSaveLines, XtRInt, sizeof(int),
X	XtOffset(XtermWidget, screen.savelines),
X	XtRInt, (caddr_t) &defaultSaveLines},
X{XtNscrollBar, XtCScrollBar, XtRBoolean, sizeof(Boolean),
X	XtOffset(XtermWidget, misc.scrollbar),
X	XtRBoolean, (caddr_t) &defaultFALSE},
X{XtNscrollTtyOutput,XtCScrollCond, XtRBoolean, sizeof(Boolean),
X	XtOffset(XtermWidget, screen.scrollttyoutput),
X	XtRBoolean, (caddr_t) &defaultTRUE},
X{XtNscrollKey, XtCScrollCond, XtRBoolean, sizeof(Boolean),
X	XtOffset(XtermWidget, screen.scrollkey),
X	XtRBoolean, (caddr_t) &defaultFALSE},
X{XtNscrollLines, XtCScrollLines, XtRInt, sizeof(int),
X	XtOffset(XtermWidget, screen.scrolllines),
X	XtRInt, (caddr_t) &defaultScrollLines},
X{XtNsignalInhibit,XtCSignalInhibit,XtRBoolean, sizeof(Boolean),
X	XtOffset(XtermWidget, misc.signalInhibit),
X	XtRBoolean, (caddr_t) &defaultFALSE},
X{XtNtekInhibit, XtCTekInhibit, XtRBoolean, sizeof(Boolean),
X	XtOffset(XtermWidget, misc.tekInhibit),
X	XtRBoolean, (caddr_t) &defaultFALSE},
X{XtNtekSmall, XtCTekSmall, XtRBoolean, sizeof(Boolean),
X	XtOffset(XtermWidget, misc.tekSmall),
X	XtRBoolean, (caddr_t) &defaultFALSE},
X{XtNtekStartup, XtCTekStartup, XtRBoolean, sizeof(Boolean),
X	XtOffset(XtermWidget, screen.TekEmu),
X	XtRBoolean, (caddr_t) &defaultFALSE},
X{XtNtiteInhibit, XtCTiteInhibit, XtRBoolean, sizeof(Boolean),
X	XtOffset(XtermWidget, misc.titeInhibit),
X	XtRBoolean, (caddr_t) &defaultFALSE},
X{XtNvisualBell, XtCVisualBell, XtRBoolean, sizeof(Boolean),
X	XtOffset(XtermWidget, screen.visualbell),
X	XtRBoolean, (caddr_t) &defaultFALSE},
X{XtNallowSendEvents, XtCAllowSendEvents, XtRBoolean, sizeof(Boolean),
X	XtOffset(XtermWidget, screen.allowSendEvents),
X	XtRBoolean, (caddr_t) &defaultFALSE},
X{"font1", "Font1", XtRString, sizeof(String),
X	XtOffset(XtermWidget, screen.menu_font_names[fontMenu_font1]),
X	XtRString, (caddr_t) NULL},
X{"font2", "Font2", XtRString, sizeof(String),
X	XtOffset(XtermWidget, screen.menu_font_names[fontMenu_font2]),
X	XtRString, (caddr_t) NULL},
X{"font3", "Font3", XtRString, sizeof(String),
X	XtOffset(XtermWidget, screen.menu_font_names[fontMenu_font3]),
X	XtRString, (caddr_t) NULL},
X{"font4", "Font4", XtRString, sizeof(String),
X	XtOffset(XtermWidget, screen.menu_font_names[fontMenu_font4]),
X	XtRString, (caddr_t) NULL},
X};
X
X
Xstatic void VTInitialize(), VTRealize(), VTExpose(), VTResize();
Xstatic void VTDestroy();
X
XWidgetClassRec xtermClassRec = {
X  {
X/* core_class fields */	
X    /* superclass	  */	(WidgetClass) &widgetClassRec,
X    /* class_name	  */	"VT100",
X    /* widget_size	  */	sizeof(XtermWidgetRec),
X    /* class_initialize   */    NULL,
X    /* class_part_initialize */ NULL,
X    /* class_inited       */	FALSE,
X    /* initialize	  */	VTInitialize,
X    /* initialize_hook    */    NULL,				
X    /* realize		  */	VTRealize,
X    /* actions		  */	actionsList,
X    /* num_actions	  */	XtNumber(actionsList),
X    /* resources	  */	resources,
X    /* num_resources	  */	XtNumber(resources),
X    /* xrm_class	  */	NULLQUARK,
X    /* compress_motion	  */	TRUE,
X    /* compress_exposure  */	FALSE,
X    /* compress_enterleave */   TRUE,
X    /* visible_interest	  */	FALSE,
X    /* destroy		  */	VTDestroy,
X    /* resize		  */	VTResize,
X    /* expose		  */	VTExpose,
X    /* set_values	  */	NULL,
X    /* set_values_hook    */    NULL,
X    /* set_values_almost  */    NULL,
X    /* get_values_hook    */    NULL,
X    /* accept_focus	  */	NULL,
X    /* version            */    XtVersion,
X    /* callback_offsets   */    NULL,
X    /* tm_table           */    defaultTranslations,
X    /* query_geometry     */    XtInheritQueryGeometry,
X    /* display_accelerator*/    XtInheritDisplayAccelerator,
X    /* extension          */    NULL
X  }
X};
X
XWidgetClass xtermWidgetClass = (WidgetClass)&xtermClassRec;
X
XVTparse()
X{
X	register TScreen *screen = &term->screen;
X	register int *parsestate = groundtable;
X	register unsigned int c;
X	register unsigned char *cp;
X	register int row, col, top, bot, scstype;
X	extern int bitset(), bitclr(), finput(), TrackMouse();
X
X	if(setjmp(vtjmpbuf))
X		parsestate = groundtable;
X	for( ; ; ) {
X	        switch (parsestate[c = doinput()]) {
X		 case CASE_PRINT:
X			/* printable characters */
X			top = bcnt > TEXT_BUF_SIZE ? TEXT_BUF_SIZE : bcnt;
X			cp = bptr;
X			*--bptr = c;
X			while(top > 0 && isprint(*cp & 0x7f)) {
X				top--;
X				bcnt--;
X				cp++;
X			}
X			if(screen->curss) {
X				dotext(screen, term->flags,
X				 screen->gsets[screen->curss], bptr, bptr + 1);
X				screen->curss = 0;
X				bptr++;
X			}
X			if(bptr < cp)
X				dotext(screen, term->flags,
X				 screen->gsets[screen->curgl], bptr, cp);
X			bptr = cp;
X			break;
X
X		 case CASE_GROUND_STATE:
X			/* exit ignore mode */
X			parsestate = groundtable;
X			break;
X
X		 case CASE_IGNORE_STATE:
X			/* Ies: ignore anything else */
X			parsestate = igntable;
X			break;
X
X		 case CASE_IGNORE_ESC:
X			/* Ign: escape */
X			parsestate = iestable;
X			break;
X
X		 case CASE_IGNORE:
X			/* Ignore character */
X			break;
X
X		 case CASE_BELL:
X			/* bell */
X			Bell();
X			break;
X
X		 case CASE_BS:
X			/* backspace */
X			CursorBack(screen, 1);
X			break;
X
X		 case CASE_CR:
X			/* carriage return */
X			CarriageReturn(screen);
X			break;
X
X		 case CASE_ESC:
X			/* escape */
X			parsestate = esctable;
X			break;
X
X		 case CASE_VMOT:
X			/*
X			 * form feed, line feed, vertical tab
X			 */
X			Index(screen, 1);
X			if (term->flags & LINEFEED)
X				CarriageReturn(screen);
X			if (screen->display->qlen > 0 ||
X			    GetBytesAvailable (screen->display->fd) > 0)
X			  xevents();
X			break;
X
X		 case CASE_TAB:
X			/* tab */
X			screen->cur_col = TabNext(term->tabs, screen->cur_col);
X			if (screen->cur_col > screen->max_col)
X				screen->cur_col = screen->max_col;
X			break;
X
X		 case CASE_SI:
X			screen->curgl = 0;
X			break;
X
X		 case CASE_SO:
X			screen->curgl = 1;
X			break;
X
X		 case CASE_SCR_STATE:
X			/* enter scr state */
X			parsestate = scrtable;
X			break;
X
X		 case CASE_SCS0_STATE:
X			/* enter scs state 0 */
X			scstype = 0;
X			parsestate = scstable;
X			break;
X
X		 case CASE_SCS1_STATE:
X			/* enter scs state 1 */
X			scstype = 1;
X			parsestate = scstable;
X			break;
X
X		 case CASE_SCS2_STATE:
X			/* enter scs state 2 */
X			scstype = 2;
X			parsestate = scstable;
X			break;
X
X		 case CASE_SCS3_STATE:
X			/* enter scs state 3 */
X			scstype = 3;
X			parsestate = scstable;
X			break;
X
X		 case CASE_ESC_IGNORE:
X			/* unknown escape sequence */
X			parsestate = eigtable;
X			break;
X
X		 case CASE_ESC_DIGIT:
X			/* digit in csi or dec mode */
X			if((row = param[nparam - 1]) == DEFAULT)
X				row = 0;
X			param[nparam - 1] = 10 * row + (c - '0');
X			break;
X
X		 case CASE_ESC_SEMI:
X			/* semicolon in csi or dec mode */
X			param[nparam++] = DEFAULT;
X			break;
X
X		 case CASE_DEC_STATE:
X			/* enter dec mode */
X			parsestate = dectable;
X			break;
X
X		 case CASE_ICH:
X			/* ICH */
X			if((row = param[0]) < 1)
X				row = 1;
X			InsertChar(screen, row);
X			parsestate = groundtable;
X			break;
X
X		 case CASE_CUU:
X			/* CUU */
X			if((row = param[0]) < 1)
X				row = 1;
X			CursorUp(screen, row);
X			parsestate = groundtable;
X			break;
X
X		 case CASE_CUD:
X			/* CUD */
X			if((row = param[0]) < 1)
X				row = 1;
X			CursorDown(screen, row);
X			parsestate = groundtable;
X			break;
X
X		 case CASE_CUF:
X			/* CUF */
X			if((row = param[0]) < 1)
X				row = 1;
X			CursorForward(screen, row);
X			parsestate = groundtable;
X			break;
X
X		 case CASE_CUB:
X			/* CUB */
X			if((row = param[0]) < 1)
X				row = 1;
X			CursorBack(screen, row);
X			parsestate = groundtable;
X			break;
X
X		 case CASE_CUP:
X			/* CUP | HVP */
X			if((row = param[0]) < 1)
X				row = 1;
X			if(nparam < 2 || (col = param[1]) < 1)
X				col = 1;
X			CursorSet(screen, row-1, col-1, term->flags);
X			parsestate = groundtable;
X			break;
X
X		 case CASE_ED:
X			/* ED */
X			switch (param[0]) {
X			 case DEFAULT:
X			 case 0:
X				ClearBelow(screen);
X				break;
X
X			 case 1:
X				ClearAbove(screen);
X				break;
X
X			 case 2:
X				ClearScreen(screen);
X				break;
X			}
X			parsestate = groundtable;
X			break;
X
X		 case CASE_EL:
X			/* EL */
X			switch (param[0]) {
X			 case DEFAULT:
X			 case 0:
X				ClearRight(screen);
X				break;
X			 case 1:
X				ClearLeft(screen);
X				break;
X			 case 2:
X				ClearLine(screen);
X				break;
X			}
X			parsestate = groundtable;
X			break;
X
X		 case CASE_IL:
X			/* IL */
X			if((row = param[0]) < 1)
X				row = 1;
X			InsertLine(screen, row);
X			parsestate = groundtable;
X			break;
X
X		 case CASE_DL:
X			/* DL */
X			if((row = param[0]) < 1)
X				row = 1;
X			DeleteLine(screen, row);
X			parsestate = groundtable;
X			break;
X
X		 case CASE_DCH:
X			/* DCH */
X			if((row = param[0]) < 1)
X				row = 1;
X			DeleteChar(screen, row);
X			parsestate = groundtable;
X			break;
X
X		 case CASE_TRACK_MOUSE:
X		 	/* Track mouse as long as in window and between
X			   specified rows */
X			TrackMouse(param[0], param[2]-1, param[1]-1,
X			 param[3]-1, param[4]-2);
X			break;
X
X		 case CASE_DECID:
X			param[0] = -1;		/* Default ID parameter */
X			/* Fall through into ... */
X		 case CASE_DA1:
X			/* DA1 */
X			if (param[0] <= 0) {	/* less than means DEFAULT */
X				reply.a_type   = CSI;
X				reply.a_pintro = '?';
X				reply.a_nparam = 2;
X				reply.a_param[0] = 1;		/* VT102 */
X				reply.a_param[1] = 2;		/* VT102 */
X				reply.a_inters = 0;
X				reply.a_final  = 'c';
X				unparseseq(&reply, screen->respond);
X			}
X			parsestate = groundtable;
X			break;
X
X		 case CASE_TBC:
X			/* TBC */
X			if ((row = param[0]) <= 0) /* less than means default */
X				TabClear(term->tabs, screen->cur_col);
X			else if (row == 3)
X				TabZonk(term->tabs);
X			parsestate = groundtable;
X			break;
X
X		 case CASE_SET:
X			/* SET */
X			modes(term, bitset);
X			parsestate = groundtable;
X			break;
X
X		 case CASE_RST:
X			/* RST */
X			modes(term, bitclr);
X			parsestate = groundtable;
X			break;
X
X		 case CASE_SGR:
X			/* SGR */
X			for (row=0; row<nparam; ++row) {
X				switch (param[row]) {
X				 case DEFAULT:
X				 case 0:
X					term->flags &= ~(INVERSE|BOLD|UNDERLINE);
X					break;
X				 case 1:
X				 case 5:	/* Blink, really.	*/
X					term->flags |= BOLD;
X					break;
X				 case 4:	/* Underscore		*/
X					term->flags |= UNDERLINE;
X					break;
X				 case 7:
X					term->flags |= INVERSE;
X				}
X			}
X			parsestate = groundtable;
X			break;
X
X		 case CASE_CPR:
X			/* CPR */
X			if ((row = param[0]) == 5) {
X				reply.a_type = CSI;
X				reply.a_pintro = 0;
X				reply.a_nparam = 1;
X				reply.a_param[0] = 0;
X				reply.a_inters = 0;
X				reply.a_final  = 'n';
X				unparseseq(&reply, screen->respond);
X			} else if (row == 6) {
X				reply.a_type = CSI;
X				reply.a_pintro = 0;
X				reply.a_nparam = 2;
X				reply.a_param[0] = screen->cur_row+1;
X				reply.a_param[1] = screen->cur_col+1;
X				reply.a_inters = 0;
X				reply.a_final  = 'R';
X				unparseseq(&reply, screen->respond);
X			}
X			parsestate = groundtable;
X			break;
X
X		 case CASE_DECSTBM:
X			/* DECSTBM */
X			if((top = param[0]) < 1)
X				top = 1;
X			if(nparam < 2 || (bot = param[1]) == DEFAULT
X			   || bot > screen->max_row + 1
X			   || bot == 0)
X				bot = screen->max_row+1;
X			if (bot > top) {
X				if(screen->scroll_amt)
X					FlushScroll(screen);
X				screen->top_marg = top-1;
X				screen->bot_marg = bot-1;
X				CursorSet(screen, 0, 0, term->flags);
X			}
X			parsestate = groundtable;
X			break;
X
X		 case CASE_DECREQTPARM:
X			/* DECREQTPARM */
X			if ((row = param[0]) == DEFAULT)
X				row = 0;
X			if (row == 0 || row == 1) {
X				reply.a_type = CSI;
X				reply.a_pintro = 0;
X				reply.a_nparam = 7;
X				reply.a_param[0] = row + 2;
X				reply.a_param[1] = 1;	/* no parity */
X				reply.a_param[2] = 1;	/* eight bits */
X				reply.a_param[3] = 112;	/* transmit 9600 baud */
X				reply.a_param[4] = 112;	/* receive 9600 baud */
X				reply.a_param[5] = 1;	/* clock multiplier ? */
X				reply.a_param[6] = 0;	/* STP flags ? */
X				reply.a_inters = 0;
X				reply.a_final  = 'x';
X				unparseseq(&reply, screen->respond);
X			}
X			parsestate = groundtable;
X			break;
X
X		 case CASE_DECSET:
X			/* DECSET */
X			dpmodes(term, bitset);
X			parsestate = groundtable;
X			if(screen->TekEmu)
X				return;
X			break;
X
X		 case CASE_DECRST:
X			/* DECRST */
X			dpmodes(term, bitclr);
X			parsestate = groundtable;
X			break;
X
X		 case CASE_DECALN:
X			/* DECALN */
X			if(screen->cursor_state)
X				HideCursor();
X			for(row = screen->max_row ; row >= 0 ; row--) {
X				bzero(screen->buf[2 * row + 1],
X				 col = screen->max_col + 1);
X				for(cp = (unsigned char *)screen->buf[2 * row] ; col > 0 ; col--)
X					*cp++ = (unsigned char) 'E';
X			}
X			ScrnRefresh(screen, 0, 0, screen->max_row + 1,
X			 screen->max_col + 1, False);
X			parsestate = groundtable;
X			break;
X
X		 case CASE_GSETS:
X			screen->gsets[scstype] = c;
X			parsestate = groundtable;
X			break;
X
X		 case CASE_DECSC:
X			/* DECSC */
X			CursorSave(term, &screen->sc);
X			parsestate = groundtable;
X			break;
X
X		 case CASE_DECRC:
X			/* DECRC */
X			CursorRestore(term, &screen->sc);
X			parsestate = groundtable;
X			break;
X
X		 case CASE_DECKPAM:
X			/* DECKPAM */
X			term->keyboard.flags |= KYPD_APL;
X			update_appkeypad();
X			parsestate = groundtable;
X			break;
X
X		 case CASE_DECKPNM:
X			/* DECKPNM */
X			term->keyboard.flags &= ~KYPD_APL;
X			update_appkeypad();
X			parsestate = groundtable;
X			break;
X
X		 case CASE_IND:
X			/* IND */
X			Index(screen, 1);
X			if (screen->display->qlen > 0 ||
X			    GetBytesAvailable (screen->display->fd) > 0)
X			  xevents();
X			parsestate = groundtable;
X			break;
X
X		 case CASE_NEL:
X			/* NEL */
X			Index(screen, 1);
X			CarriageReturn(screen);
X			
X			if (screen->display->qlen > 0 ||
X			    GetBytesAvailable (screen->display->fd) > 0)
X			  xevents();
X			parsestate = groundtable;
X			break;
X
X		 case CASE_HTS:
X			/* HTS */
X			TabSet(term->tabs, screen->cur_col);
X			parsestate = groundtable;
X			break;
X
X		 case CASE_RI:
X			/* RI */
X			RevIndex(screen, 1);
X			parsestate = groundtable;
X			break;
X
X		 case CASE_SS2:
X			/* SS2 */
X			screen->curss = 2;
X			parsestate = groundtable;
X			break;
X
X		 case CASE_SS3:
X			/* SS3 */
X			screen->curss = 3;
X			parsestate = groundtable;
X			break;
X
X		 case CASE_CSI_STATE:
X			/* enter csi state */
X			nparam = 1;
X			param[0] = DEFAULT;
X			parsestate = csitable;
X			break;
X
X		 case CASE_OSC:
X			/* do osc escapes */
X			do_osc(finput);
X			parsestate = groundtable;
X			break;
X
X		 case CASE_RIS:
X			/* RIS */
X			VTReset(TRUE);
X			parsestate = groundtable;
X			break;
X
X		 case CASE_LS2:
X			/* LS2 */
X			screen->curgl = 2;
X			parsestate = groundtable;
X			break;
X
X		 case CASE_LS3:
X			/* LS3 */
X			screen->curgl = 3;
X			parsestate = groundtable;
X			break;
X
X		 case CASE_LS3R:
X			/* LS3R */
X			screen->curgr = 3;
X			parsestate = groundtable;
X			break;
X
X		 case CASE_LS2R:
X			/* LS2R */
X			screen->curgr = 2;
X			parsestate = groundtable;
X			break;
X
X		 case CASE_LS1R:
X			/* LS1R */
X			screen->curgr = 1;
X			parsestate = groundtable;
X			break;
X
X		 case CASE_XTERM_SAVE:
X			savemodes(term);
X			parsestate = groundtable;
X			break;
X
X		 case CASE_XTERM_RESTORE:
X			restoremodes(term);
X			parsestate = groundtable;
X			break;
X		}
X	}
X}
X
Xfinput()
X{
X	return(doinput());
X}
X
Xstatic int select_mask;
Xstatic int write_mask;
X
Xstatic char v_buffer[4096];
Xstatic char *v_bufstr;
Xstatic char *v_bufptr;
Xstatic char *v_bufend;
X#define	ptymask()	(v_bufptr > v_bufstr ? pty_mask : 0)
X
Xv_write(f, d, l)
Xint f;
Xchar *d;
Xint l;
X{
X	int r;
X	int c = l;
X
X	if (!v_bufstr) {
X		v_bufstr = v_buffer;
X		v_bufptr = v_buffer;
X		v_bufend = &v_buffer[4096];
X	}
X
X
X	if ((1 << f) != pty_mask)
X		return(write(f, d, l));
X
X	if (v_bufptr > v_bufstr) {
X		if (l) {
X			if (v_bufend > v_bufptr + l) {
X				bcopy(d, v_bufptr, l);
X				v_bufptr += l;
X			} else {
X				if (v_bufstr != v_buffer) {
X					bcopy(v_bufstr, v_buffer,
X					      v_bufptr - v_bufstr);
X					v_bufptr -= v_bufstr - v_buffer;
X					v_bufstr = v_buffer;
X				}
X				if (v_bufend > v_bufptr + l) {
X					bcopy(d, v_bufptr, l);
X					v_bufptr += l;
X				} else if (v_bufptr < v_bufend) {
X					fprintf(stderr, "Out of buffer space\n");
X					c = v_bufend - v_bufptr;
X					bcopy(d, v_bufptr, c);
X					v_bufptr = v_bufend;
X				} else {
X					fprintf(stderr, "Out of buffer space\n");
X					c = 0;
X				}
X			}
X		}
X		if (v_bufptr > v_bufstr) {
X			if ((r = write(f, v_bufstr, v_bufptr - v_bufstr)) <= 0)
X				return(r);
X			if ((v_bufstr += r) >= v_bufptr)
X				v_bufstr = v_bufptr = v_buffer;
X		}
X	} else if (l) {
X		if ((r = write(f, d, l)) < 0) {
X			if (errno == EWOULDBLOCK)
X				r = 0;
X			else if (errno == EINTR)
X				r = 0;
X			else
X				return(r);
X		}
X		if (l - r) {
X			if (l - r > v_bufend - v_buffer) {
X				fprintf(stderr, "Truncating to %d\n",
X						v_bufend - v_buffer);
X				l = (v_bufend - v_buffer) + r;
X			}
X			bcopy(d + r, v_buffer, l - r);
X			v_bufstr = v_buffer;
X			v_bufptr = v_buffer + (l - r);
X		}
X	}
X	return(c);
X}
X
Xin_put()
X{
X	register TScreen *screen = &term->screen;
X	register int i;
X	static struct timeval trackTimeOut;
X
X	select_mask = pty_mask;	/* force initial read */
X	for( ; ; ) {
X#ifdef        CRAY
X		trackTimeOut.tv_sec = 0;
X		trackTimeOut.tv_usec = 0;
X		(void) select(max_plus1, &select_mask, (int *) NULL,
X		    (int *)NULL, &trackTimeOut);
X#endif        /* CRAY */
X
X		if((select_mask & pty_mask) && (eventMode == NORMAL)) {
X			if(screen->logging)
X				FlushLog(screen);
X			if((bcnt = read(screen->respond, bptr = buffer,
X			 BUF_SIZE)) < 0) {
X				if(errno == EIO)
X					Cleanup (0);
X				else if(errno != EWOULDBLOCK)
X					Panic(
X				 "input: read returned unexpected error (%d)\n",
X					 errno);
X			} else if(bcnt == 0)
X				Panic("input: read returned zero\n", 0);
X			else {
X				if(screen->scrollWidget && screen->scrollttyoutput &&
X				 screen->topline < 0)
X					/* Scroll to bottom */
X					WindowScroll(screen, 0);
X				break;
X			}
X		}
X		if(screen->scroll_amt)
X			FlushScroll(screen);
X		if(screen->cursor_set && (screen->cursor_col != screen->cur_col
X		 || screen->cursor_row != screen->cur_row)) {
X			if(screen->cursor_state)
X				HideCursor();
X			ShowCursor();
X		} else if(screen->cursor_set != screen->cursor_state) {
X			if(screen->cursor_set)
X				ShowCursor();
X			else
X				HideCursor();
X		}
X		
X	if (waitingForTrackInfo) {
X			trackTimeOut.tv_sec = TRACKTIMESEC;
X			trackTimeOut.tv_usec = TRACKTIMEUSEC;
X			select_mask = pty_mask;
X			if ((i = select(max_plus1, &select_mask, (int *)NULL, (int *)NULL,
X			 &trackTimeOut)) < 0) {
X			 	if (errno != EINTR)
X					SysError(ERROR_SELECT);
X				continue;
X			} else if (i == 0) {
X				/* emacs just isn't replying, go on */
X				waitingForTrackInfo = 0;
X				Bell();
X				select_mask = Select_mask;
X			}
X		} else if (QLength(screen->display))
X			select_mask = X_mask;
X		else {
X			write_mask = ptymask();
X			XFlush(screen->display);
X			select_mask = Select_mask;
X			if (eventMode != NORMAL)
X				select_mask = X_mask;
X			if(select(max_plus1, &select_mask, &write_mask, 
X				(int *)NULL, (struct timeval *) NULL) < 0){
X				if (errno != EINTR)
X					SysError(ERROR_SELECT);
X				continue;
X			} 
X		}
X		if (write_mask & ptymask())
X			v_write(screen->respond, 0, 0);	/* flush buffer */
X		if(select_mask & X_mask) {
X			if (bcnt <= 0) {
X				bcnt = 0;
X				bptr = buffer;
X			}
X			xevents();
X			if (bcnt > 0)
X				break;
X		}
X	}
X	bcnt--;
X	return(*bptr++);
X}
X
X/*
X * process a string of characters according to the character set indicated
X * by charset.  worry about end of line conditions (wraparound if selected).
X */
Xdotext(screen, flags, charset, buf, ptr)
Xregister TScreen	*screen;
Xunsigned	flags;
Xchar		charset;
Xchar	*buf;
Xchar	*ptr;
X{
X	register char	*s;
X	register int	len;
X	register int	n;
X	register int	next_col;
X
X	switch (charset) {
X	case 'A':	/* United Kingdom set			*/
X		for (s=buf; s<ptr; ++s)
X			if (*s == '#')
X				*s = '\036';	/* UK pound sign*/
X		break;
X
X	case 'B':	/* ASCII set				*/
X		break;
X
X	case '0':	/* special graphics (line drawing)	*/
X		for (s=buf; s<ptr; ++s)
X			if (*s>=0x5f && *s<=0x7e)
X				*s = *s == 0x5f ? 0x7f : *s - 0x5f;
X		break;
X
X	default:	/* any character sets we don't recognize*/
X		return;
X	}
X
X	len = ptr - buf; 
X	ptr = buf;
X	while (len > 0) {
X		n = screen->max_col-screen->cur_col+1;
X		if (n <= 1) {
X			if (screen->do_wrap && (flags&WRAPAROUND)) {
X				Index(screen, 1);
X				screen->cur_col = 0;
X				screen->do_wrap = 0;
X				n = screen->max_col+1;
X			} else
X				n = 1;
X		}
X		if (len < n)
X			n = len;
X		next_col = screen->cur_col + n;
X		WriteText(screen, ptr, n, flags);
X		/*
X		 * the call to WriteText updates screen->cur_col.
X		 * If screen->cur_col != next_col, we must have
X		 * hit the right margin, so set the do_wrap flag.
X		 */
X		screen->do_wrap = (screen->cur_col < next_col);
X		len -= n;
X		ptr += n;
X	}
X}
X 
X/*
X * write a string str of length len onto the screen at
X * the current cursor position.  update cursor position.
X */
XWriteText(screen, str, len, flags)
Xregister TScreen	*screen;
Xregister char	*str;
Xregister int	len;
Xunsigned	flags;
X{
X	register int cx, cy;
X	register unsigned fgs = flags;
X	GC	currentGC;
X 
X   if(screen->cur_row - screen->topline <= screen->max_row) {
X	/*
X	if(screen->cur_row == screen->cursor_row && screen->cur_col <=
X	 screen->cursor_col && screen->cursor_col <= screen->cur_col + len - 1)
X		screen->cursor_state = OFF;
X	 */
X	if(screen->cursor_state)
X		HideCursor();
X
X	/*
X	 *	make sure that the correct GC is current
X	 */
X
X	if (fgs & BOLD)
X		if (fgs & INVERSE)
X			currentGC = screen->reverseboldGC;
X		else	currentGC = screen->normalboldGC;
X	else  /* not bold */
X		if (fgs & INVERSE)
X			currentGC = screen->reverseGC;
X		else	currentGC = screen->normalGC;
X
X	if (fgs & INSERT)
X		InsertChar(screen, len);
X      if (!(AddToRefresh(screen))) {
X		if(screen->scroll_amt)
X			FlushScroll(screen);
X	cx = CursorX(screen, screen->cur_col);
X	cy = CursorY(screen, screen->cur_row)+screen->fnt_norm->ascent;
X 	XDrawImageString(screen->display, TextWindow(screen), currentGC,
X			cx, cy, str, len);
X
X	if((fgs & BOLD) && screen->enbolden) 
X		if (currentGC == screen->normalGC || screen->reverseGC)
X			XDrawString(screen->display, TextWindow(screen),
X			      	currentGC,cx + 1, cy, str, len);
X
X	if(fgs & UNDERLINE) 
X		XDrawLine(screen->display, TextWindow(screen), currentGC,
X			cx, cy+1,
X			cx + len * FontWidth(screen), cy+1);
X	/*
X	 * the following statements compile data to compute the average 
X	 * number of characters written on each call to XText.  The data
X	 * may be examined via the use of a "hidden" escape sequence.
X	 */
X	ctotal += len;
X	++ntotal;
X      }
X    }
X	ScreenWrite(screen, str, flags, len);
X	CursorForward(screen, len);
X}
X 
X/*
X * process ANSI modes set, reset
X */
Xmodes(term, func)
XXtermWidget	term;
Xint		(*func)();
X{
X	register int	i;
X
X	for (i=0; i<nparam; ++i) {
X		switch (param[i]) {
X		case 4:			/* IRM				*/
X			(*func)(&term->flags, INSERT);
X			break;
X
X		case 20:		/* LNM				*/
X			(*func)(&term->flags, LINEFEED);
X			update_autolinefeed();
X			break;
X		}
X	}
X}
X
X/*
X * process DEC private modes set, reset
X */
Xdpmodes(term, func)
XXtermWidget	term;
Xint		(*func)();
X{
X	register TScreen	*screen	= &term->screen;
X	register int	i, j;
X	extern int bitset();
X
X	for (i=0; i<nparam; ++i) {
X		switch (param[i]) {
X		case 1:			/* DECCKM			*/
X			(*func)(&term->keyboard.flags, CURSOR_APL);
X			break;
X		case 2:			/* ANSI/VT52 mode		*/
X			if (func == bitset) {
X				screen->gsets[0] =
X					screen->gsets[1] =
X					screen->gsets[2] =
X					screen->gsets[3] = 'B';
X				screen->curgl = 0;
X				screen->curgr = 2;
X			}
X			break;
X		case 3:			/* DECCOLM			*/
X			if(screen->c132) {
X				ClearScreen(screen);
X				CursorSet(screen, 0, 0, term->flags);
X				if((j = func == bitset ? 132 : 80) !=
X				 ((term->flags & IN132COLUMNS) ? 132 : 80) ||
X				 j != screen->max_col + 1) {
X				        Dimension replyWidth, replyHeight;
X					XtGeometryResult status;
X
X					status = XtMakeResizeRequest (
X					    (Widget) term, 
X					    (Dimension) FontWidth(screen) * j
X					        + 2*screen->border
X						+ screen->scrollbar,
X					    (Dimension) FontHeight(screen)
X						* (screen->max_row + 1)
X						+ 2 * screen->border,
X					    &replyWidth, &replyHeight);
X
X					if (status == XtGeometryYes ||
X					    status == XtGeometryDone) {
X					    ScreenResize (&term->screen,
X							  replyWidth,
X							  replyHeight,
X							  &term->flags);
X					}
X				}
X				(*func)(&term->flags, IN132COLUMNS);
X			}
X			break;
X		case 4:			/* DECSCLM (slow scroll)	*/
X			if (func == bitset) {
X				screen->jumpscroll = 0;
X				if (screen->scroll_amt)
X					FlushScroll(screen);
X			} else
X				screen->jumpscroll = 1;
X			(*func)(&term->flags, SMOOTHSCROLL);
X			update_jumpscroll();
X			break;
X		case 5:			/* DECSCNM			*/
X			j = term->flags;
X			(*func)(&term->flags, REVERSE_VIDEO);
X			if ((term->flags ^ j) & REVERSE_VIDEO)
X				ReverseVideo(term);
X			/* update_reversevideo done in RevVid */
X			break;
X
X		case 6:			/* DECOM			*/
X			(*func)(&term->flags, ORIGIN);
X			CursorSet(screen, 0, 0, term->flags);
X			break;
X
X		case 7:			/* DECAWM			*/
X			(*func)(&term->flags, WRAPAROUND);
X			update_autowrap();
X			break;
X		case 8:			/* DECARM			*/
X			/* ignore autorepeat */
X			break;
X		case 9:			/* MIT bogus sequence		*/
X			if(func == bitset)
X				screen->send_mouse_pos = 1;
X			else
X				screen->send_mouse_pos = 0;
X			break;
X		case 38:		/* DECTEK			*/
X			if(func == bitset & !(screen->inhibit & I_TEK)) {
X				if(screen->logging) {
X					FlushLog(screen);
X					screen->logstart = Tbuffer;
X				}
X				screen->TekEmu = TRUE;
X			}
X			break;
X		case 40:		/* 132 column mode		*/
X			screen->c132 = (func == bitset);
X			update_allow132();
X			break;
X		case 41:		/* curses hack			*/
X			screen->curses = (func == bitset);
X			update_cursesemul();
X			break;
X		case 44:		/* margin bell			*/
X			screen->marginbell = (func == bitset);
X			if(!screen->marginbell)
X				screen->bellarmed = -1;
X			update_marginbell();
X			break;
X		case 45:		/* reverse wraparound	*/
X			(*func)(&term->flags, REVERSEWRAP);
X			update_reversewrap();
X			break;
X		case 46:		/* logging		*/
X#ifdef ALLOWLOGFILEONOFF
X			/*
X			 * if this feature is enabled, logging may be 
X			 * enabled and disabled via escape sequences.
X			 */
X			if(func == bitset)
X				StartLog(screen);
X			else
X				CloseLog(screen);
X#else
X			Bell();
X			Bell();
X#endif /* ALLOWLOGFILEONOFF */
X			break;
X		case 47:		/* alternate buffer		*/
X			if(func == bitset)
X				ToAlternate(screen);
X			else
X				FromAlternate(screen);
X			break;
X		case 1000:		/* xtem bogus sequence		*/
X			if(func == bitset)
X				screen->send_mouse_pos = 2;
X			else
X				screen->send_mouse_pos = 0;
X			break;
X		case 1001:		/* xtem sequence w/hilite tracking */
X			if(func == bitset)
X				screen->send_mouse_pos = 3;
X			else
X				screen->send_mouse_pos = 0;
X			break;
X		}
X	}
X}
X
X/*
X * process xterm private modes save
X */
Xsavemodes(term)
XXtermWidget term;
X{
X	register TScreen	*screen	= &term->screen;
X	register int i;
X
X	for (i = 0; i < nparam; i++) {
X		switch (param[i]) {
X		case 1:			/* DECCKM			*/
X			screen->save_modes[0] = term->keyboard.flags &
X			 CURSOR_APL;
X			break;
X		case 3:			/* DECCOLM			*/
X			if(screen->c132)
X				screen->save_modes[1] = term->flags &
X				 IN132COLUMNS;
X			break;
X		case 4:			/* DECSCLM (slow scroll)	*/
X			screen->save_modes[2] = term->flags & SMOOTHSCROLL;
X			break;
X		case 5:			/* DECSCNM			*/
X			screen->save_modes[3] = term->flags & REVERSE_VIDEO;
X			break;
X		case 6:			/* DECOM			*/
X			screen->save_modes[4] = term->flags & ORIGIN;
X			break;
X
X		case 7:			/* DECAWM			*/
X			screen->save_modes[5] = term->flags & WRAPAROUND;
X			break;
X		case 8:			/* DECARM			*/
X			/* ignore autorepeat */
X			break;
X		case 9:			/* mouse bogus sequence */
X			screen->save_modes[7] = screen->send_mouse_pos;
X			break;
X		case 40:		/* 132 column mode		*/
X			screen->save_modes[8] = screen->c132;
X			break;
X		case 41:		/* curses hack			*/
X			screen->save_modes[9] = screen->curses;
X			break;
X		case 44:		/* margin bell			*/
X			screen->save_modes[12] = screen->marginbell;
X			break;
X		case 45:		/* reverse wraparound	*/
X			screen->save_modes[13] = term->flags & REVERSEWRAP;
X			break;
X		case 46:		/* logging		*/
X			screen->save_modes[14] = screen->logging;
X			break;
X		case 47:		/* alternate buffer		*/
X			screen->save_modes[15] = screen->alternate;
X			break;
X		case 1000:		/* mouse bogus sequence		*/
X		case 1001:
X			screen->save_modes[7] = screen->send_mouse_pos;
X			break;
X		}
X	}
X}
X
X/*
X * process xterm private modes restore
X */
Xrestoremodes(term)
XXtermWidget term;
X{
X	register TScreen	*screen	= &term->screen;
X	register int i, j;
X
X	for (i = 0; i < nparam; i++) {
X		switch (param[i]) {
X		case 1:			/* DECCKM			*/
X			term->keyboard.flags &= ~CURSOR_APL;
X			term->keyboard.flags |= screen->save_modes[0] &
X			 CURSOR_APL;
X			update_appcursor();
X			break;
X		case 3:			/* DECCOLM			*/
X			if(screen->c132) {
X				ClearScreen(screen);
X				CursorSet(screen, 0, 0, term->flags);
X				if((j = (screen->save_modes[1] & IN132COLUMNS)
X				 ? 132 : 80) != ((term->flags & IN132COLUMNS)
X				 ? 132 : 80) || j != screen->max_col + 1) {
X				        Dimension replyWidth, replyHeight;
X					XtGeometryResult status;
X					status = XtMakeResizeRequest (
X					    (Widget) term,
X					    (Dimension) FontWidth(screen) * j 
X						+ 2*screen->border
X						+ screen->scrollbar,
X					    (Dimension) FontHeight(screen)
X						* (screen->max_row + 1)
X						+ 2*screen->border,
X					    &replyWidth, &replyHeight);
X
X					if (status == XtGeometryYes ||
X					    status == XtGeometryDone) {
X					    ScreenResize (&term->screen,
X							  replyWidth,
X							  replyHeight,
X							  &term->flags);
X					}
X				}
X				term->flags &= ~IN132COLUMNS;
X				term->flags |= screen->save_modes[1] &
X				 IN132COLUMNS;
X			}
X			break;
X		case 4:			/* DECSCLM (slow scroll)	*/
X			if (screen->save_modes[2] & SMOOTHSCROLL) {
X				screen->jumpscroll = 0;
X				if (screen->scroll_amt)
X					FlushScroll(screen);
X			} else
X				screen->jumpscroll = 1;
X			term->flags &= ~SMOOTHSCROLL;
X			term->flags |= screen->save_modes[2] & SMOOTHSCROLL;
X			update_jumpscroll();
X			break;
X		case 5:			/* DECSCNM			*/
X			if((screen->save_modes[3] ^ term->flags) &
X			 REVERSE_VIDEO) {
X				term->flags &= ~REVERSE_VIDEO;
X				term->flags |= screen->save_modes[3] &
X				 REVERSE_VIDEO;
X				ReverseVideo(term);
X				/* update_reversevideo done in RevVid */
X			}
X			break;
X		case 6:			/* DECOM			*/
X			term->flags &= ~ORIGIN;
X			term->flags |= screen->save_modes[4] & ORIGIN;
X			CursorSet(screen, 0, 0, term->flags);
X			break;
X
X		case 7:			/* DECAWM			*/
X			term->flags &= ~WRAPAROUND;
X			term->flags |= screen->save_modes[5] & WRAPAROUND;
X			update_autowrap();
X			break;
X		case 8:			/* DECARM			*/
X			/* ignore autorepeat */
X			break;
X		case 9:			/* MIT bogus sequence		*/
X			screen->send_mouse_pos = screen->save_modes[7];
X			break;
X		case 40:		/* 132 column mode		*/
X			screen->c132 = screen->save_modes[8];
X			update_allow132();
X			break;
X		case 41:		/* curses hack			*/
X			screen->curses = screen->save_modes[9];
X			update_cursesemul();
X			break;
X		case 44:		/* margin bell			*/
X			if(!(screen->marginbell = screen->save_modes[12]))
X				screen->bellarmed = -1;
X			update_visualbell();
X			break;
X		case 45:		/* reverse wraparound	*/
X			term->flags &= ~REVERSEWRAP;
X			term->flags |= screen->save_modes[13] & REVERSEWRAP;
X			update_reversewrap();
X			break;
X		case 46:		/* logging		*/
X#ifdef ALLOWLOGFILEONOFF
X			if(screen->save_modes[14])
X				StartLog(screen);
X			else
X				CloseLog(screen);
X#endif /* ALLOWLOGFILEONOFF */
X			/* update_logging done by StartLog and CloseLog */
X			break;
X		case 47:		/* alternate buffer		*/
X			if(screen->save_modes[15])
X				ToAlternate(screen);
X			else
X				FromAlternate(screen);
X			/* update_altscreen done by ToAlt and FromAlt */
X			break;
X		case 1000:		/* mouse bogus sequence		*/
X		case 1001:
X			screen->send_mouse_pos = screen->save_modes[7];
X			break;
X		}
X	}
X}
X
X/*
X * set a bit in a word given a pointer to the word and a mask.
X */
Xbitset(p, mask)
Xint	*p;
X{
X	*p |= mask;
X}
X
X/*
X * clear a bit in a word given a pointer to the word and a mask.
X */
Xbitclr(p, mask)
Xint	*p;
X{
X	*p &= ~mask;
X}
X
Xunparseseq(ap, fd)
Xregister ANSI	*ap;
X{
X	register int	c;
X	register int	i;
X	register int	inters;
X
X	c = ap->a_type;
X	if (c>=0x80 && c<=0x9F) {
X		unparseputc(ESC, fd);
X		c -= 0x40;
X	}
X	unparseputc(c, fd);
X	c = ap->a_type;
X	if (c==ESC || c==DCS || c==CSI || c==OSC || c==PM || c==APC) {
X		if (ap->a_pintro != 0)
X			unparseputc((char) ap->a_pintro, fd);
X		for (i=0; i<ap->a_nparam; ++i) {
X			if (i != 0)
X				unparseputc(';', fd);
X			unparseputn((unsigned int) ap->a_param[i], fd);
X		}
X		inters = ap->a_inters;
X		for (i=3; i>=0; --i) {
X			c = (inters >> (8*i)) & 0xff;
X			if (c != 0)
X				unparseputc(c, fd);
X		}
X		unparseputc((char) ap->a_final, fd);
X	}
X}
X
Xunparseputn(n, fd)
Xunsigned int	n;
Xint fd;
X{
X	unsigned int	q;
X
X	q = n/10;
X	if (q != 0)
X		unparseputn(q, fd);
X	unparseputc((char) ('0' + (n%10)), fd);
X}
X
Xunparseputc(c, fd)
Xchar c;
Xint fd;
X{
X	char	buf[2];
X	register i = 1;
X	extern XtermWidget term;
X
X	if((buf[0] = c) == '\r' && (term->flags & LINEFEED)) {
X		buf[1] = '\n';
X		i++;
X	}
X	if (write(fd, buf, i) != i)
X		Panic("unparseputc: error writing character\n", 0);
X}
X
Xunparsefputs (s, fd)
X    register char *s;
X    int fd;
X{
X    if (s) {
X	while (*s) unparseputc (*s++, fd);
X    }
X}
X
X
XToAlternate(screen)
Xregister TScreen *screen;
X{
X	extern ScrnBuf Allocate();
X
X	if(screen->alternate)
X		return;
X	if(!screen->altbuf)
X		screen->altbuf = Allocate(screen->max_row + 1, screen->max_col
X		 + 1, &screen->abuf_address);
X	SwitchBufs(screen);
X	screen->alternate = TRUE;
X	update_altscreen();
X}
X
XFromAlternate(screen)
Xregister TScreen *screen;
X{
X	if(!screen->alternate)
X		return;
X	screen->alternate = FALSE;
X	SwitchBufs(screen);
X	update_altscreen();
X}
X
XSwitchBufs(screen)
Xregister TScreen *screen;
X{
X	register int rows, top;
X	char *save [2 * MAX_ROWS];
X
X	if(screen->cursor_state)
X		HideCursor();
X	rows = screen->max_row + 1;
X	bcopy((char *)screen->buf, (char *)save, 2 * sizeof(char *) * rows);
X	bcopy((char *)screen->altbuf, (char *)screen->buf, 2 * sizeof(char *) *
X	 rows);
X	bcopy((char *)save, (char *)screen->altbuf, 2 * sizeof(char *) * rows);
X
X	if((top = -screen->topline) <= screen->max_row) {
X		if(screen->scroll_amt)
X			FlushScroll(screen);
X		if(top == 0)
X			XClearWindow(screen->display, TextWindow(screen));
X		else
X			XClearArea(
X			    screen->display,
X			    TextWindow(screen),
X			    (int) screen->border + screen->scrollbar,
X			    (int) top * FontHeight(screen) + screen->border,
X			    (unsigned) Width(screen),
X			    (unsigned) (screen->max_row - top + 1)
X				* FontHeight(screen),
X			    FALSE);
X	}
X	ScrnRefresh(screen, 0, 0, rows, screen->max_col + 1, False);
X}
X
XVTRun()
X{
X	register TScreen *screen = &term->screen;
X	register int i;
X	
X	if (!screen->Vshow) {
X	    XtRealizeWidget (term->core.parent);
X	    set_vt_visibility (TRUE);
X	} 
X	update_vttekmode();
X	update_vtshow();
X	update_tekshow();
X	set_vthide_sensitivity();
X
X	if (screen->allbuf == NULL) VTallocbuf ();
X
X	screen->cursor_state = OFF;
X	screen->cursor_set = ON;
X
X	bcnt = 0;
X	bptr = buffer;
X	while(Tpushb > Tpushback) {
X		*bptr++ = *--Tpushb;
X		bcnt++;
X	}
X	bcnt += (i = Tbcnt);
X	for( ; i > 0 ; i--)
X		*bptr++ = *Tbptr++;
X	bptr = buffer;
X	if(!setjmp(VTend))
X		VTparse();
X	HideCursor();
X	screen->cursor_set = OFF;
X}
X
X/*ARGSUSED*/
Xstatic void VTExpose(w, event, region)
XWidget w;
XXEvent *event;
XRegion region;
X{
X	register TScreen *screen = &term->screen;
X
X#ifdef DEBUG
X	if(debug)
X		fputs("Expose\n", stderr);
X#endif	/* DEBUG */
X	if (event->type == Expose)
X		HandleExposure (screen, (XExposeEvent *)event);
X}
X
Xstatic void VTGraphicsOrNoExpose (event)
XXEvent *event;
X    {
X	register TScreen *screen = &term->screen;
X	if (screen->incopy <= 0) {
X		screen->incopy = 1;
X		if (screen->scrolls > 0)
X			screen->scrolls--;
X	}
X	if (event->type == GraphicsExpose)
X	  if (HandleExposure (screen, (XExposeEvent *)event))
X		screen->cursor_state = OFF;
X	if ((event->type == NoExpose) || ((XGraphicsExposeEvent *)event)->count == 0) {
X		if (screen->incopy <= 0 && screen->scrolls > 0)
X			screen->scrolls--;
X		if (screen->scrolls)
X			screen->incopy = -1;
X		else
X			screen->incopy = 0;
X	}
X}
X
X/*ARGSUSED*/
Xstatic void VTNonMaskableEvent (w, closure, event)
XWidget w;
Xcaddr_t closure;
XXEvent *event;
X    {
X    switch (event->type) {
X       case MappingNotify:
X	  XRefreshKeyboardMapping (&event->xmapping);
X	  break;
X       case GraphicsExpose:
X       case NoExpose:
X	  VTGraphicsOrNoExpose (event);
X	  break;
X	  }
X    }
X
X
X
X
Xstatic void VTResize(w)
X    Widget w;
X{
X    if (XtIsRealized(w))
X      ScreenResize (&term->screen, term->core.width, term->core.height,
X		    &term->flags);
X}
X
X
Xint VTInit ()
X{
X    register TScreen *screen = &term->screen;
X
X    XtRealizeWidget (term->core.parent);
X    if (screen->allbuf == NULL) VTallocbuf ();
X    return (1);
X}
X
Xstatic void VTallocbuf ()
X{
X    register TScreen *screen = &term->screen;
X    int nrows = screen->max_row + 1;
X    extern ScrnBuf Allocate();
X
X    /* allocate screen buffer now, if necessary. */
X    if (screen->scrollWidget)
X      nrows += screen->savelines;
X    screen->allbuf = Allocate (nrows, screen->max_col + 1,
X     &screen->sbuf_address);
X    if (screen->scrollWidget)
X      screen->buf = &screen->allbuf[2 * screen->savelines];
X    else
X      screen->buf = screen->allbuf;
X    return;
X}
X
Xstatic void VTInitialize (request, new)
X   XtermWidget request, new;
X{
X   int i;
X   /* Zero out the entire "screen" component of "new" widget,
X      then do field-by-field assigment of "screen" fields
X      that are named in the resource list. */
X
X   bzero ((char *) &new->screen, sizeof(new->screen));
X   new->screen.c132 = request->screen.c132;
X   new->screen.curses = request->screen.curses;
X   new->screen.foreground = request->screen.foreground;
X   new->screen.cursorcolor = request->screen.cursorcolor;
X   new->screen.border = request->screen.border;
X   new->screen.jumpscroll = request->screen.jumpscroll;
X   new->screen.logfile = request->screen.logfile;
X   new->screen.marginbell = request->screen.marginbell;
X   new->screen.mousecolor = request->screen.mousecolor;
X   new->screen.mousecolorback = request->screen.mousecolorback;
X   new->screen.multiscroll = request->screen.multiscroll;
X   new->screen.nmarginbell = request->screen.nmarginbell;
X   new->screen.savelines = request->screen.savelines;
X   new->screen.scrolllines = request->screen.scrolllines;
X   new->screen.scrollttyoutput = request->screen.scrollttyoutput;
X   new->screen.scrollkey = request->screen.scrollkey;
X   new->screen.visualbell = request->screen.visualbell;
X   new->screen.TekEmu = request->screen.TekEmu;
X   new->misc.re_verse = request->misc.re_verse;
X   new->screen.multiClickTime = request->screen.multiClickTime;
X   new->screen.charClass = request->screen.charClass;
X   new->screen.cutNewline = request->screen.cutNewline;
X   new->screen.cutToBeginningOfLine = request->screen.cutToBeginningOfLine;
X   new->screen.always_highlight = request->screen.always_highlight;
X   new->screen.pointer_cursor = request->screen.pointer_cursor;
X   new->screen.eight_bits = request->screen.eight_bits;
X   new->screen.allowSendEvents = request->screen.allowSendEvents;
X   new->misc.titeInhibit = request->misc.titeInhibit;
X   for (i = 0; i < NMENUFONTS; i++) {
X       new->screen.menu_font_names[i] = request->screen.menu_font_names[i];
X   }
X   /* set default in realize proc */
X   new->screen.menu_font_names[fontMenu_fontdefault] = NULL;
X   new->screen.menu_font_names[fontMenu_fontescape] = NULL;
X   new->screen.menu_font_names[fontMenu_fontsel] = NULL;
X   new->screen.menu_font_number = fontMenu_fontdefault;
X
X    /*
X     * The definition of -rv now is that it changes the definition of 
X     * XtDefaultForeground and XtDefaultBackground.  So, we no longer
X     * need to do anything special.
X     */
X   new->keyboard.flags = 0;
X   new->screen.display = new->core.screen->display;
X   new->core.height = new->core.width = 1;
X      /* dummy values so that we don't try to Realize the parent shell 
X	 with height or width of 0, which is illegal in X.  The real
X	 size is computed in the xtermWidget's Realize proc,
X	 but the shell's Realize proc is called first, and must see
X	 a valid size. */
X
X   /* look for focus related events on the shell, because we need
X    * to care about the shell's border being part of our focus.
X    */
X   XtAddEventHandler(XtParent(new), EnterWindowMask, FALSE,
X		HandleEnterWindow, (Opaque)NULL);
X   XtAddEventHandler(XtParent(new), LeaveWindowMask, FALSE,
X		HandleLeaveWindow, (Opaque)NULL);
X   XtAddEventHandler(XtParent(new), FocusChangeMask, FALSE,
X		HandleFocusChange, (Opaque)NULL);
X   XtAddEventHandler(new, 0L, TRUE,
X		VTNonMaskableEvent, (Opaque)NULL);
X
X   set_character_class (new->screen.charClass);
X
X   /* create it, but don't realize it */
X   ScrollBarOn (new, TRUE, FALSE);
X   return;
X}
X
X
Xstatic void VTDestroy (w)
XWidget w;
X{
X    XtFree(((XtermWidget)w)->screen.selection);
X}
X
X/*ARGSUSED*/
Xstatic void VTRealize (w, valuemask, values)
XWidget w;
XXtValueMask *valuemask;
XXSetWindowAttributes *values;
X{
X	unsigned int width, height;
X	register TScreen *screen = &term->screen;
X	int xpos, ypos, pr;
X	extern char *malloc();
X	XSizeHints		sizehints;
X	extern int		VTgcFontMask;
X	int scrollbar_width;
X
X	TabReset (term->tabs);
X
X	screen->menu_font_names[fontMenu_fontdefault] = term->misc.f_n;
X	screen->fnt_norm = screen->fnt_bold = NULL;
X	if (!LoadNewFont(screen, term->misc.f_n, term->misc.f_b, False, 0)) {
X	    if (XmuCompareISOLatin1(term->misc.f_n, "fixed") != 0) {
X		fprintf (stderr, 
X		     "%s:  unable to open font \"%s\", trying \"fixed\"....\n",
X		     xterm_name, term->misc.f_n);
X		(void) LoadNewFont (screen, "fixed", NULL, False, 0);
X		screen->menu_font_names[fontMenu_fontdefault] = "fixed";
X	    }
X	}
X
X	/* really screwed if we couldn't open default font */
X	if (!screen->fnt_norm) {
X	    fprintf (stderr, "%s:  unable to locate a suitable font\n",
X		     xterm_name);
X	    Exit (1);
X	}
X
X	/* making cursor */
X	if (!screen->pointer_cursor) 
X	  screen->pointer_cursor = make_colored_cursor(XC_xterm, 
X						       screen->mousecolor,
X						       screen->mousecolorback);
X	else 
X	  recolor_cursor (screen->pointer_cursor, 
X			  screen->mousecolor, screen->mousecolorback);
X
X	scrollbar_width = (term->misc.scrollbar ?
X			   screen->scrollWidget->core.width : 0);
X
X
X	/* set defaults */
X	xpos = 1; ypos = 1; width = 80; height = 24;
X	pr = XParseGeometry (term->misc.geo_metry, &xpos, &ypos,
X			     &width, &height);
X	screen->max_col = (width - 1);	/* units in character cells */
X	screen->max_row = (height - 1);	/* units in character cells */
X	update_font_info (&term->screen, False);
X
X	width = screen->fullVwin.fullwidth;
X	height = screen->fullVwin.fullheight;
X
X	if ((pr & XValue) && (XNegative&pr)) 
X	  xpos += DisplayWidth(screen->display, DefaultScreen(screen->display))
X			- width - (term->core.parent->core.border_width * 2);
X	if ((pr & YValue) && (YNegative&pr))
X	  ypos += DisplayHeight(screen->display,DefaultScreen(screen->display))
X			- height - (term->core.parent->core.border_width * 2);
X
X	/* set up size hints for window manager; min 1 char by 1 char */
X	sizehints.base_width = 2 * screen->border + scrollbar_width;
X	sizehints.base_height = 2 * screen->border;
X	sizehints.width_inc = FontWidth(screen);
X	sizehints.height_inc = FontHeight(screen);
X	sizehints.min_width = sizehints.base_width + sizehints.width_inc;
X	sizehints.min_height = sizehints.base_height + sizehints.height_inc;
X	sizehints.flags = (PBaseSize|PMinSize|PResizeInc);
X	sizehints.x = xpos;
X	sizehints.y = ypos;
X	if ((XValue&pr) || (YValue&pr)) {
X	    sizehints.flags |= USSize|USPosition;
X	    sizehints.flags |= PWinGravity;
X	    switch (pr & (XNegative | YNegative)) {
X	      case 0:
X		sizehints.win_gravity = NorthWestGravity;
X		break;
X	      case XNegative:
X		sizehints.win_gravity = NorthEastGravity;
X		break;
X	      case YNegative:
X		sizehints.win_gravity = SouthWestGravity;
X		break;
X	      default:
X		sizehints.win_gravity = SouthEastGravity;
X		break;
X	    }
X	} else {
X	    /* set a default size, but do *not* set position */
X	    sizehints.flags |= PSize;
X	}
X	sizehints.width = width;
X	sizehints.height = height;
X	if ((WidthValue&pr) || (HeightValue&pr)) 
X	  sizehints.flags |= USSize;
X	else sizehints.flags |= PSize;
X
X	(void) XtMakeResizeRequest((Widget) term,
X				   (Dimension)width, (Dimension)height,
X				   &term->core.width, &term->core.height);
X
X	/* XXX This is bogus.  We are parsing geometries too late.  This
X	 * is information that the shell widget ought to have before we get
X	 * realized, so that it can do the right thing.
X	 */
X        if (sizehints.flags & USPosition)
X	    XMoveWindow (XtDisplay(term), term->core.parent->core.window,
X			 sizehints.x, sizehints.y);
X
X	XSetWMNormalHints (XtDisplay(term), term->core.parent->core.window,
X			   &sizehints);
X
X	values->bit_gravity = NorthWestGravity;
X	term->screen.fullVwin.window = term->core.window =
X	  XCreateWindow(XtDisplay(term), XtWindow(term->core.parent),
X		term->core.x, term->core.y,
X		term->core.width, term->core.height, term->core.border_width,
X		(int) term->core.depth,
X		InputOutput, CopyFromParent,	
X		*valuemask|CWBitGravity, values);
X
X	set_cursor_gcs (screen);
X
X	/* Reset variables used by ANSI emulation. */
X
X	screen->gsets[0] = 'B';			/* ASCII_G		*/
X	screen->gsets[1] = 'B';
X	screen->gsets[2] = 'B';			/* DEC supplemental.	*/
X	screen->gsets[3] = 'B';
X	screen->curgl = 0;			/* G0 => GL.		*/
X	screen->curgr = 2;			/* G2 => GR.		*/
X	screen->curss = 0;			/* No single shift.	*/
X
X	XDefineCursor(screen->display, VShellWindow, screen->pointer_cursor);
X
X        screen->cur_col = screen->cur_row = 0;
X	screen->max_col = Width(screen)/screen->fullVwin.f_width - 1;
X	screen->top_marg = 0;
X	screen->bot_marg = screen->max_row = Height(screen) /
X				screen->fullVwin.f_height - 1;
X
X	screen->sc.row = screen->sc.col = screen->sc.flags = NULL;
X
X	/* Mark screen buffer as unallocated.  We wait until the run loop so
X	   that the child process does not fork and exec with all the dynamic
X	   memory it will never use.  If we were to do it here, the
X	   swap space for new process would be huge for huge savelines. */
X	if (!tekWidget)			/* if not called after fork */
X	  screen->buf = screen->allbuf = NULL;
X
X	screen->do_wrap = NULL;
X	screen->scrolls = screen->incopy = 0;
X	set_vt_box (screen);
X
X	screen->savedlines = 0;
X
X	if (term->misc.scrollbar) {
X		screen->scrollbar = 0;
X		ScrollBarOn (term, FALSE, TRUE);
X	}
X	CursorSave (term, &screen->sc);
X	return;
X}
X
X/*
X * Shows cursor at new cursor position in screen.
X */
XShowCursor()
X{
X	register TScreen *screen = &term->screen;
X	register int x, y, flags;
X	Char c;
X	GC	currentGC;
X	Boolean	in_selection;
X
X	if (eventMode != NORMAL) return;
X
X	if (screen->cur_row - screen->topline > screen->max_row)
X		return;
X	c = screen->buf[y = 2 * (screen->cursor_row = screen->cur_row)]
X	 [x = screen->cursor_col = screen->cur_col];
X	flags = screen->buf[y + 1][x];
X	if (c == 0)
X		c = ' ';
X
X	if (screen->cur_row > screen->endHRow ||
X	    (screen->cur_row == screen->endHRow &&
X	     screen->cur_col >= screen->endHCol) ||
X	    screen->cur_row < screen->startHRow ||
X	    (screen->cur_row == screen->startHRow &&
X	     screen->cur_col < screen->startHCol))
X	    in_selection = False;
X	else
X	    in_selection = True;
X
X	if(screen->select || screen->always_highlight) {
X		if (( (flags & INVERSE) && !in_selection) ||
X		    (!(flags & INVERSE) &&  in_selection)){
X		    /* text is reverse video */
X		    if (screen->cursorGC) {
X			currentGC = screen->cursorGC;
X		    } else {
X			if (flags & BOLD) {
X				currentGC = screen->normalboldGC;
X			} else {
X				currentGC = screen->normalGC;
X			}
X		    }
X		} else { /* normal video */
X		    if (screen->reversecursorGC) {
X			currentGC = screen->reversecursorGC;
X		    } else {
X			if (flags & BOLD) {
X				currentGC = screen->reverseboldGC;
X			} else {
X				currentGC = screen->reverseGC;
X			}
X		    }
X		}
X	} else { /* not selected */
X		if (( (flags & INVERSE) && !in_selection) ||
X		    (!(flags & INVERSE) &&  in_selection)) {
X		    /* text is reverse video */
X			currentGC = screen->reverseGC;
X		} else { /* normal video */
X			currentGC = screen->normalGC;
X		}
X	    
X	}
X
X	x = CursorX (screen, screen->cur_col);
X	y = CursorY(screen, screen->cur_row) + 
X	  screen->fnt_norm->ascent;
X	XDrawImageString(screen->display, TextWindow(screen), currentGC,
X		x, y, (char *) &c, 1);
X
X	if((flags & BOLD) && screen->enbolden) /* no bold font */
X		XDrawString(screen->display, TextWindow(screen), currentGC,
X			x + 1, y, (char *) &c, 1);
X	if(flags & UNDERLINE) 
X		XDrawLine(screen->display, TextWindow(screen), currentGC,
X			x, y+1, x + FontWidth(screen), y+1);
X	if (!screen->select && !screen->always_highlight) {
X		screen->box->x = x;
X		screen->box->y = y - screen->fnt_norm->ascent;
X		XDrawLines (screen->display, TextWindow(screen), 
X			    screen->cursoroutlineGC ? screen->cursoroutlineGC 
X			    			    : currentGC,
X			    screen->box, NBOX, CoordModePrevious);
X	}
X	screen->cursor_state = ON;
X}
X
X/*
X * hide cursor at previous cursor position in screen.
X */
XHideCursor()
X{
X	register TScreen *screen = &term->screen;
X	GC	currentGC;
X	register int x, y, flags;
X	char c;
X	Boolean	in_selection;
X
X	if(screen->cursor_row - screen->topline > screen->max_row)
X		return;
X	c = screen->buf[y = 2 * screen->cursor_row][x = screen->cursor_col];
X	flags = screen->buf[y + 1][x];
X
X	if (screen->cursor_row > screen->endHRow ||
X	    (screen->cursor_row == screen->endHRow &&
X	     screen->cursor_col >= screen->endHCol) ||
X	    screen->cursor_row < screen->startHRow ||
X	    (screen->cursor_row == screen->startHRow &&
X	     screen->cursor_col < screen->startHCol))
X	    in_selection = False;
X	else
X	    in_selection = True;
X
X	if (( (flags & INVERSE) && !in_selection) ||
X	    (!(flags & INVERSE) &&  in_selection)) {
X		if(flags & BOLD) {
X			currentGC = screen->reverseboldGC;
X		} else {
X			currentGC = screen->reverseGC;
X		}
X	} else {
X		if(flags & BOLD) {
X			currentGC = screen->normalboldGC;
X		} else {
X			currentGC = screen->normalGC;
X		}
X	}
X
X	if (c == 0)
X		c = ' ';
X	x = CursorX (screen, screen->cursor_col);
X	y = (((screen->cursor_row - screen->topline) * FontHeight(screen))) +
X	 screen->border;
X	y = y+screen->fnt_norm->ascent;
X	XDrawImageString(screen->display, TextWindow(screen), currentGC,
X		x, y, &c, 1);
X	if((flags & BOLD) && screen->enbolden)
X		XDrawString(screen->display, TextWindow(screen), currentGC,
X			x + 1, y, &c, 1);
X	if(flags & UNDERLINE) 
X		XDrawLine(screen->display, TextWindow(screen), currentGC,
X			x, y+1, x + FontWidth(screen), y+1);
X	screen->cursor_state = OFF;
X}
X
XVTReset(full)
Xint full;
X{
X	register TScreen *screen = &term->screen;
X
X	/* reset scrolling region */
X	screen->top_marg = 0;
X	screen->bot_marg = screen->max_row;
X	term->flags &= ~ORIGIN;
X	if(full) {
X		TabReset (term->tabs);
X		term->keyboard.flags = NULL;
X		screen->gsets[0] = 'B';
X		screen->gsets[1] = 'B';
X		screen->gsets[2] = 'B';
X		screen->gsets[3] = 'B';
X		screen->curgl = 0;
X		screen->curgr = 2;
X		screen->curss = 0;
X		ClearScreen(screen);
X		screen->cursor_state = OFF;
X		if (term->flags & REVERSE_VIDEO)
X			ReverseVideo(term);
X
X		term->flags = term->initflags;
X		if(screen->c132 && (term->flags & IN132COLUMNS)) {
X		        Dimension junk;
X			XtMakeResizeRequest(
X			    (Widget) term,
X			    (Dimension) 80*FontWidth(screen)
X				+ 2 * screen->border + screen->scrollbar,
X			    (Dimension) FontHeight(screen)
X			        * (screen->max_row + 1) + 2 * screen->border,
X			    &junk, &junk);
X			XSync(screen->display, FALSE);	/* synchronize */
X			if(QLength(screen->display) > 0)
X				xevents();
X		}
X		CursorSet(screen, 0, 0, term->flags);
X	}
X	longjmp(vtjmpbuf, 1);	/* force ground state in parser */
X}
X
X
X
X/*
X * set_character_class - takes a string of the form
X * 
X *                 low[-high]:val[,low[-high]:val[...]]
X * 
X * and sets the indicated ranges to the indicated values.
X */
X
Xint set_character_class (s)
X    register char *s;
X{
X    register int i;			/* iterator, index into s */
X    int len;				/* length of s */
X    int acc;				/* accumulator */
X    int low, high;			/* bounds of range [0..127] */
X    int base;				/* 8, 10, 16 (octal, decimal, hex) */
X    int numbers;			/* count of numbers per range */
X    int digits;				/* count of digits in a number */
X    static char *errfmt = "%s:  %s in range string \"%s\" (position %d)\n";
X    extern char *ProgramName;
X
X    if (!s || !s[0]) return -1;
X
X    base = 10;				/* in case we ever add octal, hex */
X    low = high = -1;			/* out of range */
X
X    for (i = 0, len = strlen (s), acc = 0, numbers = digits = 0;
X	 i < len; i++) {
X	char c = s[i];
X
X	if (isspace(c)) {
X	    continue;
X	} else if (isdigit(c)) {
X	    acc = acc * base + (c - '0');
X	    digits++;
X	    continue;
X	} else if (c == '-') {
X	    low = acc;
X	    acc = 0;
X	    if (digits == 0) {
X		fprintf (stderr, errfmt, ProgramName, "missing number", s, i);
X		return (-1);
X	    }
X	    digits = 0;
X	    numbers++;
X	    continue;
X	} else if (c == ':') {
X	    if (numbers == 0)
X	      low = acc;
X	    else if (numbers == 1)
X	      high = acc;
X	    else {
X		fprintf (stderr, errfmt, ProgramName, "too many numbers",
X			 s, i);
X		return (-1);
X	    }
X	    digits = 0;
X	    numbers++;
X	    acc = 0;
X	    continue;
X	} else if (c == ',') {
X	    /*
X	     * now, process it
X	     */
X
X	    if (high < 0) {
X		high = low;
X		numbers++;
X	    }
X	    if (numbers != 2) {
X		fprintf (stderr, errfmt, ProgramName, "bad value number", 
X			 s, i);
X	    } else if (SetCharacterClassRange (low, high, acc) != 0) {
X		fprintf (stderr, errfmt, ProgramName, "bad range", s, i);
X	    }
X
X	    low = high = -1;
X	    acc = 0;
X	    digits = 0;
X	    numbers = 0;
X	    continue;
X	} else {
X	    fprintf (stderr, errfmt, ProgramName, "bad character", s, i);
X	    return (-1);
X	}				/* end if else if ... else */
X
X    }
X
X    if (low < 0 && high < 0) return (0);
X
X    /*
X     * now, process it
X     */
X
X    if (high < 0) high = low;
X    if (numbers < 1 || numbers > 2) {
X	fprintf (stderr, errfmt, ProgramName, "bad value number", s, i);
X    } else if (SetCharacterClassRange (low, high, acc) != 0) {
X	fprintf (stderr, errfmt, ProgramName, "bad range", s, i);
X    }
X
X    return (0);
X}
X
X/* ARGSUSED */
Xstatic void HandleKeymapChange(w, event, params, param_count)
X    Widget w;
X    XEvent *event;
X    String *params;
X    Cardinal *param_count;
X{
X    static XtTranslations keymap, original;
X    static XtResource resources[] = {
X	{ XtNtranslations, XtCTranslations, XtRTranslationTable,
X	      sizeof(XtTranslations), 0, XtRTranslationTable, (caddr_t)NULL}
X    };
X    char mapName[1000];
X    char mapClass[1000];
X
X    if (*param_count != 1) return;
X
X    if (original == NULL) original = w->core.tm.translations;
X
X    if (strcmp(params[0], "None") == 0) {
X	XtOverrideTranslations(w, original);
X	return;
X    }
X    (void) sprintf( mapName, "%sKeymap", params[0] );
X    (void) strcpy( mapClass, mapName );
X    if (islower(mapClass[0])) mapClass[0] = toupper(mapClass[0]);
X    XtGetSubresources( w, &keymap, mapName, mapClass,
X		       resources, (Cardinal)1, NULL, (Cardinal)0 );
X    if (keymap != NULL)
X	XtOverrideTranslations(w, keymap);
X}
X
X
X/* ARGSUSED */
Xstatic void HandleBell(w, event, params, param_count)
X    Widget w;
X    XEvent *event;		/* unused */
X    String *params;		/* [0] = volume */
X    Cardinal *param_count;	/* 0 or 1 */
X{
X    int percent = (*param_count) ? atoi(params[0]) : 0;
X
X    XBell( XtDisplay(w), percent );
X}
X
X
X/* ARGSUSED */
Xstatic void HandleIgnore(w, event, params, param_count)
X    Widget w;
X    XEvent *event;		/* unused */
X    String *params;		/* unused */
X    Cardinal *param_count;	/* unused */
X{
X    /* do nothing, but check for funny escape sequences */
X    (void) SendMousePosition(w, event);
X}
X
X
X/* ARGSUSED */
Xvoid DoSetSelectedFont(w, client_data, selection, type, value, length, format)
X    Widget w;
X    XtPointer client_data;
X    Atom *selection, *type;
X    XtPointer value;
X    unsigned long *length;
X    int *format;
X{
X    int len;
X    if (*type != XA_STRING || *format != 8) { Bell(); return; }
X    len = strlen(value);
X    if (len > 0) {
X	if (value[len-1] == '\n') value[len-1] = '\0';
X	if (!LoadNewFont (&term->screen, value, NULL, True, 
X			  fontMenu_fontescape))
X	  Bell();
X    }
X}
X
Xvoid FindFontSelection (atom_name, justprobe)
X    char *atom_name;
X    Bool justprobe;
X{
X    static AtomPtr *atoms;
X    static int atomCount = 0;
X    AtomPtr *pAtom;
X    int a;
X    Atom target;
X
X    if (!atom_name) atom_name = "PRIMARY";
X
X    for (pAtom = atoms, a = atomCount; a; a--, pAtom++) {
X	if (strcmp(atom_name, XmuNameOfAtom(*pAtom)) == 0) break;
X    }
X    if (!a) {
X	atoms = (AtomPtr*) XtRealloc (atoms, sizeof(AtomPtr)*(atomCount+1));
X	*(pAtom = &atoms[atomCount++]) = XmuMakeAtom(atom_name);
X    }
X
X    target = XmuInternAtom(XtDisplay(term), *pAtom);
X    if (justprobe) {
X	term->screen.menu_font_names[fontMenu_fontsel] = 
X	  XGetSelectionOwner(XtDisplay(term), target) ? _Font_Selected_ : NULL;
X    } else {
X	XtGetSelectionValue(term, target, XA_STRING,
X			    DoSetSelectedFont, NULL,
X			    XtLastTimestampProcessed(XtDisplay(term)));
X    }
X    return;
X}
X
X
X/* ARGSUSED */
Xvoid HandleSetFont(w, event, params, param_count)
X    Widget w;
X    XEvent *event;		/* unused */
X    String *params;		/* unused */
X    Cardinal *param_count;	/* unused */
X{
X    int fontnum;
X    char *name1 = NULL, *name2 = NULL;
X
X    if (*param_count == 0) {
X	fontnum = fontMenu_fontdefault;
X    } else {
X	int maxparams = 1;		/* total number of params allowed */
X
X	switch (params[0][0]) {
X	  case 'd': case 'D': case '0':
X	    fontnum = fontMenu_fontdefault; break;
X	  case '1':
X	    fontnum = fontMenu_font1; break;
X	  case '2':
X	    fontnum = fontMenu_font2; break;
X	  case '3':
X	    fontnum = fontMenu_font3; break;
X	  case '4':
X	    fontnum = fontMenu_font4; break;
X	  case 'e': case 'E':
X	    fontnum = fontMenu_fontescape; maxparams = 3; break;
X	  case 's': case 'S':
X	    fontnum = fontMenu_fontsel; maxparams = 2; break;
X	  default:
X	    Bell();
X	    return;
X	}
X	if (*param_count > maxparams) {	 /* see if extra args given */
X	    Bell();
X	    return;
X	}
X	switch (*param_count) {		/* assign 'em */
X	  case 3:
X	    name2 = params[2];
X	    /* fall through */
X	  case 2:
X	    name1 = params[1];
X	    break;
X	}
X    }
X
X    SetVTFont (fontnum, True, name1, name2);
X}
X
X
Xvoid SetVTFont (i, doresize, name1, name2)
X    int i;
X    Bool doresize;
X    char *name1, *name2;
X{
X    TScreen *screen = &term->screen;
X
X    if (i < 0 || i >= NMENUFONTS) {
X	Bell();
X	return;
X    }
X    if (i == fontMenu_fontsel) {	/* go get the selection */
X	FindFontSelection (name1, False);  /* name1 = atom, name2 is ignored */
X	return;
X    }
X    if (!name1) name1 = screen->menu_font_names[i];
X    if (!LoadNewFont(screen, name1, name2, doresize, i)) {
X	Bell();
X    }
X    return;
X}
X
X
Xint LoadNewFont (screen, nfontname, bfontname, doresize, fontnum)
X    TScreen *screen;
X    char *nfontname, *bfontname;
X    Bool doresize;
X    int fontnum;
X{
X    XFontStruct *nfs = NULL, *bfs = NULL;
X    XGCValues xgcv;
X    unsigned long mask;
X    GC new_normalGC = NULL, new_normalboldGC = NULL;
X    GC new_reverseGC = NULL, new_reverseboldGC = NULL;
X    char *tmpname = NULL;
X
X    if (!nfontname) return 0;
X
X    if (fontnum == fontMenu_fontescape &&
X	nfontname != screen->menu_font_names[fontnum]) {
X	tmpname = (char *) malloc (strlen(nfontname) + 1);
X	if (!tmpname) return 0;
X	strcpy (tmpname, nfontname);
X    }
X
X    if (!(nfs = XLoadQueryFont (screen->display, nfontname))) goto bad;
X
X    if (!(bfontname && 
X	  (bfs = XLoadQueryFont (screen->display, bfontname))))
X      bfs = nfs;
X
X    mask = (GCFont | GCForeground | GCBackground | GCGraphicsExposures |
X	    GCFunction);
X
X    xgcv.font = nfs->fid;
X    xgcv.foreground = screen->foreground;
X    xgcv.background = term->core.background_pixel;
X    xgcv.graphics_exposures = TRUE;	/* default */
X    xgcv.function = GXcopy;
X
X    new_normalGC = XtGetGC((Widget)term, mask, &xgcv);
X    if (!new_normalGC) goto bad;
X
X    if (nfs == bfs) {			/* there is no bold font */
X	new_normalboldGC = new_normalGC;
X    } else {
X	xgcv.font = bfs->fid;
X	new_normalboldGC = XtGetGC((Widget)term, mask, &xgcv);
X	if (!new_normalboldGC) goto bad;
X    }
X
X    xgcv.font = nfs->fid;
X    xgcv.foreground = term->core.background_pixel;
X    xgcv.background = screen->foreground;
X    new_reverseGC = XtGetGC((Widget)term, mask, &xgcv);
X    if (!new_reverseGC) goto bad;
X
X    if (nfs == bfs) {			/* there is no bold font */
X	new_reverseboldGC = new_reverseGC;
X    } else {
X	xgcv.font = bfs->fid;
X	new_reverseboldGC = XtGetGC((Widget)term, mask, &xgcv);
X	if (!new_reverseboldGC) goto bad;
X    }
X
X    XtReleaseGC ((Widget) term, screen->normalGC);
X    if (screen->normalGC != screen->normalboldGC)
X      XtReleaseGC ((Widget) term, screen->normalboldGC);
X    XtReleaseGC ((Widget) term, screen->reverseGC);
X    if (screen->reverseGC != screen->reverseboldGC)
X      XtReleaseGC ((Widget) term, screen->reverseboldGC);
X    screen->normalGC = new_normalGC;
X    screen->normalboldGC = new_normalboldGC;
X    screen->reverseGC = new_reverseGC;
X    screen->reverseboldGC = new_reverseboldGC;
X    screen->fnt_norm = nfs;
X    screen->fnt_bold = bfs;
X    screen->fnt_bold = screen->fnt_norm;
X    screen->enbolden = (nfs == bfs);
X    set_menu_font (False);
X    screen->menu_font_number = fontnum;
X    set_menu_font (True);
X    if (tmpname) {			/* if setting escape or sel */
X	if (screen->menu_font_names[fontnum])
X	  free (screen->menu_font_names[fontnum]);
X	screen->menu_font_names[fontnum] = tmpname;
X	if (fontnum == fontMenu_fontescape) {
X	    set_sensitivity (term->screen.fontMenu,
X			     fontMenuEntries[fontMenu_fontescape].widget,
X			     TRUE);
X	}
X    }
X    set_cursor_gcs (screen);
X    update_font_info (screen, doresize);
X    return 1;
X
X  bad:
X    if (tmpname) free (tmpname);
X    if (new_normalGC)
X      XtReleaseGC ((Widget) term, screen->normalGC);
X    if (new_normalGC && new_normalGC != new_normalboldGC)
X      XtReleaseGC ((Widget) term, new_normalboldGC);
X    if (new_reverseGC)
X      XtReleaseGC ((Widget) term, new_reverseGC);
X    if (new_reverseGC && new_reverseGC != new_reverseboldGC)
X      XtReleaseGC ((Widget) term, new_reverseboldGC);
X    if (nfs) XFreeFont (screen->display, nfs);
X    if (nfs && nfs != bfs) XFreeFont (screen->display, bfs);
X    return 0;
X}
X
X
Xupdate_font_info (screen, doresize)
X    TScreen *screen;
X    Bool doresize;
X{
X    int i, j, width, height, scrollbar_width;
X
X    screen->fullVwin.f_width = screen->fnt_norm->max_bounds.width;
X    screen->fullVwin.f_height = (screen->fnt_norm->ascent +
X				 screen->fnt_norm->descent);
X    scrollbar_width = (term->misc.scrollbar ? 
X		       screen->scrollWidget->core.width : 0);
X    i = 2 * screen->border + scrollbar_width;
X    j = 2 * screen->border;
X    width = (screen->max_col + 1) * screen->fullVwin.f_width + i;
X    height = (screen->max_row + 1) * screen->fullVwin.f_height + j;
X    screen->fullVwin.fullwidth = width;
X    screen->fullVwin.fullheight = height;
X    screen->fullVwin.width = width - i;
X    screen->fullVwin.height = height - j;
X
X    if (doresize) {
X	if (VWindow(screen)) {
X	    XClearWindow (screen->display, VWindow(screen));
X	}
X	DoResizeScreen (term);		/* set to the new natural size */
X	if (screen->scrollWidget)
X	  ResizeScrollBar (screen->scrollWidget, -1, -1,
X			   Height(screen) + screen->border * 2);
X	Redraw ();
X    }
X    set_vt_box (screen);
X}
X
Xset_vt_box (screen)
X	TScreen *screen;
X{
X	XPoint	*vp;
X
X	vp = &VTbox[1];
X	(vp++)->x = FontWidth(screen) - 1;
X	(vp++)->y = FontHeight(screen) - 1;
X	(vp++)->x = -(FontWidth(screen) - 1);
X	vp->y = -(FontHeight(screen) - 1);
X	screen->box = VTbox;
X}
X
X
Xset_cursor_gcs (screen)
X    TScreen *screen;
X{
X    XGCValues xgcv;
X    unsigned long mask;
X    unsigned long cc = screen->cursorcolor;
X    unsigned long fg = screen->foreground;
X    unsigned long bg = term->core.background_pixel;
X    GC new_cursorGC = NULL, new_reversecursorGC = NULL;
X    GC new_cursoroutlineGC = NULL;
X
X    /*
X     * Let's see, there are three things that have "color":
X     *
X     *     background
X     *     text
X     *     cursorblock
X     *
X     * And, there are four situation when drawing a cursor, if we decide
X     * that we like have a solid block of cursor color with the letter
X     * that it is highlighting shown in the background color to make it
X     * stand out:
X     *
X     *     selected window, normal video - background on cursor
X     *     selected window, reverse video - foreground on cursor
X     *     unselected window, normal video - foreground on background
X     *     unselected window, reverse video - background on foreground
X     *
X     * Since the last two are really just normalGC and reverseGC, we only
X     * need two new GC's.  Under monochrome, we get the same effect as
X     * above by setting cursor color to foreground.
X     */
X
X    xgcv.font = screen->fnt_norm->fid;
X    mask = (GCForeground | GCBackground | GCFont);
X    if (cc != fg && cc != bg) {
X	/* we have a colored cursor */
X	xgcv.foreground = fg;
X	xgcv.background = cc;
X	new_cursorGC = XtGetGC ((Widget) term, mask, &xgcv);
X
X	if (screen->always_highlight) {
X	    new_reversecursorGC = (GC) 0;
X	    new_cursoroutlineGC = (GC) 0;
X	} else {
X	    xgcv.foreground = bg;
X	    xgcv.background = cc;
X	    new_reversecursorGC = XtGetGC ((Widget) term, mask, &xgcv);
X	    xgcv.foreground = cc;
X	    xgcv.background = bg;
X	    new_cursoroutlineGC = XtGetGC ((Widget) term, mask, &xgcv);
X		}
X    } else {
X	new_cursorGC = (GC) 0;
X	new_reversecursorGC = (GC) 0;
X	new_cursoroutlineGC = (GC) 0;
X    }
X    if (screen->cursorGC) XtReleaseGC (term, screen->cursorGC);
X    if (screen->reversecursorGC) XtReleaseGC (term, screen->reversecursorGC);
X    if (screen->cursoroutlineGC) XtReleaseGC (term, screen->cursoroutlineGC);
X    screen->cursorGC = new_cursorGC;
X    screen->reversecursorGC = new_reversecursorGC;
X    screen->cursoroutlineGC = new_cursoroutlineGC;
X}
SHAR_EOF
chmod 0644 charproc.c || echo "restore of charproc.c fails"
if [ $TOUCH = can ]
then
    touch -am 1109132790 charproc.c
fi
fi
# ============= input.c ==============
if test -f input.c; then echo "File input.c exists"; else
sed 's/^X//' << 'SHAR_EOF' > input.c &&
X/*
X *	$XConsortium: input.c,v 1.8 89/12/10 20:44:48 jim Exp $
X */
X
X#ifndef lint
Xstatic char *rcsid_input_c = "$XConsortium: input.c,v 1.8 89/12/10 20:44:48 jim Exp $";
X#endif	/* lint */
X
X#include <X11/copyright.h>
X
X/*
X * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
X *
X *                         All Rights Reserved
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Digital Equipment
X * Corporation not be used in advertising or publicity pertaining to
X * distribution of the software without specific, written prior permission.
X *
X *
X * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
X * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
X * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
X * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
X * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
X * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
X * SOFTWARE.
X */
X
X/* input.c */
X
X#ifndef lint
Xstatic char rcs_id[] = "$XConsortium: input.c,v 1.8 89/12/10 20:44:48 jim Exp $";
X#endif	/* lint */
X
X#include <X11/Xlib.h>
X#include <X11/keysym.h>
X#include "DECkeysym.h"
X
X#include <X11/Intrinsic.h>
X#include <X11/Xutil.h>
X#include <stdio.h>
X#include "ptyx.h"
X
Xstatic XComposeStatus compose_status = {NULL, 0};
Xstatic char *kypd_num = " XXXXXXXX\tXXX\rXXXxxxxXXXXXXXXXXXXXXXXXXXXX*+,-.\\0123456789XXX=";
Xstatic char *kypd_apl = " ABCDEFGHIJKLMNOPQRSTUVWXYZ??????abcdefghijklmnopqrstuvwxyzXXX";
Xstatic char *cur = "DACB";
X
Xstatic int funcvalue(), sunfuncvalue();
Xextern Boolean sunFunctionKeys;
X
Xvoid
XAdjustAfterInput (screen)
Xregister TScreen *screen;
X{
X	if(screen->scrollkey && screen->topline != 0)
X		WindowScroll(screen, 0);
X	if(screen->marginbell) {
X		int col = screen->max_col - screen->nmarginbell;
X		if(screen->bellarmed >= 0) {
X			if(screen->bellarmed == screen->cur_row) {
X				if(screen->cur_col >= col) {
X					if(screen->cur_col == col)
X						Bell();
X					screen->bellarmed = -1;
X				}
X			} else
X				screen->bellarmed = screen->cur_col <
X				 col ? screen->cur_row : -1;
X		} else if(screen->cur_col < col)
X			screen->bellarmed = screen->cur_row;
X	}
X}
X
XInput (keyboard, screen, event, eightbit)
Xregister TKeyboard	*keyboard;
Xregister TScreen		*screen;
Xregister XKeyPressedEvent *event;
XBool eightbit;
X{
X
X#define STRBUFSIZE 100
X
X	 char strbuf[STRBUFSIZE];
X	register char *string;
X	register int key = FALSE;
X	int	pty	= screen->respond;
X	int	nbytes;
X	KeySym  keysym;
X	ANSI	reply;
X
X	nbytes = XLookupString ((XKeyEvent *)event, strbuf, STRBUFSIZE, 
X		&keysym, &compose_status);
X
X	string = &strbuf[0];
X	reply.a_pintro = 0;
X	reply.a_final = 0;
X	reply.a_nparam = 0;
X	reply.a_inters = 0;
X
X	if (IsPFKey(keysym)) {
X		reply.a_type = SS3;
X		unparseseq(&reply, pty);
X		unparseputc((char)(keysym-XK_KP_F1+'P'), pty);
X		key = TRUE;
X	} else if (IsKeypadKey(keysym)) {
X	  	if (keyboard->flags & KYPD_APL)	{
X			reply.a_type   = SS3;
X			unparseseq(&reply, pty);
X			unparseputc(kypd_apl[keysym-XK_KP_Space], pty);
X		} else
X			unparseputc(kypd_num[keysym-XK_KP_Space], pty);
X		key = TRUE;
X        } else if (IsCursorKey(keysym) &&
X        	keysym != XK_Prior && keysym != XK_Next) {
X       		if (keyboard->flags & CURSOR_APL) {
X			reply.a_type = SS3;
X			unparseseq(&reply, pty);
X			unparseputc(cur[keysym-XK_Left], pty);
X		} else {
X			reply.a_type = CSI;
X			reply.a_final = cur[keysym-XK_Left];
X			unparseseq(&reply, pty);
X		}
X		key = TRUE;
X	 } else if (IsFunctionKey(keysym) || IsMiscFunctionKey(keysym) ||
X	 	keysym == XK_Prior || keysym == XK_Next ||
X	 	keysym == DXK_Remove) {
X		reply.a_type = CSI;
X		reply.a_nparam = 1;
X		if (sunFunctionKeys) {
X		    reply.a_param[0] = sunfuncvalue (keysym);
X		    reply.a_final = 'z';
X		} else {
X		    reply.a_param[0] = funcvalue (keysym);
X		    reply.a_final = '~';
X		}
X		if (reply.a_param[0] > 0)
X			unparseseq(&reply, pty);
X		key = TRUE;
X	} else if (nbytes > 0) {
X		if(screen->TekGIN) {
X			TekEnqMouse(*string++);
X			TekGINoff();
X			nbytes--;
X		}
X		if ((nbytes == 1) && eightbit) {
X		    if (screen->eight_bits)
X		      *string |= 0x80;	/* turn on eighth bit */
X		    else
X		      unparseputc (033, pty);  /* escape */
X		}
X		while (nbytes-- > 0)
X			unparseputc(*string++, pty);
X		key = TRUE;
X	}
X	if(key && !screen->TekEmu)
X	        AdjustAfterInput(screen);
X#ifdef ENABLE_PRINT
X	if (keysym == XK_F2) TekPrint();
X#endif
X	return;
X}
X
XStringInput (screen, string)
Xregister TScreen	*screen;
Xregister char *string;
X{
X	int	pty	= screen->respond;
X	int	nbytes;
X
X	nbytes = strlen(string);
X	if(nbytes && screen->TekGIN) {
X		TekEnqMouse(*string++);
X		TekGINoff();
X		nbytes--;
X	}
X	while (nbytes-- > 0)
X		unparseputc(*string++, pty);
X	if(!screen->TekEmu)
X	        AdjustAfterInput(screen);
X}
X
Xstatic int funcvalue (keycode)
X	int keycode;
X{
X	switch (keycode) {
X		case XK_F1:	return(11);
X		case XK_F2:	return(12);
X		case XK_F3:	return(13);
X		case XK_F4:	return(14);
X		case XK_F5:	return(15);
X		case XK_F6:	return(17);
X		case XK_F7:	return(18);
X		case XK_F8:	return(19);
X		case XK_F9:	return(20);
X		case XK_F10:	return(21);
X		case XK_F11:	return(23);
X		case XK_F12:	return(24);
X		case XK_F13:	return(25);
X		case XK_F14:	return(26);
X		case XK_F15:	return(28);
X		case XK_Help:	return(28);
X		case XK_F16:	return(29);
X		case XK_Menu:	return(29);
X		case XK_F17:	return(31);
X		case XK_F18:	return(32);
X		case XK_F19:	return(33);
X		case XK_F20:	return(34);
X
X		case XK_Find :	return(1);
X		case XK_Insert:	return(2);
X		case XK_Delete:	return(3);
X		case DXK_Remove: return(3);
X		case XK_Select:	return(4);
X		case XK_Prior:	return(5);
X		case XK_Next:	return(6);
X		default:	return(-1);
X	}
X}
X
X
Xstatic int sunfuncvalue (keycode)
X	int keycode;
X  {
X  	switch (keycode) {
X		case XK_F1:	return(224);
X		case XK_F2:	return(225);
X		case XK_F3:	return(226);
X		case XK_F4:	return(227);
X		case XK_F5:	return(228);
X		case XK_F6:	return(229);
X		case XK_F7:	return(230);
X		case XK_F8:	return(231);
X		case XK_F9:	return(232);
X		case XK_F10:	return(233);
X		case XK_F11:	return(192);
X		case XK_F12:	return(193);
X		case XK_F13:	return(194);
X		case XK_F14:	return(195);
X		case XK_F15:	return(196);
X		case XK_Help:	return(196);
X		case XK_F16:	return(197);
X		case XK_Menu:	return(197);
X		case XK_F17:	return(198);
X		case XK_F18:	return(199);
X		case XK_F19:	return(200);
X		case XK_F20:	return(201);
X
X		case XK_R1:	return(208);
X		case XK_R2:	return(209);
X		case XK_R3:	return(210);
X		case XK_R4:	return(211);
X		case XK_R5:	return(212);
X		case XK_R6:	return(213);
X		case XK_R7:	return(214);
X		case XK_R8:	return(215);
X		case XK_R9:	return(216);
X		case XK_R10:	return(217);
X		case XK_R11:	return(218);
X		case XK_R12:	return(219);
X		case XK_R13:	return(220);
X		case XK_R14:	return(221);
X		case XK_R15:	return(222);
X  
X		case XK_Find :	return(1);
X		case XK_Insert:	return(2);
X		case XK_Delete:	return(3);
X		case DXK_Remove: return(3);
X		case XK_Select:	return(4);
X		case XK_Prior:	return(5);
X		case XK_Next:	return(6);
X		default:	return(-1);
X	}
X}
X
SHAR_EOF
chmod 0644 input.c || echo "restore of input.c fails"
if [ $TOUCH = can ]
then
    touch -am 1109132790 input.c
fi
fi
# ============= main.c ==============
if test -f main.c; then echo "File main.c exists"; else
sed 's/^X//' << 'SHAR_EOF' > main.c &&
X#ifndef lint
Xstatic char rcs_id[] = "$XConsortium: main.c,v 1.145 90/01/11 14:22:31 jim Exp $";
X#endif	/* lint */
X
X/*
X * 				 W A R N I N G
X * 
X * If you think you know what all of this code is doing, you are probably
X * very mistaken.  There be serious and nasty dragons here.
X *
X * This client is *not* to be taken as an example of how to write X Toolkit
X * applications.  It is in need of a substantial rewrite, ideally to create
X * a generic tty widget with several different parsing widgets so that you 
X * can plug 'em together any way you want.  Don't hold your breath, though....
X */
X
X#include <X11/copyright.h>
X
X/***********************************************************
XCopyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
Xand the Massachusetts Institute of Technology, Cambridge, Massachusetts.
X
X                        All Rights Reserved
X
XPermission to use, copy, modify, and distribute this software and its 
Xdocumentation for any purpose and without fee is hereby granted, 
Xprovided that the above copyright notice appear in all copies and that
Xboth that copyright notice and this permission notice appear in 
Xsupporting documentation, and that the names of Digital or MIT not be
Xused in advertising or publicity pertaining to distribution of the
Xsoftware without specific, written prior permission.  
X
XDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
XALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
XDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
XANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
XWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
XARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
XSOFTWARE.
X
X******************************************************************/
X
X
X/* main.c */
X
X#include <X11/Xos.h>
X#include <X11/Xlib.h>
X#include <X11/cursorfont.h>
X#include <pwd.h>
X#include <ctype.h>
X
X#ifdef att
X#define USE_USG_PTYS
X#endif
X
X#ifndef att
X#define USE_HANDSHAKE
X#endif
X
X#include <sys/ioctl.h>
X
X#ifdef AIXV3
X#include <sys/termio.h>
X#endif /* AIXV3 */
X
X#ifdef SYSV
X#include <sys/termio.h>
X#ifdef USE_USG_PTYS			/* AT&T SYSV has no ptyio.h */
X#include <sys/stream.h>			/* get typedef used in ptem.h */
X#include <sys/ptem.h>			/* get struct winsize */
X#include <sys/stropts.h>		/* for I_PUSH */
X#include <poll.h>			/* for POLLIN */
X#endif
X#include <sys/stat.h>
X#define USE_SYSV_TERMIO
X#define USE_SYSV_SIGNALS
X#define	USE_SYSV_PGRP
X#define USE_SYSV_ENVVARS		/* COLUMNS/LINES vs. TERMCAP */
X/*
X * now get system-specific includes
X */
X#ifdef CRAY
X#define HAS_UTMP_UT_HOST
X#define HAS_BSD_GROUPS
X#endif
X#ifdef macII
X#define HAS_UTMP_UT_HOST
X#define HAS_BSD_GROUPS
X#include <sys/ttychars.h>
X#undef USE_SYSV_ENVVARS
X#undef FIOCLEX
X#undef FIONCLEX
X#define setpgrp2 setpgrp
X#include <sgtty.h>
X#include <sys/resource.h>
X#endif
X#ifdef hpux
X#define HAS_BSD_GROUPS
X#include <sys/ptyio.h>
X#endif
X#endif /* SYSV */
X
X#ifndef SYSV				/* BSD systems */
X#include <sgtty.h>
X#include <sys/resource.h>
X#define HAS_UTMP_UT_HOST
X#define HAS_BSD_GROUPS
X#endif	/* !SYSV */
X
X#include <stdio.h>
X#include <errno.h>
X#include <setjmp.h>
X
X#ifdef hpux
X#include <sys/utsname.h>
X#endif /* hpux */
X
X#ifdef apollo
X#define ttyslot() 1
X#endif /* apollo */
X
X#include <utmp.h>
X#ifdef LASTLOG
X#include <lastlog.h>
X#endif
X#include <sys/param.h>	/* for NOFILE */
X
X#ifdef  PUCC_PTYD
X#include <local/openpty.h>
Xint	Ptyfd;
X#endif /* PUCC_PTYD */
X
X#ifndef UTMP_FILENAME
X#define UTMP_FILENAME "/etc/utmp"
X#endif
X#ifndef LASTLOG_FILENAME
X#define LASTLOG_FILENAME "/usr/adm/lastlog"  /* only on BSD systems */
X#endif
X#ifndef WTMP_FILENAME
X#if defined(SYSV)
X#define WTMP_FILENAME "/etc/wtmp"
X#else
X#define WTMP_FILENAME "/usr/adm/wtmp"
X#endif
X#endif
X
X#include "ptyx.h"
X#include "data.h"
X#include "error.h"
X#include "main.h"
X#include "menu.h"
X#include <X11/StringDefs.h>
X#include <X11/Shell.h>
X#ifdef SIGTSTP
X#include <sys/wait.h>
X#ifdef hpux
X#include <sys/bsdtty.h>
X#endif
X#endif
X
X#ifdef SIGNALRETURNSINT
X#define SIGNAL_T int
X#define SIGNAL_RETURN return 0
X#else
X#define SIGNAL_T void
X#define SIGNAL_RETURN return
X#endif
X
XSIGNAL_T Exit();
Xextern char *malloc();
Xextern char *calloc();
Xextern char *realloc();
Xextern char *ttyname();
Xextern char *getenv();
Xextern char *strindex ();
Xextern void exit();
Xextern void sleep();
Xextern void bcopy();
Xextern long lseek();
Xextern void HandlePopupMenu();
X
Xint switchfb[] = {0, 2, 1, 3};
X
Xstatic SIGNAL_T reapchild ();
X
Xstatic Bool added_utmp_entry = False;
X
Xstatic char **command_to_exec;
X
X#ifdef USE_SYSV_TERMIO
X/* The following structures are initialized in main() in order
X** to eliminate any assumptions about the internal order of their
X** contents.
X*/
Xstatic struct termio d_tio;
X#ifdef TIOCSLTC
Xstatic struct ltchars d_ltc;
X#endif	/* TIOCSLTC */
X#ifdef TIOCLSET
Xstatic unsigned int d_lmode;
X#endif	/* TIOCLSET */
X#else /* not USE_SYSV_TERMIO */
X
X#ifdef AIXV3
X
Xstatic struct termios   terminal_modes;
X
X#else /* not AIXV3 */
X
Xstatic struct  sgttyb d_sg = {
X        0, 0, 0177, CKILL, EVENP|ODDP|ECHO|XTABS|CRMOD
X};
Xstatic struct  tchars d_tc = {
X        CINTR, CQUIT, CSTART,
X        CSTOP, CEOF, CBRK,
X};
Xstatic struct  ltchars d_ltc = {
X        CSUSP, CDSUSP, CRPRNT,
X        CFLUSH, CWERASE, CLNEXT
X};
Xstatic int d_disipline = NTTYDISC;
Xstatic long int d_lmode = LCRTBS|LCRTERA|LCRTKIL|LCTLECH;
X
X#endif /* AIXV3 */
X
X#endif /* USE_SYSV_TERMIO */
X
Xstatic int parse_tty_modes ();
X/*
X * SYSV has the termio.c_cc[V] and ltchars; BSD has tchars and ltchars
X */
Xstatic int override_tty_modes = 0;
Xstruct _xttymodes {
X    char *name;
X    int len;
X    int set;
X    char value;
X} ttymodelist[] = {
X{ "intr", 4, 0, '\0' },			/* tchars.t_intrc ; VINTR */
X#define XTTYMODE_intr 0
X{ "quit", 4, 0, '\0' },			/* tchars.t_quitc ; VQUIT */
X#define XTTYMODE_quit 1
X{ "erase", 5, 0, '\0' },		/* sgttyb.sg_erase ; VERASE */
X#define XTTYMODE_erase 2
X{ "kill", 4, 0, '\0' },			/* sgttyb.sg_kill ; VKILL */
X#define XTTYMODE_kill 3
X{ "eof", 3, 0, '\0' },			/* tchars.t_eofc ; VEOF */
X#define XTTYMODE_eof 4
X{ "eol", 3, 0, '\0' },			/* VEOL */
X#define XTTYMODE_eol 5
X{ "swtch", 5, 0, '\0' },		/* VSWTCH */
X#define XTTYMODE_swtch 6
X{ "start", 5, 0, '\0' },		/* tchars.t_startc */
X#define XTTYMODE_start 7
X{ "stop", 4, 0, '\0' },			/* tchars.t_stopc */
X#define XTTYMODE_stop 8
X{ "brk", 3, 0, '\0' },			/* tchars.t_brkc */
X#define XTTYMODE_brk 9
X{ "susp", 4, 0, '\0' },			/* ltchars.t_suspc */
X#define XTTYMODE_susp 10
X{ "dsusp", 5, 0, '\0' },		/* ltchars.t_dsuspc */
X#define XTTYMODE_dsusp 11
X{ "rprnt", 5, 0, '\0' },		/* ltchars.t_rprntc */
X#define XTTYMODE_rprnt 12
X{ "flush", 5, 0, '\0' },		/* ltchars.t_flushc */
X#define XTTYMODE_flush 13
X{ "weras", 5, 0, '\0' },		/* ltchars.t_werasc */
X#define XTTYMODE_weras 14
X{ "lnext", 5, 0, '\0' },		/* ltchars.t_lnextc */
X#define XTTYMODE_lnext 15
X#define NXTTYMODES 16
X};
X
X#ifdef USE_SYSV_UTMP
Xextern struct utmp *getutent();
Xextern struct utmp *getutid();
Xextern struct utmp *getutline();
Xextern void pututline();
Xextern void setutent();
Xextern void endutent();
Xextern void utmpname();
X
Xextern struct passwd *getpwent();
Xextern struct passwd *getpwuid();
Xextern struct passwd *getpwnam();
Xextern void setpwent();
Xextern void endpwent();
Xextern struct passwd *fgetpwent();
X#else	/* not USE_SYSV_UTMP */
Xstatic char etc_utmp[] = UTMP_FILENAME;
X#ifdef LASTLOG
Xstatic char etc_lastlog[] = LASTLOG_FILENAME;
X#endif 
X#ifdef WTMP
Xstatic char etc_wtmp[] = WTMP_FILENAME;
X#endif
X#endif	/* USE_SYSV_UTMP */
X
X/*
X * Some people with 4.3bsd /bin/login seem to like to use login -p -f user
X * to implement xterm -ls.  They can turn on USE_LOGIN_DASH_P and turn off
X * WTMP and LASTLOG.
X */
X#ifdef USE_LOGIN_DASH_P
X#ifndef LOGIN_FILENAME
X#define LOGIN_FILENAME "/bin/login"
X#endif
Xstatic char bin_login[] = LOGIN_FILENAME;
X#endif
X
Xstatic int inhibit;
Xstatic char passedPty[2];	/* name if pty if slave */
X
X#ifdef TIOCCONS
Xstatic int Console;
X#endif	/* TIOCCONS */
X#ifndef USE_SYSV_UTMP
Xstatic int tslot;
X#endif	/* USE_SYSV_UTMP */
Xstatic jmp_buf env;
X
Xchar *ProgramName;
XBoolean sunFunctionKeys;
X
X#ifdef AIXV3
X
X#ifndef CTRL
X#define CTRL(c)		('c'&0x1f)
X#endif
X
Xstatic void
Xset_default_terminal_modes()
X{
X	int  i;
X
X	terminal_modes.c_iflag = (BRKINT|ICRNL|IXON|IXOFF|IMAXBEL);
X	terminal_modes.c_oflag = (OPOST|ONLCR|TAB3);
X	terminal_modes.c_cflag = (CS8|CREAD|HUPCL|B9600);
X	terminal_modes.c_lflag = (ISIG|ICANON|ECHO|ECHOE|ECHOK|IEXTEN|ECHOKE|ECHOCTL);
X	for(i=0; i< NCCS; i++){
X	    terminal_modes.c_cc[i] = 0;
X	}
X	terminal_modes.c_cc[VINTR] = CTRL(c);
X	terminal_modes.c_cc[VQUIT] = CTRL(\\);
X	terminal_modes.c_cc[VERASE] = CTRL(h);
X	terminal_modes.c_cc[VKILL] = CTRL(u);
X	terminal_modes.c_cc[VEOF] = CTRL(d);
X	terminal_modes.c_cc[VEOL] = CTRL(@);
X	terminal_modes.c_cc[VEOL2] = CTRL(@);
X	terminal_modes.c_cc[VSTRT] = CTRL(q);
X	terminal_modes.c_cc[VSTOP] = CTRL(s);
X	terminal_modes.c_cc[VSUSP] = CTRL(z);
X	terminal_modes.c_cc[VDSUSP] = CTRL(y);
X	terminal_modes.c_cc[VREPRINT] = CTRL(r);
X	terminal_modes.c_cc[VDISCRD] = CTRL(o);
X	terminal_modes.c_cc[VWERSE] = CTRL(w);
X	terminal_modes.c_cc[VLNEXT] = CTRL(v);
X}
X
Xstatic void
Xget_tty_info(ttyfd)
X    int  ttyfd;
X{
X    if( tcgetattr(ttyfd, &terminal_modes) < 0 ){
X	/* it failed, punt */
X	set_default_terminal_modes();
X    }
X}
X
Xstatic void
Xset_tty_info(ttyfd)
X    int  ttyfd;
X{
X    ioctl(ttyfd,TXADDCD,"posix");
X    if( tcsetattr(ttyfd, TCSANOW, &terminal_modes) < 0 ){
X	/* failed, punt */
X	exit(0);
X    }
X}
X#endif /* AIXV3 */
X
Xstatic struct _resource {
X    char *xterm_name;
X    char *icon_geometry;
X    char *title;
X    char *icon_name;
X    char *term_name;
X    char *tty_modes;
X    Boolean utmpInhibit;
X    Boolean sunFunctionKeys;	/* %%% should be widget resource? */
X    Boolean wait_for_map;
X} resource;
X
X/* used by VT (charproc.c) */
X
X#define offset(field)	XtOffset(struct _resource *, field)
X
Xstatic XtResource application_resources[] = {
X    {"name", "Name", XtRString, sizeof(char *),
X	offset(xterm_name), XtRString, "xterm"},
X    {"iconGeometry", "IconGeometry", XtRString, sizeof(char *),
X	offset(icon_geometry), XtRString, (caddr_t) NULL},
X    {XtNtitle, XtCTitle, XtRString, sizeof(char *),
X	offset(title), XtRString, (caddr_t) NULL},
X    {XtNiconName, XtCIconName, XtRString, sizeof(char *),
X	offset(icon_name), XtRString, (caddr_t) NULL},
X    {"termName", "TermName", XtRString, sizeof(char *),
X	offset(term_name), XtRString, (caddr_t) NULL},
X    {"ttyModes", "TtyModes", XtRString, sizeof(char *),
X	offset(tty_modes), XtRString, (caddr_t) NULL},
X    {"utmpInhibit", "UtmpInhibit", XtRBoolean, sizeof (Boolean),
X	offset(utmpInhibit), XtRString, "false"},
X    {"sunFunctionKeys", "SunFunctionKeys", XtRBoolean, sizeof (Boolean),
X	offset(sunFunctionKeys), XtRString, "false"},
X    {"waitForMap", "WaitForMap", XtRBoolean, sizeof (Boolean),
X        offset(wait_for_map), XtRString, "false"},
X};
X#undef offset
X
X/* Command line options table.  Only resources are entered here...there is a
X   pass over the remaining options after XtParseCommand is let loose. */
X
Xstatic char *fallback_resources[] = {
X    "XTerm*SimpleMenu*menuLabel.vertSpace: 100",
X    "XTerm*SimpleMenu*HorizontalMargins: 16",
X    "XTerm*SimpleMenu*Sme.height: 16",
X    "XTerm*SimpleMenu*Cursor: left_ptr",
X    "XTerm*mainMenu.Label:  Main Options (no app-defaults)",
X    "XTerm*vtMenu.Label:  VT Options (no app-defaults)",
X    "XTerm*fontMenu.Label:  VT Fonts (no app-defaults)",
X    "XTerm*tekMenu.Label:  Tek Options (no app-defaults)",
X    NULL
X};
X
Xstatic XrmOptionDescRec optionDescList[] = {
X{"-geometry",	"*vt100.geometry",XrmoptionSepArg,	(caddr_t) NULL},
X{"-132",	"*c132",	XrmoptionNoArg,		(caddr_t) "on"},
X{"+132",	"*c132",	XrmoptionNoArg,		(caddr_t) "off"},
X{"-ah",		"*alwaysHighlight", XrmoptionNoArg,	(caddr_t) "on"},
X{"+ah",		"*alwaysHighlight", XrmoptionNoArg,	(caddr_t) "off"},
X{"-b",		"*internalBorder",XrmoptionSepArg,	(caddr_t) NULL},
X{"-cb",		"*cutToBeginningOfLine", XrmoptionNoArg, (caddr_t) "off"},
X{"+cb",		"*cutToBeginningOfLine", XrmoptionNoArg, (caddr_t) "on"},
X{"-cc",		"*charClass",	XrmoptionSepArg,	(caddr_t) NULL},
X{"-cn",		"*cutNewline",	XrmoptionNoArg,		(caddr_t) "off"},
X{"+cn",		"*cutNewline",	XrmoptionNoArg,		(caddr_t) "on"},
X{"-cr",		"*cursorColor",	XrmoptionSepArg,	(caddr_t) NULL},
X{"-cu",		"*curses",	XrmoptionNoArg,		(caddr_t) "on"},
X{"+cu",		"*curses",	XrmoptionNoArg,		(caddr_t) "off"},
X{"-e",		NULL,		XrmoptionSkipLine,	(caddr_t) NULL},
X{"-fb",		"*boldFont",	XrmoptionSepArg,	(caddr_t) NULL},
X{"-j",		"*jumpScroll",	XrmoptionNoArg,		(caddr_t) "on"},
X{"+j",		"*jumpScroll",	XrmoptionNoArg,		(caddr_t) "off"},
X{"-l",		"*logging",	XrmoptionNoArg,		(caddr_t) "on"},
X{"+l",		"*logging",	XrmoptionNoArg,		(caddr_t) "off"},
X{"-lf",		"*logFile",	XrmoptionSepArg,	(caddr_t) NULL},
X{"-ls",		"*loginShell",	XrmoptionNoArg,		(caddr_t) "on"},
X{"+ls",		"*loginShell",	XrmoptionNoArg,		(caddr_t) "off"},
X{"-mb",		"*marginBell",	XrmoptionNoArg,		(caddr_t) "on"},
X{"+mb",		"*marginBell",	XrmoptionNoArg,		(caddr_t) "off"},
X{"-mc",		"*multiClickTime", XrmoptionSepArg,	(caddr_t) NULL},
X{"-ms",		"*pointerColor",XrmoptionSepArg,	(caddr_t) NULL},
X{"-nb",		"*nMarginBell",	XrmoptionSepArg,	(caddr_t) NULL},
X{"-rw",		"*reverseWrap",	XrmoptionNoArg,		(caddr_t) "on"},
X{"+rw",		"*reverseWrap",	XrmoptionNoArg,		(caddr_t) "off"},
X{"-s",		"*multiScroll",	XrmoptionNoArg,		(caddr_t) "on"},
X{"+s",		"*multiScroll",	XrmoptionNoArg,		(caddr_t) "off"},
X{"-sb",		"*scrollBar",	XrmoptionNoArg,		(caddr_t) "on"},
X{"+sb",		"*scrollBar",	XrmoptionNoArg,		(caddr_t) "off"},
X{"-sf",		"*sunFunctionKeys", XrmoptionNoArg,	(caddr_t) "on"},
X{"+sf",		"*sunFunctionKeys", XrmoptionNoArg,	(caddr_t) "off"},
X{"-si",		"*scrollTtyOutput",	XrmoptionNoArg,		(caddr_t) "off"},
X{"+si",		"*scrollTtyOutput",	XrmoptionNoArg,		(caddr_t) "on"},
X{"-sk",		"*scrollKey",	XrmoptionNoArg,		(caddr_t) "on"},
X{"+sk",		"*scrollKey",	XrmoptionNoArg,		(caddr_t) "off"},
X{"-sl",		"*saveLines",	XrmoptionSepArg,	(caddr_t) NULL},
X{"-t",		"*tekStartup",	XrmoptionNoArg,		(caddr_t) "on"},
X{"+t",		"*tekStartup",	XrmoptionNoArg,		(caddr_t) "off"},
X{"-tm",		"*ttyModes",	XrmoptionSepArg,	(caddr_t) NULL},
X{"-tn",		"*termName",	XrmoptionSepArg,	(caddr_t) NULL},
X{"-ut",		"*utmpInhibit",	XrmoptionNoArg,		(caddr_t) "on"},
X{"+ut",		"*utmpInhibit",	XrmoptionNoArg,		(caddr_t) "off"},
X{"-vb",		"*visualBell",	XrmoptionNoArg,		(caddr_t) "on"},
X{"+vb",		"*visualBell",	XrmoptionNoArg,		(caddr_t) "off"},
X{"-wf",		"*waitForMap",	XrmoptionNoArg,		(caddr_t) "on"},
X{"+wf",		"*waitForMap",	XrmoptionNoArg,		(caddr_t) "off"},
X/* bogus old compatibility stuff for which there are
X   standard XtInitialize options now */
X{"%",		"*tekGeometry",	XrmoptionStickyArg,	(caddr_t) NULL},
X{"#",		".iconGeometry",XrmoptionStickyArg,	(caddr_t) NULL},
X{"-T",		"*title",	XrmoptionSepArg,	(caddr_t) NULL},
X{"-n",		"*iconName",	XrmoptionSepArg,	(caddr_t) NULL},
X{"-r",		"*reverseVideo",XrmoptionNoArg,		(caddr_t) "on"},
X{"+r",		"*reverseVideo",XrmoptionNoArg,		(caddr_t) "off"},
X{"-rv",		"*reverseVideo",XrmoptionNoArg,		(caddr_t) "on"},
X{"+rv",		"*reverseVideo",XrmoptionNoArg,		(caddr_t) "off"},
X{"-w",		".borderWidth", XrmoptionSepArg,	(caddr_t) NULL},
X};
X
Xstatic struct _options {
X  char *opt;
X  char *desc;
X} options[] = {
X{ "-help",                 "print out this message" },
X{ "-display displayname",  "X server to contact" },
X{ "-geometry geom",        "size (in characters) and position" },
X{ "-/+rv",                 "turn on/off reverse video" },
X{ "-bg color",             "background color" },
X{ "-fg color",             "foreground color" },
X{ "-bd color",             "border color" },
X{ "-bw number",            "border width in pixels" },
X{ "-fn fontname",          "normal text font" },
X{ "-iconic",               "start iconic" },
X{ "-name string",          "client instance, icon, and title strings" },
X{ "-title string",         "title string" },
X{ "-xrm resourcestring",   "additional resource specifications" },
X{ "-/+132",                "turn on/off column switch inhibiting" },
X{ "-/+ah",                 "turn on/off always highlight" },
X{ "-b number",             "internal border in pixels" },
X{ "-/+cb",                 "turn on/off cut-to-beginning-of-line inhibit" },
X{ "-cc classrange",        "specify additional character classes" },
X{ "-/+cn",                 "turn on/off cut newline inhibit" },
X{ "-cr color",             "text cursor color" },
X{ "-/+cu",                 "turn on/off curses emulation" },
X{ "-fb fontname",          "bold text font" },
X{ "-/+j",                  "turn on/off jump scroll" },
X{ "-/+l",                  "turn on/off logging" },
X{ "-lf filename",          "logging filename" },
X{ "-/+ls",                 "turn on/off login shell" },
X{ "-/+mb",                 "turn on/off margin bell" },
X{ "-mc milliseconds",      "multiclick time in milliseconds" },
X{ "-ms color",             "pointer color" },
X{ "-nb number",            "margin bell in characters from right end" },
X{ "-/+rw",                 "turn on/off reverse wraparound" },
X{ "-/+s",                  "turn on/off multiscroll" },
X{ "-/+sb",                 "turn on/off scrollbar" },
X{ "-/+sf",                 "turn on/off Sun Function Key escape codes" },
X{ "-/+si",                 "turn on/off scroll-on-tty-output inhibit" },
X{ "-/+sk",                 "turn on/off scroll-on-keypress" },
X{ "-sl number",            "number of scrolled lines to save" },
X{ "-/+t",                  "turn on/off Tek emulation window" },
X{ "-tm string",            "terminal mode keywords and characters" },
X{ "-tn name",              "TERM environment variable name" },
X{ "-/+ut",                 "turn on/off utmp inhibit" },
X{ "-/+vb",                 "turn on/off visual bell" },
X{ "-e command args",       "command to execute" },
X{ "%geom",                 "Tek window geometry" },
X{ "#geom",                 "icon window geometry" },
X{ "-T string",             "title name for window" },
X{ "-n string",             "icon name for window" },
X{ "-C",                    "intercept console messages, if supported" },
X{ "-Sxxd",                 "slave mode on \"ttyxx\", file descriptor \"d\"" },
X{ NULL, NULL }};
X
Xstatic char *message[] = {
X"Fonts must be fixed width and, if both normal and bold are specified, must",
X"have the same size.  If only a normal font is specified, it will be used for",
X"both normal and bold text (by doing overstriking).  The -e option, if given,",
X"must be appear at the end of the command line, otherwise the user's default",
X"shell will be started.  Options that start with a plus sign (+) restore the",
X"default.",
XNULL};
X
Xstatic void Syntax (badOption)
X    char *badOption;
X{
X    struct _options *opt;
X    int col;
X
X    fprintf (stderr, "%s:  bad command line option \"%s\"\r\n\n",
X	     ProgramName, badOption);
X
X    fprintf (stderr, "usage:  %s", ProgramName);
X    col = 8 + strlen(ProgramName);
X    for (opt = options; opt->opt; opt++) {
X	int len = 3 + strlen(opt->opt);	 /* space [ string ] */
X	if (col + len > 79) {
X	    fprintf (stderr, "\r\n   ");  /* 3 spaces */
X	    col = 3;
X	}
X	fprintf (stderr, " [%s]", opt->opt);
X	col += len;
X    }
X
X    fprintf (stderr, "\r\n\nType %s -help for a full description.\r\n\n",
X	     ProgramName);
X    exit (1);
X}
X
Xstatic void Help ()
X{
X    struct _options *opt;
X    char **cpp;
X
X    fprintf (stderr, "usage:\n        %s [-options ...] [-e command args]\n\n",
X	     ProgramName);
X    fprintf (stderr, "where options include:\n");
X    for (opt = options; opt->opt; opt++) {
X	fprintf (stderr, "    %-28s %s\n", opt->opt, opt->desc);
X    }
X
X    putc ('\n', stderr);
X    for (cpp = message; *cpp; cpp++) {
X	fputs (*cpp, stderr);
X	putc ('\n', stderr);
X    }
X    putc ('\n', stderr);
X
X    exit (0);
X}
X
X
Xextern WidgetClass xtermWidgetClass;
X
XArg ourTopLevelShellArgs[] = {
X	{ XtNallowShellResize, (XtArgVal) TRUE },	
X	{ XtNinput, (XtArgVal) TRUE },
X};
Xint number_ourTopLevelShellArgs = 2;
X	
XXtAppContext app_con;
XWidget toplevel;
XBool waiting_for_initial_map;
X
Xmain (argc, argv)
Xint argc;
Xchar **argv;
X{
X	register TScreen *screen;
X	register int i, pty;
X	int Xsocket, mode;
X	char *basename();
X	int xerror(), xioerror();
X
X	ProgramName = argv[0];
X
X	ttydev = (char *) malloc (strlen (TTYDEV) + 1);
X	ptydev = (char *) malloc (strlen (PTYDEV) + 1);
X	if (!ttydev || !ptydev) {
X	    fprintf (stderr, 
X	    	     "%s:  unable to allocate memory for ttydev or ptydev\n",
X		     ProgramName);
X	    exit (1);
X	}
X	strcpy (ttydev, TTYDEV);
X	strcpy (ptydev, PTYDEV);
X
X#ifdef USE_SYSV_TERMIO
X	/* Initialization is done here rather than above in order
X	** to prevent any assumptions about the order of the contents
X	** of the various terminal structures (which may change from
X	** implementation to implementation).
X	*/
X#if defined(macII) || defined(att)
X	d_tio.c_iflag = ICRNL|IXON;
X	d_tio.c_oflag = OPOST|ONLCR|TAB3;
X    	d_tio.c_cflag = B9600|CS8|CREAD|PARENB|HUPCL;
X    	d_tio.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
X
X	d_tio.c_line = 0;
X
X	d_tio.c_cc[VINTR] = CINTR;
X	d_tio.c_cc[VQUIT] = CQUIT;
X	d_tio.c_cc[VERASE] = CERASE;
X	d_tio.c_cc[VKILL] = CKILL;
X    	d_tio.c_cc[VEOF] = CEOF;
X	d_tio.c_cc[VEOL] = CNUL;
X	d_tio.c_cc[VEOL2] = CNUL;
X	d_tio.c_cc[VSWTCH] = CNUL;
X
X#ifdef TIOCSLTC
X        d_ltc.t_suspc = CSUSP;		/* t_suspc */
X        d_ltc.t_dsuspc = CDSUSP;	/* t_dsuspc */
X        d_ltc.t_rprntc = 0;		/* reserved...*/
X        d_ltc.t_flushc = 0;
X        d_ltc.t_werasc = 0;
X        d_ltc.t_lnextc = 0;
X#endif /* TIOCSLTC */
X#else  /* else !macII */
X	d_tio.c_iflag = ICRNL|IXON;
X	d_tio.c_oflag = OPOST|ONLCR|TAB3;
X#ifdef BAUD_0
X    	d_tio.c_cflag = CS8|CREAD|PARENB|HUPCL;
X#else	/* !BAUD_0 */
X    	d_tio.c_cflag = B9600|CS8|CREAD|PARENB|HUPCL;
X#endif	/* !BAUD_0 */
X    	d_tio.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
X	d_tio.c_line = 0;
X	d_tio.c_cc[VINTR] = 0x7f;		/* DEL  */
X	d_tio.c_cc[VQUIT] = '\\' & 0x3f;	/* '^\'	*/
X	d_tio.c_cc[VERASE] = '#';		/* '#'	*/
X	d_tio.c_cc[VKILL] = '@';		/* '@'	*/
X    	d_tio.c_cc[VEOF] = 'D' & 0x3f;		/* '^D'	*/
X	d_tio.c_cc[VEOL] = '@' & 0x3f;		/* '^@'	*/
X#ifdef VSWTCH
X	d_tio.c_cc[VSWTCH] = '@' & 0x3f;	/* '^@'	*/
X#endif	/* VSWTCH */
X	/* now, try to inherit tty settings */
X	{
X	    int i;
X
X	    for (i = 0; i <= 2; i++) {
X		struct termio deftio;
X		if (ioctl (i, TCGETA, &deftio) == 0) {
X		    d_tio.c_cc[VINTR] = deftio.c_cc[VINTR];
X		    d_tio.c_cc[VQUIT] = deftio.c_cc[VQUIT];
X		    d_tio.c_cc[VERASE] = deftio.c_cc[VERASE];
X		    d_tio.c_cc[VKILL] = deftio.c_cc[VKILL];
X		    d_tio.c_cc[VEOF] = deftio.c_cc[VEOF];
X		    d_tio.c_cc[VEOL] = deftio.c_cc[VEOL];
X#ifdef VSWTCH
X		    d_tio.c_cc[VSWTCH] = deftio.c_cc[VSWTCH];
X#endif /* VSWTCH */
X		    break;
X		}
X	    }
X	}
X#ifdef TIOCSLTC
X        d_ltc.t_suspc = '\000';		/* t_suspc */
X        d_ltc.t_dsuspc = '\000';	/* t_dsuspc */
X        d_ltc.t_rprntc = '\377';	/* reserved...*/
X        d_ltc.t_flushc = '\377';
X        d_ltc.t_werasc = '\377';
X        d_ltc.t_lnextc = '\377';
X#endif	/* TIOCSLTC */
X#ifdef TIOCLSET
X	d_lmode = 0;
X#endif	/* TIOCLSET */
X#endif  /* macII */
X#endif	/* USE_SYSV_TERMIO */
X
X	/* Init the Toolkit. */
X	toplevel = XtAppInitialize (&app_con, "XTerm", 
X				    optionDescList, XtNumber(optionDescList), 
X				    &argc, argv, fallback_resources, 
X				    NULL, 0);
X
X	XtGetApplicationResources( toplevel, &resource, application_resources,
X				   XtNumber(application_resources), NULL, 0 );
X
X	waiting_for_initial_map = resource.wait_for_map;
X
X	/*
X	 * fill in terminal modes
X	 */
X	if (resource.tty_modes) {
X	    int n = parse_tty_modes (resource.tty_modes,
X				     ttymodelist, NXTTYMODES);
X	    if (n < 0) {
X		fprintf (stderr, "%s:  bad tty modes \"%s\"\n",
X			 ProgramName, resource.tty_modes);
X	    } else if (n > 0) {
X		override_tty_modes = 1;
X	    }
X	}
X
X	xterm_name = resource.xterm_name;
X	sunFunctionKeys = resource.sunFunctionKeys;
X	if (strcmp(xterm_name, "-") == 0) xterm_name = "xterm";
X	if (resource.icon_geometry != NULL) {
X	    int scr, junk;
X	    int ix, iy;
X	    Arg args[2];
X
X	    for(scr = 0;	/* yyuucchh */
X		XtScreen(toplevel) != ScreenOfDisplay(XtDisplay(toplevel),scr);
X		scr++);
X
X	    args[0].name = XtNiconX;
X	    args[1].name = XtNiconY;
X	    XGeometry(XtDisplay(toplevel), scr, resource.icon_geometry, "",
X		      0, 0, 0, 0, 0, &ix, &iy, &junk, &junk);
X	    args[0].value = (XtArgVal) ix;
X	    args[1].value = (XtArgVal) iy;
X	    XtSetValues( toplevel, args, 2);
X	}
X
X	XtSetValues (toplevel, ourTopLevelShellArgs, 
X		     number_ourTopLevelShellArgs);
X
X
X	/* Parse the rest of the command line */
X	for (argc--, argv++ ; argc > 0 ; argc--, argv++) {
X	    if(**argv != '-') Syntax (*argv);
X
X	    switch(argv[0][1]) {
X	     case 'h':
X		Help ();
X		/* NOTREACHED */
X	     case 'C':
X#ifdef TIOCCONS
X		Console = TRUE;
X#endif	/* TIOCCONS */
X		continue;
X	     case 'S':
X		sscanf(*argv + 2, "%c%c%d", passedPty, passedPty+1,
X		 &am_slave);
X		if (am_slave <= 0) Syntax(*argv);
X		continue;
X#ifdef DEBUG
X	     case 'D':
X		debug = TRUE;
X		continue;
X#endif	/* DEBUG */
X	     case 'e':
X		if (argc <= 1) Syntax (*argv);
X		command_to_exec = ++argv;
X		break;
X	     default:
X		Syntax (*argv);
X	    }
X	    break;
X	}
X
X	XawSimpleMenuAddGlobalActions (XtWidgetToApplicationContext(toplevel));
X	XtRegisterGrabAction (HandlePopupMenu, True,
X			      (ButtonPressMask|ButtonReleaseMask),
X			      GrabModeAsync, GrabModeAsync);
X
X        term = (XtermWidget) XtCreateManagedWidget(
X	    "vt100", xtermWidgetClass, toplevel, NULL, 0);
X            /* this causes the initialize method to be called */
X
X        screen = &term->screen;
X
X	term->flags = WRAPAROUND;
X	update_autowrap();
X	if (!screen->jumpscroll) {
X	    term->flags |= SMOOTHSCROLL;
X	    update_jumpscroll();
X	}
X	if (term->misc.reverseWrap) {
X	    term->flags |= REVERSEWRAP;
X	    update_reversewrap();
X	}
X	if (term->misc.re_verse) {
X	    term->flags |= REVERSE_VIDEO;
X	    update_reversevideo();
X	}
X
X	inhibit = 0;
X	if (term->misc.logInhibit) 	    inhibit |= I_LOG;
X	if (term->misc.signalInhibit)		inhibit |= I_SIGNAL;
X	if (term->misc.tekInhibit)			inhibit |= I_TEK;
X
X	term->initflags = term->flags;
X
X/*
X * Set title and icon name if not specified
X */
X
X	if (command_to_exec) {
X	    Arg args[2];
X
X	    if (!resource.title) {
X		if (command_to_exec) {
X		    resource.title = basename (command_to_exec[0]);
X		} /* else not reached */
X	    }
X
X	    if (!resource.icon_name) 
X	      resource.icon_name = resource.title;
X	    XtSetArg (args[0], XtNtitle, resource.title);
X	    XtSetArg (args[1], XtNiconName, resource.icon_name);		
X
X	    XtSetValues (toplevel, args, 2);
X	}
X
X
X	if(inhibit & I_TEK)
X		screen->TekEmu = FALSE;
X
X	if(screen->TekEmu && !TekInit())
X		exit(ERROR_INIT);
X
X	/* set up stderr properly */
X	i = -1;
X#ifdef DEBUG
X	if(debug)
X		i = open ("xterm.debug.log", O_WRONLY | O_CREAT | O_TRUNC,
X		 0666);
X#endif	/* DEBUG */
X	if(i >= 0) {
X#ifdef USE_SYSV_TERMIO
X		/* SYSV has another pointer which should be part of the
X		** FILE structure but is actually a seperate array.
X		*/
X		unsigned char *old_bufend;
X
X		old_bufend = (unsigned char *) _bufend(stderr);
X		fileno(stderr) = i;
X		_bufend(stderr) = old_bufend;
X#else	/* USE_SYSV_TERMIO */
X		fileno(stderr) = i;
X#endif	/* USE_SYSV_TERMIO */
X
X		/* mark this file as close on exec */
X		(void) fcntl(i, F_SETFD, 1);
X	}
X
X	/* open a terminal for client */
X	get_terminal ();
X	spawn ();
X	/* Child process is out there, let's catch it's termination */
X	signal (SIGCHLD, reapchild);
X
X	/* Realize procs have now been executed */
X
X	Xsocket = screen->display->fd;
X	pty = screen->respond;
X
X	if (am_slave) { /* Write window id so master end can read and use */
X	    char buf[80];
X
X	    buf[0] = '\0';
X	    sprintf (buf, "%lx\n", 
X	    	     screen->TekEmu ? XtWindow (XtParent (tekWidget)) :
X				      XtWindow (XtParent (term)));
X	    write (pty, buf, strlen (buf));
X	}
X
X	if (term->misc.log_on) {
X		StartLog(screen);
X	}
X	screen->inhibit = inhibit;
X
X#ifdef USE_SYSV_TERMIO
X	if (0 > (mode = fcntl(pty, F_GETFL, 0)))
X		Error();
X	mode |= O_NDELAY;
X	if (fcntl(pty, F_SETFL, mode))
X		Error();
X#else	/* USE_SYSV_TERMIO */
X
X#ifdef AIXV3
X        /* place controller side of pty in NO DELAY MODE     */
X        /* otherwise it hangs,                               */
X    fcntl(pty, F_SETFL, O_NDELAY );
X        /* place controller side of pty in NO DELAY MODE     */
X        /* otherwise it hangs,                               */
X
X#else /* AIXV3 */
X	mode = 1;
X	if (ioctl (pty, FIONBIO, (char *)&mode) == -1) SysError (ERROR_FIONBIO);
X#endif /* AIXV3 */
X
X#endif	/* USE_SYSV_TERMIO */
X	
X	pty_mask = 1 << pty;
X	X_mask = 1 << Xsocket;
X	Select_mask = pty_mask | X_mask;
X	max_plus1 = (pty < Xsocket) ? (1 + Xsocket) : (1 + pty);
X
X#ifdef DEBUG
X	if (debug) printf ("debugging on\n");
X#endif	/* DEBUG */
X	XSetErrorHandler(xerror);
X	XSetIOErrorHandler(xioerror);
X	for( ; ; ) {
X		if(screen->TekEmu) {
X			TekRun();
X		} else
X			VTRun();
X	}
X}
X
Xchar *basename(name)
Xchar *name;
X{
X	register char *cp;
X	char *rindex();
X
X	return((cp = rindex(name, '/')) ? cp + 1 : name);
X}
X
X/* This function opens up a pty master and stuffs it's value into pty.
X * If it finds one, it returns a value of 0.  If it does not find one,
X * it returns a value of !0.  This routine is designed to be re-entrant,
X * so that if a pty master is found and later, we find that the slave
X * has problems, we can re-enter this function and get another one.
X */
X
Xget_pty (pty)
Xint *pty;
X{
X	static int devindex, letter = 0;
X
X#ifdef att
X	if ((*pty = open ("/dev/ptmx", O_RDWR)) < 0) {
X	    return 1;
X	}
X	return 0;
X#else /* !att, need lots of code */
X
X#if defined(umips) && defined (SYSTYPE_SYSV)
X	struct stat fstat_buf;
X
X	*pty = open ("/dev/ptc", O_RDWR);
X	if (*pty < 0 || (fstat (*pty, &fstat_buf)) < 0) {
X	  return(1);
X	}
X	sprintf (ttydev, "/dev/ttyq%d", minor(fstat_buf.st_rdev));
X	sprintf (ptydev, "/dev/ptyq%d", minor(fstat_buf.st_rdev));
X	if ((*tty = open (ttydev, O_RDWR)) < 0) {
X	  close (*pty);
X	  return(1);
X	}
X	/* got one! */
X	return(0);
X#else /* not (umips && SYSTYPE_SYSV) */
X#ifdef CRAY
X	for (; devindex < 256; devindex++) {
X	    sprintf (ttydev, "/dev/ttyp%03d", devindex);
X	    sprintf (ptydev, "/dev/pty/%03d", devindex);
X
X	    if ((*pty = open (ptydev, O_RDWR)) >= 0) {
X		/* We need to set things up for our next entry
X		 * into this function!
X		 */
X		(void) devindex++;
X		return(0);
X	    }
X	}
X#else /* !CRAY */
X	while (PTYCHAR1[letter]) {
X	    ttydev [strlen(ttydev) - 2]  = ptydev [strlen(ptydev) - 2] =
X		    PTYCHAR1 [letter];
X
X	    while (PTYCHAR2[devindex]) {
X		ttydev [strlen(ttydev) - 1] = ptydev [strlen(ptydev) - 1] =
X			PTYCHAR2 [devindex];
X		if ((*pty = open (ptydev, O_RDWR)) >= 0) {
X			/* We need to set things up for our next entry
X			 * into this function!
X			 */
X			(void) devindex++;
X			return(0);
X		}
X		devindex++;
X	    }
X	    devindex = 0;
X	    (void) letter++;
X	}
X#endif /* CRAY else not CRAY */
X	/* We were unable to allocate a pty master!  Return an error
X	 * condition and let our caller terminate cleanly.
X	 */
X	return(1);
X#endif /* umips && SYSTYPE_SYSV */
X#endif /* att */
X}
X
Xget_terminal ()
X/* 
X * sets up X and initializes the terminal structure except for term.buf.fildes.
X */
X{
X	register TScreen *screen = &term->screen;
X	
X	screen->arrow = make_colored_cursor (XC_left_ptr, 
X					     screen->mousecolor,
X					     screen->mousecolorback);
X}
X
X/*
X * The only difference in /etc/termcap between 4014 and 4015 is that 
X * the latter has support for switching character sets.  We support the
X * 4015 protocol, but ignore the character switches.  Therefore, we should
X * probably choose 4014 over 4015.
X */
X
Xstatic char *tekterm[] = {
X	"tek4014",
X	"tek4015",		/* has alternate character set switching */
X	"tek4013",
X	"tek4010",
X	"dumb",
X	0
X};
X
Xstatic char *vtterm[] = {
X#ifdef USE_X11TERM
X	"x11term",		/* for people who want special term name */
X#endif
X	"xterm",		/* the prefered name, should be fastest */
X	"vt102",
X	"vt100",
X	"ansi",
X	"dumb",
X	0
X};
X
X/* ARGSUSED */
XSIGNAL_T hungtty(i)
X	int i;
X{
X	longjmp(env, 1);
X	SIGNAL_RETURN;
X}
X
X#ifdef USE_HANDSHAKE
Xtypedef enum {		/* c == child, p == parent                        */
X	PTY_BAD,	/* c->p: can't open pty slave for some reason     */
X	PTY_FATALERROR,	/* c->p: we had a fatal error with the pty        */
X	PTY_GOOD,	/* c->p: we have a good pty, let's go on          */
X	PTY_NEW,	/* p->c: here is a new pty slave, try this        */
X	PTY_NOMORE,	/* p->c; no more pty's, terminate                 */
X	UTMP_ADDED,	/* c->p: utmp entry has been added                */
X	UTMP_TTYSLOT,	/* c->p: here is my ttyslot                       */
X	PTY_EXEC	/* p->c: window has been mapped the first time    */
X} status_t;
X
Xtypedef struct {
X	status_t status;
X	int error;
X	int fatal_error;
X	int tty_slot;
X	int rows;
X	int cols;
X	char buffer[1024];
X} handshake_t;
X
X/* HsSysError()
X *
X * This routine does the equivalent of a SysError but it handshakes
X * over the errno and error exit to the master process so that it can
X * display our error message and exit with our exit code so that the
X * user can see it.
X */
X
Xvoid
XHsSysError(pf, error)
Xint pf;
Xint error;
X{
X	handshake_t handshake;
X
X	handshake.status = PTY_FATALERROR;
X	handshake.error = errno;
X	handshake.fatal_error = error;
X	strcpy(handshake.buffer, ttydev);
X	write(pf, &handshake, sizeof(handshake));
X	exit(error);
X}
X
Xstatic int pc_pipe[2];	/* this pipe is used for parent to child transfer */
Xstatic int cp_pipe[2];	/* this pipe is used for child to parent transfer */
X
Xfirst_map_occurred ()
X{
X    handshake_t handshake;
X    register TScreen *screen = &term->screen;
X
X    if (screen->max_row > 0 && screen->max_col > 0) {
X	handshake.status = PTY_EXEC;
X	handshake.rows = screen->max_row;
X	handshake.cols = screen->max_col;
X	write (pc_pipe[1], (char *) &handshake, sizeof(handshake));
X	close (cp_pipe[0]);
X	close (pc_pipe[1]);
X	waiting_for_initial_map = False;
X    }
X}
X#else
X/*
X * temporary hack to get xterm working on att ptys
X */
Xfirst_map_occurred ()
X{
X    return;
X}
X#define HsSysError(a,b)
X#endif /* USE_HANDSHAKE else !USE_HANDSHAKE */
X
X
Xspawn ()
X/* 
X *  Inits pty and tty and forks a login process.
X *  Does not close fd Xsocket.
X *  If slave, the pty named in passedPty is already open for use
X */
X{
X	extern char *SysErrorMsg();
X	register TScreen *screen = &term->screen;
X	int Xsocket = screen->display->fd;
X#ifdef USE_HANDSHAKE
X	handshake_t handshake;
X#else
X	int fds[2];
X#endif
X	int tty = -1;
X	int discipline;
X	int done;
X#ifdef USE_SYSV_TERMIO
X	struct termio tio;
X	struct termio dummy_tio;
X#ifdef TIOCLSET
X	unsigned lmode;
X#endif	/* TIOCLSET */
X#ifdef TIOCSLTC
X	struct ltchars ltc;
X#endif	/* TIOCSLTC */
X	int one = 1;
X	int zero = 0;
X	int status;
X#else	/* else not USE_SYSV_TERMIO */
X
X#ifdef AIXV3
X#else /* not AIXV3 */
X	unsigned lmode;
X	struct tchars tc;
X	struct ltchars ltc;
X	struct sgttyb sg;
X#endif /* AIXV3 */
X
X#endif	/* USE_SYSV_TERMIO */
X
X	char termcap [1024];
X	char newtc [1024];
X	char *ptr, *shname, *shname_minus;
X	int i, no_dev_tty = FALSE;
X#ifdef USE_SYSV_TERMIO
X	char *dev_tty_name = (char *) 0;
X	int fd;			/* for /etc/wtmp */
X#endif	/* USE_SYSV_TERMIO */
X	char **envnew;		/* new environment */
X	char buf[32];
X	char *TermName = NULL;
X	int ldisc = 0;
X#ifdef sun
X#ifdef TIOCSSIZE
X	struct ttysize ts;
X#endif	/* TIOCSSIZE */
X#else	/* not sun */
X#ifdef TIOCSWINSZ
X	struct winsize ws;
X#endif	/* TIOCSWINSZ */
X#endif	/* sun */
X	struct passwd *pw = NULL;
X#ifdef UTMP
X	struct utmp utmp;
X#ifdef LASTLOG
X	struct lastlog lastlog;
X#endif	/* LASTLOG */
X#endif	/* UTMP */
X
X	screen->uid = getuid();
X	screen->gid = getgid();
X
X#ifdef SIGTTOU
X	/* so that TIOCSWINSZ || TIOCSIZE doesn't block */
X	signal(SIGTTOU,SIG_IGN);
X#endif
X
X	if (am_slave) {
X		screen->respond = am_slave;
X		ptydev[strlen(ptydev) - 2] = ttydev[strlen(ttydev) - 2] =
X			passedPty[0];
X		ptydev[strlen(ptydev) - 1] = ttydev[strlen(ttydev) - 1] =
X			passedPty[1];
X
X		setgid (screen->gid);
X		setuid (screen->uid);
X	} else {
X		Bool tty_got_hung = False;
X
X 		/*
X 		 * Sometimes /dev/tty hangs on open (as in the case of a pty
X 		 * that has gone away).  Simply make up some reasonable
X 		 * defaults.
X 		 */
X 		signal(SIGALRM, hungtty);
X 		alarm(2);		/* alarm(1) might return too soon */
X 		if (! setjmp(env)) {
X 			tty = open ("/dev/tty", O_RDWR, 0);
X 			alarm(0);
X 		} else {
X			tty_got_hung = True;
X 			tty = -1;
X 			errno = ENXIO;
X 		}
X 		signal(SIGALRM, SIG_DFL);
X 
X		/*
X		 * Check results and ignore current control terminal if
X		 * necessary.  ENXIO is what is normally returned if there is
X		 * no controlling terminal, but some systems (e.g. SunOS 4.0)
X		 * seem to return EIO.
X		 */
X 		if (tty < 0) {
X			if (tty_got_hung || errno == ENXIO || errno == EIO) {
X				no_dev_tty = TRUE;
X#ifdef USE_SYSV_TERMIO
X				tio = d_tio;
X#ifdef TIOCSLTC
X				ltc = d_ltc;
X#endif	/* TIOCSLTC */
X#ifdef TIOCLSET
X				lmode = d_lmode;
X#endif	/* TIOCLSET */
X#else	/* not USE_SYSV_TERMIO */
X
X#ifdef AIXV3
X				set_default_terminal_modes();
X#else /* not AIXV3 */
X				sg = d_sg;
X				tc = d_tc;
X				discipline = d_disipline;
X				ltc = d_ltc;
X				lmode = d_lmode;
X#endif /* AIXV3 */
X
X#endif	/* USE_SYSV_TERMIO */
X			} else {
X			    SysError(ERROR_OPDEVTTY);
X			}
X		} else {
X			/* get a copy of the current terminal's state */
X
X#ifdef USE_SYSV_TERMIO
X			if(ioctl(tty, TCGETA, &tio) == -1)
X				SysError(ERROR_TIOCGETP);
X#ifdef TIOCSLTC
X			if(ioctl(tty, TIOCGLTC, &ltc) == -1)
X				SysError(ERROR_TIOCGLTC);
X#endif	/* TIOCSLTC */
X#ifdef TIOCLSET
X			if(ioctl(tty, TIOCLGET, &lmode) == -1)
X				SysError(ERROR_TIOCLGET);
X#endif	/* TIOCLSET */
X#else	/* not USE_SYSV_TERMIO */
X
X#ifdef AIXV3
X			get_tty_info(tty);
X#else /* not AIXV3 */
X			if(ioctl(tty, TIOCGETP, (char *)&sg) == -1)
X				SysError (ERROR_TIOCGETP);
X			if(ioctl(tty, TIOCGETC, (char *)&tc) == -1)
X				SysError (ERROR_TIOCGETC);
X			if(ioctl(tty, TIOCGETD, (char *)&discipline) == -1)
X				SysError (ERROR_TIOCGETD);
X			if(ioctl(tty, TIOCGLTC, (char *)&ltc) == -1)
X				SysError (ERROR_TIOCGLTC);
X			if(ioctl(tty, TIOCLGET, (char *)&lmode) == -1)
X				SysError (ERROR_TIOCLGET);
X#endif /* AIXV3 */
X#endif	/* USE_SYSV_TERMIO */
X			close (tty);
X			/* tty is no longer an open fd! */
X			tty = -1;
X		}
X
X#ifdef 	PUCC_PTYD
X		if(-1 == (screen->respond = openrpty(ttydev, ptydev,
X				(resource.utmpInhibit ?  OPTY_NOP : OPTY_LOGIN),
X				getuid(), XDisplayString(screen->display)))) {
X#else /* not PUCC_PTYD */
X		if (get_pty (&screen->respond)) {
X#endif /* PUCC_PTYD */
X			/*  no ptys! */
X			(void) fprintf(stderr, "%s: no available ptys\n",
X				       xterm_name);
X			exit (ERROR_PTYS);
X#ifdef PUCC_PTYD
X		}
X#else
X		}			/* keep braces balanced for emacs */
X#endif
X#ifdef PUCC_PTYD
X		  else {
X			/*
X			 *  set the fd of the master in a global var so
X			 *  we can undo all this on exit
X			 *
X			 */
X			Ptyfd = screen->respond;
X		  }
X#endif /* PUCC_PTYD */
X	}
X
X	/* avoid double MapWindow requests */
X	XtSetMappedWhenManaged( screen->TekEmu ? XtParent(tekWidget) :
X			        XtParent(term), False );
X        /* Realize the Tek or VT widget, depending on which mode we're in.
X           If VT mode, this calls VTRealize (the widget's Realize proc) */
X        XtRealizeWidget (screen->TekEmu ? XtParent(tekWidget) :
X			 XtParent(term));
X
X	if(screen->TekEmu) {
X		envnew = tekterm;
X		ptr = newtc;
X	} else {
X		envnew = vtterm;
X		ptr = termcap;
X	}
X	TermName = NULL;
X	if (resource.term_name) {
X	    if (tgetent (ptr, resource.term_name) == 1) {
X		TermName = resource.term_name;
X		if (!screen->TekEmu)
X		    resize (screen, TermName, termcap, newtc);
X	    } else {
X		fprintf (stderr, "%s:  invalid termcap entry \"%s\".\n",
X			 ProgramName, resource.term_name);
X	    }
X	}
X	if (!TermName) {
X	    while (*envnew != NULL) {
X		if(tgetent(ptr, *envnew) == 1) {
X			TermName = *envnew;
X			if(!screen->TekEmu)
X			    resize(screen, TermName, termcap, newtc);
X			break;
X		}
X		envnew++;
X	    }
X	    if (TermName == NULL) {
X		fprintf (stderr, "%s:  unable to find usable termcap entry.\n",
X			 ProgramName);
X		Exit (1);
X	    }
X	}
X
X#ifdef sun
X#ifdef TIOCSSIZE
X	/* tell tty how big window is */
X	if(screen->TekEmu) {
X		ts.ts_lines = 38;
X		ts.ts_cols = 81;
X	} else {
X		ts.ts_lines = screen->max_row + 1;
X		ts.ts_cols = screen->max_col + 1;
X	}
X#endif	/* TIOCSSIZE */
X#else	/* not sun */
X#ifdef TIOCSWINSZ
X	/* tell tty how big window is */
X	if(screen->TekEmu) {
X		ws.ws_row = 38;
X		ws.ws_col = 81;
X		ws.ws_xpixel = TFullWidth(screen);
X		ws.ws_ypixel = TFullHeight(screen);
X	} else {
X		ws.ws_row = screen->max_row + 1;
X		ws.ws_col = screen->max_col + 1;
X		ws.ws_xpixel = FullWidth(screen);
X		ws.ws_ypixel = FullHeight(screen);
X	}
X#endif	/* TIOCSWINSZ */
X#endif	/* sun */
X
X	if (!am_slave) {
X#ifdef USE_HANDSHAKE
X	    if (pipe(pc_pipe) || pipe(cp_pipe))
X		SysError (ERROR_FORK);
X#endif
X	    if ((screen->pid = fork ()) == -1)
X		SysError (ERROR_FORK);
X		
X	    if (screen->pid == 0) {
X		/*
X		 * now in child process
X		 */
X		extern char **environ;
X		int pgrp = getpid();
X#ifdef USE_SYSV_TERMIO
X		char numbuf[12];
X#endif	/* USE_SYSV_TERMIO */
X
X#ifndef USE_HANDSHAKE
X		int ptyfd;
X
X		setpgrp();
X		grantpt (screen->respond);
X		unlockpt (screen->respond);
X		if ((ptyfd = open (ptsname(screen->respond), O_RDWR)) < 0) {
X		    SysError (1);
X		}
X		if (ioctl (ptyfd, I_PUSH, "ptem") < 0) {
X		    SysError (2);
X		}
X		if (!getenv("CONSEM") && ioctl (ptyfd, I_PUSH, "consem") < 0) {
X		    SysError (3);
X		}
X		if (ioctl (ptyfd, I_PUSH, "ldterm") < 0) {
X		    SysError (4);
X		}
X		tty = ptyfd;
X		close (screen->respond);
X#ifdef TIOCSWINSZ
X                /* tell tty how big window is */
X                if(screen->TekEmu) {
X                        ws.ws_row = 24;
X                        ws.ws_col = 80;
X                        ws.ws_xpixel = TFullWidth(screen);
X                        ws.ws_ypixel = TFullHeight(screen);
X                } else {
X                        ws.ws_row = screen->max_row + 1;
X                        ws.ws_col = screen->max_col + 1;
X                        ws.ws_xpixel = FullWidth(screen);
X                        ws.ws_ypixel = FullHeight(screen);
X                }
X#endif
X
X
X#else /* USE_HANDSHAKE:  warning, goes for a long ways */
X		/* close parent's sides of the pipes */
X		close (cp_pipe[0]);
X		close (pc_pipe[1]);
X
X		/* Make sure that our sides of the pipes are not in the
X		 * 0, 1, 2 range so that we don't fight with stdin, out
X		 * or err.
X		 */
X		if (cp_pipe[1] <= 2) {
X			if ((i = fcntl(cp_pipe[1], F_DUPFD, 3)) >= 0) {
X				(void) close(cp_pipe[1]);
X				cp_pipe[1] = i;
X			}
X		}
X		if (pc_pipe[0] <= 2) {
X			if ((i = fcntl(pc_pipe[0], F_DUPFD, 3)) >= 0) {
X				(void) close(pc_pipe[0]);
X				pc_pipe[0] = i;
X			}
X		}
X
X		/* we don't need the socket, or the pty master anymore */
X		close (Xsocket);
X		close (screen->respond);
X
X		/* Now is the time to set up our process group and
X		 * open up the pty slave.
X		 */
X#ifdef	USE_SYSV_PGRP
X		(void) setpgrp();
X#endif	/* USE_SYSV_PGRP */
X		while (1) {
X#ifdef TIOCNOTTY
X			if ((tty = open ("/dev/tty", 2)) >= 0) {
X				ioctl (tty, TIOCNOTTY, (char *) NULL);
X				close (tty);
X			}
X#endif	/* TIOCNOTTY */
X			if ((tty = open(ttydev, O_RDWR, 0)) >= 0) {
X#ifdef	USE_SYSV_PGRP
X				/* We need to make sure that we are acutally
X				 * the process group leader for the pty.  If
X				 * we are, then we should now be able to open
X				 * /dev/tty.
X				 */
X				if ((i = open("/dev/tty", O_RDWR, 0)) >= 0) {
X					/* success! */
X					close(i);
X					break;
X				}
X#else	/* USE_SYSV_PGRP */
X				break;
X#endif	/* USE_SYSV_PGRP */
X			}
X
X#ifdef TIOCSCTTY
X			ioctl(tty, TIOCSCTTY, 0);
X#endif
X			/* let our master know that the open failed */
X			handshake.status = PTY_BAD;
X			handshake.error = errno;
X			strcpy(handshake.buffer, ttydev);
X			write(cp_pipe[1], (char *) &handshake,
X			    sizeof(handshake));
X
X			/* get reply from parent */
X			i = read(pc_pipe[0], (char *) &handshake,
X			    sizeof(handshake));
X			if (i <= 0) {
X				/* parent terminated */
X				exit(1);
X			}
X
X			if (handshake.status == PTY_NOMORE) {
X				/* No more ptys, let's shutdown. */
X				exit(1);
X			}
X
X			/* We have a new pty to try */
X			free(ttydev);
X			ttydev = malloc((unsigned)
X			    (strlen(handshake.buffer) + 1));
X			strcpy(ttydev, handshake.buffer);
X		}
X
X		/* use the same tty name that everyone else will use
X		** (from ttyname)
X		*/
X		if (ptr = ttyname(tty))
X		{
X			/* it may be bigger */
X			ttydev = realloc (ttydev, (unsigned) (strlen(ptr) + 1));
X			(void) strcpy(ttydev, ptr);
X		}
X
X#endif /* !USE_HANDSHAKE else USE_HANDSHAKE - from near fork */
X
X#ifdef USE_TTY_GROUP
X	{ 
X#include <grp.h>
X		struct group *ttygrp;
X		if (ttygrp = getgrnam("tty")) {
X			/* change ownership of tty to real uid, "tty" gid */
X			chown (ttydev, screen->uid, ttygrp->gr_gid);
X			chmod (ttydev, 0620);
X		}
X		else {
X			/* change ownership of tty to real group and user id */
X			chown (ttydev, screen->uid, screen->gid);
X			chmod (ttydev, 0622);
X		}
X		endgrent();
X	}
X#else /* else !USE_TTY_GROUP */
X		/* change ownership of tty to real group and user id */
X		chown (ttydev, screen->uid, screen->gid);
X
X		/* change protection of tty */
X		chmod (ttydev, 0622);
X#endif /* USE_TTY_GROUP */
X
X		/*
X		 * set up the tty modes
X		 */
X		{
X#ifdef USE_SYSV_TERMIO
X#ifdef umips
X		    /* If the control tty had its modes screwed around with,
X		       eg. by lineedit in the shell, or emacs, etc. then tio
X		       will have bad values.  Let's just get termio from the
X		       new tty and tailor it.  */
X		    if (ioctl (tty, TCGETA, &tio) == -1)
X		      SysError (ERROR_TIOCGETP);
X		    tio.c_lflag |= ECHOE;
X#endif /* umips */
X		    /* Now is also the time to change the modes of the
X		     * child pty.
X		     */
X		    /* input: nl->nl, don't ignore cr, cr->nl */
X		    tio.c_iflag &= ~(INLCR|IGNCR);
X		    tio.c_iflag |= ICRNL;
X		    /* ouput: cr->cr, nl is not return, no delays, ln->cr/nl */
X		    tio.c_oflag &=
X		     ~(OCRNL|ONLRET|NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
X		    tio.c_oflag |= ONLCR;
X#ifdef BAUD_0
X		    /* baud rate is 0 (don't care) */
X		    tio.c_cflag &= ~(CBAUD);
X#else	/* !BAUD_0 */
X		    /* baud rate is 9600 (nice default) */
X		    tio.c_cflag &= ~(CBAUD);
X		    tio.c_cflag |= B9600;
X#endif	/* !BAUD_0 */
X		    /* enable signals, canonical processing (erase, kill, etc),
X		    ** echo
X		    */
X		    tio.c_lflag |= ISIG|ICANON|ECHO;
X		    /* reset EOL to defalult value */
X		    tio.c_cc[VEOL] = '@' & 0x3f;		/* '^@'	*/
X		    /* certain shells (ksh & csh) change EOF as well */
X		    tio.c_cc[VEOF] = 'D' & 0x3f;		/* '^D'	*/
X
X#define TMODE(ind,var) if (ttymodelist[ind].set) var = ttymodelist[ind].value;
X		    if (override_tty_modes) {
X			/* sysv-specific */
X			TMODE (XTTYMODE_intr, tio.c_cc[VINTR]);
X			TMODE (XTTYMODE_quit, tio.c_cc[VQUIT]);
X			TMODE (XTTYMODE_erase, tio.c_cc[VERASE]);
X			TMODE (XTTYMODE_kill, tio.c_cc[VKILL]);
X			TMODE (XTTYMODE_eof, tio.c_cc[VEOF]);
X			TMODE (XTTYMODE_eol, tio.c_cc[VEOL]);
X#ifdef VSWTCH
X			TMODE (XTTYMODE_swtch, d_tio.c_cc[VSWTCH]);
X#endif
X#ifdef TIOCSLTC
X			/* both SYSV and BSD have ltchars */
X			TMODE (XTTYMODE_susp, ltc.t_suspc);
X			TMODE (XTTYMODE_dsusp, ltc.t_dsuspc);
X			TMODE (XTTYMODE_rprnt, ltc.t_rprntc);
X			TMODE (XTTYMODE_flush, ltc.t_flushc);
X			TMODE (XTTYMODE_weras, ltc.t_werasc);
X			TMODE (XTTYMODE_lnext, ltc.t_lnextc);
X#endif
X		    }
X#undef TMODE
X
X		    if (ioctl (tty, TCSETA, &tio) == -1)
X			    HsSysError(cp_pipe[1], ERROR_TIOCSETP);
X#ifdef TIOCSLTC
X		    if (ioctl (tty, TIOCSLTC, &ltc) == -1)
X			    HsSysError(cp_pipe[1], ERROR_TIOCSETC);
X#endif	/* TIOCSLTC */
X#ifdef TIOCLSET
X		    if (ioctl (tty, TIOCLSET, (char *)&lmode) == -1)
X			    HsSysError(cp_pipe[1], ERROR_TIOCLSET);
X#endif	/* TIOCLSET */
X#ifdef TIOCCONS
X		    if (Console) {
X			    int on = 1;
X			    if (ioctl (tty, TIOCCONS, (char *)&on) == -1)
X				    HsSysError(cp_pipe[1], ERROR_TIOCCONS);
X		    }
X#endif	/* TIOCCONS */
X#else	/* USE_SYSV_TERMIO */
X
X#ifdef AIXV3
X/*
X	c_iflag = (BRKINT|ICRNL|IXON|IXOFF|IMAXBEL);
X	c_oflag = (OPOST|ONLCR|TAB3);
X	c_cflag = (CS8|CREAD|HUPCL|B9600);
X	c_lflag = (ISIG|ICANON|ECHO|ECHOE|ECHOK|IEXTEN|ECHOKE|ECHOCTL);
X*/
X	/* set some flags that should be on */
X	terminal_modes.c_oflag |= OPOST;
X	/* set some flags that should be on */
X
X	/* set some flags that should be off */
X	terminal_modes.c_cflag &= ~( CLOCAL );
X	/* set some flags that should be off */
X
X#define TMODE(ind,var) if (ttymodelist[ind].set) var = ttymodelist[ind].value;
X    if( override_tty_modes ){
X	TMODE( XTTYMODE_intr, terminal_modes.c_cc[VINTR] );
X	TMODE( XTTYMODE_quit, terminal_modes.c_cc[VQUIT] );
X	TMODE( XTTYMODE_erase, terminal_modes.c_cc[VERASE] );
X	TMODE( XTTYMODE_kill, terminal_modes.c_cc[VKILL] );
X	TMODE( XTTYMODE_eof, terminal_modes.c_cc[VEOF] );
X	TMODE( XTTYMODE_eol, terminal_modes.c_cc[VEOL] );
X/*
X	TMODE( XTTYMODE_, terminal_modes.c_cc[VEOL2] );
X*/
X	TMODE( XTTYMODE_start, terminal_modes.c_cc[VSTRT] );
X	TMODE( XTTYMODE_stop, terminal_modes.c_cc[VSTOP] );
X	TMODE( XTTYMODE_susp, terminal_modes.c_cc[VSUSP] );
X	TMODE( XTTYMODE_dsusp, terminal_modes.c_cc[VDSUSP] );
X	TMODE( XTTYMODE_rprnt, terminal_modes.c_cc[VREPRINT] );
X	TMODE( XTTYMODE_flush, terminal_modes.c_cc[VDISCRD] );
X	TMODE( XTTYMODE_weras, terminal_modes.c_cc[VWERSE] );
X	TMODE( XTTYMODE_lnext, terminal_modes.c_cc[VLNEXT] );
X    }
X
X
X	set_tty_info(tty);
X
X#else /* not AIXV3 */
X		    sg.sg_flags &= ~(ALLDELAY | XTABS | CBREAK | RAW);
X		    sg.sg_flags |= ECHO | CRMOD;
X		    /* make sure speed is set on pty so that editors work right*/
X		    sg.sg_ispeed = B9600;
X		    sg.sg_ospeed = B9600;
X		    /* reset t_brkc to default value */
X		    tc.t_brkc = -1;
X
X#define TMODE(ind,var) if (ttymodelist[ind].set) var = ttymodelist[ind].value;
X		    if (override_tty_modes) {
X			TMODE (XTTYMODE_intr, tc.t_intrc);
X			TMODE (XTTYMODE_quit, tc.t_quitc);
X			TMODE (XTTYMODE_erase, sg.sg_erase);
X			TMODE (XTTYMODE_kill, sg.sg_kill);
X			TMODE (XTTYMODE_eof, tc.t_eofc);
X			TMODE (XTTYMODE_start, tc.t_startc);
X			TMODE (XTTYMODE_stop, tc.t_stopc);
X			TMODE (XTTYMODE_brk, tc.t_brkc);
X			/* both SYSV and BSD have ltchars */
X			TMODE (XTTYMODE_susp, ltc.t_suspc);
X			TMODE (XTTYMODE_dsusp, ltc.t_dsuspc);
X			TMODE (XTTYMODE_rprnt, ltc.t_rprntc);
X			TMODE (XTTYMODE_flush, ltc.t_flushc);
X			TMODE (XTTYMODE_weras, ltc.t_werasc);
X			TMODE (XTTYMODE_lnext, ltc.t_lnextc);
X		    }
X#undef TMODE
X
X		    if (ioctl (tty, TIOCSETP, (char *)&sg) == -1)
X			    HsSysError (cp_pipe[1], ERROR_TIOCSETP);
X		    if (ioctl (tty, TIOCSETC, (char *)&tc) == -1)
X			    HsSysError (cp_pipe[1], ERROR_TIOCSETC);
X		    if (ioctl (tty, TIOCSETD, (char *)&discipline) == -1)
X			    HsSysError (cp_pipe[1], ERROR_TIOCSETD);
X		    if (ioctl (tty, TIOCSLTC, (char *)&ltc) == -1)
X			    HsSysError (cp_pipe[1], ERROR_TIOCSLTC);
X		    if (ioctl (tty, TIOCLSET, (char *)&lmode) == -1)
X			    HsSysError (cp_pipe[1], ERROR_TIOCLSET);
X
X#ifdef TIOCCONS
X		    if (Console) {
X			    int on = 1;
X			    if (ioctl (tty, TIOCCONS, (char *)&on) == -1)
X				    HsSysError(cp_pipe[1], ERROR_TIOCCONS);
X		    }
X#endif	/* TIOCCONS */
X
X#endif /* AIXV3 */
X
X#endif	/* !USE_SYSV_TERMIO */
X		}
X
X		signal (SIGCHLD, SIG_DFL);
X#ifdef att
X		/* watch out for extra shells (I don't understand either) */
X		signal (SIGHUP, SIG_DFL);
X#else
X		signal (SIGHUP, SIG_IGN);
X#endif
X		/* restore various signals to their defaults */
X		signal (SIGINT, SIG_DFL);
X		signal (SIGQUIT, SIG_DFL);
X		signal (SIGTERM, SIG_DFL);
X
X		/* copy the environment before Setenving */
X		for (i = 0 ; environ [i] != NULL ; i++) ;
X		/*
X		 * The `4' (`5' for SYSV) is the number of Setenv()
X		 * calls which may add a new entry to the environment.
X		 * The `1' is for the NULL terminating entry.
X		 */
X#ifdef USE_SYSV_ENVVARS
X		envnew = (char **) calloc ((unsigned) i + (5 + 1), sizeof(char *));
X#else
X		envnew = (char **) calloc ((unsigned) i + (4 + 1), sizeof(char *));
X#endif /* USE_SYSV_ENVVARS */
X		bcopy((char *)environ, (char *)envnew, i * sizeof(char *));
X		environ = envnew;
X		Setenv ("TERM=", TermName);
X		if(!TermName)
X			*newtc = 0;
X
X		sprintf (buf, "%lu", screen->TekEmu ? 
X			 ((unsigned long) XtWindow (XtParent(tekWidget))) :
X			 ((unsigned long) XtWindow (XtParent(term))));
X		Setenv ("WINDOWID=", buf);
X		/* put the display into the environment of the shell*/
X		Setenv ("DISPLAY=", XDisplayString (screen->display));
X
X		signal(SIGTERM, SIG_DFL);
X
X		/* this is the time to go and set up stdin, out, and err
X		 */
X		{
X		    /* dup the tty */
X		    for (i = 0; i <= 2; i++)
X			if (i != tty) {
X			    (void) close(i);
X			    (void) dup(tty);
X			}
X
X#ifndef att
X		    /* and close the tty */
X		    if (tty > 2)
X			(void) close(tty);
X#endif
X		}
X
X
X#ifndef	USE_SYSV_PGRP
X#ifdef TIOCSCTTY
X		setsid();
X		ioctl(0, TIOCSCTTY, 0);
X#endif
X		ioctl(0, TIOCSPGRP, (char *)&pgrp);
X		setpgrp(0,0);
X		close(open(ttydev, O_WRONLY, 0));
X		setpgrp (0, pgrp);
X#endif /* USE_SYSV_PGRP */
X
X#ifdef UTMP
X#ifdef USE_SYSV_UTMP
X		/* Set up our utmp entry now.  We need to do it here
X		** for the following reasons:
X		**   - It needs to have our correct process id (for
X		**     login).
X		**   - If our parent was to set it after the fork(),
X		**     it might make it out before we need it.
X		**   - We need to do it before we go and change our
X		**     user and group id's.
X		*/
X
X		(void) setutent ();
X		/* set up entry to search for */
X		(void) strncpy(utmp.ut_id,ttydev + strlen(ttydev) - 2,
X		 sizeof (utmp.ut_id));
X		utmp.ut_type = DEAD_PROCESS;
X
X		/* position to entry in utmp file */
X		(void) getutid(&utmp);
X
X		/* set up the new entry */
X		pw = getpwuid(screen->uid);
X		utmp.ut_type = USER_PROCESS;
X		utmp.ut_exit.e_exit = 2;
X		(void) strncpy(utmp.ut_user,
X			       (pw && pw->pw_name) ? pw->pw_name : "????",
X			       sizeof(utmp.ut_user));
X		    
X		(void) strncpy(utmp.ut_id, ttydev + strlen(ttydev) - 2,
X			sizeof(utmp.ut_id));
X		(void) strncpy (utmp.ut_line,
X			ttydev + strlen("/dev/"), sizeof (utmp.ut_line));
X#ifdef HAS_UTMP_UT_HOST
X		(void) strncpy(utmp.ut_host, DisplayString(screen->display),
X			       sizeof(utmp.ut_host));
X#endif
X		(void) strncpy(utmp.ut_name, pw->pw_name, 
X			       sizeof(utmp.ut_name));
X
X		utmp.ut_pid = getpid();
X		utmp.ut_time = time ((long *) 0);
X
X		/* write out the entry */
X		if (!resource.utmpInhibit) (void) pututline(&utmp);
X
X		/* close the file */
X		(void) endutent();
X
X#else	/* USE_SYSV_UTMP */
X		/* We can now get our ttyslot!  We can also set the initial
X		 * UTMP entry.
X		 */
X		tslot = ttyslot();
X		added_utmp_entry = False;
X		{
X			if ((pw = getpwuid(screen->uid)) &&
X			    !resource.utmpInhibit &&
X			    (i = open(etc_utmp, O_WRONLY)) >= 0) {
X				bzero((char *)&utmp, sizeof(struct utmp));
X				(void) strncpy(utmp.ut_line,
X					       ttydev + strlen("/dev/"),
X					       sizeof(utmp.ut_line));
X				(void) strncpy(utmp.ut_name, pw->pw_name,
X					       sizeof(utmp.ut_name));
X#ifdef HAS_UTMP_UT_HOST
X				(void) strncpy(utmp.ut_host, 
X					       XDisplayString (screen->display),
X					       sizeof(utmp.ut_host));
X#endif
X				time(&utmp.ut_time);
X				lseek(i, (long)(tslot * sizeof(struct utmp)), 0);
X				write(i, (char *)&utmp, sizeof(struct utmp));
X				close(i);
X				added_utmp_entry = True;
X#ifdef WTMP
X				if (term->misc.login_shell &&
X				(i = open(etc_wtmp, O_WRONLY|O_APPEND)) >= 0) {
X				    write(i, (char *)&utmp,
X					sizeof(struct utmp));
X				close(i);
X				}
X#endif /* WTMP */
X#ifdef LASTLOG
X				if (term->misc.login_shell &&
X				(i = open(etc_lastlog, O_WRONLY)) >= 0) {
X				    bzero((char *)&lastlog,
X					sizeof (struct lastlog));
X				    (void) strncpy(lastlog.ll_line, ttydev +
X					sizeof("/dev"),
X					sizeof (lastlog.ll_line));
X				    (void) strncpy(lastlog.ll_host, 
X					  XDisplayString (screen->display),
X					  sizeof (lastlog.ll_host));
X				    time(&lastlog.ll_time);
X				    lseek(i, (long)(screen->uid *
X					sizeof (struct lastlog)), 0);
X				    write(i, (char *)&lastlog,
X					sizeof (struct lastlog));
X				    close(i);
X				}
X#endif /* LASTLOG */
X			} else
X				tslot = -tslot;
X		}
X
X		/* Let's pass our ttyslot to our parent so that it can
X		 * clean up after us.
X		 */
X#ifdef USE_HANDSHAKE
X		handshake.tty_slot = tslot;
X#endif /* USE_HANDSHAKE */
X#endif /* USE_SYSV_UTMP */
X
X#ifdef USE_HANDSHAKE
X		/* Let our parent know that we set up our utmp entry
X		 * so that it can clean up after us.
X		 */
X		handshake.status = UTMP_ADDED;
X		handshake.error = 0;
X		strcpy(handshake.buffer, ttydev);
X		(void) write(cp_pipe[1], &handshake, sizeof(handshake));
X#endif /* USE_HANDSHAKE */
X#endif/* UTMP */
X
X		(void) setgid (screen->gid);
X#ifdef HAS_BSD_GROUPS
X		if (geteuid() == 0 && pw)
X		  initgroups (pw->pw_name, pw->pw_gid);
X#endif
X		(void) setuid (screen->uid);
X
X#ifdef USE_HANDSHAKE
X		/* mark the pipes as close on exec */
X		fcntl(cp_pipe[1], F_SETFD, 1);
X		fcntl(pc_pipe[0], F_SETFD, 1);
X
X		/* We are at the point where we are going to
X		 * exec our shell (or whatever).  Let our parent
X		 * know we arrived safely.
X		 */
X		handshake.status = PTY_GOOD;
X		handshake.error = 0;
X		(void) strcpy(handshake.buffer, ttydev);
X		(void) write(cp_pipe[1], &handshake, sizeof(handshake));
X
X		if (waiting_for_initial_map) {
X		    i = read (pc_pipe[0], (char *) &handshake,
X			      sizeof(handshake));
X		    if (i != sizeof(handshake) ||
X			handshake.status != PTY_EXEC) {
X			/* some very bad problem occurred */
X			exit (ERROR_PTY_EXEC);
X		    }
X		    screen->max_row = handshake.rows;
X		    screen->max_col = handshake.cols;
X#ifdef sun
X#ifdef TIOCSSIZE
X		    ts.ts_lines = screen->max_row + 1;
X		    ts.ts_cols = screen->max_col + 1;
X#endif /* TIOCSSIZE */
X#else /* !sun */
X#ifdef TIOCSWINSZ
X		    ws.ws_row = screen->max_row + 1;
X		    ws.ws_col = screen->max_col + 1;
X		    ws.ws_xpixel = FullWidth(screen);
X		    ws.ws_ypixel = FullHeight(screen);
X#endif /* TIOCSWINSZ */
X#endif /* sun else !sun */
X		}
X#endif /* USE_HANDSHAKE */
X
X#ifdef USE_SYSV_ENVVARS
X		sprintf (numbuf, "%d", screen->max_col + 1);
X		Setenv("COLUMNS=", numbuf);
X		sprintf (numbuf, "%d", screen->max_row + 1);
X		Setenv("LINES=", numbuf);
X#else
X		if(!screen->TekEmu) {
X		    strcpy (termcap, newtc);
X		    resize (screen, TermName, termcap, newtc);
X		}
X		if (term->misc.titeInhibit) {
X		    remove_termcap_entry (newtc, ":ti=");
X		    remove_termcap_entry (newtc, ":te=");
X		}
X		Setenv ("TERMCAP=", newtc);
X#endif /* USE_SYSV_ENVVAR */
X
X
X		/* need to reset after all the ioctl bashing we did above */
X#ifdef sun
X#ifdef TIOCSSIZE
X		ioctl  (0, TIOCSSIZE, &ts);
X#endif	/* TIOCSSIZE */
X#else	/* not sun */
X#ifdef TIOCSWINSZ
X		ioctl (0, TIOCSWINSZ, (char *)&ws);
X#endif	/* TIOCSWINSZ */
X#endif	/* sun */
X
X
X		signal(SIGHUP, SIG_DFL);
X		if (command_to_exec) {
X			execvp(*command_to_exec, command_to_exec);
X			/* print error message on screen */
X			fprintf(stderr, "%s: Can't execvp %s\n", xterm_name,
X			 *command_to_exec);
X		} 
X
X#ifdef att
X		/* fix pts sh hanging around */
X		signal (SIGHUP, SIG_DFL);
X#endif
X
X#ifdef UTMP
X		if(((ptr = getenv("SHELL")) == NULL || *ptr == 0) &&
X		 ((pw == NULL && (pw = getpwuid(screen->uid)) == NULL) ||
X		 *(ptr = pw->pw_shell) == 0))
X#else	/* UTMP */
X		if(((ptr = getenv("SHELL")) == NULL || *ptr == 0) &&
X		 ((pw = getpwuid(screen->uid)) == NULL ||
X		 *(ptr = pw->pw_shell) == 0))
X#endif	/* UTMP */
X			ptr = "/bin/sh";
X		if(shname = rindex(ptr, '/'))
X			shname++;
X		else
X			shname = ptr;
X		shname_minus = malloc(strlen(shname) + 2);
X		(void) strcpy(shname_minus, "-");
X		(void) strcat(shname_minus, shname);
X
X#ifndef AIXV3
X#ifndef USE_SYSV_TERMIO
X		ldisc = XStrCmp("csh", shname + strlen(shname) - 3) == 0 ?
X		 NTTYDISC : 0;
X		ioctl(0, TIOCSETD, (char *)&ldisc);
X#endif	/* !USE_SYSV_TERMIO */
X#endif /* not AIXV3 */
X
X#ifdef USE_LOGIN_DASH_P
X		if (term->misc.login_shell && pw && added_utmp_entry)
X		  execl (bin_login, "login", "-p", "-f", pw->pw_name, 0);
X#endif
X		execlp (ptr, (term->misc.login_shell ? shname_minus : shname),
X			0);
X
X		/* Exec failed. */
X		fprintf (stderr, "%s: Could not exec %s!\n", xterm_name, ptr);
X		sleep(5);
X		exit(ERROR_EXEC);
X	    }				/* end if in child after fork */
X
X#ifdef USE_HANDSHAKE
X	    /* Parent process.  Let's handle handshaked requests to our
X	     * child process.
X	     */
X
X	    /* close childs's sides of the pipes */
X	    close (cp_pipe[1]);
X	    close (pc_pipe[0]);
X
X	    for (done = 0; !done; ) {
X		if (read(cp_pipe[0], &handshake, sizeof(handshake)) <= 0) {
X			/* Our child is done talking to us.  If it terminated
X			 * due to an error, we will catch the death of child
X			 * and clean up.
X			 */
X			break;
X		}
X
X		switch(handshake.status) {
X		case PTY_GOOD:
X			/* Success!  Let's free up resources and
X			 * continue.
X			 */
X			done = 1;
X			break;
X
X		case PTY_BAD:
X			/* The open of the pty failed!  Let's get
X			 * another one.
X			 */
X			(void) close(screen->respond);
X			if (get_pty(&screen->respond)) {
X			    /* no more ptys! */
X			    (void) fprintf(stderr,
X				   "%s: no available ptys\n", xterm_name);
X			    handshake.status = PTY_NOMORE;
X			    write(pc_pipe[1], &handshake, sizeof(handshake));
X			    exit (ERROR_PTYS);
X			}
X			handshake.status = PTY_NEW;
X			(void) strcpy(handshake.buffer, ttydev);
X			write(pc_pipe[1], &handshake, sizeof(handshake));
X			break;
X
X		case PTY_FATALERROR:
X			errno = handshake.error;
X			close(cp_pipe[0]);
X			close(pc_pipe[1]);
X			SysError(handshake.fatal_error);
X
X		case UTMP_ADDED:
X			/* The utmp entry was set by our slave.  Remember
X			 * this so that we can reset it later.
X			 */
X			added_utmp_entry = True;
X#ifndef	USE_SYSV_UTMP
X			tslot = handshake.tty_slot;
X#endif	/* USE_SYSV_UTMP */
X			free(ttydev);
X			ttydev = malloc((unsigned) strlen(handshake.buffer) + 1);
X			strcpy(ttydev, handshake.buffer);
X			break;
X		}
X	    }
X	    /* close our sides of the pipes */
X	    if (!waiting_for_initial_map) {
X		close (cp_pipe[0]);
X		close (pc_pipe[1]);
X	    }
X#endif /* USE_HANDSHAKE */
X	}				/* end if no slave */
X
X	/*
X	 * still in parent (xterm process)
X	 */
X
X#ifdef att
X	/* hung sh problem? */
X	signal (SIGHUP, SIG_DFL);
X#else
X	signal (SIGHUP,SIG_IGN);
X#endif
X
X/*
X * Unfortunately, System V seems to have trouble divorcing the child process
X * from the process group of xterm.  This is a problem because hitting the 
X * INTR or QUIT characters on the keyboard will cause xterm to go away if we
X * don't ignore the signals.  This is annoying.
X */
X
X#if defined(USE_SYSV_SIGNALS) && !defined(SIGTSTP)
X	signal (SIGINT, SIG_IGN);
X
X#ifndef att
X	/* hung shell problem */
X	signal (SIGQUIT, SIG_IGN);
X#endif
X	signal (SIGTERM, SIG_IGN);
X#else /* else is bsd or has job control */
X#ifdef SYSV
X	/* if we were spawned by a jobcontrol smart shell (like ksh or csh),
X	 * then our pgrp and pid will be the same.  If we were spawned by
X	 * a jobcontrol dump shell (like /bin/sh), then we will be in out
X	 * parents pgrp, and we must ignore keyboard signals, or will will
X	 * tank on everything.
X	 */
X	if (getpid() == getpgrp()) {
X	    (void) signal(SIGINT, Exit);
X	    (void) signal(SIGQUIT, Exit);
X	    (void) signal(SIGTERM, Exit);
X	} else {
X	    (void) signal(SIGINT, SIG_IGN);
X	    (void) signal(SIGQUIT, SIG_IGN);
X	    (void) signal(SIGTERM, SIG_IGN);
X	}
X#else	/* SYSV */
X	signal (SIGINT, Exit);
X	signal (SIGQUIT, Exit);
X	signal (SIGTERM, Exit);
X#endif	/* SYSV */
X#endif /* USE_SYSV_SIGNALS and not SIGTSTP */
X
X	return;
X}							/* end spawn */
X
XSIGNAL_T Exit(n)
X	int n;
X{
X	register TScreen *screen = &term->screen;
X        int pty = term->screen.respond;  /* file descriptor of pty */
X#ifdef UTMP
X#ifdef USE_SYSV_UTMP
X	struct utmp utmp;
X	struct utmp *utptr;
X#ifdef WTMP
X	int fd;			/* for /etc/wtmp */
X#endif
X	/* cleanup the utmp entry we forged earlier */
X	if (!resource.utmpInhibit && added_utmp_entry) {
X#ifdef CRAY
X#define PTYCHARLEN 4
X#else
X#define PTYCHARLEN 2
X#endif
X	    utmp.ut_type = USER_PROCESS;
X	    (void) strncpy(utmp.ut_id, ttydev + strlen(ttydev) - PTYCHARLEN,
X		    sizeof(utmp.ut_id));
X	    (void) setutent();
X	    utptr = getutid(&utmp);
X	    /* write it out only if it exists, and the pid's match */
X	    if (utptr && (utptr->ut_pid = screen->pid)) {
X		    utptr->ut_type = DEAD_PROCESS;
X		    utptr->ut_time = time((long *) 0);
X		    (void) pututline(utptr);
X#ifdef WTMP
X		    /* set wtmp entry if wtmp file exists */
X		    if ((fd = open(etc_wtmp, O_WRONLY | O_APPEND)) >= 0) {
X		      (void) write(fd, utptr, sizeof(utmp));
X		      (void) close(fd);
X		    }
X#endif
X
X	    }
X	    (void) endutent();
X	}
X#else	/* not USE_SYSV_UTMP */
X	register int i;
X	struct utmp utmp;
X
X	if (!resource.utmpInhibit && added_utmp_entry &&
X	    (!am_slave && tslot > 0 && (i = open(etc_utmp, O_WRONLY)) >= 0)) {
X		bzero((char *)&utmp, sizeof(struct utmp));
X		lseek(i, (long)(tslot * sizeof(struct utmp)), 0);
X		write(i, (char *)&utmp, sizeof(struct utmp));
X		close(i);
X#ifdef WTMP
X		if (term->misc.login_shell &&
X		    (i = open(etc_wtmp, O_WRONLY | O_APPEND)) >= 0) {
X			(void) strncpy(utmp.ut_line, ttydev +
X			    sizeof("/dev"), sizeof (utmp.ut_line));
X			time(&utmp.ut_time);
X			write(i, (char *)&utmp, sizeof(struct utmp));
X			close(i);
X		}
X#endif /* WTMP */
X	}
X#endif	/* USE_SYSV_UTMP */
X#endif	/* UTMP */
X        close(pty); /* close explicitly to avoid race with slave side */
X	if(screen->logging)
X		CloseLog(screen);
X
X	if (!am_slave) {
X		/* restore ownership of tty and pty */
X		chown (ttydev, 0, 0);
X		chown (ptydev, 0, 0);
X
X		/* restore modes of tty and pty */
X		chmod (ttydev, 0666);
X		chmod (ptydev, 0666);
X	}
X	exit(n);
X	SIGNAL_RETURN;
X}
X
X/* ARGSUSED */
Xresize(screen, TermName, oldtc, newtc)
XTScreen *screen;
Xchar *TermName;
Xregister char *oldtc, *newtc;
X{
X#ifndef USE_SYSV_ENVVARS
X	register char *ptr1, *ptr2;
X	register int i;
X	register int li_first = 0;
X	register char *temp;
X	char *index();
X
X	if ((ptr1 = strindex (oldtc, "co#")) == NULL){
X		strcat (oldtc, "co#80:");
X		ptr1 = strindex (oldtc, "co#");
X	}
X	if ((ptr2 = strindex (oldtc, "li#")) == NULL){
X		strcat (oldtc, "li#24:");
X		ptr2 = strindex (oldtc, "li#");
X	}
X	if(ptr1 > ptr2) {
X		li_first++;
X		temp = ptr1;
X		ptr1 = ptr2;
X		ptr2 = temp;
X	}
X	ptr1 += 3;
X	ptr2 += 3;
X	strncpy (newtc, oldtc, i = ptr1 - oldtc);
X	newtc += i;
X	sprintf (newtc, "%d", li_first ? screen->max_row + 1 :
X	 screen->max_col + 1);
X	newtc += strlen(newtc);
X	ptr1 = index (ptr1, ':');
X	strncpy (newtc, ptr1, i = ptr2 - ptr1);
X	newtc += i;
X	sprintf (newtc, "%d", li_first ? screen->max_col + 1 :
X	 screen->max_row + 1);
X	ptr2 = index (ptr2, ':');
X	strcat (newtc, ptr2);
X#endif /* USE_SYSV_ENVVARS */
X}
X
Xstatic SIGNAL_T reapchild ()
X{
X#if defined(USE_SYSV_SIGNALS) && !defined(SIGTSTP)
X	int status, pid;
X
X	pid = wait(&status);
X	if (pid == -1) {
X		(void) signal(SIGCHLD, reapchild);
X		SIGNAL_RETURN;
X	}
X#else	/* defined(USE_SYSV_SIGNALS) && !defined(SIGTSTP) */
X	union wait status;
X	register int pid;
X	
X#ifdef DEBUG
X	if (debug) fputs ("Exiting\n", stderr);
X#endif	/* DEBUG */
X	pid  = wait3 (&status, WNOHANG, (struct rusage *)NULL);
X	if (!pid) {
X#ifdef USE_SYSV_SIGNALS
X		(void) signal(SIGCHLD, reapchild);
X#endif /* USE_SYSV_SIGNALS */
X		SIGNAL_RETURN;
X	}
X#endif	/* defined(USE_SYSV_SIGNALS) && !defined(SIGTSTP) */
X
X#ifdef PUCC_PTYD
X		closepty(ttydev, ptydev, (resource.utmpInhibit ?  OPTY_NOP : OPTY_LOGIN), Ptyfd);
X#endif /* PUCC_PTYD */
X
X	if (pid != term->screen.pid) {
X#ifdef USE_SYSV_SIGNALS
X		(void) signal(SIGCHLD, reapchild);
X#endif	/* USE_SYSV_SIGNALS */
X		SIGNAL_RETURN;
X	}
X	
X	/*
X	 * Use pid instead of process group (which would have to get before
X	 * the wait call above) so that we don't accidentally hose other
X	 * applications.  Otherwise, somebody could write a program which put
X	 * itself in somebody else's process group.  Also, we call Exit instead
X	 * of Cleanup so that we don't do a killpg on -1 by accident.  Some
X	 * operating systems seem to do very nasty things with that.
X	 */
X	if (pid > 1) {
X	    killpg (pid, SIGHUP);
X	}
X	Exit (0);
X	SIGNAL_RETURN;
X}
X
X/* VARARGS1 */
Xconsolepr(fmt,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9)
Xchar *fmt;
X{
X	extern int errno;
X	extern char *SysErrorMsg();
X	int oerrno;
X	int f;
X 	char buf[ BUFSIZ ];
X
X	oerrno = errno;
X 	strcpy(buf, "xterm: ");
X 	sprintf(buf+strlen(buf), fmt, x0,x1,x2,x3,x4,x5,x6,x7,x8,x9);
X 	strcat(buf, ": ");
X 	strcat(buf, SysErrorMsg (oerrno));
X 	strcat(buf, "\n");	
X	f = open("/dev/console",O_WRONLY);
X	write(f, buf, strlen(buf));
X	close(f);
X#ifdef TIOCNOTTY
X	if ((f = open("/dev/tty", 2)) >= 0) {
X		ioctl(f, TIOCNOTTY, (char *)NULL);
X		close(f);
X	}
X#endif	/* TIOCNOTTY */
X}
X
X
Xremove_termcap_entry (buf, str)
X    char *buf;
X    char *str;
X{
X    register char *strinbuf;
X
X    strinbuf = strindex (buf, str);
X    if (strinbuf) {
X        register char *colonPtr = index (strinbuf+1, ':');
X        if (colonPtr) {
X            while (*colonPtr) {
X                *strinbuf++ = *colonPtr++;      /* copy down */
X            }
X            *strinbuf = '\0';
X        } else {
X            strinbuf[1] = '\0';
X        }
X    }
X    return;
X}
X
X/*
X * parse_tty_modes accepts lines of the following form:
X *
X *         [SETTING] ...
X *
X * where setting consists of the words in the modelist followed by a character
X * or ^char.
X */
Xstatic int parse_tty_modes (s, modelist, nmodes)
X    char *s;
X    struct _xttymodes *modelist;
X    int nmodes;
X{
X    struct _xttymodes *mp;
X    int c, i;
X    int count = 0;
X
X    while (1) {
X	while (*s && isascii(*s) && isspace(*s)) s++;
X	if (!*s) return count;
X
X	for (mp = modelist, i = 0; mp->name; mp++, i++) {
X	    if (strncmp (s, mp->name, mp->len) == 0) break;
X	}
X	if (!mp->name) return -1;
X
X	s += mp->len;
X	while (*s && isascii(*s) && isspace(*s)) s++;
X	if (!*s) return -1;
X
X	if (*s == '^') {
X	    s++;
X	    c = ((*s == '?') ? 0177 : *s & 31);	 /* keep control bits */
X	} else {
X	    c = *s;
X	}
X	mp->value = c;
X	mp->set = 1;
X	count++;
X	s++;
X    }
X}
X
X
Xint GetBytesAvailable (fd)
X    int fd;
X{
X#ifdef FIONREAD
X    static long arg;
X    ioctl (fd, FIONREAD, (char *) &arg);
X    return (int) arg;
X#else
X    struct pollfd pollfds[1];
X
X    pollfds[0].fd = fd;
X    pollfds[0].events = POLLIN;
X    return poll (pollfds, 1, 0);
X#endif
X}
X
SHAR_EOF
chmod 0644 main.c || echo "restore of main.c fails"
if [ $TOUCH = can ]
then
    touch -am 1109132790 main.c
fi
fi
# ============= misc.c ==============
if test -f misc.c; then echo "File misc.c exists"; else
sed 's/^X//' << 'SHAR_EOF' > misc.c &&
X/*
X *	$XConsortium: misc.c,v 1.65 90/03/12 10:30:17 jim Exp $
X */
X
X
X#include <X11/copyright.h>
X
X/*
X * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
X *
X *                         All Rights Reserved
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Digital Equipment
X * Corporation not be used in advertising or publicity pertaining to
X * distribution of the software without specific, written prior permission.
X *
X *
X * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
X * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
X * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
X * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
X * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
X * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
X * SOFTWARE.
X */
X
X#include "ptyx.h"		/* X headers included here. */
X
X#include <stdio.h>
X#include <X11/Xos.h>
X#include <setjmp.h>
X#include <ctype.h>
X#include <pwd.h>
X
X#include <X11/Xatom.h>
X#include <X11/cursorfont.h>
X
X#include <X11/Shell.h>
X#include <X11/Xmu/Error.h>
X#include <X11/Xmu/SysUtil.h>
X#include <X11/Xmu/WinUtil.h>
X
X#include "data.h"
X#include "error.h"
X#include "menu.h"
X
Xextern char *malloc();
Xextern char *mktemp();
Xextern void exit();
Xextern void perror();
Xextern void abort();
X
Xstatic void DoSpecialEnterNotify();
Xstatic void DoSpecialLeaveNotify();
X
X#ifndef lint
Xstatic char rcs_id[] = "$XConsortium: misc.c,v 1.65 90/03/12 10:30:17 jim Exp $";
X#endif	/* lint */
X
Xxevents()
X{
X	XEvent event;
X	register TScreen *screen = &term->screen;
X
X	if(screen->scroll_amt)
X		FlushScroll(screen);
X	XPending (screen->display);
X	do {
X		if (waitingForTrackInfo)
X			return;
X		XNextEvent (screen->display, &event);
X		/*
X		 * Hack to get around problems with the toolkit throwing away
X		 * eventing during the exclusive grab of the menu popup.  By
X		 * looking at the event ourselves we make sure that we can
X		 * do the right thing.
X		 */
X		if (event.type == EnterNotify &&
X		    (event.xcrossing.window == XtWindow(XtParent(term))) ||
X		    (tekWidget &&
X		     event.xcrossing.window == XtWindow(XtParent(tekWidget))))
X		  DoSpecialEnterNotify (&event);
X		else 
X		if (event.type == LeaveNotify &&
X		    (event.xcrossing.window == XtWindow(XtParent(term))) ||
X		    (tekWidget &&
X		     event.xcrossing.window == XtWindow(XtParent(tekWidget))))
X		  DoSpecialLeaveNotify (&event);
X
X		if (!event.xany.send_event ||
X		    screen->allowSendEvents ||
X		    ((event.xany.type != KeyPress) &&
X		     (event.xany.type != KeyRelease) &&
X		     (event.xany.type != ButtonPress) &&
X		     (event.xany.type != ButtonRelease)))
X		    XtDispatchEvent(&event);
X	} while (QLength(screen->display) > 0);
X}
X
X
XCursor make_colored_cursor (cursorindex, fg, bg)
X	int cursorindex;			/* index into font */
X	unsigned long fg, bg;			/* pixel value */
X{
X	register TScreen *screen = &term->screen;
X	Cursor c;
X	register Display *dpy = screen->display;
X	
X	c = XCreateFontCursor (dpy, cursorindex);
X	if (c == (Cursor) 0) return (c);
X
X	recolor_cursor (c, fg, bg);
X	return (c);
X}
X
X/* ARGSUSED */
Xvoid HandleKeyPressed(w, event, params, nparams)
X    Widget w;
X    XEvent *event;
X    String *params;
X    Cardinal *nparams;
X{
X    register TScreen *screen = &term->screen;
X
X#ifdef ACTIVEWINDOWINPUTONLY
X    if (w == (screen->TekEmu ? (Widget)tekWidget : (Widget)term))
X#endif
X	Input (&term->keyboard, screen, event, False);
X}
X/* ARGSUSED */
Xvoid HandleEightBitKeyPressed(w, event, params, nparams)
X    Widget w;
X    XEvent *event;
X    String *params;
X    Cardinal *nparams;
X{
X    register TScreen *screen = &term->screen;
X
X#ifdef ACTIVEWINDOWINPUTONLY
X    if (w == (screen->TekEmu ? (Widget)tekWidget : (Widget)term))
X#endif
X	Input (&term->keyboard, screen, event, True);
X}
X
X/* ARGSUSED */
Xvoid HandleStringEvent(w, event, params, nparams)
X    Widget w;
X    XEvent *event;
X    String *params;
X    Cardinal *nparams;
X{
X    register TScreen *screen = &term->screen;
X
X#ifdef ACTIVEWINDOWINPUTONLY
X    if (w != (screen->TekEmu ? (Widget)tekWidget : (Widget)term)) return;
X#endif
X
X    if (*nparams != 1) return;
X
X    if ((*params)[0] == '0' && (*params)[1] == 'x' && (*params)[2] != '\0') {
X	char c, *p, hexval[2];
X	hexval[0] = hexval[1] = 0;
X	for (p = *params+2; (c = *p); p++) {
X	    hexval[0] *= 16;
X	    if (isupper(c)) c = tolower(c);
X	    if (c >= '0' && c <= '9')
X		hexval[0] += c - '0';
X	    else if (c >= 'a' && c <= 'f')
X		hexval[0] += c - 'a' + 10;
X	    else break;
X	}
X	if (c == '\0')
X	    StringInput (screen, hexval);
X    }
X    else {
X	StringInput (screen, *params);
X    }
X}
X
Xstatic void DoSpecialEnterNotify (ev)
X    register XEnterWindowEvent *ev;
X{
X    register TScreen *screen = &term->screen;
X
X#ifdef ACTIVEWINDOWINPUTONLY
X    if (ev->window == XtWindow(XtParent(screen->TekEmu ?
X					(Widget)tekWidget : (Widget)term)))
X#endif
X      if (((ev->detail) != NotifyInferior) &&
X	  ev->focus &&
X	  !(screen->select & FOCUS))
X	selectwindow(screen, INWINDOW);
X}
X
X/*ARGSUSED*/
Xvoid HandleEnterWindow(w, eventdata, event)
XWidget w;
Xregister XEnterWindowEvent *event;
Xcaddr_t eventdata;
X{
X    /* NOP since we handled it above */
X}
X
X
Xstatic void DoSpecialLeaveNotify (ev)
X    register XEnterWindowEvent *ev;
X{
X    register TScreen *screen = &term->screen;
X
X#ifdef ACTIVEWINDOWINPUTONLY
X    if (ev->window == XtWindow(XtParent(screen->TekEmu ?
X					(Widget)tekWidget : (Widget)term)))
X#endif
X      if (((ev->detail) != NotifyInferior) &&
X	  ev->focus &&
X	  !(screen->select & FOCUS))
X	unselectwindow(screen, INWINDOW);
X}
X
X
X/*ARGSUSED*/
Xvoid HandleLeaveWindow(w, eventdata, event)
XWidget w;
Xregister XEnterWindowEvent *event;
Xcaddr_t eventdata;
X{
X    /* NOP since we handled it above */
X}
X
X
X/*ARGSUSED*/
Xvoid HandleFocusChange(w, eventdata, event)
XWidget w;
Xregister XFocusChangeEvent *event;
Xcaddr_t eventdata;
X{
X        register TScreen *screen = &term->screen;
X
X        if(event->type == FocusIn)
X                selectwindow(screen,
X			     (event->detail == NotifyPointer) ? INWINDOW :
X								FOCUS);
X        else {
X                unselectwindow(screen,
X			       (event->detail == NotifyPointer) ? INWINDOW :
X								  FOCUS);
X		if (screen->grabbedKbd && (event->mode == NotifyUngrab)) {
X		    screen->grabbedKbd = FALSE;
X		    ReverseVideo(term);
X		    XBell(screen->display, 100);
X		}
X	}
X}
X
X
X
Xselectwindow(screen, flag)
Xregister TScreen *screen;
Xregister int flag;
X{
X	if(screen->TekEmu) {
X		if(!Ttoggled)
X			TCursorToggle(TOGGLE);
X		screen->select |= flag;
X		if(!Ttoggled)
X			TCursorToggle(TOGGLE);
X		return;
X	} else {
X		if(screen->cursor_state &&
X		   (screen->cursor_col != screen->cur_col ||
X		    screen->cursor_row != screen->cur_row))
X		    HideCursor();
X		screen->select |= flag;
X		if(screen->cursor_state)
X			ShowCursor();
X		return;
X	}
X}
X
Xunselectwindow(screen, flag)
Xregister TScreen *screen;
Xregister int flag;
X{
X    if (screen->always_highlight) return;
X
X    if(screen->TekEmu) {
X	if(!Ttoggled) TCursorToggle(TOGGLE);
X	screen->select &= ~flag;
X	if(!Ttoggled) TCursorToggle(TOGGLE);
X    } else {
X	screen->select &= ~flag;
X	if(screen->cursor_state &&
X	   (screen->cursor_col != screen->cur_col ||
X	    screen->cursor_row != screen->cur_row))
X	      HideCursor();
X	if(screen->cursor_state)
X	  ShowCursor();
X    }
X}
X
X
XBell()
X{
X	extern XtermWidget term;
X	register TScreen *screen = &term->screen;
X	register Pixel xorPixel = screen->foreground ^ term->core.background_pixel;
X	XGCValues gcval;
X	GC visualGC;
X
X	if(screen->visualbell) {
X		gcval.function = GXxor;
X		gcval.foreground = xorPixel;
X		visualGC = XtGetGC((Widget)term, GCFunction+GCForeground, &gcval);
X		if(screen->TekEmu) {
X			XFillRectangle(
X			    screen->display,
X			    TWindow(screen), 
X			    visualGC,
X			    0, 0,
X			    (unsigned) TFullWidth(screen),
X			    (unsigned) TFullHeight(screen));
X			XFlush(screen->display);
X			XFillRectangle(
X			    screen->display,
X			    TWindow(screen), 
X			    visualGC,
X			    0, 0,
X			    (unsigned) TFullWidth(screen),
X			    (unsigned) TFullHeight(screen));
X		} else {
X			XFillRectangle(
X			    screen->display,
X			    VWindow(screen), 
X			    visualGC,
X			    0, 0,
X			    (unsigned) FullWidth(screen),
X			    (unsigned) FullHeight(screen));
X			XFlush(screen->display);
X			XFillRectangle(
X			    screen->display,
X			    VWindow(screen), 
X			    visualGC,
X			    0, 0,
X			    (unsigned) FullWidth(screen),
X			    (unsigned) FullHeight(screen));
X		}
X	} else
X		XBell(screen->display, 0);
X}
X
XRedraw()
X{
X	extern XtermWidget term;
X	register TScreen *screen = &term->screen;
X	XExposeEvent event;
X
X	event.type = Expose;
X	event.display = screen->display;
X	event.x = 0;
X	event.y = 0;
X	event.count = 0; 
X	
X	if(VWindow(screen)) {
X	        event.window = VWindow(screen);
X		event.width = term->core.width;
X		event.height = term->core.height;
X		(*term->core.widget_class->core_class.expose)(term, &event, NULL);
X		if(screen->scrollbar) 
X			(*screen->scrollWidget->core.widget_class->core_class.expose)(screen->scrollWidget, &event, NULL);
X		}
X
X	if(TWindow(screen) && screen->Tshow) {
X	        event.window = TWindow(screen);
X		event.width = tekWidget->core.width;
X		event.height = tekWidget->core.height;
X		TekExpose (tekWidget, &event, NULL);
X	}
X}
X
XStartLog(screen)
Xregister TScreen *screen;
X{
X	register char *cp;
X	register int i;
X	static char *log_default;
X	char *malloc(), *rindex();
X#ifdef ALLOWLOGFILEEXEC
X	void logpipe();
X#ifdef SYSV
X	/* SYSV has another pointer which should be part of the
X	** FILE structure but is actually a separate array.
X	*/
X	unsigned char *old_bufend;
X#endif	/* SYSV */
X#endif /* ALLOWLOGFILEEXEC */
X
X	if(screen->logging || (screen->inhibit & I_LOG))
X		return;
X	if(screen->logfile == NULL || *screen->logfile == 0) {
X		if(screen->logfile)
X			free(screen->logfile);
X		if(log_default == NULL)
X			mktemp(log_default = log_def_name);
X		if((screen->logfile = malloc((unsigned)strlen(log_default) + 1)) == NULL)
X			return;
X		strcpy(screen->logfile, log_default);
X	}
X	if(*screen->logfile == '|') {	/* exec command */
X#ifdef ALLOWLOGFILEEXEC
X		/*
X		 * Warning, enabling this "feature" allows arbitrary programs
X		 * to be run.  If ALLOWLOGFILECHANGES is enabled, this can be
X		 * done through escape sequences....  You have been warned.
X		 */
X		int p[2];
X		static char *shell;
X
X		if(pipe(p) < 0 || (i = fork()) < 0)
X			return;
X		if(i == 0) {	/* child */
X			close(p[1]);
X			dup2(p[0], 0);
X			close(p[0]);
X			dup2(fileno(stderr), 1);
X			dup2(fileno(stderr), 2);
X#ifdef SYSV
X			old_bufend = _bufend(stderr);
X#endif	/* SYSV */
X			close(fileno(stderr));
X			fileno(stderr) = 2;
X#ifdef SYSV
X			_bufend(stderr) = old_bufend;
X#endif	/* SYSV */
X			close(screen->display->fd);
X			close(screen->respond);
X			if(!shell) {
X				register struct passwd *pw;
X				char *getenv(), *malloc();
X				struct passwd *getpwuid();
X
X				if(((cp = getenv("SHELL")) == NULL || *cp == 0)
X				 && ((pw = getpwuid(screen->uid)) == NULL ||
X				 *(cp = pw->pw_shell) == 0) ||
X				 (shell = malloc((unsigned) strlen(cp) + 1)) == NULL)
X					shell = "/bin/sh";
X				else
X					strcpy(shell, cp);
X			}
X			signal(SIGHUP, SIG_DFL);
X			signal(SIGCHLD, SIG_DFL);
X			setgid(screen->gid);
X			setuid(screen->uid);
X			execl(shell, shell, "-c", &screen->logfile[1], 0);
X			fprintf(stderr, "%s: Can't exec `%s'\n", xterm_name,
X			 &screen->logfile[1]);
X			exit(ERROR_LOGEXEC);
X		}
X		close(p[0]);
X		screen->logfd = p[1];
X		signal(SIGPIPE, logpipe);
X#else
X		Bell();
X		Bell();
X		return;
X#endif
X	} else {
X		if(access(screen->logfile, F_OK) == 0) {
X			if(access(screen->logfile, W_OK) < 0)
X				return;
X		} else if(cp = rindex(screen->logfile, '/')) {
X			*cp = 0;
X			i = access(screen->logfile, W_OK);
X			*cp = '/';
X			if(i < 0)
X				return;
X		} else if(access(".", W_OK) < 0)
X			return;
X		if((screen->logfd = open(screen->logfile, O_WRONLY | O_APPEND |
X		 O_CREAT, 0644)) < 0)
X			return;
X		chown(screen->logfile, screen->uid, screen->gid);
X
X	}
X	screen->logstart = screen->TekEmu ? Tbptr : bptr;
X	screen->logging = TRUE;
X	update_logging();
X}
X
XCloseLog(screen)
Xregister TScreen *screen;
X{
X	if(!screen->logging || (screen->inhibit & I_LOG))
X		return;
X	FlushLog(screen);
X	close(screen->logfd);
X	screen->logging = FALSE;
X	update_logging();
X}
X
XFlushLog(screen)
Xregister TScreen *screen;
X{
X	register Char *cp;
X	register int i;
X
X	cp = screen->TekEmu ? Tbptr : bptr;
X	if((i = cp - screen->logstart) > 0)
X		write(screen->logfd, screen->logstart, i);
X	screen->logstart = screen->TekEmu ? Tbuffer : buffer;
X}
X
X#ifdef ALLOWLOGFILEEXEC
Xvoid logpipe()
X{
X	register TScreen *screen = &term->screen;
X
X#ifdef SYSV
X	(void) signal(SIGPIPE, SIG_IGN);
X#endif	/* SYSV */
X	if(screen->logging)
X		CloseLog(screen);
X}
X#endif /* ALLOWLOGFILEEXEC */
X
X
Xdo_osc(func)
Xint (*func)();
X{
X	register TScreen *screen = &term->screen;
X	register int mode, c;
X	register char *cp;
X	char buf[512];
X	char *bufend = &buf[(sizeof buf) - 1];	/* leave room for null */
X	extern char *malloc();
X	Bool okay = True;
X
X	/* 
X	 * lines should be of the form <ESC> ] number ; string <BEL>
X	 *
X	 * where number is one of 0, 1, 2, or 46
X	 */
X	mode = 0;
X	while(isdigit(c = (*func)()))
X		mode = 10 * mode + (c - '0');
X	if (c != ';') okay = False;
X	cp = buf;
X	while(isprint((c = (*func)()) & 0x7f) && cp < bufend)
X		*cp++ = c;
X	if (c != 7) okay = False;
X	*cp = 0;
X	if (okay) switch(mode) {
X	 case 0:	/* new icon name and title*/
X		Changename(buf);
X		Changetitle(buf);
X		break;
X
X	 case 1:	/* new icon name only */
X		Changename(buf);
X		break;
X
X	 case 2:	/* new title only */
X		Changetitle(buf);
X		break;
X
X	 case 46:	/* new log file */
X#ifdef ALLOWLOGFILECHANGES
X		/*
X		 * Warning, enabling this feature allows people to overwrite
X		 * arbitrary files accessible to the person running xterm.
X		 */
X		if((cp = malloc((unsigned)strlen(buf) + 1)) == NULL)
X			break;
X		strcpy(cp, buf);
X		if(screen->logfile)
X			free(screen->logfile);
X		screen->logfile = cp;
X#else
X		Bell();
X		Bell();
X#endif
X		break;
X
X	case 50:
X		SetVTFont (fontMenu_fontescape, True, buf, NULL);
X		break;
X
X	/*
X	 * One could write code to send back the display and host names,
X	 * but that could potentially open a fairly nasty security hole.
X	 */
X	}
X}
X
Xstatic ChangeGroup(attribute, value)
X     String attribute;
X     XtArgVal value;
X{
X	extern Widget toplevel;
X	Arg args[1];
X
X	XtSetArg( args[0], attribute, value );
X	XtSetValues( toplevel, args, 1 );
X}
X
XChangename(name)
Xregister char *name;
X{
X    ChangeGroup( XtNiconName, (XtArgVal)name );
X}
X
XChangetitle(name)
Xregister char *name;
X{
X    ChangeGroup( XtNtitle, (XtArgVal)name );
X}
X
X#ifndef DEBUG
X/* ARGSUSED */
X#endif
XPanic(s, a)
Xchar	*s;
Xint a;
X{
X#ifdef DEBUG
X	if(debug) {
X		fprintf(stderr, "%s: PANIC!	", xterm_name);
X		fprintf(stderr, s, a);
X		fputs("\r\n", stderr);
X		fflush(stderr);
X	}
X#endif	/* DEBUG */
X}
X
Xchar *SysErrorMsg (n)
X    int n;
X{
X    extern char *sys_errlist[];
X    extern int sys_nerr;
X
X    return ((n >= 0 && n < sys_nerr) ? sys_errlist[n] : "unknown error");
X}
X
X
XSysError (i)
Xint i;
X{
X	int oerrno;
X
X	oerrno = errno;
X	/* perror(3) write(2)s to file descriptor 2 */
X	fprintf (stderr, "%s: Error %d, errno %d: ", xterm_name, i, oerrno);
X	fprintf (stderr, "%s\n", SysErrorMsg (oerrno));
X	Cleanup(i);
X}
X
XError (i)
Xint i;
X{
X	fprintf (stderr, "%s: Error %d\n", xterm_name, i);
X	Cleanup(i);
X}
X
X
X/*
X * cleanup by sending SIGHUP to client processes
X */
XCleanup (code)
Xint code;
X{
X	extern XtermWidget term;
X	register TScreen *screen;
X
X	screen = &term->screen;
X	if (screen->pid > 1) {
X	    (void) killpg (screen->pid, SIGHUP);
X	}
X	Exit (code);
X}
X
X/*
X * sets the value of var to be arg in the Unix 4.2 BSD environment env.
X * Var should end with '=' (bindings are of the form "var=value").
X * This procedure assumes the memory for the first level of environ
X * was allocated using calloc, with enough extra room at the end so not
X * to have to do a realloc().
X */
XSetenv (var, value)
Xregister char *var, *value;
X{
X	extern char **environ;
X	register int index = 0;
X	register int len = strlen(var);
X
X	while (environ [index] != NULL) {
X	    if (strncmp (environ [index], var, len) == 0) {
X		/* found it */
X		environ[index] = (char *)malloc ((unsigned)len + strlen (value) + 1);
X		strcpy (environ [index], var);
X		strcat (environ [index], value);
X		return;
X	    }
X	    index ++;
X	}
X
X#ifdef DEBUG
X	if (debug) fputs ("expanding env\n", stderr);
X#endif	/* DEBUG */
X
X	environ [index] = (char *) malloc ((unsigned)len + strlen (value) + 1);
X	(void) strcpy (environ [index], var);
X	strcat (environ [index], value);
X	environ [++index] = NULL;
X}
X
X/*
X * returns a pointer to the first occurrence of s2 in s1,
X * or NULL if there are none.
X */
Xchar *strindex (s1, s2)
Xregister char	*s1, *s2;
X{
X	register char	*s3;
X	char		*index();
X	int s2len = strlen (s2);
X
X	while ((s3=index(s1, *s2)) != NULL) {
X		if (strncmp(s3, s2, s2len) == 0)
X			return (s3);
X		s1 = ++s3;
X	}
X	return (NULL);
X}
X
X/*ARGSUSED*/
Xxerror(d, ev)
XDisplay *d;
Xregister XErrorEvent *ev;
X{
X    fprintf (stderr, "%s:  warning, error event receieved:\n", xterm_name);
X    (void) XmuPrintDefaultErrorMessage (d, ev, stderr);
X    Exit (ERROR_XERROR);
X}
X
X/*ARGSUSED*/
Xxioerror(dpy)
XDisplay *dpy;
X{
X    (void) fprintf (stderr, 
X		    "%s:  fatal IO error %d (%s) or KillClient on X server \"%s\"\r\n",
X		    xterm_name, errno, SysErrorMsg (errno),
X		    DisplayString (dpy));
X
X    Exit(ERROR_XIOERROR);
X}
X
XXStrCmp(s1, s2)
Xchar *s1, *s2;
X{
X  if (s1 && s2) return(strcmp(s1, s2));
X  if (s1 && *s1) return(1);
X  if (s2 && *s2) return(-1);
X  return(0);
X}
X
Xstatic void withdraw_window (dpy, w, scr)
X    Display *dpy;
X    Window w;
X    int scr;
X{
X    (void) XmuUpdateMapHints (dpy, w, NULL);
X    XWithdrawWindow (dpy, w, scr);
X    return;
X}
X
X
Xvoid set_vt_visibility (on)
X    Boolean on;
X{
X    register TScreen *screen = &term->screen;
X
X    if (on) {
X	if (!screen->Vshow && term) {
X	    VTInit ();
X	    XtMapWidget (term->core.parent);
X	    screen->Vshow = TRUE;
X	}
X    } else {
X	if (screen->Vshow && term) {
X	    withdraw_window (XtDisplay (term), 
X			     XtWindow(XtParent(term)),
X			     XScreenNumberOfScreen(XtScreen(term)));
X	    screen->Vshow = FALSE;
X	}
X    }
X    set_vthide_sensitivity();
X    set_tekhide_sensitivity();
X    update_vttekmode();
X    update_tekshow();
X    update_vtshow();
X    return;
X}
X
Xvoid set_tek_visibility (on)
X    Boolean on;
X{
X    register TScreen *screen = &term->screen;
X
X    if (on) {
X	if (!screen->Tshow && (tekWidget || TekInit())) {
X	    XtRealizeWidget (tekWidget->core.parent);
X	    XtMapWidget (tekWidget->core.parent);
X	    screen->Tshow = TRUE;
X	}
X    } else {
X	if (screen->Tshow && tekWidget) {
X	    withdraw_window (XtDisplay (tekWidget), 
X			     XtWindow(XtParent(tekWidget)),
X			     XScreenNumberOfScreen(XtScreen(tekWidget)));
X	    screen->Tshow = FALSE;
X	}
X    }
X    set_tekhide_sensitivity();
X    set_vthide_sensitivity();
X    update_vtshow();
X    update_tekshow();
X    update_vttekmode();
X    return;
X}
X
Xvoid end_tek_mode ()
X{
X    register TScreen *screen = &term->screen;
X
X    if (screen->TekEmu) {
X	if (screen->logging) {
X	    FlushLog (screen);
X	    screen->logstart = buffer;
X	}
X	longjmp(Tekend, 1);
X    } 
X    return;
X}
X
Xvoid end_vt_mode ()
X{
X    register TScreen *screen = &term->screen;
X
X    if (!screen->TekEmu) {
X	if(screen->logging) {
X	    FlushLog(screen);
X	    screen->logstart = Tbuffer;
X	}
X	screen->TekEmu = TRUE;
X	longjmp(VTend, 1);
X    } 
X    return;
X}
SHAR_EOF
chmod 0644 misc.c || echo "restore of misc.c fails"
if [ $TOUCH = can ]
then
    touch -am 1109132790 misc.c
fi
fi
exit 0
John Harvey	Austin, Texas
AT HOME  ...!sequoia!johnbob!jph  OR
..!uunet!cs.utexas.edu!execu!sequoia!johnbob!jph
AT WORK  johnbob at ausvmq  OR  john at johnbob  OR  johnbob at austin
         @cs.utexas.edu:ibmchs!auschs!johnbob.austin.ibm.com!john  OR
..!uunet!cs.utexas.edu!ibmaus!auschs!johnbob.austin.ibm.com!john
I don't speak for anybody.  Not even myself.



More information about the Comp.unix.aix mailing list