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

RichEdit

开发平台:

Delphi

  1.       if (rvfoSaveBinary in RVFOptions) or
  2.          not (rvioUnicode in GetItemOptions(i-SectionBackOffs)) then
  3.         SaveMode := 0
  4.       else
  5.         SaveMode := 3;
  6.      {$ELSE}
  7.      SaveMode := 0;
  8.      {$ENDIF}
  9.      RVFWriteCheckpoint(Stream, rvoTagsArePChars in Options, Header.Item.Checkpoint);
  10.      if MarkerItemNo>=0 then begin
  11.        ItemOptions := RVFGetItemOptions(Header.Item.ItemOptions, MarkerItemNo>=0);
  12.        RVFWriteLine(Stream, Format('%s %d %s %d %d %s',
  13.          [RVFSaveText(GetRVStyle, rvfoUseStyleNames in RVFOptions, Header.StyleNo),
  14.          1,
  15.          RVFSavePara(GetRVStyle, rvfoUseStyleNames in RVFOptions, -1),
  16.          Byte(ItemOptions) and RVItemOptionsMask,
  17.          SaveMode, RVFSaveTag(rvoTagsArePChars in Options, Header.Item.Tag)]));
  18.        RVFWriteLineX(Stream, Items[i-SectionBackOffs],
  19.          rvioUnicode in GetItemOptions(i-SectionBackOffs), SaveMode=3);
  20.        dec(SectionBackOffs);
  21.        MarkerItemNo := -1;
  22.      end;
  23.      if SectionBackOffs=0 then
  24.        exit;
  25.      Tail := '';
  26.      {$IFNDEF RVDONOTUSEITEMHINTS}
  27.      {$IFDEF RICHVIEWCBDEF3}
  28.      if GetItem(i-SectionBackOffs).Hint<>'' then
  29.        Tail := ' '+AnsiQuotedStr(GetItem(i-SectionBackOffs).Hint, '"');
  30.      {$ENDIF}
  31.      {$ENDIF}
  32.      RVFWriteLine(Stream, Format('%s %d %s %d %d %s%s',
  33.        [RVFSaveText(GetRVStyle, rvfoUseStyleNames in RVFOPtions, Header.StyleNo),
  34.        SectionBackOffs,
  35.        RVFSavePara(GetRVStyle, rvfoUseStyleNames in RVFOPtions, Header.ParaNo),
  36.        Byte(Header.Item.ItemOptions) and RVItemOptionsMask,
  37.        SaveMode, RVFSaveTag(rvoTagsArePChars in Options, Header.Item.Tag),
  38.        Tail]));
  39.      for j := i-SectionBackOffs to i-1 do
  40.        RVFWriteLineX(Stream, Items[j], rvioUnicode in GetItemOptions(j), SaveMode=3);
  41.      SectionBackOffs := 0;
  42.    end;
  43.   {.......................................................}
  44.    procedure RVFSetHeaderHeader(i: Integer); // in: Header
  45.    begin
  46.      with GetItem(i) do begin
  47.        Header.Item.Checkpoint := Checkpoint;
  48.        Header.Item.ItemOptions := ItemOptions;
  49.        Header.StyleNo      := StyleNo;
  50.        Header.Item.StyleNo := StyleNo;
  51.        {$IFNDEF RVDONOTUSEITEMHINTS}
  52.        Header.Item.Hint := Hint;
  53.        {$ENDIF}
  54.        if SameAsPrev and not ((i=StartItem) and (SaveScope=rvfss_Page)) then
  55.          Header.ParaNo   := -1
  56.        else
  57.          Header.ParaNo   := ParaNo;
  58.        Header.Item.Tag     := Tag;
  59.      end;
  60.    end;
  61.   {.......................................................}
  62.    procedure RVFWriteNonText(i: Integer; Part: TRVMultiDrawItemPart); // in: Header
  63.    {$IFNDEF RVDONOTUSELISTS}
  64.    var StartFrom: Integer;
  65.        Reset: Boolean;
  66.        marker: TRVMarkerItemInfo;
  67.    {$ENDIF}
  68.    begin
  69.      with GetItem(i) do begin
  70.        RVFWriteCheckpoint(Stream, rvoTagsArePChars in Options, Checkpoint);
  71.        {$IFNDEF RVDONOTUSELISTS}
  72.        if StyleNo=rvsListMarker then begin
  73.          marker := TRVMarkerItemInfo(GetItem(i));
  74.          StartFrom := marker.StartFrom;
  75.          Reset     := marker.Reset;
  76.          if SaveScope=rvfss_Page then begin
  77.            marker.StartFrom := marker.Counter;
  78.            marker.Reset     := True;
  79.          end;
  80.          end
  81.        else begin
  82.          StartFrom := 0;    // avoiding warnings
  83.          Reset     := False;
  84.          marker    := nil;
  85.        end;
  86.        {$ENDIF}
  87.        SaveRVF(Stream, Self, i, Header.ParaNo, Items[i], Part, MarkerItemNo>=0);
  88.        {$IFNDEF RVDONOTUSELISTS}
  89.        if StyleNo=rvsListMarker then begin
  90.          marker.StartFrom := StartFrom;
  91.          marker.Reset     := Reset;
  92.        end;
  93.        {$ENDIF}
  94.        MarkerItemNo := -1;
  95.      end;
  96.    end;
  97.   {.......................................................}
  98.   { Should the first selected item be saved as an empty text line? }
  99.   function ShouldSaveEndOfNonTextItemAsEmptyText: Boolean;
  100.   begin
  101.     Result := (SaveScope=rvfss_Selection) and
  102.       (GetItem(StartItem).AssociatedTextStyleNo>=0) and
  103.       (StartOffs>=GetOffsAfterItem(StartItem)) and
  104.       GetItem(StartItem).GetBoolValue(rvbpSwitchToAssStyleNo) and
  105.       ((StartItem+1=ItemCount) or IsFromNewLine(StartItem+1));
  106.   end;
  107.   {.......................................................}
  108.   { Should the last selected item be saved as an empty text line? }  
  109.   function ShouldSaveBeginningOfNonTextItemAsEmptyText: Boolean;
  110.   begin
  111.     Result := (SaveScope=rvfss_Selection) and
  112.       (GetItem(EndItem).AssociatedTextStyleNo>=0) and
  113.       (EndOffs<=GetOffsBeforeItem(EndItem)) and
  114.       GetItem(EndItem).GetBoolValue(rvbpSwitchToAssStyleNo) and
  115.       IsFromNewLine(EndItem);
  116.   end;
  117.   {.......................................................}
  118. begin
  119.   Result := True;
  120.   if (Items.Count=0) {or (SelectionOnly and not SelectionExists)} then
  121.     exit;
  122.   FillChar(Header, sizeof(Header), 0);
  123.   Header.Item := RichViewTextItemClass.Create(Self);
  124.   try
  125.     RVFSaveVersionInfo;
  126.     if (SaveScope<>rvfss_Selection) and (rvfoSaveBack in RVFOptions) then
  127.       RVFSaveBackground;
  128.     if (rvflRoot in Flags) or (SaveScope=rvfss_Selection) then begin
  129.       {$IFDEF RICHVIEWCBDEF3}
  130.       if (rvfoSaveTextStyles in RVFOptions) then
  131.         RVFSaveStyles(RVF_DOCPROP_TEXTSTYLES, GetRVStyle.TextStyles);
  132.       if (rvfoSaveParaStyles in RVFOptions) and (Self=GetRootData) then begin
  133.         RVFSaveStyles(RVF_DOCPROP_PARASTYLES, GetRVStyle.ParaStyles);
  134.         RVFSaveStyles(RVF_DOCPROP_LISTSTYLES, GetRVStyle.ListStyles);
  135.       end;
  136.       {$ENDIF}
  137.       if (rvfoSaveDocProperties in RVFOptions) and (SaveScope<>rvfss_Page) then
  138.         RVFSaveDocPropertiesStringList;
  139.     end;
  140.     if (SaveScope=rvfss_Page) and (Layout<>nil) then begin
  141.       RVFGetLimits(SaveScope,StartItem,EndItem,StartOffs,EndOffs,StartPart,EndPart);
  142.       if (StartItem>=0) and (StartItem<=EndItem) then begin
  143.         if (StartOffs>GetOffsBeforeItem(StartItem)) or
  144.            ((StartOffs<=GetOffsBeforeItem(StartItem)) and not IsParaStart(StartItem)) then begin
  145.           Layout.FirstParaAborted := 1;
  146.           {$IFNDEF RVDONOTUSELISTS}
  147.           MarkerItemNo := GetFirstParaItem(StartItem);
  148.           if (MarkerItemNo<>StartItem) and (GetItemStyle(MarkerItemNo)=rvsListMarker) then begin
  149.             Layout.FirstMarkerListNo := TRVMarkerItemInfo(GetItem(MarkerItemNo)).ListNo;
  150.             Layout.FirstMarkerLevel := TRVMarkerItemInfo(GetItem(MarkerItemNo)).Level;
  151.           end;
  152.           {$ENDIF}
  153.         end;
  154.         if (EndOffs<GetOffsAfterItem(EndItem)) or
  155.            ((EndOffs>=GetOffsAfterItem(EndItem)) and not ((EndItem+1=ItemCount) or (IsParaStart(EndItem+1)))) then
  156.           Layout.LastParaAborted := 1;
  157.         {$IFNDEF RVDONOTUSELISTS}
  158.         RVFSavePrevMarkers(StartItem);
  159.         {$ENDIF}
  160.       end;
  161.     end;
  162.     if (rvfoSaveLayout in RVFOptions) and (Self=GetRootData) and (Layout<>nil) and
  163.        (SaveScope<>rvfss_Selection) then
  164.       RVFSaveLayout;
  165.     {$IFNDEF RVDONOTUSEINPLACE}
  166.     if (SaveScope=rvfss_Selection) and (GetChosenRVData<>nil) then begin
  167.       Result := GetChosenRVData.SaveRVFToStreamEx(Stream, SaveScope,
  168.         clNone, nil, nil);
  169.       Header.Item.Free;
  170.       exit;
  171.     end;
  172.     {$ENDIF}
  173.     RVFGetLimits(SaveScope,StartItem,EndItem,StartOffs,EndOffs,StartPart,EndPart);
  174.     if (StartItem=-1) or (StartItem>EndItem) then exit;
  175.     if (StartItem=EndItem) and
  176.        ((StartOffs>GetOffsBeforeItem(StartItem)) or
  177.         (EndOffs  <GetOffsAfterItem(EndItem))) then begin
  178.       // only part of text line is selected
  179.       WritePartialTextLine(StartItem, StartOffs, EndOffs, SaveScope=rvfss_Page);
  180.       exit;
  181.     end;
  182.     SectionBackOffs := 0;
  183.     if (StartPart<>nil) then begin
  184.       Header.ParaNo := GetItem(StartItem).ParaNo;
  185.       RVFWriteNonText(StartItem, StartPart);
  186.       inc(StartItem);
  187.     end;
  188.     MarkerItemNo := -1;
  189.     {$IFNDEF RVDONOTUSELISTS}
  190.     if (SaveScope=rvfss_Selection) and (StartPart=nil) then begin
  191.       MarkerItemNo := GetFirstParaItem(StartItem);
  192.       if (MarkerItemNo<>StartItem) and (GetItemStyle(MarkerItemNo)=rvsListMarker) then begin
  193.         RVFWriteNonText(MarkerItemNo, nil);
  194.         MarkerItemNo := GetFirstParaItem(StartItem);
  195.         end
  196.       else
  197.         MarkerItemNo := -1;
  198.     end;
  199.     {$ENDIF}
  200.     if (EndPart<>nil) then
  201.       dec(EndItem);
  202.     for i := StartItem to EndItem do begin
  203.       if (i=StartItem) then begin
  204.         if ((GetItemStyle(i)>=0) or ShouldSaveEndOfNonTextItemAsEmptyText()) and
  205.          ((StartOffs>GetOffsBeforeItem(i)) or (SaveScope=rvfss_Page)) then begin
  206.           WritePartialTextLine(StartItem, StartOffs, GetOffsAfterItem(StartItem), SaveScope=rvfss_Page);
  207.           continue;
  208.         end;
  209.         if (StartOffs>GetOffsBeforeItem(i)) then
  210.           continue;
  211.       end;
  212.       if (i>StartItem) and IsTheSameStyleText then
  213.         inc(SectionBackOffs)
  214.       else begin
  215.         if SectionBackOffs>0 then
  216.           RVFWritePrevStrings(i);
  217.         RVFSetHeaderHeader(i);
  218.         if Header.StyleNo<0 then begin
  219.           if (i<EndItem) or (EndOffs=1) then
  220.             RVFWriteNonText(i, nil)
  221.           end
  222.         else
  223.           SectionBackOffs := 1;
  224.       end;
  225.     end;
  226.     if (Header.StyleNo<0) and ShouldSaveBeginningOfNonTextItemAsEmptyText() then
  227.       WritePartialTextLine(EndItem, GetOffsBeforeItem(EndItem), EndOffs, False)
  228.     else if (Header.StyleNo>=0) and (EndOffs<GetOffsAfterItem(EndItem)) then begin
  229.       dec(SectionBackOffs);
  230.       if SectionBackOffs>0 then
  231.         RVFWritePrevStrings(EndItem);
  232.       WritePartialTextLine(EndItem, GetOffsBeforeItem(EndItem), EndOffs, False);
  233.       end
  234.     else begin
  235.       if SectionBackOffs<>0 then
  236.         RVFWritePrevStrings(EndItem+1);
  237.       if (EndItem=Items.Count-1) and (EndOffs=1) then
  238.         RVFWriteCheckpoint(Stream, rvoTagsArePChars in Options, NotAddedCP);
  239.     end;
  240.     if (EndPart<>nil) then begin
  241.       RVFSetHeaderHeader(EndItem+1);
  242.       RVFWriteNonText(EndItem+1, EndPart);
  243.     end;
  244.   except;
  245.     Result := False;
  246.   end;
  247.   Header.Item.Free;
  248. end;
  249. {$ENDIF}{RVDONOTUSERVF}
  250. {------------------------------------------------------------------------------}
  251. function TCustomRVData.InsertFirstRVFItem(var Index: Integer;
  252.   var s: String; var item: TCustomRVItemInfo; EditFlag: Boolean;
  253.   var FullReformat: Boolean;
  254.   var NewListNo: Integer): Boolean;
  255. begin
  256.   FullReformat := False;
  257.   NewListNo := -1;
  258.   item.Inserting(Self, s, False);
  259.   Items.InsertObject(Index, s, item);
  260.   item.Inserted(Self, Index);
  261.   {$IFNDEF RVDONOTUSELISTS}
  262.   AddMarkerInList(Index);
  263.   {$ENDIF}
  264.   Result := True;
  265. end;
  266. {------------------------------------------------------------------------------}
  267. procedure TCustomRVData.UpdateItemsPaletteInfo;
  268. var i: Integer;
  269. begin
  270.   if not ShareItems then
  271.     for i := 0 to Items.Count-1 do
  272.       TCustomRVItemInfo(Items.Objects[i]).
  273.          UpdatePaletteInfo(GetDoInPaletteMode, False, GetRVPalette, GetRVLogPalette);
  274. end;
  275. {------------------------------------------------------------------------------}
  276. procedure TCustomRVData.InsertCheckpoint(ItemNo, Tag: Integer;
  277.                              const Name: String; RaiseEvent: Boolean);
  278. var
  279.   cp: TRVCPInfo;
  280. begin
  281.   if TCustomRVItemInfo(Items.Objects[ItemNo]).Checkpoint<>nil then
  282.     raise ERichViewError.Create(errRVCPExists);
  283.   cp            := TRVCPInfo.Create;
  284.   cp.Tag        := Tag;
  285.   cp.Name       := Name;
  286.   cp.RaiseEvent := RaiseEvent;
  287.   cp.ItemInfo   := TCustomRVItemInfo(Items.Objects[ItemNo]);
  288.   cp.Next := nil;
  289.   cp.Prev := nil;
  290.   TCustomRVItemInfo(Items.Objects[ItemNo]).Checkpoint := cp;
  291.   inc(CPCount);
  292.   UpdateCPPos(cp, ItemNo);
  293. end;
  294. {------------------------------------------------------------------------------}
  295. procedure TCustomRVData.UpdateCPPos(cp: TRVCPInfo; ItemNo: Integer);
  296. var cpi: TRVCPInfo;
  297. begin
  298.   if ItemNo=-1 then exit;
  299.   UpdateCPItemNo;
  300.   cp.Prev := nil;
  301.   cp.Next := nil;
  302.   if FirstCP = nil then begin
  303.     FirstCP := cp;
  304.     LastCP  := cp;
  305.     end
  306.   else if FirstCP.ItemNo>cp.ItemNo then begin
  307.     cp.Next := FirstCP;
  308.     FirstCP.Prev := cp;
  309.     FirstCP      := cp;
  310.     end
  311.   else if LastCP.ItemNo<=cp.ItemNo then begin
  312.     LastCP.Next := cp;
  313.     cp.Prev := LastCP;
  314.     LastCP := cp
  315.     end
  316.   else begin
  317.     cpi := FirstCP;
  318.     while cpi.Next<>nil do begin
  319.       if cpi.Next.ItemNo>cp.ItemNo then break;
  320.       cpi := cpi.Next;
  321.     end;
  322.     if cpi.Next<>nil then cpi.Next.Prev := cp;
  323.     cp.Next := cpi.Next;
  324.     cpi.Next := cp;
  325.     cp.Prev := cpi;
  326.   end;
  327. end;
  328. {------------------------------------------------------------------------------}
  329. procedure TCustomRVData.ShareItemsFrom(Source: TCustomRVData);
  330. begin
  331.   if ShareItems then begin
  332.     Clear;
  333.     FItems := Source.Items;
  334.   end;
  335. end;
  336. {------------------------------------------------------------------------------}
  337. procedure TCustomRVData.AssignItemsFrom(Source: TCustomRVData);
  338. begin
  339.   FItems := Source.Items;
  340. end;
  341. {------------------------------------------------------------------------------}
  342. procedure TCustomRVData.AppendFrom(Source: TCustomRVData);
  343. var i: Integer;
  344.     item,itemcopy: TCustomRVItemInfo;
  345. begin
  346.   if (rvoTagsArePChars in Options) <> (rvoTagsArePChars in Source.Options) then
  347.     raise ERichViewError.Create(errRVTagsTypesMismatch);
  348.   for i:=0 to Source.Items.Count-1 do begin
  349.     item := Source.GetItem(i);
  350.     itemcopy := RV_DuplicateItem(item, Self, True);
  351.     if itemcopy.GetBoolValue(rvbpValid) then begin
  352.       if itemcopy.SameAsPrev then
  353.         itemcopy.ParaNo := -1;
  354.       AddItem(Source.Items[i],itemcopy);
  355.       {$IFNDEF RVDONOTUSELISTS}
  356.       AddMarkerInList(ItemCount-1);
  357.       {$ENDIF}
  358.       end
  359.     else
  360.       InternalFreeItem(itemcopy,False);
  361.   end;
  362. end;
  363. {------------------------------------------------------------------------------}
  364. procedure TCustomRVData.UpdateCPItemNo;
  365. var i,cnt: Integer;
  366. begin
  367.   cnt := 0;
  368.   if cnt=CPCount then exit;
  369.   for i := 0 to Items.Count-1 do
  370.     if TCustomRVItemInfo(Items.Objects[i]).Checkpoint<>nil then begin
  371.       TCustomRVItemInfo(Items.Objects[i]).Checkpoint.ItemNo := i;
  372.       inc(cnt);
  373.       if cnt=CPCount then
  374.         exit;
  375.     end;
  376. end;
  377. {------------------------------------------------------------------------------}
  378. function TCustomRVData.IsDelimiterA(ch: Char): Boolean;
  379. var Del: String;
  380. begin
  381.   Del := GetDelimiters;
  382.   Result := RV_CharPos(PChar(Del), ch, Length(Del))<>0;
  383. end;
  384. {------------------------------------------------------------------------------}
  385. function TCustomRVData.IsDelimiterW(ch: Word): Boolean;
  386. begin
  387.   Result := (ch<256) and (Pos(Char(ch), GetDelimiters)<>0);
  388. end;
  389. {------------------------------------------------------------------------------}
  390. function TCustomRVData.IsDelimiter(const s: String; Index: Integer;
  391.                                    ItemOptions: TRVItemOptions): Boolean;
  392. begin
  393.   {$IFNDEF RVDONOTUSEUNICODE}
  394.   if rvioUnicode in ItemOptions then
  395.     Result := IsDelimiterW(PWord(PChar(s)+(Index-1)*2)^)
  396.   else
  397.   {$ENDIF}
  398.     Result := IsDelimiterA(s[Index]);
  399. end;
  400. {------------------------------------------------------------------------------}
  401. function TCustomRVData.GetItemOptions(ItemNo: Integer): TRVItemOptions;
  402. begin
  403.   Result := TCustomRVItemInfo(Items.Objects[ItemNo]).ItemOptions;
  404. end;
  405. {------------------------------------------------------------------------------}
  406. function TCustomRVData.GetStyleCodePage(StyleNo: Integer): TRVCodePage;
  407. begin
  408.   {$IFDEF RICHVIEWCBDEF3}
  409.   if (GetRVStyle<>nil) then
  410.     if (StyleNo>=0) and (GetRVStyle.TextStyles[StyleNo].Charset<>DEFAULT_CHARSET) then
  411.       Result := RVU_Charset2CodePage(GetRVStyle.TextStyles[StyleNo].Charset)
  412.     else
  413.       Result := GetRVStyle.DefCodePage
  414.   else
  415.   {$ENDIF}
  416.     Result := CP_ACP;
  417. end;
  418. {------------------------------------------------------------------------------}
  419. function TCustomRVData.GetStyleLocale(StyleNo: Integer): Cardinal;
  420. begin
  421.   {$IFDEF RICHVIEWCBDEF3}
  422.   if (GetRVStyle<>nil) and (StyleNo>=0) then
  423.     Result := RVMAKELCID(RVU_Charset2Language(GetRVStyle.TextStyles[StyleNo].Charset))
  424.   else
  425.   {$ENDIF}
  426.     Result := RVMAKELCID(LANG_NEUTRAL);
  427. end;
  428. {------------------------------------------------------------------------------}
  429. function TCustomRVData.GetDefaultCodePage: TRVCodePage;
  430. begin
  431.   {$IFNDEF RVDONOTUSEUNICODE}
  432.   if (GetRVStyle<>nil) then
  433.     Result := GetRVStyle.DefCodePage
  434.   else
  435.   {$ENDIF}
  436.     Result := CP_ACP;
  437. end;
  438. {------------------------------------------------------------------------------}
  439. function TCustomRVData.GetDoInPaletteMode: TRVPaletteAction;
  440. begin
  441.   Result := GetRootData.GetDoInPaletteMode;
  442. end;
  443. {------------------------------------------------------------------------------}
  444. function TCustomRVData.GetOptions: TRVOptions;
  445. begin
  446.   Result := GetRootData.GetOptions;
  447. end;
  448. {------------------------------------------------------------------------------}
  449. procedure TCustomRVData.SetOptions(const Value: TRVOptions);
  450. begin
  451.   GetRootData.SetOptions(Value);
  452. end;
  453. {------------------------------------------------------------------------------}
  454. function TCustomRVData.GetDocProperties: TStringList;
  455. begin
  456.   Result := nil;
  457. end;
  458. {------------------------------------------------------------------------------}
  459. function TCustomRVData.GetRVLogPalette: PLogPalette;
  460. begin
  461.   Result := GetRootData.GetRVLogPalette;
  462. end;
  463. {------------------------------------------------------------------------------}
  464. function TCustomRVData.GetRVPalette: HPALETTE;
  465. begin
  466.   Result := GetRootData.GetRVPalette;
  467. end;
  468. {------------------------------------------------------------------------------}
  469. function TCustomRVData.GetDelimiters: String;
  470. begin
  471.   Result := GetRootData.GetDelimiters;
  472. end;
  473. {------------------------------------------------------------------------------}
  474. function TCustomRVData.GetRVFParaStylesReadMode: TRVFReaderStyleMode;
  475. begin
  476.   Result := GetRootData.GetRVFParaStylesReadMode;
  477. end;
  478. {------------------------------------------------------------------------------}
  479. function TCustomRVData.GetRVFTextStylesReadMode: TRVFReaderStyleMode;
  480. begin
  481.   Result := GetRootData.GetRVFTextStylesReadMode;
  482. end;
  483. {------------------------------------------------------------------------------}
  484. function TCustomRVData.RVFPictureNeeded(const ItemName: String; ItemTag: Integer): TGraphic;
  485. begin
  486.   Result := GetRootData.RVFPictureNeeded(ItemName, ItemTag);
  487. end;
  488. {------------------------------------------------------------------------------}
  489. function TCustomRVData.SaveComponentToFile(const Path: String;
  490.   SaveMe: TComponent; SaveFormat: TRVSaveFormat): String;
  491. begin
  492.   Result := GetAbsoluteRootData.SaveComponentToFile(Path, SaveMe, SaveFormat);
  493. end;
  494. {------------------------------------------------------------------------------}
  495. function TCustomRVData.SaveItemToFile(const Path: String;
  496.   RVData: TCustomRVData; ItemNo: Integer; SaveFormat: TRVSaveFormat;
  497.   Unicode: Boolean; var Text: String): Boolean;
  498. begin
  499.   Result := GetAbsoluteRootData.SaveItemToFile(Path, RVData, ItemNo, SaveFormat,
  500.     Unicode, Text);
  501. end;
  502. {------------------------------------------------------------------------------}
  503. function TCustomRVData.ImportPicture(const Location: String; Width,
  504.   Height: Integer; var Invalid: Boolean): TGraphic;
  505. begin
  506.   Result := GetAbsoluteRootData.ImportPicture(Location, Width, Height, Invalid);
  507. end;
  508. {------------------------------------------------------------------------------}
  509. function TCustomRVData.GetItemHint(RVData: TCustomRVData; ItemNo: Integer;
  510.   const UpperRVDataHint: String): String;
  511. begin
  512.   Result := GetAbsoluteParentData.GetItemHint(RVData, ItemNo, UpperRVDataHint);
  513. end;
  514. {------------------------------------------------------------------------------}
  515. function TCustomRVData.RVFControlNeeded(const ItemName: String; ItemTag: Integer): TControl;
  516. begin
  517.   Result := GetRootData.RVFControlNeeded(ItemName, ItemTag);
  518. end;
  519. {------------------------------------------------------------------------------}
  520. function TCustomRVData.RVFImageListNeeded(ImageListTag: Integer): TCustomImageList;
  521. begin
  522.   Result := GetRootData.RVFImageListNeeded(ImageListTag);
  523. end;
  524. {------------------------------------------------------------------------------}
  525. procedure TCustomRVData.HTMLSaveImage(RVData: TCustomRVData;
  526.   ItemNo: Integer; const Path: String; BackgroundColor: TColor;
  527.   var Location: String; var DoDefault: Boolean);
  528. begin
  529.   GetAbsoluteRootData.HTMLSaveImage(RVData, ItemNo, Path, BackgroundColor,
  530.     Location, DoDefault);
  531. end;
  532. {------------------------------------------------------------------------------}
  533. procedure TCustomRVData.SaveImage2(Graphic: TGraphic;
  534.   SaveFormat: TRVSaveFormat; const Path, ImagePrefix: String;
  535.   var ImageSaveNo: Integer; var Location: String; var DoDefault: Boolean);
  536. begin
  537.   GetAbsoluteRootData.SaveImage2(Graphic, SaveFormat, Path, ImagePrefix,
  538.     ImageSaveNo, Location, DoDefault);
  539. end;
  540. {------------------------------------------------------------------------------}
  541. function TCustomRVData.GetRVStyle: TRVStyle;
  542. begin
  543.   Result := GetParentData.GetRVStyle;
  544. end;
  545. {------------------------------------------------------------------------------}
  546. function TCustomRVData.GetParentControl: TWinControl;
  547. begin
  548.   Result := GetRootData.GetParentControl;
  549. end;
  550. {------------------------------------------------------------------------------}
  551. procedure TCustomRVData.ReadHyperlink(const Target, Extras: String;
  552.   DocFormat: TRVLoadFormat; var StyleNo, ItemTag: Integer;
  553.   var ItemName: String);
  554. begin
  555.   GetRootData.ReadHyperlink(Target, Extras, DocFormat, StyleNo, ItemTag, ItemName);
  556. end;
  557. {------------------------------------------------------------------------------}
  558. procedure TCustomRVData.WriteHyperlink(id: Integer; RVData: TCustomRVData;
  559.   ItemNo: Integer; SaveFormat: TRVSaveFormat; var Target, Extras: String);
  560. begin
  561.   GetAbsoluteRootData.WriteHyperlink(id, RVData, ItemNo, SaveFormat,
  562.     Target, Extras);
  563. end;
  564. {------------------------------------------------------------------------------}
  565. procedure TCustomRVData.ControlAction(ControlAction: TRVControlAction; ItemNo: Integer;
  566.                             Item: TCustomRVItemInfo);
  567. begin
  568.   if (item is TRVControlItemInfo) then
  569.      ControlAction2(ControlAction, ItemNo, TRVControlItemInfo(item).Control);
  570. end;
  571. {------------------------------------------------------------------------------}
  572. procedure TCustomRVData.ItemAction(ItemAction: TRVItemAction;
  573.   Item: TCustomRVItemInfo; var Text: String; RVData: TCustomRVData);
  574. begin
  575. end;
  576. {------------------------------------------------------------------------------}
  577. procedure TCustomRVData.Replace0(var s: String);
  578. var p: Integer;
  579. begin
  580.   while True do begin
  581.     p := Pos(#0,s);
  582.     if p=0 then break;
  583.     s[p] := RVDEFAULTCHARACTER;
  584.   end;
  585. end;
  586. {------------------------------- RTF ------------------------------------------}
  587. procedure TCustomRVData.SetRTFOptions(const Value: TRVRTFOptions);
  588. begin
  589.   GetRootData.SetRTFOptions(Value);
  590. end;
  591. {------------------------------------------------------------------------------}
  592. function TCustomRVData.GetRTFOptions: TRVRTFOptions;
  593. begin
  594.   Result := GetRootData.GetRTFOptions;
  595. end;
  596. {------------------------------------------------------------------------------}
  597. procedure TCustomRVData.MakeRTFTables(ColorList: TRVColorList;
  598.   ListOverrideCountList: TRVIntegerList; TopLevel: Boolean);
  599.    const ArrDefColorTable: array [0..16] of TColor =
  600.          (
  601.          clWindowText, clBlack, clBlue, clAqua,
  602.          clLime, clFuchsia, clRed, clYellow,
  603.          clWhite, clNavy, clTeal, clGreen,
  604.          clPurple, clMaroon, clOlive,
  605.          clGray, clSilver
  606.          );
  607.    var i{$IFNDEF RVDONOTUSELISTS},j{$ENDIF}: Integer;
  608.        RVStyle: TRVStyle;
  609. begin
  610.    RVStyle := GetRVStyle;
  611.    if TopLevel then begin
  612.      ColorList.Clear;
  613.      ListOverrideCountList.Clear;
  614.      for i := Low(ArrDefColorTable) to High(ArrDefColorTable) do
  615.        ColorList.Add(ArrDefColorTable[i]);
  616.      for i := 0 to RVStyle.TextStyles.Count-1 do
  617.        with RVStyle.TextStyles[i] do begin
  618.          ColorList.AddUnique(Color);
  619.          ColorList.AddUnique(BackColor);
  620.          ColorList.AddUnique(HoverColor);
  621.          ColorList.AddUnique(HoverBackColor);
  622.        end;
  623.      for i := 0 to RVStyle.ParaStyles.Count-1 do
  624.        with RVStyle.ParaStyles[i] do begin
  625.          if (Border.Style<>rvbNone) then
  626.            ColorList.AddUnique(Border.Color);
  627.          ColorList.AddUnique(Background.Color);
  628.        end;
  629.      {$IFNDEF RVDONOTUSELISTS}
  630.      for i := 0 to RVStyle.ListStyles.Count-1 do begin
  631.        ListOverrideCountList.Add(1);
  632.        for j := 0 to RVStyle.ListStyles[i].Levels.Count-1 do
  633.          with RVStyle.ListStyles[i].Levels[j] do
  634.            if UsesFont then
  635.              ColorList.AddUnique(Font.Color);
  636.      end;
  637.      {$ENDIF}
  638.    end;
  639.    for i := 0 to Items.Count-1 do
  640.      with GetItem(i) do
  641.        if StyleNo<0 then
  642.          FillRTFTables(ColorList, ListOverrideCountList, Self);
  643. end;
  644. {------------------------------------------------------------------------------}
  645. {$IFNDEF RVDONOTUSERTF}
  646. function TCustomRVData.SaveRTF(const FileName: String; SelectionOnly: Boolean;
  647.                        Color: TColor;
  648.                        Background: TRVBackground):Boolean;
  649. var Stream: TFileStream;
  650. begin
  651.   try
  652.     Stream := TFileStream.Create(FileName,fmCreate);
  653.     try
  654.       Result := SaveRTFToStream(Stream, ExtractFilePath(FileName), SelectionOnly,
  655.         0, Color, Background, nil, nil, nil, nil, nil, 0.0);
  656.     finally
  657.       Stream.Free;
  658.     end;
  659.   except
  660.     Result := False;
  661.   end;
  662. end;
  663. {------------------------------------------------------------------------------}
  664. procedure RVSaveFontToRTF(Stream: TStream; Font: TFont;
  665.                           ColorList: TRVColorList; FontTable: TRVRTFFontTable;
  666.                           RVStyle: TRVStyle);
  667. var idx: Integer;
  668.     {$IFDEF RICHVIEWCBDEF3}
  669.     Language: Cardinal;
  670.     {$ENDIF}
  671. begin
  672.   idx := FontTable.Find(Font.Name {$IFDEF RICHVIEWCBDEF3}, Font.Charset{$ENDIF});
  673.   if idx>=0 then
  674.     RVFWrite(Stream, Format('f%d', [idx]));
  675.   if fsBold in Font.Style then
  676.     RVFWrite(Stream, 'b');
  677.   if fsItalic in Font.Style then
  678.     RVFWrite(Stream, 'i');
  679.   if fsUnderline in Font.Style then
  680.     RVFWrite(Stream, 'ul');
  681.   if fsStrikeOut in Font.Style then
  682.     RVFWrite(Stream, 'strike');
  683.   RVFWrite(Stream, Format('fs%d', [Font.Size*2]));
  684.   {$IFDEF RICHVIEWCBDEF3}
  685.   if (Font.Charset<>DEFAULT_CHARSET) and (Font.Charset<>RVStyle.TextStyles[0].Charset) then begin
  686.     Language := RVU_Charset2Language(Font.Charset);
  687.     RVFWrite(Stream, Format('lang%d', [Language]));
  688.   end;
  689.   {$ENDIF}
  690.   if Font.Color<>clWindowText then
  691.     RVFWrite(Stream, Format('cf%d', [ColorList.IndexOf(Pointer(Font.Color))]));
  692. end;
  693. {------------------------------------------------------------------------------}
  694. {$IFNDEF RVDONOTUSELISTS}
  695. procedure TCustomRVData.SaveRTFListTable97(Stream: TStream; ColorList: TRVColorList;
  696.   ListOverrideOffsetsList: TRVIntegerList;
  697.   FontTable: TRVRTFFontTable; tpp: Double);
  698. var IDList, TemplateIDList: TRVIntegerList;
  699.     i,j, id, levelcount, idx: Integer;
  700.     s1,s2: String;
  701.     RVStyle: TRVStyle;
  702.     LevelInfo: TRVListLevel;
  703.     {...................................................}
  704.     function Getlevelnfc(LevelInfo: TRVListLevel): Integer;
  705.     begin
  706.       case LevelInfo.ListType of
  707.         rvlstBullet,
  708.         {$IFNDEF RVDONOTUSEUNICODE}
  709.         rvlstUnicodeBullet,
  710.         {$ENDIF}
  711.         rvlstPicture, rvlstImageList:
  712.           Result := 23;
  713.         rvlstDecimal,rvlstImageListCounter:
  714.           Result := 0;
  715.         rvlstLowerAlpha:
  716.           Result := 4;
  717.         rvlstUpperAlpha:
  718.           Result := 3;
  719.         rvlstLowerRoman:
  720.           Result := 2;
  721.         rvlstUpperRoman:
  722.           Result := 1;
  723.         else
  724.           Result := 255;
  725.       end;
  726.     end;
  727.     {...................................................}
  728.     function Getleveljc(LevelInfo: TRVListLevel): Integer;
  729.     begin
  730.       case LevelInfo.MarkerAlignment of
  731.         rvmaLeft:
  732.           Result := 0;
  733.         rvmaCenter:
  734.           Result := 1;
  735.         rvmaRight:
  736.           Result := 2;
  737.         else
  738.           Result := -1;
  739.       end;
  740.     end;
  741.     {...................................................}
  742.     procedure Getlevetext(LevelInfo: TRVListLevel; var LevelText, LevelNumbers: String);
  743.     var
  744.         {$IFNDEF RVDONOTUSEUNICODE}
  745.         {$IFDEF RICHVIEWCBDEF3}
  746.         Stream: TMemoryStream;
  747.         {$ENDIF}
  748.         {$ENDIF}
  749.         s: String;
  750.         i: Integer;
  751.     begin
  752.       case LevelInfo.ListType of
  753.         rvlstBullet:
  754.           begin
  755.             LevelText := RVMakeRTFStr(LevelInfo.FormatString, False, False);
  756.             LevelText := Format('''%.2x%s',[Length(LevelInfo.FormatString),LevelText]);
  757.             LevelNumbers := '';
  758.           end;
  759.         {$IFNDEF RVDONOTUSEUNICODE}
  760.         {$IFDEF RICHVIEWCBDEF3}        
  761.         rvlstUnicodeBullet:
  762.           begin
  763.             SetLength(s, Length(LevelInfo.FormatStringW)*2);
  764.             if Length(s)>0 then
  765.               Move(Pointer(LevelInfo.FormatStringW)^, Pointer(s)^, Length(s));
  766.             Stream := TMemoryStream.Create;
  767.             RVWriteUnicodeRTFStr(Stream, s, RVStyle.DefCodePage, rvrtfDuplicateUnicode in RTFOptions, False);
  768.             SetLength(LevelText, Stream.Size);
  769.             Stream.Position := 0;
  770.             Stream.ReadBuffer(Pointer(LevelText)^, Stream.Size);
  771.             Stream.Free;
  772.             LevelText := Format('''%.2x%s',[Length(LevelInfo.FormatStringW),LevelText]);
  773.             LevelNumbers := '';
  774.           end;
  775.         {$ENDIF}
  776.         {$ENDIF}
  777.         rvlstDecimal,rvlstImageListCounter,
  778.         rvlstLowerAlpha,rvlstUpperAlpha,
  779.         rvlstLowerRoman,rvlstUpperRoman:
  780.           begin
  781.             LevelText := Format(LevelInfo.FormatString, ['''00','''01','''02','''03','''04','''05','''06','''07','''08']);
  782.             s := Format(LevelInfo.FormatString, [#0, #1, #2, #3, #4, #5, #6, #7, #8]);
  783.             LevelNumbers := '';
  784.             for i := 1 to Length(s) do
  785.               if s[i]<#9 then
  786.                 LevelNumbers := Format('%s''%.2x',[LevelNumbers,i]);
  787.             LevelText := Format('''%.2x%s',[Length(s),LevelText]);
  788.           end;
  789.         else
  790.           begin
  791.             LevelText := '''00';
  792.             LevelNumbers := '';
  793.           end;
  794.       end;
  795.     end;
  796.     {...................................................}
  797.     procedure SaveListOverrideTable;
  798.     var i,j,k,prevcount,curcount,index: Integer;
  799.         Markers: TRVMarkerList;
  800.         Marker: TRVMarkerItemInfo;
  801.     begin
  802.       Markers := GetMarkers(False);
  803.       //if Markers=nil then
  804.       //  exit;
  805.       RVFWriteLine(Stream, '{*listoverridetable');
  806.       index := 1;
  807.       for i := 0 to IDList.Count-1 do begin
  808.         RVFWriteLine(Stream,
  809.           Format('{listoverridelistid%dlistoverridecount0ls%d}', [IDList[i],index]));
  810.         inc(index);
  811.         if (Markers<>nil) and (ListOverrideOffsetsList[i]>1) then begin
  812.           for j := 0 to Markers.Count-1 do begin
  813.             Marker := Markers[j];
  814.             if (Marker.ListNo=i) and (Marker.Level>=0) and Marker.Reset then begin
  815.               RVFWrite(Stream,
  816.                 Format('{listoverridelistid%dlistoverridecount%d',
  817.                   [IDList[i],Marker.Level+1]));
  818.               for k := 0 to Marker.Level-1 do
  819.                 RVFWrite(Stream, '{lfolevel}');
  820.               RVFWrite(Stream,
  821.                 Format('{lfolevellistoverridestartatlevelstartat%d}', [Marker.StartFrom]));
  822.               RVFWriteLine(Stream, Format('ls%d}', [index]));
  823.               inc(index);
  824.             end;
  825.           end;
  826.         end;
  827.       end;
  828.       RVFWriteLine(Stream, '}');
  829.       // transforming a list of counts to a list of offsets
  830.       if RVStyle.ListStyles.Count>0 then begin
  831.         prevcount := ListOverrideOffsetsList[0];
  832.         ListOverrideOffsetsList[0] := 1; // starting from 1
  833.         for i := 1 to RVStyle.ListStyles.Count-1 do begin
  834.           curcount := ListOverrideOffsetsList[i];
  835.           ListOverrideOffsetsList[i] := ListOverrideOffsetsList[i-1]+prevcount;
  836.           prevcount := curcount;
  837.         end;
  838.       end;
  839.     end;
  840.     {...................................................}
  841. //var listsarenotused: Boolean;
  842. begin
  843.   RVStyle := GetRVStyle;
  844.   {
  845.   listsarenotused := True;
  846.   for i := 0 to ListOverrideOffsetsList.Count-1 do
  847.     if ListOverrideOffsetsList[i]>0 then begin
  848.       listsarenotused := False;
  849.       break;
  850.     end;
  851.   }
  852.   if (RVStyle.ListStyles.Count=0) {or listsarenotused} then begin
  853.     RVFWriteLine(Stream, '');
  854.     exit;
  855.   end;
  856.   IDList := TRVIntegerList.Create;
  857.   TemplateIDList := TRVIntegerList.Create;
  858.   try
  859.     // writing list table
  860.     RVFWrite(Stream, '{*listtable');
  861.     for i := 0 to RVStyle.ListStyles.Count-1 do begin
  862.       // if ListOverrideOffsetsList[i]>1 then begin
  863.         // writing list
  864.         repeat
  865.           id := Random(MaxInt);
  866.         until IDList.IndexOf(Pointer(id))<0;
  867.         TemplateIDList.Add(id);
  868.         RVFWrite(Stream, Format('{listlisttemplateid%d',[id]));
  869.         if RVStyle.ListStyles[i].Levels.Count=1 then
  870.           RVFWrite(Stream, 'listsimple1');
  871.         RVFWriteLine(Stream, '');
  872.         levelcount := RVStyle.ListStyles[i].Levels.Count;
  873.         if levelcount>1 then
  874.           levelcount := 9;
  875.         for j := 0 to levelcount-1 do begin
  876.           // writing list level
  877.           if j<RVStyle.ListStyles[i].Levels.Count then
  878.             idx := j
  879.           else
  880.             idx := RVStyle.ListStyles[i].Levels.Count-1;
  881.           LevelInfo := RVStyle.ListStyles[i].Levels[idx];
  882.           RVFWrite(Stream, Format('{listlevellevelnfc%dleveljc%dli%dfi%djclisttabtx%d',
  883.             [Getlevelnfc(LevelInfo), Getleveljc(LevelInfo),
  884.              Round(LevelInfo.LeftIndent*tpp),
  885.              Round((LevelInfo.MarkerIndent-LevelInfo.LeftIndent)*tpp),
  886.              Round((LevelInfo.FirstIndent+LevelInfo.LeftIndent)*tpp)]));
  887.           if Getlevelnfc(LevelInfo)<>23 then
  888.             RVFWrite(Stream, Format('levelstartat%d', [LevelInfo.StartFrom]));
  889.           if rvloLegalStyleNumbering in LevelInfo.Options then
  890.             RVFWrite(Stream, 'levellegal1');
  891.           if not (rvloLevelReset in LevelInfo.Options) then
  892.             RVFWrite(Stream, 'levelnorestart1');
  893.           Getlevetext(LevelInfo, s1, s2);
  894.           RVFWrite(Stream, Format('{leveltext%s;}{levelnumbers%s;}', [s1,s2]));
  895.           if LevelInfo.UsesFont then
  896.             RVSaveFontToRTF(Stream, LevelInfo.Font, ColorList, FontTable, RVStyle);
  897.           RVFWriteLine(Stream, '}');
  898.         end;
  899.         // writing list table (continued)
  900.         repeat
  901.           id := Random(MaxInt);
  902.         until TemplateIDList.IndexOf(Pointer(id))<0;
  903.         IDList.Add(id);
  904.         RVFWriteLine(Stream, Format('listid%d}',[id]));
  905.       {
  906.         end
  907.       else begin
  908.         IDList.Add(-1);
  909.         TemplateIDList.Add(-1);
  910.       end;
  911.       }
  912.     end;
  913.     RVFWriteLine(Stream, '}');
  914.     SaveListOverrideTable;
  915.   finally
  916.     IDList.Free;
  917.     TemplateIDList.Free;
  918.   end;
  919. end;
  920. {$ENDIF}
  921. {------------------------------------------------------------------------------}
  922. function TCustomRVData.ShouldSaveTextToRTF(StyleNo: Integer): Boolean;
  923. begin
  924.   with GetRVStyle.TextStyles[StyleNo] do
  925.     Result := (rvteoRTFCode in Options) or not (rvteoHTMLCode in Options)
  926. end;
  927. {------------------------------------------------------------------------------}
  928. function TCustomRVData.SaveRTFToStream(Stream: TStream; const Path: String;
  929.   SelectionOnly: Boolean; Level: Integer; Color: TColor;
  930.   Background: TRVBackground; ColorList: TRVColorList;
  931.   StyleToFont, ListOverrideOffsetsList1, ListOverrideOffsetsList2: TRVIntegerList;
  932.   FontTable: TRVRTFFontTable; tpp: Double): Boolean;
  933. var RVStyle: TRVStyle;
  934.     {$IFNDEF RVDONOTUSELISTS}
  935.     LastListLevel: TRVListLevel;
  936.     {$ENDIF}
  937.     LastParaNo, LastTextStyleNo, CurTextStyleNo: Integer;
  938.     function GetTwipsPerPixel: Double;
  939.     var DC: HDC;
  940.     begin
  941.       DC := CreateCompatibleDC(0);
  942.       if RichViewPixelsPerInch>0 then
  943.         Result := (72*20) / RichViewPixelsPerInch
  944.       else
  945.         Result := (72*20) / GetDeviceCaps(DC, LOGPIXELSY);
  946.       DeleteDC(DC);
  947.     end;
  948.    {.................................................}
  949.    procedure MakeFontTable(FontTable: TRVRTFFontTable;StyleToFont: TRVIntegerList);
  950.    var i {$IFNDEF RVDONOTUSELISTS},j{$ENDIF}: Integer;
  951.        Index: Integer;
  952.    begin
  953.      FontTable.Clear;
  954.      StyleToFont.Clear;
  955.      for i := 0 to RVStyle.TextStyles.Count-1 do begin
  956.        Index := FontTable.AddUnique(RVStyle.TextStyles[i].FontName
  957.          {$IFDEF RICHVIEWCBDEF3}
  958.          , RVStyle.TextStyles[i].Charset
  959.          {$ENDIF});
  960.        StyleToFont.Add(Index);
  961.      end;
  962.      {$IFNDEF RVDONOTUSELISTS}
  963.      for i := 0 to RVStyle.ListStyles.Count-1 do
  964.        for j := 0 to RVStyle.ListStyles[i].Levels.Count-1 do
  965.          if RVStyle.ListStyles[i].Levels[j].UsesFont then
  966.            with RVStyle.ListStyles[i].Levels[j].Font do
  967.              FontTable.AddUnique(Name {$IFDEF RICHVIEWCBDEF3}, Charset{$ENDIF});
  968.      {$ENDIF}
  969.    end;
  970.    {.................................................}
  971.    procedure SaveFontTable(FontTable: TRVRTFFontTable);
  972.    var i: Integer;
  973.        Charset: Integer;
  974.    begin
  975.      RVFWrite(Stream, '{fonttbl');
  976.      for i := 0 to FontTable.Count-1 do begin
  977.        {$IFDEF RICHVIEWCBDEF3}
  978.        Charset := FontTable[i].Charset;
  979.        {$ELSE}
  980.        Charset := 1;
  981.        {$ENDIF}
  982.        RVFWrite(Stream, Format('{f%dfnilfcharset%d %s;}',[i, Charset, FontTable[i].FontName]));
  983.      end;
  984.      RVFWrite(Stream, '}');
  985.    end;
  986.    {.................................................}
  987.    procedure SaveColorTable(List: TList);
  988.    var i: Integer;
  989.        Color: Integer;
  990.    begin
  991.      RVFWrite(Stream, '{colortbl;');
  992.      for i := 1 to List.Count-1 do begin
  993.        Color := ColorToRGB(Integer(List.Items[i]));
  994.        RVFWrite(Stream, Format('red%dgreen%dblue%d;',
  995.                 [
  996.                   Color and $0000FF,
  997.                   (Color and $00FF00) shr 8,
  998.                   (Color and $FF0000) shr 16
  999.                 ]));
  1000.      end;
  1001.      RVFWrite(Stream, '}');
  1002.    end;
  1003.    {.................................................}
  1004.    procedure SaveTextStyle(StyleNo: Integer; StyleToFont, ColorTable: TList;
  1005.      ToStyleSheet: Boolean);
  1006.    var idx, fsscale: Integer;
  1007.        {$IFDEF RICHVIEWCBDEF3}
  1008.        ALanguage: Cardinal;
  1009.        {$ENDIF}
  1010.    begin
  1011.      if not ToStyleSheet then
  1012.        LastTextStyleNo := StyleNo;
  1013.      if StyleNo>=RVStyle.TextStyles.Count then
  1014.        StyleNo := 0;
  1015.      with RVStyle.TextStyles[StyleNo] do begin
  1016.        RVFWrite(Stream, Format('f%d', [Integer(StyleToFont.Items[StyleNo])]));
  1017.        if fsBold in Style then
  1018.          RVFWrite(Stream, 'b');
  1019.        if fsItalic in Style then
  1020.          RVFWrite(Stream, 'i');
  1021.        if fsUnderline in Style then
  1022.          RVFWrite(Stream, 'ul');
  1023.        if fsStrikeOut in Style then
  1024.          RVFWrite(Stream, 'strike');
  1025.        // RTF-viewer will also shrink font size for s/s scripts...
  1026.        fsscale := 1;
  1027.        if VShift<>0 then
  1028.          fsscale := 2;
  1029.        if VShift<0 then
  1030.          RVFWrite(Stream, 'sub');
  1031.        if VShift>0 then
  1032.          RVFWrite(Stream, 'super');
  1033.        if CharScale<>100 then
  1034.          RVFWrite(Stream, Format('charscalex%d',[CharScale]));
  1035.        if CharSpacing<>0 then
  1036.          RVFWrite(Stream, Format('expndtw%d',[Round(CharSpacing*tpp)]));
  1037.        if rvfsAllCaps in StyleEx then
  1038.          RVFWrite(Stream, 'caps');
  1039.        case BiDiMode of
  1040.          rvbdLeftToRight:
  1041.            RVFWrite(Stream, 'ltrch');
  1042.          rvbdRightToLeft:
  1043.            RVFWrite(Stream, 'rtlch');
  1044.        end;
  1045.        {$IFDEF RICHVIEWCBDEF3}
  1046.        if (Charset<>DEFAULT_CHARSET) and (Charset<>RVStyle.TextStyles[0].Charset) then begin
  1047.          {$IFDEF RVLANGUAGEPROPERTY}
  1048.          ALanguage := Language;
  1049.          {$ELSE}
  1050.          ALanguage := RVU_Charset2Language(Charset);
  1051.          {$ENDIF}
  1052.          if ALanguage<>0 then
  1053.            RVFWrite(Stream, Format('lang%d', [ALanguage]));
  1054.        end;
  1055.        {$ENDIF}
  1056.        RVFWrite(Stream, Format('fs%d', [Size*2*fsscale]));
  1057.        if BackColor<>clNone then begin
  1058.          idx := ColorTable.IndexOf(Pointer(BackColor));
  1059.          //RVFWrite(Stream, Format('chshdng0chcfpat0chcbpat%d', [idx]));
  1060.          RVFWrite(Stream, Format('chcbpat%d', [idx]));
  1061.        end;
  1062.        if Color<>clWindowText then begin
  1063.          idx := ColorTable.IndexOf(Pointer(Color));
  1064.          RVFWrite(Stream, Format('cf%d', [idx]));
  1065.        end;
  1066.        {$IFDEF RVTEXTFOOTNOTES}
  1067.        if (rvfsFootnotes in StyleEx) and not ToStyleSheet then
  1068.          RVFWrite(Stream, ' {chftn {footnote { chftn } { ' + FootNote + ' }}}');
  1069.        {$ENDIF}
  1070.        RVFWrite(Stream, GetExtraRTFCode(rv_rtfs_TextStyle, RVStyle.TextStyles[StyleNo], StyleNo, -1, ToStyleSheet));
  1071.        RVFWrite(Stream, ' ');
  1072.      end;
  1073.    end;
  1074.    {.................................................}
  1075.    {$IFNDEF RVDONOTUSELISTS}
  1076.    function IsListLevelNew(item: TCustomRVItemInfo): Boolean;
  1077.    begin
  1078.      if item.StyleNo<>rvsListMarker then begin
  1079.        Result := True;
  1080.        exit;
  1081.      end;
  1082.      Result := TRVMarkerItemInfo(item).GetLevelInfo(RVStyle)<>LastListLevel;
  1083.    end;
  1084.    {$ENDIF}
  1085.    {.................................................}
  1086.    {$IFNDEF RVDONOTUSETABS}
  1087.    function GetTabAlignStr(Align: TRVTabAlign): String;
  1088.    begin
  1089.      case Align of
  1090.        rvtaRight:  Result := 'tqr';
  1091.        rvtaCenter: Result := 'tqc';
  1092.        else        Result := '';
  1093.      end;
  1094.    end;
  1095.    {.................................................}
  1096.    function GetTabLeader(const LeaderStr: String): String;
  1097.    begin
  1098.      if LeaderStr='' then
  1099.        Result := ''
  1100.      else
  1101.        case LeaderStr[1] of
  1102.          '-':  Result := 'tlhyph';
  1103.          '_':  Result := 'tlul';
  1104.          #$B7: Result := 'tlmdot';
  1105.          '=': Result := 'tleq';         
  1106.          else  Result := 'tldot';
  1107.        end;
  1108.    end;
  1109.    {.................................................}
  1110.    procedure SaveTabs(ParaNo, MinAllowedPosition: Integer);
  1111.    var i: Integer;
  1112.    begin
  1113.      with RVStyle.ParaStyles[ParaNo] do
  1114.        for i := 0 to Tabs.Count-1 do
  1115.          if Tabs[i].Position>MinAllowedPosition then begin
  1116.            RVFWrite(Stream, GetTabAlignStr(Tabs[i].Align)+GetTabLeader(Tabs[i].Leader)+
  1117.              'tx'+IntToStr(Round(Tabs[i].Position*tpp)));
  1118.          end;
  1119.    end;
  1120.    {$ENDIF}   
  1121.    {.................................................}
  1122.    procedure SaveParaStyle(ParaNo: Integer; ColorTable: TList; ToStyleSheet: Boolean;
  1123.      item: TCustomRVItemInfo);
  1124.    var s,s2,s3,s4: String;
  1125.        bw: Integer;
  1126.        {$IFNDEF RVDONOTUSETABS}
  1127.        MinAllowedTabPos: Integer;
  1128.        {$ENDIF}
  1129.    begin
  1130.      if not ToStyleSheet then
  1131.        LastParaNo := ParaNo;
  1132.      {$IFNDEF RVDONOTUSETABS}
  1133.      MinAllowedTabPos := 0;
  1134.      {$ENDIF}
  1135.      with RVStyle.ParaStyles[ParaNo] do begin
  1136.        case Alignment of
  1137.          rvaLeft:
  1138.            s := 'l';
  1139.          rvaRight:
  1140.            s := 'r';
  1141.          rvaCenter:
  1142.            s := 'c';
  1143.          rvaJustify:
  1144.            s := 'j';
  1145.        end;
  1146.        if (LineSpacingType=rvlsPercent) and (LineSpacing>100) then
  1147.          RVFWrite(Stream, Format('sl%dslmult1', [LineSpacing*240 div 100]));
  1148.        if rvpaoKeepLinesTogether in Options then
  1149.          RVFWrite(Stream, 'keep');
  1150.        if rvpaoKeepWithNext in Options then
  1151.          RVFWrite(Stream, 'keepn');
  1152.        {$IFNDEF RVDONOTUSELISTS}
  1153.        LastListLevel := nil;
  1154.        if (item<>nil) and (item.StyleNo = rvsListMarker) and
  1155.           (TRVMarkerItemInfo(item).GetLevelInfo(RVStyle)<>nil) then begin
  1156.          LastListLevel := TRVMarkerItemInfo(item).GetLevelInfo(RVStyle);
  1157.          with LastListLevel do begin
  1158.            {$IFNDEF RVDONOTUSETABS}
  1159.            MinAllowedTabPos := FirstIndent+LeftIndent;
  1160.            {$ENDIF}
  1161.            RVFWrite(Stream, Format('li%dfi%djclisttabtx%d',
  1162.             [Round(LeftIndent*tpp),
  1163.              Round((MarkerIndent-LeftIndent)*tpp),
  1164.              Round((FirstIndent+LeftIndent)*tpp)]))
  1165.          end;
  1166.          end
  1167.        else
  1168.        {$ENDIF}
  1169.          RVFWrite(Stream, Format('fi%dli%d', [Round(FirstIndent*tpp), Round(LeftIndent*tpp)]));
  1170.        {$IFNDEF RVDONOTUSETABS}
  1171.        SaveTabs(ParaNo, MinAllowedTabPos);
  1172.        {$ENDIF}
  1173.        RVFWrite(Stream, Format('q%sri%dsb%dsa%d',
  1174.                         [s, Round(RightIndent*tpp),
  1175.                          Round(SpaceBefore*tpp), Round(SpaceAfter*tpp)]));
  1176.        case BiDiMode of
  1177.          rvbdLeftToRight:
  1178.            RVFWrite(Stream, 'ltrpar');
  1179.          rvbdRightToLeft:
  1180.            RVFWrite(Stream, 'rtlpar');
  1181.        end;
  1182.        if Background.Color<>clNone then
  1183.          RVFWrite(Stream, Format('cbpat%d', [ColorTable.IndexOf(Pointer(Background.Color))]));
  1184.        if (Border.Style<>rvbNone) and (Border.Color<>clNone) then begin
  1185.          RVFWrite(Stream, 'brdrbtw'); // <- does not work, unfortunately
  1186.          s2 := 'brdr';
  1187.          bw := Border.Width;
  1188.          case Border.Style of
  1189.            rvbSingle:
  1190.              s2 := s2+'s';
  1191.            rvbDouble:
  1192.              s2 := s2+'db';
  1193.            rvbTriple:
  1194.              s2 := s2+'triple';
  1195.            rvbThickInside:
  1196.              begin
  1197.                s2 := s2+'thtnmg';
  1198.                bw := bw*2;
  1199.              end;
  1200.            rvbThickOutside:
  1201.              begin
  1202.                s2 := s2+'tnthmg';
  1203.                bw := bw*2;
  1204.              end;
  1205.          end;
  1206.          case Border.Style of
  1207.            rvbThickInside:
  1208.              s3 := 'brdrtnthmg';
  1209.            rvbThickOutside:
  1210.              s3 := 'brdrthtnmg';
  1211.            else
  1212.              s3 := s2;
  1213.          end;
  1214.          s4 := Format('brdrcf%dbrdrw%d',
  1215.                [ColorTable.IndexOf(Pointer(Border.Color)),
  1216.                 Round(bw*tpp)
  1217.                ]);
  1218.          s2 := s2 + s4;
  1219.          s3 := s3 + s4;
  1220.          s := '';
  1221.          with Border.VisibleBorders do begin
  1222.            if Left   then s := s+Format('brdrlbrsp%d',[Round(Border.BorderOffsets.Left*tpp)])+s2;
  1223.            if Top    then s := s+Format('brdrtbrsp%d',[Round(Border.BorderOffsets.Top*tpp)])+s2;
  1224.            if Right  then s := s+Format('brdrrbrsp%d',[Round(Border.BorderOffsets.Right*tpp)])+s3;
  1225.            if Bottom then s := s+Format('brdrbbrsp%d',[Round(Border.BorderOffsets.Bottom*tpp)])+s3;
  1226.          end;
  1227.          RVFWrite(Stream, s);
  1228.        end;
  1229.        if not ToStyleSheet then
  1230.          RVFWrite(Stream, Format('itap%d',[Level]));
  1231.        if Level=1 then
  1232.          RVFWrite(Stream, 'intbl');
  1233.          RVFWrite(Stream, GetExtraRTFCode(rv_rtfs_ParaStyle, RVStyle.ParaStyles[ParaNo], ParaNo, -1, ToStyleSheet));
  1234.        RVFWrite(Stream, ' ');
  1235.      end;
  1236.    end;
  1237.    {.................................................}
  1238.    procedure SaveStyleSheet(StyleToFont, ColorTable: TList);
  1239.    var i: Integer;
  1240.    begin
  1241.      RVFWrite(Stream, '{stylesheet');
  1242.      for i := 0 to RVStyle.ParaStyles.Count-1 do begin
  1243.        if RVStyle.ParaStyles[i].Standard then begin
  1244.          RVFWrite(Stream, '{');
  1245.          RVFWrite(Stream, Format('s%d',[i]));
  1246.          SaveParaStyle(i, ColorTable,True,nil);
  1247.          RVFWrite(Stream, MakeRTFIdentifierStr(RVStyle.ParaStyles[i].StyleName));
  1248.          RVFWrite(Stream, ';}');
  1249.        end;
  1250.      end;
  1251.      for i := 0 to RVStyle.TextStyles.Count-1 do begin
  1252.        if RVStyle.TextStyles[i].Standard then begin
  1253.          RVFWrite(Stream, Format('{*cs%d',[i+RVStyle.ParaStyles.Count]));
  1254.          SaveTextStyle(i, StyleToFont, ColorTable,True);
  1255.          RVFWrite(Stream, MakeRTFIdentifierStr(RVStyle.TextStyles[i].StyleName)+';}');
  1256.        end;
  1257.      end;
  1258.      RVFWrite(Stream, '}');
  1259.    end;
  1260.    {.................................................}
  1261.    procedure SaveHeader(ColorList: TRVColorList; StyleToFont: TRVIntegerList;
  1262.                         FontTable: TRVRTFFontTable);
  1263.    var CodePage: TRVCodePage;
  1264.        Language: Cardinal;
  1265.    begin
  1266.      {$IFNDEF RVDONOTUSEUNICODE}
  1267.      {$IFDEF RICHVIEWCBDEF3}
  1268.      CodePage := GetRVStyle.DefCodePage;
  1269.      {$IFDEF RVLANGUAGEPROPERTY}
  1270.      Language := GetRVStyle.TextStyles[0].Language;
  1271.      if Language=0 then
  1272.        Language := $0400;
  1273.      {$ELSE}
  1274.      Language := RVU_Charset2Language(GetRVStyle.TextStyles[0].CharSet);
  1275.      {$ENDIF}
  1276.      {$ELSE}
  1277.      CodePage := 1252;
  1278.      Language := $0400;
  1279.      {$ENDIF}
  1280.      {$ELSE}
  1281.      CodePage := 1252;
  1282.      Language := $0400;
  1283.      {$ENDIF}
  1284.      RVFWrite(Stream, Format('{rtf1ansiansicpg%duc1deff0deflang%ddeflangfe%d',
  1285.        [CodePage, Language, Language]));
  1286.      case GetBiDiMode of
  1287.        rvbdLeftToRight:
  1288.          RVFWrite(Stream, 'ltrdoc');
  1289.        rvbdRightToLeft:
  1290.          RVFWrite(Stream, 'rtldoc');
  1291.      end;
  1292.      SaveFontTable(FontTable);
  1293.      SaveColorTable(ColorList);
  1294.      if rvrtfSaveStyleSheet in RTFOptions then
  1295.        SaveStyleSheet(StyleToFont, ColorList);
  1296.      {$IFNDEF RVDONOTUSELISTS}
  1297.      SaveRTFListTable97(Stream, ColorList, ListOverrideOffsetsList1, FontTable,tpp);
  1298.      ListOverrideOffsetsList2.Assign(ListOverrideOffsetsList1);
  1299.      {$ELSE}
  1300.      RVFWriteLine(Stream, '');
  1301.      {$ENDIF}
  1302.      RVFWriteLine(Stream, GetExtraRTFCode(rv_rtfs_Doc, nil, -1, -1, False));     
  1303.    end;
  1304.    {.................................................}
  1305. var i, CPIndex: Integer;
  1306.     item: TCustomRVItemInfo;
  1307.     s: String;
  1308.     StartItem,EndItem,StartOffs,EndOffs
  1309.     {$IFNDEF RVDONOTUSELISTS}
  1310.     ,MarkerItemNo
  1311.     {$ENDIF}
  1312.     : Integer;
  1313.     UrlTarget, UrlExtras: String;
  1314.     NotUsedPart: TRVMultiDrawItemPart;
  1315. begin
  1316.   {$IFNDEF RVDONOTUSEINPLACE}
  1317.   if SelectionOnly and (GetChosenRVData<>nil) then begin
  1318.     Result := GetChosenRVData.SaveRTFToStream(Stream, Path, SelectionOnly, Level,
  1319.       Color, Background, ColorList, StyleToFont,
  1320.       ListOverrideOffsetsList1, ListOverrideOffsetsList2,
  1321.       FontTable, tpp);
  1322.     exit;
  1323.   end;
  1324.   {$ENDIF}
  1325.   Result := True;
  1326.   RVFGetLimits(GetRVFSaveScope(SelectionOnly),StartItem,EndItem,StartOffs,EndOffs,NotUsedPart,NotUsedPart);
  1327.   if (StartItem=-1) or (StartItem>EndItem) then
  1328.     exit;
  1329.   LastParaNo := -1;
  1330.   LastTextStyleNo := -1;
  1331.   {$IFNDEF RVDONOTUSELISTS}
  1332.   LastListLevel := nil;
  1333.   {$ENDIF}
  1334.   if Level=0 then begin
  1335.     ColorList   := TRVColorList.Create;
  1336.     StyleToFont := TRVIntegerList.Create;
  1337.     FontTable := TRVRTFFontTable.Create;
  1338.     ListOverrideOffsetsList1 := TRVIntegerList.Create;
  1339.     ListOverrideOffsetsList2 := TRVIntegerList.Create;    
  1340.   end;
  1341.   RVStyle := GetRVStyle;
  1342.   CPIndex := 0;
  1343.   try
  1344.     Include(State, rvstRTFSkipPar);
  1345.     if Level=0 then begin
  1346.       tpp := GetTwipsPerPixel;
  1347.       MakeFontTable(FontTable, StyleToFont);
  1348.       MakeRTFTables(ColorList, ListOverrideOffsetsList1, True);
  1349.       if (Color<>clWindow) then
  1350.         ColorList.AddUnique(Color);
  1351.       SaveHeader(ColorList, StyleToFont, FontTable);
  1352.       if rvrtfDuplicateUnicode in RTFOptions then
  1353.         RVFWrite(Stream,'uc1')
  1354.       else
  1355.         RVFWrite(Stream,'uc0');
  1356.       {$IFNDEF RVDONOTUSELISTS}
  1357.       if SelectionOnly then begin
  1358.         MarkerItemNo := GetFirstParaItem(StartItem);
  1359.         if (MarkerItemNo<>StartItem) and (GetItemStyle(MarkerItemNo)=rvsListMarker) then begin
  1360.           GetItem(MarkerItemNo).SaveRTF(Stream, Path, Self, MarkerItemNo,
  1361.             Items[MarkerItemNo], tpp, Level, ColorList, StyleToFont,
  1362.             ListOverrideOffsetsList1, ListOverrideOffsetsList2, FontTable);
  1363.           Exclude(State, rvstRTFSkipPar);
  1364.         end;
  1365.       end;
  1366.       {$ENDIF}
  1367.     end;
  1368.     for i := StartItem to EndItem do begin
  1369.       if not ((StartItem=EndItem) and (GetItemStyle(StartItem)>=0)) then begin
  1370.         if (i=StartItem) and (StartOffs>=GetOffsAfterItem(i)) and (Items[i]<>'') then
  1371.           continue
  1372.         else if (i=EndItem) and (EndOffs<=GetOffsBeforeItem(i)) and (Items[i]<>'') then
  1373.           continue;
  1374.       end;
  1375.       item := GetItem(i);
  1376.       if not item.SameAsPrev then begin
  1377.         RVFWriteLine(Stream,'');
  1378.         if item.GetBoolValue(rvbpFullWidth) and PageBreaksBeforeItems[i]  then
  1379.           RVFWrite(Stream,'page ');
  1380.         if item.BR then
  1381.           RVFWrite(Stream,'line ')
  1382.         else begin
  1383.           if not (rvstRTFSkipPar in State) then begin
  1384.             {$IFNDEF RVDONOTUSELISTS}
  1385.             if (i>0) and (GetItemStyle(GetFirstParaItem(i-1))=rvsListMarker) then begin
  1386.               RVFWrite(Stream, 'plain');
  1387.               LastTextStyleNo := -1;
  1388.             end;
  1389.             {$ENDIF}
  1390.             RVFWrite(Stream, 'par ');
  1391.           end;
  1392.           if not item.GetBoolValue(rvbpFullWidth) and PageBreaksBeforeItems[i]  then
  1393.             RVFWrite(Stream,'page ');
  1394.           if (item.ParaNo<>LastParaNo)
  1395.              {$IFNDEF RVDONOTUSELISTS}or IsListLevelNew(item){$ENDIF} then begin
  1396.             RVFWrite(Stream, 'pard');
  1397.             if (rvrtfSaveStyleSheet in RTFOptions) and
  1398.               RVStyle.ParaStyles[item.ParaNo].Standard then
  1399.               RVFWrite(Stream, Format('s%d', [item.ParaNo]));
  1400.             SaveParaStyle(item.ParaNo, ColorList,False,item);
  1401.           end;
  1402.         end;
  1403.       end;
  1404.       Exclude(State, rvstRTFSkipPar);      
  1405.       if item.Checkpoint<>nil then begin
  1406.         // I decided to use names of checkpoints here (if assigned).
  1407.         // If several checkpoints have the same name, only one of them
  1408.         // will be used as a bookmark in MS Word.
  1409.         s := MakeRTFBookmarkNameStr(item.Checkpoint.Name);
  1410.         if s='' then
  1411.           s := 'RichViewCheckpoint'+IntToStr(CPIndex);
  1412.         RVFWrite(Stream, Format('{*bkmkstart %s}{*bkmkend %s}',[s,s]));
  1413.         inc(CPIndex);
  1414.       end;
  1415.       if item.GetBoolValueEx(rvbpJump,RVStyle) then begin
  1416.         WriteHyperlink(item.JumpID+FirstJumpNo, Self, i, rvsfRTF,
  1417.           UrlTarget, UrlExtras);
  1418.         UrlTarget := RVMakeRTFFileNameStr(UrlTarget);
  1419.         UrlExtras := RVMakeRTFStr(UrlExtras,False, False);
  1420.         if (UrlTarget<>'') or (UrlExtras<>'') then begin
  1421.           if UrlExtras<>'' then
  1422.             UrlExtras := ' '+UrlExtras;
  1423.           RVFWrite(Stream,
  1424.             Format('{field{*fldinst HYPERLINK "%s"%s}{fldrslt ',[UrlTarget, UrlExtras]));
  1425.           LastTextStyleNo := -1;
  1426.         end;
  1427.         end
  1428.       else begin
  1429.         UrlTarget := '';      
  1430.         UrlExtras := '';
  1431.       end;
  1432.       if ((item.StyleNo>=0) or (item.AssociatedTextStyleNo>=0)) and
  1433.          ShouldSaveTextToRTF(GetActualStyle(item)) then begin
  1434.         if item.StyleNo>=0 then begin
  1435.           if (i=StartItem) then
  1436.             if (i=EndItem) then
  1437.               s := RVU_Copy(Items[i], StartOffs, EndOffs-StartOffs, item.ItemOptions)
  1438.             else
  1439.               s := RVU_Copy(Items[i], StartOffs,
  1440.                 RVU_Length(Items[i],item.ItemOptions)-StartOffs+1, item.ItemOptions)
  1441.           else
  1442.             if i=EndItem then
  1443.               s := RVU_Copy(Items[i], 1, EndOffs-1, item.ItemOptions)
  1444.             else
  1445.               s := Items[i];
  1446.           CurTextStyleNo := GetActualStyle(item);
  1447.           end
  1448.         else begin
  1449.           s := '';
  1450.           CurTextStyleNo := item.AssociatedTextStyleNo;
  1451.         end;
  1452.         if LastTextStyleNo<>CurTextStyleNo then begin
  1453.           RVFWrite(Stream, 'plain ');
  1454.           if (rvrtfSaveStyleSheet in RTFOptions) and
  1455.             RVStyle.TextStyles[CurTextStyleNo].Standard then
  1456.             RVFWrite(Stream,Format('cs%d', [CurTextStyleNo+RVStyle.ParaStyles.Count]));
  1457.           SaveTextStyle(CurTextStyleNo, StyleToFont, ColorList, False);
  1458.         end;
  1459.         if SaveItemToFile(Path, Self, i, rvsfRTF, False, s) then
  1460.           RVFWrite(Stream, s)
  1461.         else begin
  1462.           if item.StyleNo>=0 then begin
  1463.             {$IFNDEF RVDONOTUSEUNICODE}
  1464.             if rvioUnicode in item.ItemOptions then
  1465.               RVWriteUnicodeRTFStr(Stream, s, GetStyleCodePage(GetActualStyle(item)),
  1466.                 rvrtfDuplicateUnicode in RTFOptions,
  1467.                 rvteoRTFCode in RVStyle.TextStyles[GetActualStyle(item)].Options)
  1468.             else
  1469.             {$ENDIF}
  1470.               RVFWrite(Stream, RVMakeRTFStr(s,rvteoRTFCode in
  1471.                 RVStyle.TextStyles[GetActualStyle(item)].Options, True));
  1472.             end
  1473.           else
  1474.             item.SaveRTF(Stream, Path, Self, i, Items[i], tpp, Level, ColorList,
  1475.               StyleToFont, ListOverrideOffsetsList1, ListOverrideOffsetsList2,
  1476.               FontTable);
  1477.         end;
  1478.         end
  1479.       else begin
  1480.         s := '';
  1481.         if SaveItemToFile(Path, Self, i, rvsfRTF, False, s) then
  1482.           RVFWrite(Stream, s)
  1483.         else
  1484.           item.SaveRTF(Stream, Path, Self, i, Items[i], tpp, Level, ColorList,
  1485.             StyleToFont, ListOverrideOffsetsList1, ListOverrideOffsetsList2,
  1486.             FontTable);
  1487.         LastTextStyleNo := -1;
  1488.       end;
  1489.       if (UrlTarget<>'') or (UrlExtras<>'') then begin
  1490.         RVFWrite(Stream, '}}');
  1491.         LastTextStyleNo := -1;
  1492.       end;
  1493.     end;
  1494.     if NotAddedCP<>nil then begin
  1495.       // I decided to use names of checkpoints here (if assigned).
  1496.       // If several checkpoints have the same name, only one of them
  1497.       // will be used as a bookmark in MS Word.
  1498.       s := MakeRTFBookmarkNameStr(NotAddedCP.Name);
  1499.       if s='' then
  1500.         s := 'RichViewCheckpoint'+IntToStr(CPIndex);
  1501.       RVFWrite(Stream, Format('{*bkmkstart %s}{*bkmkend %s}',[s,s]));
  1502.     end;
  1503.     if (Level=0) and (StartItem<>EndItem) and IsParaStart(EndItem) and (GetItemStyle(EndItem)>=0) and (Items[EndItem]='') then
  1504.       RVFWrite(Stream, 'par');
  1505.     if Level=0 then
  1506.       RVFWrite(Stream, '}');
  1507.   except
  1508.     Result := False;
  1509.   end;
  1510.   if Level=0 then begin
  1511.     ColorList.Free;
  1512.     StyleToFont.Free;
  1513.     FontTable.Free;
  1514.     ListOverrideOffsetsList1.Free;
  1515.     ListOverrideOffsetsList2.Free;    
  1516.   end;
  1517. end;
  1518. {$ENDIF}
  1519. {------------------------------------------------------------------------------}
  1520. function TCustomRVData.GetParentData: TCustomRVData;
  1521. begin
  1522.   Result := nil;
  1523. end;
  1524. {------------------------------------------------------------------------------}
  1525. function TCustomRVData.GetRootData: TCustomRVData;
  1526. begin
  1527.   Result := Self;
  1528. end;
  1529. {------------------------------------------------------------------------------}
  1530. function TCustomRVData.GetAbsoluteParentData: TCustomRVData;
  1531. begin
  1532.   Result := nil;
  1533. end;
  1534. {------------------------------------------------------------------------------}
  1535. function TCustomRVData.GetAbsoluteRootData: TCustomRVData;
  1536. begin
  1537.   Result := Self;
  1538. end;
  1539. {------------------------------------------------------------------------------}
  1540. procedure TCustomRVData.DrainFrom(Victim: TCustomRVData);
  1541. var i: Integer;
  1542.     item: TCustomRVItemInfo;
  1543. begin
  1544.   if Victim=nil then exit;
  1545.   if (rvoTagsArePChars in Options) <> (rvoTagsArePChars in Victim.Options) then
  1546.     raise ERichViewError.Create(errRVTagsTypesMismatch);
  1547.   for i := 0 to Victim.Items.Count-1 do begin
  1548.     item := Victim.GetItem(i);
  1549.     if item.SameAsPrev then
  1550.       item.ParaNo := -1;
  1551.     AddItem(Victim.Items[i], item);
  1552.   end;
  1553.   if NotAddedCP<>nil then
  1554.     NotAddedCP := Victim.NotAddedCP;
  1555.   Victim.Items.Clear;
  1556.   Victim.FirstCP := nil;
  1557.   Victim.LastCP := nil;
  1558.   Victim.NotAddedCP := nil;
  1559.   Victim.CPCount := 0;
  1560.   Victim.Clear;
  1561. end;
  1562. {------------------------------------------------------------------------------}
  1563. function TCustomRVData.GetItemNo(Item: TCustomRVItemInfo): Integer;
  1564. begin
  1565.   Result := Items.IndexOfObject(Item);
  1566. end;
  1567. {------------------------------------------------------------------------------}
  1568. procedure TCustomRVData.Inserting(RVData: TCustomRVData; Safe: Boolean);
  1569. var i: Integer;
  1570.     s: String;
  1571. begin
  1572.   for i := 0 to Items.Count-1 do begin
  1573.     s := Items[i];
  1574.     GetItem(i).Inserting(RVData, s, Safe);
  1575.     Items[i] := s;
  1576.   end;
  1577. end;
  1578. {------------------------------------------------------------------------------}
  1579. procedure TCustomRVData.Beep;
  1580. begin
  1581.   if (GetRVStyle<>nil) and (GetRVStyle.UseSound) then
  1582.     MessageBeep(MB_OK);
  1583. end;
  1584. {------------------------------------------------------------------------------}
  1585. procedure TCustomRVData.SetParagraphStyleToAll(ParaNo: Integer);
  1586. var i: Integer;
  1587. begin
  1588.   for i := 0 to Items.Count-1 do
  1589.     if GetItemStyle(i)<>rvsBreak then
  1590.       GetItem(i).ParaNo := ParaNo;
  1591. end;
  1592. {------------------------------------------------------------------------------}
  1593. function TCustomRVData.GetRVData: TCustomRVData;
  1594. begin
  1595.   Result := Self;
  1596. end;
  1597. {------------------------------------------------------------------------------}
  1598. function TCustomRVData.GetSourceRVData: TCustomRVData;
  1599. begin
  1600.   Result := Self;
  1601. end;
  1602. {------------------------------------------------------------------------------}
  1603. function TCustomRVData.GetItem(ItemNo: Integer): TCustomRVItemInfo;
  1604. begin
  1605.   Result := TCustomRVItemInfo(Items.Objects[ItemNo]);
  1606. end;
  1607. {------------------------------------------------------------------------------}
  1608. function TCustomRVData.GetRTFProperties: TPersistent;
  1609. begin
  1610.   Result := GetRootData.GetRTFProperties;
  1611. end;
  1612. {------------------------------------------------------------------------------}
  1613. function TCustomRVData.RV_CanConcateItems(FirstItemNo: Integer;
  1614.                                           item1, item2: TCustomRVItemInfo;
  1615.                                           IgnorePara: Boolean): Boolean;
  1616. var RVStyle: TRVStyle;
  1617. begin
  1618.   RVStyle := GetRVStyle;
  1619.   if (item1=nil) or (item2=nil) or (item1.StyleNo<0) or (item2.StyleNo<0) then begin
  1620.     Result := False;
  1621.     exit;
  1622.   end;
  1623.   if ((Items[FirstItemNo]='') or (Items[FirstItemNo+1]='')) and
  1624.      (IgnorePara or item2.SameAsPrev) then begin
  1625.     Result := True;
  1626.     exit;
  1627.   end;
  1628.   Result := (item1.StyleNo=item2.StyleNo) and
  1629.             (IgnorePara or item2.SameAsPrev) and
  1630.             {$IFNDEF RVDONOTUSEUNICODE}
  1631.             (RVStyle.TextStyles[GetActualStyle(item1)].Unicode=
  1632.               RVStyle.TextStyles[GetActualStyle(item2)].Unicode) and
  1633.             {$ENDIF}
  1634.             {$IFNDEF RVDONOTUSEITEMHINTS}
  1635.             (item1.Hint=item2.Hint) and
  1636.             {$ENDIF}
  1637.             RV_CompareTags(item1.Tag,item2.Tag, rvoTagsArePChars in Options) and
  1638.             (item2.Checkpoint=nil) and
  1639.             (
  1640.             (Length(Items[FirstItemNo])=0) or
  1641.             (Length(Items[FirstItemNo+1])=0) or
  1642.             ([rvprConcateProtect,rvprModifyProtect]*
  1643.               RVStyle.TextStyles[GetActualStyle(item1)].Protection=[])
  1644.             )
  1645. end;
  1646. {------------------------------------------------------------------------------}
  1647. procedure TCustomRVData.SimpleConcate(FirstItemNo: Integer; item1,
  1648.   item2: TCustomRVItemInfo);
  1649. begin
  1650.   Items[FirstItemNo] := Items[FirstItemNo]+Items[FirstItemNo+1];
  1651.   InternalFreeItem(item2,False);
  1652.   Items.Delete(FirstItemNo+1);
  1653. end;
  1654. {------------------------------------------------------------------------------}
  1655. procedure TCustomRVData.MassSimpleConcate(FirstItemNo,
  1656.   LastItemNo: Integer);
  1657. var i: Integer;
  1658.     item1,
  1659.     item2: TCustomRVItemInfo;
  1660. begin
  1661.   if FirstItemNo<0 then
  1662.     FirstItemNo := 0;
  1663.   if LastItemNo>=Items.Count then
  1664.     LastItemNo := Items.Count-1;
  1665.   for i := LastItemNo downto FirstItemNo+1 do begin
  1666.     SimpleConcateSubitems(i);
  1667.     item1 := TCustomRVItemInfo(Items.Objects[i-1]);
  1668.     item2 := TCustomRVItemInfo(Items.Objects[i]);
  1669.     if RV_CanConcateItems(i-1, item1, item2, False) then
  1670.       SimpleConcate(i-1, item1, item2);
  1671.   end;
  1672.   if (FirstItemNo>=0) and (FirstItemNo<=LastItemNo) then
  1673.     SimpleConcateSubitems(FirstItemNo);
  1674. end;
  1675. {------------------------------------------------------------------------------}
  1676. procedure TCustomRVData.SimpleConcateSubitems(ItemNo: Integer);
  1677. var StoreSub: TRVStoreSubRVData;
  1678.     SubRVData: TCustomRVData;
  1679.     item: TCustomRVItemInfo;
  1680.     i: Integer;
  1681. begin
  1682.   item := GetItem(ItemNo);
  1683.   SubRVData := TCustomRVData(item.GetSubRVData(StoreSub,rvdFirst));
  1684.   while SubRVData<>nil do begin
  1685.     SubRVData.MassSimpleConcate(0, SubRVData.ItemCount-1);
  1686.     for i := 0 to SubRVData.ItemCount-1 do
  1687.       SubRVData.SimpleConcateSubitems(i);
  1688.     SubRVData := TCustomRVData(item.GetSubRVData(StoreSub, rvdNext));
  1689.   end;
  1690.   StoreSub.Free;
  1691. end;
  1692. {------------------------------------------------------------------------------}
  1693. {$IFNDEF RVDONOTUSERTFIMPORT}
  1694. function TCustomRVData.LoadRTF(const FileName: String): TRVRTFErrorCode;
  1695. var rp: TRVRTFReaderProperties;
  1696.     ItemNo: Integer;
  1697. begin
  1698.   rp := TRVRTFReaderProperties(GetRTFProperties);
  1699.   if rp<>nil then begin
  1700.     ItemNo := Items.Count-1;
  1701.     rp.BasePath := ExtractFilePath(FileName);
  1702.     try
  1703.       Result := rp.ReadFromFile(FileName, Self);
  1704.     finally
  1705.       rp.BasePath := '';
  1706.     end;
  1707.     MassSimpleConcate(ItemNo, Items.Count-1);
  1708.     end
  1709.   else
  1710.     Result := rtf_ec_Assertion;
  1711. end;
  1712. {------------------------------------------------------------------------------}
  1713. function TCustomRVData.LoadRTFFromStream(Stream: TStream): TRVRTFErrorCode;
  1714. var rp: TRVRTFReaderProperties;
  1715.     ItemNo: Integer;
  1716. begin
  1717.   rp := TRVRTFReaderProperties(GetRTFProperties);
  1718.   if rp<>nil then begin
  1719.     ItemNo := Items.Count-1;
  1720.     Result := rp.ReadFromStream(Stream, Self);
  1721.     MassSimpleConcate(ItemNo, Items.Count-1);
  1722.     end
  1723.   else
  1724.     Result := rtf_ec_Assertion;
  1725. end;
  1726. {------------------------------------------------------------------------------}
  1727. {$IFDEF RVUSEWORDDOC}
  1728. function TCustomRVData.LoadWordDoc(const FileName: String):TRVRTFErrorCode;
  1729. var rp: TRVRTFReaderProperties;
  1730.     ItemNo: Integer;
  1731. begin
  1732.   rp := TRVRTFReaderProperties(GetRTFProperties);
  1733.   if rp<>nil then begin
  1734.     ItemNo := Items.Count-1;
  1735.     Result := rp.ReadFromWordDocFile(FileName, Self);
  1736.     MassSimpleConcate(ItemNo, Items.Count-1);
  1737.     end
  1738.   else
  1739.     Result := rtf_ec_Assertion;
  1740. end;
  1741. {$ENDIF}
  1742. {$ENDIF}
  1743. {------------------------------------------------------------------------------}
  1744. procedure TCustomRVData.DoMarkStylesInUse(Data: TRVDeleteUnusedStylesData);
  1745. var i: Integer;
  1746. begin
  1747.   for i := 0 to Items.Count-1 do
  1748.     GetItem(i).MarkStylesInUse(Data);
  1749. end;
  1750. {------------------------------------------------------------------------------}
  1751. procedure TCustomRVData.DoUpdateStyles(Data: TRVDeleteUnusedStylesData);
  1752. var i: Integer;
  1753. begin
  1754.   for i := 0 to Items.Count-1 do
  1755.     GetItem(i).UpdateStyles(Data);
  1756. end;
  1757. {------------------------------------------------------------------------------}
  1758. procedure TCustomRVData.MarkStylesInUse(Data: TRVDeleteUnusedStylesData);
  1759.     {............................................}
  1760.     procedure ExpandStyle(Index, FirstIndex: Integer; Styles: TCustomRVInfos;
  1761.       Used, Expanded: TRVIntegerList);
  1762.     var Style: TCustomRVInfo;
  1763.     begin
  1764.       if Expanded[Index]<>0 then
  1765.         exit;
  1766.       Used[Index] := 1;
  1767.       Expanded[Index] := 1;
  1768.       Style := TCustomRVInfo(Styles.Items[Index]);
  1769.       if Style.BaseStyleNo>=0 then begin
  1770.         if Style.BaseStyleNo >= Styles.Count then
  1771.           Style.BaseStyleNo := -1
  1772.         else
  1773.           ExpandStyle(Style.BaseStyleNo, FirstIndex, Styles, Used, Expanded);
  1774.       end;
  1775.       if (Styles is TFontInfos) and (TFontInfo(Style).NextStyleNo>=0) then begin
  1776.         if TFontInfo(Style).NextStyleNo>= Styles.Count then
  1777.           TFontInfo(Style).NextStyleNo := -1
  1778.         else
  1779.           ExpandStyle(TFontInfo(Style).NextStyleNo, FirstIndex, Styles, Used, Expanded)
  1780.         end
  1781.       else if (Styles is TParaInfos) and (TParaInfo(Style).NextParaNo>=0) then begin
  1782.         if TParaInfo(Style).NextParaNo >= Styles.Count then
  1783.           TParaInfo(Style).NextParaNo := -1
  1784.         else
  1785.           ExpandStyle(TParaInfo(Style).NextParaNo, FirstIndex, Styles, Used, Expanded);
  1786.       end;
  1787.     end;
  1788.     {............................................}
  1789.     procedure ExpandStyles(Styles: TCustomRVInfos; Used: TRVIntegerList);
  1790.     var i: Integer;
  1791.         Expanded: TRVIntegerList;
  1792.     begin
  1793.       Expanded := TRVIntegerList.CreateEx(Used.Count, 0);
  1794.       for i := 0 to Used.Count-1 do
  1795.         if (Used[i]<>0) then
  1796.           ExpandStyle(i, i, Styles, Used, Expanded);
  1797.       Expanded.Free;
  1798.     end;
  1799.     {............................................}
  1800.     procedure MarkDefStyles;
  1801.     var i: Integer;
  1802.         RVStyle: TRVStyle;
  1803.     begin
  1804.       RVStyle := GetRVStyle;
  1805.       for i := 0 to RVStyle.ParaStyles.Count-1 do
  1806.         if (Data.UsedParaStyles[i]<>0) and
  1807.            (RVStyle.ParaStyles[i].DefStyleNo>=0) then
  1808.           Data.UsedTextStyles[RVStyle.ParaStyles[i].DefStyleNo] := 1;
  1809.     end;
  1810.     {............................................}
  1811. begin
  1812.   Data.Init(GetRVStyle);
  1813.   DoMarkStylesInUse(Data);
  1814.   if Data.ParaStyles then
  1815.     ExpandStyles(GetRVStyle.ParaStyles, Data.UsedParaStyles);
  1816.   if Data.TextStyles then begin
  1817.     MarkDefStyles;
  1818.     {$IFNDEF RVDONOTUSEUNICODE}
  1819.     if (GetRVStyle.DefUnicodeStyle>=0) then
  1820.       if GetRVStyle.DefUnicodeStyle>=Data.UsedTextStyles.Count then
  1821.         GetRVStyle.DefUnicodeStyle := -1
  1822.       else
  1823.         Data.UsedTextStyles[GetRVStyle.DefUnicodeStyle] := 1;
  1824.     {$ENDIF}
  1825.     ExpandStyles(GetRVStyle.TextStyles, Data.UsedTextStyles);
  1826.   end;
  1827.   if Data.ListStyles then
  1828.     ExpandStyles(GetRVStyle.ListStyles, Data.UsedListStyles);
  1829. end;
  1830. {------------------------------------------------------------------------------}
  1831. procedure TCustomRVData.DeleteMarkedStyles(Data: TRVDeleteUnusedStylesData);
  1832. begin
  1833.   Data.ConvertFlagsToShifts(Self.GetRVStyle);
  1834.   DoUpdateStyles(Data);
  1835.   AfterDeleteStyles(Data);  
  1836. end;
  1837. {------------------------------------------------------------------------------}
  1838. procedure TCustomRVData.DeleteUnusedStyles(TextStyles, ParaStyles, ListStyles: Boolean);
  1839. var Data: TRVDeleteUnusedStylesData;
  1840. begin
  1841.   Data := TRVDeleteUnusedStylesData.Create(TextStyles, ParaStyles, ListStyles);
  1842.   try
  1843.     MarkStylesInUse(Data);
  1844.     DeleteMarkedStyles(Data);
  1845.     {$IFNDEF RVDONOTUSEUNICODE}
  1846.     if TextStyles and (GetRVStyle.DefUnicodeStyle>=0) then
  1847.       if GetRVStyle.DefUnicodeStyle>=Data.UsedTextStyles.Count then
  1848.         GetRVStyle.DefUnicodeStyle := -1
  1849.       else
  1850.         GetRVStyle.DefUnicodeStyle :=
  1851.           GetRVStyle.DefUnicodeStyle-Data.UsedTextStyles[GetRVStyle.DefUnicodeStyle]+1;
  1852.     {$ENDIF}
  1853.   finally
  1854.     Data.Free;
  1855.   end;
  1856. end;
  1857. {------------------------------------------------------------------------------}
  1858. procedure TCustomRVData.AfterDeleteStyles(Data: TRVDeleteUnusedStylesData);
  1859. begin
  1860.   // nothing to do here
  1861. end;
  1862. {------------------------------------------------------------------------------}
  1863. procedure TCustomRVData.InitStyleMappings(var PTextStylesMapping,
  1864.   PParaStylesMapping, PListStylesMapping: PRVIntegerList);
  1865. begin
  1866.   GetRootData.InitStyleMappings(PTextStylesMapping, PParaStylesMapping, PListStylesMapping);
  1867. end;
  1868. {------------------------------------------------------------------------------}
  1869. procedure TCustomRVData.DoneStyleMappings(PTextStylesMapping,
  1870.   PParaStylesMapping, PListStylesMapping: PRVIntegerList);
  1871. begin
  1872.   // nothing to do here
  1873. end;
  1874. {------------------------------------------------------------------------------}
  1875. function TCustomRVData.SupportsPageBreaks: Boolean;
  1876. begin
  1877.   Result := True;
  1878. end;
  1879. {------------------------------------------------------------------------------}
  1880. procedure TCustomRVData.AdjustInItemsRange(var ItemNo: Integer);
  1881. begin
  1882.   if ItemNo>=Items.Count then
  1883.     ItemNo := Items.Count-1;
  1884.   if ItemNo<0 then
  1885.     ItemNo := 0;
  1886. end;
  1887. {------------------------------------------------------------------------------}
  1888. function TCustomRVData.NextChar(ItemNo, Index: Integer): Integer;
  1889. begin
  1890.   Result := NextCharStr(Items[ItemNo], ItemNo, Index);
  1891. end;
  1892. {------------------------------------------------------------------------------}
  1893. function TCustomRVData.PrevChar(ItemNo, Index: Integer): Integer;
  1894. begin
  1895.   Result := PrevCharStr(Items[ItemNo], ItemNo, Index);
  1896. end;
  1897. {------------------------------------------------------------------------------}
  1898. function TCustomRVData.NextCharStr(const str: String;
  1899.   ItemNo, Index: Integer): Integer;
  1900. {$IFNDEF RVDONOTUSEUNICODE}
  1901. var s: String;
  1902.     p1,p2: Pointer;
  1903. {$ENDIF}
  1904. begin
  1905.   {$IFNDEF RVDONOTUSEUNICODE}
  1906.   if RVNT and (rvioUnicode in GetItemOptions(ItemNo)) then begin
  1907.     s := str;
  1908.     SetLength(s, Length(s)+1);
  1909.     s[Length(s)]:=#0;
  1910.     p1 := Pointer(s);
  1911.     p2 := CharNextW(Pointer(PChar(p1)+(Index-1)*2));
  1912.     Result := (PChar(p2)-PChar(p1)) div 2+1;
  1913.     end
  1914.   else
  1915.   {$ENDIF}
  1916.     Result := Index+1;
  1917. end;
  1918. {------------------------------------------------------------------------------}
  1919. function TCustomRVData.PrevCharStr(const str: String;
  1920.   ItemNo, Index: Integer): Integer;
  1921. {$IFNDEF RVDONOTUSEUNICODE}
  1922. var s: String;
  1923.     p1,p2: Pointer;
  1924. {$ENDIF}
  1925. begin
  1926.   {$IFNDEF RVDONOTUSEUNICODE}
  1927.   if RVNT and (rvioUnicode in GetItemOptions(ItemNo)) then begin
  1928.     s := str;
  1929.     SetLength(s, Length(s)+1);
  1930.     s[Length(s)]:=#0;
  1931.     p1 := Pointer(s);
  1932.     p2 := CharPrevW(p1, Pointer(PChar(p1)+(Index-1)*2));
  1933.     if p2=PChar(p1)+(Index-1)*2 then
  1934.       p2 := p1;
  1935.     Result := (PChar(p2)-PChar(p1)) div 2+1;
  1936.     end
  1937.   else
  1938.   {$ENDIF}
  1939.     Result := Index-1;
  1940. end;
  1941. {------------------------------------------------------------------------------}
  1942. function TCustomRVData.GetFirstParaItem(ItemNo: Integer): Integer;
  1943. begin
  1944.   Result := ItemNo;
  1945.   while (Result>0) and not IsParaStart(Result) do
  1946.     dec(Result);
  1947. end;
  1948. {------------------------------------------------------------------------------}
  1949. function TCustomRVData.GetFirstParaSectionItem(ItemNo: Integer): Integer;
  1950. begin
  1951.   Result := ItemNo;
  1952.   while (Result>0) and not IsFromNewLine(Result) do
  1953.     dec(Result);
  1954. end;
  1955. {------------------------------------------------------------------------------}
  1956. procedure TCustomRVData.GetParentInfo(var ParentItemNo: Integer;
  1957.   var Location: TRVStoreSubRVData);
  1958. begin
  1959.   ParentItemNo := -1;
  1960.   Location   := nil;
  1961. end;
  1962. {------------------------------------------------------------------------------}
  1963. function TCustomRVData.GetBiDiMode: TRVBiDiMode;
  1964. begin
  1965.   Result := GetRootData.GetBiDiMode;
  1966. end;
  1967. {------------------------------------------------------------------------------}
  1968. function TCustomRVData.GetItemBiDiMode(ItemNo: Integer): TRVBiDiMode;
  1969. var item: TCustomRVItemInfo;
  1970. begin
  1971.   item := GetItem(ItemNo);
  1972.   if item.StyleNo>=0 then
  1973.     Result := GetRVStyle.TextStyles[GetActualStyle(item)].BiDiMode
  1974.   else
  1975.     Result := rvbdUnspecified;
  1976.   if Result=rvbdUnspecified then
  1977.     Result := GetParaBiDiMode(item.ParaNo);
  1978. end;
  1979. {------------------------------------------------------------------------------}
  1980. function TCustomRVData.GetParaBiDiMode(
  1981.   ParaNo: Integer): TRVBiDiMode;
  1982. begin
  1983.   Result := GetRVStyle.ParaStyles[ParaNo].BiDiMode;
  1984.   if Result=rvbdUnspecified then
  1985.     Result := GetBiDiMode;
  1986. end;
  1987. {------------------------------------------------------------------------------}
  1988. {$IFNDEF RVDONOTUSELISTS}
  1989. function TCustomRVData.SetListMarkerInfo(AItemNo, AListNo, AListLevel, AStartFrom, AParaNo: Integer;
  1990.                                      AUseStartFrom: Boolean): Integer;
  1991. var Marker: TRVMarkerItemInfo;
  1992.     s: String;
  1993.     Markers: TRVMarkerList;
  1994. begin
  1995.   if (AItemNo>=Items.Count) or (AItemNo<0) then
  1996.     Result := Items.Count
  1997.   else begin
  1998.     Result := GetFirstParaItem(AItemNo);
  1999.     if GetItem(Result).GetBoolValue(rvbpFullWidth) then begin
  2000.       Result := -1;
  2001.       exit;
  2002.     end;
  2003.   end;
  2004.   if (Result<Items.Count) and (GetItemStyle(Result)=rvsListMarker) then begin
  2005.     Marker := TRVMarkerItemInfo(GetItem(Result));
  2006.     Marker.ListNo    := AListNo;
  2007.     Marker.Level     := AListLevel;
  2008.     Marker.StartFrom := AStartFrom;
  2009.     Marker.Reset     := AUseStartFrom;
  2010.     Markers := GetMarkers(False);
  2011.     if Markers<>nil then
  2012.       Markers.RecalcCounters(Marker.GetIndexInList(Markers), GetRVStyle);
  2013.     end
  2014.   else begin
  2015.     Marker := TRVMarkerItemInfo.CreateEx(Self, AListNo, AListLevel, AStartFrom, AUseStartFrom);
  2016.     s := '';
  2017.     Marker.Inserting(Self,s,False);
  2018.     if Result<Items.Count then begin
  2019.       GetItem(Result).SameAsPrev := True;
  2020.       Marker.ParaNo := GetItemPara(Result);
  2021.       end
  2022.     else begin
  2023.       Marker.ParaNo := AParaNo;
  2024.       if AParaNo<0 then
  2025.         if Items.Count=0 then
  2026.           Marker.ParaNo := 0
  2027.         else
  2028.           Marker.ParaNo := GetItemPara(Items.Count-1);
  2029.     end;
  2030.     Items.InsertObject(Result, s, Marker);
  2031.     Marker.Inserted(Self, Result);
  2032.     AddMarkerInList(Result);
  2033.   end;
  2034. end;
  2035. {------------------------------------------------------------------------------}
  2036. procedure TCustomRVData.RecalcMarker(AItemNo: Integer; AllowCreateList: Boolean);
  2037. var Markers: TRVMarkerList;
  2038. begin
  2039.   if GetItemStyle(AItemNo)<>rvsListMarker then
  2040.     exit;
  2041.   Markers := GetMarkers(AllowCreateList);
  2042.   if Markers=nil then
  2043.     exit;
  2044.   Markers.RecalcCounters(TRVMarkerItemInfo(GetItem(AItemNo)).GetIndexInList(Markers), GetRVStyle);
  2045. end;
  2046. {------------------------------------------------------------------------------}
  2047. procedure TCustomRVData.RemoveListMarker(ItemNo: Integer);
  2048. begin
  2049.   ItemNo := GetFirstParaItem(ItemNo);
  2050.   if GetItemStyle(ItemNo)=rvsListMarker then begin
  2051.     DeleteItems(ItemNo,1);
  2052.     if ItemNo<Items.Count then
  2053.       GetItem(ItemNo).SameAsPrev := False;
  2054.   end;
  2055. end;
  2056. {------------------------------------------------------------------------------}
  2057. function TCustomRVData.GetListMarkerInfo(AItemNo: Integer;
  2058.                                  var AListNo, AListLevel, AStartFrom: Integer;
  2059.                                  var AUseStartFrom: Boolean): Integer;
  2060. begin
  2061.   Result := GetFirstParaItem(AItemNo);
  2062.   if GetItemStyle(Result)<>rvsListMarker then begin
  2063.     Result := -1;
  2064.     exit;
  2065.   end;
  2066.   with TRVMarkerItemInfo(GetItem(Result)) do begin
  2067.     AListNo := ListNo;
  2068.     AListLevel := Level;
  2069.     AStartFrom := StartFrom;
  2070.     AUseStartFrom := Reset;
  2071.   end;
  2072. end;
  2073. {------------------------------------------------------------------------------}
  2074. function TCustomRVData.GetMarkers(AllowCreate: Boolean): TRVMarkerList;
  2075. begin
  2076.   Result := GetAbsoluteRootData.GetMarkers(AllowCreate);
  2077. end;
  2078. {------------------------------------------------------------------------------}
  2079. function TCustomRVData.GetPrevMarkers: TRVMarkerList;
  2080. begin
  2081.   Result := nil;
  2082. end;
  2083. {------------------------------------------------------------------------------}
  2084. procedure TCustomRVData.DestroyMarkers;
  2085. begin
  2086.   GetAbsoluteRootData.DestroyMarkers;
  2087. end;
  2088. {------------------------------------------------------------------------------}
  2089. procedure TCustomRVData.AddMarkerInList(ItemNo: Integer);
  2090. var List: TRVMarkerList;
  2091.     PrevMarker: TRVMarkerItemInfo;
  2092.     Index: Integer;
  2093. begin
  2094.   if GetItemStyle(ItemNo)<>rvsListMarker then
  2095.     exit;
  2096.   List := GetMarkers(True);
  2097.   if List=nil then
  2098.     exit;
  2099.   if TRVMarkerItemInfo(GetItem(ItemNo)).GetIndexInList(List)>=0 then
  2100.     exit;
  2101.   PrevMarker := FindPreviousMarker(ItemNo-1);
  2102.   Index := List.InsertAfter(TRVMarkerItemInfo(GetItem(ItemNo)), PrevMarker);
  2103.   GetMarkers(False).RecalcCounters(Index, GetRVStyle);
  2104. end;
  2105. {------------------------------------------------------------------------------}
  2106. procedure TCustomRVData.DeleteMarkerFromList(Item: TCustomRVItemInfo; Clearing: Boolean);
  2107. var List: TRVMarkerList;
  2108.     Index: Integer;
  2109. begin
  2110.   if Item.StyleNo=rvsListMarker then begin
  2111.     List := GetMarkers(False);
  2112.     if List=nil then
  2113.       exit;
  2114.     Index := List.IndexOf(Item);
  2115.     List.Delete(Index);
  2116.     if List.Count=0 then
  2117.       DestroyMarkers
  2118.     else if not Clearing then
  2119.       List.RecalcCounters(Index, GetRVStyle);
  2120.   end;
  2121. end;
  2122. {------------------------------------------------------------------------------}
  2123. function TCustomRVData.FindPreviousMarker(ItemNo: Integer): TRVMarkerItemInfo;
  2124.    {...................................................}
  2125.    function FindMarkerInRVData(RVData: TCustomRVData; LastItemNo: Integer): TRVMarkerItemInfo; forward;
  2126.    {...................................................}
  2127.    function FindMarkerInItem(Item: TCustomRVItemInfo; StoreSub: TRVStoreSubRVData): TRVMarkerItemInfo;
  2128.    var RVData: TCustomRVData;
  2129.    begin
  2130.      Result := nil;
  2131.      if StoreSub=nil then
  2132.        RVData := TCustomRVData(item.GetSubRVData(StoreSub, rvdLast))
  2133.      else
  2134.        RVData := TCustomRVData(item.GetSubRVData(StoreSub, rvdPrev));
  2135.      if RVData<>nil then begin
  2136.        repeat
  2137.          Result := FindMarkerInRVData(RVData, RVData.Items.Count-1);
  2138.          if Result<>nil then
  2139.            break;
  2140.          RVData := TCustomRVData(item.GetSubRVData(StoreSub, rvdPrev));
  2141.        until RVData=nil;
  2142.      end;
  2143.      StoreSub.Free;
  2144.    end;
  2145.    {...................................................}
  2146.    function FindMarkerInRVData(RVData: TCustomRVData; LastItemNo: Integer): TRVMarkerItemInfo;
  2147.    var i: Integer;
  2148.    begin
  2149.      for i := LastItemNo downto 0 do begin
  2150.        if RVData.GetItem(i).StyleNo=rvsListMarker then
  2151.          Result := TRVMarkerItemInfo(RVData.GetItem(i))
  2152.        else
  2153.          Result := FindMarkerInItem(RVData.GetItem(i), nil);
  2154.        if Result<>nil then
  2155.          exit;
  2156.      end;
  2157.      Result := nil;
  2158.    end;
  2159.    {...................................................}
  2160. var RVData: TCustomRVData;
  2161.     StoreSub: TRVStoreSubRVData;
  2162. begin
  2163.   Result := nil;
  2164.   RVData := Self;
  2165.   while RVData<>nil do begin
  2166.     Result := FindMarkerInRVData(RVData, ItemNo);
  2167.     if Result<>nil then
  2168.       break;
  2169.     RVData.GetParentInfo(ItemNo, StoreSub);
  2170.     if ItemNo<0 then begin
  2171.       StoreSub.Free;
  2172.       break;
  2173.     end;
  2174.     RVData := RVData.GetAbsoluteParentData;
  2175.     Result := FindMarkerInItem(RVData.GetItem(ItemNo), StoreSub);
  2176.     if Result<>nil then
  2177.       break;
  2178.     dec(ItemNo);
  2179.   end;
  2180. end;
  2181. {------------------------------------------------------------------------------}
  2182. function TCustomRVData.FindMarkerLocalLocationFrom(StartItemNo: Integer;
  2183.   Marker: TRVMarkerItemInfo): Integer;
  2184.    {...................................................}
  2185.    function FindMarkerInRVData(RVData: TCustomRVData; FirstItemNo: Integer): Integer; forward;
  2186.    {...................................................}
  2187.    function FindMarkerInItem(Item: TCustomRVItemInfo): Boolean;
  2188.    var RVData: TCustomRVData;
  2189.        StoreSub: TRVStoreSubRVData;
  2190.    begin
  2191.      Result := False;
  2192.      RVData := TCustomRVData(item.GetSubRVData(StoreSub, rvdFirst));
  2193.      if RVData<>nil then begin
  2194.        repeat
  2195.          Result := FindMarkerInRVData(RVData, 0)>=0;
  2196.          if Result then
  2197.            break;
  2198.          RVData := TCustomRVData(item.GetSubRVData(StoreSub, rvdNext));
  2199.        until RVData=nil;
  2200.      end;
  2201.      StoreSub.Free;
  2202.    end;
  2203.    {...................................................}
  2204.    function FindMarkerInRVData(RVData: TCustomRVData; FirstItemNo: Integer): Integer;
  2205.    var i: Integer;
  2206.    begin
  2207.      for i := FirstItemNo to RVData.Items.Count-1 do
  2208.        if (RVData.GetItem(i)=Marker) or
  2209.            FindMarkerInItem(RVData.GetItem(i)) then begin
  2210.          Result := i;
  2211.          exit;
  2212.        end;
  2213.      Result := -1;
  2214.    end;
  2215.    {...................................................}
  2216. begin;
  2217.   Result := FindMarkerInRVData(Self, StartItemNo);
  2218. end;
  2219. {------------------------------------------------------------------------------}
  2220. function TCustomRVData.FindLastMarkerIndex(StartAfterMeIndex: Integer;
  2221.   ListStyles: TRVIntegerList): Integer;
  2222. var i, j, ListNo: Integer;
  2223.     ok: Boolean;
  2224.     Markers: TRVMarkerList;
  2225. begin
  2226.   Result := -1;
  2227.   Markers := GetMarkers(False);
  2228.   if Markers=nil then
  2229.     exit;
  2230.   for i := Markers.Count-1 downto StartAfterMeIndex+1 do begin
  2231.     ok := False;
  2232.     ListNo := TRVMarkerItemInfo(Markers[i]).ListNo;
  2233.     for j := 0 to ListStyles.Count-1 do
  2234.       if ListStyles[j] = ListNo then begin
  2235.         ok := True;
  2236.         break;
  2237.       end;
  2238.     if ok then begin
  2239.       Result := i;
  2240.       exit;
  2241.     end;
  2242.   end;
  2243. end;
  2244. {$ENDIF}
  2245. function TCustomRVData.GetChosenItem: TCustomRVItemInfo;
  2246. begin
  2247.   Result := nil;
  2248. end;
  2249. function TCustomRVData.GetChosenRVData: TCustomRVData;
  2250. begin
  2251.   Result := nil;
  2252. end;
  2253. function TCustomRVData.GetItemText(ItemNo: Integer): String;
  2254. begin
  2255.   Result := Items[ItemNo];
  2256. end;
  2257. procedure TCustomRVData.SetItemText(ItemNo: Integer; const s: String);
  2258. begin
  2259.   if rvioUnicode in GetItemOptions(ItemNo) then
  2260.     RVCheckUni(Length(s));
  2261.   Items[ItemNo] := s;
  2262. end;
  2263. {------------------------------------------------------------------------------}
  2264. { Returns the first and the last item of paragraph section containing
  2265.   the given range of items }
  2266. procedure TCustomRVData.ExpandToParaSection(ItemNo1,ItemNo2: Integer;
  2267.   var FirstItemNo, LastItemNo: Integer);
  2268. begin
  2269.   FirstItemNo := ItemNo1;
  2270.   while (FirstItemNo>0) and not IsFromNewLine(FirstItemNo) do
  2271.     dec(FirstItemNo);
  2272.   LastItemNo := ItemNo2+1;
  2273.   while (LastItemNo<Items.Count) and not IsFromNewLine(LastItemNo) do
  2274.     inc(LastItemNo);
  2275.   dec(LastItemNo);
  2276. end;
  2277. {------------------------------------------------------------------------------}
  2278. { Returns the first and the last item of paragraph containing
  2279.   the given range of items }
  2280. procedure TCustomRVData.ExpandToPara(ItemNo1,ItemNo2: Integer;
  2281.   var FirstItemNo, LastItemNo: Integer);
  2282. begin
  2283.   FirstItemNo := ItemNo1;
  2284.   while (FirstItemNo>0) and not IsParaStart(FirstItemNo) do
  2285.     dec(FirstItemNo);
  2286.   LastItemNo := ItemNo2+1;
  2287.   while (LastItemNo<Items.Count) and not IsParaStart(LastItemNo) do
  2288.     inc(LastItemNo);
  2289.   dec(LastItemNo);
  2290. end;
  2291. {------------------------------------------------------------------------------}
  2292. { READ method for ItemCount property }
  2293. function TCustomRVData.GetItemCount: Integer;
  2294. begin
  2295.   Result := Items.Count;
  2296. end;
  2297. {------------------------------------------------------------------------------}
  2298. { Inits editing mode and returns RVData of inplace editor. For most RVDatas,
  2299.   this method does nothing and returns themselves.
  2300.   Overriden in TRVTableCellData. }
  2301. function TCustomRVData.Edit: TCustomRVData;
  2302. begin
  2303.   Result := Self;
  2304. end;
  2305. {------------------------------------------------------------------------------}
  2306. { Enumerates all items from the first to the last one: calls Proc for each item.
  2307.   Items in sub-documents (cells) are included. If they are edited, RVData of
  2308.   inplace editor is used as a parameter. Value of UserData is passed as a
  2309.   last parameter of Proc. }
  2310. function TCustomRVData.EnumItems(Proc: TRVEnumItemsProc; var UserData1: Integer;
  2311.       const UserData2: String): Boolean;
  2312. var i: Integer;
  2313.     RVData: TCustomRVData;
  2314.     StoreSub: TRVStoreSubRVData;
  2315.     item: TCustomRVItemInfo;
  2316. begin
  2317.   Result := True;
  2318.   for i := 0 to ItemCount-1 do begin
  2319.     Proc(Self, i, UserData1, UserData2, Result);
  2320.     if not Result then
  2321.       exit;
  2322.     item := GetItem(i);
  2323.     RVData := TCustomRVData(item.GetSubRVData(StoreSub, rvdFirst));
  2324.     if RVData<>nil then begin
  2325.        repeat
  2326.          Result := RVData.GetRVData.EnumItems(Proc, UserData1, UserData2);
  2327.          if not Result then
  2328.            break;
  2329.          RVData := TCustomRVData(item.GetSubRVData(StoreSub, rvdNext));
  2330.        until RVData=nil;
  2331.      end;
  2332.      StoreSub.Free;
  2333.    end;
  2334. end;
  2335. {------------------------------------------------------------------------------}
  2336. { Compares two locations in the same document:
  2337.   (RVData1, ItemNo1) and (RVData2, ItemNo2).
  2338.   Return value: 0 if equal, <0 if (1) before (2), >0 if (1) after (2).
  2339.   Table is assumed before its cells. }
  2340. function RVCompareLocations(RVData1: TCustomRVData; ItemNo1: Integer;
  2341.   RVData2: TCustomRVData; ItemNo2: Integer): Integer;
  2342. var CurItemNo2: Integer;
  2343.     CurRVData2: TCustomRVData;
  2344.     StoreSub1,StoreSub2: TRVStoreSubRVData;
  2345. begin
  2346.   RVData1 := RVData1.GetSourceRVData;
  2347.   RVData2 := RVData2.GetSourceRVData;
  2348.   CurRVData2 := RVData2;
  2349.   CurItemNo2 := ItemNo2;
  2350.   StoreSub1 := nil;
  2351.   StoreSub2 := nil;
  2352.   while True do begin
  2353.     while True do begin
  2354.       if RVData1=CurRVData2 then begin
  2355.         Result := ItemNo1-CurItemNo2; // different items?
  2356.         if Result=0 then
  2357.           if StoreSub1<>nil then
  2358.             if StoreSub2<>nil then
  2359.               Result := StoreSub1.Compare(StoreSub2) // cells in the same table?
  2360.             else
  2361.               Result := +1 // (1) is from table cell, (2) is a table itself
  2362.           else
  2363.             if StoreSub2<>nil then
  2364.               Result := -1  // (2) is from table cell, (1) is a table itself
  2365.             else
  2366.               Result := 0; // the same item;
  2367.         StoreSub1.Free;
  2368.         StoreSub2.Free;
  2369.         exit;
  2370.       end;
  2371.       StoreSub2.Free;
  2372.       CurRVData2.GetParentInfo(CurItemNo2, StoreSub2);
  2373.       if CurItemNo2<0 then
  2374.         break;
  2375.       CurRVData2 := CurRVData2.GetAbsoluteParentData.GetSourceRVData;
  2376.     end;
  2377.     StoreSub1.Free;
  2378.     RVData1.GetParentInfo(ItemNo1, StoreSub1);
  2379.     if ItemNo1<0 then
  2380.       raise ERichViewError.Create(errRVCompare);
  2381.     RVData1 := RVData1.GetAbsoluteParentData.GetSourceRVData;
  2382.     CurRVData2 := RVData2;
  2383.   end;
  2384. end;
  2385. initialization
  2386.   {$IFNDEF RVDONOTUSERVF}
  2387.   RegisterClasses([TBitmap, TIcon, TMetafile]);
  2388.   {$IFNDEF RVDONOTUSEJPEGIMAGE}
  2389.   RegisterClasses([TJpegImage]);
  2390.   {$ENDIF}
  2391.   {$ENDIF}
  2392.   HTMLGraphicFormats := nil;
  2393.   RVPngGraphiClass   := nil;
  2394. finalization
  2395.   HTMLGraphicFormats.Free;
  2396.   HTMLGraphicFormats := nil;
  2397. end.