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

RichEdit

开发平台:

Delphi

  1. {*******************************************************}
  2. {                                                       }
  3. {       RichView                                        }
  4. {       TRVSerializer - class converting RichView       }
  5. {       coordinates (RVData, ItemNo) to linear          }
  6. {       coordinates (AbsoluteItemNo) and vice versa.    }
  7. {       Used in parsers for spell-checkers.             }
  8. {       See RVLinear.pas for converting                 }
  9. {       (RVData, ItemNo, Offset) to AbsoluteItemNo'.    }
  10. {                                                       }
  11. {       Copyright (c) Sergey Tkachenko                  }
  12. {       svt@trichview.com                               }
  13. {       http://www.trichview.com                        }
  14. {                                                       }
  15. {*******************************************************}
  16. unit RVSer;
  17. interface
  18. uses SysUtils, RVClasses,
  19.      RichView, CRVData, CRVFData, RVERVData, RVItem, RVEdit, RVRVData;
  20. type
  21.   TRVSerEntry = class
  22.     public
  23.       AbsoluteItemNo: Integer;
  24.       RVData: TCustomRVFormattedData;
  25.       ParentEntryNo, PrevEntryNo: Integer;
  26.       ParentItemNo: Integer;
  27.       ParentSubPos: TRVStoreSubRVData;
  28.       FirstItemNo,LastItemNo : Integer;
  29.       constructor Create(ARVData: TCustomRVFormattedData; AAbsoluteItemNo: Integer);
  30.       destructor Destroy; override;
  31.   end;
  32.   TRVSerializer = class (TRVList)
  33.     private
  34.       RootRVData: TCustomRVFormattedData;
  35.       CurEntryNo: Integer;
  36.       FBeyondTheEnd: Boolean;
  37.     public
  38.       constructor Create(RVData: TCustomRVFormattedData);
  39.       function Expand: Boolean;
  40.       function Shrink: Boolean;
  41.       function ExpandToRV(RVData: TCustomRVFormattedData; ItemNo: Integer): Boolean;
  42.       function ExpandTo(AbsoluteItemNo: Integer): Boolean;
  43.       function RollBackTo(AbsoluteItemNo: Integer): Boolean;
  44.       function RollBackToRV(RVData: TCustomRVFormattedData; ItemNo: Integer): Boolean;
  45.       procedure GoToCaret;
  46.       procedure GoToSelEnd(var AbsItemNo1, Offs1, AbsItemNo2, Offs2: Integer);
  47.       procedure AbsoluteToRV(AbsoluteItemNo: Integer;
  48.                              var RVData: TCustomRVFormattedData;
  49.                              var ItemNo: Integer);
  50.       procedure RVToAbsolute(RVData: TCustomRVFormattedData;
  51.                              ItemNo: Integer;
  52.                              var AbsoluteItemNo: Integer);
  53.       procedure GoToPosRV(RVData: TCustomRVFormattedData;
  54.                              ItemNo: Integer);
  55.       procedure GoToPos(AbsoluteItemNo: Integer);
  56.       procedure CurPosToRV(var RVData: TCustomRVFormattedData;
  57.                            var ItemNo: Integer);
  58.       function CurPos: Integer;
  59.       procedure EditAtCurPos;
  60.       property BeyondTheEnd: Boolean read FBeyondTheEnd;
  61.   end;
  62. implementation
  63. {============================== TRVSerEntry ===================================}
  64. constructor TRVSerEntry.Create(ARVData: TCustomRVFormattedData; AAbsoluteItemNo: Integer);
  65. begin
  66.   inherited Create;
  67.   RVData        := ARVData;
  68.   AbsoluteItemNo := AAbsoluteItemNo;
  69.   ParentEntryNo := -1;
  70.   ParentItemNo  := -1;
  71.   PrevEntryNo   := -1;
  72.   LastItemNo    := -1;
  73. end;
  74. {------------------------------------------------------------------------------}
  75. destructor TRVSerEntry.Destroy;
  76. begin
  77.   if PrevEntryNo>=0 then
  78.     ParentSubPos.Free;
  79.   inherited;
  80. end;
  81. {============================== TRVSerializer =================================}
  82. constructor TRVSerializer.Create(RVData: TCustomRVFormattedData);
  83. var Entry: TRVSerEntry;
  84. begin
  85.   inherited Create;
  86.   RootRVData := RVData;
  87.   Entry := TRVSerEntry.Create(RootRVData,0);
  88.   Add(Entry);
  89.   CurEntryNo := 0;
  90. end;
  91. {------------------------------------------------------------------------------}
  92. function TRVSerializer.Expand: Boolean;
  93. var NewEntry,ParentEntry,Entry, LastEntry: TRVSerEntry;
  94.     RVData: TCustomRVFormattedData;
  95.     SubPos: TRVStoreSubRVData;
  96. begin
  97.   Result := True;
  98.   Entry := TRVSerEntry(Items[CurEntryNo]);
  99.   if Entry.LastItemNo<Entry.RVData.GetRVData.Items.Count-1 then begin
  100.     inc(Entry.LastItemNo);
  101.     RVData := TCustomRVFormattedData(Entry.RVData.GetRVData.GetItem(Entry.LastItemNo).GetSubRVData(SubPos, rvdFirst));
  102.     if RVData<>nil then begin
  103.       // if new item is a table, adding first cell
  104.       LastEntry := TRVSerEntry(Items[Count-1]);
  105.       NewEntry := TRVSerEntry.Create(RVData, LastEntry.AbsoluteItemNo+LastEntry.LastItemNo-LastEntry.FirstItemNo+1);
  106.       NewEntry.ParentEntryNo := CurEntryNo;
  107.       NewEntry.ParentItemNo  := Entry.LastItemNo;
  108.       NewEntry.ParentSubPos := SubPos;
  109.       Add(NewEntry);
  110.       CurEntryNo := Count-1;
  111.       Result := Expand;
  112.     end;
  113.     end
  114.   else begin
  115.     if Entry.ParentSubPos<>nil then begin
  116.       // if last entry is a cell, trying to add next cell
  117.       SubPos := Entry.ParentSubPos.Duplicate;
  118.       ParentEntry := TRVSerEntry(Items[Entry.ParentEntryNo]);
  119.       RVData := TCustomRVFormattedData(ParentEntry.RVData.GetRVData.GetItem(Entry.ParentItemNo).GetSubRVData(SubPos, rvdNext));
  120.       if RVData<>nil then begin
  121.         // adding a new cell
  122.         LastEntry := TRVSerEntry(Items[Count-1]);
  123.         NewEntry := TRVSerEntry.Create(RVData, LastEntry.AbsoluteItemNo+LastEntry.LastItemNo-LastEntry.FirstItemNo+1);
  124.         NewEntry.ParentEntryNo := Entry.ParentEntryNo;
  125.         NewEntry.ParentItemNo  := Entry.ParentItemNo;
  126.         NewEntry.ParentSubPos  := SubPos;
  127.         Add(NewEntry);
  128.         CurEntryNo := Count-1;
  129.         Result := Expand;
  130.         end
  131.       else begin
  132.         SubPos.Free;
  133.         CurEntryNo := Entry.ParentEntryNo;
  134.         Entry := TRVSerEntry(Items[CurEntryNo]);
  135.         if Entry.LastItemNo<Entry.RVData.GetRVData.Items.Count-1 then begin
  136.           // resuming parent entry
  137.           LastEntry := TRVSerEntry(Items[Count-1]);
  138.           NewEntry := TRVSerEntry.Create(Entry.RVData, LastEntry.AbsoluteItemNo+LastEntry.LastItemNo-LastEntry.FirstItemNo+1);
  139.           NewEntry.PrevEntryNo := CurEntryNo;
  140.           NewEntry.ParentEntryNo := Entry.ParentEntryNo;
  141.           NewEntry.ParentItemNo := Entry.ParentItemNo;
  142.           if Entry.ParentSubPos=nil then
  143.             NewEntry.ParentSubPos := nil
  144.           else
  145.             NewEntry.ParentSubPos := Entry.ParentSubPos.Duplicate;
  146.           NewEntry.FirstItemNo := Entry.LastItemNo+1;
  147.           NewEntry.LastItemNo := Entry.LastItemNo;
  148.           Add(NewEntry);
  149.           CurEntryNo := Count-1;
  150.           Result := Expand;
  151.           end
  152.         else begin
  153.           Result := Expand;
  154.         end;
  155.       end;
  156.       end
  157.     else begin
  158.       Result := False; // that's all, folks
  159.       FBeyondTheEnd := True;
  160.     end;
  161.   end;
  162. end;
  163. {------------------------------------------------------------------------------}
  164. function TRVSerializer.Shrink: Boolean;
  165. var Entry: TRVSerEntry;
  166. begin
  167.   if FBeyondTheEnd then begin
  168.     FBeyondTheEnd := False;
  169.     Result := True;
  170.     exit;
  171.   end;
  172.   Result := True;
  173.   if CurEntryNo<>Count-1 then
  174.     raise ERichViewError.Create('Internal error 1');
  175.   Entry := TRVSerEntry(Items[CurEntryNo]);
  176.   dec(Entry.LastItemNo);
  177.   if Entry.LastItemNo<Entry.FirstItemNo then begin
  178.     if CurEntryNo=0 then begin
  179.       Entry.LastItemNo := -1;
  180.       Result := False;
  181.       exit;
  182.     end;
  183.     Delete(CurEntryNo);
  184.     dec(CurEntryNo);
  185.   end;
  186. end;
  187. {------------------------------------------------------------------------------}
  188. function TRVSerializer.ExpandToRV(RVData: TCustomRVFormattedData;
  189.   ItemNo: Integer): Boolean;
  190. var Entry: TRVSerEntry;
  191.     Index: Integer;
  192. begin
  193.   FBeyondTheEnd := False;
  194.   repeat
  195.     Index := Count-1;
  196.     while True do begin
  197.       Entry := TRVSerEntry(Items[Index]);
  198.       if (Entry.RVData=RVData) and (ItemNo<=Entry.LastItemNo) then begin
  199.         CurEntryNo := Index;
  200.         Result := True;
  201.         exit;
  202.       end;
  203.       if Entry.ParentEntryNo<0 then
  204.         break;
  205.       Index := Entry.ParentEntryNo;
  206.     end;
  207.   until not Expand;
  208.   Result := False;
  209. end;
  210. {------------------------------------------------------------------------------}
  211. function TRVSerializer.ExpandTo(AbsoluteItemNo: Integer): Boolean;
  212. begin
  213.   FBeyondTheEnd := False;
  214.   repeat
  215.     if AbsoluteItemNo=CurPos then begin
  216.       Result := True;
  217.       exit;
  218.     end;
  219.   until not Expand;
  220.   Result := False;
  221. end;
  222. {------------------------------------------------------------------------------}
  223. procedure TRVSerializer.GoToCaret;
  224. var RVData: TCustomRVFormattedData;
  225.     ItemNo: Integer;
  226. begin
  227.   RVData := RootRVData;
  228.   while RVData.GetChosenRVData <>nil do
  229.     RVData := TCustomRVFormattedData(RVData.GetChosenRVData);
  230.   ItemNo := (RVData as TRVEditRVData).GetCurItemNo;
  231.   RVData := TCustomRVFormattedData(RVData.GetSourceRVData);
  232.   GoToPosRV(RVData, ItemNo);
  233. end;
  234. {------------------------------------------------------------------------------}
  235. procedure TRVSerializer.GoToSelEnd(var AbsItemNo1, Offs1, AbsItemNo2, Offs2: Integer);
  236. var RVData: TCustomRVFormattedData;
  237.     ItemNo1,ItemNo2: Integer;
  238. begin
  239.   RVData := RootRVData;
  240.   while RVData.GetChosenRVData <>nil do
  241.     RVData := TCustomRVFormattedData(RVData.GetChosenRVData);
  242.   RVData.GetSelectionBoundsEx(ItemNo1,Offs1,ItemNo2,Offs2,True);
  243.   if RVData.GetItemStyle(ItemNo1)>=0 then
  244.     dec(Offs1);
  245.   if RVData.GetItemStyle(ItemNo2)>=0 then
  246.     dec(Offs2);
  247.   RVData := TCustomRVFormattedData(RVData.GetSourceRVData);
  248.   GoToPosRV(RVData, ItemNo2);
  249.   RVToAbsolute(RVData, ItemNo1, AbsItemNo1);
  250.   RVToAbsolute(RVData, ItemNo2, AbsItemNo2);
  251. end;
  252. {------------------------------------------------------------------------------}
  253. function TRVSerializer.RollBackTo(AbsoluteItemNo: Integer): Boolean;
  254. var i,j: Integer;
  255.     Entry: TRVSerEntry;
  256. begin
  257.   if AbsoluteItemNo=-1 then begin
  258.     for j := Count-1 downto 1 do
  259.       Delete(j);
  260.     Entry := TRVSerEntry(Items[0]);
  261.     Entry.LastItemNo := -1;
  262.     CurEntryNo := 0;
  263.     Result := False;
  264.     exit;
  265.   end;
  266.   Result := True;
  267.   for i := Count-1 downto 0 do begin
  268.     Entry := TRVSerEntry(Items[i]);
  269.     if (Count=1) and (Entry.LastItemNo<0) then begin
  270.       Result := False;
  271.       exit;
  272.     end;
  273.     if (AbsoluteItemNo>=Entry.AbsoluteItemNo) then begin
  274.       if (AbsoluteItemNo>Entry.AbsoluteItemNo+(Entry.LastItemNo-Entry.FirstItemNo)) then begin
  275.         Result := False;
  276.         exit;
  277.       end;
  278.       for j := Count-1 downto i+1 do
  279.         Delete(j);
  280.       Entry.LastItemNo := Entry.FirstItemNo+AbsoluteItemNo-Entry.AbsoluteItemNo;
  281.       CurEntryNo := i;
  282.       dec(Entry.LastItemNo);
  283.       Expand;
  284.       exit;
  285.     end;
  286.   end;
  287.   Result := False;
  288. end;
  289. {------------------------------------------------------------------------------}
  290. function TRVSerializer.RollBackToRV(RVData: TCustomRVFormattedData; ItemNo: Integer): Boolean;
  291. var i,j: Integer;
  292.     Entry: TRVSerEntry;
  293. begin
  294.   Result := True;
  295.   for i := Count-1 downto 0 do begin
  296.     Entry := TRVSerEntry(Items[i]);
  297.     if (Count=1) and (Entry.LastItemNo<0) then begin
  298.       Result := False;
  299.       exit;
  300.     end;
  301.     if (RVData=Entry.RVData) and
  302.       (ItemNo>=Entry.FirstItemNo) and (ItemNo<=Entry.LastItemNo) then begin
  303.       for j := Count-1 downto i+1 do
  304.         Delete(j);
  305.       Entry.LastItemNo := ItemNo;
  306.       CurEntryNo := i;
  307.       exit;
  308.     end;
  309.   end;
  310.   Result := False;
  311. end;
  312. {------------------------------------------------------------------------------}
  313. procedure TRVSerializer.AbsoluteToRV(AbsoluteItemNo: Integer;
  314.   var RVData: TCustomRVFormattedData; var ItemNo: Integer);
  315. var i: Integer;
  316.     Entry: TRVSerEntry;
  317. begin
  318.   for i := Count-1 downto 0 do begin
  319.     Entry := TRVSerEntry(Items[i]);
  320.     if (AbsoluteItemNo>=Entry.AbsoluteItemNo) then begin
  321.       if (AbsoluteItemNo>Entry.AbsoluteItemNo+(Entry.LastItemNo-Entry.FirstItemNo)) then
  322.         raise ERichViewError.Create('Internal error 2');
  323.       RVData := Entry.RVData;
  324.       ItemNo := AbsoluteItemNo-Entry.AbsoluteItemNo+Entry.FirstItemNo;
  325.       exit;
  326.     end;
  327.   end;
  328.   raise ERichViewError.Create('Internal error 3');
  329. end;
  330. {------------------------------------------------------------------------------}
  331. procedure TRVSerializer.RVToAbsolute(RVData: TCustomRVFormattedData;
  332.   ItemNo: Integer; var AbsoluteItemNo: Integer);
  333. var i: Integer;
  334.     Entry: TRVSerEntry;
  335. begin
  336.   AbsoluteItemNo := -1;
  337.   for i := Count-1 downto 0 do begin
  338.     Entry := TRVSerEntry(Items[i]);
  339.     if (Count=1) and (Entry.LastItemNo<0) then begin
  340.       exit;
  341.     end;
  342.     if (RVData=Entry.RVData) and
  343.       (ItemNo>=Entry.FirstItemNo) then begin
  344.       AbsoluteItemNo := Entry.AbsoluteItemNo-Entry.FirstItemNo+ItemNo;
  345.       exit;
  346.     end;
  347.   end;
  348. end;
  349. {------------------------------------------------------------------------------}
  350. procedure TRVSerializer.GoToPosRV(RVData: TCustomRVFormattedData;
  351.                                ItemNo: Integer);
  352. begin
  353.   if not RollBackToRV(RVData, ItemNo) then
  354.     ExpandToRV(RVData, ItemNo);
  355. end;
  356. {------------------------------------------------------------------------------}
  357. procedure TRVSerializer.GoToPos(AbsoluteItemNo: Integer);
  358. begin
  359.   if not RollBackTo(AbsoluteItemNo) then
  360.     ExpandTo(AbsoluteItemNo);
  361. end;
  362. {------------------------------------------------------------------------------}
  363. procedure TRVSerializer.CurPosToRV(var RVData: TCustomRVFormattedData;
  364.   var ItemNo: Integer);
  365. var Entry: TRVSerEntry;
  366. begin
  367.   Entry := TRVSerEntry(Items[CurEntryNo]);
  368.   RVData := Entry.RVData;
  369.   ItemNo := Entry.LastItemNo;
  370. end;
  371. {------------------------------------------------------------------------------}
  372. function TRVSerializer.CurPos: Integer;
  373. var Entry: TRVSerEntry;
  374. begin
  375.   Entry := TRVSerEntry(Items[CurEntryNo]);
  376.   Result := Entry.AbsoluteItemNo+(Entry.LastItemNo-Entry.FirstItemNo);
  377. end;
  378. {------------------------------------------------------------------------------}
  379. procedure TRVSerializer.EditAtCurPos;
  380. var ParentEntry, Entry: TRVSerEntry;
  381. begin
  382.   Entry := TRVSerEntry(Items[CurEntryNo]);
  383.   if Entry.ParentItemNo=-1 then
  384.     exit;
  385.   ParentEntry := TRVSerEntry(Items[Entry.ParentEntryNo]);
  386.   ParentEntry.RVData.GetRVData.GetItem(Entry.ParentItemNo).ChooseSubRVData(Entry.ParentSubPos);
  387. end;
  388. end.