home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / EDITOR / NVI179B / NVI179B.ZIP / vi / v_undo.c < prev    next >
C/C++ Source or Header  |  1996-04-27  |  4KB  |  140 lines

  1. /*-
  2.  * Copyright (c) 1992, 1993, 1994
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  * Copyright (c) 1992, 1993, 1994, 1995, 1996
  5.  *    Keith Bostic.  All rights reserved.
  6.  *
  7.  * See the LICENSE file for redistribution information.
  8.  */
  9.  
  10. #include "config.h"
  11.  
  12. #ifndef lint
  13. static const char sccsid[] = "@(#)v_undo.c    10.5 (Berkeley) 3/6/96";
  14. #endif /* not lint */
  15.  
  16. #include <sys/types.h>
  17. #include <sys/queue.h>
  18. #include <sys/time.h>
  19.  
  20. #include <bitstring.h>
  21. #include <errno.h>
  22. #include <limits.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26.  
  27. #include "../common/common.h"
  28. #include "vi.h"
  29.  
  30. /*
  31.  * v_Undo -- U
  32.  *    Undo changes to this line.
  33.  *
  34.  * PUBLIC: int v_Undo __P((SCR *, VICMD *));
  35.  */
  36. int
  37. v_Undo(sp, vp)
  38.     SCR *sp;
  39.     VICMD *vp;
  40. {
  41.     /*
  42.      * Historically, U reset the cursor to the first column in the line
  43.      * (not the first non-blank).  This seems a bit non-intuitive, but,
  44.      * considering that we may have undone multiple changes, anything
  45.      * else (including the cursor position stored in the logging records)
  46.      * is going to appear random.
  47.      */
  48.     vp->m_final.cno = 0;
  49.  
  50.     /*
  51.      * !!!
  52.      * Set up the flags so that an immediately subsequent 'u' will roll
  53.      * forward, instead of backward.  In historic vi, a 'u' following a
  54.      * 'U' redid all of the changes to the line.  Given that the user has
  55.      * explicitly discarded those changes by entering 'U', it seems likely
  56.      * that the user wants something between the original and end forms of
  57.      * the line, so starting to replay the changes seems the best way to
  58.      * get to there.
  59.      */
  60.     F_SET(sp->ep, F_UNDO);
  61.     sp->ep->lundo = BACKWARD;
  62.  
  63.     return (log_setline(sp));
  64. }
  65.  
  66. /*
  67.  * v_undo -- u
  68.  *    Undo the last change.
  69.  *
  70.  * PUBLIC: int v_undo __P((SCR *, VICMD *));
  71.  */
  72. int
  73. v_undo(sp, vp)
  74.     SCR *sp;
  75.     VICMD *vp;
  76. {
  77.     EXF *ep;
  78.  
  79.     /* Set the command count. */
  80.     VIP(sp)->u_ccnt = sp->ccnt;
  81.  
  82.     /*
  83.      * !!!
  84.      * In historic vi, 'u' toggled between "undo" and "redo", i.e. 'u'
  85.      * undid the last undo.  However, if there has been a change since
  86.      * the last undo/redo, we always do an undo.  To make this work when
  87.      * the user can undo multiple operations, we leave the old semantic
  88.      * unchanged, but make '.' after a 'u' do another undo/redo operation.
  89.      * This has two problems.
  90.      *
  91.      * The first is that 'u' didn't set '.' in historic vi.  So, if a
  92.      * user made a change, realized it was in the wrong place, does a
  93.      * 'u' to undo it, moves to the right place and then does '.', the
  94.      * change was reapplied.  To make this work, we only apply the '.'
  95.      * to the undo command if it's the command immediately following an
  96.      * undo command.  See vi/vi.c:getcmd() for the details.
  97.      *
  98.      * The second is that the traditional way to view the numbered cut
  99.      * buffers in vi was to enter the commands "1pu.u.u.u. which will
  100.      * no longer work because the '.' immediately follows the 'u' command.
  101.      * Since we provide a much better method of viewing buffers, and
  102.      * nobody can think of a better way of adding in multiple undo, this
  103.      * remains broken.
  104.      *
  105.      * !!!
  106.      * There is change to historic practice for the final cursor position
  107.      * in this implementation.  In historic vi, if an undo was isolated to
  108.      * a single line, the cursor moved to the start of the change, and
  109.      * then, subsequent 'u' commands would not move it again. (It has been
  110.      * pointed out that users used multiple undo commands to get the cursor
  111.      * to the start of the changed text.)  Nvi toggles between the cursor
  112.      * position before and after the change was made.  One final issue is
  113.      * that historic vi only did this if the user had not moved off of the
  114.      * line before entering the undo command; otherwise, vi would move the
  115.      * cursor to the most attractive position on the changed line.
  116.      *
  117.      * It would be difficult to match historic practice in this area. You
  118.      * not only have to know that the changes were isolated to one line,
  119.      * but whether it was the first or second undo command as well.  And,
  120.      * to completely match historic practice, we'd have to track users line
  121.      * changes, too.  This isn't worth the effort.
  122.      */
  123.     ep = sp->ep;
  124.     if (!F_ISSET(ep, F_UNDO)) {
  125.         F_SET(ep, F_UNDO);
  126.         ep->lundo = BACKWARD;
  127.     } else if (!F_ISSET(vp, VC_ISDOT))
  128.         ep->lundo = ep->lundo == BACKWARD ? FORWARD : BACKWARD;
  129.  
  130.     switch (ep->lundo) {
  131.     case BACKWARD:
  132.         return (log_backward(sp, &vp->m_final));
  133.     case FORWARD:
  134.         return (log_forward(sp, &vp->m_final));
  135.     default:
  136.         abort();
  137.     }
  138.     /* NOTREACHED */
  139. }
  140.