diff packages/services/gfx/mw/current/src/demos/nanox/nxterm.c @ 208:e0c0827131d1 ecos

Merge from eCos master repository on 2002-05-20-20:11:54-BST
author jlarmour
date Mon, 20 May 2002 22:19:26 +0000
parents
children
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/packages/services/gfx/mw/current/src/demos/nanox/nxterm.c
@@ -0,0 +1,1182 @@
+/*
+ * nxterm - terminal emulator for Nano-X
+ *
+ * (C) 1994,95,96 by Torsten Scherer (TeSche)
+ * itschere@techfak.uni-bielefeld.de
+ *
+ * - quite some changes for W1R1
+ * - yet more changes for W1R2
+ *
+ * TeSche 01/96:
+ * - supports W_ICON & W_CLOSE
+ * - supports /etc/utmp logging for SunOS4 and Linux
+ * - supports catching of console output for SunOS4
+ * Phx 02-06/96:
+ * - supports NetBSD-Amiga
+ * Eero 11/97:
+ * - unsetenv(DISPLAY), setenv(LINES, COLUMNS).
+ * - Add new text modes (you need to use terminfo...).
+ * Eero 2/98:
+ * - Implemented fg/bgcolor setting.  With monochrome server it changes
+ *   bgmode variable, which tells in which mode to draw to screen
+ *   (M_CLEAR/M_DRAW) and affects F_REVERSE settings.
+ * - Added a couple of checks.
+ *
+ * TODO:
+ * - Allocate and set sensible window palette for fg/bg color setting.
+ * - add scroll-region ('cs') command. Fairly many programs
+ *   can take advantage of that.
+ * - Add xterm like mouse event to terminfo key event conversion... :)
+ * - check if current NetBSD really needs ifdefs below with
+ *   current W server/library.
+ */
+#include <stdio.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <utmp.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#define MWINCLUDECOLORS
+#include "nano-X.h"
+#include "nxterm.h"
+
+#define TITLE	"nxterm"
+
+#define	SMALLBUFFER 80
+#define	LARGEBUFFER 1024
+
+/*
+ * some pty helper functions
+ */
+#ifdef linux
+#define NSIG _NSIG
+#endif
+
+#ifdef __FreeBSD__
+#include <libutil.h>
+#endif
+
+
+/*
+ * some global variables
+ */
+
+static GR_WINDOW_ID	w1;	/* id for window */
+static GR_GC_ID		gc1;	/* graphics context */
+static GR_FONT_ID       regFont;
+/*static GR_FONT_ID       boldFont;*/
+
+static GR_SCREEN_INFO	si;	/* screen info */
+static GR_FONT_INFO     fi;     /* Font Info */
+static GR_WINDOW_INFO   wi;
+static GR_GC_INFO       gi;
+static GR_BOOL		havefocus = GR_FALSE;
+
+static short winw, winh, pid, console;
+static int pipeh;
+static short cblink = 0, visualbell = 0, debug = 0;
+#ifdef __FreeBSD__
+static char pty[SMALLBUFFER];
+static struct winsize winsz;
+#endif
+
+#define fonh fi.height
+#define fonw fi.maxwidth
+
+int term_init();
+
+/****************************************************************************/
+
+/*
+ *
+ */
+
+/* static int isIconified; */
+static int isMaximized=0;
+
+void maximize(void)
+{
+    static short x0, y0, w, h, w_max,h_max;
+
+    if (!isMaximized) 
+    {
+      
+	w_max=si.cols-wi.bordersize;
+	h_max=si.rows-wi.bordersize;
+	GrMoveWindow(w1,0,0);
+	GrResizeWindow(w1,w_max, h_max);
+	isMaximized=1;
+    } 
+    else 
+    {
+	GrResizeWindow(w1, w, h);
+	GrMoveWindow(w1, x0, y0);
+	isMaximized=0;
+    }
+}
+
+
+/****************************************************************************/
+
+
+/*
+ * some common tool functions
+ */
+
+void sigpipe(int sig)
+{
+  /* this one musn't close the window */
+/*  _write_utmp(pty, "", "", 0);  */
+  kill(-pid, SIGHUP);
+  _exit(sig);
+}
+
+
+void sigchld(int sig)
+{
+/*  _write_utmp(pty, "", "", 0);  */
+  _exit(sig);
+}
+
+
+void sigquit(int sig)
+{
+  signal(sig, SIG_IGN);
+  kill(-pid, SIGHUP);
+}
+
+
+/*
+ * this is the wterm terminal code, almost like VT52
+ */
+
+short	bgmode, escstate, curx, cury, curon, curvis;
+short	savx, savy, wrap, style;
+short	col, row, colmask = 0x7f, rowmask = 0x7f;
+
+/*
+ * something to buffer plain text output
+ */
+
+short	sbufcnt = 0;
+short	sbufx, sbufy;
+char    lineBuffer[SMALLBUFFER+1];
+char	*sbuf=lineBuffer;
+
+void sflush(void)
+{
+    if (sbufcnt) 
+    {
+	GrText(w1,gc1, sbufx*fonw, sbufy*fonh, sbuf, sbufcnt, GR_TFTOP);
+	sbufcnt = 0;
+    }
+}
+
+
+void lineRedraw(void)
+{
+    GrSetGCForeground(gc1,gi.background);
+    GrFillRect(w1, gc1, curx*fonw, cury*fonh, (col-curx)*fonw, fonh);
+    GrSetGCForeground(gc1,gi.foreground);
+
+    if (sbufcnt) 
+    {
+	sbuf[sbufcnt] = 0;
+	GrText(w1,gc1, sbufx*fonw, sbufy*fonh, sbuf, sbufcnt, GR_TFTOP);
+    }
+}
+
+void sadd (char c)
+{
+    if (sbufcnt == SMALLBUFFER)
+    {
+	sflush ();
+    }
+
+    if (!sbufcnt)
+    { 
+ 	sbufx = curx; 
+ 	sbufy = cury; 
+    } 
+
+    sbuf[sbufcnt++] = c;
+}
+
+void show_cursor (void)
+{
+	GrSetGCMode(gc1,GR_MODE_XOR);
+	GrSetGCForeground(gc1, WHITE);
+	GrFillRect(w1, gc1, curx*fonw, cury*fonh+1, fonw, fonh-1);
+	GrSetGCForeground(gc1, gi.foreground);
+	GrSetGCMode(gc1,GR_MODE_COPY);
+}
+
+
+void draw_cursor (void)
+{
+    if (!curvis)
+    {
+	curvis = 1;
+	show_cursor();
+    }
+}
+void hide_cursor (void)
+{
+    if (curvis) 
+    {
+	curvis = 0;
+	show_cursor();
+    }
+}
+
+
+void vscroll(int lines)
+{
+    hide_cursor();
+    GrCopyArea(w1,gc1,0, 0, winw, winh-(lines*fonh),
+	       w1, 0, (lines*fonh), MWROP_SRCCOPY);
+    
+    GrSetGCForeground(gc1,gi.background);    
+    GrFillRect(w1, gc1, 0, winh-(lines*fonh),
+	       winw, (lines*fonh));
+    GrSetGCForeground(gc1,gi.foreground);    
+}
+
+void esc5(unsigned char c)	/* setting background color */
+{
+
+    GrSetGCBackground(gc1, c);
+    GrGetGCInfo(gc1,&gi);
+    escstate = 0;
+}
+
+void esc4(unsigned char c)	/* setting foreground color */
+{
+    GrSetGCForeground(gc1,c);
+    GrGetGCInfo(gc1,&gi);
+    escstate = 0;
+}
+
+void esc3(unsigned char c)	/* cursor position x axis */
+{
+    curx = (c - 32) & colmask;
+    if (curx >= col)
+	curx = col - 1;
+    else if (curx < 0)
+	curx = 0;
+    escstate = 0;
+}
+
+
+void esc2(unsigned char c)	/* cursor position y axis */
+{
+  cury = (c - 32) & rowmask;
+  if (cury >= row)
+    cury = row - 1;
+  else if (cury < 0)
+    cury = 0;
+  escstate = 3;
+}
+
+
+void esc1(unsigned char c)	/* various control codes */
+{
+    static int ReverseMode=0;
+    escstate = 0;
+
+    switch(c) 
+    {
+    case 'A':/* cursor up */
+	hide_cursor();
+	if ((cury -= 1) < 0)
+	    cury = 0;
+	break;
+
+    case 'B':/* cursor down */
+	hide_cursor();
+	if ((cury += 1) >= row)
+	    cury = row - 1;
+	break;
+
+    case 'C':/* cursor right */
+	hide_cursor();
+	if ((curx += 1) >= col)
+	    curx = col - 1;
+	break;
+
+    case 'D':/* cursor left */
+	hide_cursor();
+	if ((curx -= 1) < 0)
+	    curx = 0;
+	break;
+
+    case 'E':/* clear screen & home */
+	GrClearWindow(w1, 0);
+	curx = 0;
+	cury = 0;
+	break;
+
+    case 'H':/* cursor home */
+	curx = 0;
+	cury = 0;
+	break;
+
+    case 'I':/* reverse index */
+	if ((cury -= 1) < 0) 
+	{
+	    cury = 0;
+	    vscroll(1);
+	}
+	break;
+
+    case 'J':/* erase to end of page */
+
+ 	if (cury < row-1) 
+	{
+	    GrSetGCForeground(gc1,gi.background);
+	    GrFillRect(w1,gc1, 0,(cury+1)*fonh, winw, (row-1-cury)*fonh);
+	    GrSetGCForeground(gc1,gi.foreground);
+	}
+	GrSetGCForeground(gc1,gi.background);
+ 	GrFillRect(w1, gc1, curx*fonw, cury*fonh, (col-curx)*fonw, fonh);
+	GrSetGCForeground(gc1,gi.foreground);
+	break;
+
+    case 'K':/* erase to end of line */
+	GrSetGCForeground(gc1,gi.background);
+	GrFillRect(w1, gc1, curx*fonw, cury*fonh, (col-curx)*fonw, fonh);
+	GrSetGCForeground(gc1,gi.foreground);
+	break;
+
+    case 'L':/* insert line */
+ 	if (cury < row-1) 
+	{
+	    vscroll(1);
+	}
+ 	curx = 0;
+	break;
+
+    case 'M':/* delete line */
+ 	if (cury < row-1) 
+	{ 
+	    vscroll(1);
+ 	}
+ 	curx = 0;
+	break;
+
+    case 'Y':/* position cursor */
+	escstate = 2;
+	break;
+
+    case 'b':/* set foreground color */
+	escstate = 4;
+	break;
+
+    case 'c':/* set background color */
+	escstate = 5;
+	break;
+
+    case 'd':/* erase beginning of display */
+/* 	w_setmode(win, bgmode); */
+ 	if (cury > 0) 
+	{
+	    GrSetGCForeground(gc1,gi.background);
+	    GrFillRect(w1,gc1, 0, 0, winw, cury*fonh);
+	    GrSetGCForeground(gc1,gi.foreground);
+	}
+ 	if (curx > 0) 
+	{
+	    GrSetGCForeground(gc1,gi.background);
+	    GrFillRect(w1,gc1, 0, cury*fonh, curx*fonw, fonh);
+	    GrSetGCForeground(gc1,gi.foreground);
+	}
+	break;
+
+    case 'e':/* enable cursor */
+	curon = 1;
+	break;
+
+    case 'f':/* disable cursor */
+	curon = 0;
+	break;
+
+    case 'j':/* save cursor position */
+	savx = curx;
+	savy = cury;
+	break;
+
+    case 'k':/* restore cursor position */
+	curx = savx;
+	cury = savy;
+	break;
+
+    case 'l':/* erase entire line */
+	GrSetGCForeground(gc1,gi.background);
+	GrRect(w1,gc1, 0, cury*fonh, winw, fonh);
+	GrSetGCForeground(gc1,gi.foreground);
+	curx = 0;
+	break;
+
+    case 'o':/* erase beginning of line */
+	if (curx > 0)
+	{
+	    GrSetGCForeground(gc1,gi.background);
+	    GrRect(w1,gc1,0, cury*fonh, curx*fonw, fonh);
+	    GrSetGCForeground(gc1,gi.foreground);
+	}
+	break;
+
+    case 'p':/* enter reverse video mode */
+    {
+	if(!ReverseMode)
+	{
+	    GrSetGCForeground(gc1,gi.background);
+	    GrSetGCBackground(gc1,gi.foreground);
+ 	    ReverseMode=1; 
+	}
+    }
+	break;
+
+    case 'q':/* exit reverse video mode */
+    {
+	if(ReverseMode)
+	{
+	    GrSetGCForeground(gc1,gi.foreground);
+	    GrSetGCBackground(gc1,gi.background);
+ 	    ReverseMode=0;
+	}
+    }
+	break;
+
+    case 'v':/* enable wrap at end of line */
+	wrap = 1;
+	break;
+
+    case 'w':/* disable wrap at end of line */
+	wrap = 0;
+	break;
+
+/* and these are the extentions not in VT52 */
+
+    case 'G': /* clear all attributes */
+	break;
+
+    case 'g': /* enter bold mode */
+/*	GrSetGCFont(gc1, boldFont); */
+	break;
+
+    case 'h': /* exit bold mode */
+/*	GrSetGCFont(gc1, regFont); */
+	break;
+
+    case 'i': /* enter underline mode */
+	break;
+
+	/* j, k and l are already used */
+
+    case 'm': /* exit underline mode */
+	break;
+
+/* these ones aren't yet on the termcap entries */
+
+    case 'n': /* enter italic mode */
+	break;
+	/* o, p and q are already used */
+
+    case 'r': /* exit italic mode */
+	break;
+
+    case 's': /* enter light mode */
+	break;
+
+    case 't': /* exit ligth mode */
+	break;
+
+    default: /* unknown escape sequence */
+	break;
+    }
+}
+
+/*
+ * un-escaped character print routine
+ */
+
+void esc0 (unsigned char c)
+{
+    switch (c) 
+    {
+    case 0:
+	/*
+	 * printing \000 on a terminal means "do nothing".
+	 * But since we use \000 as string terminator none
+	 * of the characters that follow were printed.
+	 *
+	 * perl -e 'printf("a%ca", 0);'
+	 *
+	 * said 'a' in a wterm, but should say 'aa'. This
+	 * bug screwed up most ncurses programs.
+	 *
+	 * kay.
+	 */
+	break;
+ 
+    case 7: /* bell */
+	if (visualbell) 
+	{
+/* 	    w_setmode(win, M_INVERS); */
+/* 	    w_pbox(win, 0, 0, winw, winh); */
+/* 	    w_test(win, 0, 0); */
+/* 	    w_pbox(win, 0, 0, winw, winh); */
+	    ;
+	} 
+	else 
+	{
+	    ;
+ 	    GrBell();
+	}
+	break;
+
+    case 8: /* backspace */
+	lineRedraw();
+	if (--curx < 0) 
+	{
+	    curx = 0;
+	}
+	break;
+
+    case 9: /* tab */
+    {
+	int borg,i;
+
+	borg=(((curx >> 3) + 1) << 3);
+	if(borg >= col)
+	{
+	    borg=col-1;
+	}
+	borg=borg-curx;
+	for(i=0; i < borg; ++i){sadd(' ');}
+ 	if ((curx = ((curx >> 3) + 1) << 3) >= col) 
+ 	{ 
+ 	    curx = col - 1; 
+ 	} 
+    }
+	break;
+
+    case 10: /* line feed */
+	sflush();
+	if (++cury >= row) 
+	{
+	    vscroll(1);
+	    cury = row-1;
+	}
+	break;
+
+    case 13: /* carriage return */
+	sflush();
+	curx = 0;
+	break;
+
+    case 27: /* escape */
+	sflush();
+	escstate = 1;
+	break;
+
+    case 127: /* delete */
+	break;
+
+    default: /* any printable char */
+	sadd(c);
+	if (++curx >= col) 
+	{
+	    sflush();
+	    if (!wrap) 
+	    {
+		curx = col-1;
+	    } 
+	    else 
+	    {
+		curx = 0;
+		if (++cury >= row) 
+		{
+		    vscroll(1);
+		}
+	    }
+	}
+	break;
+    }
+}
+
+
+void printc(unsigned char c)
+{
+    switch(escstate) 
+    {
+    case 0:
+	esc0(c);
+	break;
+
+    case 1:
+	sflush();
+	esc1(c);
+	break;
+
+    case 2:
+	sflush();
+	esc2(c);
+	break;
+
+    case 3:
+	sflush();
+	esc3(c);
+	break;
+
+    case 4:
+	sflush();
+	esc4(c);
+	break;
+
+    case 5:
+	sflush();
+	esc5(c);
+	break;
+
+    default: 
+	escstate = 0;
+	break;
+    }
+}
+
+
+void init()
+{
+    curx = savx = 0;
+    cury = savy = 0;
+    wrap = 1;
+    curon = 1;
+    curvis = 0;
+    escstate = 0;
+}
+
+
+/*
+ * general code...
+ */
+
+void
+term(void)
+{
+	long 		in, l;
+	GR_EVENT 	wevent;
+	GR_EVENT_KEYSTROKE *kp;
+	unsigned char 	buf[LARGEBUFFER];
+
+	GrRegisterInput(pipeh);
+	while (42) {
+		if (havefocus)
+			draw_cursor();
+		GrGetNextEvent(&wevent);
+
+		switch(wevent.type) {
+		case GR_EVENT_TYPE_CLOSE_REQ:
+			GrClose();
+			exit(0);
+			break;
+
+		case GR_EVENT_TYPE_KEY_DOWN:
+			kp=(GR_EVENT_KEYSTROKE *)&wevent;
+			/* toss all special keys*/
+			if (kp->ch & MWKEY_NONASCII_MASK)
+				break;
+			*buf = kp->ch & 0xff;
+			write(pipeh, buf,1);
+			break;
+
+		case GR_EVENT_TYPE_FOCUS_IN:
+			havefocus = GR_TRUE;
+			break;
+
+		case GR_EVENT_TYPE_FOCUS_OUT:
+			havefocus = GR_FALSE;
+			hide_cursor();
+			break;
+
+		case GR_EVENT_TYPE_UPDATE:
+			/*
+			 * if we get temporarily unmapped (moved),
+			 * set cursor state off.
+			 */
+			if (wevent.update.utype == GR_UPDATE_UNMAPTEMP)
+				curvis = 0;
+			break;
+
+		case GR_EVENT_TYPE_FDINPUT:
+			hide_cursor();
+			while ((in = read(pipeh, buf, sizeof(buf))) > 0) {
+				for (l=0; l<in; l++) {
+					printc(buf[l]); 
+					if (buf[l] == '\n')
+						printc('\r');
+				}
+				sflush();
+			}
+	    		break;
+		}
+	}
+}
+
+
+void usage(char *s)
+{
+    if (s) 
+	fprintf(stderr, "error: %s\n", s);
+    printf("usage: nxterm [-b] [-d] [-f <font family>] [-s <font size>]\n");
+    printf("       [-g <geometry>] [-v] [-c] [-h] [program {args}]\n");
+    exit(0);
+}
+
+
+void *mysignal(int signum, void *handler)
+{
+  struct sigaction sa, so;
+
+  sa.sa_handler = handler;
+  sigemptyset(&sa.sa_mask);
+  sa.sa_flags = SA_RESTART;
+  sigaction(signum, &sa, &so);
+
+  return so.sa_handler;
+}
+
+/*
+ * guess what... :)
+ */
+
+int main(int argc, char **argv)
+{
+    GR_BITMAP	bitmap1fg[7];	/* mouse cursor */
+    GR_BITMAP	bitmap1bg[7];
+    GR_WM_PROPERTIES props;
+
+    short xp, yp, fsize;
+    char *family, *shell = NULL, *cptr, *geometry = NULL;
+    struct passwd *pw;
+    char buf[80];
+    short uid;
+    char thesh[128];
+#ifdef __FreeBSD__
+    char *ptr;
+#endif
+
+#ifdef SIGTTOU
+    /* just in case we're started in the background */
+    signal(SIGTTOU, SIG_IGN);
+#endif
+
+    /* who am I? */
+    if (!(pw = getpwuid((uid = getuid())))) 
+    {
+	fprintf(stderr, "error: wterm can't determine determine your login name\n");
+	exit(-1);
+    }
+
+  
+    if (GrOpen() < 0) 
+    {
+	fprintf(stderr, "cannot open graphics\n");
+	exit(1);
+    }
+
+    GrGetScreenInfo(&si);
+    /*
+     * scan arguments...
+     */
+
+    console = 0;
+    argv++;
+    while (*argv && **argv=='-') 
+	switch (*(*argv+1)) 
+	{
+	case 'b':
+	    cblink = 1;
+	    argv++;
+	    break;
+
+	case 'c':
+	    console = 1;
+	    argv++;
+	    break;
+
+	case 'd':
+	    debug = 1;
+	    argv++;
+	    break;
+
+	case 'f':
+	    if (*++argv) {
+		family = *argv++;
+	    } else {
+		usage("-f option requires an argument");
+	    }
+	    break;
+
+	case 's':
+	    if (*++argv) {
+		fsize = atoi(*argv++);
+	    } else {
+		usage("-s option requires an argument");
+	    }
+	    break;
+
+	case 'g':
+	    if (*++argv) {
+		geometry = *argv++;
+	    } else {
+		usage("-g option requires an argument");
+	    }
+	    break;
+
+	case 'h':
+	    /* this will never return */
+	    usage("");
+
+	case 'v':
+	    visualbell = 1;
+	    argv++;
+	    break;
+
+	default:
+	    usage("unknown option");
+	}
+
+    /*
+     * now *argv either points to a program to start or is zero
+     */
+
+    if (*argv) {
+	shell = *argv;
+    }
+    if (!shell) {
+	shell = getenv("SHELL=");
+    }
+    if (!shell) {
+	shell = pw->pw_shell;
+    }
+    if (!shell) {
+	shell = "/bin/sh";
+    }
+
+    if (!*argv) {
+	/*
+	 * the '-' makes the shell think it is a login shell,
+	 * we leave argv[0] alone if it isn`t a shell (ie.
+	 * the user specified the program to run as an argument
+	 * to wterm.
+	 */
+	cptr = strrchr(shell, '/');
+	sprintf (thesh, "-%s", cptr ? cptr + 1 : shell);
+	*--argv = thesh;
+    }
+
+    col = 80;
+    row = 25;
+    xp = 0;
+    yp = 0;
+    if (geometry) 
+    {
+	if (col < 1) 
+	{
+	    col = 80;
+	}
+	if (row < 1) 
+	{
+	    row = 25;
+	}
+	if (col > 0x7f)
+	    colmask = 0xffff;
+	if (row > 0x7f)
+	    rowmask = 0xffff;
+    }
+    
+    regFont=GrCreateFont(GR_FONT_SYSTEM_FIXED, 0, NULL);
+    /*regFont=GrCreateFont(GR_FONT_OEM_FIXED, 0, NULL);*/
+    /*boldFont=GrCreateFont(GR_FONT_SYSTEM_FIXED, 0, NULL);*/
+    GrGetFontInfo(regFont, &fi);
+
+    winw=col*fi.maxwidth;
+    winh=row*fi.height;
+    w1 = GrNewWindow(GR_ROOT_WINDOW_ID, 10,10,winw, winh,0,BLACK,LTBLUE);
+    props.flags = GR_WM_FLAGS_TITLE;
+    props.title = TITLE;
+    GrSetWMProperties(w1, &props);
+
+    GrSelectEvents(w1, GR_EVENT_MASK_BUTTON_DOWN |
+		   GR_EVENT_MASK_KEY_DOWN | 
+		   GR_EVENT_MASK_FOCUS_IN | GR_EVENT_MASK_FOCUS_OUT |
+		   GR_EVENT_MASK_UPDATE | GR_EVENT_MASK_CLOSE_REQ);
+
+    GrMapWindow(w1);
+
+    gc1 = GrNewGC();
+    GrSetGCFont(gc1, regFont);
+
+#define	_	((unsigned) 0)		/* off bits */
+#define	X	((unsigned) 1)		/* on bits */
+#define	MASK(a,b,c,d,e,f,g) \
+	(((((((((((((a * 2) + b) * 2) + c) * 2) + d) * 2) \
+	+ e) * 2) + f) * 2) + g) << 9)
+	bitmap1fg[0] = MASK(_,_,X,_,X,_,_);
+	bitmap1fg[1] = MASK(_,_,_,X,_,_,_);
+	bitmap1fg[2] = MASK(_,_,_,X,_,_,_);
+	bitmap1fg[3] = MASK(_,_,_,X,_,_,_);
+	bitmap1fg[4] = MASK(_,_,_,X,_,_,_);
+	bitmap1fg[5] = MASK(_,_,_,X,_,_,_);
+	bitmap1fg[6] = MASK(_,_,X,_,X,_,_);
+
+	bitmap1bg[0] = MASK(_,X,X,X,X,X,_);
+	bitmap1bg[1] = MASK(_,_,X,X,X,_,_);
+	bitmap1bg[2] = MASK(_,_,X,X,X,_,_);
+	bitmap1bg[3] = MASK(_,_,X,X,X,_,_);
+	bitmap1bg[4] = MASK(_,_,X,X,X,_,_);
+	bitmap1bg[5] = MASK(_,_,X,X,X,_,_);
+	bitmap1bg[6] = MASK(_,X,X,X,X,X,_);
+    GrSetCursor(w1, 7, 7, 3, 3, GREEN, BLACK, bitmap1fg, bitmap1bg);
+    GrSetGCForeground(gc1, GREEN);
+    GrSetGCBackground(gc1, BLACK);
+    GrGetWindowInfo(w1,&wi);
+    GrGetGCInfo(gc1,&gi);
+
+    sprintf(buf, "wterm: %s", shell);
+
+    /*
+     * what kind of terminal do we want to emulate?
+     */
+#ifdef __FreeBSD__
+    putenv ("TERM=wterm");
+#else
+    putenv ("TERM=vt52");
+#endif
+
+    /*
+     * this one should enable us to get rid of an /etc/termcap entry for
+     * both curses and ncurses, hopefully...
+     */
+
+    if (termcap_string) 
+    {
+	sprintf (termcap_string + strlen (termcap_string), "li#%d:co#%d:",
+		 row, col);
+	putenv (termcap_string);
+    }
+    /* in case program absolutely needs terminfo entry, these 'should'
+     * transmit the screen size of correctly (at least xterm sets these
+     * and everything seems to work correctly...). Unlike putenv(),
+     * setenv() allocates also the given string not just a pointer.
+     */
+    sprintf (buf, "%d", col);
+    setenv ("COLUMNS", buf, 1);
+    sprintf (buf, "%d", row);
+    setenv ("LINES", buf, 1);
+
+    init();
+
+    /*
+     * create a pty
+     */
+#ifdef __FreeBSD__
+    winsz.ws_col = col;
+    winsz.ws_row = row;
+    if ((pid = forkpty(&pipeh, pty, NULL, &winsz)) < 0)  
+    {
+	fprintf(stderr,"wterm: can't create pty\r\n");
+	perror("wterm");
+	sleep(2);
+	GrKillWindow(w1);
+	exit(-1);
+    }
+
+    if ((ptr = rindex(pty, '/'))) 
+    {
+	strcpy(pty, ptr + 1);
+    }
+  
+    if (!pid) 
+    {
+	int i;
+	for (i = getdtablesize(); --i >= 3; )
+	    close (i);
+	/*
+	 * SIG_IGN are not reset on exec()
+	 */
+	for (i = NSIG; --i >= 0; )
+	    signal (i, SIG_DFL);
+ 
+	/* caution: start shell with correct user id! */
+	seteuid(getuid());
+	setegid(getgid());
+
+	/* this shall not return */
+	execvp(shell, argv);
+
+	/* oops? */
+	fprintf(stderr,"wterm: can't start shell\r\n");
+	sleep(3);
+	GrKillWindow(w1);
+	_exit(-1);
+    }
+#else
+    pipeh = term_init();
+#endif
+
+/*    _write_utmp(pty, pw->pw_name, "", time(0)); */
+
+#if 0
+    /* catch some signals */
+    mysignal(SIGTERM, sigquit);
+    mysignal(SIGHUP, sigquit);
+    mysignal(SIGINT, SIG_IGN);
+    mysignal(SIGQUIT, sigquit);
+    mysignal(SIGPIPE, sigpipe);
+    mysignal(SIGCHLD, sigchld);
+#endif
+
+    /* prepare to catch console output */
+    if (console) 
+    {
+	/* for any OS chr$(7) might cause endless loops if 
+	 * catched from console 
+	 */
+	visualbell = 1;
+	console = 0;       /* data will come to normal pipe handle */
+	ioctl(pipeh, TIOCCONS, 0);
+    }
+
+    term();
+    return 0;
+}
+
+#if ELKS
+char * nargv[2] = {"/bin/sash", NULL};
+#else
+#if DOS_DJGPP
+char * nargv[2] = {"bash", NULL};
+#else
+char * nargv[2] = {"/bin/sh", NULL};
+#endif
+#endif
+
+void sigchild(int signo)
+{
+	GrClose();
+	exit(0);
+}
+
+int term_init()
+{
+	int tfd;
+	int n = 0;
+	pid_t pid;
+	char pty_name[12];
+
+again:
+	sprintf(pty_name, "/dev/ptyp%d", n);
+	if ((tfd = open(pty_name, O_RDWR | O_NONBLOCK)) < 0) {
+		if ((errno == EBUSY || errno == EIO) && n < 10) {
+			n++;
+			goto again;
+		}
+		fprintf(stderr, "Can't create pty %s\n", pty_name);
+		return -1;
+	}
+	signal(SIGCHLD, sigchild);
+	signal(SIGINT, sigchild);
+	if ((pid = fork()) == -1) {
+		fprintf(stderr, "No processes\n");
+		return -1;
+	}
+	if (!pid) {
+		close(STDIN_FILENO);
+		close(STDOUT_FILENO);
+		close(tfd);
+		
+		setsid();
+		pty_name[5] = 't';
+		if ((tfd = open(pty_name, O_RDWR)) < 0) {
+			fprintf(stderr, "Child: Can't open pty %s\n", pty_name);
+			exit(1);
+		}
+		close(STDERR_FILENO);
+		dup2(tfd, STDIN_FILENO);
+		dup2(tfd, STDOUT_FILENO);
+		dup2(tfd, STDERR_FILENO);
+		execv(nargv[0], nargv);
+		exit(1);
+	}
+	return tfd;
+}
+
+#if 0
+void _write_utmp(char *line, char *user, char *host, int time)
+{
+    int fh, offset, isEmpty, isLine;
+    struct utmp ut;
+
+    if ((fh = open("/etc/utmp", O_RDWR)) < 0) {
+	return;
+    }
+
+    /* first of all try to find an entry with the same line */
+
+    offset = 0;
+    isEmpty = -1;
+    isLine = -1;
+
+    while ((isLine < 0) && (read(fh, &ut, sizeof(ut)) == sizeof(ut))) {
+	if (!ut.ut_line[0]) 
+	{
+	    if (isEmpty < 0) 
+	    {
+		isEmpty = offset;
+	    }
+	} 
+	else 
+	{
+	    if (!strncmp(ut.ut_line, line, sizeof(ut.ut_line))) {
+		isLine = offset;
+	    }
+	}
+	offset += sizeof(ut);
+    }
+
+    if (isLine != -1) {
+	/* we've found a match */
+	lseek(fh, isLine, SEEK_SET);
+    } else if (isEmpty != -1) {
+	/* no match found, but at least an empty entry */
+	lseek(fh, isLine, SEEK_SET);
+    } else {
+	/* not even an empty entry found, assume we can append to the file */
+    }
+
+    if (time) 
+    {
+	strncpy(ut.ut_line, line, sizeof(ut.ut_line));
+	strncpy(ut.ut_name, user, sizeof(ut.ut_name));
+	strncpy(ut.ut_host, host, sizeof(ut.ut_host));
+	ut.ut_time = time;
+    } 
+    else 
+    {
+	memset(&ut, 0, sizeof(ut));
+    }
+    write(fh, &ut, sizeof(ut));
+    close(fh);
+}
+#endif