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

RichEdit

开发平台:

Delphi

  1.       if Result then
  2.         exit;
  3.     end;
  4.   end;
  5.   if Down then
  6.     SubPos := rvdFirst
  7.   else
  8.     SubPos := rvdLast;
  9.   SrchStart(Down, strt, offs);
  10.   if (strt>=Items.Count) or (strt<0) then exit;
  11.   if Items.Objects[strt]=item then begin
  12.     if Down then
  13.       inc(strt)
  14.     else
  15.       dec(strt);
  16.     if (strt>=Items.Count) or (strt<0) then exit;
  17.     end
  18.   else if GetItemStyle(strt)>=0 then begin
  19.     ItemOptions := GetItemOptions(strt);
  20.     if not Down then begin
  21.       s2 := RVU_Copy(Items[strt], 1, offs-1, ItemOptions);
  22.       offs := 1;
  23.       end
  24.     else
  25.       s2 := RVU_Copy(Items[strt],offs,RVU_Length(Items[strt],ItemOptions), ItemOptions);
  26.     {$IFNDEF RVDONOTUSEUNICODE}
  27.     if rvioUnicode in ItemOptions then
  28.       s2 := RVU_UnicodeToAnsi(GetDefaultCodePage, s2);
  29.     {$ENDIF}
  30.     if not MatchCase then
  31.       s2 := AnsiUpperCase(s2);
  32.     if not Down then
  33.       so := RevPos(s,s2)
  34.     else
  35.       so := FwdPos(s,s2);
  36.     if so<>0 then begin
  37.       Result := True;
  38.       len := Length(s);
  39.       UpdateUnicodePos(s2, s, ItemOptions, so, len);
  40.       SrchSelectIt(strt, offs+so-1, len, not Down);
  41.       exit;
  42.     end;
  43.     if Down then
  44.       inc(strt)
  45.     else
  46.       dec(strt);
  47.   end;
  48.   if not Down then
  49.     for i := strt downto 0 do begin
  50.       if GetItemStyle(i)>=0 then begin
  51.         {$IFNDEF RVDONOTUSEUNICODE}
  52.          if rvioUnicode in GetItemOptions(i) then
  53.            s2 := RVU_UnicodeToAnsi(GetDefaultCodePage, Items[i])
  54.          else
  55.         {$ENDIF}
  56.            s2 := Items[i];
  57.         if not MatchCase then
  58.           offs := RevPos(s,AnsiUpperCase(s2))
  59.         else
  60.           offs := RevPos(s, s2);
  61.         if offs<>0 then begin
  62.           Result := True;
  63.           len := Length(s);
  64.           UpdateUnicodePos(s2, s, GetItemOptions(i), offs, len);
  65.           SrchSelectIt(i, offs, len, not Down);
  66.           exit;
  67.         end;
  68.         end
  69.       else begin
  70.         item := TCustomRVItemInfo(Items.Objects[i]);
  71.         SubRVData := TCustomRVFormattedData(item.GetSubRVData(StoreSub, SubPos));
  72.         if SubRVData<>nil then begin
  73.           Result := SearchInItem(item, StoreSub, SubRVData);
  74.           if Result then
  75.            exit;
  76.         end;
  77.       end;
  78.     end
  79.   else
  80.     for i := strt to Items.Count-1 do
  81.       if GetItemStyle(i)>=0 then begin
  82.          {$IFNDEF RVDONOTUSEUNICODE}
  83.          if rvioUnicode in GetItemOptions(i) then
  84.            s2 := RVU_UnicodeToAnsi(GetDefaultCodePage, Items[i])
  85.          else
  86.         {$ENDIF}
  87.            s2 := Items[i];
  88.         if not MatchCase then
  89.           offs := FwdPos(s,AnsiUpperCase(s2))
  90.         else
  91.           offs := FwdPos(s, s2);
  92.         if offs<>0 then begin
  93.           Result := True;
  94.           len := Length(s);
  95.           UpdateUnicodePos(s2, s, GetItemOptions(i), offs, len);
  96.           SrchSelectIt(i, offs, len, not Down);
  97.           exit;
  98.         end;
  99.         end
  100.       else begin
  101.         item := GetItem(i);
  102.         SubRVData := TCustomRVFormattedData(item.GetSubRVData(StoreSub, SubPos));
  103.         if SubRVData<>nil then begin
  104.           Result := SearchInItem(item, StoreSub, SubRVData);
  105.           if Result then
  106.            exit;
  107.         end;
  108.       end;
  109. end;
  110. {------------------------------------------------------------------------------}
  111. procedure TCustomRVFormattedData.GetSelectionBounds(var StartItemNo, StartItemOffs,
  112.                                  EndItemNo, EndItemOffs: Integer;
  113.                                  Normalize: Boolean);
  114. begin
  115.   StoreSelBounds(StartItemNo, EndItemNo, StartItemOffs, EndItemOffs, Normalize);
  116. end;
  117. {------------------------------------------------------------------------------}
  118. procedure TCustomRVFormattedData.GetSelectionBoundsEx(var StartItemNo,
  119.   StartItemOffs, EndItemNo, EndItemOffs: Integer; Normalize: Boolean);
  120. begin
  121.   GetSelectionBounds(StartItemNo, StartItemOffs, EndItemNo, EndItemOffs, Normalize);
  122. end;
  123. {------------------------------------------------------------------------------}
  124. procedure TCustomRVFormattedData.AdjustSelection;
  125. begin
  126.   if (FSelStartNo<0) or (FSelEndNo<0) then
  127.     exit;
  128.   if FSelStartOffs<GetOffsBeforeDrawItem(FSelStartNo) then
  129.     FSelStartOffs := GetOffsBeforeDrawItem(FSelStartNo);
  130.   if FSelStartOffs>GetOffsAfterDrawItem(FSelStartNo) then
  131.     FSelStartOffs := GetOffsAfterDrawItem(FSelStartNo);
  132.   if FSelEndOffs<GetOffsBeforeDrawItem(FSelEndNo) then
  133.     FSelEndOffs := GetOffsBeforeDrawItem(FSelEndNo);
  134.   if FSelEndOffs>GetOffsAfterDrawItem(FSelEndNo) then
  135.     FSelEndOffs := GetOffsAfterDrawItem(FSelEndNo);
  136. end;
  137. {------------------------------------------------------------------------------}
  138. procedure TCustomRVFormattedData.DoSetSelectionBounds(StartItemNo, StartItemOffs,
  139.                                  EndItemNo, EndItemOffs: Integer);
  140. begin
  141.   DeselectPartiallySelectedItem(nil);
  142.   DestroyInplaceEditor;
  143.   {$IFNDEF RVDONOTUSELISTS}
  144.   if (StartItemNo>=0) and (EndItemNo>=0) then begin
  145.     if (StartItemNo+1<Items.Count) and (GetItemStyle(StartItemNo)=rvsListMarker) then begin
  146.       inc(StartItemNo);
  147.       StartItemOffs := GetOffsBeforeItem(StartItemNo);
  148.     end;
  149.     if (EndItemNo+1<Items.Count) and (GetItemStyle(EndItemNo)=rvsListMarker) then begin
  150.       inc(EndItemNo);
  151.       EndItemOffs := GetOffsBeforeItem(EndItemNo);
  152.     end;
  153.   end;
  154.   {$ENDIF}
  155.   RestoreSelBounds(StartItemNo, EndItemNo, StartItemOffs, EndItemOffs);
  156.   AdjustSelection;  
  157. //  if GetRVStyle.SelectionMode=rvsmParagraph then
  158. //    ExpandSelectionToParagraph(True);
  159.   DoOnSelection(True);
  160.   DoSelect;
  161. end;
  162. {------------------------------------------------------------------------------}
  163. procedure TCustomRVFormattedData.SetSelectionBounds(StartItemNo, StartItemOffs,
  164.                                  EndItemNo, EndItemOffs: Integer);
  165. begin
  166.   {$IFNDEF RVDONOTUSELIVESPELL}
  167.   LiveSpellingCheckCurrentItem;
  168.   {$ENDIF}
  169.   DoSetSelectionBounds(StartItemNo, StartItemOffs, EndItemNo, EndItemOffs);
  170. end;
  171. {------------------------------------------------------------------------------}
  172. procedure TCustomRVFormattedData.GetWordAt(X,Y: Integer;
  173.   var RVData: TCustomRVFormattedData; var ItemNo: Integer;
  174.   var Word: String);
  175. var StyleNo, Offs: Integer;
  176. begin
  177.   if not FindWordAt(Word, X,Y, StyleNo, ItemNo, Offs, RVData) then
  178.     ItemNo := -1;
  179. end;
  180. {------------------------------------------------------------------------------}
  181. function TCustomRVFormattedData.GetClientSelectionRect: TRect;
  182. var i: Integer;
  183.     StartNo, EndNo, StartOffs, EndOffs, x,y: Integer;
  184.     R: TRect;
  185. begin
  186.   // This is very rough function for returning selection rectangle
  187.   // It does not count offsets in text items.
  188.   {$IFNDEF RVDONOTUSEINPLACE}
  189.   if (GetChosenRVData<>nil) then begin
  190.     Result := TCustomRVFormattedData(GetChosenRVData).GetClientSelectionRect;
  191.     exit;
  192.   end;
  193.   {$ENDIF}
  194.   if SelectionExists(False, False) then begin
  195.     ResetSubCoords;
  196.     GetSelBounds(StartNo, EndNo, StartOffs, EndOffs, True);
  197.     Result := Rect(0,0,0,0);
  198.     for i:= StartNo to EndNo do begin
  199.       with DrawItems[i] do
  200.         R := Bounds(Left-GetZHOffs,Top-GetZVOffs, Width, Height);
  201.       UnionRect(Result, Result, R);
  202.     end;
  203.     R := Rect(0,0,GetWidth,GetHeight);
  204.     IntersectRect(Result, Result, R);
  205.     GetOrigin(x,y);
  206.     OffsetRect(Result, x,y);
  207.     end
  208.   else begin
  209.     GetOriginEx(x,y);
  210.     Result := Bounds(x,y,GetWidth,GetHeight);
  211.   end;
  212. end;
  213. {------------------------------------------------------------------------------}
  214. procedure TCustomRVFormattedData.OnTimerScroll;
  215. begin
  216.   //LastSelectionRect.Left := 1;
  217. end;
  218. {------------------------------------------------------------------------------}
  219. function TCustomRVFormattedData.GetSelectionRect:TRect;
  220. var P: TPoint;
  221. begin
  222.   {$IFNDEF RVDONOTUSEINPLACE}
  223.   if (GetInplaceEditor<>nil) and (GetInplaceEditor is TCustomRichView) then begin
  224.     Result := TCustomRichView(GetInplaceEditor).RVData.GetSelectionRect;
  225.     exit;
  226.   end;
  227.   {$ENDIF}
  228.   Result := GetClientSelectionRect;
  229.   P := Point(0,0);
  230.   P := ClientToScreen(P);
  231.   OffsetRect(Result, P.x, P.y);
  232. end;
  233. {------------------------------------------------------------------------------}
  234. procedure TCustomRVFormattedData.SelectWordAt(X,Y: Integer);
  235. var StyleNo, ItemNo, Offs: Integer;
  236.     Word: String;
  237.     RVData: TCustomRVFormattedData;
  238. begin
  239.   if not (rvoAllowSelection in Options) then exit;
  240.   if FindWordAt(Word, X, Y, StyleNo, ItemNo, Offs, RVData) then begin
  241.     if StyleNo>=0 then
  242.       RVData.SetSelectionBounds(ItemNo, Offs, ItemNo, Offs+RVU_Length(Word, GetItemOptions(ItemNo)))
  243.     else
  244.       RVData.SetSelectionBounds(ItemNo, 0, ItemNo, 1);
  245.     Invalidate;
  246.   end;
  247. end;
  248. {------------------------------------------------------------------------------}
  249. procedure TCustomRVFormattedData.GetCheckpointXY(CheckpointData: TCheckpointData;
  250.                                                  var X,Y: Integer);
  251. begin
  252.   if CheckpointData = nil then
  253.     raise ERichViewError.Create(errRVNil);
  254.   if CheckpointData = NotAddedCP then begin
  255.     X := 0;
  256.     Y := DocumentHeight;
  257.     end
  258.   else
  259.     with TRVCPInfo(CheckpointData) do begin
  260.       if (ItemInfo=nil) or (ItemInfo.DrawItemNo=-1) then
  261.         raise ERichViewError.Create(errRVNotFormatted);
  262.       X := DrawItems[ItemInfo.DrawItemNo].Left;
  263.       Y := DrawItems[ItemInfo.DrawItemNo].Top;
  264.     end;
  265. end;
  266. {------------------------------------------------------------------------------}
  267. function TCustomRVFormattedData.GetCheckpointYEx(CheckpointData: TCheckpointData): Integer;
  268. begin
  269.   if CheckpointData = nil then
  270.     raise ERichViewError.Create(errRVNil);
  271.   if CheckpointData = NotAddedCP then
  272.     Result := DocumentHeight
  273.   else
  274.     with TRVCPInfo(CheckpointData) do begin
  275.       if (ItemInfo=nil) or (ItemInfo.DrawItemNo=-1) then
  276.         raise ERichViewError.Create(errRVNotFormatted);
  277.       Result := DrawItems[ItemInfo.DrawItemNo].Top;
  278.     end;
  279. end;
  280. {------------------------------------------------------------------------------}
  281. function TCustomRVFormattedData.GetJumpPointY(id: Integer): Integer;
  282. var i: Integer;
  283. begin
  284.   {$IFNDEF RVDONOTUSEINPLACE}
  285.   if (GetChosenRVData<>nil) then begin
  286.     Result := TCustomRVFormattedData(GetChosenRVData).GetJumpPointY(id);
  287.     if Result>0 then
  288.       exit;
  289.   end;
  290.   {$ENDIF}
  291.   Result := 0;
  292.   for i := 0 to Jumps.Count-1 do
  293.    if  TRVJumpInfo(Jumps[i]).id = id-FirstJumpNo then begin
  294.      Result := TRVJumpInfo(Jumps[i]).t;
  295.      exit;
  296.    end;
  297. end;
  298. {------------------------------------------------------------------------------}
  299. function TCustomRVFormattedData.GetJumpPointItemNo(id: Integer): Integer;
  300. var i: Integer;
  301. begin
  302.   {$IFNDEF RVDONOTUSEINPLACE}
  303.   if (GetChosenRVData<>nil) then begin
  304.     Result := TCustomRVFormattedData(GetChosenRVData).GetJumpPointItemNo(id);
  305.     if Result>=0 then
  306.       exit;
  307.   end;
  308.   {$ENDIF}
  309.   Result := -1;
  310.   for i :=0 to Jumps.Count-1 do
  311.     if TRVJumpInfo(Jumps[i]).id = id-FirstJumpNo then begin
  312.       Result := TRVJumpInfo(Jumps[i]).RVData.DrawItems[TRVJumpInfo(Jumps[i]).DrawItemNo].ItemNo;
  313.       exit;
  314.     end;
  315. end;
  316. {------------------------------------------------------------------------------}
  317. procedure TCustomRVFormattedData.GetJumpPointLocation(id: Integer;
  318.   var RVData: TCustomRVFormattedData; var ItemNo: Integer);
  319. var i: Integer;
  320. begin
  321.   {$IFNDEF RVDONOTUSEINPLACE}
  322.   if (GetChosenRVData<>nil) then begin
  323.     TCustomRVFormattedData(GetChosenRVData).GetJumpPointLocation(id,RVData,ItemNo);
  324.     if ItemNo>=0 then
  325.       exit;
  326.   end;
  327.   {$ENDIF}
  328.   ItemNo := -1;
  329.   RVData := nil;
  330.   for i :=0 to Jumps.Count-1 do
  331.     if TRVJumpInfo(Jumps[i]).id = id-FirstJumpNo then begin
  332.       RVData := TRVJumpInfo(Jumps[i]).RVData;
  333.       ItemNo := RVData.DrawItems[TRVJumpInfo(Jumps[i]).DrawItemNo].ItemNo;
  334.       exit;
  335.     end;
  336. end;
  337. {------------------------------------------------------------------------------}
  338. procedure TCustomRVFormattedData.CopyText_;
  339. begin
  340.   if SelectionExists(True, True) then begin
  341.     Clipboard.SetTextBuf(PChar(GetSelText(False)));
  342.   end;
  343. end;
  344. {------------------------------------------------------------------------------}
  345. procedure TCustomRVFormattedData.CopyTextW_;
  346. var mem: Cardinal;
  347.     ptr: Pointer;
  348.     s: String;
  349.     zero: Word;
  350. begin
  351.   if SelectionExists(True, True) then begin
  352.     s := GetSelText(True);
  353.     mem := GlobalAlloc(GMEM_MOVEABLE or GMEM_DDESHARE, Length(s)+2);
  354.     if mem=0 then raise ERichViewError.Create(errRVNoMemory);
  355.     ptr := GlobalLock(mem);
  356.     Move(PChar(s)^,ptr^, Length(s));
  357.     zero := 0;
  358.     Move(zero,(PChar(ptr)+Length(s))^, 2);
  359.     GlobalUnlock(mem);
  360.     Clipboard.SetAsHandle(CF_UNICODETEXT ,mem);
  361.   end;
  362. end;
  363. {------------------------------------------------------------------------------}
  364. procedure TCustomRVFormattedData.CopyImage_;
  365. var gr: TGraphic;
  366. begin
  367.   gr := GetSelectedImage;
  368.   if gr<>nil then
  369.     try
  370.       Clipboard.Assign(gr);
  371.     except;
  372.     end;
  373. end;
  374. {------------------------------------------------------------------------------}
  375. procedure TCustomRVFormattedData.Copy(Color: TColor; Background: TRVBackground);
  376. begin
  377.   {$IFNDEF RVDONOTUSEINPLACE}
  378.   if (GetChosenRVData<>nil) then begin
  379.     TCustomRVFormattedData(GetChosenRVData).Copy(clNone, nil);
  380.     exit;
  381.   end;
  382.   {$ENDIF}
  383.   if SelectionExists(True, True) then begin
  384.     Clipboard.Clear;
  385.     Clipboard.Open;
  386.     try
  387.       DoCopy;
  388.       {$IFNDEF RVDONOTUSERVF}
  389.       CopyRVF_(Color, Background);
  390.       {$ENDIF}
  391.       CopyText_;
  392.       CopyImage_;
  393.       {$IFNDEF RVDONOTUSEUNICODE}
  394.       CopyTextW_;
  395.       {$ENDIF}
  396.       {$IFNDEF RVDONOTUSERTF}
  397.       CopyRTF_(Color, Background);
  398.       {$ENDIF}
  399.     finally
  400.       Clipboard.Close;
  401.     end;
  402.   end;
  403. end;
  404. {------------------------------------------------------------------------------}
  405. function TCustomRVFormattedData.CopyDef(Color: TColor; Background: TRVBackground): Boolean;
  406. begin
  407.   {$IFNDEF RVDONOTUSEINPLACE}
  408.   if (GetChosenRVData<>nil) then begin
  409.     Result := TCustomRVFormattedData(GetChosenRVData).CopyDef(clNone, nil);
  410.     exit;
  411.   end;
  412.   {$ENDIF}
  413.   Result := ((rvoAutoCopyText in Options) or
  414.              {$IFNDEF RVDONOTUSERVF}
  415.              (rvoAutoCopyRVF in Options) or
  416.              {$ENDIF}
  417.              {$IFNDEF RVDONOTUSEUNICODE}
  418.              (rvoAutoCopyUnicodeText in Options) or
  419.              {$ENDIF}
  420.              {$IFNDEF RVDONOTUSERTF}
  421.              (rvoAutoCopyRTF in Options) or
  422.              {$ENDIF}
  423.              (rvoAutoCopyImage in Options) or
  424.              IsAssignedCopy
  425.              );
  426.   if Result and SelectionExists(True, True) then begin
  427.     Clipboard.Clear;
  428.     Clipboard.Open;
  429.     DoCopy;
  430.     {$IFNDEF RVDONOTUSERVF}
  431.     if (rvoAutoCopyRVF in Options) then CopyRVF_(Color, Background);
  432.     {$ENDIF}
  433.     if (rvoAutoCopyText in Options) and not (RVNT and (rvoAutoCopyUnicodeText in Options)) then CopyText_;
  434.     if (rvoAutoCopyImage in Options) then CopyImage_;
  435.     {$IFNDEF RVDONOTUSEUNICODE}
  436.     if (rvoAutoCopyUnicodeText in Options) then CopyTextW_;
  437.     {$ENDIF}
  438.     {$IFNDEF RVDONOTUSERTF}
  439.     if (rvoAutoCopyRTF in Options) then CopyRTF_(Color, Background);
  440.     {$ENDIF}
  441.     Clipboard.Close;
  442.   end;
  443. end;
  444. {------------------------------------------------------------------------------}
  445. procedure TCustomRVFormattedData.CopyImage;
  446. begin
  447.   {$IFNDEF RVDONOTUSEINPLACE}
  448.   if (GetChosenRVData<>nil) then begin
  449.     TCustomRVFormattedData(GetChosenRVData).CopyImage;
  450.     exit;
  451.   end;
  452.   {$ENDIF}
  453.   if SelectionExists(True, True) then begin
  454.     Clipboard.Clear;
  455.     CopyImage_;
  456.   end;
  457. end;
  458. {------------------------------------------------------------------------------}
  459. procedure TCustomRVFormattedData.CopyText;
  460. begin
  461.   {$IFNDEF RVDONOTUSEINPLACE}
  462.   if (GetChosenRVData<>nil) then begin
  463.     TCustomRVFormattedData(GetChosenRVData).CopyText;
  464.     exit;
  465.   end;
  466.   {$ENDIF}
  467.   if SelectionExists(True, True) then begin
  468.     Clipboard.Clear;
  469.     CopyText_;
  470.   end;
  471. end;
  472. {------------------------------------------------------------------------------}
  473. procedure TCustomRVFormattedData.CopyTextW;
  474. begin
  475.   {$IFNDEF RVDONOTUSEINPLACE}
  476.   if (GetChosenRVData<>nil) then begin
  477.     TCustomRVFormattedData(GetChosenRVData).CopyTextW;
  478.     exit;
  479.   end;
  480.   {$ENDIF}
  481.   if SelectionExists(True, True) then begin
  482.     Clipboard.Clear;
  483.     CopyTextW_;
  484.   end;
  485. end;
  486. {------------------------------------------------------------------------------}
  487. {$IFNDEF RVDONOTUSERTF}
  488. procedure TCustomRVFormattedData.CopyRTF(Color: TColor; Background: TRVBackground);
  489. begin
  490.   {$IFNDEF RVDONOTUSEINPLACE}
  491.   if (GetChosenRVData<>nil) then begin
  492.     TCustomRVFormattedData(GetChosenRVData).CopyRTF(clNone, nil);
  493.     exit;
  494.   end;
  495.   {$ENDIF}
  496.   if SelectionExists(True, True) then begin
  497.     Clipboard.Clear;
  498.     CopyRTF_(Color, Background);
  499.   end;
  500. end;
  501. {------------------------------------------------------------------------------}
  502. procedure TCustomRVFormattedData.CopyRTF_(Color: TColor; Background: TRVBackground);
  503. var mem: Cardinal;
  504.     ptr: Pointer;
  505.     Stream: TMemoryStream;
  506. begin
  507.   Stream := TMemoryStream.Create;
  508.   try
  509.      SaveRTFToStream(Stream, '', True, 0, Color, Background,
  510.        nil, nil, nil, nil, nil, 0.0);
  511.      mem := GlobalAlloc(GMEM_MOVEABLE or GMEM_DDESHARE, Stream.Size);
  512.      if mem=0 then raise ERichViewError.Create(errRVNoMemory);
  513.      ptr := GlobalLock(mem);
  514.      Move(Stream.Memory^,ptr^,Stream.Size);
  515.      GlobalUnlock(mem);
  516.   finally
  517.     Stream.Free;
  518.   end;
  519.   Clipboard.SetAsHandle(CFRV_RTF, mem);
  520. end;
  521. {$ENDIF}
  522. {------------------------------------------------------------------------------}
  523. {$IFNDEF RVDONOTUSERVF}
  524. procedure TCustomRVFormattedData.RVFGetLimits(SaveScope: TRVFSaveScope;
  525.                              var StartItem, EndItem, StartOffs, EndOffs: Integer;
  526.                              var StartPart, EndPart: TRVMultiDrawItemPart);
  527. begin
  528.   if SaveScope=rvfss_Selection then begin
  529.     StartPart := nil;
  530.     EndPart   := nil;
  531.     StoreSelBounds(StartItem, EndItem, StartOffs, EndOffs, True);
  532.     end
  533.   else
  534.     inherited RVFGetLimits(SaveScope, StartItem, EndItem, StartOffs, EndOffs, StartPart, EndPart);
  535. end;
  536. {------------------------------------------------------------------------------}
  537. procedure TCustomRVFormattedData.CopyRVF_(Color: TColor; Background: TRVBackground);
  538. var mem: Cardinal;
  539.     ptr: Pointer;
  540.     Size: Integer;
  541.     Stream: TMemoryStream;
  542. begin
  543.   Stream := TMemoryStream.Create;
  544.   try
  545.      Size := 0;
  546.      Stream.WriteBuffer(Size, SizeOf(Size));
  547.      SaveRVFToStream(Stream, True, Color, Background, nil);
  548.      Size := Stream.Position-SizeOf(Size);
  549.      Stream.Position := 0;
  550.      Stream.WriteBuffer(Size, SizeOf(Size));
  551.      mem := GlobalAlloc(GMEM_MOVEABLE or GMEM_DDESHARE, Stream.Size);
  552.      if mem=0 then raise ERichViewError.Create(errRVNoMemory);
  553.      ptr := GlobalLock(mem);
  554.      Move(Stream.Memory^,ptr^,Stream.Size);
  555.      GlobalUnlock(mem);
  556.   finally
  557.     Stream.Free;
  558.   end;
  559.   Clipboard.SetAsHandle(CFRV_RVF,mem);
  560. end;
  561. {------------------------------------------------------------------------------}
  562. procedure TCustomRVFormattedData.CopyRVF(Color: TColor; Background: TRVBackground);
  563. begin
  564.   {$IFNDEF RVDONOTUSEINPLACE}
  565.   if (GetChosenRVData<>nil) then begin
  566.     TCustomRVFormattedData(GetChosenRVData).CopyRVF(clNone, nil);
  567.     exit;
  568.   end;
  569.   {$ENDIF}
  570.   if SelectionExists(True,True) then begin
  571.     Clipboard.Clear;
  572.     CopyRVF_(Color, Background);
  573.   end;
  574. end;
  575. {$ENDIF}
  576. {------------------------------------------------------------------------------}
  577. procedure TCustomRVFormattedData.AfterVScroll;
  578. var CP: TRVCPInfo;
  579.     y, ymin, ymax: Integer;
  580.     {..........................................................}
  581.     function FindCPBefore(EndCP: TRVCPInfo): TRVCPInfo;
  582.     begin
  583.       Result := EndCP;
  584.       while (Result<>nil) and (not Result.RaiseEvent) do
  585.         Result := Result.Prev;
  586.     end;
  587.     {..........................................................}
  588. begin
  589.   if not IsAssignedCheckpointVisible or (GetCPEventKind=cpeNone) then
  590.     exit;
  591.   ymin := GetVOffs;
  592.   ymax := ymin+GetHeight;
  593.   CP := FirstCP;
  594.   case GetCPEventKind  of
  595.     cpeWhenVisible: // raise event for first visible cp
  596.       begin
  597.         while CP<>nil do begin
  598.           if CP.RaiseEvent then begin
  599.             if CP.ItemInfo.DrawItemNo=-1 then exit; // not formatted
  600.             y := DrawItems[CP.ItemInfo.DrawItemNo].Top;
  601.             if y>=ymin then begin
  602.               if y>ymax then begin
  603.                 if LastRaisedCP<>nil then begin
  604.                   LastRaisedCP := nil;
  605.                   DoCheckpointVisible(nil);
  606.                 end;
  607.                 exit;
  608.               end;
  609.               if CP=LastRaisedCP then exit;
  610.               LastRaisedCP := CP;
  611.               DoCheckpointVisible(CP);
  612.               exit;
  613.             end;
  614.           end;
  615.           CP := CP.Next;
  616.         end;
  617.         if (NotAddedCP<>nil) and (NotAddedCP.RaiseEvent) and (NotAddedCP<>LastRaisedCP) and
  618.            (DocumentHeight<ymax) then begin
  619.           LastRaisedCP := NotAddedCP;
  620.           DoCheckpointVisible(NotAddedCP);
  621.           exit;
  622.         end;
  623.         if LastRaisedCP<>nil then begin
  624.           LastRaisedCP := nil;
  625.           DoCheckpointVisible(nil);
  626.         end;
  627.       end;
  628.     cpeAsSectionStart: // raise event for first visible cp
  629.                        // if there is no such cp, raise event for the closest cp
  630.                        // before visible area
  631.       begin
  632.         while CP<>nil do begin
  633.           if CP.RaiseEvent then begin
  634.             if CP.ItemInfo.DrawItemNo=-1 then exit; // not formatted
  635.             y := DrawItems[CP.ItemInfo.DrawItemNo].Top;
  636.             if y>=ymin then begin
  637.               if y>ymax then
  638.                 CP := FindCPBefore(CP.Prev);
  639.               if CP<>nil then begin
  640.                 if CP=LastRaisedCP then exit;
  641.                 LastRaisedCP := CP;
  642.                 DoCheckpointVisible(CP);
  643.               end;
  644.               exit;
  645.             end;
  646.           end;
  647.           CP := CP.Next;
  648.         end;
  649.         if (NotAddedCP<>nil) and (NotAddedCP.RaiseEvent) and (DocumentHeight<ymax) then begin
  650.           if NotAddedCP=LastRaisedCP then exit;
  651.           LastRaisedCP := NotAddedCP;
  652.           DoCheckpointVisible(NotAddedCP);
  653.           exit;
  654.         end;
  655.         CP := FindCPBefore(LastCP);
  656.         if CP<>nil then begin
  657.           y := DrawItems[CP.ItemInfo.DrawItemNo].Top;
  658.           if y<=ymin then begin
  659.             if CP=LastRaisedCP then exit;
  660.             LastRaisedCP := CP;
  661.             DoCheckpointVisible(CP);
  662.             exit;
  663.           end;
  664.         end;
  665.       end;
  666.   end;
  667. end;
  668. {------------------------------------------------------------------------------}
  669. procedure TCustomRVFormattedData.UpdateBackgroundPaletteInfo(Background: TRVBackground);
  670. begin
  671.   State := State + [rvstChangingBkPalette];
  672.   Background.UpdatePaletted(GetDoInPaletteMode, GetRVPalette, GetRVLogPalette);
  673.   State := State - [rvstChangingBkPalette];
  674. end;
  675. {------------------------------------------------------------------------------}
  676. function TCustomRVFormattedData.UpdatingBackgroundPalette: Boolean;
  677. begin
  678.   Result := rvstChangingBkPalette in State;
  679. end;
  680. {------------------------------------------------------------------------------}
  681. procedure TCustomRVFormattedData.StartFormatting;
  682. begin
  683.    State := State + [rvstSkipformatting];
  684. end;
  685. {------------------------------------------------------------------------------}
  686. procedure TCustomRVFormattedData.EndFormatting;
  687. begin
  688.    State := State - [rvstSkipformatting];
  689. end;
  690. {------------------------------------------------------------------------------}
  691. procedure TCustomRVFormattedData.GetParaBounds(DINo1, DINo2: Integer; var ParaStart,
  692.   ParaEnd: Integer);
  693. var ItemNo: Integer;
  694.     item: TCustomRVItemInfo;
  695. begin
  696.   { calculating paragraphs bounds }
  697.   ParaStart := DINo1;
  698.   while (ParaStart>0) do begin
  699.     item := GetItem(DrawItems[ParaStart].ItemNo);
  700.     if not item.SameAsPrev and not item.BR and
  701.        (DrawItems[ParaStart-1].ItemNo<>DrawItems[ParaStart].ItemNo) then break;
  702.     dec(ParaStart);
  703.   end;
  704.   { and prev. paragraph...}
  705.   if ParaStart<>0 then dec(ParaStart);
  706.   while (ParaStart>0) do begin
  707.     item := GetItem(DrawItems[ParaStart].ItemNo);
  708.     if not item.SameAsPrev and not item.BR and
  709.        (DrawItems[ParaStart-1].ItemNo<>DrawItems[ParaStart].ItemNo) then break;
  710.     dec(ParaStart);
  711.   end;
  712.   ParaEnd := DINo2;
  713.   ItemNo := DrawItems[ParaEnd].ItemNo;
  714.   while (ParaEnd<DrawItems.Count) and (DrawItems[ParaEnd].ItemNo=ItemNo) do
  715.     inc(ParaEnd);
  716.   while (ParaEnd<DrawItems.Count) and (DrawItems[ParaEnd].ItemNo<Items.Count) do begin
  717.     item := GetItem(DrawItems[ParaEnd].ItemNo);
  718.     if not item.SameAsPrev and not item.BR then
  719.       break;
  720.     inc(ParaEnd);
  721.   end;
  722.   { and next paragraph...}
  723.   if (ParaEnd<DrawItems.Count) then begin
  724.     ItemNo := DrawItems[ParaEnd].ItemNo;
  725.     while (ParaEnd<DrawItems.Count) and
  726.       (DrawItems[ParaEnd].ItemNo=ItemNo) do inc(ParaEnd);
  727.     while (ParaEnd<DrawItems.Count) and (DrawItems[ParaEnd].ItemNo<Items.Count) do begin
  728.       item := GetItem(DrawItems[ParaEnd].ItemNo);
  729.       if not item.SameAsPrev and not item.BR then
  730.         break;
  731.       inc(ParaEnd);
  732.     end;
  733.   end;
  734.   dec(ParaEnd);
  735. end;
  736. {------------------------------------------------------------------------------}
  737. procedure TCustomRVFormattedData.FormatParas(StartDrawItemNo, EndDrawItemNo,
  738.                                              ItemsInserted: Integer);
  739. var First,Last, ItemNo: Integer;
  740. begin
  741.   { calculating paragraphs bounds }
  742.   First := StartDrawItemNo;
  743.   while (First>0) do begin
  744.     if not GetItem(DrawItems[First].ItemNo).SameAsPrev and
  745.        (DrawItems[First-1].ItemNo<>DrawItems[First].ItemNo) then break;
  746.     dec(First);
  747.   end;
  748.   Last := EndDrawItemNo;
  749.   ItemNo := DrawItems[Last].ItemNo;
  750.   if ItemNo>=Items.Count-1 then
  751.     Last := DrawItems.Count-1
  752.   else begin
  753.     while (Last<DrawItems.Count) and
  754.           (DrawItems[Last].ItemNo=ItemNo) do inc(Last);
  755.     if Last<DrawItems.Count then begin
  756.       ItemNo := DrawItems[Last].ItemNo;
  757.       if ItemNo>=Items.Count-1 then
  758.         Last := DrawItems.Count-1
  759.       else begin
  760.         while (Last<DrawItems.Count) and
  761.               (DrawItems[Last].ItemNo+ItemsInserted<Items.Count) and
  762.               TCustomRVItemInfo(Items.Objects[DrawItems[Last].ItemNo+ItemsInserted]).SameAsPrev do
  763.             inc(Last);
  764.         if Last<>DrawItems.Count-1 then dec(Last);
  765.       end;
  766.       end
  767.     else
  768.       Last := DrawItems.Count-1;
  769.   end;
  770.   FormatParasExact(First, Last,ItemsInserted, False);
  771. end;
  772. {-----------------------------------------------------------------------}
  773. procedure TCustomRVFormattedData.FormatParasExact(StartDrawItemNo,EndDrawItemNo,
  774.   ItemsInserted: Integer; NoCaching: Boolean);
  775.   function GetParagraphBottom(EndDrawItemNo: Integer):Integer;
  776.   var i: Integer;
  777.   begin
  778.    Result := GetTopMargin;
  779.    i := EndDrawItemNo;
  780.    while (i>=0) do
  781.      with DrawItems[i] do begin
  782.        if Top+Height+ExtraSpaceBelow>Result then
  783.          Result := Top+Height+ExtraSpaceBelow;
  784.        if FromNewLine then
  785.          break;
  786.        dec(i);
  787.      end;
  788.   end;
  789.   function GetParagraphTop(StartDrawItemNo: Integer):Integer;
  790.   var i: Integer;
  791.   begin
  792.    Result := DrawItems[StartDrawItemNo].Top;
  793.    i := StartDrawItemNo+1;
  794.    while (i<DrawItems.Count) and
  795.          not DrawItems[i].FromNewLine do
  796.      with DrawItems[i] do begin
  797.        if Top<Result then
  798.          Result := Top;
  799.        inc(i);
  800.      end;
  801.   end;
  802.   procedure FormatParasExact_(var StartItemNo,EndItemNo: Integer);
  803.   var PrevParBottom, ParBottom, NextParTop: Integer;
  804.     i: Integer;
  805.     sad: TRVScreenAndDevice;
  806.     DLC: Integer;
  807.     Canvas: TCanvas;
  808.     item: TCustomRVItemInfo;
  809.     RVStyle: TRVStyle;
  810.     ExtraSpaceBelowLine: Integer;
  811.     RepaintRect: TRect;
  812.     SavedVOffs: Integer;
  813.     Params: TRVFormatParams;
  814.   begin
  815.     Canvas := GetCanvas;
  816.     DLC := DrawItems.Count;
  817.     Params.SpaceEaten := False;
  818.     Params.NoCaching := NoCaching;
  819.     Params.LastTextStyle := -1;
  820.     Params.FirstParaItemNo := -1;
  821.     StartItemNo := DrawItems[StartDrawItemNo].ItemNo;
  822.     EndItemNo   := DrawItems[EndDrawItemNo  ].ItemNo+ItemsInserted;
  823.     AdjustInItemsRange(StartItemNo);
  824.     if EndItemNo<StartItemNo then
  825.       EndItemNo := StartItemNo;
  826.     AdjustInItemsRange(EndItemNo);
  827.     //ExpandToPara(StartItemNo, EndItemNo, StartItemNo, EndItemNo);
  828.     PrevParBottom := GetParagraphBottom(StartDrawItemNo-1);
  829.     if EndDrawItemNo<>DrawItems.Count-1 then
  830.        NextParTop := GetParagraphTop(EndDrawItemNo+1)
  831.     else
  832.        NextParTop := -1;
  833.     RepaintRect.Top := PrevParBottom-10-GetVOffs;
  834.     RepaintRect.Left := 0;
  835.     RepaintRect.Right := GetWidth;       
  836.     Params.x := 0;
  837.     Params.prevdesc := 0;
  838.     Params.prevabove := 0;
  839.     Params.baseline := PrevParBottom;
  840.     Params.LastTabDrawItemNo := -1;
  841.     GetSADForFormatting(GetCanvas, sad);
  842.     sad.LeftMargin := MulDiv(GetLeftMargin,  sad.ppixDevice, sad.ppixScreen);
  843.     sad.RightMargin := MulDiv(GetRightMargin,  sad.ppixDevice, sad.ppixScreen);
  844.     Params.IsParaStart := True;
  845.     Params.LineWidth   := 0;
  846.     Params.FirstIndent      := 0;
  847.     Params.LastDrawItem := StartDrawItemNo;
  848.     DrawItems.MarkForDelete(StartDrawItemNo,EndDrawItemNo);
  849.     Params.DontFSL := True;
  850.     RVStyle := GetRVStyle;
  851.     CreateFontInfoCache(Canvas);
  852.     Params.FontInfoCache := GetFontInfoCache(Canvas, Self);
  853.     Params.FormatCanvas := Canvas;
  854.     Params.FormatCanvasHandle := Canvas.Handle;
  855.     for i:=StartItemNo to EndItemNo do
  856.       with TCustomRVItemInfo(Items.Objects[i]) do begin
  857.         if not SameAsPrev and not BR then
  858.           Params.FirstParaItemNo := i;
  859.         if (StyleNo>=0) then
  860.           if (RVStyle.ParaStyles[ParaNo].Alignment = rvaJustify) then
  861.              FormatWords(i, Canvas, sad, Params)
  862.           else
  863.              FormatLine(
  864.                RV_ReturnProcessedString(Items[i],
  865.                  RVStyle.TextStyles[GetActualStyleNo(RVStyle)], False,
  866.                    rvoShowSpecialCharacters in Options, False),
  867.                Items[i], 0,
  868.                {$IFNDEF RVDONOTUSEUNICODE}
  869.                RVU_Length(Items[i], ItemOptions),
  870.                {$ELSE}
  871.                Length(Items[i]),
  872.                {$ENDIF}
  873.                i, Canvas, sad, Params)
  874.         else
  875.           FormatLine('', '', 0, Length(Items[i]),i, Canvas, sad, Params);
  876.       end;
  877.     UpdateLastTab(Params);
  878.     FinishScreenLine(sad, Params.LineWidth+Params.FirstIndent, Params.LastDrawItem, True,
  879.       ExtraSpaceBelowLine, Params.DontFSL, Params.FormatCanvas);
  880.     DestroyFontInfoCache(Params.FontInfoCache);
  881.     inc(Params.baseline, ExtraSpaceBelowLine);
  882.     DrawItems.DeleteMarked;
  883.     if (EndItemNo=Items.Count-1) or GetItem(EndItemNo+1).CanBeBorderStart then
  884.       inc(Params.prevdesc, GetRVStyle.ParaStyles[GetItemPara(EndItemNo)].SpaceAfter);
  885.     if (EndItemNo<Items.Count-1) and GetItem(EndItemNo+1).CanBeBorderStart then
  886.       inc(Params.prevdesc, GetRVStyle.ParaStyles[GetItemPara(EndItemNo+1)].SpaceBefore);
  887.     RepaintRect.Bottom := Params.baseline+Params.prevdesc+10-GetVOffs;
  888.     if (ItemsInserted<>0) or (DLC<>DrawItems.Count) or
  889.        (NextParTop<>Params.baseline+Params.prevdesc) then begin
  890.       ParBottom := Params.baseline+Params.prevdesc;
  891.       // RepaintRect.Bottom := GetHeight;
  892.       for i:=Params.LastDrawItem to DrawItems.Count-1 do
  893.         with DrawItems[i] do begin
  894.           Top := Top-NextParTop+(Params.baseline+Params.prevdesc);
  895.           if Top+Height>ParBottom then
  896.             ParBottom := Top+Height;
  897.           ItemNo := ItemNo + ItemsInserted;
  898.           item := TCustomRVItemInfo(Items.Objects[ItemNo]);
  899.           if GetOffsBeforeItem(ItemNo)=Offs then
  900.             item.DrawItemNo := i;
  901.         end;
  902.       if (EndItemNo<Items.Count-1) then
  903.         inc(ParBottom, GetRVStyle.ParaStyles[GetItemPara(Items.Count-1)].SpaceAfter);
  904.       RepaintRect.Bottom := ParBottom-GetVOffs+10;
  905.       if DocumentHeight-GetBottomMargin+10>RepaintRect.Bottom then
  906.         RepaintRect.Bottom := DocumentHeight-GetBottomMargin+10;
  907.       if RepaintRect.Bottom>GetHeight then
  908.         RepaintRect.Bottom := GetHeight;
  909.       if DocumentHeight <> (ParBottom+GetBottomMargin) then begin
  910.         SavedVOffs := GetVOffs;
  911.         DocumentHeight := ParBottom+GetBottomMargin;
  912.         AdjustVScrollUnits;
  913.         AlreadyFormatted := True;
  914.         SetDocumentAreaSize(GetAreaWidth, DocumentHeight, False);
  915.         AlreadyFormatted := False;
  916.         if SavedVOffs<>GetVOffs then
  917.           RepaintRect := GetParentControl.ClientRect;
  918.       end;
  919.     end;
  920.     AdjustChildrenCoords;
  921.     LastItemFormatted := Items.Count-1;
  922.     InvalidateRect(RepaintRect);
  923.     GetParentControl.Update;
  924.   end;
  925. var StartItemNo,EndItemNo: Integer;
  926. begin
  927.   FormatParasExact_(StartItemNo,EndItemNo);
  928.   Formatted(StartItemNo,EndItemNo,True);
  929. end;
  930. {------------------------------------------------------------------------------}
  931. procedure TCustomRVFormattedData.DoOnSelection(AllowScrolling: Boolean);
  932. begin
  933.   {$IFNDEF RVDONOTUSEANIMATION}
  934.   ResetAniBackground;
  935.   {$ENDIF}
  936. end;
  937. {------------------------------------------------------------------------------}
  938. procedure TCustomRVFormattedData.XorDrawing;
  939. begin
  940.   if Assigned(FXORDrawing) then begin
  941.     FXORDrawing(Self, [], MouseX, MouseY);
  942.     XorImageDrawn := not XorImageDrawn;
  943.   end;
  944. end;
  945. {------------------------------------------------------------------------------}
  946. procedure TCustomRVFormattedData.XorDrawingEx(X, Y: Integer);
  947. begin
  948.   MouseX := X;
  949.   MouseY := Y;
  950.   XorDrawing;
  951. end;
  952. {------------------------------------------------------------------------------}
  953. procedure TCustomRVFormattedData.UnAssignXorDrawing(P: TMouseMoveEvent);
  954. begin
  955.   if @FXORDrawing=@P then begin
  956.     if XorImageDrawn and not (csDestroying in GetParentControl.ComponentState) then
  957.       XorDrawing;
  958.     FXORDrawing := nil;
  959.   end;
  960. end;
  961. {------------------------------------------------------------------------------}
  962. procedure TCustomRVFormattedData.AssignXorDrawing(P: TMouseMoveEvent);
  963. begin
  964.   if XorImageDrawn then
  965.     XorDrawing;
  966.   FXORDrawing := P;
  967. end;
  968. {------------------------------------------------------------------------------}
  969. function TCustomRVFormattedData.UsingThisXorDrawing(P: TMouseMoveEvent): Boolean;
  970. begin
  971.   Result := @FXORDrawing=@P;
  972. end;
  973. {------------------------------------------------------------------------------}
  974. function TCustomRVFormattedData.ClearXorDrawing: Boolean;
  975. begin
  976.   Result := XorImageDrawn;
  977.   if XorImageDrawn then
  978.     XorDrawing;
  979. end;
  980. {------------------------------------------------------------------------------}
  981. procedure TCustomRVFormattedData.InternalFreeItem(item: TCustomRVItemInfo;
  982.                                                   Clearing: Boolean);
  983. begin
  984.   if item=FCaptureMouseItem then
  985.     FCaptureMouseItem := nil;
  986. //  if item=GetChosenItem then
  987. //    UnassignChosenRVData(GetChosenRVData);
  988.   inherited InternalFreeItem(item, Clearing);
  989. end;
  990. {------------------------------------------------------------------------------}
  991. procedure TCustomRVFormattedData.ReleaseMouseCapture(Item: TCustomRVItemInfo);
  992. begin
  993.   if Item=FCaptureMouseItem then
  994.     FCaptureMouseItem := nil;
  995. end;
  996. {------------------------------------------------------------------------------}
  997. procedure TCustomRVFormattedData.SetMouseCapture(Item: TCustomRVItemInfo;
  998.                                                  var Left,Top: Integer);
  999. begin
  1000.   if (LastDIMovedAbove<0) or (LastDIMovedAbove>=DrawItems.Count) or
  1001.      (Item <> Items.Objects[DrawItems[LastDIMovedAbove].ItemNo]) then
  1002.     Item2FirstDrawItem(Items.IndexOfObject(Item),LastDIMovedAbove);
  1003.   Left := DrawItems[LastDIMovedAbove].Left;
  1004.   Top := DrawItems[LastDIMovedAbove].Top;
  1005.   FCaptureMouseItem := Item;
  1006. end;
  1007. {------------------------------------------------------------------------------}
  1008. function TCustomRVFormattedData.GetCPEventKind: TCPEventKind;
  1009. begin
  1010.   Result := TCustomRVFormattedData(GetAbsoluteRootData).GetCPEventKind;
  1011. end;
  1012. {------------------------------------------------------------------------------}
  1013. procedure TCustomRVFormattedData.DoSelect;
  1014. begin
  1015.   TCustomRVFormattedData(GetAbsoluteRootData).DoSelect;
  1016. end;
  1017. {------------------------------------------------------------------------------}
  1018. procedure TCustomRVFormattedData.DoCurrentTextStyleConversion(
  1019.   var StyleNo: Integer; ParaStyleNo, ItemNo, UserData: Integer;
  1020.   ToWholeParagraphs: Boolean);
  1021. begin
  1022.   if not (rvflRoot in Flags) then
  1023.     TCustomRVFormattedData(GetAbsoluteRootData).DoCurrentTextStyleConversion(
  1024.       StyleNo, ParaStyleNo, ItemNo, UserData, ToWholeParagraphs);
  1025. end;
  1026. {------------------------------------------------------------------------------}
  1027. function TCustomRVFormattedData.IsAssignedRVDblClick: Boolean;
  1028. begin
  1029.    Result := TCustomRVFormattedData(GetAbsoluteRootData).IsAssignedRVDblClick;
  1030. end;
  1031. {------------------------------------------------------------------------------}
  1032. procedure TCustomRVFormattedData.DoRVDblClick(const ClickedWord: String;
  1033.   StyleNo: Integer);
  1034. begin
  1035.   TCustomRVFormattedData(GetAbsoluteRootData).DoRVDblClick(ClickedWord, StyleNo);
  1036. end;
  1037. {------------------------------------------------------------------------------}
  1038. function TCustomRVFormattedData.IsAssignedRVRightClick: Boolean;
  1039. begin
  1040.   Result := TCustomRVFormattedData(GetAbsoluteRootData).IsAssignedRVRightClick;
  1041. end;
  1042. {------------------------------------------------------------------------------}
  1043. procedure TCustomRVFormattedData.DoRVRightClick(const ClickedWord: String;
  1044.   StyleNo, X, Y: Integer);
  1045. begin
  1046.   TCustomRVFormattedData(GetAbsoluteRootData).DoRVRightClick(ClickedWord, StyleNo, X,Y);
  1047. end;
  1048. {------------------------------------------------------------------------------}
  1049. function TCustomRVFormattedData.GetCanvas: TCanvas;
  1050. begin
  1051.   Result := TCustomRVFormattedData(GetRootData).GetCanvas;
  1052. end;
  1053. {------------------------------------------------------------------------------}
  1054. procedure TCustomRVFormattedData.DeselectPartiallySelectedItem(NewPartiallySelected: TCustomRVItemInfo);
  1055. begin
  1056.   if (FPartialSelectedItem<>nil) and (FPartialSelectedItem<>NewPartiallySelected) then begin
  1057.     //if not (csDestroying in GetParentControl.ComponentState) then
  1058.       FPartialSelectedItem.DeselectPartial;
  1059.     FPartialSelectedItem := nil;
  1060.   end;
  1061.   if (GetChosenItem<>nil) and (GetChosenItem<>NewPartiallySelected) then begin
  1062.     if not (csDestroying in GetParentControl.ComponentState) then
  1063.       UnassignChosenRVData(GetChosenRVData);
  1064.   end;  
  1065. end;
  1066. {------------------------------------------------------------------------------}
  1067. procedure TCustomRVFormattedData.SetPartialSelectedItem(Item: TCustomRVItemInfo);
  1068. begin
  1069.   if FPartialSelectedItem<>Item then begin
  1070.     Deselect(Item, True);
  1071.     FPartialSelectedItem := Item;
  1072.     DoSelect;
  1073.   end;
  1074. end;
  1075. {------------------------------------------------------------------------------}
  1076. function TCustomRVFormattedData.GetItemCoords(ItemNo: Integer; var Left, Top: Integer): Boolean;
  1077. begin
  1078.   Item2FirstDrawItem(ItemNo, ItemNo);
  1079.   Result := ItemNo<>-1;
  1080.   if Result then begin
  1081.     Left := DrawItems[ItemNo].Left;
  1082.     Top := DrawItems[ItemNo].Top;
  1083.   end;
  1084. end;
  1085. {------------------------------------------------------------------------------}
  1086. function TCustomRVFormattedData.GetItemClientCoords(ItemNo: Integer; var Left, Top: Integer): Boolean;
  1087. begin
  1088.   Result := GetItemCoords(ItemNo, Left, Top);
  1089.   if Result then begin
  1090.     dec(Left, GetHOffs);
  1091.     dec(Top, GetVOffs);
  1092.   end;
  1093. end;
  1094. {------------------------------------------------------------------------------}
  1095. procedure TCustomRVFormattedData.DoCopy;
  1096. var root: TCustomRVData;
  1097. begin
  1098.   root := GetRootData;
  1099.   if root is TCustomRVFormattedData then
  1100.     TCustomRVFormattedData(GetRootData).DoCopy;
  1101. end;
  1102. {------------------------------------------------------------------------------}
  1103. function TCustomRVFormattedData.IsAssignedCopy: Boolean;
  1104. var root: TCustomRVData;
  1105. begin
  1106.   root := GetRootData;
  1107.   if root is TCustomRVFormattedData then
  1108.     Result := TCustomRVFormattedData(GetRootData).IsAssignedCopy
  1109.   else
  1110.     Result := False;
  1111. end;
  1112. {------------------------------------------------------------------------------}
  1113. procedure TCustomRVFormattedData.AssignChosenRVData(RVData: TCustomRVFormattedData;
  1114.                                                     Item: TCustomRVItemInfo);
  1115. begin
  1116. end;
  1117. {------------------------------------------------------------------------------}
  1118. procedure TCustomRVFormattedData.SilentReplaceChosenRVData(RVData: TCustomRVFormattedData);
  1119. begin
  1120. end;
  1121. {------------------------------------------------------------------------------}
  1122. procedure TCustomRVFormattedData.UnassignChosenRVData(RVData: TCustomRVData);
  1123. begin
  1124.   Include(State,rvstForceStyleChangeEvent);
  1125. end;
  1126. {------------------------------------------------------------------------------}
  1127. procedure TCustomRVFormattedData.Formatted(FirstItemNo, LastItemNo: Integer;Partial: Boolean);
  1128. begin
  1129. end;
  1130. {------------------------------------------------------------------------------}
  1131. function TCustomRVFormattedData.GetInplaceEditor: TControl;
  1132. begin
  1133.   Result := nil
  1134. end;
  1135. {------------------------------------------------------------------------------}
  1136. procedure TCustomRVFormattedData.DestroyInplaceEditor;
  1137. begin
  1138. end;
  1139. {------------------------------------------------------------------------------}
  1140. function TCustomRVFormattedData.GetNextFocusedItem(ItemNo: Integer; GoForward: Boolean;
  1141.                                   var TopLevelRVData: TCustomRVFormattedData;
  1142.                                   var TopLevelItemNo: Integer): Integer;
  1143. var i: Integer;
  1144.     Style: TRVStyle;
  1145.     {...........................................}
  1146.     function CheckItem(ItemNo: Integer): Boolean;
  1147.     begin
  1148.       if GetItem(i).GetBoolValueEx(rvbpAllowsFocus, Style) then begin
  1149.         TopLevelRVData := Self;
  1150.         TopLevelItemNo := ItemNo;
  1151.         Result := True;
  1152.         exit;
  1153.       end;
  1154.       Result := GetItem(i).MoveFocus(GoForward, TPersistent(TopLevelRVData), TopLevelItemNo);
  1155.     end;
  1156.     {...........................................}
  1157. begin
  1158.   if (FocusedItemNo<0) or (FocusedItemNo>=Items.Count) then
  1159.     FocusedItemNo := -1;
  1160.   Style := GetRVStyle;
  1161.   if GoForward then begin
  1162.     if (ItemNo<0) or
  1163.        GetItem(ItemNo).GetBoolValueEx(rvbpAllowsFocus, Style) then
  1164.       inc(ItemNo);
  1165.     for i := ItemNo to Items.Count-1 do
  1166.       if CheckItem(i) then begin
  1167.         Result := i;
  1168.         exit;
  1169.       end;
  1170.     end
  1171.   else begin
  1172.     if ItemNo<0 then
  1173.       ItemNo := Items.Count;
  1174.     if (ItemNo=Items.Count) or
  1175.        GetItem(ItemNo).GetBoolValueEx(rvbpAllowsFocus, Style) then
  1176.       dec(ItemNo);
  1177.     for i := ItemNo downto 0 do
  1178.       if CheckItem(i) then begin
  1179.         Result := i;
  1180.         exit;
  1181.       end;
  1182.   end;
  1183.   Result := -1;
  1184. end;
  1185. {------------------------------------------------------------------------------}
  1186. procedure TCustomRVFormattedData.ClearFocus;
  1187. begin
  1188.   if (FocusedItemNo<0) or (FocusedItemNo>=Items.Count) then
  1189.     FocusedItemNo := -1;
  1190.   if FocusedItemNo<>-1 then
  1191.     GetItem(FocusedItemNo).ClearFocus;
  1192. end;
  1193. {------------------------------------------------------------------------------}
  1194. procedure TCustomRVFormattedData.AdjustFocus(NewFocusedItemNo: Integer;
  1195.                   TopLevelRVData: TPersistent; TopLevelItemNo: Integer);
  1196. begin
  1197.   FocusedItemNo := NewFocusedItemNo;
  1198. end;
  1199. {------------------------------------------------------------------------------}
  1200. procedure TCustomRVFormattedData.ShowRectangle(Left, Top, Width, Height: Integer);
  1201. begin
  1202.   if (Left<GetHOffs) then begin
  1203.     HScrollTo(Left-GetWidth div 4);
  1204.     end
  1205.   else if (Left+Width>GetHOffs+GetWidth) then begin
  1206.     HScrollTo(Left-GetWidth div 4);
  1207.   end;
  1208.   if (Top+Height>GetVOffs+GetHeight-GetVSmallStep*2) and (Top<GetVOffs+GetVSmallStep) then exit;
  1209.   if (Top+Height>GetVOffs+GetHeight) then begin
  1210.      ScrollTo(Top+Height-GetHeight+GetVSmallStep,True);
  1211.     end
  1212.   else if (Top<GetVOffs) then begin
  1213.      ScrollTo(Top,True);
  1214.   end;
  1215. end;
  1216. {------------------------------------------------------------------------------}
  1217. {
  1218. procedure TCustomRVFormattedData.SetZoomPercent(const Value: Integer);
  1219. begin
  1220.   FZoomPercent := Value;
  1221. end;
  1222. }
  1223. {------------------------------------------------------------------------------}
  1224. function TCustomRVFormattedData.GetZHOffs: Integer;
  1225. begin
  1226.   Result := GetHOffs;
  1227.   ZoomInt(Result);
  1228. end;
  1229. {------------------------------------------------------------------------------}
  1230. function TCustomRVFormattedData.GetZVOffs: Integer;
  1231. begin
  1232.   Result := GetVOffs;
  1233.   ZoomInt(Result);
  1234. end;
  1235. {------------------------------------------------------------------------------}
  1236. procedure TCustomRVFormattedData.BuildJumpsCoords(var StartJumpNo: Integer; jumps: TList);
  1237. var i: Integer;
  1238.     LastItemNo,tmp: Integer;
  1239.     jmpinfo: TRVJumpInfo;
  1240.     Style: TRVStyle;
  1241.     item: TCustomRVItemInfo;
  1242. begin
  1243.   if jumps=nil then
  1244.     jumps := Self.jumps;
  1245.   Style := GetRVStyle;
  1246.   if Style=nil then exit;
  1247.   nJmps := 0;
  1248.   LastItemNo := -1;
  1249.   for i := 0 to DrawItems.Count-1 do begin
  1250.     item := GetItem(DrawItems[i].ItemNo);
  1251.     if item.GetBoolValueEx(rvbpJump, Style) then
  1252.       with DrawItems[i] do begin
  1253.         jmpinfo     := TRVJumpInfo.Create;
  1254.         jmpinfo.l   := Left;
  1255.         jmpinfo.t   := Top;
  1256.         jmpinfo.w   := Width;
  1257.         jmpinfo.h   := Height;
  1258.         jmpinfo.id  := nJmps+StartJumpNo;
  1259.         if LastItemNo=DrawItems[i].ItemNo then
  1260.           dec(jmpinfo.id);
  1261.         jmpinfo.RVData := Self;
  1262.         jmpinfo.DrawItemNo := i;
  1263.         GetItem(DrawItems[i].ItemNo).JumpID := jmpinfo.id;
  1264.         if (item.StyleNo<0) then
  1265.           jmpinfo.Cursor := item.GetHypertextCursor(Style)
  1266.         else
  1267.           jmpinfo.Cursor := Style.TextStyles[GetActualStyle(item)].JumpCursor;
  1268.         jumps.Add(jmpinfo);
  1269.         if LastItemNo<>DrawItems[i].ItemNo then begin
  1270.            inc(nJmps);
  1271.            LastItemNo := DrawItems[i].ItemNo;
  1272.         end;
  1273.       end
  1274.     else if item.StyleNo<0 then
  1275.       with DrawItems[i] do begin
  1276.         tmp := nJmps+ StartJumpNo;
  1277.         item.BuildJumps(Left, Top, tmp, jumps);
  1278.         nJmps := tmp-StartJumpNo;
  1279.       end;
  1280.   end;
  1281.   inc(StartJumpNo,nJmps);
  1282. end;
  1283. {------------------------------------------------------------------------------}
  1284. { Coordinates of the top left corner of this RVData relative to the closest
  1285.   top left of the parent RichView's document (root one or inplace editor)
  1286.   (overriden in TRVTableCellData)                                              }
  1287. procedure TCustomRVFormattedData.GetOrigin(var ALeft, ATop: Integer);
  1288. begin
  1289.   ALeft := 0;
  1290.   ATop := 0;
  1291. end;
  1292. {------------------------------------------------------------------------------}
  1293. { Coordinates of the top left corner of this RVData relative to the top left of
  1294.   the root parent RichView's document
  1295.   (overriden in TRVTableCellData, TRVTableInplaceRVData)                       }
  1296. procedure TCustomRVFormattedData.GetOriginEx(var ALeft, ATop: Integer);
  1297. begin
  1298.   ALeft := 0;
  1299.   ATop := 0;
  1300. end;
  1301. {------------------------------------------------------------------------------}
  1302. { Is the specified position (drawing item, offset in it) inside the selection? }
  1303. function TCustomRVFormattedData.DItem_InsideSelection(DItemNo,
  1304.   DItemOffs: Integer): Boolean;
  1305. var sno,soff,eno,eoff: Integer;
  1306. begin
  1307.   Result := False;
  1308.   if not SelectionExists(False, False) then
  1309.     exit;
  1310.   GetSelBounds(sno, eno, soff,eoff, True);
  1311.   Result :=
  1312.     (sno>=0) and
  1313.     ((DItemNo>sno) or ((DItemNo=sno) and (DItemOffs>=soff))) and
  1314.     ((DItemNo<eno) or ((DItemNo=eno) and (DItemOffs<=eoff)));
  1315. end;
  1316. {------------------------------------------------------------------------------}
  1317. { Is the specified position (item, offset in it) inside the selection?
  1318.   Unlike DItem_InsideSelection, checks if the current RVData is completely
  1319.   selected in its parent RVData                                                }
  1320. function  TCustomRVFormattedData.Item_InsideSelection(ItemNo,
  1321.   ItemOffs: Integer): Boolean;
  1322. var sno,soff,eno,eoff: Integer;
  1323.     PItemNo: Integer;
  1324.     Location: TRVStoreSubRVData;
  1325. begin
  1326.   Result := False;
  1327.   if GetParentData<>nil then begin
  1328.     GetParentInfo(PItemNo, Location);
  1329.     Location.Free;
  1330.     if (PItemNo>=0) then
  1331.       Result := TCustomRVFormattedData(GetParentData).Item_InsideSelection(PItemNo, 0);
  1332.   end;
  1333.   if Result then
  1334.     exit;
  1335.   if not SelectionExists(False, False) then
  1336.     exit;
  1337.   GetSelectionBounds(sno, soff, eno, eoff, True);
  1338.   Result :=
  1339.     (sno>=0) and
  1340.     ((sno<>eno) or (soff<>eoff)) and
  1341.     ((ItemNo>sno) or ((ItemNo=sno) and (ItemOffs>=soff))) and
  1342.     ((ItemNo<eno) or ((ItemNo=eno) and (ItemOffs<=eoff)));
  1343. end;
  1344. {------------------------------------------------------------------------------}
  1345. procedure TCustomRVFormattedData.AfterDeleteStyles(Data: TRVDeleteUnusedStylesData);
  1346. {$IFNDEF RVDONOTUSEINPLACE}
  1347. var inplace: TControl;
  1348. {$ENDIF}
  1349. begin
  1350.   {$IFNDEF RVDONOTUSEINPLACE}
  1351.   inplace := GetInplaceEditor;
  1352.   if inplace is TCustomRichView then
  1353.     TCustomRichView(inplace).RVData.AfterDeleteStyles(Data);
  1354.   {$ENDIF}
  1355. end;
  1356. {------------------------------------------------------------------------------}
  1357. procedure TCustomRVFormattedData.GetItemAt(X, Y: Integer; var ItemNo,
  1358.   OffsetInItem: Integer);
  1359. begin
  1360.   FindDrawItemForSel(X, Y, ItemNo, OffsetInItem, True);
  1361.   if ItemNo<>-1 then
  1362.     DrawItem2Item(ItemNo, OffsetInItem, ItemNo, OffsetInItem);
  1363. end;
  1364. {------------------------------------------------------------------------------}
  1365. procedure TCustomRVFormattedData.GetItemAtEx(X,Y: Integer;
  1366.   var RVData: TCustomRVFormattedData; var ItemNo, OffsetInItem: Integer;
  1367.   Strict: Boolean; var InSubRVDataOwnerItem: Boolean);
  1368. var AX, AY, BX,BY: Integer;
  1369. begin
  1370.   InSubRVDataOwnerItem := False;
  1371.   RVData := Self;
  1372.   FindDrawItemForSel(X, Y, ItemNo, OffsetInItem, Strict);
  1373.   if ItemNo<>-1 then begin
  1374.     DrawItem2Item(ItemNo, OffsetInItem, ItemNo, OffsetInItem);
  1375.     GetItemCoords(ItemNo, AX, AY);
  1376.     RVData := TCustomRVFormattedData(GetItem(ItemNo).GetSubRVDataAt(X-AX,Y-AY));
  1377.     if RVData=nil then begin
  1378.       RVData := Self;
  1379.       InSubRVDataOwnerItem := GetItem(ItemNo).GetBoolValue(rvbpHasSubRVData);
  1380.       end
  1381.     else begin
  1382.       RVData.GetOriginEx(BX,BY);
  1383.       GetOriginEx(AX,AY);
  1384.       X := X+AX-BX;
  1385.       Y := Y+AY-BY;
  1386.       RVData.GetItemAtEx(X,Y, RVData, ItemNo, OffsetInItem, Strict, InSubRVDataOwnerItem);
  1387.     end;
  1388.   end;
  1389. end;
  1390. {------------------------------------------------------------------------------}
  1391. function TCustomRVFormattedData.FindWordAt(var Word: String; X,Y: Integer;
  1392.   var StyleNo, ItemNo, Offs: Integer;
  1393.   var RVData: TCustomRVFormattedData): Boolean;
  1394. var no: Integer;
  1395.     arr: PRVIntegerArray;
  1396.     i,max,min,first,len: Integer;
  1397.     Canvas: TCanvas;
  1398.     ItemOptions: TRVItemOptions;
  1399.     item: TCustomRVItemInfo;
  1400.     ditem: TRVDrawLineInfo;
  1401.     AX, AY: Integer;
  1402.     ARVData: TCustomRVFormattedData;
  1403.     s: String;
  1404. begin
  1405.   Canvas := GetCanvas;
  1406.   Result := False;
  1407.   RVData := Self;
  1408.   no := FindDrawItemAtPos(X+GetZHOffs, Y+GetZVOffs);
  1409.   ItemNo := -1;
  1410.   if no<>-1 then begin
  1411.      ditem := DrawItems[no];
  1412.      ItemNo := ditem.ItemNo;
  1413.      Word   := Items[ItemNo];
  1414.      StyleNo := GetItemStyle(ItemNo);
  1415.      if StyleNo>=0 then begin
  1416.        GetRVStyle.ApplyStyle(Canvas, StyleNo, GetParaBiDiMode(GetItemPara(ItemNo)),
  1417.          rvflCanUseCustomPPI in Flags);
  1418.        ItemOptions := GetItemOptions(ItemNo);
  1419.        s := DrawItems.GetString(no,Items);
  1420.        s := RV_ReturnProcessedString(s, GetRVStyle.TextStyles[StyleNo],
  1421.          IsDrawItemLastOnWrappedLine(no), rvoShowSpecialCharacters in Options, False);
  1422.        GetMem(arr, (ditem.Length+2)*sizeof(Integer));
  1423.        try
  1424.          if (GetItemBiDiMode(ditem.ItemNo)<>rvbdUnspecified) and
  1425.             RVU_GetTextCaretPos(Canvas, s, arr, ItemOptions,
  1426.               ditem.Width{$IFNDEF RVDONOTUSEJUSTIFY}-DrawItems[no].SpaceBefore{$ENDIF}) then begin
  1427.            min := Abs(X-arr[0]-ditem.Left{$IFNDEF RVDONOTUSEJUSTIFY}-ditem.SpaceBefore{$ENDIF});
  1428.            max := 0;
  1429.            for i := 1 to ditem.Length do
  1430.              if Abs(X-arr[i]-ditem.Left{$IFNDEF RVDONOTUSEJUSTIFY}-ditem.SpaceBefore{$ENDIF})<min then begin
  1431.                max := i;
  1432.                min := Abs(X-arr[i]-ditem.Left{$IFNDEF RVDONOTUSEJUSTIFY}-ditem.SpaceBefore{$ENDIF});
  1433.              end;
  1434.            end
  1435.          else begin
  1436.            RVU_GetTextExtentExPoint(Canvas,  s, X+GetZHOffs-ditem.Left
  1437.              {$IFNDEF RVDONOTUSEJUSTIFY}-ditem.SpaceBefore{$ENDIF},
  1438.              max,
  1439.              {$IFDEF RICHVIEWDEF4}nil,{$ELSE}@(arr[0]),{$ENDIF} ItemOptions);
  1440.          end;
  1441.        finally
  1442.          FreeMem(arr);
  1443.        end;
  1444.        inc(max,DrawItems[no].Offs);
  1445.        if max>RVU_Length(Word,ItemOptions) then
  1446.          max := RVU_Length(Word,ItemOptions);
  1447.        first := max;
  1448.        if IsDelimiter(Word, first, ItemOptions) then begin
  1449.          Offs := First;
  1450.          Word := '';
  1451.          Result := True;
  1452.          exit;
  1453.        end;
  1454.        while (first>1) and not IsDelimiter(Word, first-1, ItemOptions) do
  1455.          dec(first);
  1456.        len := max-first+1;
  1457.        while (first+len-1<RVU_Length(Word,ItemOptions)) and
  1458.              not IsDelimiter(Word, first+len, ItemOptions) do
  1459.          inc(len);
  1460.        Word := RVU_Copy(Word, first, len, ItemOptions);
  1461.        Offs := First;
  1462.        end
  1463.      else begin
  1464.        item := GetItem(ItemNo);
  1465.        item.ResetSubCoords;
  1466.        GetItemClientCoords(ItemNo,AX,AY);
  1467.        ARVData := TCustomRVFormattedData(item.GetSubRVDataAt(X-AX,Y-AY));
  1468.        if ARVData<>nil then begin
  1469.          if ARVData.GetRVData.GetParentControl.Parent=GetParentControl then begin
  1470.            dec(X, ARVData.GetRVData.GetParentControl.Left);
  1471.            dec(Y, ARVData.GetRVData.GetParentControl.Top);
  1472.          end;
  1473.          Result := TCustomRVFormattedData(ARVData.GetRVData).FindWordAt(Word,
  1474.            X,Y,StyleNo,ItemNo,Offs, RVData);
  1475.          exit;
  1476.        end;
  1477.      end;
  1478.      Result := True;
  1479.   end;
  1480. end;
  1481. {------------------------------------------------------------------------------}
  1482. function TCustomRVFormattedData.GetEditor: TWinControl;
  1483. begin
  1484.   Result := nil;
  1485. end;
  1486. {------------------------------------------------------------------------------}
  1487. procedure TCustomRVFormattedData.ResetSubCoords;
  1488. begin
  1489. end;
  1490. {------------------------------------------------------------------------------}
  1491. { Selects the screen line containing (ItemNo, Offs) location.                  }
  1492. procedure TCustomRVFormattedData.SelectLine(ItemNo, Offs: Integer);
  1493. var DItemNo, DOffs: Integer;
  1494.     DStrt, DEnd: Integer;
  1495.     ItemNo1,ItemNo2,Offs1, Offs2: Integer;
  1496. begin
  1497.   Item2DrawItem(ItemNo,Offs,DItemNo,DOffs);
  1498.   DStrt := DItemNo;
  1499.   while not DrawItems[DStrt].FromNewLine do
  1500.     dec(DStrt);
  1501.   DEnd := DItemNo+1;
  1502.   while (DEnd<Items.Count) and not DrawItems[DEnd].FromNewLine do
  1503.     inc(DEnd);
  1504.   dec(DEnd);
  1505.   DrawItem2Item(DStrt, GetOffsBeforeDrawItem(Dstrt), ItemNo1, Offs1);
  1506.   DrawItem2Item(DEnd, GetOffsAfterDrawItem(DEnd), ItemNo2, Offs2);
  1507.   SetSelectionBounds(ItemNo1, Offs1, ItemNo2, Offs2);
  1508. end;
  1509. {------------------------------------------------------------------------------}
  1510. { Fills the list of soft page breaks by information form RVPrint (must be of
  1511.   TCustomRVPrint class).
  1512.   RVPrint must be formatted for printing.                                      }
  1513. procedure TCustomRVFormattedData.AssignSoftPageBreaks(RVPrint: TComponent);
  1514. var i: Integer;
  1515.     Item: TRVSoftPageBreakInfo;
  1516. begin
  1517.   ClearSoftPageBreaks;
  1518.   FSoftPageBreaks := TRVSoftPageBreakList.Create;
  1519.   for i := 1 to TCustomRVPrint(RVPrint).PagesCount do begin
  1520.     item := TRVSoftPageBreakInfo.Create;
  1521.     TCustomRVPrint(RVPrint).GetFirstItemOnPageEx(i, item.ItemNo, item.Offset,
  1522.       item.ExtraData);
  1523.     FSoftPageBreaks.Add(Item);
  1524.   end;
  1525.   if rvoShowPageBreaks in Options then
  1526.     Invalidate;
  1527. end;
  1528. {------------------------------------------------------------------------------}
  1529. { Clears, destorys and nils the list of soft page breaks                       }
  1530. function TCustomRVFormattedData.ClearSoftPageBreaks: Boolean;
  1531. begin
  1532.   Result := FSoftPageBreaks<>nil;
  1533.   if Result then begin
  1534.     FSoftPageBreaks.Free;
  1535.     FSoftPageBreaks := nil;
  1536.   end;
  1537. end;
  1538. {------------------------------------------------------------------------------}
  1539. { Returns a line number of location (ItemNo, ItemOffs). Line numbers are
  1540.   started from 1. Line number are counted from the beginning of each RVData.
  1541.   This method is relatively slow: iteration from the beginning of this RVData
  1542.   items.                                                                       }
  1543. function TCustomRVFormattedData.GetLineNo(ItemNo, ItemOffs: Integer): Integer;
  1544. var i, DItemNo, DItemOffs: Integer;
  1545. begin
  1546.   Item2DrawItem(ItemNo, ItemOffs, DItemNo, DItemOffs);
  1547.   Result := 0;
  1548.   for i := DItemNo downto 0 do
  1549.     if DrawItems[i].FromNewLine then
  1550.       inc(Result);
  1551. end;
  1552. {------------------------------------------------------------------------------}
  1553. { Called in MouseUp. Adjusts selection. Overriden in TRVEditRVData (where
  1554.   selects resizable item if needed)                                            } 
  1555. procedure TCustomRVFormattedData.AdjustMouseUpSelection;
  1556. begin
  1557. end;
  1558. {------------------------------------------------------------------------------}
  1559. { Searching for the item containing AControl and selecting it. Search is
  1560.   recursive, it includes nested RVData-s.                                      }
  1561. function TCustomRVFormattedData.SelectControl(AControl: TControl): Boolean;
  1562.     {........................................................}
  1563.     function SearchInItem(item: TCustomRVItemInfo): Boolean;
  1564.     var SubRVData: TCustomRVFormattedData;
  1565.         StoreSub: TRVStoreSubRVData;
  1566.     begin
  1567.       Result := False;
  1568.       SubRVData := TCustomRVFormattedData(item.GetSubRVData(StoreSub, rvdFirst));
  1569.       if SubRVData=nil then
  1570.         exit;
  1571.       repeat
  1572.         Result := TCustomRVFormattedData(SubRVData.GetRVData).SelectControl(AControl);
  1573.         if Result then
  1574.           break;
  1575.         SubRVData := TCustomRVFormattedData(item.GetSubRVData(StoreSub, rvdNext));
  1576.       until SubRVData=nil;
  1577.       StoreSub.Free;
  1578.     end;
  1579.     {........................................................}    
  1580. var i: Integer;
  1581.     RVData: TCustomRVFormattedData;
  1582. begin
  1583.   Result := False;
  1584.   for i := 0 to ItemCount-1 do
  1585.     if GetItemStyle(i)<0 then begin
  1586.       if (GetItem(i) is TRVControlItemInfo) and
  1587.          GetItem(i).OwnsControl(AControl) then begin
  1588.          RVData := TCustomRVFormattedData(Edit);
  1589.          RVData.SetSelectionBounds(i, 0, i, 1);
  1590.          RVData.Invalidate;
  1591.          Result := True;
  1592.          exit;
  1593.       end;
  1594.       Result := SearchInItem(GetItem(i));
  1595.       if Result then
  1596.         break;
  1597.     end;
  1598. end;
  1599. {------------------------------------------------------------------------------}
  1600. { Returns True if the position (DrawItemNo,DrawItemOffs) is inside a word      }
  1601. function TCustomRVFormattedData.InsideWord(DrawItemNo,
  1602.   DrawItemOffs: Integer): Boolean;
  1603. var s: String;
  1604.     StyleNo : Integer;
  1605.     ItemOptions: TRVItemOptions;
  1606. begin
  1607.   Result := False;
  1608.   StyleNo := GetDrawItemStyle(DrawItemNo);
  1609.   if (StyleNo<0) or
  1610.      (DrawItemOffs<=GetOffsBeforeDrawItem(DrawItemNo)) or
  1611.      (DrawItemOffs>=GetOffsAfterDrawItem(DrawItemNo)) then
  1612.     exit;
  1613.   s := DrawItems.GetString(DrawItemNo, Items);
  1614.   ItemOptions := GetItemOptions(DrawItems[DrawItemNo].ItemNo);
  1615.   Result := not IsDelimiter(s, DrawItemOffs-1, ItemOptions) and
  1616.             not IsDelimiter(s, DrawItemOffs, ItemOptions);
  1617. end;
  1618. {------------------------------------------------------------------------------}
  1619. { Returns bounds of word containing position (DrawItemNo,DrawItemOffs).
  1620.   Returns:
  1621.   DrawItemWordOffs1 - index of the first word character (1-based),
  1622.   DrawItemWordOffs2 - index of the first character after the word (1-based).
  1623.   This procedure assumes that position is inside word (check by InsideWord())  }
  1624. procedure TCustomRVFormattedData.GetWordBounds(DrawItemNo,
  1625.   DrawItemOffs: Integer; var DrawItemWordOffs1, DrawItemWordOffs2: Integer);
  1626. var s: String;
  1627.     ItemOptions: TRVItemOptions;
  1628.     Len: Integer;
  1629. begin
  1630.   s := DrawItems.GetString(DrawItemNo, Items);
  1631.   ItemOptions := GetItemOptions(DrawItems[DrawItemNo].ItemNo);
  1632.   DrawItemWordOffs1 := DrawItemOffs-1;
  1633.   while (DrawItemWordOffs1-1>0) and
  1634.         not IsDelimiter(s, DrawItemWordOffs1-1, ItemOptions) do
  1635.     dec(DrawItemWordOffs1);
  1636.   DrawItemWordOffs2 := DrawItemOffs;
  1637.   Len := RVU_Length(s, ItemOptions);
  1638.   while (DrawItemWordOffs2<=Len) and
  1639.         not IsDelimiter(s, DrawItemWordOffs2, ItemOptions) do
  1640.     inc(DrawItemWordOffs2);
  1641. end;
  1642. {------------------------------------------------------------------------------}
  1643. { Adjusts selection bounds depending on RVStyle.SelectionMode.
  1644.   (X,Y) is coordinate of mouse making selection (relative to the top left
  1645.   corner of the document).
  1646.   Returns True if the new selection bounds are different from their previous
  1647.   values.                                                                      }
  1648. function TCustomRVFormattedData.AdjustSelectionByMode(X, Y: Integer): Boolean;
  1649. var w1, w2: Integer;
  1650.     AdjustSelEnd: Boolean;
  1651.     OldSelSNo, OldSelENo, OldSelSOffs, OldSelEOffs: Integer;
  1652.     DrawItemNo, DrawItemOffs: Integer;
  1653.     {...........................................................}
  1654.     function IsSelectionChanged: Boolean;
  1655.     begin
  1656.       Result := (OldSelSNo<>FSelStartNo) or (OldSelENo<>FSelEndNo) or
  1657.         (OldSelSOffs<>FSelStartOffs) or (OldSelEOffs<>FSelEndOffs);
  1658.     end;
  1659.     {...........................................................}
  1660. begin
  1661.   GetSelectionBounds(OldSelSNo, OldSelSOffs, OldSelENo, OldSelEOffs, False);
  1662.   FindDrawItemForSel(X, Y, DrawItemNo, DrawItemOffs, False);
  1663.   if FSelectingInfo<>nil then begin
  1664.     if FSelectingInfo.SWordState=rvsesParaMode then begin
  1665.       FSelectingInfo.DrawItemENo := DrawItemNo;
  1666.       FSelectingInfo.DrawItemEOffs := DrawItemOffs;
  1667.       FSelStartNo   := FSelectingInfo.DrawItemSNo;
  1668.       FSelStartOffs := FSelectingInfo.DrawItemSOffs;
  1669.       FSelEndNo     := DrawItemNo;
  1670.       FSelEndOffs   := DrawItemOffs;
  1671.       ExpandSelectionToParagraph(True);
  1672.       Result := IsSelectionChanged;
  1673.       exit;
  1674.     end;
  1675.     AdjustSelEnd := True;
  1676.     // 1. Adjusting selection start
  1677.     case FSelectingInfo.SWordState of
  1678.       rvsesInWord: // mouse is inside the initial word
  1679.         begin
  1680.           // checking mouse leaving the initial word
  1681.           // when it leaves, setting SWordState := rvsesOutsideWord and
  1682.           // adjusting the selection start to the word bound
  1683.           if FSelectingInfo.IsAboveSWord(DrawItemNo, DrawItemOffs) then begin
  1684.             FSelectingInfo.SWordState := rvsesOutsideWord;
  1685.             FSelStartOffs := FSelectingInfo.DrawItemSWordOffs2;
  1686.             end
  1687.           else if FSelectingInfo.IsBelowSWord(DrawItemNo, DrawItemOffs) then begin
  1688.             FSelectingInfo.SWordState := rvsesOutsideWord;
  1689.             FSelStartOffs := FSelectingInfo.DrawItemSWordOffs1;
  1690.             end
  1691.           else
  1692.             AdjustSelEnd := False;
  1693.         end;
  1694.       rvsesOutsideWord: // mouse is outside the initial word
  1695.         begin
  1696.           // checking mouse returning to the initial word
  1697.           // when it returns, stopping adjusting the selection start,
  1698.           // setting SWordState := rvsesFreeMode
  1699.           if FSelectingInfo.IsInSWord(DrawItemNo, DrawItemOffs) then begin
  1700.             FSelStartOffs := FSelectingInfo.DrawItemSOffs;
  1701.             FSelectingInfo.SWordState := rvsesFreeMode;
  1702.             AdjustSelEnd := False;
  1703.           end;
  1704.         end;
  1705.     end;
  1706.     // 1. Adjusting selection end
  1707.     if AdjustSelEnd then begin
  1708.       if InsideWord(DrawItemNo, DrawItemOffs) then begin
  1709.         GetWordBounds(DrawItemNo, DrawItemOffs, w1, w2);
  1710.         if FSelectingInfo.IsEWord(DrawItemNo, w1, w2) then
  1711.           // mouse is in the same word as before
  1712.           case FSelectingInfo.EWordState of
  1713.             rvsesInWord:
  1714.               begin
  1715.                 // if it's moved in backward direction, allowing selection
  1716.                 // by characters (setting EWordState := rvsesFreeMode)
  1717.                 if FSelectingInfo.IsEFreeStateNeeded(DrawItemNo, DrawItemOffs) then begin
  1718.                   FSelectingInfo.EWordState := rvsesFreeMode;
  1719.                   AdjustSelEnd := False;
  1720.                   end
  1721.                 else
  1722.                 // if it's moved in forward direction, updating DrawItemEOffs
  1723.                   FSelectingInfo.DrawItemEOffs := DrawItemOffs;
  1724.               end;
  1725.             rvsesFreeMode:
  1726.               AdjustSelEnd := False;
  1727.           end
  1728.         else begin
  1729.           // mouse is entered a new word
  1730.           FSelectingInfo.EWordState := rvsesInWord;
  1731.           FSelectingInfo.DrawItemEWordOffs1 := w1;
  1732.           FSelectingInfo.DrawItemEWordOffs2 := w2;
  1733.           FSelectingInfo.DrawItemEOffs := DrawItemOffs;
  1734.         end;
  1735.         // adjusting the selection end
  1736.         if AdjustSelEnd then
  1737.           if FSelectingInfo.IsAboveSWord(DrawItemNo, DrawItemOffs) then begin
  1738.             DrawItemOffs := w1;
  1739.             end
  1740.           else if FSelectingInfo.IsBelowSWord(DrawItemNo, DrawItemOffs) then begin
  1741.             DrawItemOffs := w2;
  1742.           end;
  1743.         end
  1744.       else begin
  1745.         // mouse is outside word
  1746.         FSelectingInfo.EWordState := rvsesInWord;
  1747.         FSelectingInfo.DrawItemEWordOffs1 := -1;
  1748.         FSelectingInfo.DrawItemEWordOffs2 := -1;
  1749.       end;
  1750.     end;
  1751.   end;
  1752.   FSelEndNo := DrawItemNo;
  1753.   FSelEndOffs := DrawItemOffs;
  1754.   Result := IsSelectionChanged;
  1755. end;
  1756. {------------------------------------------------------------------------------}
  1757. { Making selection by lines.
  1758.   (X,Y) is coordinate of mouse making selection (relative to the top left
  1759.   corner of the document).                                                     }
  1760. function TCustomRVFormattedData.AdjustLineSelection(X, Y: Integer): Boolean;
  1761. var OldSelSNo, OldSelENo, OldSelSOffs, OldSelEOffs: Integer;
  1762.     {...........................................................}
  1763.     function IsSelectionChanged: Boolean;
  1764.     begin
  1765.       Result := (OldSelSNo<>FSelStartNo) or (OldSelENo<>FSelEndNo) or
  1766.         (OldSelSOffs<>FSelStartOffs) or (OldSelEOffs<>FSelEndOffs);
  1767.     end;
  1768.     {...........................................................}
  1769. begin
  1770.   GetSelectionBounds(OldSelSNo, OldSelSOffs, OldSelENo, OldSelEOffs, False);
  1771.   FindDrawItemForSel(X, Y, FSelEndNo, FSelEndOffs, False);
  1772.   ExpandSelectionToLines(False);
  1773.   if GetRVStyle.SelectionMode=rvsmParagraph then
  1774.     ExpandSelectionToParagraph(True);
  1775.   Result := IsSelectionChanged;
  1776. end;
  1777. {------------------------------------------------------------------------------}
  1778. { Expands the selection (if it is not empty) to the paragraphs boundaries
  1779.   Does nothing if OnlyIfMultiple=True and selection does not include
  1780.   more than 1 paragraph.                                                       }
  1781. function TCustomRVFormattedData.ExpandSelectionToParagraph(
  1782.   OnlyIfMultiple: Boolean): Boolean;
  1783.   {..........................................................}
  1784.   procedure ExpandUp(var DrawItemNo, DrawItemOffs: Integer);
  1785.   begin
  1786.     while DrawItemNo>0 do begin
  1787.       if IsDrawItemParaStart(DrawItemNo) then
  1788.         break;
  1789.       dec(DrawItemNo);
  1790.     end;
  1791.     DrawItemOffs := GetOffsBeforeDrawItem(DrawItemNo);
  1792.   end;
  1793.   {..........................................................}
  1794.   procedure ExpandDown(var DrawItemNo, DrawItemOffs: Integer);
  1795.   begin
  1796.     while DrawItemNo+1<DrawItems.Count do begin
  1797.       if IsDrawItemParaStart(DrawItemNo+1) then
  1798.         break;
  1799.       inc(DrawItemNo);
  1800.     end;
  1801.     DrawItemOffs := GetOffsAfterDrawItem(DrawItemNo);
  1802.   end;
  1803. begin
  1804.   Result := (FSelStartNo>=0) and
  1805.      not ((FSelStartNo=FSelEndNo) and (FSelStartOffs=FSelEndOffs));
  1806.   if not Result then
  1807.     exit;
  1808.   Result := not OnlyIfMultiple or IsMultiParagraphSelection;
  1809.   if not Result then
  1810.     exit;
  1811.   if IsSelectionTopDown then begin
  1812.     ExpandUp(FSelStartNo, FSelStartOffs);
  1813.     ExpandDown(FSelEndNo, FSelEndOffs);
  1814.     end
  1815.   else begin
  1816.     ExpandDown(FSelStartNo, FSelStartOffs);
  1817.     ExpandUp(FSelEndNo, FSelEndOffs);
  1818.   end;
  1819. end;
  1820. {------------------------------------------------------------------------------}
  1821. { If OneLine=False, expands selection to the lines boundaries.
  1822.   If OneLine=True, selects the line containing the beginning of selection,
  1823.   from the beginning to the end of the line                                    }
  1824. procedure TCustomRVFormattedData.ExpandSelectionToLines(OneLine: Boolean);
  1825. {..........................................................}
  1826.   procedure ExpandUp(var DrawItemNo, DrawItemOffs: Integer);
  1827.   begin
  1828.     while (DrawItemNo>0) and not DrawItems[DrawItemNo].FromNewLine do
  1829.       dec(DrawItemNo);
  1830.     DrawItemOffs := GetOffsBeforeDrawItem(DrawItemNo);
  1831.   end;
  1832.   {..........................................................}
  1833.   procedure ExpandDown(var DrawItemNo, DrawItemOffs: Integer);
  1834.   begin
  1835.     while (DrawItemNo+1<DrawItems.Count) and
  1836.       not DrawItems[DrawItemNo+1].FromNewLine do
  1837.       inc(DrawItemNo);
  1838.     DrawItemOffs := GetOffsAfterDrawItem(DrawItemNo);
  1839.   end;
  1840.   {..........................................................}
  1841. begin
  1842.   if FSelStartNo<0 then
  1843.     exit;
  1844.   if OneLine then begin
  1845.     FSelEndNo := FSelStartNo;
  1846.     ExpandUp(FSelStartNo, FSelStartOffs);
  1847.     ExpandDown(FSelEndNo, FSelEndOffs);
  1848.     end
  1849.   else begin
  1850.     if IsSelectionTopDown then begin
  1851.       ExpandUp(FSelStartNo, FSelStartOffs);
  1852.       ExpandDown(FSelEndNo, FSelEndOffs);
  1853.       end
  1854.     else begin
  1855.       ExpandDown(FSelStartNo, FSelStartOffs);
  1856.       ExpandUp(FSelEndNo, FSelEndOffs);
  1857.     end;
  1858.   end;
  1859. end;
  1860. {------------------------------------------------------------------------------}
  1861. { Returns True if the selection is in top-down direction.                     }
  1862. function TCustomRVFormattedData.IsSelectionTopDown: Boolean;
  1863. begin
  1864.   Result := (FSelStartNo<FSelEndNo) or
  1865.     ((FSelStartNo=FSelEndNo) and (FSelStartOffs<=FSelEndOffs));
  1866. end;
  1867. {------------------------------------------------------------------------------}
  1868. { Returns True if the drawing item starts a new paragraph.                     }
  1869. function TCustomRVFormattedData.IsDrawItemParaStart(DrawItemNo: Integer): Boolean;
  1870. begin
  1871.   Result := (DrawItemNo=0) or
  1872.     ((DrawItems[DrawItemNo].ItemNo<>DrawItems[DrawItemNo-1].ItemNo) and
  1873.      IsParaStart(DrawItems[DrawItemNo].ItemNo));
  1874. end;
  1875. {------------------------------------------------------------------------------}
  1876. { Returns True if the drawing item is the first drawing item for an item }
  1877. function TCustomRVFormattedData.IsDrawItemItemStart(DrawItemNo: Integer): Boolean;
  1878. begin
  1879.   Result := (DrawItemNo=0) or
  1880.     (DrawItems[DrawItemNo].ItemNo<>DrawItems[DrawItemNo-1].ItemNo);
  1881. end;
  1882. {------------------------------------------------------------------------------}
  1883. { Returns True if the drawing item starts a new paragraph or section inside
  1884.   paragraph }
  1885. function TCustomRVFormattedData.IsDrawItemParaSectionStart(DrawItemNo: Integer): Boolean;
  1886. begin
  1887.   Result := (DrawItemNo=0) or
  1888.     ((DrawItems[DrawItemNo].ItemNo<>DrawItems[DrawItemNo-1].ItemNo) and
  1889.      IsFromNewLine(DrawItems[DrawItemNo].ItemNo));
  1890. end;
  1891. {------------------------------------------------------------------------------}
  1892. { Returns True if the drawing item ends a paragraph.                           }
  1893. function TCustomRVFormattedData.IsDrawItemParaEnd(DrawItemNo: Integer): Boolean;
  1894. begin
  1895.   Result := (DrawItemNo=DrawItems.Count-1) or IsDrawItemParaStart(DrawItemNo+1);
  1896. end;
  1897. {------------------------------------------------------------------------------}
  1898. { Returns true, if the given DrawItem either starts a new line
  1899.   or follows a marker                                                          }
  1900. function TCustomRVFormattedData.IsDrawItemFromNewLine(DrawItemNo: Integer): Boolean;
  1901. begin
  1902.   Result := DrawItems[DrawItemNo].FromNewLine;
  1903.   {$IFNDEF RVDONOTUSELISTS}
  1904.   if not Result and (DrawItemNo>0) and
  1905.     (DrawItems[DrawItemNo].ItemNo<>DrawItems[DrawItemNo-1].ItemNo) and
  1906.     (GetDrawItemStyle(DrawItemNo-1)=rvsListMarker) then
  1907.     Result := True;
  1908.   {$ENDIF}
  1909. end;
  1910. {------------------------------------------------------------------------------}
  1911. { Returns true, if the given DrawItem is the last item on the line, and this
  1912.   line is not the last line of the paragraph }
  1913. function TCustomRVFormattedData.IsDrawItemLastOnWrappedLine(DrawItemNo: Integer): Boolean;
  1914. begin
  1915.   Result := (DrawItemNo<DrawItems.Count-1) and DrawItems[DrawItemNo+1].FromNewLine and
  1916.    not IsDrawItemParaSectionStart(DrawItemNo+1);
  1917. end;
  1918. {------------------------------------------------------------------------------}
  1919. { Returns the style of item associated with the given drawing item
  1920.   // Result := GetItemStyle(DrawItems[DrawItemNo].ItemNo)                      }
  1921. function TCustomRVFormattedData.GetDrawItemStyle(DrawItemNo: Integer): Integer;
  1922. begin
  1923.   Result := TCustomRVItemInfo(Items.Objects[DrawItems[DrawItemNo].ItemNo]).StyleNo;
  1924. end;
  1925. {------------------------------------------------------------------------------}
  1926. { Returns True if there is a character (space) missed between the DrawItemNo-th
  1927.   and the next drawing item }
  1928. function TCustomRVFormattedData.IsSpaceBetweenDrawItems(DrawItemNo: Integer): Boolean;
  1929. var ditem: TRVDrawLineInfo;
  1930. begin
  1931.   Result := False;
  1932.   ditem := DrawItems[DrawItemNo];
  1933.   if ditem.Offs+ditem.Length-1>=ItemLength(ditem.ItemNo) then
  1934.     exit;
  1935.   if (DrawItemNo+1<DrawItems.Count) and (DrawItems[DrawItemNo+1].ItemNo=ditem.ItemNo) and
  1936.      (DrawItems[DrawItemNo+1].Offs = ditem.Offs+ditem.Length) then
  1937.     exit;
  1938.   Result := True;
  1939. end;
  1940. {------------------------------------------------------------------------------}
  1941. { Returns True, if the selection includes more than one paragraphs (at least
  1942.   partially.                                                                   }
  1943. function TCustomRVFormattedData.IsMultiParagraphSelection: Boolean;
  1944. var StartDrawItemNo, EndDrawItemNo, i: Integer;
  1945. begin
  1946.   Result := FSelStartNo>=0;
  1947.   if not Result then
  1948.     exit;
  1949.   if IsSelectionTopDown then begin
  1950.     StartDrawItemNo := FSelStartNo;
  1951.     EndDrawItemNo   := FSelEndNo;
  1952.     end
  1953.   else begin
  1954.     StartDrawItemNo := FSelEndNo;
  1955.     EndDrawItemNo   := FSelStartNo;
  1956.   end;
  1957.   Result := False;
  1958.   for i := StartDrawItemNo+1 to EndDrawItemNo do
  1959.     if IsDrawItemParaStart(i) then begin
  1960.       Result := True;
  1961.       exit;
  1962.     end;
  1963. end;
  1964. {$IFNDEF RVDONOTUSEDRAGDROP}
  1965. {------------------------------------------------------------------------------}
  1966. { Drag&Drop: IDropTarget related                                               }
  1967. {------------------------------------------------------------------------------}
  1968. { Sets the position of drag&drop target to (X,Y).
  1969.   (X,Y) - client coordinates.
  1970.   Usually it's called for the root (or inplace editor's) RVData.
  1971.   Calls SetDragDropCaret for the RVData containing
  1972.   d&d caret. Redraws d&d caret. Scrolls to make it visible.                    }
  1973. procedure TCustomRVFormattedData.SetDragDropCaretTo(X,Y: Integer);
  1974. var RVData: TCustomRVFormattedData;
  1975.     ItemNo, Offs: Integer;
  1976.     DragDropCaretInfo: TRVDragDropCaretInfo;
  1977. var NoScroll: Boolean;
  1978. begin
  1979.   inc(X, GetHOffs);
  1980.   inc(Y, GetVOffs);
  1981.   DrawDragDropCaret(GetCanvas, False);
  1982.   GetItemAtEx(X,Y, RVData, ItemNo, Offs, False, NoScroll);
  1983.   if (RVData<>nil) and (ItemNo>=0) then
  1984.     RVData.SetDragDropCaret(ItemNo, Offs);
  1985.   DrawDragDropCaret(GetCanvas, False);
  1986.   if not NoScroll then begin
  1987.     DragDropCaretInfo := GetDragDropCaretInfo;
  1988.     if DragDropCaretInfo<>nil then
  1989.       with DragDropCaretInfo do
  1990.         TCustomRVFormattedData(RVData).ShowRectangle(X, Y, 1, Height);
  1991.   end;
  1992. end;
  1993. {------------------------------------------------------------------------------}
  1994. { Draw drag&drop caret. Usually called to remove it.                           }
  1995. procedure TCustomRVFormattedData.RemoveDragDropCaret;
  1996. begin
  1997.   DrawDragDropCaret(GetCanvas, False);
  1998. end;
  1999. {------------------------------------------------------------------------------}
  2000. { Sets the position of drag&drop caret
  2001.   (fills the field of GetDragDropCaretInfo)                                    }
  2002. procedure TCustomRVFormattedData.SetDragDropCaret(ItemNo, Offs: Integer);
  2003. var s: String;
  2004.     StyleNo, DItemNo, DOffs, max: Integer;
  2005.     ItemOptions: TRVItemOptions;
  2006.     arr: PRVIntegerArray;
  2007.     ditem: TRVDrawLineInfo;
  2008.     DragDropCaretInfo: TRVDragDropCaretInfo;
  2009. begin
  2010.   DragDropCaretInfo := GetDragDropCaretInfo;
  2011.   if DragDropCaretInfo=nil then
  2012.     exit;
  2013.   DragDropCaretInfo.RVData := Self;
  2014.   DragDropCaretInfo.ItemNo := ItemNo;
  2015.   DragDropCaretInfo.ItemOffs := Offs;
  2016.   StyleNo := GetActualStyle(GetItem(ItemNo));
  2017.   Item2DrawItem(ItemNo, Offs, DItemNo, DOffs);
  2018.   ditem := DrawItems[DItemNo];
  2019.   DragDropCaretInfo.Y := ditem.Top;
  2020.   DragDropCaretInfo.Height := ditem.Height;
  2021.   DragDropCaretInfo.X := ditem.Left;
  2022.   if (StyleNo>=0) and (ditem.Length>0) then begin
  2023.     GetRVStyle.ApplyStyle(GetCanvas, StyleNo, GetParaBiDiMode(GetItemPara(ItemNo)), True);
  2024.     ItemOptions := GetItemOptions(ItemNo);
  2025.     s := DrawItems.GetString(DItemNo,Items);
  2026.     s := RV_ReturnProcessedString(s, GetRVStyle.TextStyles[StyleNo],
  2027.       IsDrawItemLastOnWrappedLine(DItemNo), rvoShowSpecialCharacters in Options, False);
  2028.     GetMem(arr, (ditem.Length+2)*sizeof(Integer));
  2029.     try
  2030.       if (GetItemBiDiMode(ItemNo)=rvbdUnspecified) or
  2031.         not RVU_GetTextCaretPos(GetCanvas, s, arr, ItemOptions, ditem.Width-ditem.SpaceBefore) then begin
  2032.         if DOffs=1 then
  2033.           DragDropCaretInfo.X := ditem.Left
  2034.         else begin
  2035.           RVU_GetTextExtentExPoint(GetCanvas,  s, ditem.Width*10, max, arr, ItemOptions);
  2036.           DragDropCaretInfo.X := ditem.Left+arr[DOffs-2];
  2037.         end;
  2038.         end
  2039.       else
  2040.         DragDropCaretInfo.X := ditem.Left+arr[DOffs-1];
  2041.     finally
  2042.       FreeMem(arr);
  2043.     end;
  2044.     end
  2045.   else if Offs<=GetOffsBeforeItem(ItemNo) then
  2046.     DragDropCaretInfo.X := ditem.Left
  2047.   else
  2048.     DragDropCaretInfo.X := ditem.Left+ditem.Width;
  2049. end;
  2050. {------------------------------------------------------------------------------}
  2051. { Returns information about drag&drop caret location.
  2052.   Returned value <> nil only if dragging to this RichViewEdit is in process.
  2053.   Physically, returned object is a field of the root TRichViewEdit.
  2054.   This method is overriden in TRVEditRVData and
  2055.   in TRichViewRVData (returns nil)                                             }
  2056. function TCustomRVFormattedData.GetDragDropCaretInfo: TRVDragDropCaretInfo;
  2057. begin
  2058.   Result := TCustomRVFormattedData(GetAbsoluteRootData).GetDragDropCaretInfo;
  2059. end;
  2060. {------------------------------------------------------------------------------}
  2061. { Drawing drag&drop caret (using inverted color).
  2062.   Draws something only when d&d cursor is above the editor.
  2063.   If OnlyForSelf, drawing is performed only if this RVData contains
  2064.   d&d caret. Otherwise, drawing is performed by RVData contained d&d caret.
  2065.   Canvas - canvas for drawing to. If drawing is performed not by this RVData,
  2066.   its own Canvas is used instead.                                              }
  2067. procedure TCustomRVFormattedData.DrawDragDropCaret(Canvas: TCanvas;
  2068.   OnlyForSelf: Boolean);
  2069. var DragDropCaretInfo: TRVDragDropCaretInfo;
  2070.     i: Integer;
  2071.     dx,dy: Integer;
  2072. begin
  2073.   DragDropCaretInfo := GetDragDropCaretInfo;
  2074.   if (DragDropCaretInfo=nil) or (DragDropCaretInfo.RVData=nil) then
  2075.     exit;
  2076.   if (DragDropCaretInfo.RVData<>Self) then begin
  2077.     if not OnlyForSelf then
  2078.       TCustomRVFormattedData(DragDropCaretInfo.RVData).DrawDragDropCaret(
  2079.         TCustomRVFormattedData(DragDropCaretInfo.RVData).GetCanvas, True);
  2080.     exit;
  2081.   end;
  2082.   Canvas.Pen.Mode := pmNot;
  2083.   Canvas.Pen.Width := 1;
  2084.   Canvas.Brush.Style := bsClear;
  2085.   Canvas.Pen.Style := psDot;
  2086.   GetOrigin(dx,dy);
  2087.   dec(dy, GetRVDataExtraVOffs);  
  2088.   dec(dx, TCustomRVFormattedData(GetRootData).GetHOffs);
  2089.   dec(dy, TCustomRVFormattedData(GetRootData).GetVOffs);
  2090.   for i := DragDropCaretInfo.Y+dy to DragDropCaretInfo.Y+DragDropCaretInfo.Height+dy do
  2091.     if i mod 2=0 then begin
  2092.       Canvas.MoveTo(dx+DragDropCaretInfo.X,i);
  2093.       Canvas.LineTo(dx+DragDropCaretInfo.X+2,i);
  2094.     end;
  2095.   Canvas.Pen.Style := psSolid;
  2096.   Canvas.Pen.Mode := pmCopy;
  2097. end;
  2098. {------------------------------------------------------------------------------}
  2099. { Drag&Drop: IDropSource related                                               }
  2100. {------------------------------------------------------------------------------}
  2101. { Can dragging from this TRichView be started?
  2102.   Overriden in TRichViewRVData.                                                }
  2103. function TCustomRVFormattedData.CanStartDragging: Boolean;
  2104. begin
  2105.   Result := TCustomRVFormattedData(GetAbsoluteRootData).CanStartDragging;
  2106. end;
  2107. {------------------------------------------------------------------------------}
  2108. { Is dragging from this TRichView in process? Overriden in TRichViewRVData.    }
  2109. function TCustomRVFormattedData.IsDragging: Boolean;
  2110. begin
  2111.   Result := TCustomRVFormattedData(GetAbsoluteRootData).IsDragging;
  2112. end;
  2113. {------------------------------------------------------------------------------}
  2114. { Initializing dragging. Overriden in TRichViewRVData.
  2115.   Returns True on success.
  2116.   Returns DropSource and OKEffect for call of DoDragDrop.                      }
  2117. function TCustomRVFormattedData.InitDragging(var DropSource: TRVDropSource;
  2118.   var OKEffect: Integer): Boolean;
  2119. begin
  2120.   Result := TCustomRVFormattedData(GetAbsoluteRootData).InitDragging(DropSource, OKEffect);
  2121. end;
  2122. {------------------------------------------------------------------------------}
  2123. { Finalizing dragging. Overriden in TRichViewRVData.                           }
  2124. procedure TCustomRVFormattedData.DoneDragging(FDeleteSelection: Boolean);
  2125. begin
  2126.   TCustomRVFormattedData(GetAbsoluteRootData).DoneDragging(FDeleteSelection);
  2127. end;
  2128. {------------------------------------------------------------------------------}
  2129. { Perform drag & drop from this RVData (called only for absolute root RVData)  }
  2130. procedure TCustomRVFormattedData.DoDrag;
  2131. var Effect, OKEffect: LongInt;
  2132.     DropSource: TRVDropSource;
  2133.     pt: TPoint;
  2134.     RVData: TCustomRVFormattedData;
  2135.     ItemNo, Offs: Integer;
  2136.     Dummy: Boolean;
  2137. begin
  2138.   State := State-[rvstStartingDragDrop]+
  2139.     [rvstCanDragDropDeleteSelection,rvstDragDropCursorNotMoved];
  2140.   try
  2141.     if InitDragging(DropSource, OKEffect) then begin
  2142.       DoDragDrop(DropSource as IDataObject, DropSource as IDropSource,
  2143.         OKEffect, Effect);
  2144.       DoneDragging((Effect=DROPEFFECT_MOVE) and (rvstCanDragDropDeleteSelection in State));
  2145.       if (Effect=DROPEFFECT_NONE) and (rvstDragDropCursorNotMoved in State) then begin
  2146.         GetCursorPos(pt);
  2147.         pt := GetParentControl.ScreenToClient(pt);
  2148.         GetItemAtEx(pt.X+GetHOffs,pt.Y+GetVOffs, RVData, ItemNo, Offs, False, Dummy);
  2149.         if ItemNo>=0 then begin
  2150.           RVData := TCustomRVFormattedData(RVData.Edit);
  2151.           RVData.SetSelectionBounds(ItemNo, Offs, ItemNo, Offs);
  2152.           RVData.Invalidate;
  2153.         end;
  2154.         {
  2155.         MouseDown(mbLeft, [ssLeft], pt.X, pt.Y);
  2156.         MouseUp(mbLeft, [], pt.X, pt.Y);
  2157.         }
  2158.       end;
  2159.     end;
  2160.   finally
  2161.     State := State-[rvstCanDragDropDeleteSelection,rvstDragDropCursorNotMoved];
  2162.   end;
  2163. end;
  2164. {$ENDIF}
  2165. {------------------------------------------------------------------------------}
  2166. { Returns true, if insertion in the specified location is possible.
  2167.   Used by drag&drop functions.                                                 }
  2168. function TCustomRVFormattedData.CanInsertHere(ItemNo, Offs: Integer): Boolean;
  2169. begin
  2170.   Result := False;
  2171.   if IsItemParaProtected(ItemNo) then
  2172.     exit;
  2173.   if Offs<=GetOffsBeforeItem(ItemNo) then
  2174.     Result := not IsSticking(ItemNo-1, True)
  2175.   else if Offs>=GetOffsAfterItem(ItemNo) then
  2176.     Result := not IsSticking(ItemNo, True)
  2177.   else
  2178.     Result := not IsProtected(ItemNo, rvprModifyProtect);
  2179. end;
  2180. {------------------------------------------------------------------------------}
  2181. { Returns true if the ItemNo-th item has the specified protection.
  2182.   There is a special processing of rvprDeleteProtect - for non-text items,
  2183.   their DeleteProtect property is returned.
  2184.   This function used in editor and by CanInsertHere().                         }
  2185. function TCustomRVFormattedData.IsProtected(ItemNo: Integer;
  2186.   Option: TRVProtectOption): Boolean;
  2187. var item: TCustomRVItemInfo;
  2188.     TextStyleNo: Integer;
  2189. begin
  2190.   item := GetItem(ItemNo);
  2191.   if item.StyleNo>=0 then
  2192.     Result := Option in GetRVStyle.TextStyles[GetActualStyle(item)].Protection
  2193.   else begin
  2194.     TextStyleNo := item.AssociatedTextStyleNo;
  2195.     if TextStyleNo>=0 then
  2196.       Result := Option in GetRVStyle.TextStyles[TextStyleNo].Protection
  2197.     else
  2198.       Result := False;
  2199.     if Option = rvprDeleteProtect then
  2200.       Result := Result or TRVNonTextItemInfo(item).DeleteProtect
  2201.   end;
  2202. end;
  2203. {------------------------------------------------------------------------------}
  2204. { Returns true if the ParaNo-th paragraph style has the specified option.
  2205.   This function used in editor and by CanInsertHere().                         }
  2206. function TCustomRVFormattedData.IsParaProtected(ParaNo: Integer;
  2207.   Option: TRVParaOption): Boolean;
  2208. begin
  2209.   Result := Option in GetRVStyle.ParaStyles[ParaNo].Options;
  2210. end;
  2211. {------------------------------------------------------------------------------}
  2212. { Returns true if the ItemNo-th item's paragraph style is read-only.
  2213.   This function used in editor and by CanInsertHere().                         }
  2214. function TCustomRVFormattedData.IsItemParaProtected(ItemNo: Integer): Boolean;
  2215. begin
  2216.   Result := IsParaProtected(GetItemPara(ItemNo), rvpaoReadOnly);
  2217. end;
  2218. {------------------------------------------------------------------------------}
  2219. { Returns true if insertion between FirstItemNo and (FirstItemNo+1) items is
  2220.   forbidden.
  2221.   FirstItemNo=-1 and FirstItemNo=Items.Count-1 are valid indices.
  2222.   This function used in editor and by CanInsertHere().
  2223.   If the function returns True and not NoSound, the function beeps             }
  2224. function TCustomRVFormattedData.IsSticking(FirstItemNo: Integer;
  2225.   NoSound: Boolean): Boolean;
  2226. begin
  2227.   if (FirstItemNo=-1) then
  2228.     Result := IsProtected(0, rvprStickToTop)
  2229.   else if (FirstItemNo=Items.Count-1) then
  2230.     Result := IsProtected(FirstItemNo, rvprStickToBottom)
  2231.   else
  2232.     Result := IsProtected(FirstItemNo, rvprSticking) and
  2233.               IsProtected(FirstItemNo+1, rvprSticking);
  2234.   if Result and not NoSound then
  2235.     Beep;
  2236. end;
  2237. {------------------------------------------------------------------------------}
  2238. {$IFNDEF RVDONOTUSELIVESPELL}
  2239. procedure TCustomRVFormattedData.LiveSpellingCheckCurrentItem;
  2240. begin
  2241.   if not (rvflRoot in Flags) then
  2242.     TCustomRVFormattedData(GetAbsoluteRootData).LiveSpellingCheckCurrentItem;
  2243. end;
  2244. {$ENDIF}
  2245. {------------------------------------------------------------------------------}
  2246. {$IFNDEF RVDONOTUSEANIMATION}
  2247. procedure TCustomRVFormattedData.InsertAnimator(var Animator: TObject);
  2248. begin
  2249.   TCustomRVFormattedData(GetAbsoluteRootData).InsertAnimator(Animator);
  2250. end;
  2251. {------------------------------------------------------------------------------}
  2252. function TCustomRVFormattedData.AllowAnimation: Boolean;
  2253. begin
  2254.   Result := TCustomRVFormattedData(GetAbsoluteRootData).AllowAnimation;
  2255. end;
  2256. {------------------------------------------------------------------------------}
  2257. procedure TCustomRVFormattedData.ResetAniBackground;
  2258. begin
  2259.   TCustomRVFormattedData(GetAbsoluteRootData).ResetAniBackground;
  2260. end;
  2261. {$ENDIF}
  2262. {------------------------------------------------------------------------------}
  2263. {$IFNDEF RVDONOTUSESMARTPOPUP}
  2264. procedure TCustomRVFormattedData.AdjustSpecialControlsCoords(
  2265.   RVData: TCustomRVFormattedData);
  2266. begin
  2267. end;
  2268. {$ENDIF}
  2269. {------------------------------------------------------------------------------}
  2270. procedure TCustomRVFormattedData.CreateFontInfoCache(ACanvas: TCanvas);
  2271. begin
  2272. end;
  2273. {------------------------------------------------------------------------------}
  2274. procedure TCustomRVFormattedData.DestroyFontInfoCache(var Cache: TRVFontInfoCache);
  2275. begin
  2276.   if (Cache<>nil) and (Cache.FOwner=Self) then begin
  2277.     Cache.Free;
  2278.     Cache := nil;
  2279.   end;
  2280. end;
  2281. {------------------------------------------------------------------------------}
  2282. function TCustomRVFormattedData.GetFontInfoCache(ACanvas: TCanvas;
  2283.   RVData: TCustomRVFormattedData): TRVFontInfoCache;
  2284. begin
  2285.   Result := TCustomRVFormattedData(GetRootData).GetFontInfoCache(ACanvas,Self);
  2286. end;
  2287. {=========================== TRVFontInfoCache =================================}
  2288. constructor TRVFontInfoCache.Create(const AData: TCustomRVFormattedData;
  2289.   const ARVStyle: TRVStyle; const ACanvas: TCanvas; ACanUseCustomPPI: Boolean);
  2290. var i: Integer;
  2291. begin
  2292.   FRVStyle := ARVStyle;
  2293.   FCanvas := ACanvas;
  2294.   FCanUseCustomPPI := ACanUseCustomPPI;
  2295.   FOwner := AData;
  2296.   LastTextStyle := -1;
  2297.   Capacity := ARVStyle.TextStyles.Count;
  2298.   for i := 0 to ARVStyle.TextStyles.Count-1 do
  2299.     Add(nil);
  2300. end;
  2301. end.