[gnu.emacs] Improved cursor motion subroutines

julian@UHCCUX.UHCC.HAWAII.EDU (Julian Cowley) (03/28/89)

A little while back I posted a bug report and patch to gnu.emacs.bug
about GNU Emacs' handling of tabs.  While patching the code I noticed
that Emacs doesn't have support for backtabs (bt) or the multiple cursor
motion commands (UP, DO, LE, RI), so after little deliberation I decided
to go ahead and implement them myself.  The result is this: a drop-in
replacement for the Emacs 18.53 source file cm.c and a support patch for
cm.h and term.c.  It turned out to be a great learning experience --
everytime you explore Emacs source code you learn something new.

Ordinarily, adding a couple of new features like this should be a
fairly simple patch.  However, since the original file was not written
by rms, I decided to rewrite it from scratch since the original seemed
to be slightly messy.  If you take the time to compare this new
version with the old, you will notice several places where I changed
its behavior to make it more efficient, hopefully resulting in a
slight speedup in display update time.

While doing all this, I also took the time to make a couple of small
modifications to other parts of Emacs.  The first was to patch a
portion of term.c so that it will read the width of tabs correctly.
Emacs was previously checking for a `tw' capability, which presumably
means tab width, but I've not seen any other reference to this
capability, even in the GNU Termcap manual.  Instead, I've changed it
to check for `it' first, which is indeed mentioned in the System V
termcap manual, and to then check for `tw' second.  If none of these
are found, the tab width is set to a default of 8.

The second was to prevent a minor bug that was present with the old
version of cm.c, but which probably never manifested itself.  It
involves terminals which have no absolute cursor motion but are able
to set a scrolling region.  Highly unlikely, right?  Well, you never
know.  Emacs will currently try to run a terminal that is configured
this way, but it fails whenever the scrolling region is set.  The
reason is that Emacs tries to force absolute cursor motion right after
it sets the scrolling region, but since the terminal cannot position
the cursor without instead issuing a home command, the cursor position
gets mucked.  Therefore, I've added to term.c the requirement that
absolute cursor motion be present before Emacs attempts to use
scrolling region commands.

However much I have the urge to say that I am 100% sure that the
modifications will work without a hitch, I will refrain.  The cursor
sequences that it *should* output have been tested thoroughly,
however, so I do not expect any problems in the guts of the code.

Lastly, I hope these patches might be of worth to someone, even if
they do not end up in the distribution.  I just did it for the
learning experience, and I'm passing along the results to whoever
wants them.  Cheers!

julian@uhccux.uhcc.hawaii.edu
uunet!ucsd!nosc!uhccux!julian
julian@uhccux.bitnet
"Bunny rabbit?  What is bunny rabbit?"

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  cm.c cm.h.diff term.c.diff
# Wrapped by julian@uhccux on Mon Mar 27 09:28:41 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'cm.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cm.c'\"
else
echo shar: Extracting \"'cm.c'\" \(16883 characters\)
sed "s/^X//" >'cm.c' <<'END_OF_FILE'
X/* Cursor motion subroutines for GNU Emacs.
X   Copyright (C) 1985 Free Software Foundation, Inc.
X   based primarily on public domain code written by Chris Torek
X
XThis file is part of GNU Emacs.
X
XGNU Emacs is distributed in the hope that it will be useful,
Xbut WITHOUT ANY WARRANTY.  No author or distributor
Xaccepts responsibility to anyone for the consequences of using it
Xor for whether it serves any particular purpose or works at all,
Xunless he says so in writing.  Refer to the GNU Emacs General Public
XLicense for full details.
X
XEveryone is granted permission to copy, modify and redistribute
XGNU Emacs, but only under the conditions described in the
XGNU Emacs General Public License.   A copy of this license is
Xsupposed to have been given to you along with GNU Emacs so you
Xcan know your rights and responsibilities.  It should be in a
Xfile named COPYING.  Among other things, the copyright notice
Xand this notice must be preserved on all copies.  */
X
X#ifndef TEST
X#include "config.h"
X#endif /* TEST */
X#include <stdio.h>
X#include "cm.h"
X#ifndef TEST
X#include "termhooks.h"
X#endif /* TEST */
X
X/* External function definitions for termcap library */
X
Xextern int tputs ();
Xextern char *tgoto (), *BC, *UP;
X
X/* BIG is a constant that is big enough to never be selected as the
X   minimum cost for a cursor motion.  Use 9999 for VAXen
X   and about 2000 for 16-bit machines. */
X
X#define	BIG	9999
X
Xint cost;		/* Sums up costs -- also used in term.c */
X
X/* ARGSUSED */
Xevalcost (c)
X     char c;
X{
X  cost++;
X}
X
X#ifndef TEST
Xvoid
Xcmputc (c)
X     char c;
X{
X  if (termscript)
X    fputc (c & 0177, termscript);
X  putchar (c & 0177);
X}
X#endif /* TEST */
X
X/* NEXT TWO ARE DONE WITH MACROS */
X#if 0
X/*
X * Assume the cursor is at row row, column col.  Normally used only after
X * clearing the screen, when the cursor is at (0, 0), but what the heck,
X * let's let the guy put it anywhere.
X */
X
Xstatic
Xcmat (row, col)
X{
X  curY = row;
X  curX = col;
X}
X
X/*
X * Add n columns to the current cursor position.
X */
X
Xstatic
Xcmplus (n)
X{
X  curX += n;
X
X  /*
X   * If cursor hit edge of screen, what happened?
X   * N.B.: DO NOT!! write past edge of screen.  If you do, you
X   * deserve what you get.  Furthermore, on terminals with
X   * autowrap (but not magicwrap), don't write in the last column
X   * of the last line.
X   */
X
X  if (curX >= ScreenCols && !MagicWrap)
X    {
X      if (Wcm.cm_losewrap)
X	curY = -1;
X      else if (AutoWrap)
X	curX = 0, curY++;
X      else
X	curX--;
X    }
X}
X#endif
X
X/* Returns 1 if a termcap string outputs parameters that can be
X   of variable length, otherwise returns 0.  This function is
X   not very smart and can easily mistake an entry to contain
X   variable parameters, but those entries are pretty rare. */
X
Xstatic
Xcheck_var_param (p)
X     register char *p;
X{
X  while (*p)
X    {
X      if (p[0] == '%' && (p[1] == 'd' || p[1] == 'C'))
X      	return 1;
X      p++;
X    }
X  return 0;
X}
X
X/* The cost macros compute the cost in characters of using a certain
X   capability (including padding), or BIG if the capability is not
X   available.  For the cursor motion costs, we compute the cost with all
X   the parameters set to zero.  That way, if the length of the cursor
X   motion string varies (most commonly because of the `%d' sequence),
X   then we can get an idea of the minimum cost.  In that case we also set
X   the cost negative as a flag that we have to recompute the cost when
X   we've got the real parameters.
X
X   The variable char *p must be defined in the domain that these macros
X   are used. */
X
X#define COST(s)   (s ? (cost = 0, tputs (s, 1, evalcost), cost) : BIG)
X#define CMCOST(s) (s ? (p = tgoto (s, 0, 0), \
X			check_var_param (s) ? -COST (p) : COST (p)) \
X		     : BIG)
X
X/* Given the output speed of the terminal in the variable
X   ospeed, compute the cost factors for all of the termcap
X   strings that we will be using. */
X
Xcmcostinit ()
X{
X  register char *p;
X
X  UpCost =		COST (Up);
X  DownCost =		COST (Down);
X  LeftCost =		COST (Left);
X  RightCost =		COST (Right);
X  HomeCost =		COST (Home);
X  CRCost =		COST (CR);
X  LastLineCost =	COST (LastLine);
X  TabCost =		TabWidth ? COST (Tab) : BIG;
X  BackTabCost =		TabWidth ? COST (BackTab) : BIG;
X
X  AbsPositionCost =	CMCOST (AbsPosition);
X  ColPositionCost =	CMCOST (ColPosition);
X  RowPositionCost = 	CMCOST (RowPosition);
X  MultiUpCost =		CMCOST (MultiUp);
X  MultiDownCost =	CMCOST (MultiDown);
X  MultiLeftCost =	CMCOST (MultiLeft);
X  MultiRightCost =	CMCOST (MultiRight);
X}
X
X#undef COST
X#undef CMCOST
X
X/* Calculate the cost to move from (srcy, srcx) to (dsty, dstx) using
X   up and down, left and right strings, and tabs.  If doit is set,
X   actually perform the motion. */
X
X#define TAB 0
X#define SINGLE 1
X#define MULTIPLE 2
X#define ABSOLUTE 3
X
Xstatic int
Xcalccost (srcy, srcx, dsty, dstx, doit)
X{
X  int tabx, ntabs, singlecost, multicost, tabcost;
X  int tabl, tabr, ntabl, ntabr, c;
X  int deltax, deltay;
X  char *single, *multi, *tab;
X  register int bestcost, totalcost, use;
X
X  totalcost = 0;
X
X  if ((deltay = dsty - srcy) == 0)
X    goto x;
X
X  /* Select the functions that we will be considering according to
X     the direction we want to move in. */
X
X  if (deltay < 0)
X    {
X      single = Up, singlecost = UpCost;
X      multi = MultiUp, multicost = MultiUpCost;
X      deltay = -deltay;
X    }
X  else
X    {
X      single = Down, singlecost = DownCost;
X      multi = MultiDown, multicost = MultiDownCost;
X    }
X    
X  /* Find the cost of... */
X
X  /* ...using up or do a number of times */
X  if (singlecost < BIG)
X    bestcost = deltay * singlecost, use = SINGLE;
X  else
X    bestcost = BIG;
X
X  /* ...just going directly there with a cursor sequence */
X  if (RowPositionCost > 0)
X    {
X      if (RowPositionCost < bestcost)
X	bestcost = RowPositionCost, use = ABSOLUTE;
X    }
X  else if (-RowPositionCost < bestcost)
X    {
X      cost = 0;
X      tputs (tgoto (RowPosition, 0, dsty), 1, evalcost);
X      if (cost < bestcost)
X	bestcost = cost, use = ABSOLUTE;
X    }
X
X  /* ...or bundling all the up's or do's into one sequence. */
X  if (multicost > 0)
X    {
X      if (multicost < bestcost)
X	bestcost = multicost, use = MULTIPLE;
X    }
X  else if (-multicost < bestcost)
X    {
X      cost = 0;
X      tputs (tgoto (multi, 0, deltay), 1, evalcost);
X      if (cost < bestcost)
X	bestcost = cost, use = MULTIPLE;
X    }
X
X  if (doit)
X    {
X      if (bestcost >= BIG)
X        {
X	  /* This shouldn't have happened... */
X          printf ("OOPS");
X          return BIG;
X        }
X
X      switch (use)
X        {
X	case SINGLE:
X          while (deltay-- > 0)
X            tputs (single, 1, cmputc);
X          break;
X
X        case MULTIPLE:
X          tputs (tgoto (multi, 0, deltay), 1, cmputc);
X          break;
X
X  	case ABSOLUTE:
X  	  tputs (tgoto (RowPosition, 0, dsty), 1, cmputc);
X  	  break;
X        }
X    }
X
X  totalcost += bestcost;
X
Xx: 
X  if ((deltax = dstx - srcx) == 0)
X    goto done;
X
X  if (deltax < 0)
X    {
X      single = Left, singlecost = LeftCost;
X      multi = MultiLeft, multicost = MultiLeftCost;
X      tab = BackTab, tabcost = BackTabCost;
X      deltax = -deltax;
X    }
X  else
X    {
X      single = Right, singlecost = RightCost;
X      multi = MultiRight, multicost = MultiRightCost;
X      tab = Tab, tabcost = TabCost;
X    }
X
X  if (singlecost < BIG)
X    bestcost = deltax * singlecost, use = SINGLE;
X  else
X    bestcost = BIG;
X
X  /* Tabs (the toughie)....no kidding! */
X
X  if (tabcost < BIG && UseTabs)
X    {
X      /* There are two ways to use tabs: either to undershoot and then
X	 move forward, or to overshoot and then back up.  Therefore, we
X	 need to compute the columns of the two tab stops surrounding
X	 dstx.  Generally speaking, tabl is the tab stop to the left of
X	 dstx, and tabr is the tab stop to the right.  We also check to
X	 see if these tab stops don't go out of the bounds of the
X	 terminal.  Furthermore, ntabl is the number of tabs needed to
X	 reach tabl, and ntabr is the number of tabs needed to reach tabr.
X
X	 On some terminals, backtabs are supported; the behavior of
X	 backtabs is similar to regular tabs, but we need to compute
X	 the tab stops differently.  Here are the specifics:
X
X	 For forward tabs:
X
X	   tabl is the column of the tab stop directly to the left of
X	   but not at dstx.
X
X	   tabr is the column of the tab stop at or directly to the right
X	   of dstx, and must not be past the last column on the screen.
X
X	 For backtabs:
X
X	   tabl is the column of the tab stop at or directly to the left
X	   of dstx, and must be greater than zero since there is usually no
X	   tab stop at the first column.
X
X	   tabr is the column of the tab stop to the right of but not at
X	   dstx.
X
X      */
X	 
X      if (tab == Tab)
X        {
X          /* Compute the tabstops for regular tabs */
X	  ntabr = 1;
X          tabr = (srcx / TabWidth) * TabWidth + TabWidth;
X	  while (tabr < dstx)
X	    tabr += TabWidth, ntabr++;
X	  ntabl = ntabr - 1;
X	  tabl = tabr - TabWidth;
X	  if (tabr >= ScreenCols)
X	    /* Too far past the edge of the screen... */
X	    ntabr = 0;
X        }
X      else
X	{
X	  /* Otherwise compute the tabstops for backtabs...this is tricky! */
X	  ntabl = 1;
X	  tabl = ((srcx - 1) / TabWidth) * TabWidth;
X          while (tabl > dstx)
X            tabl -= TabWidth, ntabl++;
X          ntabr = ntabl - 1;
X          tabr = tabl + TabWidth;
X	  /* For backtabs, never assume there is a tab stop in column 0. */
X	  if (tabl == 0)
X	    ntabl = 0;
X	}
X
X      /* First compute the cost for undershooting... */
X
X      	       /* cost for ntabl  +   cost for right motion */
X      c = ntabl ? ntabl * tabcost + (dstx - tabl) * RightCost : BIG;
X      if (c < bestcost)
X	bestcost = c, tabx = tabl, ntabs = ntabl, use = TAB;
X
X      /* Now compute the cost for overshooting... */
X
X	       /* cost for ntabr  +   cost for left motion */
X      c = ntabr ? ntabr * tabcost + (tabr - dstx) * LeftCost : BIG;
X      if (c < bestcost)
X        bestcost = c, tabx = tabr, ntabs = ntabr, use = TAB;
X    }
X
X  if (ColPositionCost > 0)
X    {
X      if (ColPositionCost < bestcost)
X	bestcost = ColPositionCost, use = ABSOLUTE;
X    }
X  else if (-ColPositionCost < bestcost)
X    {
X      cost = 0;
X      tputs (tgoto (ColPosition, 0, dstx), 1, evalcost);
X      if (cost < bestcost)
X	bestcost = cost, use = ABSOLUTE;
X    }
X
X  if (multicost > 0)
X    {
X      if (multicost < bestcost)
X	bestcost = multicost, use = MULTIPLE;
X    }
X  else if (-multicost < bestcost)
X    {
X      cost = 0;
X      tputs (tgoto (multi, 0, deltax), 1, evalcost);
X      if (cost < bestcost)
X	bestcost = cost, use = MULTIPLE;
X    }
X
X  if (doit)
X    {
X      if (bestcost >= BIG)
X        {
X	  /* This shouldn't have happened... */
X          printf ("OOPS");
X          return BIG;
X        }
X
X      switch (use)
X        {
X	case TAB:
X	  while (ntabs-- > 0)
X	    tputs (tab, 1, cmputc);
X	  deltax = dstx - tabx;
X	  if (deltax < 0)
X	    single = Left, deltax = -deltax;
X	  else
X	    single = Right;
X	  /* Fall through.... */
X
X	case SINGLE:
X	  while (deltax-- > 0)
X	    tputs (single, 1, cmputc);
X	  break;
X
X	case MULTIPLE:
X	  tputs (tgoto (multi, 0, deltax), 1, cmputc);
X	  break;
X
X	case ABSOLUTE:
X	  tputs (tgoto (ColPosition, 0, dstx), 1, cmputc);
X	  break;
X        }
X    }
X  totalcost += bestcost;
X
Xdone:
X  return totalcost;
X}
X
Xlosecursor ()
X{
X  curY = -1;
X}
X
X#define	USEREL	0
X#define	USEHOME	1
X#define	USELL	2
X#define	USECR	3
X
Xcmgoto (row, col)
X{
X  register int bestcost, c, use;
X  register char *p;
X
X  /* First the degenerate case */
X  if (row == curY && col == curX)	/* already there */
X    return;
X
X  /* If we know the position of the cursor, we can use relative
X     motion commands, but only if we are not about to wrap on a
X     MagicWrap terminal.  In that case, don't believe the cursor
X     position: give up here and force use of absolute positioning.
X     We could also output a CR/LF, leaving us at the beginning of
X     the next line, but it's not worth the trouble to figure out
X     whether to use it or not.
X
X     If we don't know the position of the cursor, then we *have* to
X     use absolute cursor motion since we might have just set a
X     scrolling region. */
X
X  bestcost = BIG;
X
X  if (curX < 0 || curY < 0 || curX >= ScreenCols)
X    {
X      if (AbsPosition)
X	goto abs;
X      else
X	/* Last fighting chance for a terminal with no abs. cursor motion. */
X	goto home;
X    }
X
X  bestcost = calccost (curY, curX, row, col, 0);
X  use = USEREL;
X  
X  if ((c = CRCost) < BIG)
X    {
X      if (AutoLF)
X	if (curY + 1 >= ScreenRows)
X	  c = BIG;
X	else
X	  c += calccost (curY + 1, 0, row, col, 0);
X      else
X	c += calccost (curY, 0, row, col, 0);
X      if (c < bestcost)
X	bestcost = c, use = USECR;
X    }
X
X  if ((c = HomeCost) < BIG)
X    {
X      c += calccost (0, 0, row, col, 0);
X      if (c < bestcost)
X      bestcost = c, use = USEHOME;
X    }
X
X  if ((c = LastLineCost) < BIG)
X    {
X      c += calccost (ScreenRows - 1, 0, row, col, 0);
X      if (c < bestcost)
X	bestcost = c, use = USELL;
X    }
X
X  /* In the following comparisons, the = in <= is because when the costs
X     are the same, it looks nicer to move directly there. */
X
X  if (AbsPositionCost > 0)
X    {
X      if (AbsPositionCost <= bestcost)
X        {
X          /* Since we know the exact cost of absolute cursor motion,
X	     there is no need to recompute it...just go ahead.... */
X	abs:
X          tputs (tgoto (AbsPosition, col, row), 1, cmputc);
X          curY = row, curX = col;
X          return;
X        }
X    }
X  else if (-AbsPositionCost <= bestcost)
X    {
X      /* We're gonna have to recompute the cost to find out for
X	 sure whether it is cheaper... */
X
X      cost = 0;
X      p = tgoto (AbsPosition, col, row);
X      tputs (p, 1, evalcost);
X      if (cost <= bestcost)
X	{
X	  /* Ok, really is cheaper, so do it... */
X	  tputs (p, 1, cmputc);
X	  curY = row, curX = col;
X	  return;
X	}
X    }
X
X  switch (use)
X    {
X    home:
X    case USEHOME: 
X      tputs (Home, 1, cmputc);
X      curY = 0, curX = 0;
X      break;
X
X    case USELL: 
X      tputs (LastLine, 1, cmputc);
X      curY = ScreenRows - 1, curX = 0;
X      break;
X
X    case USECR: 
X      tputs (CR, 1, cmputc);
X      if (AutoLF)
X	curY++;
X      curX = 0;
X      break;
X    }
X
X  (void) calccost (curY, curX, row, col, 1);
X  curY = row, curX = col;
X  return;
X}
X
X/* Clear out all terminal info.  Used before copying in the info
X   on the actual terminal.  */
X
XWcm_clear ()
X{
X  bzero (&Wcm, sizeof Wcm);
X  UP = 0;
X  BC = 0;
X}
X
X/* Return 0 if the terminal is actually capable of moving the
X   cursor around on the screen. */
X
XWcm_init ()
X{
X  /* Check that we know the size of the screen.... */
X  if (ScreenRows <= 0 || ScreenCols <= 0)
X    return -1;
X  /* We need Left for some special functions. */
X  if (!Up || !Left)
X    return -1;
X  if (AbsPosition)
X    return 0;
X  if (Home && Down && Right)
X    return 0;
X  return -1;
X}
X
X#ifdef TEST
Xextern char *tgetstr ();
Xextern int tgetent (), tgetnum (), tgetflag ();
Xextern char PC;
Xextern char *getenv ();
X
Xstruct cm Wcm;
X
Xvoid
Xcmputc (c)
X     char c;
X{
X  c &= 0177;
X  if (c < ' ')
X    {
X      putchar ('^');
X      putchar (c + 'A' - '\001');
X    }
X  else
X    putchar (c);
X  fflush (stdout);
X}
X
Xmain (argc, argv)
X     int argc;
X     char **argv;
X{
X  char bp[2048], buf[2048], s[80], *area, *term, *pad_char;
X  int status, dstx, dsty;
X
X  if (argc == 1)
X    term = getenv ("TERM");
X  else
X    term = argv[1];
X
X  if ((status = tgetent (bp, term)) < 0)
X    fatal ("Cannot open termcap database.\n");
X  if (status == 0)
X    fatal ("Terminal type `%s' is not defined.\n", term);
X
X  Wcm_clear ();
X
X  area = buf;
X  Up = tgetstr ("up", &area);
X  Down = tgetstr ("do", &area);
X  if (!Down)
X    tgetstr ("nl", &area);
X  if (tgetflag ("bs"))
X    Left = "\b";
X  else
X    Left = tgetstr ("le", &area);
X  if (!Left)
X    Left = tgetstr ("bc", &area);
X  Right = tgetstr ("nd", &area);
X  Home = tgetstr ("ho", &area);
X  CR = tgetstr ("cr", &area);
X  LastLine = tgetstr ("ll", &area);
X  AbsPosition = tgetstr ("cm", &area);
X  ColPosition = tgetstr ("ch", &area);
X  RowPosition = tgetstr ("cv", &area);
X  Tab = tgetstr ("ta", &area);
X  BackTab = tgetstr ("bt", &area);
X  MultiUp = tgetstr ("UP", &area);
X  MultiDown = tgetstr ("DO", &area);
X  MultiLeft = tgetstr ("LE", &area);
X  MultiRight = tgetstr ("RI", &area);
X  pad_char = tgetstr ("pc", &area);
X  PC = pad_char ? *pad_char : 0;
X
X  TabWidth = tgetnum ("it");
X  if (TabWidth < 0)
X    {
X      TabWidth = tgetnum ("tw");
X      if (TabWidth < 0)
X	TabWidth = 8;
X    }
X  ScreenCols = tgetnum ("co");
X  ScreenRows = tgetnum ("li");
X
X  AutoWrap = tgetflag ("am");
X  MagicWrap = tgetflag ("xn");
X
X  UseTabs = 1;
X
X  if (Wcm_init ())
X    fatal ("Your terminal does not support cursor motion.\n");
X
X  cmcostinit ();
X  losecursor ();
X
X  gets (s);
X  while (*s)
X    {
X      if (s[0] == '-')
X	losecursor ();
X      else
X	{
X	  sscanf (s, "%d %d", &dsty, &dstx);	
X	  cmgoto (dsty, dstx);
X	  putchar ('\n');
X	}
X      gets (s);
X    }
X
X  exit (0);
X}
X
Xfatal (s, arg1, arg2)
X     char *s, *arg1, *arg2;
X{
X  fprintf (stderr, s, arg1, arg2);
X  exit (1);
X}
X#endif /* TEST */
END_OF_FILE
if test 16883 -ne `wc -c <'cm.c'`; then
    echo shar: \"'cm.c'\" unpacked with wrong size!
