home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / fed0217s.zip / source / undo.cpp < prev    next >
C/C++ Source or Header  |  2001-02-20  |  11KB  |  434 lines

  1. /*
  2. ** Module   :UNDO.CPP
  3. ** Abstract :UNDO processor
  4. **
  5. ** Copyright (C) Sergey I. Yevtushenko
  6. **
  7. ** Log: Mon  15/03/1998     Created
  8. */
  9.  
  10. #include <string.h>
  11.  
  12. #include <buffer.h>
  13. #include <version.h>
  14.  
  15. #define UNDO    1
  16.  
  17. #ifndef max
  18. #define max(a,b) (((a) > (b)) ? (a) : (b))
  19. #define min(a,b) (((a) < (b)) ? (a) : (b))
  20. #endif
  21.  
  22. //----------------------------------------------------------------------
  23. // Undo processing routines
  24. //
  25. //----------------------------------------------------------------------
  26.  
  27. void Buffer::track_beg()
  28. {
  29.     tracking = UNDO;
  30. }
  31.  
  32. void Buffer::track_end()
  33. {
  34.     if(!tracking)
  35.         return;
  36.     if(!track_head)
  37.     {
  38.         tracking   = 0;
  39.         return;
  40.     }
  41.  
  42.     trackinfo *head = track_head; //Save track
  43.     track_head = undobuff;        //spoof 'track'
  44.  
  45.     track(opAction, head);
  46.  
  47.     undobuff   = track_head;
  48.     track_head = 0;
  49.     tracking   = 0;
  50.     undo_count++;
  51. }
  52.  
  53. void Buffer::track_cancel()
  54. {
  55.     if(track_head) //cleanup here
  56.     {
  57.         while(track_head)
  58.         {
  59.             switch(track_head->op)
  60.             {
  61.                 case opInsBlock:
  62.                     delete (Buffer *)track_head->arg1;
  63.                     break;
  64.                 case opRestoreLine:
  65.                 case opInsLine:
  66.                     Free(track_head->arg1);
  67.                     break;
  68. //                case opRestoreOrder:
  69. //                    delete (char*)(track_head->arg1);
  70.             }
  71.             trackinfo *tmp = track_head;
  72.             track_head = track_head->next;
  73.             delete tmp;
  74.         }
  75.     }
  76.     tracking = 0;
  77. }
  78.  
  79. void Buffer::track(int op, void *arg1, void *arg2)
  80. {
  81.     if(!tracking)
  82.     {
  83.         if(op == opInsBlock)
  84.             delete (Buffer *)arg1;
  85.         return;
  86.     }
  87.  
  88.     trackinfo *item = new trackinfo;
  89.  
  90.     item->next = track_head;
  91.     item->op   = op;
  92.     item->arg1 = arg1;
  93.     item->arg2 = arg2;
  94.     track_head = item;
  95.     switch(op)
  96.     {
  97.         case opRestoreLine:
  98.         case opInsLine:
  99.             // In this cases arg1 contains pointer to line,
  100.             // we need a copy of them
  101.  
  102.             item->arg1 = new Line(PLine(arg1));
  103.             break;
  104.     }
  105. }
  106.  
  107. void Buffer::undo(Rect&)
  108. {
  109.     trackinfo *item = undobuff;
  110.     int need_recalc = 0;
  111.  
  112.     if(item) //Undo buffer always contains opAction items
  113.     {
  114.         undobuff = item->next;
  115.  
  116.         trackinfo *action = (trackinfo *)item->arg1;
  117.  
  118.         while(action)
  119.         {
  120.             // Do action
  121.             switch(action->op)
  122.             {
  123.                 case opCurRow:
  124.                     cur_row = (int)action->arg1;
  125.                     break;
  126.  
  127.                 case opCurCol:
  128.                     cur_col = (int)action->arg1;
  129.                     break;
  130.  
  131.                 case opStartRow:
  132.                     start_row = (int)action->arg1;
  133.                     break;
  134.  
  135.                 case opStartCol:
  136.                     start_col = (int)action->arg1;
  137.                     break;
  138.  
  139.                 case opColBlock:
  140.                     col_block = (int)action->arg1;
  141.                     break;
  142.  
  143.                 case opInsMode:
  144.                     ins_mode = (int)action->arg1;
  145.                     break;
  146.  
  147.                 case opHiliting:
  148.                     hiliting = (int)action->arg1;
  149.                     need_recalc = 1;
  150.                     break;
  151.  
  152.                 case opMarking:
  153.                     mark_state = (int)action->arg1;
  154.                     break;
  155.  
  156.                 case opDelLine:
  157.                     //Free(del_line(rect, (int)action->arg1));
  158.                     Free(Remove((unsigned)action->arg1));
  159.                     need_recalc = 1;
  160.                     break;
  161.  
  162.                 case opInsBlock:
  163.                     {
  164.                         Buffer* tmp_buf = (Buffer *)action->arg1;
  165.                         int start_pos   = (int)action->arg2;
  166.                         move_items(tmp_buf, start_pos);
  167.                         delete tmp_buf;
  168.                         need_recalc = 1;
  169.                     }
  170.                     break;
  171.  
  172.                 case opInsLine:
  173.                     //ins_line(PLine(action->arg1), (int)action->arg2);
  174.                     At(action->arg1, (unsigned) action->arg2);
  175.                     need_recalc = 1;
  176.                     break;
  177.  
  178.                 case opRestoreLine:
  179.  
  180.                     //Free(del_line(rect, (int)action->arg2));
  181.                     //ins_line(PLine(action->arg1), (int)action->arg2);
  182.  
  183.                     //Semi-brute force:
  184.                     Free(Remove((unsigned)action->arg2));
  185.                     At(action->arg1,(unsigned)action->arg2);
  186.  
  187.                     need_recalc = 1;
  188.                     break;
  189.  
  190.                 case opMarkPos:
  191.                     old_abs_col = (int)action->arg1;
  192.                     old_abs_row = (int)action->arg2;
  193.                     break;
  194.  
  195.                 case opInsChar:
  196.                     abs_line()->ins_char(chr_in((int)action->arg1), abs_col());
  197.                     need_recalc = 1;
  198.                     break;
  199.  
  200.                 case opDelChar:
  201.                     abs_line()->del_char(abs_col());
  202.                     need_recalc = 1;
  203.                     break;
  204.  
  205.             }
  206.  
  207.             trackinfo *temp = action->next;
  208.  
  209.             delete action;
  210.             action = temp;
  211.         }
  212.         delete item;
  213.         undo_count--;
  214.  
  215.         if(undo_count < 0)
  216.             undo_count = 0;
  217.     }
  218.  
  219.     if(hiliting && need_recalc)
  220.         fill_hiliting(0, ST_INITIAL);
  221. }
  222.  
  223. int Buffer::get_undo_count()
  224. {
  225.     return undo_count;
  226. }
  227.  
  228. void Buffer::clear_undobuff()
  229. {
  230.     while(undobuff)
  231.     {
  232.         trackinfo *item = undobuff;
  233.  
  234.         if(item) //Undo buffer always contains opAction items
  235.         {
  236.             undobuff = item->next;
  237.             trackinfo *action = (trackinfo *)item->arg1;
  238.  
  239.             while(action)
  240.             {
  241.                 // Cleanup action item
  242.  
  243.                 switch(action->op)
  244.                 {
  245.                     case opRestoreLine:
  246.                     case opInsLine:
  247.                         Free(action->arg1);
  248.                         break;
  249.                 }
  250.  
  251.                 trackinfo *temp = action->next;
  252.  
  253.                 delete action;
  254.                 action = temp;
  255.             }
  256.             delete item;
  257.         }
  258.     }
  259.     undo_count = 0;
  260. }
  261.  
  262. //----------------------------------------------------------------------
  263. // Massive block processing routines
  264. //
  265. //----------------------------------------------------------------------
  266.  
  267. void Buffer::process_block(Rect& rect, PerCharFunc func)
  268. {
  269.     changed = 1;
  270.     if(!mark_state)
  271.     {
  272.         int chr = chr_out(get_cur_char());
  273.         if(chr)
  274.         {
  275.             replace_char(rect, func((char)chr));
  276.             cursor_left(rect);
  277.         }
  278.         return;
  279.     }
  280.     int mark_beg_row = min(old_abs_row, abs_row());
  281.     int mark_end_row = max(old_abs_row, abs_row());
  282.     int i,j;
  283.  
  284.     for(i = mark_beg_row; i <= mark_end_row; i++)
  285.         track(opRestoreLine,(void *)line(i),(void *)i);
  286.  
  287.     if(col_block || mark_beg_row == mark_end_row)
  288.     {
  289.         int mark_col_start = min(old_abs_col, abs_col());
  290.         int mark_col_end   = max(old_abs_col, abs_col());
  291.  
  292.         for(i = mark_beg_row; i <= mark_end_row; i++)
  293.             for(j = mark_col_start; j < mark_col_end; j++)
  294.             {
  295.                 int chr = chr_out(line(i)->del_char(j));
  296.                 line(i)->ins_char(chr_in(func((char)chr)),j);
  297.             }
  298.     }
  299.     else
  300.     {
  301.         for(i = mark_beg_row; i <= mark_end_row; i++)
  302.         {
  303.             int chr;
  304.             int col_start = 0;
  305.             int col_end = line(i)->len();
  306.  
  307.             if(i == mark_beg_row)
  308.                 col_start = (mark_beg_row == old_abs_row) ? old_abs_col : abs_col();
  309.  
  310.             if(i == mark_end_row)
  311.                 col_end = (mark_end_row == old_abs_row) ? old_abs_col : abs_col();
  312.  
  313.             for(int j = col_start; j < col_end; j++)
  314.             {
  315.                 chr = chr_out(line(i)->del_char(j));
  316.                 line(i)->ins_char(chr_in(func((char)chr)), j);
  317.             }
  318.         }
  319.     }
  320.  
  321.     fill_hiliting(mark_beg_row, line(mark_beg_row)->state());
  322. }
  323.  
  324. void Buffer::indent()
  325. {
  326.     changed = 1;
  327.     if(!mark_state)
  328.     {
  329.         track(opRestoreLine,(void *)abs_line(),(void *)abs_row());
  330.         abs_line()->ins_char(' ',0);
  331.         return;
  332.     }
  333.  
  334.     int mark_beg_row = min(old_abs_row, abs_row());
  335.     int mark_end_row = max(old_abs_row, abs_row());
  336.     int i;
  337.  
  338.     for(i = mark_beg_row; i <= mark_end_row; i++)
  339.         track(opRestoreLine,(void *)line(i),(void *)i);
  340.  
  341.     if(col_block || mark_beg_row == mark_end_row)
  342.     {
  343.         int mark_col_start = min(old_abs_col, abs_col());
  344.         for(i = mark_beg_row; i <= mark_end_row; i++)
  345.             line(i)->ins_char(' ', mark_col_start);
  346.     }
  347.     else
  348.     {
  349.         for(i = mark_beg_row; i <= mark_end_row; i++)
  350.         {
  351.             int col_start = 0;
  352.  
  353.             if(i == mark_beg_row)
  354.                 col_start = (mark_beg_row == old_abs_row) ?
  355.                                 old_abs_col :
  356.                                 abs_col();
  357.  
  358.             if(i == mark_end_row)
  359.             {
  360.                 int col_end = (mark_end_row == old_abs_row) ?
  361.                                 old_abs_col :
  362.                                 abs_col();
  363.  
  364.                 if(col_end == 0)
  365.                     break;
  366.             }
  367.  
  368.             line(i)->ins_char(' ', col_start);
  369.         }
  370.     }
  371.  
  372.     fill_hiliting(mark_beg_row, line(mark_beg_row)->state());
  373. }
  374.  
  375. void Buffer::unindent()
  376. {
  377.     changed = 1;
  378.     if(!mark_state)
  379.     {
  380.         track(opRestoreLine,(void *)abs_line(),(void *)abs_row());
  381.         abs_line()->del_char(0);
  382.         return;
  383.     }
  384.     int mark_beg_row = min(old_abs_row, abs_row());
  385.     int mark_end_row = max(old_abs_row, abs_row());
  386.     int i;
  387.  
  388.     for(i = mark_beg_row; i <= mark_end_row; i++)
  389.         track(opRestoreLine,(void *)line(i),(void *)i);
  390.  
  391.     if(col_block || mark_beg_row == mark_end_row)
  392.     {
  393.         int mark_col_start = min(old_abs_col, abs_col());
  394.         for(i = mark_beg_row; i <= mark_end_row; i++)
  395.             line(i)->del_char(mark_col_start);
  396.     }
  397.     else
  398.     {
  399.         for(i = mark_beg_row; i <= mark_end_row; i++)
  400.         {
  401.             int col_start = 0;
  402.  
  403.             if(i == mark_beg_row)
  404.                 col_start = (mark_beg_row == old_abs_row) ? old_abs_col : abs_col();
  405.  
  406.             if(i == mark_end_row)
  407.             {
  408.                 int col_end = (mark_end_row == old_abs_row) ?
  409.                                 old_abs_col :
  410.                                 abs_col();
  411.  
  412.                 if(col_end == 0)
  413.                     break;
  414.             }
  415.  
  416.             line(i)->del_char(col_start);
  417.         }
  418.     }
  419.  
  420.     fill_hiliting(mark_beg_row, line(mark_beg_row)->state());
  421. }
  422.  
  423. void Buffer::toupper(Rect& rect)
  424. {
  425.     process_block(rect, __to_upper);
  426. }
  427.  
  428. void Buffer::tolower(Rect& rect)
  429. {
  430.     process_block(rect, __to_lower);
  431. }
  432.  
  433.  
  434.