[gnu.emacs.bug] Tab cost calculated wrong in cm.c

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

In GNU Emacs 18.51.3 of Mon Jun  6 1988 on uhccux (berkeley-unix),
Emacs incorrectly calculates the cost of using tabs.  Quite
often a cursor motion sequence using tabs is output when in fact
a shorter sequence is possible using some other method of cursor
control.  Here is a patch for cm.c to solve the problem.
Actually, it would be really nice to rewrite cm.c (and term.c)
to include the use of the backtab character (bt), and the
relative screen motion capabilities (UP, DO, LE, RI).  However,
other than this one important error, it is adequate for now.

To see why Emacs makes this error, try using the test values of
srcx = 7 and dstx = 14.  The variable tab2x, which is supposed
to hold the value of the first tab stop greater than dstx, is
actually given the value of 8.  This causes the cost calculation
expressions further on in the file to produce a negative value,
leading Emacs to believe that tabs are the optimum cursor motion
sequence.

One note on the patch: I thought of changing the first line of
the original to read

  ntabs = (deltax + srcx % Wcm.cm_tabwidth) / Wcm.cm_tabwidth;

which is corrects the error algebraically, but I thought that it
looked a little cryptic.  With the while loop below, it may be
slightly slower but it is much more understandable.

julian@uhccux.uhcc.hawaii.edu
uunet!ucsd!nosc!uhccux!julian
julian@uhccux.bitnet
"Looks like Jim might be having entirely too much fun."

*** cm.c.18.52	Wed Mar 15 19:49:56 1989
--- cm.c	Wed Mar 15 19:53:44 1989
***************
*** 201,208
       */
  
!     ntabs = deltax / Wcm.cm_tabwidth;
!     n2tabs = ntabs + 1;
!     tabx = (srcx / Wcm.cm_tabwidth + ntabs) * Wcm.cm_tabwidth;
!     tab2x = tabx + Wcm.cm_tabwidth;
  
      if (tab2x >= Wcm.cm_cols)	/* too far (past edge) */

--- 201,210 -----
       */
  
!     n2tabs = 0;
!     tab2x = (srcx / Wcm.cm_tabwidth) * Wcm.cm_tabwidth;
!     while (tab2x <= dstx)
!       tab2x += Wcm.cm_tabwidth, n2tabs++;
!     ntabs = n2tabs - 1;
!     tabx = tab2x - Wcm.cm_tabwidth;
  
      if (tab2x >= Wcm.cm_cols)	/* too far (past edge) */