home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / ftes46b5.zip / ftes46b5 / src / e_undo.cpp < prev    next >
C/C++ Source or Header  |  1997-08-25  |  10KB  |  371 lines

  1. /*    e_undo.cpp
  2.  *
  3.  *    Copyright (c) 1994-1996, Marko Macek
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  */
  9.  
  10. #include "fte.h"
  11.  
  12. int EBuffer::NextCommand() {
  13.     if (Match.Row != -1) {
  14.     Draw(Match.Row, Match.Row);
  15.     Match.Col = Match.Row = -1;
  16.     }
  17.     if (View)
  18.         View->SetMsg(0);
  19. #ifdef CONFIG_UNDOREDO
  20.     return BeginUndo();
  21. #else
  22.     return 1;
  23. #endif
  24. }
  25.  
  26. #ifdef CONFIG_UNDOREDO
  27.  
  28. int EBuffer::PushBlockData() {
  29.     if (BFI(this, BFI_Undo) == 0) return 1;
  30.     if (PushULong(BB.Col) == 0) return 0;
  31.     if (PushULong(BB.Row) == 0) return 0;
  32.     if (PushULong(BE.Col) == 0) return 0;
  33.     if (PushULong(BE.Row) == 0) return 0;
  34.     if (PushULong(BlockMode) == 0) return 0;
  35.     if (PushUChar(ucBlock) == 0) return 0;
  36.     return 1;
  37. }
  38.  
  39. int EBuffer::BeginUndo() {
  40.     US.NextCmd = 1;
  41.     return 1;
  42. }
  43.  
  44. int EBuffer::EndUndo() {
  45.     int N = US.Num - 1;
  46.     
  47.     assert(N >= 0);
  48.     if (N >= 1) {
  49.         int Order = 1;
  50.         
  51.         while (Order < N) Order <<= 1;
  52.  
  53.         US.Data = (void **) realloc(US.Data, sizeof(void *) * Order);
  54.         US.Top = (int *) realloc(US.Top, sizeof(int) * Order);
  55.         US.Num--;
  56.     } else {
  57.         free(US.Data); US.Data = 0;
  58.         free(US.Top); US.Top = 0;
  59.         US.Num = 0;
  60.     }
  61.     return 1;
  62. }
  63.  
  64. int EBuffer::PushULong(unsigned long l) {
  65. //    static unsigned long x = l;
  66.     return PushUData(&l, sizeof(unsigned long));
  67. }
  68.  
  69. int EBuffer::PushUChar(unsigned char ch) {
  70.     return PushUData(&ch, sizeof(unsigned char));
  71. }
  72.  
  73.  
  74. int EBuffer::PushUData(void *data, int len) {
  75.     int N;
  76.     int Order = 1;
  77.     
  78. //    printf("UPUSH: %d %c\n", len, *(char *)data); fflush(stdout);
  79.  
  80.     if (BFI(this, BFI_Undo) == 0) return 0;
  81.     if (US.Record == 0) return 1;
  82.     if (US.NextCmd || US.Num == 0 || US.Data == 0 || US.Top == 0) {
  83.         N = US.Num;
  84.         if ((BFI(this, BFI_UndoLimit) == -1) || (US.Undo) || (US.Num < BFI(this, BFI_UndoLimit))) {
  85.             N++;
  86.             US.Data = (void **) realloc(US.Data, sizeof(void *) * (N | 255));
  87.             US.Top = (int *)   realloc(US.Top,  sizeof(int)    * (N | 255));
  88.             if (US.Num == US.UndoPtr && !US.Undo)
  89.                 US.UndoPtr++;
  90.             US.Num++;
  91.         } else {
  92.             N = US.Num;
  93.             free(US.Data[0]);
  94.             memmove(US.Data, US.Data + 1, (N - 1) * sizeof(US.Data[0]));
  95.             memmove(US.Top,  US.Top  + 1, (N - 1) * sizeof(US.Top[0]));
  96.         }
  97.         assert(US.Data);
  98.         assert(US.Top);
  99.         N = US.Num - 1;
  100.         US.Data[N] = 0;
  101.         US.Top[N] = 0;
  102.         if (US.NextCmd == 1) {
  103.             US.NextCmd = 0;
  104. //            puts("\x7");
  105.             if (PushULong(CP.Col) == 0) return 0;
  106.             if (PushULong(CP.Row) == 0) return 0;
  107.             if (PushUChar(ucPosition) == 0) return 0;
  108. //            puts("\x7");
  109.         }
  110.         US.NextCmd = 0;
  111.     }
  112.     
  113.     N = US.Num - 1;
  114.     assert(N >= 0);
  115.     
  116.     if (US.Undo == 0) US.UndoPtr = US.Num;
  117.  
  118.     while (Order < (US.Top[N] + len)) Order <<= 1;
  119.     US.Data[N] = realloc(US.Data[N], Order);
  120.     memcpy((char *) US.Data[N] + US.Top[N], data, len);
  121.     US.Top[N] += len;
  122.     return 1;
  123. }
  124.  
  125. int EBuffer::GetUData(int No, int pos, void **data, int len) {
  126.     int N;
  127.     
  128.     if (No == -1)
  129.         N = US.Num - 1;
  130.     else
  131.         N = No;
  132.  
  133.     if (BFI(this, BFI_Undo) == 0) return 0;
  134.     if (N < 0) return 0;
  135.     if (US.Data[N] == 0) return 0;
  136.     if (US.Top[N] == 0) return 0;
  137.     
  138.     if (pos == -1)
  139.         pos = US.Top[N];
  140.     
  141.     
  142.     if (pos == 0) 
  143.         return 0;
  144. //    printf("N,pos = %d,%d len = %d\n", N, pos, len);
  145.     
  146.     assert(pos >= len);
  147.     *data = ((char *) US.Data[N]) + pos - len;
  148.     return 1;
  149. }
  150.  
  151. #define UGETC(rc,no,pos,what) \
  152.     do { void *d; \
  153.     rc = GetUData(no, pos, &d, sizeof(unsigned char)); \
  154.     *(unsigned char *)&what = *(unsigned char *)d; \
  155.     pos -= sizeof(unsigned char); \
  156.     } while (0)
  157.  
  158. #define UGET(rc,no,pos,what) \
  159.     do { void *d; \
  160.     rc = GetUData(no, pos, &d, sizeof(what)); \
  161.     memcpy((void *)&what, d, sizeof(what)); \
  162.     pos -= sizeof(what); \
  163.     } while (0)
  164.  
  165. int EBuffer::Undo(int undo) {
  166.     unsigned char UndoCmd;
  167.     int rc;
  168.     unsigned long Line;
  169.     unsigned long Len;
  170.     unsigned long ACount;
  171.     unsigned long Col;
  172.     void *data;
  173.     
  174.     int No;
  175.     int Pos;
  176.     
  177.     if (BFI(this, BFI_Undo) == 0)
  178.         return 0;
  179.     
  180.     if (undo)
  181.         No = US.UndoPtr - 1;
  182.     else
  183.         No = US.Num - 1;
  184.     
  185.     Pos = US.Top[No];
  186.     
  187.     if (No == 0 && Pos == 0) {
  188.         //puts("bottom");
  189.         return 0;
  190.     }
  191. //    for (int i = 0; i < Pos; i++) {
  192. //        printf("%d: %d\n", i, ((char *)US.Data[No])[i]);
  193. //    }
  194.     
  195. //    printf("Undo %d %d,%d\n", undo, No, Pos); fflush(stdout);
  196.     
  197. //    fprintf(stderr, "\nNo = %d, Num = %d\n", No, US.Num);
  198.     UGETC(rc, No, Pos, UndoCmd);
  199.     while (rc == 1) {
  200. //        printf("%d Undo %d %d,%d\n", UndoCmd, undo, No, Pos); fflush(stdout);
  201.   //  for (int i = 0; i < Pos; i++) {
  202. //        printf("%d: %d\n", i, ((char *)US.Data[No])[i]);
  203. //    }
  204.         switch (UndoCmd) {
  205.         case ucInsLine:
  206.             UGET(rc, No, Pos, Line); if (rc == 0) return 0;
  207. //            printf("\tDelLine %d\n", Line);
  208.             if (DelLine(Line) == 0) return 0;
  209.             break;
  210.             
  211.         case ucDelLine:
  212.             UGET(rc, No, Pos, Line); if (rc == 0) return 0;
  213.             UGET(rc, No, Pos, Len); if (rc == 0) return 0;
  214.             if (GetUData(No, Pos, &data, Len) == 0) return 0;
  215. //            printf("\tInsLine %d\n", Line);
  216.             if (InsLine(Line, 0) == 0) return 0;
  217. //            printf("\tInsText %d - %d\n", Line, Len);
  218.             if (InsText(Line, 0, Len, (char *) data) == 0) return 0;
  219.             Pos -= Len;
  220.             break;
  221.             
  222.         case ucInsChars:
  223.             UGET(rc, No, Pos, ACount); if (rc == 0) return 0;
  224.             UGET(rc, No, Pos, Col); if (rc == 0) return 0;
  225.             UGET(rc, No, Pos, Line); if (rc == 0) return 0;
  226. //            printf("\tDelChars %d %d %d\n", Line, Col, ACount);
  227.             if (DelChars(Line, Col, ACount) == 0) return 0;
  228.             break;
  229.             
  230.         case ucDelChars:
  231.             UGET(rc, No, Pos, Line); if (rc == 0) return 0;
  232.             UGET(rc, No, Pos, Col); if (rc == 0) return 0;
  233.             UGET(rc, No, Pos, ACount); if (rc == 0) return 0;
  234.             if (GetUData(No, Pos, &data, ACount) == 0) return 0;
  235. //            printf("\tInsChars %d %d %d\n", Line, Col, ACount);
  236.             if (InsChars(Line, Col, ACount, (char *) data) == 0) return 0;
  237.             Pos -= ACount;
  238.             break;
  239.             
  240.         case ucPosition:
  241.             UGET(rc, No, Pos, Line); if (rc == 0) return 0;
  242.             UGET(rc, No, Pos, Col); if (rc == 0) return 0;
  243. //            printf("\tSetPos %d %d\n", Line, Col);
  244.             if (SetPos(Col, Line) == 0) return 0;
  245.             break;
  246.           
  247.         case ucBlock: 
  248.             {
  249.                 EPoint P;
  250.                 unsigned long l;
  251.                 
  252. //                printf("\tBlock\n");
  253.                 UGET(rc, No, Pos, l); if (rc == 0) return 0;
  254.                 if (BlockMode != (int)l) BlockRedraw();
  255.                 BlockMode = l;
  256.                 UGET(rc, No, Pos, l); if (rc == 0) return 0;   P.Row = l;
  257.                 UGET(rc, No, Pos, l); if (rc == 0) return 0;   P.Col = l;
  258.                 if (SetBE(P) == 0) return 0;
  259.                 UGET(rc, No, Pos, l); if (rc == 0) return 0;   P.Row = l;
  260.                 UGET(rc, No, Pos, l); if (rc == 0) return 0;   P.Col = l;
  261.                 if (SetBB(P) == 0) return 0;
  262.             }
  263.             break;
  264.  
  265.         case ucFoldCreate:
  266.             // puts("ucFoldCreate");
  267.             UGET(rc, No, Pos, Line); if (rc == 0) return 0;
  268.             if (FoldDestroy(Line) == 0) return 0;
  269.             break;
  270.         
  271.         case ucFoldDestroy:
  272.             // puts("ucFoldDestroy");
  273.             {
  274.                 unsigned long level;
  275.                 int ff;
  276.                 
  277.                 UGET(rc, No, Pos, Line); if (rc == 0) return 0;
  278.                 UGET(rc, No, Pos, level); if (rc == 0) return 0;
  279.                 if (FoldCreate(Line) == 0) return 0;
  280.                 
  281.                 ff = FindFold(Line);
  282.                 assert(ff != -1);
  283.                 FF[ff].level = (unsigned char) level;
  284.             }
  285.             break;
  286.         case ucFoldPromote:
  287.             // puts("ucFoldPromote");
  288.             UGET(rc, No, Pos, Line); if (rc == 0) return 0;
  289.             if (FoldDemote(Line) == 0) return 0;
  290.             break;
  291.             
  292.         case ucFoldDemote:
  293.             // puts("ucFoldDemote");
  294.             UGET(rc, No, Pos, Line); if (rc == 0) return 0;
  295.             if (FoldPromote(Line) == 0) return 0;
  296.             break;
  297.             
  298.         case ucFoldOpen:
  299.             // puts("ucFoldOpen");
  300.             UGET(rc, No, Pos, Line); if (rc == 0) return 0;
  301.             if (FoldClose(Line) == 0) return 0;
  302.             break;
  303.             
  304.         case ucFoldClose:
  305.             // puts("ucFoldClose");
  306.             UGET(rc, No, Pos, Line); if (rc == 0) return 0;
  307.             if (FoldOpen(Line) == 0) return 0;
  308.             break;
  309.             
  310.         case ucModified:
  311. //            printf("\tModified\n");
  312.             Modified = 0;
  313.             break;
  314.             
  315.         default:
  316.             assert(1 == "Oops: invalid undo command.\n"[0]);
  317.         }
  318. //        puts("\tok");
  319.         
  320. //        fprintf(stderr, "\nNo = %d, Num = %d\n", No, US.Num);
  321.         UGETC(rc, No, Pos, UndoCmd);
  322.     }
  323.     
  324.     if (undo)
  325.         US.UndoPtr--;
  326.     else {
  327.         US.UndoPtr++;
  328.         free(US.Data[No]);
  329.         if (EndUndo() == 0) return 0;
  330.     }
  331.     
  332.     return 1;
  333. }
  334.  
  335. int EBuffer::Redo() {
  336.     int rc;
  337.     
  338.     if (BFI(this, BFI_Undo) == 0) return 0;
  339.     
  340. //    US.NextCmd = 0; // disable auto push position
  341.     
  342.     if (US.Num == 0 || US.UndoPtr == US.Num) {
  343.         Msg(INFO, "Nothing to redo.");
  344.         return 0;
  345.     }
  346.     
  347.     US.Record = 0;
  348.     rc =  Undo(0);
  349.     US.Record = 1;
  350.     return rc;
  351. }
  352.  
  353. int EBuffer::Undo() {
  354.     int rc;
  355.     
  356.     if (BFI(this, BFI_Undo) == 0) return 0;
  357.     
  358.     assert(US.Num >= 0);
  359.     assert(US.UndoPtr >= 0);
  360.     if (US.Num == 0 || US.UndoPtr == 0) {
  361.         Msg(INFO, "Nothing to undo.");
  362.         return 0;
  363.     }
  364.     
  365.     US.Undo = 1;
  366.     rc = Undo(1);
  367.     US.Undo = 0;
  368.     return rc;
  369. }
  370. #endif
  371.