BSD 4_3 development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Fri, 16 May 1986 03:19:30 +0000 (19:19 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Fri, 16 May 1986 03:19:30 +0000 (19:19 -0800)
Work on file usr/contrib/X/xterm/main.c
Work on file usr/contrib/X/xterm/util.c

Synthesized-from: CSRG/cd1/4.3

usr/contrib/X/xterm/main.c [new file with mode: 0644]
usr/contrib/X/xterm/util.c [new file with mode: 0644]

diff --git a/usr/contrib/X/xterm/main.c b/usr/contrib/X/xterm/main.c
new file mode 100644 (file)
index 0000000..38e08f7
--- /dev/null
@@ -0,0 +1,1287 @@
+#include <X/mit-copyright.h>
+
+/* Copyright    Massachusetts Institute of Technology    1984, 1985    */
+
+/* ptyx.c */
+
+#ifndef lint
+static char *rcsid_ptyx_c = "$Header: main.c,v 10.44 86/05/16 10:17:20 jg Exp $";
+#endif lint
+
+#include <pwd.h>
+#include <sgtty.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <stdio.h>
+#include <sys/file.h>
+#include <errno.h>
+#include <signal.h>
+#include <strings.h>
+#include <X/Xlib.h>
+#include "ptyx.h"
+#include <grp.h>
+#include <ttyent.h>
+#include <utmp.h>
+
+char *xterm_name;      /* argv[0] */
+Terminal term;         /* master data structure for client */
+int am_slave = 0;      /* set to 1 if running as a slave process */
+int debug = 0;                 /* true causes error messages to be displayed */
+
+static char *ptydev = "/dev/ptyxx";
+static char *ttydev = "/dev/ttyxx";
+
+#include "../cursors/xterm.cursor"
+#include "../cursors/xterm_mask.cursor"
+#include "icon.ic"
+#include "icon_mask.ic"
+
+static int reapchild ();
+
+static char **command_to_exec = (char **) NULL;
+static char *win_name = (char *) 0;
+
+
+static struct  sgttyb d_sg = {
+        0, 0, 0177, CKILL, EVENP|ODDP|ECHO|XTABS|CRMOD
+};
+static struct  tchars d_tc = {
+        CINTR, CQUIT, CSTART,
+        CSTOP, CEOF, CBRK,
+};
+static struct  ltchars d_ltc = {
+        CSUSP, CDSUSP, CRPRNT,
+        CFLUSH, CWERASE, CLNEXT
+};
+static int d_disipline = NTTYDISC;
+static int d_lmode = LCRTBS|LCRTERA|LCRTKIL|LCTLECH;
+static int no_dev_tty = 0;
+static int loginflag = 0;
+static int dologinflag = 0;
+#ifdef sun
+#ifdef TIOCCONS
+static int SunConsole = 0;
+#endif TIOCCONS
+#endif sun
+
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+       int ind;
+       char *strind, *strind1, *strscan();
+       char *fn = "vtsingle";
+       char *fb = "vtbold";
+       short fnflag = 0;       /* True iff -fn option used */
+       short fbflag = 0;       /* True iff -fb option used */
+       char *getty = NULL;
+       int reverse = 0, multiscroll = 0;
+       int border = 1, tek = 0;
+       int borderwidth = 2;
+       int bitmapicon = 0;
+#ifdef JUMPSCROLL
+       int jumpscroll = 0;
+#endif JUMPSCROLL
+       int slave = 0;          /* if non-zero, run as slave */
+       char passedPty[2];      /* name if pty if slave */
+       char *fore_color;
+       char *back_color;
+       char *brdr_color;
+       char *curs_color;
+       char *mous_color;
+       char display[256];
+       char *getenv();
+       char *option;
+       char *geometry, *def = "=80x24+1+1";
+
+       xterm_name = argv[0];
+
+       display[0] = '\0';
+       /*
+        * go get options out of default file
+        */
+       if ((option = XGetDefault(argv[0], "BodyFont")) != NULL) {
+               fn = option;
+               fnflag = 1;
+       }
+       if ((option = XGetDefault(argv[0], "BoldFont")) != NULL) {
+               fb = option;
+               fbflag = 1;
+       }
+       if ((option = XGetDefault(argv[0], "InternalBorder")) != NULL) {
+               border = atoi (option);
+       }
+       if ((option = XGetDefault(argv[0], "BorderWidth")) != NULL) {
+               borderwidth = atoi (option);
+       }
+
+       if ((option = XGetDefault(argv[0], "BitmapIcon")) != NULL)
+               if (strcmp (option, "on") == 0) 
+                       bitmapicon = 1;
+
+       if ((option = XGetDefault(argv[0], "ReverseVideo")) != NULL)
+               if (strcmp (option, "on") == 0)
+                       reverse = 1;
+
+       if ((option = XGetDefault(argv[0], "Tektronix")) != NULL)
+               if (strcmp (option, "on") == 0) 
+                       tek = 1;
+#ifdef JUMPSCROLL
+       if ((option = XGetDefault(argv[0], "JumpScroll")) != NULL)
+               if (strcmp (option, "on") == 0) 
+                       jumpscroll = 1;
+#endif JUMPSCROLL
+
+       fore_color = XGetDefault(argv[0], "Foreground");
+       back_color = XGetDefault(argv[0], "Background");
+       brdr_color = XGetDefault(argv[0], "Border");
+       curs_color = XGetDefault(argv[0], "Cursor");
+       mous_color = XGetDefault(argv[0], "Mouse");
+
+       /* parse command line */
+       
+       for (ind = 1; ind < argc; ind++) {
+           if (argv [ind] [0] == '=') {
+               geometry = argv[ind];
+               continue;
+           }
+
+           strind = index (argv[ind], ':');
+           if(strind != NULL) {
+               strncpy(display,argv[ind],sizeof(display));
+               continue;
+           }
+
+
+           strind = (char *) index (argv [ind], '-');
+
+           if (strind == NULL) Syntax ();
+
+           if (strcmp (argv [ind], "-L") == 0) {
+               char tt[32];
+               int mode = O_RDWR|O_NDELAY;
+               loginflag = 1;
+               getty = argv[argc-1];
+               argc -= 1;
+               strcpy(tt,"/dev/");
+               strcat(tt, getty);
+               chown(tt, 0, 0);
+               chmod(tt, 0622);
+               if (open(tt, mode, 0) < 0) {
+                       consolepr("open failed\n");
+               }
+               signal(SIGHUP, SIG_IGN);
+               vhangup();
+               setpgrp(0,0);
+               signal(SIGHUP, SIG_DFL);
+               open(tt, mode, 0);
+               close(0);
+               dup(1);
+               dup(0);
+               continue;
+           }
+    
+           if (strncmp (argv [ind], "-S", 2) == 0) {
+               sscanf(argv[ind] + 2, "%c%c%d", passedPty, passedPty+1,
+                       &slave);
+               if (slave <= 0) Syntax();
+               am_slave = 1;
+               continue;
+           }
+
+           if (strcmp (argv [ind], "-e") == 0) {
+               if (++ind >= argc) Syntax ();
+               command_to_exec = argv + ind;
+               break;
+           }
+               
+           /* Switch to set up Tektronix-shaped (4096x3128 -> 512x390) window
+            * with characters sized to fit 39 lines of 85 characters each */
+
+           if (strcmp (argv [ind], "-t") == 0) {
+               tek = 1;
+               if (!fnflag) fn = "6x10";
+               if (!fbflag) fb = "6x10";
+               def = "85x39+1+1";
+               continue;
+           }
+               
+           if (strcmp (argv [ind], "-fn") == 0) {
+               if (++ind >= argc) Syntax ();
+               fn = argv [ind];
+               fnflag = 1;
+               continue;
+           }
+
+           if (strcmp (argv [ind], "-fb") == 0) {
+               if (++ind >= argc) Syntax ();
+               fb = argv [ind];
+               fbflag = 1;
+               continue;
+           }
+
+           if (strcmp (argv [ind], "-fg") == 0) {
+               if (++ind >= argc) Syntax ();
+               fore_color = argv [ind];
+               continue;
+           }
+
+           if (strcmp (argv [ind], "-bg") == 0) {
+               if (++ind >= argc) Syntax ();
+               back_color = argv [ind];
+               continue;
+           }
+
+           if (strcmp (argv [ind], "-bd") == 0) {
+               if (++ind >= argc) Syntax ();
+               brdr_color = argv [ind];
+               continue;
+           }
+
+           if (strcmp (argv [ind], "-cr") == 0) {
+               if (++ind >= argc) Syntax ();
+               curs_color = argv [ind];
+               continue;
+           }
+
+           if (strcmp (argv [ind], "-ms") == 0) {
+               if (++ind >= argc) Syntax ();
+               mous_color = argv [ind];
+               continue;
+           }
+
+           if (strcmp (argv [ind], "-l") == 0) {
+               dologinflag = 1;
+               continue;
+           }
+
+           if (strcmp (argv [ind], "-d") == 0) {
+               debug = 1;
+               continue;
+           }
+
+           if (strcmp (argv [ind], "-b") == 0) {
+               if (++ind >= argc) Syntax ();
+               border = atoi (argv [ind]);
+               continue;
+           }
+
+           if (strcmp (argv [ind], "-bw") == 0 ||
+               strcmp (argv [ind], "-w") == 0) {
+               if (++ind >= argc) Syntax ();
+               borderwidth = atoi (argv [ind]);
+               continue;
+           }
+
+           if (strcmp (argv [ind], "-rv") == 0 ||
+               strcmp (argv [ind], "-r") == 0) {
+               reverse = 1;    /* backwards from usual definition */
+               continue;
+           }
+
+           if (strcmp (argv [ind], "-s") == 0) {
+               multiscroll = 1;
+               continue;
+           }
+
+           if (strcmp (argv [ind], "-i") == 0) {
+               bitmapicon = 1;
+               continue;
+           }
+
+#ifdef JUMPSCROLL
+           if (strcmp (argv [ind], "-j") == 0) {
+               jumpscroll = 1;
+               continue;
+           }
+#endif JUMPSCROLL
+
+           if (strcmp (argv [ind], "-n") == 0) {
+               if (++ind >= argc) Syntax ();
+               win_name = argv [ind];
+               continue;
+           }
+#ifdef sun
+#ifdef TIOCCONS
+           if (strcmp (argv [ind], "-C") == 0) {
+               SunConsole = 1;
+               continue;
+           }
+#endif TIOCCONS
+#endif sun
+
+           Syntax ();
+       }
+       
+       if (fnflag && !fbflag) fb = fn;
+       if (!fnflag && fbflag) fn = fb;
+#ifdef JUMPSCROLL
+       if(tek)
+               jumpscroll = 0;
+#endif JUMPSCROLL
+       Serve (display, fn, fb, geometry, def, getty, slave, passedPty,
+          border, borderwidth, tek, reverse, multiscroll, bitmapicon,
+          fore_color, back_color, brdr_color, curs_color, mous_color
+#ifdef JUMPSCROLL
+          , jumpscroll
+#endif JUMPSCROLL
+          );
+}
+
+Syntax ()
+{
+       static char *ustring[] = {
+       "Usage: xterm [-rv] [-fn normal_font] [-fb bold_font]\n",
+       "\t[=[width]x[height][[+-]xoff[[+-]yoff]]] [-bw bdr_width]\n",
+       "\t[-fg color] [-bg color] [-bd color] [-cr color] [-ms color]\n",
+       "\t[[[host]:vs]] [-d] [-s] [-t] [-i] [-j] [-e command_to_exec]\n",
+       "\t[-n window_name]\n\n",
+       "Fonts must be of fixed width and of same size;\n",
+       "If only one font is specified, it will be used for normal and bold text\n",
+#ifdef JUMPSCROLL
+       "The -j option enables jump scroll\n",
+#endif
+       "The -s option enables asynchronous scrolling\n",
+       "The -t option enables Tektronics 4010 emulation\n",
+       "The -i option enables bitmap icons\n",
+       "The -d option turns debugging on (error messages printed)\n",
+       "The -n option sets the window name\n",
+       "The -b option specifies the inner padding\n",
+       "Default is: xterm -fn vtsingle -fb vtbold =80x24 :0\n",
+       0};
+       char **us = ustring;
+       while (*us) fputs(*us++, stderr);
+       exit (1);
+}
+
+char *strscan (search, what)
+/*
+   Returns pointer to first char ins search which is also in what, else NULL.
+ */
+char *search, *what;
+{
+       int i, len = strlen (what);
+       char c;
+
+       while ((c = *(search++)) != NULL)
+           for (i = 0; i < len; i++)
+               if (c == what [i]) return (--search);
+
+       return (NULL);
+}
+
+Serve (disp, fn, fb, geometry, def, getty, slave, passedPty,
+       border, borderwidth, tek, reverse, multiscroll, bitmapicon,
+       fore_color, back_color, brdr_color, curs_color, mous_color
+#ifdef JUMPSCROLL
+       , jumpscroll
+#endif JUMPSCROLL
+       )
+char *disp;     /* host of display to serve */
+char *fn;       /* fontname of normal characters */
+char *fb;       /* fontname of bold characters */
+char *getty;    /* true iff child should be getty */
+int slave;      /* true if should run as slave (contains file # of pty) */
+char *passedPty; /* name of pty to use if slave */
+char *geometry;         /* user supplied geometry spec */
+char *def;      /* default geometry spec */
+int border;     /* inner border in pixels */
+int borderwidth; /* outer border in pixels */
+int tek;        /* true ==> Tektronics emulation */
+int reverse;    /* true ==> black background, white characters */
+int multiscroll; /* true ==> asynchronous full-screen scrolling */
+int bitmapicon;  /* true ==> bitmap icons rather than text icon */
+#ifdef JUMPSCROLL
+int jumpscroll;  /* true ==> fast multi-line scrolling */
+#endif JUMPSCROLL
+char *fore_color;/* text color */
+char *back_color;/* background color */
+char *brdr_color;/* border color */
+char *curs_color;/* text cursor color */
+char *mous_color;/* mouse cursor color */
+{
+       int pty;        /* fildes for pty of client */
+       XEvent reply;
+       XEvent *rep = & reply;
+       int aborted = 0;
+       int Select_mask, select_mask = 0;
+       int maxplus1;
+       short toggled = NULL;
+       Screen *screen = &term.screen;
+       int Xsocket;
+       int pty_mask, X_mask;
+       extern int errno;
+       int mode = 1;
+#ifdef TIOCSWINSZ
+       struct winsize ws;
+#endif
+
+       signal (SIGCHLD, reapchild);
+       signal (SIGHUP, SIG_IGN);
+
+       /* open a terminal for client */
+       get_terminal (disp, &term, fn, fb, geometry, def, border,
+          borderwidth, (int)getty, slave, reverse, multiscroll, bitmapicon,
+          tek, fore_color, back_color, brdr_color, curs_color, mous_color
+#ifdef JUMPSCROLL
+          , jumpscroll
+#endif JUMPSCROLL
+          );
+
+       Xsocket = screen->display->fd;
+
+       spawn (disp, &pty, Xsocket, screen, getty, slave, passedPty);
+
+       if (slave) {    /* Write window id so master end can read and use */
+           write(pty, &screen->window, sizeof(screen->window));
+           write(pty, "\n", 1);
+       }
+
+       screen->respond = term.buf.fildes = pty;
+
+#ifdef TIOCSWINSZ
+       /* tell tty how big window is */
+       ws.ws_row = screen->max_row + 1;
+       ws.ws_col = screen->max_col + 1;
+       ws.ws_xpixel = screen->width;
+       ws.ws_ypixel = screen->height;
+       ioctl (screen->respond, TIOCSWINSZ, &ws);
+#endif
+
+       /* Initialize Tektronix graphics mode parameters */
+       TekErase (&term);
+       screen->TekEmu = tek;
+       screen->cur_x = screen->cur_y = 0;
+       screen->cur_X = screen->cur_Y = 0;
+       screen->TekGMode = 0;
+       screen->TekAMode = 0;
+       screen->TekPMode = 0;
+
+       if (ioctl (pty, FIONBIO, &mode) == -1) Error ();
+       
+       pty_mask = 1 << pty;
+       X_mask = 1 << Xsocket;
+       Select_mask = pty_mask | X_mask;
+       maxplus1 = (pty < Xsocket) ? (1 + Xsocket) : (1 + pty);
+
+       if (debug) printf ("debugging on\n");
+
+       while (1)
+       {
+          if (! aborted)
+          {
+#ifdef JUMPSCROLL
+               if(screen->scroll_amt)
+                       FlushScroll(screen);
+#endif JUMPSCROLL
+               if (toggled)
+               {
+                   CursorToggle (screen, toggled);
+                   toggled = NULL;
+               }
+
+               select_mask = Select_mask;
+               XFlush();
+               while (select (maxplus1, &select_mask, NULL, NULL, 0) <= 0) {
+                       if (errno != EINTR) Error();
+                       }
+          }
+          else select_mask = NULL;
+
+          if (select_mask & pty_mask || aborted)
+          {
+               if (!toggled)
+               {
+                   CursorToggle (screen, toggled);
+                   toggled = 1;
+               }
+               do {
+                       aborted = (*screen->mode)(&term);
+               } while (screen->display->qlen==0 && term.buf.cnt>0);
+          }
+
+          if (select_mask & X_mask || aborted)
+          {
+#ifdef JUMPSCROLL
+               if(screen->scroll_amt)
+                       FlushScroll(screen);
+#endif JUMPSCROLL
+               XPending ();
+               do {
+                   XNextEvent (&reply);
+
+                   switch ((int)reply.type)
+                   {
+                       case KeyPressed:
+                               Input (&term.keyboard, &term.screen,
+                                       (XKeyPressedEvent *)rep);
+                               break;
+
+                       case ExposeWindow:
+                               if (bitmapicon) {
+                                       if (((XExposeWindowEvent *)rep)->window
+                                       == screen->iconwindow) {
+                                               RefreshIcon(screen);
+                                               break;
+                                               }
+                                       }
+                               toggled = 1;
+                               if (ScreenResize (screen,
+                                       ((XExposeWindowEvent *)rep)->width,
+                                       ((XExposeWindowEvent *)rep)->height,
+                                       &term.flags) != -1)
+                               {
+                                   TabReset (term.tabs);
+                                   XClear (screen->window);
+                                   ScrnRefresh (screen, 0, 0,
+                                                screen->max_row + 1,
+                                                screen->max_col + 1);
+
+                                   if (screen->TekEmu) TekRefresh (&term);
+                               }
+                               break;
+
+                       case ExposeRegion:
+                               if (((XExposeWindowEvent *)rep)->detail ==
+                                       ExposeCopy &&
+                                   screen->incopy <= 0) {
+                                       screen->incopy = 1;
+                                       if (screen->scrolls > 0)
+                                               screen->scrolls--;
+                               }
+                               if (HandleExposure (screen, &reply))
+                                       toggled = 1;
+                               break;
+
+                       case ExposeCopy:
+                               if (screen->incopy <= 0 && screen->scrolls > 0)
+                                       screen->scrolls--;
+                               if (screen->scrolls)
+                                       screen->incopy = -1;
+                               else
+                                       screen->incopy = 0;
+                               break;
+
+                       case ButtonPressed:
+                       case ButtonReleased:
+                               if (screen->incopy)
+                                       CopyWait (screen);
+                               if (HandleButtons(&term,&reply,pty))
+                                       toggled = 1;
+                               break;
+                       /*
+                        *  Enter window is being handled just to give xterm
+                        *  a kick in the pants when the mouse gets in the
+                        *  window in case it was swapped out.  Of course,
+                        *  one might thrash...
+                        */
+                       case EnterWindow:
+                               break;
+                       default:
+                               break;
+                       }
+               } while (screen->display->qlen > 0);
+          }
+       }
+}
+
+RefreshIcon(screen)
+register Screen *screen;
+{
+       XBitmapBitsPut(screen->iconwindow, 0, 0, icon_width, icon_height,
+               icon_bits, screen->foreground, screen->background,
+               screen->iconmask, GXcopy, AllPlanes);
+}
+
+get_pty (pty, pty_name)
+/*
+   opens a pty, storing fildes in pty
+   and it's identifying character in pty_name.
+ */
+int *pty;
+char *pty_name;
+{
+       int devindex, letter = 0;
+       int fd;
+       extern errno;
+
+       if (debug) {
+           fd = open ("xterm.debug.log", O_WRONLY | O_CREAT | O_TRUNC, 0666);
+           dup2 (fd, fileno (stderr));
+       }
+
+       while (letter < 4) {
+           ttydev [8] = ptydev [8] = "pqrs" [letter++];
+           devindex = 0;
+
+           while (devindex < 16) {
+               ptydev [9] = *pty_name = "0123456789abcdef" [devindex++];
+               if ((*pty = open (ptydev, O_RDWR, 0)) < 0)      {
+                       if (debug) fprintf (stderr, "pty %d code %d\n",
+                                       devindex - 1, errno);
+                       continue;
+               }
+               goto got_pty;
+           }
+       }
+       
+       fprintf (stderr,"Not enough available pty's\n");
+       exit (11);
+
+got_pty:
+       if (debug) {
+               close (fileno (stderr));
+               close (fd);
+       }
+}
+
+get_terminal (disp, term, fn, fb, geometry, def,
+      border, borderwidth, do_warp, slave, reverse, multiscroll, bitmapicon,
+      tek, fore_color, back_color, brdr_color, curs_color, mous_color
+#ifdef JUMPSCROLL
+      , jumpscroll
+#endif JUMPSCROLL
+      )
+/* 
+ * sets up X and initializes the terminal structure except for term.buf.fildes.
+ */
+char *disp;
+register Terminal *term;
+char *fn, *fb;
+char *geometry, *def;
+int border, borderwidth, do_warp, reverse, multiscroll, bitmapicon;
+int slave;
+int tek;
+#ifdef JUMPSCROLL
+int jumpscroll;
+#endif JUMPSCROLL
+char *fore_color, *back_color, *brdr_color, *curs_color, *mous_color;
+{
+       int width, height;
+       FontInfo *fInfo;
+       register Keyboard *keyboard;
+       register Screen *screen;
+       Buffer *buf;
+       double scale_x, scale_y;
+       Color cdef;
+       int pixels[2];
+       int try = 10;
+       OpaqueFrame twindow;
+
+       keyboard = &term->keyboard;
+       screen = &term->screen;
+       buf = &term->buf;
+
+       term->flags = WRAPAROUND|SMOOTHSCROLL;
+
+       keyboard->flags = NULL;
+       keyboard->offset = 0;
+       
+       buf->cnt = 0;
+       buf->ptr = &buf->buf[0];
+       
+       TabReset (term->tabs);
+
+       while (try--)
+           if ((screen->display = XOpenDisplay(disp)) == NULL) {
+               if (loginflag == 0) {
+                       fprintf(stderr,"No such display server %s\n", disp);
+                       exit(1);
+               }
+               sleep (5);
+               continue;
+           }
+           else break;
+
+       if (try <= 0)  {
+               fprintf (stderr,"Can't connect to display server %s\n",
+               disp);
+               exit (111);
+       }           
+
+       screen->foreground = BlackPixel;
+       screen->background = WhitePixel;
+       screen->cursorcolor = BlackPixel;
+       screen->mousecolor = BlackPixel;
+       screen->xorplane = 1;
+       if (DisplayCells() > 2 && (fore_color || back_color || curs_color)) {
+               if (tek) {
+                       if (curs_color && XParseColor(curs_color, &cdef)) {
+                               if (XGetColorCells(0, 2, 1, &screen->xorplane,
+                                                               pixels)) {
+                                       screen->background = pixels[0];
+                                       screen->foreground = pixels[1];
+                                       screen->cursorcolor = screen->background |
+                                       screen->xorplane;
+                                       cdef.pixel = screen->cursorcolor;
+                                       XStoreColor(&cdef);
+                               }
+                       } 
+                       else if (XGetColorCells(0, 1, 1, &screen->xorplane,
+                                                       &screen->background)) {
+                               screen->foreground = screen->background |
+                               screen->xorplane;
+                               screen->cursorcolor = screen->foreground;
+                       }
+                       if (screen->background != WhitePixel) {
+                               if (back_color == NULL ||
+                                       !XParseColor(back_color, &cdef)) {
+                                       cdef.pixel = WhitePixel;
+                                       XQueryColor(&cdef);
+                               }
+                               cdef.pixel = screen->background;
+                               XStoreColor(&cdef);
+                               if(screen->cursorcolor != screen->foreground) {
+                                       cdef.pixel = screen->foreground |
+                                               screen->xorplane;
+                                       XStoreColor(&cdef);
+                               }
+                               if (fore_color == NULL ||
+                                       !XParseColor(fore_color, &cdef)) {
+                                       cdef.pixel = BlackPixel;
+                                       XQueryColor(&cdef);
+                               }
+                               cdef.pixel = screen->foreground;
+                               XStoreColor(&cdef);
+                       }
+               }
+               else {
+                       if (fore_color && XParseColor(fore_color, &cdef) &&
+                                               XGetHardwareColor(&cdef)) {
+                               screen->foreground = 
+                                       screen->foreground = cdef.pixel;
+                               reverse = 0;
+                       }
+                       if (back_color && XParseColor(back_color, &cdef) &&
+                                               XGetHardwareColor(&cdef)) {
+                               screen->background = cdef.pixel;
+                               reverse = 0;
+                       }
+                       if (curs_color && XParseColor(curs_color, &cdef) &&
+                       XGetHardwareColor(&cdef))
+                       screen->cursorcolor = cdef.pixel;
+                       else
+                       screen->cursorcolor = screen->foreground;
+               }
+       }
+
+       screen->border = border;
+       screen->borderwidth = borderwidth;
+       screen->fnt_norm = screen->fnt_bold = NULL;
+          
+       if ((fInfo = XOpenFont(fn)) == NULL) {
+               fprintf(stderr, "%s: Could not open font %s!\n",
+                       xterm_name, fn);
+               exit(1);
+       }
+       if (fn) screen->fnt_norm = fInfo->id;
+       if (fb) screen->fnt_bold = XOpenFont(fb)->id;
+       screen->f_width = fInfo->width;
+       screen->f_height = fInfo->height;
+
+       if (brdr_color && DisplayCells() > 2 &&
+           XParseColor(brdr_color, &cdef) && XGetHardwareColor(&cdef))
+           screen->bordertile = XMakeTile(cdef.pixel);
+       else
+           screen->bordertile = BlackPixmap;
+
+       screen->cursor = XStoreBitmap(xterm_width, xterm_height, xterm_bits);
+       screen->mask =  XStoreBitmap(xterm_mask_width, xterm_mask_height, 
+                                   xterm_mask_bits);
+       if (mous_color && DisplayCells() > 2 &&
+           XParseColor(mous_color, &cdef) && XGetHardwareColor(&cdef))
+           screen->mousecolor = cdef.pixel;
+       else
+           screen->mousecolor = screen->cursorcolor;
+       screen->curs = XStoreCursor(screen->cursor, screen->mask, 5, 8,
+               screen->mousecolor, screen->background, GXcopy);
+       screen->rcurs = XStoreCursor(screen->cursor, screen->mask, 5, 8,
+               screen->background, screen->mousecolor, GXcopy);
+
+       if (reverse) {  /* reverse is black background with white chars */
+               term->flags |= REVERSE_VIDEO;
+               screen->cursorcolor = screen->background;
+               screen->background = screen->foreground;
+               screen->foreground = screen->cursorcolor;
+               if (screen->bordertile == BlackPixmap)
+                   screen->bordertile = WhitePixmap;
+       }
+       screen->bgndtile = XMakeTile(screen->background);
+
+       twindow.bdrwidth = screen->borderwidth;
+       twindow.border = screen->bordertile;
+       twindow.background = screen->bgndtile;
+
+       screen->window = XCreateTerm ("Terminal Emulator", xterm_name,
+               geometry, def, &twindow, 12, 8, 
+               screen->border * 2, screen->border * 2,
+               &width, &height, 
+               fInfo, fInfo->width, fInfo->height);
+
+       screen->width = twindow.width - border * 2;
+       screen->height = twindow.height - border * 2;
+
+       /* Reset variables used by ANSI emulation. */
+
+       screen->ansi.a_type = 0;                /* New sequence.        */
+       screen->ansi.a_pintro = 0;              /* New sequence.        */
+       screen->ansi.a_final = 0;               /* New sequence.        */
+       screen->gsets[0] = 'B';                 /* ASCII_G              */
+       screen->gsets[1] = 'B';
+       screen->gsets[2] = '<';                 /* DEC supplemental.    */
+       screen->gsets[3] = '<';
+       screen->curgl = 0;                      /* G0 => GL.            */
+       screen->curgr = 2;                      /* G2 => GR.            */
+       screen->curss = 0;                      /* No single shift.     */
+       screen->rx8bit = 0;                     /* 7 bit.               */
+       screen->tx8bit = 0;                     /* 7 bit.               */
+       screen->mode = ANSInormal;
+
+       /* Reset Tektronix alpha mode */
+       screen->TekGMode = 0;
+       screen->TekAMode = 0;
+       screen->cur_x = screen->cur_y = 0;
+       screen->cur_X = screen->cur_Y = 0;
+
+       scale_x = screen->width / 4096.0;
+       scale_y = screen->height / 3128.0;
+       screen->TekScale = scale_x;
+       if (scale_y < scale_x) screen->TekScale = scale_y;
+
+       if (bitmapicon) {
+               screen->iconwindow = XCreateWindow (RootWindow,
+                       0, 0, icon_width, icon_height, 0, 0, 0);
+
+               XTileRelative(screen->iconwindow);
+
+               XSetIconWindow(screen->window, screen->iconwindow);
+
+               screen->iconmask = XStoreBitmap(icon_mask_width,
+                       icon_mask_height, icon_mask_bits);
+               
+               XSelectInput (screen->iconwindow, ExposeWindow);
+       }
+
+       if (reverse)
+               XDefineCursor(screen->window, screen->rcurs);
+       else    XDefineCursor(screen->window, screen->curs);
+
+       XStoreName (screen->window, (win_name != (char *) 0 ? win_name:
+                       (do_warp ? "login" :
+                       (slave ? "xtermslave" :
+                       (command_to_exec ? command_to_exec[0] : "xterm")))));
+
+       XSetResizeHint (screen->window,
+                       2 * border, 2 * border, fInfo->width, fInfo->height);
+               
+       XMapWindow (screen->window);
+
+       XSelectInput (screen->window, KeyPressed | ExposeWindow | EnterWindow |
+               ButtonPressed | ButtonReleased | ExposeRegion | ExposeCopy);
+
+
+       if (do_warp)
+               XWarpMouse (screen->window,
+                           screen->width >> 1, screen->height >>1);
+
+       screen->cur_col = screen->cur_row = 0;
+       screen->max_col = screen->width  / fInfo->width - 1;
+       screen->top_marg = 0;
+       screen->bot_marg = screen->max_row = screen->height/ fInfo->height - 1;
+
+       screen->sc.row = screen->sc.col = screen->sc.flags = NULL;
+
+
+       /* allocate memory for screen buffer */
+       screen->buf = (ScrnBuf) Allocate (screen->max_row + 1,
+                                         screen->max_col +1);
+
+       screen->do_wrap = NULL;
+       screen->scrolls = screen->incopy = 0;
+       screen->multiscroll = multiscroll;
+#ifdef JUMPSCROLL
+       if (screen->jumpscroll = jumpscroll)
+               term->flags &= ~SMOOTHSCROLL;
+#endif JUMPSCROLL
+
+
+       /* display initial cursor */
+       CursorToggle (screen, 1);
+}
+
+spawn (display, pty, Xsocket, screen, getty, slave, passedPty)
+/* 
+ *  Inits pty and tty and forks a login process. Returns fd for pty in pty.
+ *  Does not close fd Xsocket.
+ *  If getty,  execs getty rather than csh and uses std fd's rather
+ *  than opening a pty/tty pair.
+ *  If slave, the pty named in passedPty is already open for use
+ */
+int *pty, Xsocket;
+Screen *screen;
+char *getty;           /* if true execs /etc/getty - Xwindow */
+int slave;
+char *passedPty;
+char *display;
+{
+       int index1, tty;
+       char pty_name;
+       int discipline;
+       unsigned lmode;
+       struct tchars tc;
+       struct ltchars ltc;
+       struct sgttyb sg;
+
+       char termcap [1024];
+       char newtc [1024];
+       char prog [256];
+       char numbuf[10];
+       char *ptr;
+       char *index (), *strindex ();
+       int i = 0;
+       char **envnew;          /* new environment */
+       struct passwd *getpwuid();
+       struct passwd *pw;
+       char logindev[32];
+       char *TermName = "xterm";
+       int ldisc = 0;
+
+       /* be real paranoid about getting some usable entry */
+       if (tgetent (termcap, TermName)  == 1
+               || (TermName = "vt102", tgetent(termcap, TermName)) == 1
+               || (TermName = "ansi",  tgetent(termcap, TermName)) == 1) {
+               /* update termcap string */
+               /* first do columns */
+               if ((ptr = strindex (termcap, "co#")) == NULL){
+                       fprintf(stderr,"Can't find co# in termcap string %s\n",
+                               TermName);
+                       exit (1);
+               }
+               strncpy (newtc, termcap, ptr - termcap + 3);
+               newtc[ptr-termcap+3] = '\0';
+               sprintf (numbuf, "%d\0", screen->max_col + 1);
+               strcat (newtc, numbuf);
+               ptr = index (ptr, ':');
+               strcat (newtc, ptr);
+               strncpy (termcap, newtc, sizeof(termcap));
+               /* now do lines */
+               if ((ptr = strindex (termcap, "li#")) == NULL) {
+                       fprintf(stderr,"Can't find li# in termcap string %s\n",
+                               TermName);
+                       exit (1);
+               }
+               strncpy (newtc, termcap, ptr - termcap + 3);
+               newtc[ptr-termcap+3] = '\0';
+               sprintf (numbuf, "%d\0", screen->max_row + 1);
+               strcat (newtc, numbuf);
+               ptr = index (ptr, ':');
+               strcat (newtc, ptr);
+               if (strcmp(TermName, "xterm") != 0)
+                   fprintf(stderr, 
+                   "xterm: can't find xterm termcap entry, using %s instead!\n", TermName);
+       }
+       else fprintf(stderr,"xterm: can't find any usable termcap entry!\n");
+
+       if (getty) {
+               strcpy(logindev,"/dev/");
+               strcat(logindev,getty);
+               logindev [5] = 'p';
+               *pty = open (logindev, O_RDWR, 0);
+       }
+       else if (slave) {
+           *pty = slave;
+           ptydev[8] = ttydev[8] = passedPty[0];
+           ptydev[9] = ttydev[9] = passedPty[1];
+       }
+       else {
+               if ((tty = open ("/dev/tty", O_RDWR, 0)) < 0) {
+                       if (errno != ENXIO) Error();
+                       else {
+                               no_dev_tty = 1;
+                               sg = d_sg;
+                               tc = d_tc;
+                               discipline = d_disipline;
+                               ltc = d_ltc;
+                               lmode = d_lmode;
+                               for (index1 = 0; index1 < 3; index1++)
+                                   close (index1);
+                       }
+               }
+               else {
+                       /* get a copy of the current terminal's state */
+
+                       if ((tty = open ("/dev/tty", O_RDWR, 0)) < 0) Error ();
+
+                       if (ioctl (tty, TIOCGETP, &sg) == -1) Error ();
+                       if (ioctl (tty, TIOCGETC, (int *)&tc) == -1) Error ();
+                       if (ioctl (tty, TIOCGETD, &discipline) == -1) Error ();
+                       if (ioctl (tty, TIOCGLTC, (int *)&ltc) == -1) Error ();
+                       if (ioctl (tty, TIOCLGET, &lmode) == -1) Error ();
+
+                       close (tty);
+
+                       /* close all std file descriptors */
+                       for (index1 = 0; index1 < 3; index1++)
+                           close (index1);
+                       if ((tty = open ("/dev/tty", O_RDWR, 0)) < 0) Error ();
+
+                       if (ioctl (tty, TIOCNOTTY, 0) == -1) Error ();
+                       close (tty);
+               }
+
+               get_pty (pty, &pty_name);
+
+               if (*pty != Xsocket + 1) {
+                       dup2 (*pty, Xsocket + 1);
+                       close (*pty);
+                       *pty = Xsocket + 1;
+               }
+
+               ttydev [9] = pty_name;
+               if ((tty = open (ttydev, O_RDWR, 0)) < 0) Error ();
+
+               /* change ownership of tty to real group and user id */
+               chown (ttydev, getuid (), tty_gid (getgid()));
+
+               /* change protection of tty */
+               chmod (ttydev, 0620);
+
+               if (tty != Xsocket + 2) {
+                       dup2 (tty, Xsocket + 2);
+                       close (tty);
+                       tty = Xsocket + 2;
+               }
+
+               /* set the new terminal's state to be the old one's 
+                  with minor modifications for efficiency */
+
+               sg.sg_flags &= ~(ALLDELAY | XTABS | CBREAK | RAW);
+               sg.sg_flags |= ECHO | CRMOD;
+               /* make sure speed is set on pty so that editors work right*/
+               sg.sg_ispeed = B9600;
+               sg.sg_ospeed = B9600;
+
+               if (ioctl (tty, TIOCSETP, &sg) == -1) Error ();
+               if (ioctl (tty, TIOCSETC, (int *)&tc) == -1) Error ();
+               if (ioctl (tty, TIOCSETD, &discipline) == -1) Error ();
+               if (ioctl (tty, TIOCSLTC, (int *)&ltc) == -1) Error ();
+               if (ioctl (tty, TIOCLSET, &lmode) == -1) Error ();
+#ifdef sun
+#ifdef TIOCCONS
+               if (SunConsole) {
+                       int on = 1;
+                       if (ioctl (tty, TIOCCONS, &on) == -1) Error();
+               }
+#endif TIOCCONS
+#endif sun
+
+               close (open ("/dev/null", O_RDWR, 0));
+
+               for (index1 = 0; index1 < 3; index1++)
+                       dup2 (tty, index1);
+       }
+
+       if (!slave && (screen->pid = fork ()) == -1) Error ();
+               
+       if (!slave && screen->pid == 0) {
+               extern char **environ;
+               int pgrp = getpid();
+
+               close (Xsocket);
+               close (*pty);
+
+               if (getty == NULL) close (tty);
+
+               signal (SIGCHLD, SIG_DFL);
+               signal (SIGHUP, SIG_IGN);
+
+               /* copy the environment before Setenving */
+               while (environ [i] != NULL) i++;
+               envnew = (char **) malloc (sizeof (char *) * (i + 4));
+               for (; i >= 0; i--) envnew [i] = environ [i];
+               environ = envnew;
+               Setenv ("TERM=", TermName);
+               Setenv ("TERMCAP=", newtc);
+               /* put the display into the environment of the shell*/
+               if (display[0] != '\0') 
+               Setenv ("DISPLAY=", screen->display->displayname);
+
+               pw = getpwuid (getuid ());
+               signal(SIGTERM, SIG_DFL);
+               ioctl(0, TIOCSPGRP, &pgrp);
+               setpgrp (0, 0);
+               close(open(ttyname(0), O_WRONLY, 0));
+               setpgrp (0, pgrp);
+               if (dologinflag)        /* login */
+                       utrelog(1, pw->pw_name, screen->display->displayname);
+
+               setgid(getgid ());
+               setuid(getuid ());
+
+               if (command_to_exec) {
+                       execvp(command_to_exec[0], command_to_exec, 0);
+               }
+               signal(SIGHUP, SIG_IGN);
+               if (getty) {
+                       ioctl (0, TIOCNOTTY, 0);
+                       execl ("/etc/getty", "+", "Xwindow", getty, 0);
+               }
+               signal(SIGHUP, SIG_DFL);
+
+               if (*pw->pw_shell == '\0') pw->pw_shell = "/bin/sh";
+
+               /* make sure line discipline gets set */
+               ldisc = 0;
+               ioctl(0, TIOCSETD, &ldisc);
+               if (!strcmp(pw->pw_shell, "/bin/csh")) {
+                       ldisc = NTTYDISC;
+                       ioctl(0, TIOCSETD, &ldisc);
+               }
+               
+               ptr = rindex(pw->pw_shell, '/');
+               if (ptr == NULL)
+                       ptr = pw->pw_shell;
+               else
+                       ptr++;
+               if (dologinflag) {
+                       prog[0] = '-';
+                       strcpy(&prog[1], ptr);
+               } else
+                       strcpy(prog, ptr);
+               execlp (pw->pw_shell, prog, 0);
+               fprintf (stderr,"Error: Could not exec %s!\n", pw->pw_shell);
+               sleep(5);
+               Cleanup(121);
+       }
+
+       close (tty);
+       signal(SIGHUP,SIG_IGN);
+       signal(SIGTTOU,SIG_IGN); /* so that TIOCSWINSZ doesn't block */
+
+       if ((tty = open (no_dev_tty ? "/dev/null" : "/dev/tty",
+           O_RDWR, 0)) < 0) Error();
+       for (index1 = 0; index1 < 3; index1++)
+               dup2 (tty, index1);
+       if (tty > 2) close (tty);
+
+       /* set ids to user's */
+       /*
+       setgid (getgid ());
+       setuid (getuid ());
+               setregid (getegid (), getgid ());
+               setreuid (geteuid (), getuid ());
+       */
+
+}
+
+
+static reapchild ()
+{
+       extern Terminal term;
+       register long pgrp;
+       union wait status;
+       int pid;
+       
+       if (debug) printf ("Exiting\n");
+       pid  = wait3 (&status, WNOHANG, NULL);
+       if (!pid) return;
+       if (pid != term.screen.pid) return;
+       
+       if (dologinflag)
+               utrelog(0, "", "");
+       Cleanup(0);
+}
+
+consolepr(string)
+char *string;
+{
+       extern int errno;
+       extern char *sys_errlist[];
+       int oerrno;
+       int f;
+       oerrno = errno;
+       f = open("/dev/console",O_WRONLY, 0);
+       write(f, "xterm: ", 7);
+       write(f, string, strlen(string));
+       write(f, ": ", 2);
+       write(f, sys_errlist[oerrno],strlen(sys_errlist[oerrno]));
+       write(f, "\n", 1);
+       close(f);
+       if ((f = open("/dev/tty", 2, 0)) >= 0) {
+               ioctl(f, TIOCNOTTY, 0);
+               close(f);
+       }
+}
+
+#define TTYGRPNAME     "tty"
+
+tty_gid(default_gid)
+       int default_gid;
+{
+       struct group *getgrnam(), *gr;
+       int gid = default_gid;
+
+       gr = getgrnam(TTYGRPNAME);
+       if (gr != (struct group *) 0)
+               gid = gr->gr_gid;
+
+       endgrent();
+
+       return (gid);
+}
+
+utrelog(io, user, display)
+int io;
+char *user;
+char *display;
+{
+       struct utmp ut;
+       struct ttyent *ty;
+       register int s;
+       long slot;
+       int ufd;
+       char *colon;
+       
+       if (io == 1) {
+               strncpy(ut.ut_line, &ttydev[5], sizeof ut.ut_line);
+               colon = index(display, ':');
+               if (colon)
+                       *colon = '\0';
+               strncpy(ut.ut_host, display, sizeof ut.ut_host);
+               if (colon)
+                       *colon = ':';
+               strncpy(ut.ut_name, user, sizeof ut.ut_name);
+               (void) time(&ut.ut_time);
+       }
+       else {
+               strcpy(ut.ut_line, "");
+               strcpy(ut.ut_name, "");
+               strcpy(ut.ut_host, "");
+               ut.ut_time = 0;
+               chown(ttydev, 0, 0);
+               chmod(ttydev, 0666);
+       }
+
+       setttyent();
+       slot = 0;
+       s = 0;
+       while ((ty = getttyent()) != NULL) {
+               s++;
+               if (strcmp(ty->ty_name, &ttydev[5]) == 0) {
+                       slot = s;
+                       break;
+               }
+       }
+       endttyent();
+       if (slot > 0 && (ufd = open("/etc/utmp", O_WRONLY, 0)) >= 0) {
+               if (lseek(ufd, slot * sizeof ut, 0) < 0L ||
+                   write(ufd, (char *)&ut, sizeof ut) != sizeof ut) {
+                       close(ufd);
+                       return(-1);
+               }
+               close(ufd);
+       }
+       return(0);
+}
diff --git a/usr/contrib/X/xterm/util.c b/usr/contrib/X/xterm/util.c
new file mode 100644 (file)
index 0000000..9a9f0df
--- /dev/null
@@ -0,0 +1,715 @@
+#include <X/mit-copyright.h>
+
+/* Copyright    Massachusetts Institute of Technology    1984, 1985    */
+
+/* util.c */
+
+#ifndef lint
+static char *rcsid_util_c = "$Header: util.c,v 10.11 86/04/28 15:05:29 jg Exp $";
+#endif lint
+
+#include <stdio.h>
+#include <X/Xlib.h>
+#include <errno.h>
+#include <signal.h>
+
+#include "ptyx.h"
+
+extern errno;
+extern debug;
+#ifdef JUMPSCROLL
+/*
+ * These routines are used for the jump scroll feature
+ */
+FlushScroll(screen)
+register Screen *screen;
+{
+       register int height = screen->bot_marg - screen->top_marg + 1;
+       register int samount = screen->scroll_amt;
+       register int ramount = screen->refresh_amt;
+       register int scrolled = samount * screen->f_height;
+       register int refreshed = ramount * screen->f_height;
+       register int top = screen->top_marg * screen->f_height + screen->border;
+       int rtop;
+
+  if(samount > 0) {
+    rtop = screen->bot_marg - ramount + 1;
+  } else {
+    rtop = screen->top_marg;
+    top -= scrolled;
+    ramount = -ramount;
+    refreshed = -refreshed;
+  }
+
+  if (ramount != height) {
+
+      if (screen->multiscroll && samount == 1 &&
+         screen->top_marg == 0 && screen->bot_marg == screen->max_row) {
+             if (screen->incopy < 0 && screen->scrolls == 0)
+                     CopyWait (screen);
+             screen->scrolls++;
+      } else {
+             if (screen->incopy)
+                     CopyWait (screen);
+             screen->incopy = -1;
+      }
+
+      XMoveArea (screen->window,
+                screen->border, top + scrolled, screen->border, top,
+                screen->width, height * screen->f_height - refreshed);
+  }
+  screen->scroll_amt = 0;
+  screen->refresh_amt = 0;
+  XTileSet (screen->window, screen->border,
+           rtop * screen->f_height + screen->border,
+           screen->width, refreshed, screen->bgndtile);
+  ScrnRefresh(screen, rtop, 0, ramount, screen->max_col + 1);
+}
+
+AddToRefresh(screen)
+register Screen *screen;
+{
+       register int amount = screen->refresh_amt;
+       register int row = screen->cur_row;
+
+       if(amount == 0)
+               return(0);
+       if(amount > 0) {
+               register int bottom;
+
+               if(row == (bottom = screen->bot_marg) - amount) {
+                       screen->refresh_amt++;
+                       return(1);
+               }
+               return(row >= bottom - amount + 1 && row <= bottom);
+       } else {
+               register int top;
+
+               amount = -amount;
+               if(row == (top = screen->top_marg) + amount) {
+                       screen->refresh_amt--;
+                       return(1);
+               }
+               return(row <= top + amount - 1 && row >= top);
+       }
+}
+#endif JUMPSCROLL
+
+/* 
+ * scrolls the screen by amount lines, erases bottom, doesn't alter 
+ * cursor position (i.e. cursor moves down amount relative to text).
+ * All done within the scrolling region, of course. 
+ * requires: amount > 0
+ */
+Scroll (screen, amount)
+register Screen *screen;
+register int amount;
+{
+       register int height = screen->bot_marg - screen->top_marg + 1;
+       register int covered;
+       register int border = screen->border;
+       register int top = screen->top_marg * screen->f_height + border;
+
+       if (amount > height)
+               amount = height;
+#ifdef JUMPSCROLL
+    if(screen->jumpscroll) {
+       if(screen->scroll_amt > 0) {
+               if(screen->refresh_amt + amount > height)
+                       FlushScroll(screen);
+               screen->scroll_amt += amount;
+               screen->refresh_amt += amount;
+       } else {
+               if(screen->scroll_amt < 0)
+                       FlushScroll(screen);
+               screen->scroll_amt = amount;
+               screen->refresh_amt = amount;
+       }
+    } else {
+#endif JUMPSCROLL
+
+       if (amount == height) {
+               ClearScreen(screen);
+               return;
+       }
+
+       covered = amount * screen->f_height;
+
+       if (screen->multiscroll
+       && amount==1
+       && screen->top_marg==0
+       && screen->bot_marg==screen->max_row) {
+               if (screen->incopy<0 && screen->scrolls==0)
+                       CopyWait(screen);
+               screen->scrolls++;
+       } else {
+               if (screen->incopy)
+                       CopyWait(screen);
+               screen->incopy = -1;
+       }
+
+       XMoveArea(screen->window, border, top + covered, border, top,
+               screen->width, height * screen->f_height - covered);
+       XTileSet(screen->window, border,
+               (screen->bot_marg - amount + 1) * screen->f_height + border,
+               screen->width, covered, screen->bgndtile);
+#ifdef JUMPSCROLL
+       }
+#endif JUMPSCROLL
+
+       ScrnDeleteLine(screen->buf, screen->bot_marg, screen->top_marg,
+                       amount, screen->max_col + 1);
+}
+
+
+/*
+ * Reverse scrolls the screen by amount lines, erases top, doesn't alter
+ * cursor position (i.e. cursor moves up amount relative to text).
+ * All done within the scrolling region, of course.
+ * Requires: amount > 0
+ */
+RevScroll(screen, amount)
+register Screen *screen;
+register int amount;
+{
+       register int height = screen->bot_marg - screen->top_marg + 1;
+       register int border = screen->border;
+       register int top = screen->top_marg * screen->f_height + border;
+       register int covered;
+
+       amount = (amount < height) ? amount : height;
+#ifdef JUMPSCROLL
+    if(screen->jumpscroll) {
+       if(screen->scroll_amt < 0) {
+               if(-screen->refresh_amt + amount > height)
+                       FlushScroll(screen);
+               screen->scroll_amt -= amount;
+               screen->refresh_amt -= amount;
+       } else {
+               if(screen->scroll_amt > 0)
+                       FlushScroll(screen);
+               screen->scroll_amt = -amount;
+               screen->refresh_amt = -amount;
+       }
+    } else {
+#endif JUMPSCROLL
+       covered = amount * screen->f_height;
+
+       if (screen->incopy)
+               CopyWait (screen);
+       screen->incopy = -1;
+
+       XMoveArea (screen->window,
+               border, top,
+               border, top + covered,
+               screen->width, height * screen->f_height - covered);
+       XTileSet (screen->window,
+               border, top,
+               screen->width, covered,
+               screen->bgndtile);
+
+#ifdef JUMPSCROLL
+       }
+#endif JUMPSCROLL
+       ScrnInsertLine (screen->buf, screen->bot_marg, screen->top_marg,
+                       amount, screen->max_col + 1);
+}
+
+/*
+ * If cursor not in scrolling region, returns.  Else,
+ * inserts n blank lines at the cursor's position.  Lines above the
+ * bottom margin are lost.
+ */
+InsertLine (screen, n)
+register Screen *screen;
+register int n;
+{
+       register int height;
+       register int bottom = screen->bot_marg;
+
+       if (screen->cur_row < screen->top_marg ||
+           screen->cur_row > screen->bot_marg) return;
+       
+       if (screen->cur_row + n - 1 > bottom) n = bottom - screen->cur_row + 1;
+#ifdef JUMPSCROLL
+    if(screen->jumpscroll) {
+       if(screen->scroll_amt <= 0&&screen->cur_row <= -screen->refresh_amt) {
+               if(-screen->refresh_amt + n > height)
+                       FlushScroll(screen);
+               screen->scroll_amt -= n;
+               screen->refresh_amt -= n;
+       } else if(screen->scroll_amt)
+               FlushScroll(screen);
+    }
+    if(!screen->scroll_amt) {
+#endif JUMPSCROLL
+
+
+       height = n * screen->f_height;
+
+       screen->do_wrap = 0;
+
+       if (screen->incopy)
+               CopyWait (screen);
+       screen->incopy = -1;
+
+       /*
+        * move stuff down.
+        * clear hole.
+        */
+       XMoveArea(screen->window,
+                    screen->border, CursorY (screen),
+                    screen->border, CursorY (screen) + height,
+                    screen->width,
+                    (bottom + 1 - screen->cur_row - n) * screen->f_height);
+       XTileSet(screen->window,
+               screen->border, CursorY (screen),
+               screen->width, height, screen->bgndtile);
+
+#ifdef JUMPSCROLL
+       }
+#endif JUMPSCROLL
+       /* adjust screen->buf */
+       ScrnInsertLine(screen->buf, bottom, screen->cur_row, n,
+                       screen->max_col + 1);
+}
+
+/*
+ * If cursor not in scrolling region, returns.  Else, deletes n lines
+ * at the cursor's position, lines added at bottom margin are blank.
+ */
+DeleteLine(screen, n)
+register Screen *screen;
+register int n;
+{
+       register int height;
+       register int bottom = screen->bot_marg;
+
+       if (screen->cur_row < screen->top_marg
+       || screen->cur_row > screen->bot_marg)
+               return;
+       
+       if (screen->cur_row + n - 1 > bottom)
+               n = bottom - screen->cur_row + 1;
+#ifdef JUMPSCROLL
+    if(screen->jumpscroll) {
+       if(screen->scroll_amt >= 0 && screen->cur_row == screen->top_marg) {
+               if(screen->refresh_amt + n > height)
+                       FlushScroll(screen);
+               screen->scroll_amt += n;
+               screen->refresh_amt += n;
+       } else if(screen->scroll_amt)
+               FlushScroll(screen);
+    }
+    if(!screen->scroll_amt) {
+#endif JUMPSCROLL
+
+       height = n * screen->f_height;
+       screen->do_wrap = 0;
+
+       if (screen->incopy)
+               CopyWait(screen);
+       screen->incopy = -1;
+
+       /*
+        * move stuff up.
+        * clear bottom.
+        */
+       XMoveArea(screen->window,
+                    screen->border, CursorY (screen) + height,
+                    screen->border, CursorY (screen),
+                    screen->width,
+                    (bottom + 1 - screen->cur_row - n) * screen->f_height);
+       XTileSet(screen->window,
+                    screen->border,
+                    (bottom + 1 - n) * screen->f_height + screen->border,
+                    screen->width, height, screen->bgndtile);
+
+#ifdef JUMPSCROLL
+       }
+#endif JUMPSCROLL
+       /* adjust screen->buf */
+       ScrnDeleteLine(screen->buf, bottom, screen->cur_row, n,
+                       screen->max_col + 1);
+}
+
+/*
+ * Insert n blanks at the cursor's position, no wraparound.
+ */
+InsertChar (screen, n)
+register Screen *screen;
+register int n;
+{
+       register int width = n * screen->f_width;
+
+#ifdef JUMPSCROLL
+    if(!AddToRefresh(screen)) {
+       if(screen->scroll_amt)
+               FlushScroll(screen);
+#endif JUMPSCROLL
+
+       screen->do_wrap = 0;
+
+       if (screen->incopy)
+               CopyWait (screen);
+       screen->incopy = -1;
+
+       XMoveArea(screen->window,
+                    CursorX (screen), CursorY (screen),
+                    CursorX (screen) + width, CursorY (screen),
+                    screen->width - (screen->cur_col + n) * screen->f_width,
+                    screen->f_height);
+       XTileSet(screen->window,
+                    CursorX (screen), CursorY (screen),
+                    width, screen->f_height, screen->bgndtile);
+
+#ifdef JUMPSCROLL
+       }
+#endif JUMPSCROLL
+       /* adjust screen->buf */
+       ScrnInsertChar(screen->buf, screen->cur_row, screen->cur_col, n,
+                       screen->max_col + 1);
+}
+
+/*
+ * Deletes n chars at the cursor's position, no wraparound.
+ */
+DeleteChar (screen, n)
+register Screen *screen;
+register int   n;
+{
+       register int width; 
+
+       if (screen->cur_col + n > screen->max_col + 1)
+               n = screen->max_col + 1 - screen->cur_col;
+
+#ifdef JUMPSCROLL
+    if(!AddToRefresh(screen)) {
+       if(screen->scroll_amt)
+               FlushScroll(screen);
+#endif JUMPSCROLL
+
+       width = n * screen->f_width;
+
+       screen->do_wrap = 0;
+
+       if (screen->incopy)
+               CopyWait (screen);
+       screen->incopy = -1;
+
+       XMoveArea(screen->window,
+                    CursorX (screen) + width, CursorY (screen),
+                    CursorX (screen), CursorY (screen),
+                    screen->width - (screen->cur_col + n) * screen->f_width,
+                    screen->f_height);
+       XTileSet (screen->window,
+                    screen->border + screen->width - width, CursorY (screen),
+                    width, screen->f_height, screen->bgndtile);
+
+#ifdef JUMPSCROLL
+       }
+#endif JUMPSCROLL
+       /* adjust screen->buf */
+       ScrnDeleteChar (screen->buf, screen->cur_row, screen->cur_col, n,
+                       screen->max_col + 1);
+
+}
+
+/*
+ * Clear from cursor position to beginning of display, inclusive.
+ */
+ClearAbove (screen)
+register Screen *screen;
+{
+#ifdef JUMPSCROLL
+       if(screen->scroll_amt)
+               FlushScroll(screen);
+#endif JUMPSCROLL
+       ClearLeft(screen);
+       
+       XTileSet(screen->window, screen->border, 0,
+               screen->width, CursorY (screen), screen->bgndtile);
+       ClearBufRows(screen, 0, screen->cur_row - 1);
+}
+
+/*
+ * Clear from cursor position to end of display, inclusive.
+ */
+ClearBelow (screen)
+register Screen *screen;
+{
+       register int sy = CursorY (screen) + screen->f_height;
+
+#ifdef JUMPSCROLL
+       if(screen->scroll_amt)
+               FlushScroll(screen);
+#endif JUMPSCROLL
+       ClearRight(screen);
+       XTileSet(screen->window, screen->border, sy,
+            screen->width, screen->height - sy + screen->border, 
+            screen->bgndtile);
+       ClearBufRows(screen, screen->cur_row + 1, screen->max_row);
+}
+
+/* 
+ * Clear last part of cursor's line, inclusive.
+ */
+ClearRight (screen)
+register Screen *screen;
+{
+       screen->do_wrap = 0;
+
+#ifdef JUMPSCROLL
+    if(!AddToRefresh(screen)) {
+       if(screen->scroll_amt)
+               FlushScroll(screen);
+#endif JUMPSCROLL
+       XTileSet(screen->window,
+            CursorX (screen), CursorY (screen),
+            screen->width-screen->cur_col * screen->f_width,screen->f_height,
+            screen->bgndtile);
+#ifdef JUMPSCROLL
+    }
+#endif JUMPSCROLL
+       bzero((char *)(screen->buf [screen->cur_row] + screen->cur_col),
+              sizeof (short) * (screen->max_col - screen->cur_col + 1));
+}
+
+/*
+ * Clear first part of cursor's line, inclusive.
+ */
+ClearLeft (screen)
+register Screen *screen;
+{
+       screen->do_wrap = 0;
+
+#ifdef JUMPSCROLL
+    if(!AddToRefresh(screen)) {
+       if(screen->scroll_amt)
+               FlushScroll(screen);
+#endif JUMPSCROLL
+
+       XTileSet (screen->window,
+            screen->border, CursorY (screen),
+            (screen->cur_col + 1) * screen->f_width,
+            screen->f_height, screen->bgndtile);
+#ifdef JUMPSCROLL
+    }
+#endif JUMPSCROLL
+       bzero ((char *)screen->buf [screen->cur_row],
+               sizeof (short) * (screen->cur_col + 1));
+}
+
+/* 
+ * Erase the cursor's line.
+ */
+ClearLine(screen)
+register Screen *screen;
+{
+       screen->do_wrap = 0;
+
+#ifdef JUMPSCROLL
+    if(!AddToRefresh(screen)) {
+       if(screen->scroll_amt)
+               FlushScroll(screen);
+#endif JUMPSCROLL
+       XTileSet (screen->window,
+            screen->border, CursorY (screen),
+            screen->width, screen->f_height, screen->bgndtile);
+#ifdef JUMPSCROLL
+    }
+#endif JUMPSCROLL
+       bzero ((char *)screen->buf [screen->cur_row],
+               sizeof (short) * (screen->max_col + 1));
+}
+
+ClearScreen(screen)
+register Screen *screen;
+{
+       screen->do_wrap = 0;
+       
+#ifdef JUMPSCROLL
+       if(screen->scroll_amt)
+               FlushScroll(screen);
+#endif JUMPSCROLL
+       XClear(screen->window);
+       ClearBufRows (screen, 0, screen->max_row);
+}
+
+CopyWait(screen)
+register Screen *screen;
+{
+       XEvent reply;
+       XEvent *rep = &reply;
+
+       while (1) {
+               XWindowEvent (screen->window, ExposeRegion|ExposeCopy, &reply);
+               switch (reply.type) {
+               case ExposeRegion:
+                       if (((XExposeEvent *)rep)->detail == ExposeCopy &&
+                           screen->incopy <= 0) {
+                               screen->incopy = 1;
+                               if (screen->scrolls > 0)
+                                       screen->scrolls--;
+                       }
+                       HandleExposure (screen, &reply);
+                       break;
+               case ExposeCopy:
+                       if (screen->incopy <= 0 && screen->scrolls > 0)
+                               screen->scrolls--;
+                       if (screen->scrolls == 0) {
+                               screen->incopy = 0;
+                               return;
+                       }
+                       screen->incopy = -1;
+                       break;
+               }
+       }
+}
+/*
+ * This routine handles exposure events
+ */
+HandleExposure (screen, reply)
+register Screen *screen;
+register XExposeEvent *reply;
+{
+       int toprow, leftcol, nrows, ncols;
+       extern Terminal term;   /* kludge */
+       XExposeRegionEvent event;
+
+       toprow = (reply->y - screen->border) / screen->f_height;
+       leftcol = (reply->x - screen->border) / screen->f_width;
+       nrows = (reply->y + reply->height - 1 - screen->border) /
+                       screen->f_height - toprow + 1;
+       ncols = (reply->x + reply->width - 1 - screen->border) /
+                       screen->f_width - leftcol + 1;
+       toprow -= screen->scrolls;
+       if (toprow < 0) {
+               nrows += toprow;
+               toprow = 0;
+       }
+       if (toprow + nrows - 1 > screen->max_row)
+               nrows = screen->max_row - toprow + 1;
+       if (leftcol + ncols - 1 > screen->max_col)
+               ncols = screen->max_col - leftcol + 1;
+
+       if (nrows > 0 && ncols > 0) {
+               if (screen->TekEmu && reply->detail != ExposeCopy)
+                       /* Clear to avoid possible dangling cursor */
+                       XTileSet (screen->window,
+                            leftcol * screen->f_width + screen->border,
+                            toprow * screen->f_height + screen->border,
+                            ncols * screen->f_width,
+                            nrows * screen->f_height,
+                            screen->bgndtile);
+               ScrnRefresh (screen, toprow, leftcol, nrows, ncols);
+               /* only do the tek refresh on the last refresh event */
+               if (screen->TekEmu) {
+                       XSync(0);       /* make sure they are all here */
+                       if (XPending() != 0) {
+                               XPeekEvent(&event);
+                               if (event.type != ExposeRegion) {
+                                       if (reply->detail != ExposeCopy)
+                                               TekRefresh(&term);
+                               }
+                       }
+                       else {
+                               if (reply->detail != ExposeCopy)
+                                       TekRefresh (&term);
+                       }
+               }
+               if (screen->cur_row >= toprow &&
+                   screen->cur_row < toprow + nrows &&
+                   screen->cur_col >= leftcol &&
+                   screen->cur_col < leftcol + ncols)
+                       return (1);
+       }
+       return (0);
+}
+
+Panic(s, a)
+char   *s;
+{
+       fprintf(stderr, "PANIC! ");
+       fprintf(stderr, s, a);
+       fprintf(stderr, "\r\n");
+       fflush(stderr);
+}
+
+Error ()
+{
+       fprintf (stderr, "Error %d: ", errno);
+       perror ("");
+       Cleanup(66);
+}
+
+/*
+ * cleanup by sending SIGHUP to client processes
+ */
+Cleanup (code)
+int code;
+{
+       extern Terminal term;
+       register Screen *screen;
+       register long pgrp;
+       screen = &term.screen;
+       if (screen->pid > 1) {
+               pgrp = getpgrp(screen->pid);
+               if (pgrp > 1) killpg(pgrp, SIGHUP);
+       }
+       exit(code);
+}
+
+/*
+ * sets the value of var to be arg in the Unix 4.2 BSD environment env.
+ * Var should end with '=' (bindings are of the form "var=value").
+ * This procedure assumes the memory for the first level of environ
+ * was allocated using malloc.
+ */
+Setenv (var, value)
+register char *var, *value;
+{
+       extern char **environ;
+       register int index = 0;
+
+       while (environ [index] != NULL) {
+           if (strncmp (environ [index], var, strlen (var)) == 0) {
+               /* found it */
+               environ [index] = (char *) malloc (strlen (var) + strlen (value));
+               strcpy (environ [index], var);
+               strcat (environ [index], value);
+               return;
+           }
+           index ++;
+       }
+
+       if (debug) printf ("expanding env\n");
+       environ = (char **) realloc((char *)environ, sizeof(char *) * (index+2));
+       if (environ == NULL) {
+           fprintf (stderr, "Setenv: malloc out of memory\n");
+           exit (1);
+       }
+
+       environ [index] = (char *) malloc (strlen (var) + strlen (value));
+       strcpy (environ [index], var);
+       strcat (environ [index], value);
+       environ [++index] = NULL;
+}
+
+/*
+ * returns a pointer to the first occurrence of s2 in s1,
+ * or NULL if there are none.
+ */
+char *strindex (s1, s2)
+register char  *s1, *s2;
+{
+       register char   *s3;
+       char            *index();
+
+       while ((s3=index(s1, *s2)) != NULL) {
+               if (strncmp(s3, s2, strlen(s2)) == 0)
+                       return (s3);
+               s1 = ++s3;
+       }
+       return (NULL);
+}