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

RichEdit

开发平台:

Delphi

  1.      DocumentWidth := max(
  2.                GetWidth-(sad.LeftMargin+sad.RightMargin),
  3.                CalculateMinDocWidthPlus(@sad, Canvas)
  4.               );
  5.      DevMinTextWidth := MulDiv(GetMinTextWidth,  sad.ppixDevice, sad.ppixScreen);
  6.      DevMaxTextWidth := MulDiv(GetMaxTextWidth,  sad.ppixDevice, sad.ppixScreen);
  7.      if DocumentWidth<DevMinTextWidth then DocumentWidth := DevMinTextWidth;
  8.      if rvoClientTextWidth in Options then begin { widths of pictures and maxtextwidth are ignored }
  9.        TextWidth := GetWidth-(sad.LeftMargin+sad.RightMargin);
  10.        if TextWidth<DevMinTextWidth then TextWidth := DevMinTextWidth;
  11.        end
  12.      else begin
  13.         if (DocumentWidth > DevMaxTextWidth{-(sad.LeftMargin+sad.RightMargin)}) and (GetMaxTextWidth>0) then
  14.           TextWidth := DevMaxTextWidth//-(sad.LeftMargin+sad.RightMargin)
  15.         else
  16.           TextWidth := DocumentWidth;
  17.      end;
  18.      if not (OnlyResized and (TextWidth=OldTextWidth) and (DocumentWidth=OldDocumentWidth)) or ForceFormat then begin
  19.        if OnlyTail then begin
  20.           StartLine := LastItemFormatted+1;
  21.           Params.baseline := DocumentHeight-GetBottomMargin;
  22.           if LastItemFormatted>=0 then
  23.             dec(Params.baseline,
  24.               RV_XToDevice(GetRVStyle.ParaStyles[GetItemPara(LastItemFormatted)].SpaceAfter, sad));
  25.           end
  26.        else begin
  27.           StartLine := 0;
  28.           Params.baseline  := GetTopMargin;
  29.           ClearTemporal;
  30.        end;
  31.        Params.x:=0;
  32.        Params.prevdesc :=0;
  33.        Params.LastDrawItem := DrawItems.Count;
  34.        Params.DontFSL := True;
  35.        Params.LineWidth := -1;
  36.        Params.FirstIndent := 0;
  37.        RVStyle   := GetRVStyle;       
  38.        CreateFontInfoCache(Canvas);
  39.        Params.FontInfoCache := GetFontInfoCache(Canvas, Self);
  40.        Params.FormatCanvas := Canvas;
  41.        Params.FormatCanvasHandle := Canvas.Handle;
  42.        for i:=StartLine to Items.Count-1 do
  43.          with TCustomRVItemInfo(Items.Objects[i]) do begin
  44.            if not SameAsPrev and not BR then
  45.              Params.FirstParaItemNo := i;
  46.            if StyleNo>=0 then
  47.              if RVStyle.ParaStyles[ParaNo].Alignment = rvaJustify then
  48.                FormatWords(i, Canvas, sad, Params)
  49.              else
  50.                FormatLine(
  51.                  RV_ReturnProcessedString(Items[i],
  52.                    RVStyle.TextStyles[GetActualStyleNo(RVStyle)], False,
  53.                      rvoShowSpecialCharacters in Options, False),
  54.                  Items[i], 0,
  55.                  {$IFNDEF RVDONOTUSEUNICODE}
  56.                  RVU_Length(Items[i], ItemOptions),
  57.                  {$ELSE}
  58.                  Length(Items[i]),
  59.                  {$ENDIF}
  60.                  i, Canvas, sad, Params)
  61.            else
  62.                FormatLine('', '', 0, Length(Items[i]), i, Canvas, sad, Params)
  63.          end;
  64.        UpdateLastTab(Params);
  65.        FinishScreenLine(sad, Params.LineWidth+Params.FirstIndent, Params.LastDrawItem,
  66.          not (rvstLastParaAborted in State), ExtraSpaceBelowLine, Params.DontFSL,
  67.          Params.FormatCanvas);
  68.        DestroyFontInfoCache(Params.FontInfoCache);
  69.        DocumentHeight := Params.baseline+Params.prevdesc+GetBottomMargin+ExtraSpaceBelowLine;
  70.        if Items.Count>0 then
  71.          inc(DocumentHeight,
  72.            MulDiv(GetRVStyle.ParaStyles[GetItemPara(Items.Count-1)].SpaceAfter,
  73.              sad.ppiyDevice, sad.ppiyScreen));
  74.        AdjustVScrollUnits;
  75.        AdjustJumpsCoords;
  76.        end
  77.      else;
  78.       // AdjustChildrenCoords;
  79.      cw := GetWidth;
  80.      ch := GetHeight;
  81.      AlreadyFormatted := True;
  82.      SetDocumentAreaSize(DocumentWidth+GetLeftMargin+GetRightMargin, DocumentHeight, True);
  83.      AlreadyFormatted := False;
  84.      if (cw<>GetWidth) or (ch<>GetHeight) then begin
  85.        //EndFormatting;
  86.        //ScrollTo(OldY);
  87.        EndFormatting;
  88.        Format_(OnlyResized, ForceFormat, False, depth+1, Canvas, False,
  89.          NoCaching, Reformatting);
  90.        StartFormatting;
  91.      end;
  92.      if (depth=0) then begin
  93.        if OnlyResized and not NoScroll then begin
  94.          FV := FindDrawItemByItem(FV);
  95.          if FV<>-1 then
  96.            ScrollTo(DrawItems[FV].Top+DeltaFV,False)
  97.          else
  98.            ScrollTo(0,False);
  99.        end;
  100.        AdjustChildrenCoords;
  101.        if OnlyTail then begin
  102.          if rvoScrollToEnd in Options then
  103.            ScrollTo(DocumentHeight,False)
  104.          else
  105.            ScrollTo(FV,False);
  106.   //       AdjustChildrenCoords;
  107.        end;
  108.        if OnlyResized then
  109.          RestoreSelBounds(StartNo, EndNo, StartOffs, EndOffs);
  110.      end;
  111.    finally
  112.      if (depth=0) then begin
  113.        EndFormatting;
  114.        LastItemFormatted := Items.Count-1;
  115.        Formatted(0,Items.Count-1, False); // <- wrong for FormatTail
  116.      end;
  117.    end;
  118. end;
  119. {------------------------------------------------------------------------------}
  120. procedure TCustomRVFormattedData.GetSelBounds(var StartNo, EndNo,
  121.   StartOffs, EndOffs: Integer; Normalize: Boolean);
  122. begin
  123.   if not Normalize or (FSelStartNo <= FSelEndNo) then begin
  124.     StartNo := FSelStartNo;
  125.     EndNo   := FSelEndNo;
  126.     if not Normalize or not ((StartNo=EndNo) and (FSelStartOffs>FSelEndOffs)) then begin
  127.       StartOffs := FSelStartOffs;
  128.       EndOffs   := FSelEndOffs;
  129.       end
  130.     else begin
  131.       StartOffs := FSelEndOffs;
  132.       EndOffs   := FSelStartOffs;
  133.     end;
  134.     end
  135.   else begin
  136.     StartNo := FSelEndNo;
  137.     EndNo   := FSelStartNo;
  138.     StartOffs := FSelEndOffs;
  139.     EndOffs   := FSelStartOffs;
  140.   end;
  141. end;
  142. {------------------------------------------------------------------------------}
  143. procedure TCustomRVFormattedData.GetScreenLineBounds(DrawItemNo: Integer;
  144.                                                      var First, Last: Integer);
  145. begin
  146.   First := DrawItemNo;
  147.   while (First>0) and not DrawItems[First].FromNewLine do
  148.     dec(First);
  149.   Last := DrawItemNo+1;
  150.   while (Last<DrawItems.Count) and not DrawItems[Last].FromNewLine do
  151.     inc(Last);
  152.   dec(Last);
  153. end;
  154. {------------------------------------------------------------------------------}
  155. var SortDrawItems: TRVDrawLines;
  156. function CompareCoords(Item1, Item2: Pointer): Integer;
  157. begin
  158.   Result := SortDrawItems[Integer(Item1)].Left-SortDrawItems[Integer(Item2)].Left;
  159. end;
  160. procedure TCustomRVFormattedData.FindDrawItemForSel(X,Y: Integer;
  161.                                   var No, Offs: Integer;
  162.                                   Strict: Boolean);
  163. var
  164.     styleno,i, a,b,mid, midtop, midbottom, midleft, midright, beginline, endline,
  165.     min, minsign, cur: Integer;
  166.     firstinline,lastinline, delta: Integer;
  167.     dli: TRVDrawLineInfo;
  168.     arr: PRVIntegerArray;
  169.     Canvas: TCanvas;
  170.     s: String;
  171.     BiDiMode:TRVBiDiMode;
  172.     order, revorder: TRVIntegerList;
  173. begin
  174.   Canvas := GetCanvas;
  175.   No := -1;
  176.   Offs := -1;
  177.   if DrawItems.Count = 0 then
  178.     exit;
  179.   dli := DrawItems[0];
  180.   if (dli.Top+dli.Height>Y) then
  181.     mid := 0
  182.   else begin
  183.     a := 1;
  184.     b := DrawItems.Count-1;
  185.     while (b-a)>1 do begin
  186.       mid := (a+b) div 2;
  187.       if (DrawItems[mid].Top<=Y) then
  188.         a := mid
  189.       else
  190.         b := mid;
  191.     end;
  192.     mid := a;
  193.     if DrawItems[b].Top<=Y then mid := b;
  194.   end;
  195.   GetScreenLineBounds(mid, beginline, endline);
  196.   if endline<>DrawItems.Count-1 then begin
  197.     // may be the next line is better?
  198.     b := endline+2;
  199.     while b<DrawItems.Count do begin
  200.       if DrawItems[b].FromNewLine then break;
  201.       inc(b);
  202.     end;
  203.     dec(b);
  204.     a := mid;
  205.     for i := endline+1 to b do
  206.       if DrawItems[i].Top<=Y then begin
  207.         a := i;
  208.         break;
  209.       end;
  210.     if a<>mid then begin
  211.       beginline := endline+1;
  212.       endline   := b;
  213.     end;
  214.   end;
  215.   // calculating line bounds (in pixels)
  216.   midtop    := DrawItems[mid].Top;
  217.   midbottom := midtop + DrawItems[mid].Height;
  218.   midleft   := DrawItems[mid].Left;
  219.   midright  := midleft+DrawItems[mid].Width;
  220.   for i:= beginline to endline do begin
  221.     dli := DrawItems[i];
  222.     if dli.Top < midtop then midtop := dli.Top;
  223.     if dli.Top + dli.Height > midbottom then midbottom := dli.Top + dli.Height;
  224.     if dli.Left < midleft then midleft := dli.Left;
  225.     if dli.Left + dli.Width > midright then midright := dli.Left + dli.Width;
  226.   end;
  227.   BiDiMode := GetParaBiDiMode(GetItemPara(DrawItems[beginline].ItemNo));
  228.   if BiDiMode<>rvbdUnspecified then begin
  229.     order := TRVIntegerList.Create;
  230.     for i:= beginline to endline do
  231.       order.Add(i);
  232.     SortDrawItems := DrawItems;
  233.     TList(order).Sort(CompareCoords);
  234.     SortDrawItems := nil;
  235.     revorder := TRVIntegerList.CreateEx(endline-beginline+1,0);
  236.     for i:= beginline to endline do
  237.       revorder[order[i-beginline]-beginline] := i;
  238.     end
  239.   else begin
  240.     order := nil;
  241.     revorder := nil;
  242.   end;
  243.   if BiDiMode=rvbdRightToLeft then begin
  244.     firstinline := endline;
  245.     lastinline  := beginline;
  246.     delta       := -1;
  247.     end
  248.   else begin
  249.     firstinline := beginline;
  250.     lastinline  := endline;
  251.     delta       := +1;
  252.   end;
  253.   for i:= beginline to endline do begin
  254.     dli := DrawItems[i];
  255.     if (
  256.          (Strict and (dli.Left<=X) and (dli.Left+dli.Width>X) and (Y>=dli.Top) and (Y<=dli.Top+dli.Height))
  257.        or
  258.          (not Strict and (order=nil) and
  259.           (
  260.            ((dli.Left<=X) and ((i=lastinline) or (DrawItems[i+delta].Left>X)))
  261.            or
  262.            ((i=firstinline) and (X<dli.Left))
  263.            )
  264.          )
  265.        or
  266.          (not Strict and (order<>nil) and
  267.           (
  268.            ((dli.Left<=X) and ((revorder[i-beginline]=endline) or (DrawItems[order[revorder[i-beginline]-beginline+1]].Left>X)))
  269.            or
  270.            ((revorder[i-beginline]=beginline) and (X<dli.Left))
  271.            )
  272.          )
  273.        )
  274.        then begin
  275.       styleno := GetItemStyle(dli.ItemNo);
  276.       No := i;
  277.       Offs := 0;
  278.       if styleno>=0 then begin
  279.         GetRVStyle.ApplyStyle(Canvas, StyleNo, GetParaBiDiMode(GetItemPara(dli.ItemNo)), True);
  280.         s := DrawItems.GetString(i,Items);
  281.         s := RV_ReturnProcessedString(s, GetRVStyle.TextStyles[StyleNo],
  282.           IsDrawItemLastOnWrappedLine(i), rvoShowSpecialCharacters in Options, False);
  283.         if Length(s)>0 then begin
  284.           GetMem(arr, (dli.Length+2)*sizeof(Integer));
  285.           try
  286.             if (GetItemBiDiMode(dli.ItemNo)<>rvbdUnspecified) and
  287.                RVU_GetTextCaretPos(Canvas, s, arr, GetItemOptions(dli.ItemNo),
  288.                  dli.Width{$IFNDEF RVDONOTUSEJUSTIFY}-dli.SpaceBefore{$ENDIF}) then begin
  289.               min := Abs(X-arr[0]-dli.Left{$IFNDEF RVDONOTUSEJUSTIFY}-dli.SpaceBefore{$ENDIF});
  290.               offs := 0;
  291.               for a := 0 to dli.Length do
  292.                 if Abs(X-arr[a]-dli.Left{$IFNDEF RVDONOTUSEJUSTIFY}-dli.SpaceBefore{$ENDIF})<min then begin
  293.                   Offs := a;
  294.                   min := Abs(X-arr[a]-dli.Left{$IFNDEF RVDONOTUSEJUSTIFY}-dli.SpaceBefore{$ENDIF});
  295.                 end;
  296.               if (Offs<Length(s)) and (Offs>0)and (NextCharStr(s, dli.ItemNo, Offs)>Offs+1) then
  297.                 Offs := NextCharStr(s, dli.ItemNo, Offs)-1;
  298.               end
  299.             else begin
  300.               RVU_GetTextExtentExPoint(Canvas, s,
  301.                                    dli.Width*10, b, arr,
  302.                                    TCustomRVItemInfo(Items.Objects[dli.ItemNo]).ItemOptions);
  303.               minsign := X-dli.Left;
  304.               min := Abs(minsign);
  305.               offs := 0;
  306.               for a := 1 to b do begin
  307.                 cur := X-arr[a-1]-dli.Left{$IFNDEF RVDONOTUSEJUSTIFY}-dli.SpaceBefore{$ENDIF};
  308.                 if (abs(cur)<min) or
  309.                    ((abs(cur)=min) and
  310.                     (((cur<0) and (BiDiMode=rvbdRightToLeft)) or
  311.                      ((cur>=0) and (BiDiMode<>rvbdRightToLeft)))) then begin
  312.                   Offs := a;
  313.                   minsign := cur;
  314.                   min := Abs(minsign);
  315.                 end;
  316.               end;
  317.               if (Offs<Length(s)) and (Offs>0)and (NextCharStr(s, dli.ItemNo, Offs)>Offs+1) then
  318.                 Offs := NextCharStr(s, dli.ItemNo, Offs)-1;
  319.             end;
  320.             inc(Offs);
  321.             if Offs>DrawItems[i].Length+1 then
  322.               Offs := DrawItems[i].Length+1;
  323.             if (Offs < 1) and (DrawItems[i].Length>0) then
  324.               Offs := 1;
  325.           finally
  326.             FreeMem(arr);
  327.           end;
  328.           end
  329.         else begin
  330.           Offs := 1;
  331.         end;
  332.         end
  333.       else begin
  334.         Offs := (1-delta) div 2; 
  335.         if X > dli.Left + dli.Width div 2 then begin
  336.           {State := State + [rvstClickedBeyondItem];}
  337.           Offs := (1+delta) div 2;
  338.         end;
  339.       end;
  340.     end;
  341.   end;
  342.   order.Free;
  343.   revorder.Free;
  344.   {$IFNDEF RVDONOTUSELISTS}
  345.   if (No>=0) and not Strict then begin
  346.     if GetDrawItemStyle(No)=rvsListMarker then begin
  347.       inc(No);
  348.       Offs := GetOffsBeforeDrawItem(No);
  349.     end;
  350.   end;
  351.   {$ENDIF}
  352. end;
  353. {------------------------------------------------------------------------------}
  354. procedure TCustomRVFormattedData.RestoreSelBounds(StartNo, EndNo,
  355.   StartOffs, EndOffs: Integer);
  356. begin
  357.   Item2DrawItem(StartNo, StartOffs, {->} FSelStartNo, FSelStartOffs);
  358.   Item2DrawItem(EndNo,   EndOffs,   {->} FSelEndNo,   FSelEndOffs);
  359. end;
  360. {------------------------------------------------------------------------------}
  361. procedure TCustomRVFormattedData.StoreSelBounds(var StartNo, EndNo,
  362.   StartOffs, EndOffs: Integer; Normalize: Boolean);
  363. var SelStartNo, SelEndNo, SelStartOffs, SelEndOffs: Integer;
  364. begin
  365.   GetSelBounds(SelStartNo, SelEndNo, SelStartOffs, SelEndOffs, Normalize);
  366.   DrawItem2Item(SelStartNo,SelStartOffs, {->} StartNo,StartOffs);
  367.   DrawItem2Item(SelEndNo,  SelEndOffs,   {->} EndNo,  EndOffs);
  368. end;
  369. {------------------------------------------------------------------------------}
  370. procedure TCustomRVFormattedData.DrawItem2Item(DrawItemNo, DrawItemOffs: Integer;
  371.                              var ItemNo, ItemOffs: Integer);
  372. var dli: TRVDrawLineInfo;
  373. begin
  374.   ItemNo := -1;
  375.   if DrawItemNo = -1 then exit;
  376.   dli := DrawItems[DrawItemNo];
  377.   if GetItemStyle(dli.ItemNo)>=0 then
  378.     ItemOffs := DrawItemOffs + dli.Offs-1
  379.   else
  380.     ItemOffs := DrawItemOffs;
  381.   ItemNo := dli.ItemNo;
  382. end;
  383. {------------------------------------------------------------------------------}
  384. procedure TCustomRVFormattedData.Item2DrawItem(ItemNo, ItemOffs: Integer;
  385.                              var DrawItemNo, DrawItemOffs: Integer);
  386. var item: TCustomRVItemInfo;
  387.     i: Integer;
  388. begin
  389.   DrawItemNo := -1;
  390.   if ItemNo = -1 then
  391.     exit;
  392.   item := TCustomRVItemInfo(Items.Objects[ItemNo]);
  393.   DrawItemNo := item.DrawItemNo;
  394.   if item.StyleNo<0 then begin
  395.     DrawItemOffs := ItemOffs-DrawItems[DrawItemNo].Offs;
  396.     exit;
  397.   end;
  398.   DrawItemOffs := ItemOffs-DrawItems[DrawItemNo].Offs+1;
  399.   for i := DrawItemNo+1 to DrawItems.Count-1 do begin
  400.     if (DrawItems[i].ItemNo<>ItemNo) or
  401.        ((DrawItems[i].Offs>=ItemOffs) and not (DrawItems[i-1].Offs+DrawItems[i-1].Length<ItemOffs)) then begin
  402.       DrawItemNo   := i-1;
  403.       DrawItemOffs := ItemOffs-DrawItems[DrawItemNo].Offs+1;
  404.       if (GetDrawItemStyle(DrawItemNo)>=0) and
  405.          (DrawItemOffs>DrawItems[DrawItemNo].Length+DrawItems[DrawItemNo].Offs) then begin
  406.         DrawItemNo   := i;
  407.         // changed: Jun 29 2004
  408.         if DrawItems[DrawItemNo].Offs<=GetOffsBeforeDrawItem(DrawItemNo) then begin
  409.           DrawItemNo := i;
  410.           DrawItemOffs := DrawItems[DrawItemNo].Offs;
  411.           end
  412.         else begin
  413.           DrawItemNo := i-1;
  414.           DrawItemOffs := GetOffsAfterDrawItem(DrawItemNo);
  415.         end;
  416.       end;
  417.       break;
  418.     end;
  419.     if i=DrawItems.Count-1 then begin
  420.       DrawItemNo   := i;
  421.       DrawItemOffs := ItemOffs-DrawItems[DrawItemNo].Offs+1;
  422.     end;
  423.   end;
  424. end;
  425. {------------------------------------------------------------------------------}
  426. procedure TCustomRVFormattedData.Item2FirstDrawItem(ItemNo: Integer;
  427.                                                     var DrawItemNo: Integer);
  428. begin
  429.   DrawItemNo := -1;
  430.   if ItemNo = -1 then
  431.     exit;
  432.   DrawItemNo := TCustomRVItemInfo(Items.Objects[ItemNo]).DrawItemNo;
  433. end;
  434. {------------------------------------------------------------------------------}
  435. procedure TCustomRVFormattedData.Item2LastDrawItem(ItemNo: Integer; var DrawItemNo: Integer);
  436. begin
  437.   DrawItemNo := -1;
  438.   if ItemNo = -1 then
  439.     exit;  
  440.   Item2DrawItem(ItemNo, GetOffsAfterItem(ItemNo), DrawItemNo, ItemNo);
  441. end;
  442. {------------------------------------------------------------------------------}
  443. function TCustomRVFormattedData.GetDrawItemNo(BoundLine, Option: Integer): Integer;
  444. var
  445.     a,b,mid: Integer;
  446. begin
  447.   if DrawItems.Count = 0 then begin
  448.      Result := 0;
  449.      exit;
  450.   end;
  451.   if DrawItems[0].Top>=BoundLine then begin
  452.      Result := 0;
  453.      exit;
  454.   end;
  455.   if (Option=gdinLastVisible) and (DrawItems[DrawItems.Count-1].Top<BoundLine) then begin
  456.      Result := DrawItems.Count-1;
  457.      exit;
  458.   end;
  459.   a := 1;
  460.   b := DrawItems.Count-1;
  461.   mid := a;
  462.   if Option = gdinLastCompleteVisible then begin
  463.   {
  464.     while (b-a)>1 do begin
  465.       mid := (a+b) div 2;
  466.       if (TRVDrawLineInfo(DrawItems.Objects[mid]).Top+TRVDrawLineInfo(DrawItems.Objects[mid]).Height>BoundLine) then
  467.           b := mid
  468.       else
  469.           a := mid;
  470.     end;
  471.     if mid>= DrawItems.Count then mid := DrawItems.Count-1;
  472.     while (mid>0) and (TRVDrawLineInfo(DrawItems.Objects[mid]).Top+TRVDrawLineInfo(DrawItems.Objects[mid]).Height>BoundLine) do dec(mid);
  473.       if (mid>0) then dec(mid);
  474.       while (mid>0) and not TRVDrawLineInfo(DrawItems.Objects[mid]).FromNewLine do dec(mid);
  475.       if (mid>0) then dec(mid);
  476.     end
  477.     }
  478.   end
  479.   else begin
  480.     while (b-a)>1 do begin
  481.       mid := (a+b) div 2;
  482.       if (DrawItems[mid].Top>=BoundLine) then begin
  483.           if (DrawItems[mid-1].Top<BoundLine) then break;
  484.           b := mid;
  485.         end
  486.       else
  487.         a := mid;
  488.     end;
  489.     if mid>= DrawItems.Count then mid := DrawItems.Count-1;
  490.     if Option = gdinFirstVisible then begin
  491.       while (mid>0) and not DrawItems[mid].FromNewLine do dec(mid);
  492.       if (mid>0) then dec(mid);
  493.       while (mid>0) and not DrawItems[mid].FromNewLine do dec(mid);
  494.       if (mid>0) then dec(mid);
  495.       end
  496.     else
  497.       while DrawItems[mid].Top<BoundLine do inc(mid);
  498.   end;
  499.   Result := mid;
  500. end;
  501. {------------------------------------------------------------------------------}
  502. // Calculating minimal possible width for paragraph sections containing
  503. // items in the given range.
  504. // This is a maximum of min widths of all paragraph sections
  505. // Works both for normal and no-wrap paragraphs
  506. function TCustomRVFormattedData.CalculateParaSectionsMinWidth(StartItemNo,
  507.   EndItemNo: Integer; var FirstParaItemNo: Integer; sad: PRVScreenAndDevice;
  508.   Canvas: TCanvas): Integer;
  509. var i,w: Integer;
  510. begin
  511.   ExpandToParaSection(StartItemNo, EndItemNo, StartItemNo, EndItemNo);
  512.   Result := 0;
  513.   for i := StartItemNo to EndItemNo do begin
  514.     if IsParaStart(i) then
  515.       FirstParaItemNo := i;
  516.     if IsFromNewLine(i) then begin
  517.       w := CalculateParaSectionMinWidth(i, FirstParaItemNo, sad, Canvas);
  518.       if w>Result then
  519.         Result := w;
  520.     end;
  521.   end;
  522. end;
  523. {------------------------------------------------------------------------------}
  524. function TCustomRVFormattedData.CalculateParaSectionsMinWidthDef(StartItemNo,
  525.   EndItemNo: Integer): Integer;
  526. var FirstParaItemNo: Integer;
  527. begin
  528.   FirstParaItemNo := -1;
  529.   Result := CalculateParaSectionsMinWidth(StartItemNo, EndItemNo, FirstParaItemNo, nil, nil);
  530. end;
  531. {------------------------------------------------------------------------------}
  532. // Calculating total indents for the paragraph section
  533. function TCustomRVFormattedData.CalculatePureParaSectionWidth(ItemNo: Integer;
  534.   var FirstParaItemNo: Integer; sad: PRVScreenAndDevice; Canvas: TCanvas): Integer;
  535. begin
  536.   ItemNo := GetFirstParaSectionItem(ItemNo);
  537.   Result := GetMaxIndent(ItemNo, FirstParaItemNo);
  538.   if (sad<>nil) then
  539.     Result := MulDiv(Result, sad.ppixDevice, sad.ppixScreen);
  540. end;
  541. {------------------------------------------------------------------------------}
  542. // Calculates minimal possible width for paragraph section containing
  543. // StartItemNo-th item.
  544. // Works both for normal paragraphs (calls CalculateMinItemsWidthPlus)
  545. // and for no-wrap paragraphs (calculates sum of widths of all items)
  546. function TCustomRVFormattedData.CalculateParaSectionMinWidth(StartItemNo: Integer;
  547.   var FirstParaItemNo: Integer; sad: PRVScreenAndDevice;
  548.   Canvas: TCanvas): Integer;
  549. var i, EndItemNo: Integer;
  550.     item: TCustomRVItemInfo;
  551.     RVStyle: TRVStyle;
  552.     {$IFNDEF RVDONOTUSEUNICODE}
  553.     sz: TSize;
  554.     {$ENDIF}
  555. begin
  556.   item := GetItem(StartItemNo);
  557.   if Canvas=nil then
  558.     Canvas := GetCanvas;
  559.   ExpandToParaSection(StartItemNo, StartItemNo, StartItemNo, EndItemNo);
  560.   if not (rvpaoNoWrap in GetRVStyle.ParaStyles[item.ParaNo].Options) then begin
  561.     Result := CalculateMinItemsWidthPlus(StartItemNo, EndItemNo, FirstParaItemNo, sad, Canvas);
  562.     exit;
  563.   end;
  564.   RVStyle := GetRVStyle;
  565.   Result := CalculatePureParaSectionWidth(StartItemNo, FirstParaItemNo, sad, Canvas);
  566.   for i := StartItemNo to EndItemNo do begin
  567.     item := GetItem(i);
  568.     if item.StyleNo>=0 then
  569.       with RVStyle.TextStyles[GetActualStyle(item)] do begin
  570.         Apply(Canvas, GetParaBiDiMode(item.ParaNo), rvflCanUseCustomPPI in Flags);
  571.         {$IFNDEF RVDONOTUSEUNICODE}
  572.         if Unicode then begin
  573.           RVU_GetTextExtentPoint32W(Canvas, Pointer(Items[i]), Length(Items[i]) div 2, sz);
  574.           inc(Result, sz.cx);
  575.           end
  576.         else
  577.         {$ENDIF}
  578.           inc(Result, Canvas.TextWidth(Items[i]));
  579.       end
  580.     else
  581.       inc(Result, item.GetMinWidth(sad, Canvas,Self));
  582.   end;
  583. end;
  584. {------------------------------------------------------------------------------}
  585. function TCustomRVFormattedData.CalculateParaSectionMinWidthDef(StartItemNo: Integer): Integer;
  586. var FirstParaItemNo: Integer;
  587. begin
  588.   FirstParaItemNo := -1;
  589.   Result := CalculateParaSectionMinWidth(StartItemNo, FirstParaItemNo,nil,nil);
  590. end;
  591. {------------------------------------------------------------------------------}
  592. // Calculates a minimal possible width for the given range of items in
  593. // normal (i.e. wrappable) paragraphs
  594. // This is a maximum of individual widths of items in this range.
  595. function TCustomRVFormattedData.CalculateMinItemsWidthPlus(StartItemNo, EndItemNo: Integer;
  596.   var FirstParaItemNo: Integer; sad: PRVScreenAndDevice;
  597.   Canvas: TCanvas): Integer;
  598. var i,w, pspw: Integer;
  599. begin
  600.   Result := 0;
  601.   if StartItemNo>EndItemNo then
  602.     exit;
  603.   pspw := CalculatePureParaSectionWidth(StartItemNo, FirstParaItemNo, sad, Canvas);
  604.   for i := StartItemNo to EndItemNo do begin
  605.     if IsParaStart(i) then
  606.       FirstParaItemNo := i;
  607.     if IsFromNewLine(i) and (i<>StartItemNo) then
  608.       pspw := CalculatePureParaSectionWidth(i, FirstParaItemNo, sad, Canvas);
  609.     w := pspw+CalculateMinItemWidthPlus_WithoutPSWidth(i, sad, Canvas);
  610.     if w>Result then
  611.       Result := w;
  612.   end;
  613. end;
  614. {------------------------------------------------------------------------------}
  615. // Calculates a minimal possible width for the given item in
  616. // normal (i.e. wrappable) paragraphs
  617. // If this is an item preceded by a marker, this function returns
  618. // a sum of min widths of this item and marker.
  619. function TCustomRVFormattedData.CalculateMinItemWidthPlus_WithoutPSWidth(ItemNo: Integer;
  620.                                                           sad: PRVScreenAndDevice;
  621.                                                           Canvas: TCanvas): Integer;
  622. var item: TCustomRVItemInfo;
  623. begin
  624.   item := GetItem(ItemNo);
  625.   Result := item.GetMinWidth(sad, Canvas, Self);
  626.   {$IFNDEF RVDONOTUSELISTS}
  627.   if item.SameAsPrev and (ItemNo>0) then begin
  628.     item := GetItem(ItemNo-1);
  629.     if item.StyleNo=rvsListMarker then
  630.       inc(Result, item.GetMinWidth(sad, Canvas, Self));
  631.   end;
  632.   {$ENDIF}
  633. end;
  634. {------------------------------------------------------------------------------}
  635. // Calculates a minimal possible width for the paragraph section containing
  636. // the given item (both for wrappable and no-wrap paragraphs)
  637. function TCustomRVFormattedData.CalculateMinItemWidthPlusEx(ItemNo: Integer): Integer;
  638. var FirstParaItemNo: Integer;
  639. begin
  640.   FirstParaItemNo := -1;
  641.   Result := CalculateParaSectionMinWidth(ItemNo, FirstParaItemNo, nil, GetCanvas);
  642. end;
  643. {------------------------------------------------------------------------------}
  644. // Calculates a minimal possible width for the given range of items
  645. // (both for wrappable and no-wrap paragraphs)
  646. function TCustomRVFormattedData.CalculateMinItemsWidthPlusEx(StartItemNo,
  647.   EndItemNo: Integer): Integer;
  648. var item: TCustomRVItemInfo;
  649.     dummy, sno, eno,w: Integer;
  650.     FirstParaItemNo: Integer;
  651. begin
  652.   if StartItemNo>EndItemNo then begin
  653.     Result := 0;
  654.     exit;
  655.   end;
  656.   FirstParaItemNo := -1;
  657.   item := GetItem(StartItemNo);
  658.   ExpandToParaSection(StartItemNo, StartItemNo, dummy,eno);
  659.   if rvpaoNoWrap in GetRVStyle.ParaStyles[item.ParaNo].Options then
  660.     Result := CalculateParaSectionMinWidthDef(StartItemNo)
  661.   else begin
  662.     if eno>EndItemNo then
  663.       eno := EndItemNo;
  664.     Result := CalculateMinItemsWidthPlus(StartItemNo, eno, FirstParaItemNo, nil, GetCanvas);
  665.   end;
  666.   if eno>=EndItemNo then
  667.     exit;
  668.   ExpandToParaSection(EndItemNo, EndItemNo, sno, dummy);
  669.   item := GetItem(EndItemNo);
  670.   if rvpaoNoWrap in GetRVStyle.ParaStyles[item.ParaNo].Options then
  671.     w := CalculateParaSectionMinWidth(EndItemNo, FirstParaItemNo, nil,GetCanvas)
  672.   else begin
  673.     if sno<StartItemNo then
  674.       eno := StartItemNo;
  675.     w := CalculateMinItemsWidthPlus(sno, EndItemNo, FirstParaItemNo, nil,GetCanvas);
  676.   end;
  677.   if w>Result then
  678.     Result := w;
  679.   if sno<=eno then
  680.     exit;
  681.   w := CalculateParaSectionsMinWidth(eno, sno, FirstParaItemNo, nil,nil);
  682.   if w>Result then
  683.     Result := w;
  684. end;
  685. {------------------------------------------------------------------------------}
  686. // Calculates the minimal possible width for the whole document
  687. function TCustomRVFormattedData.CalculateMinDocWidthPlus(sad: PRVScreenAndDevice;
  688.                                                       Canvas: TCanvas): Integer;
  689. var FirstParaItemNo: Integer;
  690. begin
  691.   if (sad<>nil) and (sad.ppixScreen=sad.ppixDevice) and
  692.      (sad.ppiyScreen=sad.ppiyDevice) then
  693.     sad := nil;
  694.   FirstParaItemNo := 0;
  695.   Result := CalculateParaSectionsMinWidth(0, Items.Count-1, FirstParaItemNo, sad, Canvas);
  696. end;
  697. {------------------------------------------------------------------------------}
  698. function TCustomRVFormattedData.CalculateMinWidthAfterInsert(
  699.   item: TCustomRVItemInfo; InsertItemNo: Integer): Integer;
  700. begin
  701.   Result := item.GetMinWidth(nil,nil,Self);
  702.   if rvpaoNoWrap in GetRVStyle.ParaStyles[GetItemPara(InsertItemNo)].Options then
  703.     inc(Result,CalculateParaSectionMinWidthDef(InsertItemNo));
  704. end;
  705. {------------------------------------------------------------------------------}
  706. procedure TCustomRVFormattedData.AdjustJumpsCoords;
  707. var i,x,y: Integer;
  708.     jumpinfo: TRVJumpInfo;
  709. begin
  710.   for i:= 0 to Jumps.Count-1 do begin
  711.     jumpinfo := TRVJumpInfo(Jumps[i]);
  712.     jumpinfo.RVData.GetOrigin(x,y);
  713.     dec(y, GetRVDataExtraVOffs);
  714.     jumpinfo.l := x+jumpinfo.RVData.DrawItems[jumpinfo.DrawItemNo].Left;
  715.     jumpinfo.t := y+jumpinfo.RVData.DrawItems[jumpinfo.DrawItemNo].Top;
  716.   end;
  717. end;
  718. {------------------------------------------------------------------------------}
  719. procedure TCustomRVFormattedData.AdjustChildrenCoords;
  720. var i: Integer;
  721.     ditem: TRVDrawLineInfo;
  722.     item : TCustomRVItemInfo;
  723. begin
  724.   if (rvflShareContents in Flags) or (GetParentControl.ControlCount=0) or
  725.      (rvstDoNotMoveChildren in State) then exit;
  726.   for i:=0 to DrawItems.Count-1 do begin
  727.     ditem := DrawItems[i];
  728.     item := GetItem(ditem.ItemNo);
  729.     if item.StyleNo<0 then begin
  730.       TRVNonTextItemInfo(item).AdjustInserted(ditem.Left-GetZHOffs, ditem.Top-GetZVOffs, True);
  731.     end;
  732.   end;
  733.   {$IFNDEF RVDONOTUSESMARTPOPUP}
  734.   TCustomRVFormattedData(GetAbsoluteRootData).AdjustSpecialControlsCoords(Self);
  735.   {$ENDIF}
  736. end;
  737. {------------------------------------------------------------------------------}
  738. function TCustomRVFormattedData.FindDrawItemByItem(ItemNo: Integer): Integer;
  739. var i: Integer;
  740. begin
  741.   Result := -1;
  742.   if ItemNo = -1 then exit;
  743.   for i :=0 to DrawItems.Count-1 do
  744.     if DrawItems[i].ItemNo = ItemNo then begin
  745.       Result := i;
  746.       exit;
  747.     end;
  748.   //Assert(Result<>-1, 'Can''t FindDrawLineByLine');
  749. end;
  750. {------------------------------------------------------------------------------}
  751. function TCustomRVFormattedData.FindDrawItemAtPos(X,Y: Integer): Integer;
  752. var
  753.     i, a,b,mid, midtop: Integer;
  754.     dli: TRVDrawLineInfo;
  755. begin
  756.   if DrawItems.Count = 0 then begin
  757.      Result := -1;
  758.      exit;
  759.   end;
  760.   dli := DrawItems[0];
  761.   if (dli.Top<=Y) and (dli.Top+dli.Height>Y) and
  762.      (dli.Left<=X) and (dli.Left+dli.Width>X) then begin
  763.      Result := 0;
  764.      exit;
  765.   end;
  766.   if DrawItems.Count = 1 then begin
  767.      Result := -1;
  768.      exit;
  769.   end;
  770.   a := 1;
  771.   b := DrawItems.Count-1;
  772.   while (b-a)>1 do begin
  773.     mid := (a+b) div 2;
  774.     if (DrawItems[mid].Top<=Y) then
  775.       a := mid
  776.     else
  777.       b := mid;
  778.   end;
  779.   mid := a;
  780.   midtop := DrawItems[mid].Top;
  781.   while (mid>=1) and
  782.          (DrawItems[mid-1].Top+
  783.           DrawItems[mid-1].Height>midtop) do dec(mid);
  784.   for i:=1 to 2 do begin
  785.     if mid = DrawItems.Count then break;
  786.     midtop := DrawItems[mid].Top+
  787.               DrawItems[mid].Height-1;
  788.     while (mid<DrawItems.Count) do begin
  789.      dli := DrawItems[mid];
  790.      if (dli.Top>midtop) then break;
  791.      if (dli.Top<=Y) and (dli.Top+dli.Height>Y) and
  792.      (dli.Left<=X) and (dli.Left+dli.Width>X) then begin
  793.         Result := mid;
  794.         exit;
  795.      end;
  796.      inc(mid);
  797.     end;
  798.   end;
  799.   Result := -1;
  800. end;
  801. {------------------------------------------------------------------------------}
  802. procedure TCustomRVFormattedData.InvalidateDrawItem(DrawItemNo, Spacing: Integer);
  803. var R: TRect;
  804.     //X, Y: Integer;
  805. begin
  806.   //GetOrigin(X, Y);
  807.   ResetSubCoords;
  808.   with DrawItems[DrawItemNo] do
  809.     R := Bounds(Left, Top, Width, Height);
  810.   InflateRect(R, Spacing, Spacing);
  811.   OffsetRect(R, {X}-GetHOffs, {Y}-GetVOffs);
  812.   //if (R.Bottom>0) and (R.Top<TCustomRVFormattedData(GetRootData).GetHeight) then
  813.     InvalidateRect(R);
  814. end;
  815. {------------------------------------------------------------------------------}
  816. function TCustomRVFormattedData.GetFirstVisible(TopLine: Integer): Integer;
  817. begin
  818.    Result := GetDrawItemNo(TopLine,gdinFirstVisible);
  819. end;
  820. {------------------------------------------------------------------------------}
  821. function TCustomRVFormattedData.GetFirstItemVisible: Integer;
  822. var v: Integer;
  823. begin
  824.    v := GetDrawItemNo(GetVOffs, gdinFirstVisible);
  825.    if v>=DrawItems.Count then
  826.      v := DrawItems.Count-1;
  827.    if v<0 then
  828.      Result := -1
  829.    else
  830.      Result := DrawItems[v].ItemNo;
  831. end;
  832. {------------------------------------------------------------------------------}
  833. function TCustomRVFormattedData.GetLastItemVisible: Integer;
  834. var v: Integer;
  835. begin
  836.    v := GetDrawItemNo(GetVOffs+GetHeight, gdinLastVisible);
  837.    if v>=DrawItems.Count then
  838.      v := DrawItems.Count-1;
  839.    if v<0 then
  840.      Result := -1
  841.    else
  842.      Result := DrawItems[v].ItemNo;
  843. end;
  844. {------------------------------------------------------------------------------}
  845. procedure TCustomRVFormattedData.DrawBackground(Canvas: TCanvas; r: TRect);
  846. var X, Y: Integer;
  847. begin
  848.   GetOrigin(X, Y);
  849.   GetBackground.Draw(Canvas, r, GetHOffs+X, GetVOffs+Y, 0, 0, GetWidth, GetHeight,
  850.     GetColor, False);
  851. end;
  852. {------------------------------------------------------------------------------}
  853. procedure TCustomRVFormattedData.PaintTo(Canvas: TCanvas; AClipRect: TRect);
  854. var i,no, yshift, xshift, fullwidth, selwidth, ditemselstart, ditemselend: Integer;
  855.     dli:TRVDrawLineInfo;
  856.     li: TCustomRVItemInfo;
  857.     HoverNow, res: Boolean;
  858.     s : String;
  859.     StartNo, EndNo, StartOffs, EndOffs: Integer;
  860.     LastDrawnStyle: Integer;
  861.     RVStyle: TRVStyle;
  862.     BiDiMode: TRVBiDiMode;
  863.     DefaultTextDrawState: TRVTextDrawStates;
  864.     DefaultDrawState: TRVItemDrawStates;
  865.     FirstDLine, LastDLine: Integer;
  866.     LineTopY, LineBottomY: Integer;
  867.     ShowSpecialCharacters: Boolean;
  868.   {.......................................................}
  869.     function GetSelDrawState: TRVTextDrawStates;
  870.     begin
  871.       Result := [rvtsSelected];
  872.       if HoverNow then
  873.         Include(Result, rvtsHover);
  874.     end;
  875.   {.......................................................}
  876.     procedure DrawText(X,Y,W, Offs, DItemNo: Integer; const s: String;
  877.                        IsStart, IsEnd, Selected, SBAdded: Boolean);
  878.                        // in : dli, Canvas, xshift, yshift, hovernow, no
  879.     {$IFNDEF RVDONOTUSEJUSTIFY}
  880.     var SpaceBefore: Integer;
  881.     {$ENDIF}
  882.     var DrawState: TRVTextDrawStates;
  883.         s2: String;
  884.     begin
  885.       {
  886.       if s='' then begin
  887.         Canvas.Pen.Color := clBlue;
  888.         Canvas.Pen.Style := psSolid;
  889.         Canvas.Ellipse(x-10-xshift,y-10-yshift,x+10-xshift,y+10-yshift);
  890.       end;
  891.       }
  892.       DrawState := DefaultTextDrawState;
  893.       if Selected then Include(DrawState, rvtsSelected);
  894.       if HoverNow then
  895.         Include(DrawState, rvtsHover);
  896.       if Assigned(RVStyle.OnDrawStyleText) then begin
  897.         if IsStart then begin
  898.           Include(DrawState, rvtsDrawItemStart);
  899.           if dli.Offs=1 then
  900.             Include(DrawState, rvtsItemStart);
  901.         end;
  902.         if IsEnd then begin
  903.           Include(DrawState, rvtsDrawItemEnd);
  904.           if dli.Offs+dli.Length-1=ItemLength(dli.ItemNo) then
  905.             Include(DrawState, rvtsItemEnd);
  906.         end;
  907.       end;
  908.       RVStyle.ApplyStyleColor(Canvas, No, DrawState, False, rvcmColor);
  909.       {$IFNDEF RVDONOTUSEJUSTIFY}
  910.       if IsStart then begin
  911.         SpaceBefore := dli.SpaceBefore;
  912.         if not SBAdded then
  913.           inc(W,SpaceBefore);
  914.         end
  915.       else begin
  916.         SpaceBefore := 0;
  917.         inc(X, dli.SpaceBefore);
  918.         if SBAdded then
  919.           dec(W,dli.SpaceBefore);
  920.       end;
  921.       {$ENDIF}
  922.       s2 := s;
  923.       if ShowSpecialCharacters then begin
  924.         Include(DrawState, rvtsSpecialCharacters);
  925.         if RichViewShowGhostSpaces and IsEnd and
  926.            IsSpaceBetweenDrawItems(DItemNo) and
  927.            (not Selected or
  928.            (rvstCompletelySelected in State) or
  929.             not (DItemNo=EndNo)) then begin
  930.             {$IFNDEF RVDONOTUSEUNICODE}
  931.             if rvioUnicode in li.ItemOptions then
  932.               s2 := s2+' '#0
  933.             else
  934.             {$ENDIF}
  935.               s2 := s2+' ';
  936.         end;
  937.       end;
  938.       if Selected and (RVStyle.SelectionStyle=rvssLines) and (W>0) then
  939.         Canvas.FillRect(Rect(X-xshift-1, LineTopY-yshift, X-xshift+W+1, LineBottomY-yshift));
  940.       RVStyle.DrawStyleText(s2, Canvas, dli.ItemNo, Offs+dli.Offs-1, No, Self,
  941.         {$IFNDEF RVDONOTUSEJUSTIFY}SpaceBefore,{$ELSE}0,{$ENDIF}
  942.         X-xshift, Y-yshift, W, dli.Height, DrawState, False, False,
  943.         rvcmColor, BiDiMode);
  944.     end;
  945.   {.......................................................}
  946.   function GetLineTopY(DrawItemNo: Integer): Integer;
  947.   var i: Integer;
  948.   begin
  949.     Result := DrawItems[DrawItemNo].Top;
  950.     for i := DrawItemNo downto 0 do begin
  951.       if DrawItems[i].Top<Result then
  952.         Result := DrawItems[i].Top;
  953.       if DrawItems[i].FromNewLine then
  954.         break;
  955.     end;
  956.     for i := DrawItemNo+1 to DrawItems.Count-1 do begin
  957.       if DrawItems[i].FromNewLine then
  958.         break;
  959.       if DrawItems[i].Top<Result then
  960.         Result := DrawItems[i].Top;
  961.     end;
  962.   end;
  963.   {.......................................................}
  964.   procedure DrawSoftPageBreaks;
  965.   var FirstPB, i,DItemNo, Offs, Y: Integer;
  966.       dli: TRVDrawLineInfo;
  967.       PBInfo: TRVSoftPageBreakInfo;
  968.   begin
  969.     FirstPB := -1;
  970.     dli := DrawItems[FirstDLine];
  971.     for i := 0 to FSoftPageBreaks.Count-1 do
  972.       if TRVSoftPageBreakInfo(FSoftPageBreaks.Items[i]).ItemNo>=dli.ItemNo then begin
  973.         FirstPB := i;
  974.         break;
  975.       end;
  976.     if FirstPB<0 then
  977.       exit;
  978.     for i := FirstPB to FSoftPageBreaks.Count-1 do begin
  979.       PBInfo := TRVSoftPageBreakInfo(FSoftPageBreaks.Items[i]);
  980.       Item2DrawItem(PBInfo.ItemNo, PBInfo.Offset, DItemNo, Offs);
  981.       if DItemNo>LastDLine then
  982.         exit;
  983.       if (DItemNo=0) and (PBInfo.ExtraData<0) then
  984.         continue;
  985.       if PBInfo.ExtraData>=0 then
  986.         Y := DrawItems[DItemNo].Top+GetItem(PBInfo.ItemNo).GetSoftPageBreakDY(PBInfo.ExtraData)
  987.       else
  988.         Y := GetLineTopY(DItemNo);
  989.       RVStyle.DrawPageBreak(Canvas, Y-yshift-1, xshift, rvpbSoftPageBreak, GetParentControl);
  990.     end;
  991.   end;
  992.   {.......................................................}
  993.   procedure GetLineVerticalBounds(FirstDrawItemNo: Integer;
  994.     var LineTopY, LineBottomY: Integer);
  995.   var i, LastDrawItemNo: Integer;
  996.       ditem: TRVDrawLineInfo;
  997.   begin
  998.     ditem := DrawItems[FirstDrawItemNo];
  999.     LineTopY := ditem.Top;
  1000.     LineBottomY := LineTopY+ditem.Height+ditem.ExtraSpaceBelow;
  1001.     if (FirstDrawItemNo+1>=DrawItems.Count) or
  1002.        DrawItems[FirstDrawItemNo+1].FromNewLine then
  1003.        LastDrawItemNo := FirstDrawItemNo
  1004.     else begin
  1005.       LastDrawItemNo := DrawItems.Count-1;
  1006.       for i := FirstDrawItemNo+1 to DrawItems.Count-1 do begin
  1007.         ditem := DrawItems[i];
  1008.         if ditem.FromNewLine then begin
  1009.           LastDrawItemNo := i-1;
  1010.           break;
  1011.         end;
  1012.         if LineTopY>ditem.Top then
  1013.           LineTopY := ditem.Top;
  1014.         if LineBottomY<ditem.Top+ditem.Height+ditem.ExtraSpaceBelow then
  1015.           LineBottomY := ditem.Top+ditem.Height+ditem.ExtraSpaceBelow;
  1016.       end;
  1017.     end;
  1018.     if IsDrawItemParaStart(FirstDrawItemNo) then
  1019.       dec(LineTopY, RVStyle.ParaStyles[GetItemPara(
  1020.         DrawItems[FirstDrawItemNo].ItemNo)].SpaceBefore);
  1021.     if IsDrawItemParaEnd(LastDrawItemNo) then
  1022.       inc(LineBottomY, RVStyle.ParaStyles[GetItemPara(
  1023.         DrawItems[FirstDrawItemNo].ItemNo)].SpaceAfter);
  1024.   end;
  1025.   {.......................................................}
  1026.   function UseLineSelection(ditem: TRVDrawLineInfo): Boolean;
  1027.   begin
  1028.     Result := (FSelStartNo>=0) and (RVStyle.SelectionStyle=rvssLines) and
  1029.       (GetItemBiDiMode(ditem.ItemNo)=rvbdUnspecified);
  1030.   end;
  1031.   {.......................................................}
  1032.   procedure DrawParaMarkAfter(DrawItemNo: Integer);
  1033.   var BiDiMode: TRVBiDiMode;
  1034.       Left: Integer;
  1035.       s: String;
  1036.       sz: TSize;
  1037.       ditem: TRVDrawLineInfo;
  1038.   begin
  1039.     if (DrawItemNo+1<DrawItems.Count) and
  1040.        ((DrawItems[DrawItemNo].ItemNo=DrawItems[DrawItemNo+1].ItemNo) or
  1041.         not IsFromNewLine(DrawItems[DrawItemNo+1].ItemNo)) then
  1042.       exit;
  1043.     ditem := DrawItems[DrawItemNo];
  1044.     if LastDrawnStyle<0 then
  1045.       LastDrawnStyle := 0;
  1046.     BiDiMode := GetParaBiDiMode(GetItemPara(ditem.ItemNo));
  1047.     RVStyle.ApplyStyle(Canvas, LastDrawnStyle, BiDiMode, True);
  1048.     RVStyle.ApplyStyleColor(Canvas, LastDrawnStyle, [], False, rvcmColor);    
  1049.     if {$IFDEF RICHVIEWCBDEF3}(Canvas.Font.Charset=SYMBOL_CHARSET) or{$ENDIF}
  1050.        (AnsiCompareText(Canvas.Font.Name, RVFONT_SYMBOL)=0) or
  1051.        (AnsiCompareText(Canvas.Font.Name, RVFONT_WINGDINGS)=0) then begin
  1052.       LastDrawnStyle := -1;
  1053.       Canvas.Font.Name := 'Arial';
  1054.       {$IFDEF RICHVIEWCBDEF3}
  1055.       Canvas.Font.CHARSET := DEFAULT_CHARSET;
  1056.       {$ENDIF}
  1057.     end;
  1058.     if (DrawItemNo+1=DrawItems.Count) or IsParaStart(DrawItems[DrawItemNo+1].ItemNo) then
  1059.       s := #$B6
  1060.     else begin
  1061.       {$IFDEF RICHVIEWCBDEF3}
  1062.       Canvas.Font.Charset := SYMBOL_CHARSET;
  1063.       {$ENDIF}
  1064.       Canvas.Font.Name := RVFONT_SYMBOL;
  1065.       s := #$BF;
  1066.       {
  1067.       Canvas.Font.Name := RVFONT_WINGDINGS;
  1068.       s := #$C3;
  1069.       }
  1070.       LastDrawnStyle := -1;
  1071.     end;
  1072.     GetTextExtentPoint32(Canvas.Handle, PChar(s), 1, sz);
  1073.     if BiDiMode<>rvbdRightToLeft then
  1074.       Left := ditem.Left+ditem.Width
  1075.     else
  1076.       Left := ditem.Left-sz.cx;
  1077.     Canvas.TextOut(Left-xshift, ditem.Top+ditem.Height-yshift-sz.cy, s);
  1078.   end;
  1079.   {.......................................................}
  1080.   {$IFNDEF RVDONOTUSELIVESPELL}
  1081.   procedure GetSubItemRect(DItemNo, StartOffs, EndOffs: Integer;
  1082.     ditem: TRVDrawLineInfo; var r: TRect);
  1083.   var s: String;
  1084.       res: Boolean;
  1085.   begin
  1086.     dec(StartOffs, ditem.Offs-1);
  1087.     if StartOffs<1 then
  1088.       StartOffs := 1;
  1089.     dec(EndOffs, ditem.Offs-1);
  1090.     if EndOffs>ditem.Length then
  1091.       EndOffs := ditem.Length;
  1092.     s  := DrawItems.GetString(DItemNo,Items);
  1093.     if BiDiMode<>rvbdUnspecified then begin
  1094.       s := RV_ReturnProcessedString(s, RVStyle.TextStyles[No],
  1095.         (StartOffs>=GetOffsAfterDrawItem(DItemNo)) and IsDrawItemLastOnWrappedLine(DItemNo),
  1096.            rvoShowSpecialCharacters in Options, True);
  1097.       res := RVU_GetTextRangeCoords(Canvas, s, StartOffs, EndOffs-StartOffs+1,
  1098.         GetItemOptions(ditem.ItemNo), ditem.Width, r.Left, r.Right);
  1099.       end
  1100.     else
  1101.       res := False;
  1102.     if not res then begin
  1103.       if StartOffs>1 then begin
  1104.         s := DrawItems.GetSubString(DItemNo, Items, 1, StartOffs-1);
  1105.         s  := RV_ReturnProcessedString(s, RVStyle.TextStyles[No], False,
  1106.           rvoShowSpecialCharacters in Options, True);
  1107.         r.Left := RVU_TextWidth(s, Canvas, GetItemOptions(ditem.ItemNo));
  1108.         end
  1109.       else
  1110.         r.Left := 0;
  1111.       s := DrawItems.GetSubString(DItemNo, Items, StartOffs, EndOffs-StartOffs+1);
  1112.       s := RV_ReturnProcessedString(s, RVStyle.TextStyles[No],
  1113.         (EndOffs+1>=GetOffsAfterDrawItem(DItemNo)) and IsDrawItemLastOnWrappedLine(DItemNo),
  1114.         rvoShowSpecialCharacters in Options, True);
  1115.       r.Right := r.Left+ RVU_TextWidth(s, Canvas, GetItemOptions(ditem.ItemNo));
  1116.     end;
  1117.     r.Top := 0;
  1118.     r.Bottom := ditem.Height;
  1119.     {$IFNDEF RVDONOTUSEJUSTIFY}
  1120.     OffsetRect(r, ditem.SpaceBefore, 0);
  1121.     {$ENDIF}
  1122.   end;
  1123.   procedure DrawWordPainters;
  1124.   var i,j, Offs1, Offs2: Integer;
  1125.       List: TRVWordPainterList;
  1126.       ditem: TRVDrawLineInfo;
  1127.       r: TRect;
  1128.   begin
  1129.     for i := FirstDLine to LastDLine do
  1130.       if GetItem(DrawItems[i].ItemNo).WordPaintList<>nil then begin
  1131.         ditem := DrawItems[i];
  1132.         No := GetActualStyle(GetItem(ditem.ItemNo));
  1133.         if No<>LastDrawnStyle then begin
  1134.           LastDrawnStyle := No;
  1135.           RVStyle.ApplyStyle(Canvas, No, GetParaBiDiMode(GetItemPara(ditem.ItemNo)), True);
  1136.         end;
  1137.         BiDiMode := GetParaBiDiMode(GetItemPara(ditem.ItemNo));
  1138.         List := GetItem(ditem.ItemNo).WordPaintList;
  1139.         for j := 0 to List.Count-1 do begin
  1140.           Offs1 := List[j].StartOffs;
  1141.           Offs2  := Offs1+List[j].Length;
  1142.           if (ditem.Offs>Offs2) or (ditem.Offs+ditem.Length<Offs1) then
  1143.             continue;
  1144.           GetSubItemRect(i, Offs1, Offs2-1, ditem, r);
  1145.           OffsetRect(r, ditem.Left-xshift, ditem.Top-yshift);
  1146.           List[j].Draw(Canvas, ditem, Self, r, j);
  1147.         end;
  1148.       end;
  1149.   end;
  1150.   {$ENDIF}
  1151.   {.......................................................}
  1152.   var
  1153.     AParaNo, MaxTextWidth: Integer;
  1154.     BelowBottom: Boolean;
  1155.     BRect, BRect1: TRect;
  1156.     DrawState: TRVItemDrawStates;
  1157.     TextDrawState: TRVTextDrawStates;
  1158.     ShiftedClipRect: TRect;
  1159. begin
  1160.   RVStyle := GetRVStyle;
  1161.   GetSelBounds(StartNo, EndNo, StartOffs, EndOffs, True);
  1162.   ShiftedClipRect := AClipRect;
  1163.   yshift := GetZVOffs;
  1164.   xshift := GetZHOffs;
  1165.   OffsetRect(ShiftedClipRect,xshift,yshift);
  1166.   inc(yshift, AClipRect.Top);
  1167.   inc(xshift, AClipRect.Left);
  1168.   OffsetRect(AClipRect,-AClipRect.Left,-AClipRect.Top);
  1169.   Canvas.Brush.Style := bsClear;
  1170.   LastDrawnStyle := -1;
  1171.   BiDiMode       := rvbdUnspecified;
  1172.   DefaultTextDrawState := [];
  1173.   DefaultDrawState := [];
  1174.   ShowSpecialCharacters := rvoShowSpecialCharacters in GetOptions;
  1175.   if TRVScroller(GetParentControl).FocusedEx then begin
  1176.     Include(DefaultTextDrawState, rvtsControlFocused);
  1177.     Include(DefaultDrawState, rvidsControlFocused);
  1178.   end;
  1179.    {
  1180.   if GetMaxTextWidth<>0 then begin
  1181.     Canvas.Pen.Color := clBtnFace;
  1182.     Canvas.MoveTo(GetLeftMargin+GetMaxTextWidth-xshift, AClipRect.Top);
  1183.     Canvas.LineTo(GetLeftMargin+GetMaxTextWidth-xshift, AClipRect.Bottom);
  1184.   end;
  1185.    }
  1186.   // drawing paragraph backgrounds and frames...
  1187.   FirstDLine := GetFirstVisible(ShiftedClipRect.Top);
  1188.   LastDLine  := DrawItems.Count-1;
  1189.   BelowBottom := False;
  1190.   i := FirstDLine;
  1191.   while (i>0) and
  1192.        ((DrawItems[i].ItemNo=DrawItems[i-1].ItemNo) or
  1193.          not GetItem(DrawItems[i].ItemNo).CanBeBorderStart) do
  1194.     dec(i);
  1195.   MaxTextWidth := GetMaxTextWidth;
  1196.   while i<DrawItems.Count do begin
  1197.     dli := DrawItems[i];
  1198.     if BelowBottom and dli.FromNewLine then begin
  1199.       if LastDLine>i then
  1200.         LastDLine := i;
  1201.       break;
  1202.     end;
  1203.     if GetItem(dli.ItemNo).CanBeBorderStart and
  1204.       (GetItem(dli.ItemNo).StyleNo<>rvsBreak) and
  1205.       (
  1206.       (RVStyle.ParaStyles[GetItemPara(dli.ItemNo)].Border.Style<>rvbNone) or
  1207.       (RVStyle.ParaStyles[GetItemPara(dli.ItemNo)].Background.Color<>clNone) or
  1208.       Assigned(RVStyle.OnDrawParaBack)
  1209.       ) then begin
  1210.       AParaNo := GetItemPara(dli.ItemNo);
  1211.       with RVStyle.ParaStyles[AParaNo] do begin
  1212.         BRect.Left := GetLeftMargin+LeftIndent;
  1213.         if FirstIndent<0 then
  1214.           inc(BRect.Left, FirstIndent);
  1215.         if rvoClientTextWidth in Self.Options then
  1216.           BRect.Right := GetWidth-(GetRightMargin+RightIndent)
  1217.         else if MaxTextWidth>0 then
  1218.           BRect.Right := GetLeftMargin+MaxTextWidth-RightIndent
  1219.         else
  1220.           BRect.Right := GetAreaWidth-(GetRightMargin+RightIndent);
  1221.         if dli.Left+dli.Width>BRect.Right then
  1222.           BRect.Right := dli.Left+dli.Width;
  1223.       end;
  1224.       BRect.Top := dli.Top;
  1225.       BRect.Bottom := dli.Top+dli.Height+dli.ExtraSpaceBelow;
  1226.       inc(i);
  1227.       while (i<DrawItems.Count) and
  1228.             ((DrawItems[i].ItemNo=DrawItems[i-1].ItemNo) or
  1229.              not GetItem(DrawItems[i].ItemNo).CanBeBorderStart) do begin
  1230.         dli := DrawItems[i];
  1231.         if dli.Top<BRect.Top then
  1232.           BRect.Top := dli.Top;
  1233.         if dli.Top+dli.Height+dli.ExtraSpaceBelow>BRect.Bottom then
  1234.           BRect.Bottom := dli.Top+dli.Height+dli.ExtraSpaceBelow;
  1235.         if dli.Left+dli.Width>BRect.Right then
  1236.           BRect.Right := dli.Left+dli.Width;
  1237.         if BelowBottom and dli.FromNewLine and (LastDLine>i) then
  1238.            LastDLine := i;
  1239.         if (dli.Top>ShiftedClipRect.Bottom) and (GetMaxTextWidth=0) then
  1240.           BelowBottom := True;
  1241.         inc(i);
  1242.       end;
  1243.       OffsetRect(BRect, -xshift, -yshift);
  1244.       BRect1 := BRect;
  1245.       RVStyle.ParaStyles[AParaNo].Background.PrepareDraw(BRect1);
  1246.       RVStyle.ItemNo := DrawItems[i-1].ItemNo;
  1247.       RVStyle.RVData := Self;
  1248.       RVStyle.DrawParaBack(Canvas, AParaNo, BRect1, False, rvcmColor);
  1249.       RVStyle.ParaStyles[AParaNo].Border.Draw(BRect, Canvas);
  1250.       end
  1251.     else
  1252.       inc(i);
  1253.     if dli.Top>ShiftedClipRect.Bottom then
  1254.       BelowBottom := True;
  1255.   end;
  1256.   // drawing items...
  1257.   if Assigned(RVStyle.OnDrawTextBack) then
  1258.     for i:= FirstDLine to LastDLine do begin
  1259.       dli := DrawItems[i];
  1260.       with GetItem(dli.ItemNo) do
  1261.         if StyleNo>=0 then begin
  1262.           TextDrawState := [];
  1263.           if RVStyle.TextStyles[GetActualStyleNo(RVStyle)].Jump and
  1264.              (rvstDrawHover in State) and
  1265.              (LastJumpMovedAbove<>-1) and (JumpID = LastJumpMovedAbove) then
  1266.             Include(TextDrawState, rvtsHover);
  1267.           RVStyle.DrawTextBack(Canvas, dli.ItemNo, GetActualStyleNo(RVStyle),
  1268.             Self, dli.Left-xshift, dli.Top-yshift, dli.Width, dli.Height,
  1269.             TextDrawState);
  1270.         end;
  1271.     end;
  1272.   // drawing soft page breaks
  1273.   if (FSoftPageBreaks<>nil) and (rvoShowPageBreaks in Options) then
  1274.     DrawSoftPageBreaks;
  1275.   LineTopY := 0;
  1276.   LineBottomY := 0;
  1277.   for i:= FirstDLine to LastDLine do begin
  1278.     dli := DrawItems[i];
  1279.     if dli.FromNewLine and UseLineSelection(dli) then
  1280.       GetLineVerticalBounds(i, LineTopY, LineBottomY);
  1281.     li := GetItem(dli.ItemNo);
  1282.     no := GetActualStyle(li);
  1283.     if (rvioPageBreakBefore in li.ItemOptions) and
  1284.        (rvoShowPageBreaks in Options) and
  1285.        ((i=0) or (DrawItems[i-1].ItemNo<>dli.ItemNo))
  1286.        then begin
  1287.       RVStyle.DrawPageBreak(Canvas, GetLineTopY(i)-yshift-1, xshift, rvpbPageBreak, GetParentControl);
  1288.       LastDrawnStyle := -1;
  1289.     end;
  1290.     if (li.Checkpoint<>nil) and (rvoShowCheckpoints in Options) and
  1291.        ((i=0) or (DrawItems[i-1].ItemNo<>dli.ItemNo)) then begin
  1292.       RVStyle.DrawCheckpoint(Canvas, dli.Left-xshift, dli.Top-yshift,
  1293.         0, GetParentControl.Width,
  1294.         Self, dli.ItemNo, xshift, li.Checkpoint.RaiseEvent,
  1295.         GetParentControl);
  1296.       LastDrawnStyle := -1;
  1297.     end;
  1298.     if no>=0 then begin { text }
  1299.       if No<>LastDrawnStyle then begin
  1300.         LastDrawnStyle := No;
  1301.         RVStyle.ApplyStyle(Canvas, No, GetParaBiDiMode(li.ParaNo), True);
  1302.       end;
  1303.       BiDiMode := GetItemBiDiMode(dli.ItemNo);
  1304.       HoverNow := RVStyle.TextStyles[no].Jump and (rvstDrawHover in State) and
  1305.                  (LastJumpMovedAbove<>-1) and (li.JumpID = LastJumpMovedAbove);
  1306.       if ((StartNo>i) or (EndNo<i)) and
  1307.          not (rvstCompletelySelected in State) then begin {not selected}
  1308.         DrawText(dli.Left, dli.Top, dli.Width, 1, i,
  1309.           RV_ReturnProcessedString(DrawItems.GetString(i,Items),
  1310.             RVStyle.TextStyles[No], IsDrawItemLastOnWrappedLine(i),
  1311.             ShowSpecialCharacters, True),
  1312.           True, True, False,True);
  1313.         end
  1314.       else if (rvstCompletelySelected in State) or
  1315.           (((StartNo<i) or ((StartNo=i) and (StartOffs<=1))) and {selected completely}
  1316.            (((EndNo>i)) or ((EndNo=i) and (EndOffs>DrawItems[i].Length)))) then begin
  1317.         DrawText(dli.Left, dli.Top, dli.Width, 1, i,
  1318.           RV_ReturnProcessedString(DrawItems.GetString(i,Items),
  1319.             RVStyle.TextStyles[No], IsDrawItemLastOnWrappedLine(i),
  1320.             ShowSpecialCharacters, True),
  1321.           True, True, True, True);
  1322.         end
  1323.       else begin { selected partially }
  1324.         DrawText(dli.Left, dli.Top, dli.Width, 1, i,
  1325.           RV_ReturnProcessedString(DrawItems.GetString(i,Items),
  1326.             RVStyle.TextStyles[No], IsDrawItemLastOnWrappedLine(i),
  1327.             ShowSpecialCharacters, True),
  1328.           True, True, False,True);
  1329.         if (i<>StartNo) or (StartOffs<=1) then
  1330.           ditemselstart := 1
  1331.         else
  1332.           ditemselstart := StartOffs;
  1333.         if (i<>EndNo) or (EndOffs>dli.Length) then
  1334.           ditemselend := dli.Length
  1335.         else
  1336.           ditemselend := EndOffs-1;
  1337.         if ditemselend<ditemselstart then begin
  1338.           if ShowSpecialCharacters and (rvscParagraph in RVVisibleSpecialCharacters) then
  1339.             DrawParaMarkAfter(i);
  1340.           continue;
  1341.         end;
  1342.         s  := DrawItems.GetString(i,Items);
  1343.         if BiDiMode<>rvbdUnspecified then begin
  1344.           s := RV_ReturnProcessedString(s, RVStyle.TextStyles[No],
  1345.             (ditemselend>=GetOffsAfterDrawItem(i)) and IsDrawItemLastOnWrappedLine(i),
  1346.             ShowSpecialCharacters, True);
  1347.           RVStyle.ApplyStyleColor(Canvas, no, GetSelDrawState, False, rvcmColor);
  1348.           res := RVU_DrawSelectedTextEx(dli.Left{$IFNDEF RVDONOTUSEJUSTIFY}+dli.SpaceBefore{$ENDIF}-xshift,
  1349.             dli.Top-yshift, dli.Width{$IFNDEF RVDONOTUSEJUSTIFY}-dli.SpaceBefore{$ENDIF},
  1350.             dli.Height, s, Canvas, ditemselstart, ditemselend, li.ItemOptions,
  1351.             BiDiMode);
  1352.           end
  1353.         else
  1354.           res := False;
  1355.         if not res then begin
  1356.           if ditemselstart>1 then begin
  1357.             s := DrawItems.GetSubString(i, Items, 1, ditemselstart-1);
  1358.             s  := RV_ReturnProcessedString(s, RVStyle.TextStyles[No], False,
  1359.               ShowSpecialCharacters, True);
  1360.             fullwidth := RVU_TextWidth(s, Canvas, li.ItemOptions);
  1361.             end
  1362.           else
  1363.             fullwidth := 0;
  1364.           s := DrawItems.GetSubString(i, Items, ditemselstart, ditemselend-ditemselstart+1);
  1365.           s := RV_ReturnProcessedString(s, RVStyle.TextStyles[No],
  1366.             (ditemselend+1>=GetOffsAfterDrawItem(i)) and IsDrawItemLastOnWrappedLine(i),
  1367.               ShowSpecialCharacters, True);
  1368.           if Assigned(RVStyle.OnDrawStyleText) or
  1369.             (RVStyle.SelectionStyle=rvssLines) then begin
  1370.             selwidth := RVU_TextWidth(s, Canvas, li.ItemOptions);
  1371.             end
  1372.           else
  1373.             selwidth := 0;
  1374.           DrawText(dli.Left+fullwidth, dli.Top, selwidth, ditemselstart, i,
  1375.                    s, ditemselstart<=1, ditemselend>=dli.Length, True, False);
  1376.         end;
  1377.       end;
  1378.       if ShowSpecialCharacters and (rvscParagraph in RVVisibleSpecialCharacters) then
  1379.         DrawParaMarkAfter(i);
  1380.       continue;
  1381.     end;
  1382.     DrawState := DefaultDrawState;
  1383.     if ((StartNo<=i) and (EndNo>=i) and
  1384.       not ((EndNo=i) and (EndOffs=0)) and
  1385.       not ((StartNo=i) and (StartOffs=1))) or
  1386.       (rvstCompletelySelected in State) then
  1387.       Include(DrawState,rvidsSelected);
  1388.     if (rvstDrawHover in State) and
  1389.        (LastJumpMovedAbove<>-1) and (li.JumpID = LastJumpMovedAbove) and
  1390.        li.GetBoolValueEx(rvbpJump, RVStyle) then
  1391.       Include(DrawState, rvidsHover);
  1392.     if GetParaBiDiMode(GetItemPara(dli.ItemNo))=rvbdRightToLeft then
  1393.       Include(DrawState, rvidsRTL);
  1394.     if ShowSpecialCharacters then
  1395.       Include(DrawState, rvidsShowSpecialCharacters);
  1396.     if (li = FActiveItem) then
  1397.       Include(DrawState, rvidsCurrent);
  1398.     if (rvflCanUseCustomPPI in Flags) then
  1399.       Include(DrawState, rvidsCanUseCustomPPI);
  1400.     if not li.GetBoolValue(rvbpFullWidth) then begin
  1401.       // controls, pictures, bullets, hotspots, etc.
  1402.         if (rvidsSelected in DrawState) and UseLineSelection(dli)
  1403.           {$IFNDEF RVDONOTUSELISTS} and (li.StyleNo<>rvsListMarker) {$ENDIF}
  1404.           then begin
  1405.           if rvidsControlFocused in DefaultDrawState then
  1406.             Canvas.Brush.Color := RVStyle.SelColor
  1407.           else
  1408.             Canvas.Brush.Color := RVStyle.InactiveSelColor;
  1409.           if Canvas.Brush.Color<>clNone then begin
  1410.             Canvas.Brush.Style := bsSolid;
  1411.             Canvas.FillRect(Rect(dli.Left-xshift, LineTopY-yshift,
  1412.               dli.Left-xshift+dli.Width, LineBottomY-yshift));
  1413.           end;
  1414.           Canvas.Brush.Style := bsClear;
  1415.         end;
  1416.       li.Paint(dli.Left-xshift, dli.Top-yshift, Canvas, DrawState, RVStyle, dli)
  1417.       end
  1418.     else begin
  1419.       // breaks, tables
  1420.       if rvoClientTextWidth in Options then
  1421.         fullwidth := GetWidth
  1422.       else begin
  1423.         fullwidth := GetAreaWidth;
  1424.         if (GetMaxTextWidth>0) and (GetMaxTextWidth+GetLeftMargin+GetRightMargin<fullwidth) then
  1425.           fullwidth := GetMaxTextWidth+GetLeftMargin+GetRightMargin;
  1426.       end;
  1427.       li.PaintFullWidth(dli.Left-xshift, fullwidth-GetRightMargin-xshift,
  1428.                                 dli.Top-yshift, Canvas, DrawState, RVStyle, AClipRect, dli);
  1429.     end;
  1430.     if ShowSpecialCharacters and (rvscParagraph in RVVisibleSpecialCharacters) then
  1431.       DrawParaMarkAfter(i);
  1432.     if li.GetBoolValue(rvbpDrawingChangesFont) then
  1433.       LastDrawnStyle := -1;
  1434.   end;
  1435.   {$IFNDEF RVDONOTUSELIVESPELL}
  1436.   DrawWordPainters;
  1437.   {$ENDIF}
  1438.   if (NotAddedCP<>nil) and (rvoShowCheckpoints in Options) then
  1439.     RVStyle.DrawCheckpoint(Canvas, -1, DocumentHeight-yshift,
  1440.       0, GetParentControl.Width,
  1441.       Self, -1, xshift, NotAddedCP.RaiseEvent, GetParentControl);
  1442.   PostPaintTo(Canvas, xshift, yshift, FirstDLine, LastDLine);
  1443.   {$IFDEF RVWATERMARK}
  1444.   if rvflRoot in Flags then begin
  1445.     Canvas.Brush.Style := bsClear;
  1446.     Canvas.Font.Name := 'Arial';
  1447.     Canvas.Font.Size := 8;
  1448.     Canvas.Font.Style := [];
  1449.     Canvas.Font.Color := clRed;
  1450.     Canvas.TextOut(-xshift+GetWidth-80, -yshift, 'unregistered');
  1451.   end;
  1452.   {$ENDIF}
  1453. end;
  1454. {------------------------------------------------------------------------------}
  1455. procedure TCustomRVFormattedData.GetItemBackground(ItemNo: Integer; r: TRect;
  1456.   MakeImageRect: Boolean;
  1457.   var Color: TColor; var bmp: TBitmap; var UseBitmap: Boolean);
  1458. var item: TRVRectItemInfo;
  1459.     ditem: TRVDrawLineInfo;
  1460. begin
  1461.   UseBitmap := False;
  1462.   Color := GetRVStyle.ParaStyles[GetItemPara(ItemNo)].Background.Color;
  1463.   if Color<>clNone then
  1464.     exit;
  1465.   Color := GetColor;
  1466.   if (GetBackground=nil) or (GetBackground.Style=bsNoBitmap) then
  1467.     exit;
  1468.   if bmp=nil then
  1469.     bmp := TBitmap.Create;
  1470.   item := TRVRectItemInfo(GetItem(ItemNo));
  1471.   if (item.DrawItemNo<0) or (item.DrawItemNo>=DrawItems.Count) then
  1472.     exit;
  1473.   UseBitmap := True;
  1474.   ditem := DrawItems[item.DrawItemNo];
  1475.   if MakeImageRect then
  1476.     r := Bounds(ditem.Left+item.GetBorderWidth, ditem.Top+item.GetBorderHeight,
  1477.       item.GetImageWidth(nil), item.GetImageHeight(nil));
  1478.   bmp.Width := r.Right-r.Left;
  1479.   bmp.Height := r.Bottom-r.Top;
  1480.   bmp.Canvas.Brush.Style := bsSolid;
  1481.   bmp.Canvas.Brush.Color := Color;
  1482.   bmp.Canvas.FillRect(Rect(0,0,bmp.Width,bmp.Height));
  1483.   OffsetRect(r, -GetHOffs, -GetVOffs);
  1484.   DrawBackground(bmp.Canvas, r);
  1485. end;
  1486. {------------------------------------------------------------------------------}
  1487. procedure TCustomRVFormattedData.PostPaintTo(Canvas: TCanvas;
  1488.   HOffs, VOffs, FirstDrawItemNo, LastDrawItemNo: Integer);
  1489. begin
  1490. end;
  1491. {------------------------------------------------------------------------------}
  1492. procedure TCustomRVFormattedData.MouseLeave;
  1493. var id: Integer;
  1494. begin
  1495.   if not (rvflUseJumps in Flags) then
  1496.     exit;
  1497.   if LastRVDataMovedAbove<>nil then
  1498.     id := LastRVDataMovedAbove.LastJumpMovedAbove
  1499.   else
  1500.     id := -1;
  1501.   ClearLastJump;
  1502.   if id<>-1 then
  1503.     InvalidateJumpRect(id);
  1504. end;
  1505. {------------------------------------------------------------------------------}
  1506. procedure TCustomRVFormattedData.InvalidateJumpRect(id: Integer);
  1507. var rec: TRect;
  1508.     i : Integer;
  1509. begin
  1510.    if GetRVStyle.FullRedraw then
  1511.      Invalidate
  1512.    else begin
  1513.      for i:=0 to Jumps.Count -1 do
  1514.        if id = TRVJumpInfo(Jumps[i]).id then
  1515.          with TRVJumpInfo(Jumps[i]) do begin
  1516.            rec := Bounds(l-GetZHOffs-5, t-GetZVOffs-5, w+10, h+10);
  1517.            InvalidateRect(rec);
  1518.          end;
  1519.    end;
  1520.    GetParentControl.Update;
  1521. end;
  1522. {------------------------------------------------------------------------------}
  1523. procedure TCustomRVFormattedData.Invalidate;
  1524. begin
  1525.   if GetParentControl<>nil then
  1526.     GetParentControl.Invalidate;
  1527. end;
  1528. {------------------------------------------------------------------------------}
  1529. procedure TCustomRVFormattedData.Refresh;
  1530. begin
  1531.   if GetParentControl<>nil then
  1532.     GetParentControl.Refresh;
  1533. end;
  1534. {------------------------------------------------------------------------------}
  1535. procedure TCustomRVFormattedData.UpdateView;
  1536. begin
  1537.   if GetParentControl<>nil then
  1538.     GetParentControl.Update;
  1539. end;
  1540. {------------------------------------------------------------------------------}
  1541. procedure TCustomRVFormattedData.InvalidateRect(const r: TRect);
  1542. begin
  1543.   if (GetParentControl<>nil) and GetParentControl.HandleAllocated then
  1544.     Windows.InvalidateRect(GetParentControl.Handle, @r, False);
  1545. end;
  1546. {------------------------------------------------------------------------------}
  1547. procedure TCustomRVFormattedData.SearchHotItem(X,Y,HOffs,VOffs: Integer);
  1548. begin
  1549.   if FCaptureMouseItem<>nil then
  1550.     exit;
  1551.   inc(X, HOffs);
  1552.   inc(Y, VOffs);
  1553.   if (LastDIMovedAbove<>-1) then
  1554.    if (LastDIMovedAbove>=DrawItems.Count) then
  1555.      LastDIMovedAbove := -1
  1556.    else
  1557.      with DrawItems[LastDIMovedAbove] do
  1558.        if not RV_PointInRect(X,Y, Left,Top,Width,Height) then
  1559.          LastDIMovedAbove := -1;
  1560.   if LastDIMovedAbove=-1 then
  1561.     LastDIMovedAbove := FindDrawItemAtPos(X,Y);
  1562. end;
  1563. {------------------------------------------------------------------------------}
  1564. procedure TCustomRVFormattedData.MouseMove(Shift: TShiftState; X, Y: Integer);
  1565. var  JumpFound: Boolean;
  1566.      VOffs, HOffs: Integer;
  1567.     //SelRect: TRect;
  1568.     {...................................................}
  1569.     procedure DisplayRVDataHint;
  1570.     var s,s2: String;
  1571.         pt: TPoint;
  1572.     begin
  1573.       if rvoShowItemHints in GetOptions then begin
  1574.         s2 := GetAbsoluteRootData.GetParentControl.Hint;
  1575.         s := GetItemHint(Self, -1, '');
  1576.         GetAbsoluteRootData.GetParentControl.Hint := s;
  1577.         if s='' then
  1578.           Application.CancelHint
  1579.         else if (s<>s2) then begin
  1580.           GetCursorPos(pt);
  1581.           {$IFDEF RICHVIEWDEF5}
  1582.           Application.ActivateHint(pt);
  1583.           {$ENDIF}
  1584.         end;
  1585.       end;
  1586.     end;
  1587.     {...................................................}
  1588.     function MouseMoveHotItem(HOffs,VOffs: Integer): Boolean;
  1589.     {$IFNDEF RVDONOTUSEDRAGDROP}
  1590.     var DItemNo, DItemOffs: Integer;
  1591.     {$ENDIF}
  1592.     begin
  1593.       SearchHotItem(X,Y,HOffs,VOffs);
  1594.       if (LastDIMovedAbove<>-1) then
  1595.         with DrawItems[LastDIMovedAbove] do begin
  1596.           Result := GetItem(ItemNo).MouseMove(Shift,
  1597.             X-(Left-GetZHOffs),Y-(Top-GetZVOffs), ItemNo, Self);
  1598.           {$IFNDEF RVDONOTUSEDRAGDROP}
  1599.           if not Result and not (ssShift in Shift) and CanStartDragging then begin
  1600.             FindDrawItemForSel(X+HOffs, Y+VOffs, DItemNo, DItemOffs, True);
  1601.             if (DItemNo>=0) and DItem_InsideSelection(DItemNo, DItemOffs) then begin
  1602.               SetCursor(crArrow);
  1603.               Result := True;
  1604.             end;
  1605.           end;
  1606.           {$ENDIF}
  1607.         end
  1608.       else begin
  1609.         DisplayRVDataHint;
  1610.         Result := False;
  1611.       end;
  1612.     end;
  1613.     {...................................................}
  1614.     procedure ChangeSelection;
  1615.     var xs,ys,VPos,HPos,Width,Height: Integer;
  1616.     begin
  1617.       HPos := GetZHOffs;
  1618.       VPos := GetZVOffs;
  1619.       if rvstMakingSelection in State  then begin
  1620.         ys := y;
  1621.         if not (rvflMouseXYAlwaysCorrect in Flags) then begin
  1622.           Height := GetHeight;
  1623.           ZoomInt(Height);
  1624.           if ys<0 then
  1625.             ys := 0
  1626.           else if ys>Height then
  1627.             ys := Height;
  1628.         end;
  1629.         xs := x;
  1630.         if not (rvflMouseXYAlwaysCorrect in Flags) then begin
  1631.           Width := GetWidth;
  1632.           ZoomInt(Width);
  1633.           if xs<0 then
  1634.             xs := 0
  1635.           else if xs>Width then
  1636.             xs := Width;
  1637.         end;
  1638.         if rvstLineSelection in State then begin
  1639.           if AdjustLineSelection(xs+HPos, ys+VPos) then begin
  1640.             ExpandSelectionToLines(False);
  1641.             DoOnSelection(False);
  1642.             Refresh;
  1643.           end;
  1644.           end
  1645.         else if AdjustSelectionByMode(xs+HPos, ys+VPos) then begin
  1646.           DoOnSelection(True);
  1647.           //if LastSelectionRect.Left=-1 then
  1648.             Refresh
  1649.           //else begin
  1650.           //  SelRect := GetClientSelectionRect;
  1651.           //  UnionRect(LastSelectionRect,LastSelectionRect,SelRect);
  1652.           //  InvalidateRect(LastSelectionRect);
  1653.           //  LastSelectionRect := SelRect;
  1654.           //end;
  1655.         end;
  1656.       end;
  1657.     end;
  1658.     {...................................................}
  1659.     function HighlightJump: Boolean;
  1660.     var i,HPos, VPos: Integer;
  1661.         item: TCustomRVItemInfo;
  1662.     begin
  1663.       HPos := GetZHOffs;
  1664.       VPos := GetZVOffs;
  1665.       for i:=0 to jumps.Count-1 do
  1666.         with TRVJumpInfo(Jumps[i]) do
  1667.           if RV_PointInRect(X ,Y, l-HPos, t-VPos, w, h) then begin
  1668.             Result := True;
  1669.             SetCursor(TRVJumpInfo(Jumps[i]).Cursor);
  1670.             if (LastRVDataMovedAbove=nil) or (LastRVDataMovedAbove.LastJumpMovedAbove<>id) then
  1671.               DoRVMouseMove(id+FirstJumpNo);
  1672.             if (LastRVDataMovedAbove<>nil) and (rvstDrawHover in LastRVDataMovedAbove.State) and
  1673.                (LastRVDataMovedAbove.LastJumpMovedAbove<>id) then begin
  1674.               LastRVDataMovedAbove.State := LastRVDataMovedAbove.State - [rvstDrawHover];
  1675.               InvalidateJumpRect(LastRVDataMovedAbove.LastJumpMovedAbove);
  1676.             end;
  1677.             RVData.LastJumpMovedAbove := id;
  1678.             item := RVData.GetItem(RVData.DrawItems[DrawItemNo].ItemNo);
  1679.             item.MouseMove(Shift, X-(RVData.DrawItems[DrawItemNo].Left-HPos),
  1680.               Y-(RVData.DrawItems[DrawItemNo].Top-VPos),
  1681.               RVData.DrawItems[DrawItemNo].ItemNo, RVData);
  1682.             LastRVDataMovedAbove := RVData;
  1683.             if not (rvstDrawHover in RVData.State) then begin
  1684.               if not item.GetBoolValueEx(rvbpHotColdJump,GetRVStyle) then
  1685.                 exit;
  1686.               RVData.State := RVData.State + [rvstDrawHover];
  1687.               InvalidateJumpRect(RVData.LastJumpMovedAbove);
  1688.             end;
  1689.             exit;
  1690.           end;
  1691.       Result := False;
  1692.     end;
  1693.     {...................................................}
  1694. begin
  1695.   if GetRVStyle=nil then exit;
  1696.   if (rvstMakingSelection in State) and not (ssLeft in Shift) then begin
  1697.     State := State-[rvstMakingSelection];
  1698.     FSelectingInfo.Free;
  1699.     FSelectingInfo := nil;
  1700.     //MouseUp(mbLeft, Shift, X, Y);
  1701.   end;
  1702.   HOffs := GetZHOffs;
  1703.   VOffs := GetZVOffs;
  1704.   ZoomInt(X);
  1705.   ZoomInt(Y);
  1706.   ClearXorDrawing;
  1707.   if FCaptureMouseItem=nil then begin
  1708.     ChangeSelection;
  1709.     if (GetRVStyle.LineSelectCursor<>crNone) and not (rvstMakingSelection in State) and
  1710.       (GetBiDiMode<>rvbdRightToLeft) and
  1711.       (X+HOffs<GetLeftMargin) and (rvoAllowSelection in Options) then
  1712.       SetCursor(GetRVStyle.LineSelectCursor)
  1713.     else begin
  1714.       if rvflUseJumps in Flags then begin
  1715.         JumpFound := HighlightJump;
  1716.         if not JumpFound then begin
  1717.           if (LastRVDataMovedAbove<>nil) then begin
  1718.             LastRVDataMovedAbove.State := LastRVDataMovedAbove.State - [rvstDrawHover];
  1719.             InvalidateJumpRect(LastRVDataMovedAbove.LastJumpMovedAbove);
  1720.             LastRVDataMovedAbove.LastJumpMovedAbove := -1;
  1721.             LastRVDataMovedAbove := nil;
  1722.             DoRVMouseMove(-1);
  1723.           end;
  1724.           if not MouseMoveHotItem(HOffs,VOffs) then
  1725.             SetCursor(GetNormalCursor);
  1726.         end
  1727.         end
  1728.       else
  1729.         if not MouseMoveHotItem(HOffs,VOffs) then
  1730.           SetCursor(GetNormalCursor);
  1731.     end;
  1732.     end
  1733.   else
  1734.     if not MouseMoveHotItem(HOffs,VOffs) then
  1735.       SetCursor(GetNormalCursor);
  1736.   XorDrawingEx(X,Y);
  1737. end;
  1738. {------------------------------------------------------------------------------}
  1739. procedure TCustomRVFormattedData.MouseDown(Button: TMouseButton; Shift: TShiftState;
  1740.                                            X, Y: Integer);
  1741. var i,StyleNo, ItemNo, Dummy, HOffs, VOffs: Integer;
  1742.     ClickedWord: String;
  1743.     RVData: TCustomRVFormattedData;
  1744. begin
  1745.  {$IFNDEF RVDONOTUSELIVESPELL}
  1746.   LiveSpellingCheckCurrentItem;
  1747.  {$ENDIF}
  1748.   HOffs := GetZHOffs;
  1749.   VOffs := GetZVOffs;
  1750.   ZoomInt(X);
  1751.   ZoomInt(Y);
  1752.   begin
  1753.     SearchHotItem(X,Y, HOffs,VOffs);
  1754.     FClickedDrawItemNo := LastDIMovedAbove;
  1755.     if LastDIMovedAbove<>-1 then begin
  1756.       ItemNo := DrawItems[LastDIMovedAbove].ItemNo;
  1757.       if (FPartialSelectedItem<>GetItem(ItemNo)) and
  1758.          (GetChosenItem<>GetItem(ItemNo)) then begin
  1759.         DeselectPartiallySelectedItem(nil);
  1760.         if not (ssDouble in Shift) then
  1761.           Windows.SetFocus(GetParentControl.Handle);
  1762.       end;
  1763.       if LastDIMovedAbove<>-1 then
  1764.         with DrawItems[LastDIMovedAbove] do begin
  1765.            if (GetInplaceEditor<>nil) and
  1766.              not GetItem(ItemNo).OwnsInplaceEditor(GetInplaceEditor) then begin
  1767.                DestroyInplaceEditor;
  1768.                if not (ssDouble in Shift) then
  1769.                  Windows.SetFocus(GetParentControl.Handle);
  1770.              end;
  1771.            GetItem(ItemNo).MouseDown(Button, Shift, X-(Left-HOffs),Y-(Top-VOffs),
  1772.              ItemNo, Self);
  1773.         end;
  1774.       end
  1775.     else begin
  1776.       ItemNo := -1;
  1777.       DestroyInplaceEditor;
  1778.       if not (ssDouble in Shift) then
  1779.         Windows.SetFocus(GetParentControl.Handle);
  1780.     end;
  1781.     if (GetInplaceEditor=nil) and IsAssignedRVMouseDown then
  1782.       DoRVMouseDown(Button, Shift, ItemNo, X, Y);
  1783.     if (GetInplaceEditor=nil) and (Button=mbLeft) then begin
  1784.       LastJumpDowned := -1;
  1785.       for i:=0 to Jumps.Count-1 do
  1786.         with TRVJumpInfo(Jumps[i]) do
  1787.         if (X>=l-HOffs) and (X<=l+w-HOffs) and
  1788.            (Y>=t-VOffs) and (Y<=t+h-VOffs) then begin
  1789.           LastJumpDowned := id;
  1790.           break;
  1791.         end;
  1792.     end;
  1793.     if (FCaptureMouseItem<>nil) or (GetInplaceEditor<>nil) then begin
  1794.       if LastDIMovedAbove<>-1 then begin
  1795.         FSelStartNo := LastDIMovedAbove;
  1796.         FSelEndNo := LastDIMovedAbove;
  1797.         FSelStartOffs := 1;
  1798.         FSelEndOffs   := 1;
  1799.         DoOnSelection(True);
  1800.       end;
  1801.       exit;
  1802.     end;
  1803.   end;
  1804.   if (Button = mbLeft) and not (rvstIgnoreNextMouseDown in State) and not
  1805.      (rvstStartingDragDrop in GetAbsoluteRootData.State) then begin
  1806.     if (rvoSingleClick in Options) and IsAssignedRVDblClick  and
  1807.        FindWordAt(Clickedword, X, Y, StyleNo, ItemNo, Dummy, RVData) then
  1808.       DoRVDblClick(ClickedWord, StyleNo);
  1809.     if (rvoAllowSelection in Options) and  (ssLeft in Shift) then begin
  1810.       State := State - [rvstLineSelection];
  1811.       DeselectPartiallySelectedItem(nil);
  1812.       GetSelStart(FSelStartNo,FSelStartOffs);
  1813.       FindDrawItemForSel(X+HOffs, Y+VOffs, ItemNo, Dummy, False);
  1814.       {$IFNDEF RVDONOTUSEDRAGDROP}
  1815.       if not (ssShift in Shift) and (X+HOffs>=GetLeftMargin) and
  1816.          not (rvstDragDropCursorNotMoved in GetAbsoluteRootData.State) and
  1817.          DItem_InsideSelection(ItemNo, Dummy) and CanStartDragging then begin
  1818.         GetAbsoluteRootData.State := GetAbsoluteRootData.State+[rvstStartingDragDrop];
  1819.         PostMessage(GetAbsoluteRootData.GetParentControl.Handle, WM_RVDRAGDROP, 0, 0);
  1820.         end
  1821.       else
  1822.       {$ENDIF}
  1823.       begin
  1824.         FSelEndNo := ItemNo;
  1825.         FSelEndOffs := Dummy;
  1826.         if not (ssShift in Shift) or (FSelStartNo=-1) then begin
  1827.           FSelStartNo   := FSelEndNo;
  1828.           FSelStartOffs := FSelEndOffs;
  1829.         end;
  1830.         if (FSelEndNo<>-1) then begin
  1831.           State := State + [rvstMakingSelection];
  1832.           FSelectingInfo.Free;
  1833.           FSelectingInfo := nil;
  1834.           if (GetRVStyle.LineSelectCursor<>crNone) and (GetBiDiMode<>rvbdRightToLeft) and
  1835.              (X+HOffs<GetLeftMargin) and
  1836.              not (ssShift in Shift) then begin
  1837.             State := State + [rvstLineSelection];
  1838.             ExpandSelectionToLines(True);
  1839.             end
  1840.           else begin
  1841.             if (GetRVStyle.SelectionMode in [rvsmWord, rvsmParagraph]) then begin
  1842.               FSelectingInfo := TRVSelectingInfo.Create;
  1843.               FSelectingInfo.DrawItemSOffs := FSelStartOffs;
  1844.               FSelectingInfo.DrawItemEOffs := FSelStartOffs;
  1845.               FSelectingInfo.DrawItemSNo   := FSelStartNo;
  1846.               if GetRVStyle.SelectionMode = rvsmParagraph then begin
  1847.                 FSelectingInfo.InitE(rvsesParaMode);
  1848.                 if ssShift in Shift then
  1849.                   AdjustSelectionByMode(X+HOffs, Y+VOffs);
  1850.                 end
  1851.               else begin
  1852.                 if InsideWord(FSelStartNo, FSelStartOffs) then begin
  1853.                   GetWordBounds(FSelStartNo, FSelStartOffs,
  1854.                     FSelectingInfo.DrawItemSWordOffs1, FSelectingInfo.DrawItemSWordOffs2);;
  1855.                   FSelectingInfo.InitE(rvsesInWord)
  1856.                   end
  1857.                 else
  1858.                   FSelectingInfo.InitE(rvsesFreeMode);
  1859.               end;
  1860.             end;
  1861.           end;
  1862.           end
  1863.         else
  1864.           State := State - [rvstMakingSelection];
  1865.         DoOnSelection(True);
  1866.         Invalidate;
  1867.       end;
  1868.       //LastSelectionRect := GetClientSelectionRect;
  1869.     end;
  1870.   end;
  1871. end;
  1872. {------------------------------------------------------------------------------}
  1873. procedure TCustomRVFormattedData.MouseUp(Button: TMouseButton; Shift: TShiftState;
  1874.                                    X, Y: Integer);
  1875. var i, StyleNo, no, xs, ys: Integer;
  1876.     clickedword: String;
  1877.     p: TPoint;
  1878.     DoNotJump: Boolean;
  1879.     ItemNo, ItemOffs, Dummy: Integer;
  1880.     ASelStartNo, ASelEndNo, ASelStartOffs, ASelEndOffs: Integer;
  1881.     HOffs, VOffs, Width, Height: Integer;
  1882.     RVData: TCustomRVFormattedData;
  1883. begin
  1884.   HOffs := GetZHOffs;
  1885.   VOffs := GetZVOffs;
  1886.   Height := GetHeight;
  1887.   Width := GetWidth;
  1888.   ZoomInt(X);
  1889.   ZoomInt(Y);
  1890.   ZoomInt(Width);
  1891.   ZoomInt(Height);
  1892.   DoNotJump := SelectionExists(True, True);
  1893.   {$IFDEF RVMUDESELECT}
  1894.   if rvstMidSelClicked in State then begin
  1895.     State := State - [rvstMidSelClicked];
  1896.     Deselect(nil, True);
  1897.     Invalidate;
  1898.   end;
  1899.   {$ENDIF}
  1900.   if FCaptureMouseItem=nil then begin
  1901.     State := State - [rvstIgnoreNextMouseDown];
  1902.     if (rvstMakingSelection in State) and (Button = mbLeft) then begin
  1903.       ys := y;
  1904.       if not (rvflMouseXYAlwaysCorrect in Flags) then
  1905.         if ys<0 then
  1906.           ys := 0
  1907.         else if ys>Height then
  1908.           ys := Height;
  1909.       xs := x;
  1910.       if not (rvflMouseXYAlwaysCorrect in Flags) then
  1911.         if xs<0 then
  1912.           xs := 0
  1913.         else if xs>Width then
  1914.           xs := Width;
  1915.       if rvstLineSelection in State then
  1916.         AdjustLineSelection(xs+HOffs, ys+VOffs)
  1917.       else
  1918.         AdjustSelectionByMode(xs+HOffs, ys+VOffs);
  1919.       State := State - [rvstMakingSelection, rvstLineSelection];
  1920.       FSelectingInfo.Free;
  1921.       FSelectingInfo := nil;
  1922.       SearchHotItem(X,Y, HOffs,VOffs);      
  1923.       AdjustMouseUpSelection;      
  1924.       DoOnSelection(True);
  1925.       Invalidate;
  1926.       DoSelect;
  1927.     end;
  1928.     if (rvoRClickDeselects in Options) and (Button = mbRight) then begin
  1929.       GetSelBounds(ASelStartNo, ASelEndNo, ASelStartOffs, ASelEndOffs, True);
  1930.       FindDrawItemForSel(X+HOffs, Y+VOffs, ItemNo, ItemOffs, False);
  1931.       if (ItemNo<>-1) and
  1932.          (((ItemNo<ASelStartNo) or ((ItemNo=ASelStartNo) and (ItemOffs<ASelStartOffs))) or
  1933.          ((ItemNo>ASelEndNo)    or ((ItemNo=ASelEndNo)   and (ItemOffs>ASelEndOffs)))) then begin
  1934.         FSelStartNo   := ItemNo;
  1935.         FSelStartOffs := ItemOffs;
  1936.         FSelEndNo   := ItemNo;
  1937.         FSelEndOffs := ItemOffs;
  1938.         DoOnSelection(True);
  1939.         Refresh;
  1940.         DoSelect;
  1941.       end;
  1942.     end;
  1943.   end;
  1944.   SearchHotItem(X,Y, HOffs,VOffs);
  1945.   if LastDIMovedAbove<>-1 then begin
  1946.     ItemNo := DrawItems[LastDIMovedAbove].ItemNo;
  1947.     with DrawItems[LastDIMovedAbove] do
  1948.       GetItem(ItemNo).MouseUp(Button, Shift, X-(Left-HOffs),Y-(Top-VOffs),
  1949.         ItemNo, Self);
  1950.     end
  1951.   else
  1952.     ItemNo := -1;
  1953.   if FCaptureMouseItem<>nil then exit;
  1954.   if not DoNotJump and
  1955.      (Button in [mbLeft, mbRight]) and
  1956.      (ItemNo<>-1) and
  1957.      GetItem(ItemNo).GetBoolValueEx(rvbpAllowsFocus, GetRVStyle) and
  1958.      (GetRootData is TRVControlData) and
  1959.      (TRVControlData(GetRootData).TabNavigation<>rvtnNone)
  1960.    then begin
  1961.      AdjustFocus(ItemNo, Self, ItemNo);
  1962.      GetItem(ItemNo).Focusing;     
  1963.   end;
  1964.   if IsAssignedRVMouseUp then
  1965.     DoRVMouseUp(Button, Shift, ItemNo, X, Y);
  1966.   if (Button = mbRight) and IsAssignedRVRightClick and
  1967.      FindWordAt(ClickedWord, X,Y, StyleNo,no, Dummy, RVData) then begin
  1968.     p := ClientToScreen(Point(X,Y));
  1969.     DoRVRightClick(ClickedWord, StyleNo, p.X, p.Y);
  1970.   end;
  1971.   if Button <> mbLeft then exit;
  1972.   if (LastJumpDowned=-1) or not IsAssignedJump or DoNotJump then
  1973.     exit;
  1974.   for i:=0 to Jumps.Count-1 do
  1975.     with TRVJumpInfo(Jumps[i]) do
  1976.       if (LastJumpDowned=id) and
  1977.          (X>=l-HOffs) and (X<=l+w-HOffs) and
  1978.          (Y>=t-VOffs) and (Y<=t+h-VOffs) then begin
  1979.         LastJumpDowned:=-1;
  1980.         DoJump(id+FirstJumpNo);
  1981.         exit;
  1982.       end;
  1983.   LastJumpDowned:=-1;
  1984.   FClickedDrawItemNo :=-1;
  1985. end;
  1986. {------------------------------------------------------------------------------}
  1987. procedure TCustomRVFormattedData.DblClick;
  1988. var
  1989.   StyleNo, ItemNo, Offs: Integer;
  1990.   ClickedWord: String;
  1991.   p: TPoint;
  1992.   RVData: TCustomRVFormattedData;
  1993. begin
  1994.   if (not (rvoSingleClick  in Options) and IsAssignedRVDblClick) or
  1995.      (rvoDblClickSelectsWord in Options) then begin
  1996.     GetCursorPos(p);
  1997.     p := ScreenToClient(p);
  1998.     //ZoomInt(p.X);
  1999.     //ZoomInt(p.Y);
  2000.     if (rvoDblClickSelectsWord in Options) and (rvoAllowSelection in Options) then begin
  2001.       if FindWordAt(ClickedWord, p.X, p.Y, StyleNo, ItemNo, Offs, RVData) then begin
  2002.         if StyleNo>=0 then
  2003.           RVData.SetSelectionBounds(ItemNo, Offs, ItemNo,
  2004.             Offs+RVU_Length(clickedword,RVData.GetItemOptions(ItemNo)))
  2005.         else
  2006.           RVData.SetSelectionBounds(ItemNo, 0, ItemNo, 1);
  2007.         RVData.State := RVData.State + [rvstIgnoreNextMouseDown];
  2008.         RVData.State := RVData.State - [rvstMakingSelection];
  2009.         Invalidate;
  2010.         State := State - [rvstMakingSelection];
  2011.         DoRVDblClick(ClickedWord, StyleNo);
  2012.         State := State + [rvstIgnoreNextMouseDown];
  2013.       end;
  2014.       exit;
  2015.     end;
  2016.     if IsAssignedRVDblClick and
  2017.        FindWordAt(ClickedWord, p.X, p.Y, StyleNo, ItemNo, Offs, RVData) then
  2018.        DoRVDblClick(ClickedWord, StyleNo);
  2019.   end;
  2020. end;
  2021. {------------------------------------------------------------------------------}
  2022. procedure TCustomRVFormattedData.DeleteItems(FirstItemNo, Count: Integer);
  2023. begin
  2024.   Deselect(nil, True);
  2025.   inherited DeleteItems(FirstItemNo, Count);
  2026. end;
  2027. {------------------------------------------------------------------------------}
  2028. procedure TCustomRVFormattedData.DeleteParas(FirstItemNo, LastItemNo: Integer);
  2029. var FirstItemNo2, LastItemNo2,
  2030.     FirstDItemNo, LastDItemNo, tmp: Integer;
  2031. begin
  2032.   ExpandToPara(FirstItemNo, LastItemNo, FirstItemNo, LastItemNo);
  2033.   FirstItemNo2 := FirstItemNo;
  2034.   LastItemNo2  := LastItemNo;
  2035.   if FirstItemNo2>0 then
  2036.     dec(FirstItemNo2);
  2037.   if LastItemNo2<Items.Count-1 then
  2038.     inc(LastItemNo2);
  2039.   ExpandToPara(FirstItemNo2, LastItemNo2, FirstItemNo2, LastItemNo2);
  2040.   Item2FirstDrawItem(FirstItemNo2, FirstDItemNo);
  2041.   Item2FirstDrawItem(LastItemNo2, LastDItemNo);
  2042.   DeleteItems(FirstItemNo, LastItemNo-FirstItemNo+1);
  2043.   FormatParasExact(FirstDItemNo,LastDItemNo, - (LastItemNo-FirstItemNo+1), False);
  2044.   ClearJumps;  
  2045.   tmp := 0;
  2046.   BuildJumpsCoords(tmp, jumps);
  2047. end;
  2048. {------------------------------------------------------------------------------}
  2049. function TCustomRVFormattedData.SelectionExists(AllowReset: Boolean;UsePartialSelected: Boolean): Boolean;
  2050. var StartNo, EndNo, StartOffs, EndOffs: Integer;
  2051. begin
  2052.   {$IFNDEF RVDONOTUSEINPLACE}
  2053.   if (GetChosenRVData<>nil) then begin
  2054.     Result := TCustomRVFormattedData(GetChosenRVData).SelectionExists(AllowReset, UsePartialSelected);
  2055.     exit;
  2056.   end;
  2057.   {$ENDIF}
  2058.   if rvstMakingSelection in State then
  2059.     AllowReset := False;
  2060.   if UsePartialSelected and
  2061.      (FPartialSelectedItem<>nil) and
  2062.      FPartialSelectedItem.PartiallySelected then begin
  2063.     Result := True;
  2064.     exit;
  2065.   end;
  2066.   GetSelBounds(StartNo, EndNo, StartOffs, EndOffs, True);
  2067.   if (StartNo <> -1) and (StartNo=EndNo) and (StartOffs=EndOffs) then begin
  2068.     if AllowReset then
  2069.       Deselect(FPartialSelectedItem, True);
  2070.     Result := False;
  2071.     exit;
  2072.   end;
  2073.   Result :=  (StartNo<>-1) and (EndNo<>-1);
  2074. end;
  2075. {------------------------------------------------------------------------------}
  2076. procedure TCustomRVFormattedData.SetCursor(Cursor: TCursor);
  2077. begin
  2078.   GetParentControl.Cursor := Cursor;
  2079. end;
  2080. {------------------------------------------------------------------------------}
  2081. function TCustomRVFormattedData.ClientToScreen(const p: TPoint): TPoint;
  2082. begin
  2083.   Result := GetParentControl.ClientToScreen(p);
  2084. end;
  2085. {------------------------------------------------------------------------------}
  2086. function TCustomRVFormattedData.ScreenToClient(const p: TPoint): TPoint;
  2087. begin
  2088.   Result := GetParentControl.ScreenToClient(p);
  2089. end;
  2090. {------------------------------------------------------------------------------}
  2091. procedure TCustomRVFormattedData.GetSelStart(var DINo, DIOffs: Integer);
  2092. begin
  2093.   SelectionExists(True, False);
  2094.   DINo   := FSelStartNo;
  2095.   DIOffs := FSelStartOffs;
  2096. end;
  2097. {------------------------------------------------------------------------------}
  2098. function TCustomRVFormattedData.GetSelectedImage: TGraphic;
  2099. var StartNo, EndNo, StartOffs, EndOffs,Index: Integer;
  2100. begin
  2101.   {$IFNDEF RVDONOTUSEINPLACE}
  2102.   if (GetChosenRVData<>nil) then begin
  2103.     Result := TCustomRVFormattedData(GetChosenRVData).GetSelectedImage;
  2104.     exit;
  2105.   end;
  2106.   {$ENDIF}
  2107.   Result := nil;
  2108.   StoreSelBounds(StartNo, EndNo, StartOffs, EndOffs, True);
  2109.   if (StartNo=-1) then exit;
  2110.   case EndNo-StartNo of
  2111.     0:
  2112.       begin
  2113.         if (StartOffs>0) or (EndOffs<1) then exit;
  2114.         Index := StartNo;
  2115.       end;
  2116.     1:
  2117.       begin
  2118.         if StartOffs>GetOffsBeforeItem(StartNo) then begin
  2119.           if StartOffs<GetOffsAfterItem(StartNo) then exit;
  2120.           if EndOffs<GetOffsAfterItem(EndNo) then exit;
  2121.           Index := StartNo+1
  2122.           end
  2123.         else if EndOffs<GetOffsAfterItem(EndNo) then begin
  2124.           if EndOffs>GetOffsBeforeItem(EndNo) then exit;
  2125.           if StartOffs>GetOffsBeforeItem(StartNo) then exit;
  2126.           Index := StartNo
  2127.           end
  2128.         else
  2129.           exit;
  2130.       end;
  2131.     2:
  2132.       begin
  2133.         if StartOffs<GetOffsAfterItem(StartNo) then exit;
  2134.         if EndOffs>GetOffsBeforeItem(EndNo) then exit;
  2135.         Index := StartNo+1;
  2136.       end;
  2137.     else
  2138.       exit;
  2139.   end;
  2140.   Result := TCustomRVItemInfo(Items.Objects[Index]).AsImage;
  2141. end;
  2142. {------------------------------------------------------------------------------}
  2143. function TCustomRVFormattedData.GetSelText(Unicode: Boolean): String;
  2144. var Stream: TMemoryStream;
  2145. begin
  2146.   {$IFNDEF RVDONOTUSEINPLACE}
  2147.   if (GetChosenRVData<>nil) then begin
  2148.     Result := TCustomRVFormattedData(GetChosenRVData).GetSelText(Unicode);
  2149.     exit;
  2150.   end;
  2151.   {$ENDIF}
  2152.   if not SelectionExists(False, True) then begin
  2153.     Result := '';
  2154.     exit;
  2155.   end;
  2156.   Stream := TMemoryStream.Create;
  2157.   try
  2158.     if SaveTextToStream('', Stream, 80, True, True, Unicode, False) then begin
  2159.       SetLength(Result, Stream.Size);
  2160.       Stream.Position := 0;
  2161.       Stream.ReadBuffer(PChar(Result)^, Stream.Size);
  2162.       end
  2163.     else
  2164.       Result := '';
  2165.   finally
  2166.     Stream.Free;
  2167.   end;
  2168. end;
  2169. {------------------------------------------------------------------------------}
  2170. procedure TCustomRVFormattedData.SrchSelectIt(strt, offs, len: Integer;
  2171.                                               Invert: Boolean);
  2172. begin
  2173.   {$IFNDEF RVDONOTUSELIVESPELL}
  2174.   LiveSpellingCheckCurrentItem;
  2175.   {$ENDIF}
  2176.   DeselectPartiallySelectedItem(nil);
  2177.   if not Invert then
  2178.     RestoreSelBounds(strt,strt,offs,offs+len)
  2179.   else
  2180.     RestoreSelBounds(strt,strt,offs+len,offs);
  2181.   with DrawItems[FSelStartNo] do
  2182.     ShowRectangle(Left,Top,Width,Height);
  2183.   Invalidate;
  2184.   DoOnSelection(True);
  2185.   DoSelect;
  2186. end;
  2187. {------------------------------------------------------------------------------}
  2188. procedure TCustomRVFormattedData.SrchStart(Down: Boolean; var strt, offs: Integer);
  2189. var  sl,so: Integer;
  2190. begin
  2191.   if SelectionExists(True, False) then begin
  2192.     StoreSelBounds(sl, strt, so, offs, False);
  2193.     end
  2194.   else begin
  2195.     if Down then begin
  2196.       strt := GetFirstItemVisible;
  2197.       offs := GetOffsBeforeItem(0);
  2198.       end
  2199.     else begin
  2200.       strt := GetLastItemVisible;
  2201.       offs := GetOffsAfterItem(strt)+1;
  2202.     end;
  2203.   end;
  2204.   if strt<0 then strt := 0;
  2205. end;
  2206. {------------------------------------------------------------------------------}
  2207. function TCustomRVFormattedData.SearchText(Down, MatchCase, WholeWord: Boolean; s:String):Boolean;
  2208.     {....................................................}
  2209.     function FwdPos(const substr, astr: String): Integer;
  2210.     var offs,r,roffs: Integer;
  2211.         str: String;
  2212.     begin
  2213.       str := astr;
  2214.       Result := 0;
  2215.       offs := 0;
  2216.       r := Pos(substr, str);
  2217.       if WholeWord then begin
  2218.         while r <> 0 do begin
  2219.           roffs := offs+r;
  2220.           if ((roffs = 1) or ((roffs > 1) and IsDelimiter(astr, roffs-1, []))) and
  2221.              (((roffs+Length(substr)) > Length(astr)) or
  2222.               (((roffs+Length(substr))<= Length(astr)) and IsDelimiter(astr, roffs+Length(substr),[])))
  2223.               then begin
  2224.             Result := roffs;
  2225.             exit;
  2226.           end;
  2227.           str := System.Copy(str,r+Length(substr),Length(str));
  2228.           inc(offs, r+Length(substr)-1);
  2229.           r := Pos(substr, str);
  2230.         end;
  2231.         end
  2232.       else
  2233.         Result := r;
  2234.     end;
  2235.     {....................................................}
  2236.     function RevPos(substr, str: String): Integer;
  2237.     var offs,r: Integer;
  2238.     begin
  2239.       Result := 0;
  2240.       offs   := 0;
  2241.       while Length(str)<>0 do begin
  2242.         r := FwdPos(Substr, str);
  2243.         if r=0 then exit;
  2244.         Result := offs + r;
  2245.         str := System.Copy(str,r+Length(substr),Length(str));
  2246.         inc(offs, r+Length(substr)-1);
  2247.       end;
  2248.     end;
  2249.     {....................................................}
  2250.     function SearchInItem(item: TCustomRVItemInfo; StoreSub: TRVStoreSubRVData;
  2251.                           SubRVData: TCustomRVFormattedData): Boolean;
  2252.     var SubPos: TRVSubRVDataPos;
  2253.     begin
  2254.       if Down then
  2255.         SubPos := rvdNext
  2256.       else
  2257.         SubPos := rvdPrev;
  2258.       Result := TCustomRVFormattedData(SubRVData.GetRVData).SearchText(Down, MatchCase, WholeWord, s);
  2259.       if not Result then
  2260.         repeat
  2261.           SubRVData := TCustomRVFormattedData(item.GetSubRVData(StoreSub,SubPos));
  2262.           if SubRVData=nil then
  2263.             break;
  2264.           Result := TCustomRVFormattedData(SubRVData.GetRVData).SearchText(Down, MatchCase, WholeWord, s);
  2265.         until Result;
  2266.       if Result then
  2267.         item.ChooseSubRVData(StoreSub);
  2268.       StoreSub.Free;
  2269.     end;
  2270.     {....................................................}
  2271.     procedure UpdateUnicodePos(const editorstring, soughtstring: String;
  2272.                                ItemOptions: TRVItemOptions;
  2273.                                var Offs, Len: Integer);
  2274.     {$IFNDEF RVDONOTUSEUNICODE}
  2275.     var s: String;
  2276.     {$ENDIF}
  2277.     begin
  2278.       {$IFNDEF RVDONOTUSEUNICODE}
  2279.       if not (rvioUnicode in ItemOptions) then
  2280.         exit;
  2281.       s := RVU_AnsiToUnicode(GetDefaultCodePage, soughtstring);
  2282.       Len := Length(s) div 2;
  2283.       s := System.Copy(editorstring, 1, Offs-1);
  2284.       s := RVU_AnsiToUnicode(GetDefaultCodePage, s);
  2285.       Offs := Length(s) div 2+1;
  2286.       {$ENDIF}
  2287.     end;
  2288.     {....................................................}
  2289. var strt, offs, len, i, so: Integer;
  2290.     s2: String;
  2291.     ItemOptions: TRVItemOptions;
  2292.     item: TCustomRVItemInfo;
  2293.     StoreSub: TRVStoreSubRVData;
  2294.     SubPos: TRVSubRVDataPos;
  2295.     SubRVData: TCustomRVFormattedData;
  2296. begin
  2297.   Result := False;
  2298.   if not MatchCase then
  2299.     s := AnsiUpperCase(s);
  2300.   if s='' then exit;
  2301.   if Items.Count=0 then exit;
  2302.   StoreSub := nil;
  2303.   item := GetChosenItem;
  2304.   if item=nil then
  2305.     item := PartialSelectedItem;
  2306.   if item<>nil then begin
  2307.     if Down then
  2308.       SubPos := rvdChosenDown
  2309.     else
  2310.       SubPos := rvdChosenUp;
  2311.     SubRVData := TCustomRVFormattedData(item.GetSubRVData(StoreSub, SubPos));
  2312.     if SubRVData<>nil then begin
  2313.       Result := SearchInItem(item, StoreSub, SubRVData);