fi
# end of 'cm.c'
fi
if test -f 'cm.h.diff' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cm.h.diff'\"
else
echo shar: Extracting \"'cm.h.diff'\" \(2347 characters\)
sed "s/^X//" >'cm.h.diff' <<'END_OF_FILE'
X*** cm.h.18.53	Mon Mar 20 12:50:26 1989
X--- cm.h	Tue Mar 21 18:46:25 1989
X***************
X*** 41,45
X  		*cm_vabs,	/* vertical absolute (cv) */
X  		*cm_ds,		/* "don't send" string (ds) */
X! 		*cm_tab;	/* tab (ta) */
X  	int	cm_tabwidth,	/* tab width (tw) */
X  		cm_cols,	/* Number of cols on screen (co) */
X
X--- 41,50 -----
X  		*cm_vabs,	/* vertical absolute (cv) */
X  		*cm_ds,		/* "don't send" string (ds) */
X! 		*cm_tab,	/* tab (ta) */
X! 		*cm_backtab,	/* backtab (bt) */
X! 		*cm_multiup,	/* multiple up (UP) */
X! 		*cm_multidown,	/* multiple down (DO) */
X! 		*cm_multileft,	/* multiple left (LE) */
X! 		*cm_multiright;	/* multiple right (RI) */
X  	int	cm_tabwidth,	/* tab width (tw) */
X  		cm_cols,	/* Number of cols on screen (co) */
X***************
X*** 63,67
X  		cc_habs,
X  		cc_vabs,
X! 		cc_tab;
X  } Wcm;
X  
X
X--- 68,77 -----
X  		cc_habs,
X  		cc_vabs,
X! 		cc_tab,
X! 		cc_backtab,
X! 		cc_multiup,
X! 		cc_multidown,
X! 		cc_multileft,
X! 		cc_multiright;
X  } Wcm;
X  
X***************
X*** 85,88
X  #define	ColPosition	Wcm.cm_habs
X  #define	RowPosition	Wcm.cm_vabs
X  #define	AutoWrap	Wcm.cm_autowrap
X  #define	MagicWrap	Wcm.cm_magicwrap
X
X--- 95,104 -----
X  #define	ColPosition	Wcm.cm_habs
X  #define	RowPosition	Wcm.cm_vabs
X+ #define	Tab		Wcm.cm_tab
X+ #define	BackTab		Wcm.cm_backtab
X+ #define	MultiUp		Wcm.cm_multiup
X+ #define	MultiDown	Wcm.cm_multidown
X+ #define	MultiLeft	Wcm.cm_multileft
X+ #define	MultiRight	Wcm.cm_multiright
X  #define	AutoWrap	Wcm.cm_autowrap
X  #define	MagicWrap	Wcm.cm_magicwrap
X***************
X*** 91,94
X  #define	ScreenRows	Wcm.cm_rows
X  #define	ScreenCols	Wcm.cm_cols
X  
X  #define	cmat(row,col)	(curY = (row), curX = (col))
X
X--- 107,127 -----
X  #define	ScreenRows	Wcm.cm_rows
X  #define	ScreenCols	Wcm.cm_cols
X+ 
X+ #define	UpCost		Wcm.cc_up
X+ #define	DownCost	Wcm.cc_down
X+ #define	LeftCost	Wcm.cc_left
X+ #define	RightCost	Wcm.cc_right
X+ #define	HomeCost	Wcm.cc_home
X+ #define	CRCost		Wcm.cc_cr
X+ #define	LastLineCost	Wcm.cc_ll
X+ #define	AbsPositionCost	Wcm.cc_abs
X+ #define	ColPositionCost	Wcm.cc_habs
X+ #define	RowPositionCost	Wcm.cc_vabs
X+ #define	TabCost		Wcm.cc_tab
X+ #define	BackTabCost	Wcm.cc_backtab
X+ #define	MultiUpCost	Wcm.cc_multiup
X+ #define	MultiDownCost	Wcm.cc_multidown
X+ #define	MultiLeftCost	Wcm.cc_multileft
X+ #define	MultiRightCost	Wcm.cc_multiright
X  
X  #define	cmat(row,col)	(curY = (row), curX = (col))
END_OF_FILE
if test 2347 -ne `wc -c <'cm.h.diff'`; then
    echo shar: \"'cm.h.diff'\" unpacked with wrong size!
