home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / AP / JED / JED097-1.TAR / jed / src / undo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-12  |  4.6 KB  |  219 lines

  1. /*
  2.  *  Copyright (c) 1992, 1994 John E. Davis  (davis@amy.tch.harvard.edu)
  3.  *  All Rights Reserved.
  4.  */
  5. #include <stdio.h>
  6. #include "config.h"
  7. #include "buffer.h"
  8. #include "undo.h"
  9. #include "ins.h"
  10. #include "line.h"
  11. #include "misc.h"
  12.  
  13. #define LAST_UNDO CBuf->undo->Last_Undo
  14. #define FIRST_UNDO CBuf->undo->First_Undo
  15. #define UNDO_RING CBuf->undo->Undo_Ring
  16.  
  17. static int Undo_In_Progress = 0;
  18. int Undo_Buf_Unch_Flag;           /* 1 if buffer prev not modified */
  19.  
  20. #define DONT_RECORD_UNDO  (!(CBuf->flags & UNDO_ENABLED)\
  21.                || (CBuf->undo == NULL) || Undo_In_Progress)
  22.  
  23. #define UNDO_BD_FLAG 0x8000
  24. #define UNDO_UNCHANGED_FLAG 0x4000
  25.  
  26. #define IS_UNDO_BD (LAST_UNDO->type & UNDO_BD_FLAG)
  27.  
  28. void prepare_next_undo(void)
  29. {
  30.    LAST_UNDO++;
  31.    if (LAST_UNDO >= UNDO_RING + MAX_UNDOS) LAST_UNDO = UNDO_RING;
  32.    if (LAST_UNDO == FIRST_UNDO) FIRST_UNDO++;
  33.    if (FIRST_UNDO >= UNDO_RING + MAX_UNDOS) FIRST_UNDO = UNDO_RING;
  34.    
  35.    LAST_UNDO->type = 0;
  36.    LAST_UNDO->misc = 0;
  37. }
  38.  
  39.  
  40. void record_deletion(unsigned char *p, int n)
  41. {
  42.    int misc;
  43.    unsigned char *pb;
  44.    
  45.    
  46.    if (DONT_RECORD_UNDO || !n) return;
  47.    
  48.    if (((LAST_UNDO->type && 0xFF) == 0) || ((LAST_UNDO->type & CDELETE)
  49.                   && (LAST_UNDO->linenum == LineNum + CBuf->nup)
  50.                   && (LAST_UNDO->point == Point)))
  51.      {
  52.     if (LAST_UNDO->type != 0) misc = LAST_UNDO->misc; else misc = 0;
  53.     pb = LAST_UNDO->buf + misc;
  54.     while ((misc < 8) && n) 
  55.       {
  56.          *pb++ = *p++;
  57.          misc++;
  58.          n--;
  59.       }
  60.     LAST_UNDO->misc = misc;
  61.     LAST_UNDO->type |= CDELETE;
  62.     LAST_UNDO->linenum = LineNum + CBuf->nup;
  63.     LAST_UNDO->point = Point;
  64.     if (Undo_Buf_Unch_Flag) LAST_UNDO->type |= UNDO_UNCHANGED_FLAG;
  65.     Undo_Buf_Unch_Flag = 0;
  66.      }
  67.    
  68.    if (n)
  69.      {
  70.     prepare_next_undo();
  71.     record_deletion(p, n);
  72.      }
  73.    if (Undo_Buf_Unch_Flag) LAST_UNDO->type |= UNDO_UNCHANGED_FLAG;
  74. }
  75.  
  76.  
  77. int undo()
  78. {
  79.    int line;
  80.    CHECK_READ_ONLY
  81.    if (!(CBuf->flags & UNDO_ENABLED))
  82.      {
  83.     msg_error("Undo not enabled for this buffer.");
  84.     return(0);
  85.      }
  86.    else if ((CBuf->undo == NULL) || (LAST_UNDO->type == 0))
  87.      {
  88.     msg_error("No more undo information.");
  89.     return(0);
  90.      }
  91.    Undo_In_Progress = 1;
  92.    
  93.    do
  94.      {
  95.     line = (int) LAST_UNDO->linenum;
  96.     if ((line <= CBuf->nup) || (line > CBuf->nup + Max_LineNum))
  97.       {
  98.          msg_error("Next undo lies outside visible buffer.");
  99.          break;
  100.       }
  101.     line -= CBuf->nup;
  102.     goto_line(&line);
  103.     Point = LAST_UNDO->point;
  104.     
  105.     switch (LAST_UNDO->type & 0xFF)
  106.       {
  107.        case CDELETE: ins_chars(LAST_UNDO->buf, LAST_UNDO->misc);
  108.          /* Point = LAST_UNDO->point; */
  109.          break;
  110.     
  111.        case CINSERT: deln(&LAST_UNDO->misc);
  112.          break;
  113.          
  114.        case NLINSERT: del(); break;
  115.          
  116.        default: return(1);
  117.       }
  118.     
  119.     if (LAST_UNDO->type & UNDO_UNCHANGED_FLAG)
  120.       {
  121.          mark_buffer_modified(&Number_Zero);
  122.       }
  123.     
  124.     if (LAST_UNDO == FIRST_UNDO) LAST_UNDO->type = 0;
  125.     else 
  126.       {
  127.          LAST_UNDO--;
  128.          if (LAST_UNDO < UNDO_RING) LAST_UNDO = UNDO_RING + MAX_UNDOS - 1;
  129.       }
  130.      } 
  131.    while ((!IS_UNDO_BD) && (LAST_UNDO->type));
  132.    
  133.    message("Undo!");
  134.    Undo_In_Progress = 0;
  135.    return(1);
  136. }
  137.  
  138. void record_insertion(int n)
  139. {   
  140.    if (DONT_RECORD_UNDO || !n) return;
  141.    
  142.    if (LAST_UNDO->type == 0)
  143.      {
  144.     LAST_UNDO->misc = n;
  145.     LAST_UNDO->point = Point;
  146.      }
  147.    else if ((LAST_UNDO->type & CINSERT) && (LAST_UNDO->linenum == LineNum + CBuf->nup)
  148.         && (LAST_UNDO->point + LAST_UNDO->misc == Point)
  149.         && (LAST_UNDO->misc <= 32))
  150.      {
  151.     LAST_UNDO->misc += n;
  152.      }
  153.    else
  154.      {
  155.     prepare_next_undo();
  156.     LAST_UNDO->point = Point;
  157.     LAST_UNDO->misc = n;
  158.      }
  159.    
  160.    LAST_UNDO->type |= CINSERT;
  161.    if (Undo_Buf_Unch_Flag) LAST_UNDO->type |= UNDO_UNCHANGED_FLAG;
  162.    LAST_UNDO->linenum = LineNum + CBuf->nup;
  163. }
  164.  
  165. void record_newline_insertion()
  166. {
  167.    if (DONT_RECORD_UNDO) return;
  168.    if (LAST_UNDO->type != 0) prepare_next_undo();
  169.    if (Undo_Buf_Unch_Flag) LAST_UNDO->type |= UNDO_UNCHANGED_FLAG;
  170.    LAST_UNDO->point = Point;
  171.    LAST_UNDO->misc = 0;
  172.    LAST_UNDO->type |= NLINSERT;
  173.    LAST_UNDO->linenum = LineNum + CBuf->nup;
  174. }
  175.  
  176. void delete_undo_ring(Buffer *b)
  177. {
  178.    SLFREE (b->undo);   /* assume non null-- called by delete buffer */
  179. }
  180.  
  181.  
  182. void create_undo_ring()
  183. {
  184.    Undo_Type *ur;
  185.    Undo_Object_Type *uo;
  186.    int n;
  187.    
  188.    if (NULL == (ur = (Undo_Type *) SLMALLOC(sizeof(Undo_Type))))
  189.      {
  190.     msg_error("Unable to malloc space for undo!");
  191.     return;
  192.      }
  193.    CBuf->undo = ur;
  194.    uo = ur->Undo_Ring;
  195.    ur->Last_Undo = ur->First_Undo = uo;
  196.    n = MAX_UNDOS;
  197.    while (n--) 
  198.      {
  199.     uo->type = 0;
  200.     uo++;
  201.      }
  202. }
  203.  
  204. void mark_undo_boundary(Buffer *b)
  205. {
  206.    Buffer *s = CBuf;
  207.    
  208.    CBuf = b;
  209.    
  210.    if (!DONT_RECORD_UNDO && (LAST_UNDO->type != 0))
  211.      {
  212.     LAST_UNDO->type |= UNDO_BD_FLAG;
  213.      }
  214.    CBuf = s;
  215. }
  216.  
  217.    
  218.    
  219.