[comp.sources.unix] v16i049: Terminal emulator for NeWS window system, Part02/04

rsalz@uunet.uu.net (Rich Salz) (11/02/88)

Submitted-by: hoptoad!gnu (John Gilmore)
Posting-number: Volume 16, Issue 49
Archive-name: psterm/part02


: psterm part 2 of 4
: To unbundle, sh this file
echo sampl.pstermrc
cat >sampl.pstermrc <<'@@@ Fin de sampl.pstermrc'
%
% @(#)$Header: sampl.pstermrc,v 2.0 88/09/16 00:19:10 eric Release $
% to use this file, just copy it to ~/.pstermrc

% see the beginning of /usr/NeWS/lib/psterm.ps for more
% customizable things

PSTermDict begin

/DefaultTerminalFont /Courier-Bold def

/NoTopBorder {			% use psterm -ui NoTopBorder
	/UserWindowCustom {
		/BorderTop 3 def
		/PaintFrameControls nullproc def
		/PaintFrameLabel nullproc def
		/PaintFocus nullproc def
	} def
} def

/NoIconLabel {			% use psterm -ui NoIconLabel
	/UserWindowCustom {
		/MyIconLabel () store
		/IconFont OnePointFont def
	} def
} def

% this is just a combination of NoTopBorder and NoIconLabel
/BareBones {			% use psterm -ui BareBones
	/UserWindowCustom {
		/BorderTop 3 def
		/PaintFrameControls nullproc def
		/PaintFrameLabel nullproc def
		/PaintFocus nullproc def
		/MyIconLabel () store
		/IconFont OnePointFont def
	} def
} def

end
@@@ Fin de sampl.pstermrc
echo sampl.user.ps
cat >sampl.user.ps <<'@@@ Fin de sampl.user.ps'
%
% @(#)$Header: sampl.user.ps,v 2.1 88/10/04 05:59:50 gnu Release $
% to use this file, copy it to ~/user.ps
%

% these guys switch on and off some of the parts of the file...
/narrowborders true def		% give all windows nice skinny borders
/startclock false def		% start a clock up for me
/startconsole false def		% start a console window for me
/changefocus false def		% make the focus paint around the borders
/newstretch true def		% twiddle with the shape of the stretch box
/initialrootimage null def	% put the name of a picture here if you want

/NetSecurityWanted false store	% stop annoying ``security violation'' popups

 %%%% Redirect stderr for process that have been 'forkunix'ed
   %% This is done so that error message from forked processed can be seen.
   %% Note:  only available under A/UX, hence the errored...
{(/dev/console) setforkunixstderr} errored pop

 %%%% Set up LiteMenus so that submenus are stroked (outlined) and
   %% things you can select are inverted.
{
    /OrigPaintBox /PaintBox load def
    /DiffPaintBox { % value => -
        dup null ne {
	    dup % save a copy for the getmenuaction
	    MenuItems exch get begin X Y W H end rectpath
	    5 setrasteropcode 
	    getmenuaction type /dicttype eq {stroke} {fill} ifelse
        } {pop} ifelse
    } def
    /PaintBox /DiffPaintBox load def
} LitePullRightMenu send

DefaultMenu begin
	/StrokeSelection	true	def
	/Shadow			4	def
	/ShadowColor		0 0 0 rgbcolor def
end

narrowborders {
DefaultWindow begin
	/FrameFont	/Times-Roman findfont 12 scalefont def
	/ZoomSteps	0	def
	/BorderLeft	3	def
	/BorderRight	3	def
	/BorderBottom	3	def
	/BorderTop	16	def
	/stroketop?	true	def
	changefocus {
	/PaintFocus {
		gsave
		FrameCanvas setcanvas
		KeyFocus? {KeyFocusColor} {FrameFillColor} ifelse setcolor
		stroketop? {
			BorderLeft FrameHeight BorderTop sub 2 add moveto
			FrameWidth BorderRight sub
			FrameHeight BorderTop sub 2 add lineto
		} {
			BorderLeft 2 div  FrameHeight BorderTop sub moveto
			BorderLeft 2 div  BorderBottom 2 div lineto
			FrameWidth BorderRight 2 div sub
			BorderBottom 2 div lineto
			FrameWidth BorderRight 2 div sub
			FrameHeight BorderTop sub lineto
		} ifelse
		stroke
		grestore
	} def
	/PaintFrameControls nullproc def
	} if
end
} if

newstretch {
DefaultWindow begin
    /MoveFrameControls { % - => - ([Re]set frame control shapes)
    gsave
	CloseControl setcanvas
	0 FrameHeight BorderTop sub BorderTop ControlSize sub 2 div add
	movecanvas

	StretchControl setcanvas
	FrameWidth ControlSize sub 0 movecanvas
    grestore
    } def

    /CreateFrameControls { % - => - (Create frame control canvases/items)
    gsave
	FrameCanvas setcanvas
        /CloseControl FrameCanvas newcanvas dup begin
	    /Mapped true def
	    /EventsConsumed /AllEvents def
	end def
        /StretchControl FrameCanvas newcanvas dup begin
	    /Mapped true def
	    /EventsConsumed /AllEvents def
	end def
	0 0 ControlSize dup BorderTop le exch BorderLeft le or
	    {ControlSize ControlSize} {BorderTop BorderTop} ifelse
	rectpath CloseControl reshapecanvas
	ControlSize BorderRight gt ControlSize BorderBottom gt and {
		newpath
		0				0		moveto
		0				BorderBottom	lineto
		ControlSize BorderRight sub	BorderBottom	lineto
		ControlSize BorderRight sub	ControlSize	lineto
		ControlSize			ControlSize	lineto
		ControlSize			0		lineto
		closepath
	} {
		0 0 ControlSize ControlSize rectpath
	} ifelse
	StretchControl reshapecanvas
    grestore
    } def
end
} if

/davincipicturemenu [
	(angel)
	(ermine)
	(lady)
	(man)
	(mona-face)
	(mona-hands)
	(mona-smile)
%	(mona-hires)
	(mona)
	(stjerome)
	(virgin)
	(virgino)
] [{currentkey setrootpicture}] /new DefaultMenu send def
/japanesepicturemenu [
	(cherries)
	(fuji)
	(geese)
	(puppet)
	(snow)
	(stormy)
	(washing)
%	(wash-hires)
	(writing)
] [{currentkey setrootpicture}] /new DefaultMenu send def
/sunpicturemenu [
	(founders)
	(sun3110)
	(sun3160c)
	(sun3160m)
	(sun3260h)
	(sun350)
	(sun352)
	(sun352w)
	(sunballs)
	(suncase)
	(sungame)
	(sunnet)
	(sunnfs)
	(sunprism)
] [{currentkey setrootpicture}] /new DefaultMenu send def
/travelpicturemenu [
	(bryce)
	(harem)
	(joshua)
	(lascruces)
	(new_york)
	(pagosa)
	(saturn)
	(fullmoon)
	(shroom)
	(taj-detail)
	(taj)
	(vla)
	(zion)
] [{currentkey setrootpicture}] /new DefaultMenu send def

/picturerootmenu [
	    (Da Vinci =>)	davincipicturemenu
	    (Japanese =>)	japanesepicturemenu
%	    (Sun =>)		sunpicturemenu
	    (Travel =>)		travelpicturemenu
] /new DefaultMenu send def

systemdict begin
/setrootpicture {
	gsave
		framebuffer /Retained true put
		(NEWSHOME) getenv (/images/) append
		exch append (.im8) append readcanvas
		systemdict begin
			/RootImageCanvas exch def
			/PaintRoot {
				gsave
				framebuffer setcanvas
				clippath pathbbox scale pop pop
				RootImageCanvas imagecanvas
			} def
		end
		PaintRoot
	grestore
} def
end

/roots [
	(random)	{ systemdict begin
				/DefaultRootGrayOrColor
				 {random random random hsbcolor} def
				framebuffer /Retained false put
			PaintRoot end }
	(normal)	{ systemdict begin
				/DefaultRootGrayOrColor {.5 .5 .5 hsbcolor} def
				framebuffer /Retained false put
				PaintRoot end }
%	(wedge)		{ (pscode/wl.root.ps) run PaintRoot }
	(dull)		{ systemdict begin
			 	/PaintRoot systemdict /DullPaintRoot get def
				PaintRoot /RootImageCanvas null def end }
	(pictures...)	picturerootmenu
] /new DefaultMenu send def

/term (psterm -ls -t psterm -li 66 -co 132) def		% I like big windows

/loginmenu [
	(local)		{ term forkunix }
% change rsh below to remsh under A/UX
	(hoptoad)	{ (rsh hoptoad ) term append forkunix }
	(polliwog)	{ (rsh polliwog ) term append forkunix }
	(pondscum)	{ (rsh pondscum ) term append forkunix }
	(console)	{
		 (psterm -C -t sun -sl 512 -il Console -fl Console) forkunix }
] /new DefaultMenu send def

0 (Roots =>) roots /insertitem rootmenu send
0 (Login =>) loginmenu /insertitem rootmenu send

systemdict begin
	/DefaultRootGrayOrColor {.5 .5 .5 hsbcolor} def
	systemdict /DullPaintRoot known not {
		/DullPaintRoot systemdict /PaintRoot get def } if
	initialrootimage null ne {
		initialrootimage setrootpicture } { PaintRoot } ifelse
end

startclock {
	(/usr/NeWS/demo/roundclock -s) forkunix pause
} if

startconsole {
	(psterm -C -t sun -sl 512 -il Console -fl Console) forkunix pause
} if

/dragframe? false store	% false means continuously repaint

% /xhair /xhair_m framebuffer setstandardcursor
@@@ Fin de sampl.user.ps
echo psterm.tcap
cat >psterm.tcap <<'@@@ Fin de psterm.tcap'
#
#	Grasshopper Group NeWS Termcaps 1.8  -HD  88/08/23
#	@(#)$Header: psterm.tcap,v 2.1 88/09/23 19:12:35 hugh Release $
#
# nterm is a fancy vt220 terminal emulator for the NeWS window system
nt|nterm:\
	:cr=^M:do=^J:nl=^J:bl=^G:le=^H:ho=\E[H:\
	:co#80:li#65:cl=\E[H\E[2J:bs:am:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\
	:ce=\E[K:cd=\E[J:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\
	:md=\E[1m:mr=\E[7m:me=\E[m:\
	:ku=\E[A:kd=\E[B:kr=\E[C:kl=\E[D:kb=^H:\
	:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:pt:sf=\n:sr=\EM:\
	:al=\E[L:dl=\E[M:dc=\E[P:\
	:MT:ks=\E[?1h\E=:ke=\E[?1l\E>:\
	:is=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l:\
	:rs=\E[r\E<\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l:xn:\
	:AL=\E[%dL:DL=\E[%dM:IC=\E[%d@:DC=\E[%dP:\
	:ti=\E[2J\E[?47h:te=\E[?47l:im=\E[4h:ei=\E[4l:\
	:ts=\E[?E\E[?%i%dT:fs=\E[?F:es:ds=\E[?E:
nt|nterms|nterm terminal emulator (small)(NeWS window system):\
	:co#80:li#24:tc=nterm:
#
# Termcap for NeWS's psterm from Eric Messick & Hugh Daniel
p1|psterm-96x48:\
	:co#96:li#48:tc=psterm-basic:
p1|psterm-90x28:\
	:co#90:li#28:tc=psterm-basic:
p1|psterm-80x24:\
	:co#80:li#24:tc=psterm-basic:
p1|psterm|psterm-basic|psterm-80x34:\
	:am:bs:al=\EA:cd=\EB:ce=\EC:cl=^L:cm=\E%d;%d;:cs=\EE%d;%d;:\
	:dc=\EF:dl=\EK:do=\EP:ei=\ENi:el=\ENl:fs=\ENl:\
	:ho=\ER:hs:im=\EOi:is=\EN*:km:\
	:kd=\E[B:ku=\E[A:kr=\E[C:kl=\E[D:\
	:mb=\EOb:md=\EOd:\
	:me=\EN*:mr=\EOr:nd=\EV:pt:rc=\034:rs=\EN*:sc=\035:\
	:se=\ENo:sf=\EW:sl=\EOl:so=\EOo:sr=\EX:te=\ENt:\
	:ti=\EOt:ts=\EOl:ue=\ENu:\
	:le=\ET:ll=\EU:ul:up=\EY:us=\EOu:vb=\EZ:\
	:co#80:li#34:
#  This is a faster termcap for psterm, Warning: if you use this termcap
#  some control characters you type will do strange things to the screen.
p1|psterm-fast:\
	:am:bs:al=^A:cd=^B:ce=^C:cl=^L:cm=^D%d;%d;:cs=^E%d;%d;:\
	:dc=^F:dl=^K:do=^P:ei=^Ni:el=^Nl:fs=^Nl:\
	:ho=^R:hs:im=^Oi:is=^N*:km:\
	:kd=\E[B:ku=\E[A:kr=\E[C:kl=\E[D:\
	:mb=^Ob:md=^Od:\
	:me=^N*:mr=^Or:nd=^V:pt:rc=\034:rs=^N*:sc=\035:\
	:se=^No:sf=^W:sl=^Ol:so=^Oo:sr=^X:te=^Nt:\
	:ti=^Ot:ts=^Ol:ue=^Nu:\
	:le=^T:ll=^U:ul:up=^Y:us=^Ou:vb=^Z:\
	:co#80:li#34:
####  End of stuff added by Grasshopper Group
@@@ Fin de psterm.tcap
echo psterm.tinfo
cat >psterm.tinfo <<'@@@ Fin de psterm.tinfo'
#
#	Grasshopper Group NeWS Termcaps 1.9  -HD  88/9/03
#	@(#)$Header: psterm.tinfo,v 2.2 88/10/05 17:36:11 eric Release $
#
# nterm is a fancy vt220 terminal emulator for the NeWS window system
nterm,
	am,	xenl,	eslok,
	cols#80,	lines#65,
	bel=^G,	cr=\r,	clear=\E[H\E[2J,
	el=\E[K,	ed=\E[J,	cup=\E[%i%p1%d;%p2%dH,
	cud1=\n,	home=\E[H,	cub1=\b,
	cuf1=\E[C,	cuu1=\E[A,	dch1=\E[P,
	dl1=\E[M,	dsl=\E[?E,	bold=\E[1m,
	smcup=\E[2J\E[?47h,	smir=\E[4h,	rev=\E[7m,
	smso=\E[7m,	smul=\E[4m,	sgr0=\E[m,
	rmcup=\E[?47l,	rmir=\E[4l,	rmso=\E[m,
	rmul=\E[m,	fsl=\E[?F,	is1=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l,
	il1=\E[L,	kbs=\b,	kcud1=\E[B,
	kf1=\EOP,	kf2=\EOQ,	kf3=\EOR,
	kf4=\EOS,	kcub1=\E[D,	kcuf1=\E[C,
	kcuu1=\E[A,	rmkx=\E[?1l\E>,	smkx=\E[?1h\E=,
	nel=\r\n,	dch=\E[%p1%dP,	dl=\E[%p1%dM,
	ich=\E[%p1%d@,	il=\E[%p1%dL,	rs1=\E[r\E<\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l,
	ind=\n,	ri=\EM,	ht=\t,
	tsl=\E[?E\E[?%i%p1%dT,
# Small nterm terminal emulator termcap
nterms|small nterm,
	cols#80,	lines#24,
	bel=^G,	cr=\r,	cud1=\n,
	cub1=\b,	kbs=\b,	kcud1=\n,
	kcub1=\b,	nel=\r\n,	ind=\n,
	use=nterm,
#
# Termcap for NeWS's psterm from Eric Messick & Hugh Daniel
psterm-96x48,
	cols#96,	lines#48,
	bel=^G,	cr=\r,	cud1=\n,
	cub1=\b,	kbs=\b,	kcud1=\n,
	kcub1=\b,	nel=\r\n,	ind=\n,
	use=psterm-basic,
psterm-90x28,
	cols#90,	lines#28,
	bel=^G,	cr=\r,	cud1=\n,
	cub1=\b,	kbs=\b,	kcud1=\n,
	kcub1=\b,	nel=\r\n,	ind=\n,
	use=psterm-basic,
psterm-80x24,
	cols#80,	lines#24,
	bel=^G,	cr=\r,	cud1=\n,
	cub1=\b,	kbs=\b,	kcud1=\n,
	kcub1=\b,	nel=\r\n,	ind=\n,
	use=psterm-basic,
psterm|psterm-basic|psterm-80x34,
	am,	km,	hs,	ul,
	cols#80,	lines#34,
	bel=^G,	cr=\r,	csr=\EE%p1%d;%p2%d;,
	clear=\f,	el=\EC,	ed=\EB,
	cup=\E%p1%d;%p2%d;,	cud1=\EP,	home=\ER,
	cub1=\ET,	cuf1=\EV,	ll=\EU,
	cuu1=\EY,	dch1=\EF,	dl1=\EK,
	blink=\EOb,	bold=\EOd,	smcup=\EOt,
	smir=\EOi,	rev=\EOr,	smso=\EOo,
	smul=\EOu,	sgr0=\EN*,	rmcup=\ENt,
	rmir=\ENi,	rmso=\ENo,	rmul=\ENu,
	flash=\EZ,	fsl=\ENl,	is1=\EN*,
	il1=\EA,	kbs=\b,	kcud1=\E[B,
	kcub1=\E[D,	kcuf1=\E[C,	kcuu1=\E[A,
	nel=\r\n,	rs1=\EN*,	rc=^\,
	sc=^],	ind=\EW,	ri=\EX,
	ht=\t,	tsl=\EOl,
#  This is a faster termcap for psterm, Warning: if you use this termcap
#  some control characters you type will do strange things to the screen
#  on systems that echo typed control characters to the users terminal.
psterm-fast,
	am,	km,	hs,	ul,
	cols#80,	lines#34,
	bel=^G,	cr=\r,	csr=^E%p1%d;%p2%d;,
	clear=\f,	el=^C,	ed=^B,
	cup=^D%p1%d;%p2%d;,	cud1=^P,	home=^R,
	cub1=^T,	cuf1=^V,	ll=^U,
	cuu1=^Y,	dch1=^F,	dl1=^K,
	blink=^Ob,	bold=^Od,	smcup=^Ot,
	smir=^Oi,	rev=^Or,	smso=^Oo,
	smul=^Ou,	sgr0=^N*,	rmcup=^Nt,
	rmir=^Ni,	rmso=^No,	rmul=^Nu,
	flash=^Z,	fsl=^Nl,	is1=^N*,
	il1=^A,	kbs=\b,	kcud1=\E[B,
	kcub1=\E[D,	kcuf1=\E[C,	kcuu1=\E[A,
	nel=\r\n,	rs1=^N*,	rc=^\,
	sc=^],	ind=^W,	ri=^X,
	ht=\t,	tsl=^Ol,
####  End of stuff added by Grasshopper Group
@@@ Fin de psterm.tinfo
echo slave.c
cat >slave.c <<'@@@ Fin de slave.c'
/*
 * This file is a product of Sun Microsystems, Inc. and is provided for
 * unrestricted use provided that this legend is included on all tape
 * media and as a part of the software program in whole or part.
 * Users may copy, modify or distribute this file at will.
 * 
 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
 * 
 * This file is provided with no support and without any obligation on the
 * part of Sun Microsystems, Inc. to assist in its use, correction,
 * modification or enhancement.
 * 
 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
 * OR ANY PART THEREOF.
 * 
 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
 * or profits or other special, indirect and consequential damages, even
 * if Sun has been advised of the possibility of such damages.
 * 
 * Sun Microsystems, Inc.
 * 2550 Garcia Avenue
 * Mountain View, California  94043
 *
 * Modifications to the original Sun Microsystems, Inc. source code
 * made by the Grasshopper Group are in the Public Domain.
 *
 * Extensions to this file by Eric Messick of the Grasshopper Group.
 *
 * Grasshopper Group
 * 212 Clayton St
 * San Francisco, CA 94117
 *
 */

#ifndef lint
static char sccsid[] = "@(#)slave.c 9.6 88/01/19 Copyright 1985 Sun Micro";
static	char RCSid[] = "@(#)$Header: slave.c,v 2.1 88/10/04 04:22:54 eric Release $";
#endif


/*
 * Copyright (c) 1985 by Sun Microsystems, Inc. 
 */

/*-
	slave.c

	slave.c, Tue Apr  1 09:17:08 1986

		David Rosenthal,
		Sun Microsystems
 */

#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#ifdef REF
#include <ref/config.h>
#endif

extern void exit();
extern unsigned sleep();
extern void perror();

#ifndef HAVE_VFORK
#define	vfork()	fork()
#endif

int	Mfd, Sfd;
/* XXX - there should be a library routine to get a pty */
char	ptcname[] = "/dev/ptyXX";
char	ptsname[] = "/dev/ttyXX";
int	pgrp;
extern	int errno;
extern	int BackGround;

FILE       *
spawn_slave(name, args)
    char *name, **args;
{
    FILE *Master;
    int i, pid, uid, gid;
    unsigned delay = 2 ;
#define	MAXDELAY	120
    char *gp, *tp;

    GetTTYDefaults();
#ifdef SYSVREF
/* Micom-Interlan software installs some non-streams based pty's on 'p' */
#ifdef INTERLANTCP
    for (gp = "qrst"; *gp; gp++)
#else
    for (gp = "pqrst"; *gp; gp++)
#endif
#else
    for (gp = "pqrst"; *gp; gp++)
#endif
	for (tp = "0123456789abcdef"; *tp; tp++) {
	    ptcname[sizeof ("/dev/pty")-1] = *gp;
	    ptcname[sizeof ("/dev/ptyX")-1] = *tp;
	    if ((Mfd = open(ptcname, 2)) < 0)
		continue;
	    ptsname[sizeof ("/dev/pty")-1] = *gp;
	    ptsname[sizeof ("/dev/ptyX")-1] = *tp;
	    if ((Sfd = open(ptsname, 2)) >= 0)
		goto done;
	    close(Mfd);
    }
done:
    if (Mfd < 0 || Sfd < 0)
	return (NULL);
    uid = getuid(), gid = getgid();
    (void) chown(ptsname, uid, gid);		/* set tty ownership */
    (void) chmod(ptsname, 0622);		/* set tty protection */
    /*
     * Establish tty state.
     */
    SetTTYState(Sfd);
    /*
     * If we're to operate in the background, fork
     * to return control to the shell and disassociate
     * ourselves from the tty.  The caller closes
     * file descriptors so that, for example, rsh
     * will not be kept around.
     */
    if (BackGround) {
	if (fork())
	    exit(0);
	(void) setpgrp(0, getpid());
	DisAssociateTTY();
    } else
	AssociateTTY();
    Master = fdopen(Mfd, "r+");
    while ((pid = vfork()) < 0 && errno == EAGAIN) {
	sleep(delay);
	if ((delay <<= 1) > MAXDELAY) {
	    close (Mfd); close (Sfd);
	    return (NULL);
	}
    }
    if (pid == 0) {
	/*
	 * Setup controlling tty.
	 */
	for (i = 0; i < 3; i++)
	    (void) dup2(Sfd, i);
	addut(uid, ptsname);
	for (i = getdtablesize(); i > 2; i--)
	    (void) close(i);
	SetupControllingTTY(ptsname);
	(void) setuid(uid), (void) setgid(gid);
	execvp(name, args);
	perror(name);
	exit(errno);
    }
    pgrp = pid;
    close(Sfd);
    return (Master);
}

CleanupPty()
{

    rmut();
    (void) chown(ptsname, 0, 0);		/* revoke ownership */
    (void) chmod(ptsname, 0666);		/* revoke protection */
}
@@@ Fin de slave.c
echo io.c
cat >io.c <<'@@@ Fin de io.c'
/*
 * This file is a product of Sun Microsystems, Inc. and is provided for
 * unrestricted use provided that this legend is included on all tape
 * media and as a part of the software program in whole or part.
 * Users may copy, modify or distribute this file at will.
 * 
 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
 * 
 * This file is provided with no support and without any obligation on the
 * part of Sun Microsystems, Inc. to assist in its use, correction,
 * modification or enhancement.
 * 
 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
 * OR ANY PART THEREOF.
 * 
 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
 * or profits or other special, indirect and consequential damages, even
 * if Sun has been advised of the possibility of such damages.
 * 
 * Sun Microsystems, Inc.
 * 2550 Garcia Avenue
 * Mountain View, California  94043
 *
 * Modifications to the original Sun Microsystems, Inc. source code
 * made by the Grasshopper Group are in the Public Domain.
 *
 * Extensions to this file by Eric Messick of the Grasshopper Group.
 *
 * Grasshopper Group
 * 212 Clayton St
 * San Francisco, CA 94117
 *
 */

#ifndef lint
static char sccsid[] = "@(#)io.c 9.7 88/01/19 Copyright 1985 Sun Micro";
static	char RCSid[] = "@(#)$Header: io.c,v 2.1 88/10/04 04:22:45 eric Release $";
#endif


/*
 * Copyright (c) 1985 by Sun Microsystems, Inc. 
 */
#ifdef REF
#include <sys/types.h>
#include <ref/config.h>
#endif

#ifndef HAVE_SELECT
#ifdef INTERLANTCP
#include <interlan/il_errno.h>
#endif
#include <stropts.h>
#include <poll.h>
#endif
#include <stdio.h>
#include <psio.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/time.h>

extern void perror();

#define	MAX(a,b)	((a)>(b)?(a):(b))
#define	KBDBUFSIZE	4096
#define	PTYBUFSIZE	8192

static	char kbdbuf[KBDBUFSIZE], *kbdfront, *kbdback, *kbdend;
static	char ptybuf[PTYBUFSIZE];	/* buffer for reading from pty slave */
static	int wfproto;			/* prototype for write select mask */
extern	int Mfd;
extern	int errno;
extern	PSFILE *PostScript;
extern	int PageMode;
extern	int PageFull;
extern	int fontisfixedwidth;
extern	int FastPaint;
extern	int DoScrolling;

static	int pty_out();
static	int kbd_input();

/*
 * Input dispatcher: take data from postscript
 * program and pty, dispatching each to the
 * appropriate handler.
 */
terminal(cfd, kfd)
{
    register int n;
#ifdef HAVE_SELECT
    int rf, wf;
    int max;
#else	/* !HAVE_SELECT */
#define PTY 0
#define KEYBOARD 1
#define POSTSCRIPT 2
#define NFDS 3
    struct pollfd rwf[NFDS];
    int i;
#endif	/* !HAVE_SELECT */
    int keyboard, pty, postscript, ndeferred;
    char *deferred;

    PageFull = 0;			/* not inhibiting scrolling */
    ndeferred = 0;			/* no deferred output */
    keyboard = 1<<kfd;
    pty = 1<<cfd;
    postscript = 1<<psio_fileno(PostScript);
#ifdef HAVE_FNDELAY
    (void) fcntl(cfd, F_SETFL, fcntl(cfd, F_GETFL, 0)|FNDELAY);
    (void) fcntl(kfd, F_SETFL, fcntl(kfd, F_GETFL, 0)|FNDELAY);
#else
    (void) fcntl(cfd, F_SETFL, fcntl(cfd, F_GETFL, 0)|O_NDELAY);
    (void) fcntl(kfd, F_SETFL, fcntl(kfd, F_GETFL, 0)|O_NDELAY);
#endif
#ifdef HAVE_SELECT
    max = MAX(kfd, cfd) + 1;
#endif
    kbdend = kbdbuf + KBDBUFSIZE; 
    kbdfront = kbdback = kbdbuf;
    wfproto = 0;
    for (;;) {
	/*
	 * Don't poll for input to be sent to the display
	 * if we have a full screen, or we are blocked already
	 * trying to transmit to the server.
	 */
#ifdef HAVE_SELECT
	rf = (PageFull || (wfproto & postscript)) ? 0 : pty;
	wf = wfproto;
	if (kbdfront != kbdend)		/* space to read from kbd */
	    rf |= keyboard;
	if (select(max, &rf, &wf, (int *)NULL, (struct timeval *)NULL) < 0) {
	    if (errno == EINTR)
		continue;
	    perror("select");
	    break;
	}
#else
	rwf[PTY].fd = -1;
	rwf[PTY].events = 0;
	rwf[KEYBOARD].fd = -1;
	rwf[KEYBOARD].events = 0;
	rwf[POSTSCRIPT].fd = -1;
	rwf[POSTSCRIPT].events = 0;

	if (!(PageFull || (wfproto & postscript))) {
		rwf[PTY].fd = cfd;
		rwf[PTY].events |= POLLIN;
	}

	if (wfproto & pty) {
		rwf[PTY].fd = cfd;
		rwf[PTY].events |= POLLOUT;
	}
	if (wfproto & postscript) {
		rwf[POSTSCRIPT].fd = psio_fileno(PostScript);
		rwf[POSTSCRIPT].events |= POLLOUT;
	}

	if (kbdfront != kbdend) {		/* space to read from kbd */
		rwf[KEYBOARD].fd = kfd;
		rwf[KEYBOARD].events |= POLLIN;
	}
	if (poll(rwf, NFDS, -1) < 0) {
	    if (errno == EINTR)
		continue;
	    perror("poll");
break_here:
	    break;
	}

	/* check to see if any connections were hung up */
	if (rwf[KEYBOARD].revents & POLLHUP || rwf[PTY].revents & POLLHUP
					|| rwf[POSTSCRIPT].revents & POLLHUP)
		break;

	/*  look for exceptional conditions on fd's */
	for (i = 0; i < NFDS; i++) {
		if (rwf[i].revents & (POLLERR | POLLNVAL)) {
			fprintf(stderr, "Error on an fd in poll ");
			fprintf(stderr, "[POLLERR | POLLNVAL]\n");
			goto break_here;	/* should be break, but C has */
						/* no multi-level break */
		}
	}
#endif
	/*
	 * Flush PostScript descriptor.
	 */
#ifdef HAVE_SELECT
	if (wf & postscript && (psio_flush(PostScript) == 0))
#else
	if (rwf[POSTSCRIPT].revents & POLLOUT && (psio_flush(PostScript) == 0))
#endif
	    wfproto &= ~postscript;
	/*
	 * Try to flush pty, if clogged, before reading from keyboard.
	 */
#ifdef HAVE_SELECT
	if (wf & pty)
#else
	if (rwf[PTY].revents & POLLOUT)
#endif
	{
	    wfproto &= ~pty;
	    pty_out();
	}
	/*
	 * Take keyboard input.
	 */
#ifdef HAVE_SELECT
	if (rf & keyboard)
#else
	if (rwf[KEYBOARD].revents & POLLIN)
#endif
	{
	    errno = 0;
	    n = read(kfd, kbdfront, (unsigned)(kbdend-kbdfront));
	    if (n <= 0) {
		if (errno != EWOULDBLOCK) {
#ifdef HAVE_SELECT	/* Connection Reset is checked above in SYSVREF */
		    if (n < 0 && errno != ECONNRESET)
#endif
			    perror("keyboard");
		    break;
		}
	    } else if (n > 0)
		kbd_input(n);
	}
	/*
	 * If pty_out or kbd_input changed
	 * PageFull, loop to inhibit output.
	 */
	if (PageFull)			/* loop if inhibiting output */
	    continue;
	/*
	 * If screen output was blocked due to previous PageFull condition,
	 * resume it.  Note that this may leave us back in PageFull mode,
	 * and interrupted tcap ops may still need the chars in ptybuf.
	 */
#ifdef lint
	deferred = (char *)0 ;
#endif
	if (ndeferred) {
	    n = tc_display((u_char *)deferred, ndeferred);
	    if (n > 0)
		deferred += (ndeferred - n);
	    ndeferred = n;
	    tc_refresh(0);
	    if (PageFull)		/* if PageFull, can't touch ptybuf */
		continue;
	}
	/*
	 * Finally, take pty stuff and send it to the display
	 * except when we're already flush with output.
	 */
#ifdef HAVE_SELECT
	if ((wfproto & postscript) == 0 && rf & pty)
#else
	if ((wfproto & postscript) == 0 && rwf[PTY].revents & POLLIN)
#endif
	{
	    errno = 0;
	    n = read(cfd, ptybuf, PTYBUFSIZE);
#ifdef HAVE_SELECT
	    if (n < 0) {
		if (errno != EIO) {
/* BEGIN SUN BUG WORKAROUND */
			if (errno == EWOULDBLOCK)
			    continue;
/* END SUN BUG WORKAROUND */
			perror("pty");
		}
		break;
	    }
#else
	    if (n == 0)
		continue;
	    if (n < 0) {
		if (errno == EAGAIN)
			continue;
		perror("pty");
		break;
	    }
#endif
	    ndeferred = tc_display((u_char *)ptybuf, n);
	    if (ndeferred)
		deferred = ptybuf + (n - ndeferred);
	    tc_refresh(0);
	}
#ifdef notdef
if (wfproto & postscript) fprintf(stderr, "blocked\n");
#endif
    }
}

/*
 * Flush PostScript destined for window.
 * If all data was not written, then mark
 * the select mask to find out when data
 * has been flushed to the network.
 */
FlushPostScript()
{

    if (!(psio_flush(PostScript) == 0))
	wfproto |= 1<<psio_fileno(PostScript);
}

/*
 * Flush output to pty.
 */
static
pty_out()
{
	register int cc;

	if ((cc = kbdfront - kbdback) > 0) {
	    if (PageMode) {
		if (PageFull) {
		    switch (*kbdback) {
		    case '\r':
			--cc, kbdback++;
			scrollreset(1);
			break;
		    case ' ':
			--cc, kbdback++;
			/* fall thru... */
		    default:
			scrollreset(0);
			break;
		    }
		    if (cc < 1) {
			kbdfront = kbdback = kbdbuf;
			return;
		    }
		} else
		    scrollreset(0);
	    }
	    cc = write(Mfd, kbdback, (unsigned)cc);
	    if (cc < 0) {
		if (errno != EWOULDBLOCK)
		    perror("master pty");
	    } else
		kbdback += cc;
	}
	if (kbdfront != kbdback)
	    wfproto |= 1<<Mfd;		/* must explicity reenable */
	else
	    kbdfront = kbdback = kbdbuf;
}

#define EVENT_ESCAPE		0200	/* introduce event packet */

#define EVENT_REPAIR		'a'	/* window resized or damaged */
#define	EVENT_BEGINSEL		'b'	/* set selection start */
#define	EVENT_EXTSEL		'c'	/* drag end of current selection */
#define	EVENT_ENDSEL		'd'	/* complete selection */
#define EVENT_TOGGLEAM		'e'	/* toggle auto-margins */
#define EVENT_TOGGLEPM		'f'	/* toggle page mode */
#define EVENT_ROWCOL		'g'	/* new row/col size selected */
#define	EVENT_FONTFIXED		'h'	/* just switched to a fixed width font */
#define EVENT_FONTVAR		'i'	/* just switched to a variable width font */
#define	EVENT_RECTSEL		'j'	/* set rect selection start */
#define EVENT_EXTRECT		'k'	/* extend rect selection */
#define EVENT_SCROLL		'l'	/* scrollbar movement report */
#define EVENT_SAVESIZE		'm'	/* change number of lines saved */
#define EVENT_ENDREFRESH	'n'	/* postscript side has completed refresh */
#define EVENT_FASTPAINT		'o'	/* set or clear fastpaint */
#define EVENT_DOSCROLL		'p'	/* set or clear use of scrolling */

/*
 * Handle keyboard input + postscript events.
 */
static
kbd_input(n)
register int n;
{
	register unsigned char *p, *d;
	register n2;
	extern int RefreshSuppressed;
	int	col, row, rank, dorefresh = 0, doresize = 0, rect = 0 ;

#define NEXTVAL		while (n-- > 0 && *p++ != '\n') ;

	for (p = (unsigned char *)kbdfront, n2 = 0, d = p; n > 0;) {
		if (*p == EVENT_ESCAPE) {
			p++ ;
			if (--n > 0) {
				n-- ;
				switch (*p++) {
				case EVENT_TOGGLEAM:
					toggleautomargins();
					break;
				case EVENT_TOGGLEPM:
					togglepagemode();
					if (PageFull) {
						/* resume output if blocked */
						scrollreset(0);
						dorefresh++;
						}
					break;
				case EVENT_REPAIR:
					RefreshSuppressed = 0 ;
					doresize++ ;
					break;
				case EVENT_RECTSEL:
					rect = 1 ;	/* fall through... */
				case EVENT_BEGINSEL:
					/* col row rank size mode preview */
					if (n>0) { col = atoi((char *)p); NEXTVAL; }
					if (n>0) { row = atoi((char *)p); NEXTVAL; }
					if (n>0) {
						rank = atoi((char *)p); NEXTVAL;
						tc_deselect(rank);
						tc_extend_selection(col, row,
								rank, rect);
						dorefresh++;
						rect = 0 ;
						}
					break;
				case EVENT_EXTRECT:
					rect = 1 ;	/* fall through... */
				case EVENT_EXTSEL:
					/* col row rank size mode preview */
					if (n>0) { col = atoi((char *)p); NEXTVAL; }
					if (n>0) { row = atoi((char *)p); NEXTVAL; }
					if (n>0) {
						rank = atoi((char *)p); NEXTVAL;
						tc_extend_selection(col, row,
								rank, rect);
						dorefresh++;
						rect = 0 ;
						}
					break;
				case EVENT_ENDSEL:
					/* col row rank size mode preview */
					if (n>0) { col = atoi((char *)p); NEXTVAL; }
					if (n>0) { row = atoi((char *)p); NEXTVAL; }
					if (n>0) {
						rank = atoi((char *)p); NEXTVAL;
						tc_extend_selection(col, row,
								rank, rect);
						tc_report_selection(rank);
						dorefresh++;
						}
					break;
				case EVENT_ESCAPE:
					*d++ = EVENT_ESCAPE ;
					n2++ ;
					break;
				case EVENT_ROWCOL:
					if (n>0) { col = atoi((char *)p); NEXTVAL; }
					if (n>0) {
						row = atoi((char *)p); NEXTVAL;
						change_rowcol(row, col);
						}
					break;
				case EVENT_FONTFIXED:
					fontisfixedwidth = 1 ;
					break;
				case EVENT_FONTVAR:
					fontisfixedwidth = 0 ;
					break;
				case EVENT_SCROLL:
					if (n>0) {
						row = atoi((char *)p); NEXTVAL;
						scroll_to(row);
						dorefresh++;
						}
					break;
				case EVENT_SAVESIZE:
					if (n>0) {
						row = atoi((char *)p); NEXTVAL;
						set_scroll_save(row);
						dorefresh++;
						}
					break;
				case EVENT_ENDREFRESH:
					end_refresh();
					dorefresh++;
					break;
				case EVENT_FASTPAINT:
					if (n>0) {
						FastPaint = atoi((char *)p); NEXTVAL;
						}
					break;
				case EVENT_DOSCROLL:
					if (n>0) {
						DoScrolling = atoi((char *)p); NEXTVAL;
						}
					break;
					}
				}
			}
		else	{
			*d++ = *p++ ;
			n-- ;
			n2++ ;
			}
		}
	if (doresize)
		do_display_resize();
	if (n2 > 0)
		kbdfront += n2;
	if (kbdfront != kbdback) {
		tc_deselect(1);
		pty_out();
		}
	if (dorefresh)
		tc_refresh(0);
}
@@@ Fin de io.c
echo main.c
cat >main.c <<'@@@ Fin de main.c'
/*
 * This file is a product of Sun Microsystems, Inc. and is provided for
 * unrestricted use provided that this legend is included on all tape
 * media and as a part of the software program in whole or part.
 * Users may copy, modify or distribute this file at will.
 * 
 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
 * 
 * This file is provided with no support and without any obligation on the
 * part of Sun Microsystems, Inc. to assist in its use, correction,
 * modification or enhancement.
 * 
 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
 * OR ANY PART THEREOF.
 * 
 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
 * or profits or other special, indirect and consequential damages, even
 * if Sun has been advised of the possibility of such damages.
 * 
 * Sun Microsystems, Inc.
 * 2550 Garcia Avenue
 * Mountain View, California  94043
 *
 * Modifications to the original Sun Microsystems, Inc. source code
 * made by the Grasshopper Group are in the Public Domain.
 *
 * Extensions to this file by Eric Messick of the Grasshopper Group.
 *
 * Grasshopper Group
 * 212 Clayton St
 * San Francisco, CA 94117
 *
 */

#ifndef lint
static	char sccsid[] = "@(#)main.c 9.7 88/01/19 Copyright 1985 Sun Micro";
static	char RCSid[] = "@(#)$Header: main.c,v 2.2 88/10/04 04:22:48 eric Release $";
#endif

/*
 * Copyright (c) 1985 by Sun Microsystems, Inc.
 */


#include <stdio.h>
#include <psio.h>
#include <signal.h>
#include <pwd.h>
#include <fcntl.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#ifdef SYSVREF
#ifdef INTERLANTCP
#include <interlan/il_types.h>
#include <interlan/socket.h>
#include <interlan/in.h>
#include <interlan/netdb.h>
#else
#include <sys/types.h>
#endif
#else
#ifdef REF
#include <sys/types.h>
#endif
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#endif

#ifdef REF
#include <ref/config.h>
#endif

#ifdef SYSVREF
#define	SIGCHLD	SIGCLD
#else
#include <sys/wait.h>
#endif

extern void exit();
extern void perror();
extern char *strcpy();
#ifndef bcopy
extern void bcopy();
#endif
extern void endpwent();
extern void free();
extern char *strcat();

extern	PSFILE *Connect_To_Server();

int	console;
static	int KillChild();
static	int ReapChild();
static	char *term = NULL;
static	int seed = 0;
static	int Persist;
static	int loginshell = 0;
static	int tflag = 0;
static	char *framelabel = NULL;
static	char *iconlabel = NULL;
static	char *userinit = "" ;
static	char *font = "" ;
static	int xorg = -1;
static	int yorg = -1;
static	int iconx = -1;
static	int icony = -1;
static	int reload = 0;
static	int starticonic = 0 ;
static	int save_lines = 0 ;
int	fontsize = -1;
int	BackGround = 1;
int	PageMode = 0;			/* "pause on end of page" mode */
int	userCharsPerLine = -1;
int	userLinesPerScreen = -1;

main(argc,argv)
    int	argc;
    char **argv;
{
    char *s_name, **s_args, *argv0 = argv[0];
    FILE *Client;
    PSFILE *Keyboard;
    extern char *getenv();
    extern PSFILE *tc_init_screen();
    extern FILE *spawn_slave();

    BackGround = isatty(0) ;

    for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
	if (strcmp(argv[0], "-bg") == 0 || strcmp(argv[0], "-ga") == 0) {
	    BackGround++;		/* put ourself in the background */
	    continue;
	}
	if (strcmp(argv[0], "-C") == 0) {
	    console++;
	    continue;
	}
	if (strcmp(argv[0], "-co") == 0) {
	    if (--argc > 0)
		userCharsPerLine = atoi(*++argv);
	    continue;
	}
	if (strcmp(argv[0], "-F") == 0) {
	    if (--argc > 0) {
		font = *++argv;
	    }
	    continue;
	}
	if (strcmp(argv[0], "-f") == 0) {
	    continue;
	}
	if (strcmp(argv[0], "-fg") == 0) {
	    BackGround = 0 ;		/* don't put ourself in the background */
	    continue;
	}
	if (strcmp(argv[0], "-fl") == 0) {
	    if (--argc > 0)
		framelabel = *++argv;
	    continue;
	}
	if (strcmp(argv[0], "-fs") == 0) {
	    if (--argc > 0)
		fontsize = atoi(*++argv);
	    continue;
	}
	if (strcmp(argv[0], "-ic") == 0) {
	    starticonic++;
	    continue;
	}
	if (strcmp(argv[0], "-il") == 0) {
	    if (--argc > 0)
		iconlabel = *++argv;
	    continue;
	}
	if (strcmp(argv[0], "-ixy") == 0) {
	    if (--argc > 0)
		iconx = atoi(*++argv);
	    if (--argc > 0)
		iconx = atoi(*++argv);
	    if (iconx >= 0 && icony >= 0)
		continue;
	}
	if (strcmp(argv[0], "-li") == 0) {
	    if (--argc > 0)
		userLinesPerScreen = atoi(*++argv);
	    continue;
	}
	if (strcmp(argv[0], "-ls") == 0) {
	    loginshell++;
	    continue;
	}
	if (strcmp(argv[0], "-pm") == 0 || strcmp(argv[0], "-ps") == 0) {
	    PageMode++;			/* enable page mode */
	    continue;
	}
	if (strcmp(argv[0], "-r") == 0) {
	    reload++;
	    continue;
	}
	if (strcmp(argv[0], "-s") == 0) {
	    if (--argc > 0)
		seed = atoi(*++argv);
	    continue;
	}
	if (strcmp(argv[0], "-sl") == 0) {
	    if (--argc > 0)
		save_lines = atoi(*++argv);
	    continue;
	}
	if (strcmp(argv[0], "-t") == 0) {
	    if (--argc > 0) {
		term = *++argv;
		tflag++;
	    }
	    continue;
	}
	if (strcmp(argv[0], "-ui") == 0) {
	    if (--argc > 0) {
		userinit = *++argv;
	    }
	    continue;
	}
	if (strcmp(argv[0], "-w") == 0) {
	    Persist++;
	    continue;
	}
	if (strcmp(argv[0], "-xy") == 0) {
	    if (--argc > 0)
		xorg = atoi(*++argv);
	    if (--argc > 0)
		yorg = atoi(*++argv);
	    if (xorg >= 0 && yorg >= 0)
		continue;
	}
	fprintf(stderr, "Usage: %s %s \\\n\t%s \\\n\t%s \\\n\t%s\n", argv0,
		"[-bg] [-C] [-co columns] [-F font] [-f] [-fg] [-fl framelabel]",
		"[-fs fontsize] [-ic] [-il iconlabel] [-ixy x y] [-li lines]",
		"[-ls] [-pm] [-r] [-sl savelines] [-t termtype] [-ui userinit] [-w]",
		"[-xy x y] [command]");
	(void) Connect_To_Server();
	Fatal("psterm:  error in arguments", (char *)NULL);
    }
    if (loginshell) {
	char *s, *p, *malloc();
#ifndef SYSVREF
	char *rindex(), *index();
#else
#define index(s, c)		(char *)strchr(s, c)
#endif
	struct passwd *pw, *getpwuid();
	static char *loginargv[4];

	s_name = "/bin/sh";		/* default shell name */
	s_args = loginargv;

	s_args[0] = "-sh";
	s_args[1] = 0;
	if (pw = getpwuid(getuid())) {
	    if (pw->pw_dir)
		set_environment_var("HOME", pw->pw_dir);
	    if (pw->pw_name) {
		set_environment_var("LOGNAME", pw->pw_name);
	        set_environment_var("USER", pw->pw_name);
	    }
	    if (pw->pw_shell) {
		if (s = rindex(pw->pw_shell,'/')) {
		    p = malloc ((unsigned)strlen(s)+4);
		    if (p) {
			sprintf(p, "-%s", s+1);
			s_args[0] = p;
		    }
		    p = malloc((unsigned)strlen(pw->pw_shell)+4);
		    if (p) {
			s_name = p;
			strcpy(s_name, pw->pw_shell);
		    }
		    set_environment_var("SHELL",pw->pw_shell);
		}
	    }
	    endpwent();
	}
	if (argc > 0) {
	    int i, count = 0;
	    /*
	     * This goofy business in case someone wants to run complex
	     * shell commands after login-shell initialization...
	     */
	    for (i=0; i<argc; i++) {
		count += strlen(argv[i]);
	    }
	    if (s_args[2] = malloc((unsigned)count+argc+4)) {
		s_args[2][0] = 0;
		for (i=0; i<argc; i++) {
		    if (i)
			strcat(s_args[2], " ");
		    strcat(s_args[2], argv[i]);
		}
		s_args[0]++;
		s_args[1] = "-c";
		s_args[3] = 0;
	    }
	}
	/*
	 * if $NEWSSERVER isn't defined and stdin is a socket, chances
	 * are we're being invoked with rsh, so figure out where the
	 * rsh command came from and use that for NEWSSERVER.
	 */
	if (getenv("NEWSSERVER")==0) {
	    struct hostent *hp;
	    struct sockaddr_in remote;
	    int n = sizeof remote;
	    if (getpeername(0, (struct sockaddr *)&remote, &n) == 0) {
		if (remote.sin_family == AF_INET) {
		    char srv[128];
		    sprintf(srv, "%lu.%d;",
			    ntohl(remote.sin_addr.s_addr), 2000);
		    hp = gethostbyaddr((char*) &remote.sin_addr,
				       sizeof (remote.sin_addr),
				       remote.sin_family);
		    if (hp)
			strcat(srv,hp->h_name);
		    set_environment_var("NEWSSERVER", srv);
		}
	    }
	}
	if (framelabel == NULL) {
	    static char labelbuf[128];
	    gethostname(labelbuf, sizeof labelbuf);
	    if ((p = index(labelbuf, '.')) != NULL)
		*p = 0;
	    if (argc > 0) {
		strcat(labelbuf, " ");
		strcat (labelbuf, argv[0]);
	    }	    
	    framelabel = labelbuf;
	}
	if (iconlabel == NULL)
	    iconlabel = framelabel;
    } else if (argc > 0) {
	s_name = *argv;
	s_args = argv;
    } else {
#ifndef SYSVREF
	static char *def_argv[] = { "csh", NULL};
#else
	static char *def_argv[] = { "-sh", NULL};
#endif

	s_args = def_argv;
	if ((s_name = getenv("SHELL")) == NULL) {
#ifndef SYSVREF
	    s_name = *def_argv;
	    s_args[0] = s_name;
#else
	    s_name = "sh";
#endif
	}
	else {
	    s_args[0] = s_name;
	}
    }
    if ( !tflag || term == NULL) {
#ifdef RandomBehaviour
	/* Choose one at random - should scan termcap? */
	static char * def_term[] = {
	    "ansi", "h19", "wyse",
	};

	if (seed == 0)
	    seed = getpid();
	srand(seed);
	term = def_term[(rand()>>4)%((sizeof def_term)/(sizeof def_term[0]))];
#else
	term = "psterm";
#endif
    }
    if (BackGround) {
	int i;
	/*
	 * Close any extraneous files.
	 */
	for (i = getdtablesize(); i > 2; i--)
	    close(i);
    }
    if (xorg < 0)
	xorg = 0;
    if (yorg < 0)
	yorg = 0;
    Keyboard =
	tc_init_screen(term, xorg, yorg, fontsize, framelabel, iconlabel,
			reload, userinit, font, starticonic, iconx, icony, save_lines);
    if (Keyboard == NULL) {
	char *foo;
	foo = getenv("NEWSSERVER");
	if (foo)
	    Fatal("Can't connect to NeWS server at: %s", foo);
	else
	    Fatal("Can't connect to NeWS server; did you set NEWSSERVER?",
		  (char *)NULL);
    }

    tc_initmodemenu();
    set_environment_var("TERM", term);
    if ((Client = spawn_slave(s_name, s_args)) == NULL)
	Fatal("Cannot spawn %s", s_name);
    if (signal(SIGINT, SIG_IGN) != SIG_IGN)
	signal(SIGINT, KillChild);
    if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
	signal(SIGQUIT, KillChild);
    signal(SIGHUP, KillChild);
    signal(SIGTERM, KillChild);
    signal(SIGCHLD, ReapChild);
    terminal(fileno(Client), psio_fileno(Keyboard));
    Exit(0);
    /*NOTREACHED*/
}

Fatal(fmt, a1)
char *fmt, *a1;
{
	extern int ConnectionEstablished;
	char buf[1024];

	if (ConnectionEstablished) {
		sprintf(buf, fmt, a1);
		PostScriptErrorMessage(buf);
		}
	else	{
		fprintf(stderr, "psterm: ");
		fprintf(stderr, fmt, a1);
		fprintf(stderr, ".\n");
		}
	Exit(1);
}

Exit(status)
{

    CleanupPty();
    exit(status);
}

static
KillChild(sig)
{
    extern int pgrp;

    if (pgrp != 0)
	killpg(pgrp, sig);
    CleanupPty();
    signal(sig, SIG_DFL);
    kill(0, sig);
}

static
ReapChild()
{
#ifdef HAVE_WAIT3
    union wait status;
    int pid = wait3(&status, WNOHANG, 0);
#else	/* !HAVE_WAIT3 */
    int status, pid = wait(&status);
    signal(SIGCHLD, ReapChild);
#endif

    if (pid < 0)
	perror("fruitless wait3");
    else if (Persist == 0)
	Exit(0);
}

set_environment_var(name, value)
char       *name, *value; {
    register    len;
    register char **ap;
    register char **new;
    register char *buf;
    static      alloced = 0;
    extern char **environ;

    len = strlen(name);
    buf = (char *) malloc((unsigned)(len + strlen(value) + 2));
    if (buf==NULL) return;
    sprintf(buf, "%s=%s", name, value);
    for (ap = environ; *ap; ap++)
	if (strncmp(*ap, buf, len+1) == 0) {
	    *ap = buf;
	    return;
	}
    len = ap - environ;
    new = (char **) malloc((unsigned)((len + 2) * sizeof(char *)));
    if (new==NULL) return;
    bcopy((char *)environ, (char *)new, len * sizeof(char *));
    new[len] = buf;
    new[len + 1] = 0;
    if (alloced)
	free((char *)environ);
    alloced = 1 ;
    environ = new;
}

unsetenv(name)
char *name;
{
	register    len;
	register char **ap;
	register char **new;
	extern char **environ;

	len = strlen(name);
	for (new = ap = environ;  (*new = *ap) != NULL;  ap++) {
		if (strncmp(*ap, name, len) == 0  &&  (*ap)[len] == '=') {
			/* Memory leak bug: we cannot free(*ap) here, because we don't know
			 * whether *ap was created with putenv(). */
			}
		else	new++;
		}
}
@@@ Fin de main.c
echo display.c
cat >display.c <<'@@@ Fin de display.c'
/*
 * This file is a product of Sun Microsystems, Inc. and is provided for
 * unrestricted use provided that this legend is included on all tape
 * media and as a part of the software program in whole or part.
 * Users may copy, modify or distribute this file at will.
 * 
 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
 * 
 * This file is provided with no support and without any obligation on the
 * part of Sun Microsystems, Inc. to assist in its use, correction,
 * modification or enhancement.
 * 
 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
 * OR ANY PART THEREOF.
 * 
 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
 * or profits or other special, indirect and consequential damages, even
 * if Sun has been advised of the possibility of such damages.
 * 
 * Sun Microsystems, Inc.
 * 2550 Garcia Avenue
 * Mountain View, California  94043
 *
 * Modifications to the original Sun Microsystems, Inc. source code
 * made by the Grasshopper Group are in the Public Domain.
 *
 * Extensions to this file by Eric Messick of the Grasshopper Group.
 *
 * Grasshopper Group
 * 212 Clayton St
 * San Francisco, CA 94117
 *
 */

#ifndef lint
static char sccsid[] = "@(#)display.c 9.5 88/01/19 Copyright 1985 Sun Micro";
static char RCSid[] =
	"@(#)$Header: display.c,v 2.2 88/10/04 05:11:23 eric Release $";
#endif

/*
 * Copyright (c) 1985 by Sun Microsystems, Inc. 
 */

/*-
	display.c

	display.c, Wed Mar 26 15:56:31 1986

		David Rosenthal,
		Sun Microsystems
 */

#ifdef	notdef
#define Diagnose
#endif
/*
 * Screen display module 
 *
 * The external interface of this module is the routine tc_refresh(), and the
 * initialization routine tc_init_screen(). 
 */

#include	<sys/types.h>
#ifdef REF
#include	<ref/config.h>
#endif
#include	<sys/ioctl.h>
#include	<sys/signal.h>
#include	<sys/file.h>
#include	"screen.h"
#include	"tcap.h"

extern void free();
#ifndef bzero
extern void bzero();
#endif
#ifndef bcopy
extern void bcopy();
#endif
extern void perror();

#define CHARS_PER_LINE		80
#define LINES_PER_SCREEN	24

#define TypicalWidth		80

#define min(x, y) (((x)<(y))?(x):(y))

int     CharsPerLine = CHARS_PER_LINE;
int     LinesPerScreen = LINES_PER_SCREEN;
struct pair Dot = {0, 0};

int fontisfixedwidth = 1 ;

int ConnectionEstablished = 0 ;

static Repairing;
static struct pair ScreenDot = {0, 0};
static char *CursorChar = " ";
static u_char CursorProp = 0 ;
extern int PageFull;

int RefreshSuppressed = 1;

int TotalScrollLength = 0 ;
int ScrollLength = 0 ;
int ScrollY = 0 ;
int ScrollLinesSaved = 0 ;
int userScrollLength = 0 ;
int FastPaint = 1 ;
int DoScrolling = 1 ;

struct line **scroll_area;

char *
Malloc(size)
int size;
{
	extern char *malloc();
	char *ret;

	if ((ret=malloc((unsigned)size))==NULL)
		Fatal("Out of Memory", (char *)NULL);
	return ret;
}

static
RemoveCursor()
{
	if ((ScreenDot.x >= 0) && (! (CursorProp & ReverseVideoLook)))
		CursorDown(ScreenDot.x, ScreenDot.y, CursorChar, 1);
	ScreenDot.x = -1;
}

static
PlaceCursor(x, y)
{
    register struct line *l;

    if (x >= CharsPerLine) x = CharsPerLine - 1;
    if (x < 0) x = 0;

    if (y >= LinesPerScreen) y = LinesPerScreen - 1;
    if (y < 0) y = 0;

    ScreenDot.x = x ;
    ScreenDot.y = y + ScrollLength - LinesPerScreen - ScrollY ;

    l = screen[y];
    CursorChar = l->body + x ;
    CursorProp = l->prop[x] ;

    if (ScreenDot.y >= LinesPerScreen) {
	ScreenDot.x = -1 ;
	return;
	}

    if (!PageFull)			/* hide cursor if output blocked */
	CursorUp(ScreenDot.x, ScreenDot.y, CursorChar, 1);
}

set_scroll_save(length)
int length;
{
	int i, j, delta;
	struct line *line, **new_lines;
	char *body;
	u_char *prop;

	tc_deselect(0);		/* do this before we move the lines around */
	userScrollLength = length ;
	if (!RefreshSuppressed)
		ToggleScrollBar(length);
	if (length < LinesPerScreen) length = LinesPerScreen ;
	if (length > TotalScrollLength) {
		new_lines = (struct line **) Malloc(2 * length *
						sizeof(struct line *)) ;
		for (i=length-ScrollLength, j=0; j<ScrollLength; j++, i++) {
			new_lines[i] = lines[j] ;
			}
		TotalScrollLength = length ;
		if (scroll_area) free((char *)scroll_area);
		scroll_area = lines = new_lines ;
		}
	else	{
		delta = ScrollLength - length ;
		if (delta>0) {
			for (i=0; i<length; i++) {
				if (lines[i]) {
					if (lines[i]->body)
						free(lines[i]->body);
					if (lines[i]->prop)
						free((char *)lines[i]->prop);
					free((char *)lines[i]);
					}
				lines[i] = lines[i+delta] ;
				lines[i+delta] = NULL ;
				}
			}
		else	for (i=ScrollLength-1; i>=0; i--)
				lines[i-delta] = lines[i] ;
		}
	for (i=0; i<length-ScrollLength; i++) {
		line = (struct line *) Malloc(sizeof(struct line));
		line->body = Malloc(TypicalWidth) ;
		for (j=0; j<TypicalWidth; j++)
			line->body[j] = ' ' ;
		line->prop = (u_char *)Malloc(TypicalWidth) ;
		bzero((char *)line->prop, TypicalWidth);
		line->buffer_length = TypicalWidth ;
		line->length = 0 ;
		line->changeposition = 0 ;
		line->end_of_changes = 0 ;
		line->usedtobe = -1 ;
		line->flags = 0 ;
		lines[i] = line ;
		}
	ScrollY += length - ScrollLength ;
	ScrollLength = length ;
	if (ScrollY < 0) ScrollY = 0 ;
	if (ScrollY > ScrollLength - LinesPerScreen)
		ScrollY = ScrollLength - LinesPerScreen ;
	for (i=ScrollLength-LinesPerScreen; i < ScrollLength; i++) {
		if (lines[i]->buffer_length <= CharsPerLine) {
			body = Malloc(CharsPerLine+1);
			prop = (u_char *) Malloc(CharsPerLine+1);
			length = lines[i]->length ;
			if (lines[i]->buffer_length > 0) {
				bcopy(lines[i]->body, body, length);
				bcopy((char *)lines[i]->prop, (char *)prop, length);
				free(lines[i]->body);
				free((char *)lines[i]->prop);
				}
			bzero((char *)&prop[length], CharsPerLine - length + 1);
			for (; length <= CharsPerLine; length++)
				body[length] = ' ' ;
			lines[i]->body = body ;
			lines[i]->prop = prop ;
			lines[i]->buffer_length = CharsPerLine + 1 ;
			}
		}
/*	if (ScrollLinesSaved > ScrollLength) */
		ScrollLinesSaved = ScrollLength ;
	if (ScrollLinesSaved < LinesPerScreen)
		ScrollLinesSaved = LinesPerScreen ;
	screen = &lines[ScrollLength - LinesPerScreen] ;
}

scroll_to_bottom()
{
	scroll_to(ScrollLinesSaved - LinesPerScreen);
}

scroll_to(scrolly)
int scrolly;
{
	int i, lesser, greater;

	scrolly += ScrollLength - ScrollLinesSaved ;
	if (scrolly < 0) scrolly = 0 ;
	if (scrolly > ScrollLength - LinesPerScreen)
		scrolly = ScrollLength - LinesPerScreen ;
	if (scrolly != ScrollY) {
		if (scrolly < ScrollY) {
			lesser = scrolly;
			greater = ScrollY;
			}
		else	{
			lesser = ScrollY;
			greater = scrolly;
			}
		for (i=lesser; i<greater; i++)
			if (lines[i])
				lines[i]->usedtobe = -1 ;
		for (i=lesser+LinesPerScreen; i<greater+LinesPerScreen; i++)
			if (lines[i])
				lines[i]->usedtobe = -1 ;
		}
	ScrollY = scrolly ;
}

ScrollSaveLine(line)
struct line *line;
{
	int i;
	struct line *new;

	if (ScrollLength <= LinesPerScreen)
		return;
	if (ScrollLinesSaved < ScrollLength)
		ScrollLinesSaved++;
	for (i=ScrollLength; i>ScrollLength-LinesPerScreen; i--)
		lines[i] = lines[i-1] ;
	new = lines[i] = lines[0] ;
	if (new->buffer_length < line->length + 1) {
		free(new->body);
		free((char *)new->prop);
		new->body = Malloc((int)line->length + 1);
		new->prop = (u_char *) Malloc((int)line->length + 1);
		new->buffer_length = line->length + 1 ;
		}
	bcopy(line->body, new->body, (int)line->length+1);
	bcopy((char *)line->prop, (char *)new->prop, (int)line->length+1);
	new->length = line->length ;
	new->changeposition = 0 ;
	new->end_of_changes = CharsPerLine + 1 ;
	new->usedtobe = line->usedtobe ;
	new->flags = line->flags ;
	lines++ ;
	if (&lines[ScrollLength] >= &scroll_area[TotalScrollLength * 2]) {
		bcopy((char *)lines, (char *)scroll_area,
			sizeof(struct line **)*ScrollLength);
		lines = scroll_area ;
		}
	screen = &lines[ScrollLength - LinesPerScreen] ;
}
	
/* --------------- External Routines Below ------------------- */

do_display_resize() {
    register i;
/*    tc_refresh(0);*/
    BeginRepair();
    Repairing++;
    ReInitialize();
    for (i = 0; i<LinesPerScreen; i++) {
	lines[i+ScrollY]->changeposition = 0;
	lines[i+ScrollY]->end_of_changes = CharsPerLine ;
    }
    tc_refresh(0);
    tc_refresh_selection();
    psio_flush(PostScript);
}

PSFILE *
Connect_To_Server()
{
	extern PSFILE *ps_open_PostScript();
	PSFILE *f;

	if ((f = ps_open_PostScript()) == NULL) {
		return (NULL);
		}
	ConnectionEstablished = 1 ;
	return f;
}

PSFILE       *
tc_init_screen(term, xorg, yorg, font_size, framelabel, iconlabel, reload,
		userinit, font, starticonic, iconx, icony, savelines)
char *term;
int xorg, yorg, font_size;
char *framelabel, *iconlabel;
int reload;
char *userinit, *font;
int starticonic, iconx, icony, savelines;
{
	PSFILE	   *f;
	char		frametitle[100];
	char		host[100];

	f = Connect_To_Server();
	if (f==NULL) return NULL;

	PSDefs(reload);
	psio_flush(PostScript);

	if (framelabel == NULL) {
		static char te[] = " terminal emulator";
		sprintf(frametitle, "%.*s%s",
		sizeof(frametitle)-sizeof(te)-strlen(term), term, te);
		framelabel = frametitle;
		}
	if (iconlabel == NULL) {
		gethostname(host, sizeof (host));
		host[sizeof(host)-1] = '\0';
 		iconlabel = host;
		}
	if (tc_initialize(term))
		Fatal("%s: Unknown terminal type or bad termcap description",
			term);
	set_scroll_save(savelines);
	scroll_to_bottom();
	tc_init_selection();
	PSInitCode(userinit);
	CreateWindow(xorg, yorg, font_size, CharsPerLine, LinesPerScreen,
		framelabel, iconlabel, font, starticonic, iconx, icony);
	ToggleScrollBar(savelines);
	StartInput();
	/* XXX - set up PostScript process for i/p etc. */
	psio_flush(PostScript);
	return (f);
}

PostScriptErrorMessage(s)
char *s;
{
	PopMsg(s);
	psio_flush(PostScript);
}

#define Finished_Dammage	1
#define Finished_NoDammage	2
#define Painting_Dammage	3
#define Painting_NoDammage	4

static int RefreshState = Finished_Dammage ;

end_refresh()
{
	switch (RefreshState) {
	case Painting_Dammage:
		RefreshState = Finished_Dammage ;
		break;
	case Painting_NoDammage:
		RefreshState = Finished_NoDammage ;
		break;
	case Finished_Dammage:
		RefreshState = Finished_Dammage ;
		break;
	case Finished_NoDammage:
		RefreshState = Finished_NoDammage ;
		break;
		}
}

/*ARGSUSED*/
tc_refresh(full)
    int full;
{
    register struct line *l;
    register int i, pos, c;
    register u_char *cp;
    register struct line **sp;
    int delta, curdelta, len;
    int linesscrolledforward, linesscrolledreverse;
    int paintfromtop;
    int x, y;
    static int CursorLine = 0 ;
    static int CursorCol = 0 ;
    static int oldlinessaved = 0 ;
    static int oldlinesperscreen = 0 ;
    static int oldscrolly = 0 ;
    u_char *tp, *ep, hit[MaxLinesPerScreen];

    if (RefreshSuppressed) return;
    switch (RefreshState) {
	case Painting_Dammage:
		if (FastPaint) return ;
		break;
	case Painting_NoDammage:
		RefreshState = Painting_Dammage ;
		if (FastPaint) return ;
		break;
	case Finished_Dammage:
		RefreshState = Painting_NoDammage ;
		break;
	case Finished_NoDammage:
		RefreshState = Finished_Dammage ;
		return;
	    }
    if (ScrollY != oldscrolly) tc_take_down_selection();
    bzero((char *)hit, LinesPerScreen);
    linesscrolledforward = linesscrolledreverse = 0 ;
    if (!fontisfixedwidth) {
	y = Dot.y + ScrollLength - LinesPerScreen - ScrollY ;
	if (y >= 0 && y < LinesPerScreen)
		hit[y] = 1 ;
	y = CursorLine + ScrollLength - LinesPerScreen - ScrollY ;
	if (y >= 0 && y < LinesPerScreen)
		hit[y] = 1 ;
	}
    else RemoveCursor();
    /*
     * Figure out which lines have moved and by
     * how much.  Accumulate delta line movements
     * and copy lines to perform scrolling.
     */
    curdelta = 0;
		/* positive delta means lines are travelling in this direction
		 *			 |  |
		 *			 |  |
		 *			\    /
		 *			 \  /
		 *			  \/
		 */
    sp = &lines[ScrollY];
    for (i = 0; i < LinesPerScreen; i++) {
	l = *sp++;
	pos = l->usedtobe ;	/* this line just moved from position pos */
	delta = i - pos ;	/* it moved this far in getting here */
	if (pos >= LinesPerScreen || pos < 0 || hit[pos] || (delta && !DoScrolling)) {
		delta = 0 ;		/* this line has been scribbled on,
					 *   so it stays put */
		l->changeposition = 0 ;	/* but has been dammaged */
		l->end_of_changes = CharsPerLine ;
		}
	l->usedtobe = i;
#ifdef lint
	c = 0 ;
#endif
	/*
	 * If the delta changes, we need to start a new
	 * run of lines to copy.  If there was a previous
	 * run, then copy those first.
	 */
	if (delta != curdelta) {
	    if (curdelta != 0) {
		for (pos = c; pos < i; pos++)
			hit[pos] = 1 ;
		if (curdelta > 0)
			linesscrolledreverse += i - c ;
		else	linesscrolledforward += i - c ;
		CopyLines(c - curdelta, curdelta, CharsPerLine, i - c);
		}
	    curdelta = delta;		/* delta for current run */
	    c = i;			/* starting line of run */
	}
    }
    /*
     * Catch any trailing run needing to be copied.
     */
    if (curdelta != 0) {
	if (curdelta > 0)
		linesscrolledreverse += i - c ;
	else	linesscrolledforward += i - c ;
	CopyLines(c - curdelta, curdelta, CharsPerLine, i - c);
	}
#ifdef lint
	paintfromtop = linesscrolledreverse > linesscrolledforward ;
#endif
	paintfromtop = 1 ;

	/*
	 * Finally, perform any erasures
	 * and/or text painting required.
	 */
	if (paintfromtop)
		sp = &lines[ScrollY] ;
	else	sp = &lines[ScrollY + LinesPerScreen - 1];
	for (i = 0; i < LinesPerScreen; (paintfromtop ? sp++ : sp--), i++) {
		l = *sp;
		pos = l->changeposition;
		if (pos<min(l->end_of_changes+MaxCharsPerLine, l->length)+1) {
			if (!fontisfixedwidth)
				pos = 0 ;
			x = pos ;
			y = l->usedtobe ;
			MoveTo(x, y);
			if (l->buffer_length == 0) {
				PaintNor(" ", 1);
				continue;
				}
			ep = &l->prop[l->length+1];
			for (cp = &l->prop[pos]; cp < ep; pos += len) {
				/*
				 * Calculate longest sub-string of
				 * changed text with identical properties.
				 */
				tp = cp;
				if (!fontisfixedwidth &&
						y == Dot.y + ScrollLength -
						LinesPerScreen - ScrollY) {
					c = *cp++ ;
					if (x++==Dot.x)
						c ^= ReverseVideoLook ;
					for (; c==*cp && cp<ep && x!=Dot.x;
							cp++, x++)
						;
					}
				else	{
					for (c = *cp++; c==*cp && cp<ep; cp++)
						;
					}
				len = cp - tp;
				/*
				 * Paint sub-string according to properties.
				 */
				if (c & UnderlineLook) {
					if (c & ReverseVideoLook)
						PaintUnderRev(&l->body[pos],
							len);
					else
						PaintUnderNor(&l->body[pos],
							len);
					}
				else	{
					if (c & ReverseVideoLook)
						PaintRev(&l->body[pos], len);
					else
						PaintNor(&l->body[pos], len);
					}
				}
			l->changeposition = CharsPerLine + 1 ;
			l->end_of_changes = 0 ;
			}
		}

    if (fontisfixedwidth) PlaceCursor(Dot.x, Dot.y);
    CursorLine = Dot.y ;
    CursorCol = Dot.x ;
#ifdef lint
    CursorLine = CursorCol ;
#endif
    if (Repairing) {
	EndRepair();
	Repairing = 0;
    }
    if (oldlinessaved != ScrollLinesSaved ||
		oldlinesperscreen != LinesPerScreen) {
	SetScrollBarValue(ScrollLinesSaved,
		ScrollY + ScrollLinesSaved - ScrollLength);
	oldlinessaved = ScrollLinesSaved ;
	oldlinesperscreen = LinesPerScreen ;
	}
    if (ScrollY != oldscrolly) tc_refresh_selection();
    oldscrolly = ScrollY ;
    EndRefresh();
    FlushPostScript();
}

change_rowcol(row, col)
int row, col;
{
	extern int Mfd;		/* Master pty fd */
	int pgroup;

	if (row >= MaxLinesPerScreen) row = MaxLinesPerScreen - 1 ;
	if (col >= MaxCharsPerLine) col = MaxCharsPerLine - 1 ;
	if (row != LinesPerScreen || col != CharsPerLine) {
#ifdef sun

#ifdef TIOCSSIZE
		struct ttysize ts;

		ts.ts_lines = row;
		ts.ts_cols = col;
		ioctl(Mfd, TIOCSSIZE, &ts);
#endif TIOCSSIZE

#else sun

#ifdef TIOCSWINSZ
		struct winsize ws;

		ws.ws_row = row;
		ws.ws_col = col;
		ws.ws_xpixel = row; /* don't know */
		ws.ws_ypixel = col; /* don't know */
		ioctl(Mfd, TIOCSWINSZ, &ws);
#endif TIOCSWINSZ

#endif sun

		ScrollY += LinesPerScreen - row ;
		resetscreensize(row, col);

#ifdef sun
		if (ioctl(Mfd, TIOCGPGRP, &pgroup)<0)
			perror("ioctl TIOCGPGRP");
		else if (killpg(pgroup, SIGWINCH)<0)
			perror("kill SIGWINCH");
#endif sun
		}
	for (row=0; row<ScrollLength; row++)
		if (lines[row])
			lines[row]->usedtobe = -1 ;
	/* allocate full length lines for whole screen */
	set_scroll_save(userScrollLength);
	scroll_to(ScrollY - ScrollLength + ScrollLinesSaved);
}
@@@ Fin de display.c
exit 0

-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.