fi
# end of 'cm.h.diff'
fi
if test -f 'term.c.diff' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'term.c.diff'\"
else
echo shar: Extracting \"'term.c.diff'\" \(2449 characters\)
sed "s/^X//" >'term.c.diff' <<'END_OF_FILE'
X*** term.c.18.53	Fri Mar 24 19:09:49 1989
X--- term.c	Mon Mar 27 01:01:18 1989
X***************
X*** 974,977
X    TS_ins_multi_lines = tgetstr ("AL", &fill);
X    TS_bell = tgetstr ("bl", &fill);
X    TS_clr_to_bottom = tgetstr ("cd", &fill);
X    TS_clr_line = tgetstr ("ce", &fill);
X
X--- 974,978 -----
X    TS_ins_multi_lines = tgetstr ("AL", &fill);
X    TS_bell = tgetstr ("bl", &fill);
X+   BackTab = tgetstr ("bt", &fill);
X    TS_clr_to_bottom = tgetstr ("cd", &fill);
X    TS_clr_line = tgetstr ("ce", &fill);
X***************
X*** 1028,1031
X    TS_visual_mode = tgetstr ("vs", &fill);
X    TS_set_window = tgetstr ("wi", &fill);
X  
X    AutoWrap = tgetflag ("am");
X
X--- 1029,1036 -----
X    TS_visual_mode = tgetstr ("vs", &fill);
X    TS_set_window = tgetstr ("wi", &fill);
X+   MultiUp = tgetstr ("UP", &fill);
X+   MultiDown = tgetstr ("DO", &fill);
X+   MultiLeft = tgetstr ("LE", &fill);
X+   MultiRight = tgetstr ("RI", &fill);
X  
X    AutoWrap = tgetflag ("am");
X***************
X*** 1050,1054
X    min_padding_speed = tgetnum ("pb");
X    TN_standout_width = tgetnum ("sg");
X!   TabWidth = tgetnum ("tw");
X  
X  #ifdef VMS
X
X--- 1055,1065 -----
X    min_padding_speed = tgetnum ("pb");
X    TN_standout_width = tgetnum ("sg");
X!   TabWidth = tgetnum ("it");
X!   if (TabWidth < 0)
X!     {
X!       TabWidth = tgetnum ("tw");
X!       if (TabWidth < 0)
X! 	TabWidth = 8;
X!     }
X  
X  #ifdef VMS
X***************
X*** 1069,1075
X    PC = TS_pad_char ? *TS_pad_char : 0;
X  
X-   if (TabWidth < 0)
X-     TabWidth = 8;
X-   
X  /* Turned off since /etc/termcap seems to have :ta= for most terminals
X     and newer termcap doc does not seem to say there is a default.
X
X--- 1080,1083 -----
X    PC = TS_pad_char ? *TS_pad_char : 0;
X  
X  /* Turned off since /etc/termcap seems to have :ta= for most terminals
X     and newer termcap doc does not seem to say there is a default.
X***************
X*** 1185,1190
X    UseTabs = tabs_safe_p () && TabWidth == 8;
X  
X!   scroll_region_ok = TS_set_window || TS_set_scroll_region
X!     || TS_set_scroll_region_1;
X  
X    line_ins_del_ok = (((TS_ins_line || TS_ins_multi_lines)
X
X--- 1193,1200 -----
X    UseTabs = tabs_safe_p () && TabWidth == 8;
X  
X!   /* Make sure that we are able to position the cursor directly
X!      if we are going to be using the scroll region. */
X!   scroll_region_ok = (TS_set_window || TS_set_scroll_region
X!     || TS_set_scroll_region_1) && Wcm.cm_abs;
X  
X    line_ins_del_ok = (((TS_ins_line || TS_ins_multi_lines)
END_OF_FILE
if test 2449 -ne `wc -c <'term.c.diff'`; then
    echo shar: \"'term.c.diff'\" unpacked with wrong size!
fi
# end of 'term.c.diff'
fi
echo shar: End of shell archive.
exit 0