RVUndo.pas
上传用户:daoqigc
上传日期:2021-04-20
资源大小:2795k
文件大小:48k
源码类别:

RichEdit

开发平台:

Delphi

  1. {*******************************************************}
  2. {                                                       }
  3. {       RichView                                        }
  4. {       Undo/redo in TRichViewEdit.                     }
  5. {                                                       }
  6. {       Copyright (c) Sergey Tkachenko                  }
  7. {       svt@trichview.com                               }
  8. {       http://www.trichview.com                        }
  9. {                                                       }
  10. {*******************************************************}
  11. unit RVUndo;
  12. interface
  13. {$I RV_Defs.inc}
  14. uses SysUtils, Classes, RVClasses, RVItem, RVEdit, RVStyle, CRVData, CRVFData, RVRVData,
  15.      RichView;
  16. type
  17. {
  18.   Overview: TRVUndoList - list (TRVEditRVData.UndoList and RedoList) of
  19.     a group of undo items (TRVUndoInfos). Each group is is undone and redone
  20.     as one action.
  21.     Undo group is a list of undo items. They have different
  22.     types, all inherited from TRVUndoInfo.
  23. }
  24.   {
  25.     Type of undo operation
  26.   }
  27.   TRVUndoAction = (rvuMisc, rvuDeleteItem,rvuDeleteItems,rvuDeleteSubstring,
  28.                    rvuInsertItem,rvuInsertItems,rvuInsertSubstring,
  29.                    rvuNewLine, rvuBR, rvuPara, rvuPageBreak, rvuTyping,
  30.                    rvuTag, rvuStyleNo, rvuCheckpoint, rvuModifyItem,
  31.                    rvuChangeText, rvuChangeVAlign, rvuChangeListMarker);
  32.   TRVUndoList = class;
  33.   {
  34.     Basic class of undo item
  35.   }
  36.   TRVUndoInfo = class
  37.     public
  38.       Action: TRVUndoAction;  // type of elementary undo operation; maintained, but not used.
  39.       FUndoList: TRVUndoList; // a reference to undo list containing this undo item
  40.       constructor Create; virtual;
  41.       function RequiresFullReformat1(RVData: TRichViewRVData): Boolean; dynamic;
  42.       function RequiresFullReformat2(RVData: TRichViewRVData): Boolean; dynamic;
  43.       function RequiresFormat: Boolean; dynamic;
  44.       function RequiresSuperFormat: Boolean; dynamic;
  45.       procedure Undo(RVData: TRichViewRVData); dynamic;
  46.       procedure SetItemsRange(var StartItem, EndItem: Integer; RVData: TRichViewRVData);dynamic;
  47.       function ItemsAdded: Integer; dynamic;
  48.       function GetUndoListOwnerRVData: TCustomRVFormattedData;
  49.   end;
  50.   TRVUndoInfoClass = class of TRVUndoInfo;
  51.   {
  52.     Basic class of elementary undo item for operations on the ItemNo-th item.
  53.     Operation may affect a range of items ItemNo..LastAffectedItemNo
  54.     (if LastAffectedItemNo<>-1)
  55.   }
  56.   TRVUndoItemNoInfo = class(TRVUndoInfo)
  57.     public
  58.       ItemNo, LastAffectedItemNo: Integer;
  59.       constructor Create; override;
  60.       procedure SetItemsRange(var StartItem, EndItem: Integer; RVData: TRichViewRVData);override;
  61.   end;
  62.   {
  63.     Fake undo item. Used to reformat a range of items after performing undo.
  64.     (used for undo operation on paragraph numbering, affecting subsequent
  65.     paragraphs)
  66.   }
  67.   TRVUndoReformateRange = class(TRVUndoItemNoInfo)
  68.     public
  69.       SuperReformat: Boolean;
  70.       procedure Undo(RVData: TRichViewRVData); override;
  71.       function RequiresSuperFormat: Boolean; override;
  72.   end;
  73.   {
  74.     Undo changing VAlign of item
  75.   }
  76.   TRVUndoChangeVAlignInfo = class(TRVUndoItemNoInfo)
  77.     public
  78.       VAlign: TRVVAlign;
  79.       procedure Undo(RVData: TRichViewRVData); override;
  80.   end;
  81.   {
  82.     Undo resizing inserted controls
  83.   }
  84.   TRVUndoResizeInfo = class(TRVUndoItemNoInfo)
  85.     private
  86.       OldWidth: Integer;
  87.     public
  88.       Width, Height: Integer;
  89.       function RequiresFullReformat2(RVData: TRichViewRVData): Boolean; override;
  90.       procedure Undo(RVData: TRichViewRVData); override;
  91.   end;
  92.   {
  93.     Basic undo operation on text of the ItemNo-th item
  94.   }
  95.   TRVUndoStringInfo = class(TRVUndoItemNoInfo)
  96.     public
  97.       s: String;
  98.   end;
  99.   {
  100.     Undo changing item text 
  101.   }
  102.   TRVUndoChangeTextInfo = class(TRVUndoStringInfo)
  103.     private
  104.       OldWidth: Integer;
  105.     public
  106.       procedure Undo(RVData: TRichViewRVData); override;
  107.       function RequiresFullReformat2(RVData: TRichViewRVData): Boolean; override;
  108.   end;
  109.   {
  110.     Basic undo operation on substring of text of the ItemNo-th item
  111.   }
  112.   TRVUndoSubStringInfo = class(TRVUndoStringInfo)
  113.     public
  114.       Index: Integer;
  115.   end;
  116.   {
  117.     Basic undo operation on item
  118.   }
  119.   TRVUndoItemInfo = class(TRVUndoStringInfo)
  120.     public
  121.       Item: TCustomRVItemInfo;
  122.       destructor Destroy; override;
  123.   end;
  124.   {
  125.     Undo changing item (undoes operation replacing item's object)
  126.   }
  127.   TRVUndoReplaceItemInfo = class(TRVUndoItemInfo)
  128.     public
  129.       ItemNo: Integer;
  130.       function RequiresFormat: Boolean; override;
  131.       procedure Undo(RVData: TRichViewRVData); override;
  132.   end;
  133.   TRVUndoStringItemListInfo = class(TRVUndoInfo)
  134.     public
  135.       List: TStringList;
  136.       constructor Create; override;
  137.       destructor Destroy; override;
  138.   end;
  139.   TRVUndoItemRangeInfo = class(TRVUndoStringItemListInfo)
  140.     public
  141.       StartItemNo, LastAffectedItemNo: Integer;
  142.       constructor Create; override;
  143.       procedure SetItemsRange(var StartItem, EndItem: Integer; RVData: TRichViewRVData);override;
  144.   end;
  145.   TRVUndoListInfo = class(TRVUndoInfo)
  146.     public
  147.       List: TRVIntegerList;
  148.       constructor Create; override;
  149.       destructor Destroy; override;
  150.   end;
  151.   TRVUndoParaListInfo = class(TRVUndoListInfo)
  152.     private
  153.       FR: Boolean;
  154.     public
  155.       StartItemNo: Integer;
  156.       function RequiresFullReformat2(RVData: TRichViewRVData): Boolean; override;
  157.       procedure Undo(RVData: TRichViewRVData); override;
  158.       procedure SetItemsRange(var StartItem, EndItem: Integer; RVData: TRichViewRVData);override;
  159.   end;
  160.   TRVUndoParaInfo = class(TRVUndoItemNoInfo)
  161.     private
  162.       FR: Boolean;
  163.     public
  164.       ParaNo, Count: Integer;
  165.       function RequiresFullReformat2(RVData: TRichViewRVData): Boolean; override;
  166.       procedure Undo(RVData: TRichViewRVData); override;
  167.       procedure SetItemsRange(var StartItem, EndItem: Integer; RVData: TRichViewRVData);override;
  168.   end;
  169.   TRVUndoStyleNoInfo = class(TRVUndoItemNoInfo)
  170.     private
  171.       OldWidth: Integer;
  172.     public
  173.       WasStyleNo: Integer;
  174.       procedure Undo(RVData: TRichViewRVData); override;
  175.       function RequiresFullReformat2(RVData: TRichViewRVData): Boolean; override;
  176.   end;
  177.   TRVUndoAssociatedTextStyleNoInfo = class(TRVUndoStyleNoInfo)
  178.     public
  179.       procedure Undo(RVData: TRichViewRVData); override;
  180.   end;
  181.   TRVUndoDeleteItemInfo = class(TRVUndoItemInfo)
  182.     private
  183.       FR: Boolean;
  184.     public
  185.       function RequiresFullReformat2(RVData: TRichViewRVData): Boolean; override;
  186.       procedure Undo(RVData: TRichViewRVData); override;
  187.       function ItemsAdded: Integer; override;
  188.   end;
  189.   TRVUndoModifyItemInfo = class(TRVUndoItemInfo)
  190.     public
  191.       function RequiresFullReformat1(RVData: TRichViewRVData): Boolean; override;
  192.       procedure Undo(RVData: TRichViewRVData); override;
  193.   end;
  194.   TRVUndoNewLineInfo = class(TRVUndoItemNoInfo)
  195.     private
  196.       FR: Boolean;
  197.     public
  198.       WasSameAsPrev: Boolean;
  199.       WasParaNo: Integer;
  200.       function RequiresFullReformat2(RVData: TRichViewRVData): Boolean; override;
  201.       procedure Undo(RVData: TRichViewRVData); override;
  202.   end;
  203.   TRVUndoBRInfo = class(TRVUndoItemNoInfo)
  204.     public
  205.       WasBR: Boolean;
  206.       procedure Undo(RVData: TRichViewRVData); override;
  207.   end;
  208.   TRVUndoPageBreakInfo = class(TRVUndoItemNoInfo)
  209.     public
  210.       WasPageBreak: Boolean;
  211.       procedure Undo(RVData: TRichViewRVData); override;
  212.   end;
  213.   TRVUndoExtraIntProperty = class(TRVUndoItemNoInfo)
  214.     private
  215.       OldWidth: Integer;
  216.     public
  217.       OldValue: Integer;
  218.       Prop: TRVExtraItemProperty;
  219.       procedure Undo(RVData: TRichViewRVData); override;
  220.       function RequiresFullReformat2(RVData: TRichViewRVData): Boolean; override;
  221.   end;
  222.   TRVUndoExtraStrProperty = class(TRVUndoItemNoInfo)
  223.     public
  224.       OldValue: String;
  225.       Prop: TRVExtraItemStrProperty;
  226.       procedure Undo(RVData: TRichViewRVData); override;
  227.       function RequiresFormat: Boolean; override;
  228.   end;
  229.   TRVUndoDeleteItemsInfo = class(TRVUndoItemRangeInfo)
  230.     private
  231.       EndItemNo: Integer;
  232.       FR: Boolean;
  233.     public
  234.       function RequiresFullReformat2(RVData: TRichViewRVData): Boolean; override;
  235.       procedure Undo(RVData: TRichViewRVData); override;
  236.       function ItemsAdded: Integer; override;
  237.   end;
  238.   TRVUndoDeleteSubstringInfo = class(TRVUndoSubStringInfo)
  239.     private
  240.       OldWidth: Integer;
  241.     public
  242.       procedure Undo(RVData: TRichViewRVData); override;
  243.       function RequiresFullReformat2(RVData: TRichViewRVData): Boolean; override;
  244.   end;
  245.   TRVUndoInsertSubstringInfo = class(TRVUndoItemNoInfo)
  246.     private
  247.       OldWidth: Integer;
  248.     public
  249.       Index, Length: Integer;
  250.       procedure Undo(RVData: TRichViewRVData); override;
  251.       function RequiresFullReformat2(RVData: TRichViewRVData): Boolean; override;
  252.   end;
  253.   TRVRedoTypingInfo = class(TRVUndoSubStringInfo)
  254.     private
  255.       OldWidth: Integer;
  256.     public
  257.       Unicode: Boolean;
  258.       procedure Undo(RVData: TRichViewRVData); override;
  259.       function RequiresFullReformat2(RVData: TRichViewRVData): Boolean; override;
  260.   end;
  261.   TRVUndoTypingInfo = class(TRVUndoInsertSubstringInfo)
  262.     private
  263.       OldWidth: Integer;
  264.     public
  265.       Unicode: Boolean;
  266.       procedure Undo(RVData: TRichViewRVData); override;
  267.       function RequiresFullReformat2(RVData: TRichViewRVData): Boolean; override;
  268.   end;
  269.   TRVUndoInsertItemsInfo = class(TRVUndoItemNoInfo)
  270.     private
  271.       FR: Boolean;
  272.     public
  273.       Count: Integer;
  274.       function RequiresFullReformat1(RVData: TRichViewRVData): Boolean; override;
  275.       function RequiresFullReformat2(RVData: TRichViewRVData): Boolean; override;
  276.       procedure Undo(RVData: TRichViewRVData); override;
  277.       function ItemsAdded: Integer; override;
  278.   end;
  279.   TRVUndoInsertItemInfo = class(TRVUndoItemNoInfo)
  280.     private
  281.       FR: Boolean;
  282.     public
  283.       function RequiresFullReformat1(RVData: TRichViewRVData): Boolean; override;
  284.       function RequiresFullReformat2(RVData: TRichViewRVData): Boolean; override;
  285.       procedure Undo(RVData: TRichViewRVData); override;
  286.       function ItemsAdded: Integer; override;
  287.   end;
  288.   TRVUndoTagInfo = class(TRVUndoItemNoInfo)
  289.     public
  290.       WasTag: Integer;
  291.       TagsArePChars: Boolean;
  292.       function RequiresFormat: Boolean; override;
  293.       procedure Undo(RVData: TRichViewRVData); override;
  294.       destructor Destroy; override;
  295.   end;
  296.   TRVUndoAddCPInfo = class(TRVUndoItemNoInfo)
  297.     public
  298.       procedure Undo(RVData: TRichViewRVData); override;
  299.   end;
  300.   TRVUndoDeleteCPInfo = class(TRVUndoItemNoInfo)
  301.     public
  302.       Checkpoint: TRVCPInfo;
  303.       TagsArePChars: Boolean;
  304.       procedure Undo(RVData: TRichViewRVData); override;
  305.       destructor Destroy; override;
  306.   end;
  307.   TRVUndoModifyItemProps = class(TRVUndoItemNoInfo)
  308.     private
  309.       OldW: Integer;
  310.     public
  311.       AffectWidth,AffectSize: Boolean;
  312.       SubObject: TObject;
  313.       function GetOppositeClass: TRVUndoInfoClass; virtual;
  314.       function RequiresFormat: Boolean; override;
  315.       function RequiresFullReformat1(RVData: TRichViewRVData): Boolean; override;
  316.       function RequiresFullReformat2(RVData: TRichViewRVData): Boolean; override;
  317.       procedure SetOppositeUndoInfoProps(UndoInfo: TRVUndoModifyItemProps); dynamic;
  318.   end;
  319.   TRVUndoModifyItemTerminator = class (TRVUndoModifyItemProps)
  320.     public
  321.       Opening: Boolean;
  322.       constructor Create; override;
  323.       procedure Undo(RVData: TRichViewRVData); override;
  324.   end;
  325.   TRVUndoModifyItemIntProperty = class(TRVUndoModifyItemProps)
  326.     public
  327.       PropertyName: String;
  328.       Value: LongInt;
  329.       procedure Undo(RVData: TRichViewRVData); override;
  330.   end;
  331.   TRVUndoModifyItemIntProperties = class(TRVUndoModifyItemProps)
  332.     public
  333.       PropList: TStringList;
  334.       constructor Create; override;
  335.       destructor Destroy; override;
  336.       procedure Undo(RVData: TRichViewRVData); override;
  337.   end;
  338.   TRVCompositeUndo = class (TRVUndoInfo)
  339.     public
  340.       ItemNo: Integer;
  341.       IsRedo: Boolean;
  342.       UndoList: TRVUndoList;
  343.       destructor Destroy; override;
  344.       procedure Undo(RVData: TRichViewRVData); override;
  345.       procedure SetItemsRange(var StartItem, EndItem: Integer; RVData: TRichViewRVData);override;
  346.       function RequiresFormat: Boolean; override;
  347.       //!!procedure ChangeRVData(ARVData: TRichViewRVData; Restoring: Boolean); override;
  348.   end;
  349.   TRVUndoInfos = class (TRVList)
  350.     private
  351.       procedure PerformUndo(RVData: TRichViewRVData; Reformat: Boolean);
  352.     public
  353.       Caption: String;
  354.       UndoType: TRVUndoType;
  355.       CaretItemNo, CaretOffs: Integer;
  356.       procedure Undo(RVData: TRichViewRVData; Reformat: Boolean);
  357.       procedure Redo(RVData: TRichViewRVData; Reformat: Boolean);
  358.       //!!procedure ChangeRVData(RVData: TRichViewRVData; Restoring: Boolean);
  359.       function CanDelete: Boolean;
  360.       procedure ChangeUndoList(UndoList: TRVUndoList);
  361.   end;
  362.   TRVUndoList = class (TRVList)
  363.     private
  364.       FReformatLock: Integer;
  365.       procedure Pop;
  366.     public
  367.       FRVData: TCustomRVFormattedData;
  368.       Limit: Integer;
  369.       GroupModeCount: Integer;
  370.       constructor Create(ARVData: TCustomRVFormattedData);
  371.       procedure PopIfEmpty;
  372.       function BeginItem(UndoType: TRVUndoType; const Caption: String; CaretItemNo, CaretOffs: Integer): Boolean;
  373.       procedure EndItem; // optional
  374.       procedure AddInfo(Info: TRVUndoInfo);
  375.       procedure AddInfos(Infos: TRVUndoInfos);
  376.       procedure AddTyping(CaretItemNo, CaretOffs: Integer; Unicode: Boolean);
  377.       procedure AddUntyping(const c: String; CaretItemNo, CaretOffs: Integer);
  378.       procedure Undo(RVData: TRichViewRVData);
  379.       procedure Redo(RVData: TRichViewRVData);
  380.       function CurrentUndoType: TRVUndoType;
  381.       function CurrentUndoCaption: String;
  382.       procedure LockRFR;
  383.       procedure UnlockRFR;
  384.       //!!procedure ChangeRVData(ARVData: TRichViewRVData; Restoring: Boolean);
  385.   end;
  386. implementation
  387. uses RVScroll, RVERVData, RVStr;
  388. {==============================================================================}
  389. function NFR2(ItemNo, OldWidth: Integer; RVData: TRichViewRVData): Boolean;
  390. var NewWidth: Integer;
  391. begin
  392.   NewWidth := RVData.CalculateMinItemWidthPlusEx(ItemNo);
  393.   Result := (OldWidth<>NewWidth) and
  394.             ((OldWidth>=RVData.DocumentWidth) or (NewWidth>RVData.DocumentWidth));
  395. end;
  396. {==============================================================================}
  397. procedure FreeItem(item: TCustomRVItemInfo; RVData: TCustomRVData);
  398. var s: String;
  399. begin
  400.   if item=nil then exit;
  401.   s := '';
  402.   RVData.ItemAction(rviaDestroying, Item, s, nil);
  403.   RVData.ControlAction(rvcaDestroyInUndoList, -1, item);
  404.   if rvoTagsArePChars in RVData.Options then
  405.     StrDispose(PChar(item.Tag));
  406.   item.Tag := 0;
  407.   if item.Checkpoint<>nil then begin
  408.     if rvoTagsArePChars in RVData.Options then
  409.       StrDispose(PChar(item.Checkpoint.Tag));
  410.     item.Checkpoint.Tag := 0;
  411.     item.Checkpoint.Free;
  412.     item.Checkpoint     := nil;
  413.   end;
  414.   item.Free;
  415. end;
  416. {================================= TRVUndoList ================================}
  417. constructor TRVUndoList.Create(ARVData: TCustomRVFormattedData);
  418. begin
  419.   inherited Create;
  420.   FRVData := ARVData;
  421.   Limit := -1;
  422. end;
  423. {------------------------------------------------------------------------------}
  424. function TRVUndoList.BeginItem(UndoType: TRVUndoType; const Caption: String;
  425.                                CaretItemNo, CaretOffs: Integer): Boolean;
  426. var Item: TRVUndoInfos;
  427.     s: String;
  428. begin
  429.   if Limit=0 then begin
  430.     Result := False;
  431.     exit;
  432.   end;
  433.   Result := True;
  434.   if (GroupModeCount>0) and (Count>0) and
  435.      not (
  436.      (TRVUndoInfos(Items[Count-1]).Count=1) and
  437.      (TRVUndoInfo(TRVUndoInfos(Items[Count-1]).Items[0]).Action = rvuTyping)
  438.      ) then
  439.     exit;
  440.   if (Count=Limit) then
  441.     Delete(0);
  442.   s := Caption;
  443.   if (Count>0) and (TRVUndoInfos(Items[Count-1]).Count=0) then begin
  444.     CaretItemNo := TRVUndoInfos(Items[Count-1]).CaretItemNo;
  445.     CaretOffs   := TRVUndoInfos(Items[Count-1]).CaretOffs;
  446.     s           := TRVUndoInfos(Items[Count-1]).Caption;
  447.     Delete(Count-1);
  448.   end;
  449.   Item := TRVUndoInfos.Create;
  450.   Item.UndoType := UndoType;
  451.   Item.Caption := s;
  452.   Item.CaretItemNo := CaretItemNo;
  453.   Item.CaretOffs := CaretOffs;
  454.   Add(Item);
  455. end;
  456. {------------------------------------------------------------------------------}
  457. procedure TRVUndoList.EndItem;
  458. begin
  459.   if (Count>0) and (TRVUndoInfos(Items[Count-1]).Count=0) then
  460.     Delete(Count-1);
  461. end;
  462. {------------------------------------------------------------------------------}
  463. function TRVUndoList.CurrentUndoType: TRVUndoType;
  464. begin
  465.   if Count=0 then
  466.     Result := rvutNone
  467.   else
  468.     Result := TRVUndoInfos(Items[Count-1]).UndoType;
  469. end;
  470. {------------------------------------------------------------------------------}
  471. function TRVUndoList.CurrentUndoCaption: String;
  472. begin
  473.   if Count=0 then
  474.     Result := ''
  475.   else
  476.     Result := TRVUndoInfos(Items[Count-1]).Caption;
  477. end;
  478. {------------------------------------------------------------------------------}
  479. procedure TRVUndoList.AddTyping(CaretItemNo, CaretOffs: Integer; Unicode: Boolean);
  480. var info: TRVUndoTypingInfo;
  481.     infos: TRVUndoInfos;
  482.     cancombine: Boolean;
  483. begin
  484.   if Limit=0 then exit;
  485.   if (Count>0) and (TRVUndoInfos(Items[Count-1]).Count=0) then
  486.     Delete(Count-1);
  487.   cancombine := False;
  488.   if (Count>0) then begin
  489.     infos := TRVUndoInfos(Items[Count-1]);
  490.     if (infos.Count>0) and (TRVUndoInfo(infos.Items[0]) is TRVUndoTypingInfo) then begin
  491.       info := TRVUndoTypingInfo(infos.Items[0]);
  492.       if (info.ItemNo = CaretItemNo) and (info.Index+info.Length = CaretOffs) then begin
  493.         inc(info.Length);
  494.         inc(infos.CaretOffs);
  495.         cancombine := True;
  496.       end;
  497.     end;
  498.   end;
  499.   if not cancombine then begin
  500.     BeginItem(rvutTyping,'',CaretItemNo,CaretOffs);
  501.     info := TRVUndoTypingInfo.Create;
  502.     info.Action := rvuTyping;
  503.     info.ItemNo := CaretItemNo;
  504.     info.Index  := CaretOffs;
  505.     info.Length := 1;
  506.     info.Unicode := Unicode;
  507.     AddInfo(info);
  508.   end;
  509. end;
  510. {------------------------------------------------------------------------------}
  511. procedure TRVUndoList.AddUntyping(const c: String; CaretItemNo, CaretOffs: Integer);
  512. var info: TRVRedoTypingInfo;
  513.     infos: TRVUndoInfos;
  514.     unicode, cancombine: Boolean;
  515.     Len: Integer;
  516. begin
  517.   Unicode := Length(c)>1;
  518.   if (Count>0) and (TRVUndoInfos(Items[Count-1]).Count=0) then
  519.     Delete(Count-1);
  520.   cancombine := False;
  521.   if (Count>0) then begin
  522.     infos := TRVUndoInfos(Items[Count-1]);
  523.     if (infos.Count>0) and (TRVUndoInfo(infos.Items[0]) is TRVRedoTypingInfo) then begin
  524.       info := TRVRedoTypingInfo(infos.Items[0]);
  525.       Len := Length(info.s);
  526.       {$IFNDEF RVDONOTUSEUNICODE}
  527.       if Unicode then begin
  528.         RVCheckUni(Len);
  529.         Len := Len div 2;
  530.       end;
  531.       {$ENDIF}
  532.       if (info.ItemNo = CaretItemNo) and (info.Index-Len = CaretOffs) then begin
  533.         info.s := info.s+c;
  534.         dec(infos.CaretOffs);
  535.         cancombine := True;
  536.       end;
  537.     end;
  538.   end;
  539.   if not cancombine then begin
  540.     BeginItem(rvutTyping,'',CaretItemNo,CaretOffs);
  541.     info := TRVRedoTypingInfo.Create;
  542.     info.Action := rvuTyping;
  543.     info.ItemNo := CaretItemNo;
  544.     info.Index  := CaretOffs;
  545.     info.s      := c;
  546.     info.Unicode := Unicode;
  547.     AddInfo(info);
  548.   end;
  549. end;
  550. {------------------------------------------------------------------------------}
  551. procedure TRVUndoList.AddInfo(Info: TRVUndoInfo);
  552. var infos: TRVUndoInfos;
  553. begin
  554.   if Count=0 then
  555.     raise ERichViewError.Create(errRVUndoEmpty);
  556.   infos := TRVUndoInfos(Items[Count-1]);
  557.   if (infos.Count=1) and (TRVUndoInfo(infos.Items[0]).Action = rvuTyping) then
  558.     raise ERichViewError.Create(errRVUndoAdd);
  559.   Info.FUndoList := Self;
  560.   infos.Add(Info);
  561. end;
  562. {------------------------------------------------------------------------------}
  563. procedure TRVUndoList.AddInfos(Infos: TRVUndoInfos);
  564. begin
  565.   Add(Infos);
  566.   Infos.ChangeUndoList(Self);
  567. end;
  568. {------------------------------------------------------------------------------}
  569. procedure TRVUndoList.PopIfEmpty;
  570. var infos: TRVUndoInfos;
  571. begin
  572.   if (Count=0) or (GroupModeCount>0) then exit;
  573.   infos := TRVUndoInfos(Items[Count-1]);
  574.   if infos.Count=0 then
  575.     Delete(Count-1);
  576. end;
  577. {------------------------------------------------------------------------------}
  578. procedure TRVUndoList.Pop;
  579. var infos: TRVUndoInfos;
  580. begin
  581.   infos := TRVUndoInfos(Items[Count-1]);
  582.   if infos.CanDelete then
  583.     Delete(Count-1)
  584.   else
  585.     if TRVUndoInfo(infos.Items[0]) is TRVUndoTypingInfo then
  586.       dec(infos.CaretOffs)
  587.     else //TRVRedoTypingInfo
  588.       inc(infos.CaretOffs)
  589. end;
  590. {------------------------------------------------------------------------------}
  591. procedure TRVUndoList.Undo(RVData: TRichViewRVData);
  592. begin
  593.   if Count=0 then
  594.     raise ERichViewError.Create(errRVUndoEmptyBuffer);
  595.   TRVUndoInfos(Items[Count-1]).Undo(RVData, FReformatLock<=0);
  596.   Pop;
  597. end;
  598. {------------------------------------------------------------------------------}
  599. procedure TRVUndoList.Redo(RVData: TRichViewRVData);
  600. begin
  601.   if Count=0 then
  602.     raise ERichViewError.Create(errRVUndoEmptyBuffer);
  603.   TRVUndoInfos(Items[Count-1]).Redo(RVData, FReformatLock<=0);
  604.   Pop;
  605. end;
  606. {------------------------------------------------------------------------------}
  607. procedure TRVUndoList.LockRFR;
  608. begin
  609.   inc(FReformatLock);
  610. end;
  611. {------------------------------------------------------------------------------}
  612. procedure TRVUndoList.UnlockRFR;
  613. begin
  614.   dec(FReformatLock);
  615. end;
  616. {------------------------------------------------------------------------------}
  617. {
  618. procedure TRVUndoList.ChangeRVData(ARVData: TRichViewRVData;
  619.   Restoring: Boolean);
  620. var i: Integer;
  621. begin
  622.   for i := 0 to Count-1 do
  623.     TRVUndoInfos(Items[i]).ChangeRVData(ARVData, Restoring);
  624. end;
  625. //!!
  626. }
  627. {=============================== TRVUndoInfos =================================}
  628. function TRVUndoInfos.CanDelete: Boolean;
  629. begin
  630.   Result := True;
  631.   if Count=0 then exit;
  632.   if TRVUndoInfo(Items[0]) is TRVUndoTypingInfo then
  633.     Result := TRVUndoTypingInfo(Items[0]).Length=0
  634.   else if TRVUndoInfo(Items[0]) is TRVRedoTypingInfo then
  635.     Result := Length(TRVRedoTypingInfo(Items[0]).s)=0
  636.   else if TRVUndoInfo(Items[0]) is TRVCompositeUndo then
  637.     Result := TRVCompositeUndo(Items[0]).UndoList.Count=0;
  638. end;
  639. {------------------------------------------------------------------------------}
  640. procedure TRVUndoInfos.ChangeUndoList(UndoList: TRVUndoList);
  641. var i: Integer;
  642. begin
  643.   for i := 0 to Count-1 do
  644.     TRVUndoInfo(Items[i]).FUndoList := UndoList;
  645. end;
  646. {------------------------------------------------------------------------------}
  647. procedure TRVUndoInfos.PerformUndo(RVData: TRichViewRVData; Reformat: Boolean);
  648. var i, ItemsAdded,ItemsAdded1, StartItemNo, EndItemNo, StartDItemNo, EndDItemNo,
  649.     StartItemNo1, EndItemNo1, TerminatorCount,TerminatorW: Integer;
  650.     RF, RFR, SRF: Boolean;
  651.     ui: TRVUndoInfo;
  652. begin
  653.    if Count=0 then exit;
  654.    RVData.Deselect(nil, True);
  655.    StartItemNo := RVData.Items.Count-1;
  656.    EndItemNo    := 0;
  657.    ItemsAdded := 0;
  658.    RFR        := False;
  659.    RF         := False;
  660.    SRF        := False;
  661.    for i := Count-1 downto 0 do begin
  662.      ui := TRVUndoInfo(Items[i]);
  663.      RF := RF or ui.RequiresFormat;
  664.      SRF := SRF or ui.RequiresSuperFormat;
  665.      ui.SetItemsRange(StartItemNo1, EndItemNo1, RVData);
  666.      {
  667.      if ItemsAdded<0 then
  668.        inc(StartItem1,ItemsAdded);
  669.      }
  670.      if ItemsAdded>0 then
  671.        inc(EndItemNo1,ItemsAdded);
  672.      ItemsAdded1 := ui.ItemsAdded;
  673.      if ItemsAdded1>0 then
  674.        inc(EndItemNo1, ItemsAdded1);
  675.      inc(ItemsAdded,ItemsAdded1);
  676.      if StartItemNo1<StartItemNo then
  677.        StartItemNo := StartItemNo1;
  678.      if EndItemNo1>EndItemNo then
  679.        EndItemNo := EndItemNo1;
  680.    end;
  681.    if EndItemNo<StartItemNo then begin
  682.      StartItemNo1 := StartItemNo;
  683.      StartItemNo := EndItemNo;
  684.      EndItemNo   := StartItemNo1;
  685.    end;
  686.    if StartItemNo<0 then
  687.      StartItemNo := 0;
  688.    if EndItemNo<StartItemNo then
  689.      EndItemNo := StartItemNo;
  690.    if EndItemNo+ItemsAdded<StartItemNo then
  691.      EndItemNo := StartItemNo-ItemsAdded;
  692.    if EndItemNo>=RVData.Items.Count then
  693.      EndItemNo := RVData.Items.Count-1;
  694.    RVData.Item2DrawItem(StartItemNo, 1, StartDItemNo, StartItemNo1);
  695.    RVData.Item2DrawItem(EndItemNo,   1, EndDItemNo, EndItemNo1);
  696.    if StartDItemNo=-1 then
  697.      StartDItemNo := 0;
  698.    if EndDItemNo=-1 then
  699.      EndDItemNo := RVData.DrawItems.Count-1;
  700.    RVData.GetParaBounds(StartDItemNo,EndDItemNo, StartDItemNo, EndDItemNo);
  701.    TerminatorCount := 0;
  702.    TerminatorW     := 0;
  703.    for i := Count-1 downto 0 do begin
  704.      ui := TRVUndoInfo(Items[i]);
  705.      if TerminatorCount=0 then
  706.        RFR := RF and (RFR or ui.RequiresFullReformat1(RVData));
  707.      if ui is TRVUndoModifyItemTerminator then begin
  708.        if not TRVUndoModifyItemTerminator(ui).Opening then begin
  709.          if TerminatorCount=0 then
  710.            TerminatorW := TRVUndoModifyItemTerminator(ui).OldW;
  711.          inc(TerminatorCount);
  712.          end
  713.        else begin
  714.          dec(TerminatorCount);
  715.          if TerminatorCount=0 then
  716.            TRVUndoModifyItemTerminator(ui).OldW := TerminatorW;
  717.        end;
  718.      end;
  719.      ui.Undo(RVData);
  720.      if TerminatorCount=0 then
  721.        RFR := RF and (RFR or ui.RequiresFullReformat2(RVData));
  722.    end;
  723.    {$IFNDEF RVDONOTUSELIVESPELL}
  724.    RVData.AdjustInItemsRange(StartItemNo);
  725.    RVData.AdjustInItemsRange(EndItemNo);
  726.    RVData.ExpandToParaSection(StartItemNo, EndItemNo, StartItemNo, EndItemNo);
  727.    for i := StartItemNo to EndItemNo do
  728.      RVData.GetItem(i).ClearLiveSpellingResult;
  729.    (RVData as TRVEditRVData).LaterSetBackLiveSpellingTo(StartItemNo, 0, False);
  730.    {$ENDIF}
  731.    if Reformat and RF then
  732.      if RFR and (RVData.DocumentWidth<>RVData.CalculateMinDocWidthPlus(nil,nil)) then
  733.        RVData.Format(False)
  734.      else
  735.        RVData.FormatParas(StartDItemNo, EndDItemNo, ItemsAdded);
  736.    if TCustomRichView(RVData.RichView).InplaceEditor=nil then
  737.      RVData.DoSetSelectionBounds(CaretItemNo,CaretOffs,CaretItemNo,CaretOffs);
  738.    RVData.Invalidate;
  739.    if SRF then
  740.      (RVData.GetAbsoluteRootData as TRichViewRVData).Format_(True, True, True, 0, nil,
  741.        False, True, False);   
  742. end;
  743. {------------------------------------------------------------------------------}
  744. procedure TRVUndoInfos.Redo(RVData: TRichViewRVData; Reformat: Boolean);
  745. begin
  746.    TRVEditRVData(RVData).BeginNamedUndoSequence(UndoType, Caption, True);
  747.    PerformUndo(RVData, Reformat);
  748. end;
  749. {------------------------------------------------------------------------------}
  750. procedure TRVUndoInfos.Undo(RVData: TRichViewRVData; Reformat: Boolean);
  751. begin
  752.    TRVEditRVData(RVData).BeginRedoSequence(UndoType, Caption);
  753.    PerformUndo(RVData, Reformat);
  754. end;
  755. {=============================== TRVUndoInfo ==================================}
  756. constructor TRVUndoInfo.Create;
  757. begin
  758.   inherited Create;
  759. end;
  760. {------------------------------------------------------------------------------}
  761. procedure TRVUndoInfo.Undo(RVData: TRichViewRVData);
  762. begin
  763. end;
  764. {------------------------------------------------------------------------------}
  765. procedure TRVUndoInfo.SetItemsRange(var StartItem, EndItem: Integer; RVData: TRichViewRVData);
  766. begin
  767.   // empty
  768. end;
  769. {------------------------------------------------------------------------------}
  770. {
  771. procedure TRVUndoInfo.ChangeRVData(ARVData: TRichViewRVData; Restoring: Boolean);
  772. begin
  773.   // empty
  774. end;
  775. //!!
  776. }
  777. {------------------------------------------------------------------------------}
  778. function TRVUndoInfo.RequiresFullReformat1(RVData: TRichViewRVData): Boolean;
  779. begin
  780.   Result := False;
  781. end;
  782. {------------------------------------------------------------------------------}
  783. function TRVUndoInfo.RequiresFormat: Boolean;
  784. begin
  785.   Result := True;
  786. end;
  787. {------------------------------------------------------------------------------}
  788. function TRVUndoInfo.RequiresSuperFormat: Boolean;
  789. begin
  790.   Result := False;
  791. end;
  792. {------------------------------------------------------------------------------}
  793. function TRVUndoInfo.RequiresFullReformat2(RVData: TRichViewRVData): Boolean;
  794. begin
  795.   Result := False;
  796. end;
  797. {------------------------------------------------------------------------------}
  798. function TRVUndoInfo.ItemsAdded: Integer;
  799. begin
  800.   Result := 0;
  801. end;
  802. {------------------------------------------------------------------------------}
  803. function TRVUndoInfo.GetUndoListOwnerRVData: TCustomRVFormattedData;
  804. begin
  805.   Result := FUndoList.FRVData;
  806. end;
  807. {================================ TRVUndoItemNoInfo ===========================}
  808. constructor TRVUndoItemNoInfo.Create;
  809. begin
  810.   inherited Create;
  811.   LastAffectedItemNo := -1;
  812. end;
  813. {------------------------------------------------------------------------------}
  814. procedure TRVUndoItemNoInfo.SetItemsRange(var StartItem, EndItem: Integer; RVData: TRichViewRVData);
  815. begin
  816.   if ItemNo>=0 then begin
  817.     StartItem := ItemNo;
  818.     if LastAffectedItemNo>=0 then
  819.       EndItem := LastAffectedItemNo
  820.     else
  821.       EndItem := ItemNo;
  822.   end;
  823. end;
  824. {========================= TRVUndoStringItemListInfo ==========================}
  825. constructor TRVUndoStringItemListInfo.Create;
  826. begin
  827.   inherited Create;
  828.   List := TStringList.Create;
  829. end;
  830. {------------------------------------------------------------------------------}
  831. destructor TRVUndoStringItemListInfo.Destroy;
  832. var i: Integer;
  833. begin
  834.   for i := 0 to List.Count-1 do
  835.     FreeItem(TCustomRVItemInfo(List.Objects[i]), GetUndoListOwnerRVData);
  836.   List.Free;
  837.   inherited Destroy;
  838. end;
  839. {========================== TRVUndoItemRangeInfo ==============================}
  840. constructor TRVUndoItemRangeInfo.Create;
  841. begin
  842.   inherited Create;
  843.   LastAffectedItemNo := -1;
  844. end;
  845. {------------------------------------------------------------------------------}
  846. procedure TRVUndoItemRangeInfo.SetItemsRange(var StartItem,
  847.   EndItem: Integer; RVData: TRichViewRVData);
  848. begin
  849.   StartItem := StartItemNo;
  850.   if LastAffectedItemNo=-1 then
  851.     EndItem := StartItemNo+List.Count
  852.   else
  853.     EndItem := LastAffectedItemNo;
  854. end;
  855. {============================== TRVUndoItemInfo ===============================}
  856. destructor TRVUndoItemInfo.Destroy;
  857. begin
  858.   FreeItem(Item, GetUndoListOwnerRVData);
  859.   inherited Destroy;
  860. end;
  861. {================================== TRVUndoDeleteItem =========================}
  862. function TRVUndoDeleteItemInfo.ItemsAdded: Integer;
  863. begin
  864.   Result := +1;
  865. end;
  866. {------------------------------------------------------------------------------}
  867. function TRVUndoDeleteItemInfo.RequiresFullReformat2(
  868.   RVData: TRichViewRVData): Boolean;
  869. begin
  870.   Result :=  FR or
  871.             (RVData.CalculateMinItemWidthPlusEx(ItemNo)>
  872.              RVData.DocumentWidth);
  873. end;
  874. {------------------------------------------------------------------------------}
  875. procedure TRVUndoDeleteItemInfo.Undo(RVData: TRichViewRVData);
  876. begin
  877.   TRVEditRVData(RVData).Do_InsertItem(ItemNo,s,Item, True, FR);
  878.   Item := nil;
  879. end;
  880. {================================= TRVUndoDeleteItems =========================}
  881. function TRVUndoDeleteItemsInfo.ItemsAdded: Integer;
  882. begin
  883.   Result := +List.Count;
  884. end;
  885. {------------------------------------------------------------------------------}
  886. function TRVUndoDeleteItemsInfo.RequiresFullReformat2(
  887.   RVData: TRichViewRVData): Boolean;
  888. begin
  889.   Result := FR or
  890.             (RVData.CalculateMinItemsWidthPlusEx(StartItemNo, EndItemNo)>RVData.DocumentWidth);
  891. end;
  892. {------------------------------------------------------------------------------}
  893. procedure TRVUndoDeleteItemsInfo.Undo(RVData: TRichViewRVData);
  894. begin
  895.   TRVEditRVData(RVData).Do_InsertItems(StartItemNo,List,True,FR);
  896.   EndItemNo := StartItemNo+List.Count-1;
  897.   List.Clear;
  898. end;
  899. {=========================== TRVUndoDeleteSubstring ===========================}
  900. function TRVUndoDeleteSubstringInfo.RequiresFullReformat2(
  901.   RVData: TRichViewRVData): Boolean;
  902. begin
  903.   Result := NFR2(ItemNo, OldWidth, RVData);
  904. end;
  905. {------------------------------------------------------------------------------}
  906. procedure TRVUndoDeleteSubstringInfo.Undo(RVData: TRichViewRVData);
  907. begin
  908.   OldWidth := RVData.CalculateMinItemWidthPlusEx(ItemNo);
  909.   TRVEditRVData(RVData).Do_InsertSubstring(ItemNo, Index, s);
  910. end;
  911. {============================ TRVUndoInsertItem ===============================}
  912. function TRVUndoInsertItemInfo.ItemsAdded: Integer;
  913. begin
  914.   Result := -1;
  915. end;
  916. {------------------------------------------------------------------------------}
  917. function TRVUndoInsertItemInfo.RequiresFullReformat1(
  918.   RVData: TRichViewRVData): Boolean;
  919. begin
  920.  Result := RVData.CalculateMinItemWidthPlusEx(ItemNo)>=
  921.            RVData.DocumentWidth;
  922. end;
  923. {------------------------------------------------------------------------------}
  924. function TRVUndoInsertItemInfo.RequiresFullReformat2(RVData: TRichViewRVData): Boolean;
  925. begin
  926.  Result := FR;
  927. end;
  928. {------------------------------------------------------------------------------}
  929. procedure TRVUndoInsertItemInfo.Undo(RVData: TRichViewRVData);
  930. begin
  931.   TRVEditRVData(RVData).Do_DeleteItem(ItemNo, FR);
  932. end;
  933. {============================ TRVUndoInsertSubstring ==========================}
  934. function TRVUndoInsertSubstringInfo.RequiresFullReformat2(
  935.   RVData: TRichViewRVData): Boolean;
  936. begin
  937.   Result := NFR2(ItemNo, OldWidth, RVData);
  938. end;
  939. {------------------------------------------------------------------------------}
  940. procedure TRVUndoInsertSubstringInfo.Undo(RVData: TRichViewRVData);
  941. begin
  942.   OldWidth := RVData.CalculateMinItemWidthPlusEx(ItemNo);
  943.   TRVEditRVData(RVData).Do_DeleteSubstring(ItemNo, Index, Length);
  944. end;
  945. {========================= TRVUndoInsertItems =================================}
  946. function TRVUndoInsertItemsInfo.ItemsAdded: Integer;
  947. begin
  948.   Result := -Count;
  949. end;
  950. {------------------------------------------------------------------------------}
  951. function TRVUndoInsertItemsInfo.RequiresFullReformat1(
  952.   RVData: TRichViewRVData): Boolean;
  953. begin
  954.   Result := RVData.CalculateMinItemsWidthPlusEx(ItemNo,ItemNo+Count-1)>=RVData.DocumentWidth;
  955. end;
  956. {------------------------------------------------------------------------------}
  957. function TRVUndoInsertItemsInfo.RequiresFullReformat2(
  958.   RVData: TRichViewRVData): Boolean;
  959. begin
  960.   Result := FR;
  961. end;
  962. {------------------------------------------------------------------------------}
  963. procedure TRVUndoInsertItemsInfo.Undo(RVData: TRichViewRVData);
  964. begin
  965.   TRVEditRVData(RVData).Do_DeleteItems(ItemNo,ItemNo+Count-1,FR);
  966. end;
  967. {============================== TRVUndoNewLine ================================}
  968. function TRVUndoNewLineInfo.RequiresFullReformat2(RVData: TRichViewRVData): Boolean;
  969. begin
  970.   Result := FR;
  971. end;
  972. {------------------------------------------------------------------------------}
  973. procedure TRVUndoNewLineInfo.Undo(RVData: TRichViewRVData);
  974. begin
  975.   TRVEditRVData(RVData).Do_NewLine(ItemNo, WasSameAsPrev, WasParaNo, FR);
  976. end;
  977. {=============================== TRVUndoBR ====================================}
  978. procedure TRVUndoBRInfo.Undo(RVData: TRichViewRVData);
  979. var FR: Boolean;
  980. begin
  981.   TRVEditRVData(RVData).Do_BR(ItemNo, WasBR, FR);
  982. end;
  983. {========================== TRVUndoPageBreakInfo ==============================}
  984. procedure TRVUndoPageBreakInfo.Undo(RVData: TRichViewRVData);
  985. begin
  986.   TRVEditRVData(RVData).Do_PageBreak(ItemNo, WasPageBreak);
  987. end;
  988. {========================= TRVUndoExtraIntProperty ============================}
  989. function TRVUndoExtraIntProperty.RequiresFullReformat2(
  990.   RVData: TRichViewRVData): Boolean;
  991. begin
  992.   Result := NFR2(ItemNo, OldWidth, RVData);
  993. end;
  994. {------------------------------------------------------------------------------}
  995. procedure TRVUndoExtraIntProperty.Undo(RVData: TRichViewRVData);
  996. begin
  997.   OldWidth := RVData.CalculateMinItemWidthPlusEx(ItemNo);
  998.   TRVEditRVData(RVData).Do_ExtraIntProperty(ItemNo, Prop, OldValue);
  999. end;
  1000. {========================== TRVUndoExtraStrProperty ============================}
  1001. function TRVUndoExtraStrProperty.RequiresFormat: Boolean;
  1002. begin
  1003.   Result := False;
  1004. end;
  1005. {------------------------------------------------------------------------------}
  1006. procedure TRVUndoExtraStrProperty.Undo(RVData: TRichViewRVData);
  1007. begin
  1008.   TRVEditRVData(RVData).Do_ExtraStrProperty(ItemNo, Prop, OldValue);
  1009. end;
  1010. {============================= TRVUndoListInfo ================================}
  1011. constructor TRVUndoListInfo.Create;
  1012. begin
  1013.   inherited Create;
  1014.   List := TRVIntegerList.Create;
  1015. end;
  1016. {------------------------------------------------------------------------------}
  1017. destructor TRVUndoListInfo.Destroy;
  1018. begin
  1019.   List.Free;
  1020.   inherited Destroy;
  1021. end;
  1022. {============================ TRVUndoParaListInfo =============================}
  1023. function TRVUndoParaListInfo.RequiresFullReformat2(
  1024.   RVData: TRichViewRVData): Boolean;
  1025. begin
  1026.   Result := FR;
  1027. end;
  1028. {------------------------------------------------------------------------------}
  1029. procedure TRVUndoParaListInfo.SetItemsRange(var StartItem, EndItem: Integer;
  1030.                                             RVData: TRichViewRVData);
  1031. begin
  1032.   StartItem := StartItemNo;
  1033.   EndItem := StartItem+List.Count;
  1034. end;
  1035. {------------------------------------------------------------------------------}
  1036. procedure TRVUndoParaListInfo.Undo(RVData: TRichViewRVData);
  1037. begin
  1038.   TRVEditRVData(RVData).Do_ParaList(StartItemNo, List, FR);
  1039. end;
  1040. {============================== TRVUndoParaInfo ===============================}
  1041. function TRVUndoParaInfo.RequiresFullReformat2(
  1042.   RVData: TRichViewRVData): Boolean;
  1043. begin
  1044.   Result := FR;
  1045. end;
  1046. {------------------------------------------------------------------------------}
  1047. procedure TRVUndoParaInfo.SetItemsRange(var StartItem, EndItem: Integer;
  1048.                                         RVData: TRichViewRVData);
  1049. begin
  1050.   StartItem := ItemNo;
  1051.   EndItem := StartItem+Count;
  1052. end;
  1053. {------------------------------------------------------------------------------}
  1054. procedure TRVUndoParaInfo.Undo(RVData: TRichViewRVData);
  1055. begin
  1056.   TRVEditRVData(RVData).Do_Para(ItemNo, ItemNo+Count-1, ParaNo, FR);
  1057. end;
  1058. {============================ TRVUndoTypingInfo ===============================}
  1059. function TRVUndoTypingInfo.RequiresFullReformat2(
  1060.   RVData: TRichViewRVData): Boolean;
  1061. begin
  1062.   Result := NFR2(ItemNo, OldWidth, RVData);
  1063. end;
  1064. {------------------------------------------------------------------------------}
  1065. procedure TRVUndoTypingInfo.Undo(RVData: TRichViewRVData);
  1066. var s: String;
  1067.     c: String;
  1068.     idx: Integer;
  1069. begin
  1070.   OldWidth := RVData.CalculateMinItemWidthPlusEx(ItemNo);
  1071.   s := RVData.Items[ItemNo];
  1072.   {$IFNDEF RVDONOTUSEUNICODE}
  1073.   if Unicode then begin
  1074.     RVCheckUni(System.Length(s));
  1075.     idx := (Index+Length-2)*2+1;
  1076.     c := s[idx]+s[idx+1];
  1077.     Delete(s, idx, 2);
  1078.     end
  1079.   else
  1080.   {$ENDIF}
  1081.   begin
  1082.     idx := Index+Length-1;
  1083.     c := s[idx];
  1084.     Delete(s, idx, 1);
  1085.   end;
  1086.   dec(Length);
  1087.   RVData.Items[ItemNo] := s;
  1088.   TRVEditRVData(RVData).RedoList.AddUntyping(c, ItemNo, Index+Length+1);
  1089. end;
  1090. {=========================== TRVRedoTypingInfo ================================}
  1091. function TRVRedoTypingInfo.RequiresFullReformat2(
  1092.   RVData: TRichViewRVData): Boolean;
  1093. begin
  1094.   Result := NFR2(ItemNo, OldWidth, RVData);
  1095. end;
  1096. {------------------------------------------------------------------------------}
  1097. procedure TRVRedoTypingInfo.Undo(RVData: TRichViewRVData);
  1098. var str: String;
  1099.     l: Integer;
  1100. begin
  1101.   OldWidth := RVData.CalculateMinItemWidthPlusEx(ItemNo);
  1102.   str := RVData.Items[ItemNo];
  1103.   {$IFNDEF RVDONOTUSEUNICODE}
  1104.   if Unicode then begin
  1105.     RVCheckUni(Length(s));
  1106.     RVCheckUni(Length(str));
  1107.     l := Length(s);
  1108.     Insert(s[l-1]+s[l], str, (Index-1)*2-l+1);
  1109.     s := Copy(s,1,l-2);
  1110.     l := l div 2;
  1111.     end
  1112.   else
  1113.   {$ENDIF}
  1114.   begin
  1115.     l := Length(s);
  1116.     Insert(s[l], str, Index-l);
  1117.     s := Copy(s,1,l-1);
  1118.   end;
  1119.   RVData.Items[ItemNo] := str;
  1120.   TRVEditRVData(RVData).UndoList.AddTyping(ItemNo, Index-l, Unicode);
  1121. end;
  1122. {============================= TRVUndoTagInfo =================================}
  1123. destructor TRVUndoTagInfo.Destroy;
  1124. begin
  1125.   if TagsArePChars then
  1126.     StrDispose(PChar(WasTag));
  1127.   inherited Destroy;
  1128. end;
  1129. {------------------------------------------------------------------------------}
  1130. function TRVUndoTagInfo.RequiresFormat: Boolean;
  1131. begin
  1132.   Result := False;
  1133. end;
  1134. {------------------------------------------------------------------------------}
  1135. procedure TRVUndoTagInfo.Undo(RVData: TRichViewRVData);
  1136. begin
  1137.   TRVEditRVData(RVData).Do_Tag(ItemNo, WasTag, False);
  1138. end;
  1139. {============================ TRVUndoStyleNoInfo ==============================}
  1140. function TRVUndoStyleNoInfo.RequiresFullReformat2(RVData: TRichViewRVData): Boolean;
  1141. begin
  1142.   Result := NFR2(ItemNo, OldWidth, RVData);
  1143. end;
  1144. {------------------------------------------------------------------------------}
  1145. procedure TRVUndoStyleNoInfo.Undo(RVData: TRichViewRVData);
  1146. begin
  1147.   OldWidth := RVData.CalculateMinItemWidthPlusEx(ItemNo);
  1148.   TRVEditRVData(RVData).Do_StyleNo(ItemNo, WasStyleNo);
  1149. end;
  1150. {==================== TRVUndoAssociatedTextStyleNoInfo ========================}
  1151. procedure TRVUndoAssociatedTextStyleNoInfo.Undo(RVData: TRichViewRVData);
  1152. begin
  1153.   OldWidth := RVData.CalculateMinItemWidthPlusEx(ItemNo);
  1154.   TRVEditRVData(RVData).Do_AssociatedTextStyleNo(ItemNo, WasStyleNo);
  1155. end;
  1156. {============================== TRVUndoAddCPInfo ==============================}
  1157. procedure TRVUndoAddCPInfo.Undo(RVData: TRichViewRVData);
  1158. begin
  1159.   TRVEditRVData(RVData).Do_DeleteCP(ItemNo);
  1160. end;
  1161. {============================= TRVUndoDeleteCPInfo ============================}
  1162. destructor TRVUndoDeleteCPInfo.Destroy;
  1163. begin
  1164.   if Checkpoint<>nil then begin
  1165.     if TagsArePChars then
  1166.       StrDispose(PChar(Checkpoint.Tag));
  1167.     Checkpoint.Tag := 0;
  1168.     Checkpoint.Free;
  1169.   end;
  1170.   inherited Destroy;
  1171. end;
  1172. {------------------------------------------------------------------------------}
  1173. procedure TRVUndoDeleteCPInfo.Undo(RVData: TRichViewRVData);
  1174. begin
  1175.   TRVEditRVData(RVData).Do_AddCP(ItemNo, Checkpoint);
  1176.   Checkpoint := nil;
  1177. end;
  1178. {============================ TRVUndoModifyItemInfo ===========================}
  1179. function TRVUndoModifyItemInfo.RequiresFullReformat1(RVData: TRichViewRVData): Boolean;
  1180. var Item1: TCustomRVItemInfo;
  1181.     w1,w2: Integer;
  1182. begin
  1183.   Item1 := TCustomRVItemInfo(RVData.Items.Objects[ItemNo]);
  1184.   w2 := RVData.CalculateMinItemWidthPlusEx(ItemNo);
  1185.   w1 := w2-Item1.GetMinWidth(nil,nil,RVData)+Item.GetMinWidth(nil,nil,RVData);
  1186.   Result := (w1<>w2) and
  1187.             ((w1>RVData.DocumentWidth) or (w2>=RVData.DocumentWidth));
  1188. end;
  1189. {------------------------------------------------------------------------------}
  1190. procedure TRVUndoModifyItemInfo.Undo(RVData: TRichViewRVData);
  1191. begin
  1192.   TRVEditRVData(RVData).Do_ModifyItem(ItemNo, s, Item);
  1193.   Item := nil;
  1194. end;
  1195. {========================== TRVUndoChangeTextInfo =============================}
  1196. function TRVUndoChangeTextInfo.RequiresFullReformat2(RVData: TRichViewRVData): Boolean;
  1197. begin
  1198.   Result := NFR2(ItemNo, OldWidth, RVData);
  1199. end;
  1200. {------------------------------------------------------------------------------}
  1201. procedure TRVUndoChangeTextInfo.Undo(RVData: TRichViewRVData);
  1202. begin
  1203.   OldWidth := RVData.CalculateMinItemWidthPlusEx(ItemNo);
  1204.   TRVEditRVData(RVData).Do_ChangeText(ItemNo, s);
  1205. end;
  1206. {===================== TRVUndoChangeVAlignInfo ================================}
  1207. procedure TRVUndoChangeVAlignInfo.Undo(RVData: TRichViewRVData);
  1208. begin
  1209.    TRVEditRVData(RVData).Do_ChangeVAlign(ItemNo, VAlign);
  1210. end;
  1211. {============================ TRVUndoResizeInfo ===============================}
  1212. function TRVUndoResizeInfo.RequiresFullReformat2(
  1213.   RVData: TRichViewRVData): Boolean;
  1214. begin
  1215.   Result := NFR2(ItemNo, OldWidth, RVData);
  1216. end;
  1217. {------------------------------------------------------------------------------}
  1218. procedure TRVUndoResizeInfo.Undo(RVData: TRichViewRVData);
  1219. begin
  1220.   OldWidth := RVData.CalculateMinItemWidthPlusEx(ItemNo);
  1221.   TRVEditRVData(RVData).Do_Resize(ItemNo, Width, Height, False);
  1222. end;
  1223. {======================= TRVUndoModifyItemProps ===============================}
  1224. function TRVUndoModifyItemProps.GetOppositeClass: TRVUndoInfoClass;
  1225. begin
  1226.   Result := TRVUndoInfoClass(ClassType);
  1227. end;
  1228. {------------------------------------------------------------------------------}
  1229. procedure TRVUndoModifyItemProps.SetOppositeUndoInfoProps(UndoInfo: TRVUndoModifyItemProps);
  1230. begin
  1231.   // empty
  1232. end;
  1233. {------------------------------------------------------------------------------}
  1234. function TRVUndoModifyItemProps.RequiresFormat: Boolean;
  1235. begin
  1236.   Result := AffectSize;
  1237. end;
  1238. {------------------------------------------------------------------------------}
  1239. function TRVUndoModifyItemProps.RequiresFullReformat1(
  1240.   RVData: TRichViewRVData): Boolean;
  1241. begin
  1242.   Result := AffectSize and AffectWidth;
  1243.   if not Result then
  1244.     exit;
  1245.   OldW := RVData.CalculateMinItemWidthPlusEx(ItemNo);
  1246.   Result := OldW >= RVData.DocumentWidth;
  1247. end;
  1248. {------------------------------------------------------------------------------}
  1249. function TRVUndoModifyItemProps.RequiresFullReformat2(
  1250.   RVData: TRichViewRVData): Boolean;
  1251. var NewW: Integer;
  1252. begin
  1253.   Result := AffectSize and AffectWidth;
  1254.   if not Result then
  1255.     exit;
  1256.   NewW := RVData.CalculateMinItemWidthPlusEx(ItemNo);
  1257.   Result :=  (NewW<>OldW) and (NewW>RVData.DocumentWidth);
  1258. end;
  1259. {========================== TRVUndoModifyItemIntProperty ======================}
  1260. procedure TRVUndoModifyItemIntProperty.Undo(RVData: TRichViewRVData);
  1261. begin
  1262.   SetOppositeUndoInfoProps(TRVEditRVData(RVData).Do_ModifyItemIntProperty(ItemNo, SubObject, PropertyName, Value,
  1263.      AffectSize, AffectWidth,GetOppositeClass));
  1264. end;
  1265. {============================ TRVUndoModifyItemIntProperties ==================}
  1266. constructor TRVUndoModifyItemIntProperties.Create;
  1267. begin
  1268.   inherited Create;
  1269.   PropList := TStringList.Create;
  1270. end;
  1271. {------------------------------------------------------------------------------}
  1272. destructor TRVUndoModifyItemIntProperties.Destroy;
  1273. begin
  1274.   PropList.Free;
  1275.   inherited Destroy;
  1276. end;
  1277. {------------------------------------------------------------------------------}
  1278. procedure TRVUndoModifyItemIntProperties.Undo(RVData: TRichViewRVData);
  1279. begin
  1280.   SetOppositeUndoInfoProps(TRVEditRVData(RVData).Do_ModifyItemIntProperties(ItemNo, SubObject, PropList,
  1281.       AffectSize, AffectWidth, GetOppositeClass));
  1282. end;
  1283. {================================ TRVUndoModifyItemTerminator =================}
  1284. constructor TRVUndoModifyItemTerminator.Create;
  1285. begin
  1286.   inherited Create;
  1287.   AffectWidth := True;
  1288.   AffectSize := True;
  1289.   Action     := rvuModifyItem;
  1290. end;
  1291. {------------------------------------------------------------------------------}
  1292. procedure TRVUndoModifyItemTerminator.Undo(RVData: TRichViewRVData);
  1293. begin
  1294.   TRVEditRVData(RVData).Do_ItemModifyTerminator(ItemNo, not Opening);
  1295. end;
  1296. {============================== TRVCompositeUndo ==============================}
  1297. destructor TRVCompositeUndo.Destroy;
  1298. begin
  1299.   UndoList.Free;
  1300.   inherited Destroy;
  1301. end;
  1302. {------------------------------------------------------------------------------}
  1303. function TRVCompositeUndo.RequiresFormat: Boolean;
  1304. begin
  1305.   Result := False;
  1306. end;
  1307. {------------------------------------------------------------------------------}
  1308. procedure TRVCompositeUndo.SetItemsRange(var StartItem, EndItem: Integer;
  1309.   RVData: TRichViewRVData);
  1310. begin
  1311.   StartItem := ItemNo;
  1312.   EndItem   := ItemNo;
  1313. end;
  1314. {------------------------------------------------------------------------------}
  1315. procedure TRVCompositeUndo.Undo(RVData: TRichViewRVData);
  1316. begin
  1317.   UndoList.Undo(RVData);
  1318. end;
  1319. {===================== TRVUndoReplaceItemInfo =================================}
  1320. function TRVUndoReplaceItemInfo.RequiresFormat: Boolean;
  1321. begin
  1322.   Result := False;
  1323. end;
  1324. {------------------------------------------------------------------------------}
  1325. procedure TRVUndoReplaceItemInfo.Undo(RVData: TRichViewRVData);
  1326. begin
  1327.   TRVEditRVData(RVData).Do_ReplaceItem(ItemNo, item);
  1328.   item := nil;
  1329. end;
  1330. {============================= TRVUndoReformateRange ==========================}
  1331. function TRVUndoReformateRange.RequiresSuperFormat: Boolean;
  1332. begin
  1333.   Result := SuperReformat;
  1334. end;
  1335. {------------------------------------------------------------------------------}
  1336. procedure TRVUndoReformateRange.Undo(RVData: TRichViewRVData);
  1337. begin
  1338.   TRVEditRVData(RVData).Do_ReformateRange(ItemNo, LastAffectedItemNo, SuperReformat);
  1339. end;
  1340. end.