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

RichEdit

开发平台:

Delphi

  1.   else
  2.     inherited AssignTo(Dest);
  3. end;
  4. {------------------------------------------------------------------------------}
  5. { Adds a new item. }
  6. function TParaInfos.Add: TParaInfo;
  7. begin
  8.   Result := TParaInfo(inherited Add);
  9. end;
  10. {------------------------------------------------------------------------------}
  11. { READ method for the property Items[].
  12.   Returns the Index-th item. If the index is out of range (0..Count-1), returns
  13.   InvalidItem instead. This method never generates exceptions. }
  14. function TParaInfos.GetItem(Index: Integer): TParaInfo;
  15. begin
  16.   if (Index<0) or (Index>=Count) then
  17.     Result := InvalidItem
  18.   else
  19.     Result := TParaInfo(inherited GetItem(Index));
  20. end;
  21. {------------------------------------------------------------------------------}
  22. { WRITE method for the property Items[]. }
  23. procedure TParaInfos.SetItem(Index: Integer; Value: TParaInfo);
  24. begin
  25.   inherited SetItem(Index, Value);
  26. end;
  27. {------------------------------------------------------------------------------}
  28. { READ method for the property InvalidItem.
  29.   It's returned when accessing Items[] with invalid index.
  30.   By default it has all properties of Items[0] and red border. }
  31. function TParaInfos.GetInvalidItem: TParaInfo;
  32. begin
  33.   if FInvalidItem=nil then begin
  34.     FInvalidItem := (FOwner as TRVStyle).GetParaStyleClass.Create(nil);
  35.     if Count>0 then
  36.       FInvalidItem.Assign(Items[0]);
  37.     FInvalidItem.SpaceBefore :=1;
  38.     FInvalidItem.SpaceAfter :=1;
  39.     FInvalidItem.LeftIndent :=1;
  40.     FInvalidItem.RightIndent :=1;
  41.     FInvalidItem.Border.Color := clRed;
  42.     FInvalidItem.Border.Style := rvbSingle;
  43.     FInvalidItem.Border.Width := 2;
  44.     FInvalidItem.Border.BorderOffsets.SetAll(1);
  45.   end;
  46.   Result := FInvalidItem;
  47. end;
  48. {------------------------------------------------------------------------------}
  49. { WRITE method for the property InvalidItem. }
  50. procedure TParaInfos.SetInvalidItem(const Value: TParaInfo);
  51. begin
  52.   if InvalidItem<>Value then
  53.     InvalidItem.Assign(Value);
  54. end;
  55. {------------------------------------------------------------------------------}
  56. {$IFNDEF RVDONOTUSEINI}
  57. { Loads itself from the ini-file, from the section Section.
  58.   fs is a format string for ini keys. }
  59. procedure TParaInfos.LoadFromINI(ini: TRVIniFile; const Section: String);
  60. var i, cnt: Integer;
  61. begin
  62.   cnt := ini.ReadInteger(Section, RVINI_PARASTYLECOUNT, 2);
  63.   Clear;
  64.   for i:=0 to cnt-1 do begin
  65.     Add;
  66.     Items[i].LoadFromINI(ini, Section, RVINI_PARASTYLEPREFIX+IntToStr(i));
  67.   end;
  68. end;
  69. {------------------------------------------------------------------------------}
  70. { Stores itself in the ini-file, in the section Section.
  71.   fs is a format string for ini keys. }
  72. procedure TParaInfos.SaveToINI(ini: TRVIniFile; const Section: String);
  73. var i: Integer;
  74. begin
  75.   ini.WriteInteger(Section,RVINI_PARASTYLECOUNT, Count);
  76.   for i:=0 to Count-1 do
  77.     Items[i].SaveToINI(ini, Section, RVINI_PARASTYLEPREFIX+IntToStr(i));
  78. end;
  79. {$ENDIF}
  80. {------------------------------------------------------------------------------}
  81. { Returns the index of the style having the specified Alignment.
  82.   Starts searching from Items[BaseStyle], then searches in other Items.
  83.   If not found, returns -1. }
  84. function TParaInfos.FindStyleWithAlignment(BaseStyle: Integer;
  85.   Alignment: TRVAlignment): Integer;
  86. var i: Integer;
  87. begin
  88.   if Items[BaseStyle].Alignment = Alignment then begin
  89.     Result := BaseStyle;
  90.     exit;
  91.   end;
  92.   for i := 0 to Count-1 do
  93.     if (i<>BaseStyle) and (Items[i].Alignment=Alignment) and
  94.        Items[BaseStyle].IsEqual(Items[i], [rvpiAlignment]) then begin
  95.       Result := i;
  96.       exit;
  97.     end;
  98.   Result := -1;
  99. end;
  100. {------------------------------------------------------------------------------}
  101. { The most universal method for paragraph style searching.
  102.   Returns the index of the style having all properties of Style listed in Mask.
  103.   Starts searching from Items[BaseStyle], then searches in other Items.
  104.   If not found, returns -1. }
  105. function TParaInfos.FindSuchStyle(BaseStyle: Integer; Style: TParaInfo;
  106.   Mask: TRVParaInfoProperties): Integer;
  107. var i: Integer;
  108. begin
  109.   Mask := RVAllParaInfoProperties - Mask;
  110.   if Style.IsEqual(Items[BaseStyle], Mask) then begin
  111.     Result := BaseStyle;
  112.     exit;
  113.   end;
  114.   for i := 0 to Count-1 do
  115.     if (i<>BaseStyle) and Style.IsEqual(Items[i], Mask) then begin
  116.       Result := i;
  117.       exit;
  118.     end;
  119.   Result := -1;
  120. end;
  121. {============================== TRVMarkerFont =================================}
  122. { Constructor. Sets values default for ListLevel.Font. }
  123. constructor TRVMarkerFont.Create;
  124. begin
  125.   inherited Create;
  126.   Name := RVDEFAULTSTYLEFONT;
  127.   Size := 8;
  128. end;
  129. {------------------------------------------------------------------------------}
  130. { Is this font equal to Font? }
  131. function TRVMarkerFont.IsEqual(Font: TFont): Boolean;
  132. begin
  133.   Result :=
  134.     (Height=Font.Height) and
  135.     (Style=Font.Style) and
  136.     (Color=Font.Color) and
  137.     {$IFDEF RICHVIEWCBDEF3}
  138.     (Charset=Font.Charset) and
  139.     {$ENDIF}
  140.     (AnsiCompareText(Name, Font.Name)=0);
  141. end;
  142. {------------------------------------------------------------------------------}
  143. { Do all properties of this font have default values? }
  144. function TRVMarkerFont.IsDefault: Boolean;
  145. begin
  146.   Result :=
  147.     (Size=8) and
  148.     (Color=clWindowText) and
  149.     {$IFDEF RICHVIEWCBDEF3}
  150.     (Charset=DEFAULT_CHARSET) and
  151.     {$ENDIF}
  152.     (Style=[]) and
  153.     (AnsiCompareText(Name,RVDEFAULTSTYLEFONT)=0);
  154. end;
  155. {------------------------------------------------------------------------------}
  156. { STORED method for Name property. }
  157. function TRVMarkerFont.StoreName: Boolean;
  158. begin
  159.   Result := Name<>RVDEFAULTSTYLEFONT;
  160. end;
  161. {------------------------------------------------------------------------------}
  162. { STORED method for Height property. }
  163. function TRVMarkerFont.StoreHeight: Boolean;
  164. begin
  165.   Result := Size<>8;
  166. end;
  167. {============================== TRVListLevel ==================================}
  168. { Constructor. Creates a dot bullet with FirstIndent=10. }
  169. constructor TRVListLevel.Create(Collection: TCollection);
  170. begin
  171.   inherited Create(Collection);
  172.   FFirstIndent := 10;
  173.   FStartFrom   := 1;
  174.   FFormatString  := #$B7;
  175.   FOptions     := [rvloContinuous, rvloLevelReset];
  176. end;
  177. {------------------------------------------------------------------------------}
  178. { Destructor. }
  179. destructor TRVListLevel.Destroy;
  180. begin
  181.   FPicture.Free;
  182.   FFont.Free;
  183.   inherited Destroy;
  184. end;
  185. {------------------------------------------------------------------------------}
  186. { Assigns Source to Self, if Source is TRVListLevel. }
  187. procedure TRVListLevel.Assign(Source: TPersistent);
  188. begin
  189.   if Source is TRVListLevel then begin
  190.     ListType        := TRVListLevel(Source).ListType;
  191.     StartFrom       := TRVListLevel(Source).StartFrom;
  192.     ImageList       := TRVListLevel(Source).ImageList;
  193.     ImageIndex      := TRVListLevel(Source).ImageIndex;
  194.     FormatString    := TRVListLevel(Source).FormatString;
  195.     {$IFNDEF RVDONOTUSEUNICODE}
  196.     {$IFDEF RICHVIEWCBDEF3}
  197.     FormatStringW   := TRVListLevel(Source).FormatStringW;
  198.     {$ENDIF}
  199.     {$ENDIF}
  200.     LeftIndent      := TRVListLevel(Source).LeftIndent;
  201.     FirstIndent     := TRVListLevel(Source).FirstIndent;
  202.     MarkerIndent    := TRVListLevel(Source).MarkerIndent;
  203.     MarkerAlignment := TRVListLevel(Source).MarkerAlignment;
  204.     Picture         := TRVListLevel(Source).FPicture;
  205.     Font            := TRVListLevel(Source).FFont;
  206.     Options         := TRVListLevel(Source).Options;
  207.     end
  208.   else
  209.     inherited Assign(Source);
  210. end;
  211. {------------------------------------------------------------------------------}
  212. {$IFNDEF RICHVIEWDEF3}
  213. { Are the Length bytes referenced by P1 and P2 the same? }
  214. function CompareMem(P1, P2: Pointer; Length: Integer): Boolean; assembler;
  215. asm
  216.         PUSH    ESI
  217.         PUSH    EDI
  218.         MOV     ESI,P1
  219.         MOV     EDI,P2
  220.         MOV     EDX,ECX
  221.         XOR     EAX,EAX
  222.         AND     EDX,3
  223.         SHR     ECX,1
  224.         SHR     ECX,1
  225.         REPE    CMPSD
  226.         JNE     @@2
  227.         MOV     ECX,EDX
  228.         REPE    CMPSB
  229.         JNE     @@2
  230.         INC     EAX
  231. @@2:    POP     EDI
  232.         POP     ESI
  233. end;
  234. {$ENDIF}
  235. {------------------------------------------------------------------------------}
  236. { Do Picture1 and Picture2 contain the same picture? }
  237. function ArePicturesEqual(FPicture1, FPicture2: TPicture): Boolean;
  238. var Stream1, Stream2: TMemoryStream;
  239. begin
  240.   Result := ((FPicture1=nil) or (FPicture1.Graphic=nil)) =
  241.             ((FPicture2=nil) or (FPicture2.Graphic=nil));
  242.   if not Result then
  243.     exit;
  244.   if (FPicture1=nil) or (FPicture2.Graphic=nil) then
  245.     exit;
  246.   Result := FPicture1.ClassType=FPicture2.ClassType;
  247.   if not Result then
  248.     exit;
  249.   Result := (FPicture1.Width=FPicture2.Width) and
  250.             (FPicture1.Height=FPicture2.Height);
  251.   if not Result then
  252.     exit;
  253.   Stream1 := TMemoryStream.Create;
  254.   Stream2 := TMemoryStream.Create;
  255.   try
  256.     FPicture1.Graphic.SaveToStream(Stream1);
  257.     FPicture2.Graphic.SaveToStream(Stream2);
  258.     Result := (Stream1.Size=Stream2.Size) and
  259.       CompareMem(Stream1.Memory,Stream2.Memory,Stream1.Size);
  260.   finally
  261.     Stream1.Free;
  262.     Stream2.Free;
  263.   end;
  264. end;
  265. {------------------------------------------------------------------------------}
  266. { Is this list level equal to Value? }
  267. function TRVListLevel.IsSimpleEqual(Value: TRVListLevel): Boolean;
  268. begin
  269.   Result :=
  270.     (ListType = Value.ListType) and
  271.     (StartFrom = Value.StartFrom) and
  272.     (ImageList = Value.ImageList) and
  273.     (ImageIndex = Value.ImageIndex) and
  274.     (FormatString = Value.FormatString) and
  275.     {$IFNDEF RVDONOTUSEUNICODE}
  276.     {$IFDEF RICHVIEWCBDEF3}
  277.     (FormatStringW = Value.FormatStringW) and
  278.     {$ENDIF}
  279.     {$ENDIF}
  280.     (LeftIndent = Value.LeftIndent) and
  281.     (FirstIndent = Value.FirstIndent) and
  282.     (MarkerIndent = Value.MarkerIndent) and
  283.     (MarkerAlignment = Value.MarkerAlignment) and
  284.     (
  285.       ((FFont=nil) or (FFont.IsDefault)) and ((Value.FFont=nil) or (Value.FFont.IsDefault)) or
  286.       ((FFont<>nil) and (Value.FFont<>nil) and FFont.IsEqual(Value.FFont))
  287.     ) and
  288.     (Options = Value.Options) and
  289.     ArePicturesEqual(FPicture, Value.FPicture);
  290. end;
  291. {------------------------------------------------------------------------------}
  292. { Returns a value of similarity between this list level and Value.
  293.   The greater value - the higher similarity. }
  294. function TRVListLevel.SimilarityValue(Value: TRVListLevel): Integer;
  295. begin
  296.   Result := 0;
  297.   if ListType=Value.ListType then
  298.     inc(Result, RVMW_LISTTYPE);
  299.   if StartFrom=Value.StartFrom then
  300.     inc(Result, RVMW_LISTMISC);
  301.   if ImageList=Value.ImageList then
  302.     inc(Result, RVMW_LISTMISC);
  303.   if ImageIndex=Value.ImageIndex then
  304.     inc(Result, RVMW_LISTMISC);
  305.   if FormatString=Value.FormatString then
  306.     inc(Result, RVMW_LISTMISC);
  307.   {$IFNDEF RVDONOTUSEUNICODE}
  308.   {$IFDEF RICHVIEWCBDEF3}
  309.   if FormatStringW=Value.FormatStringW then
  310.     inc(Result, RVMW_LISTMISC);
  311.   {$ENDIF}
  312.   {$ENDIF}
  313.   if LeftIndent=Value.LeftIndent then
  314.     inc(Result, RVMW_LISTMISC);
  315.   if FirstIndent=Value.FirstIndent then
  316.     inc(Result, RVMW_LISTMISC);
  317.   if FirstIndent=Value.FirstIndent then
  318.     inc(Result, RVMW_LISTMISC);
  319.   if MarkerIndent=Value.MarkerIndent then
  320.     inc(Result, RVMW_LISTMISC);
  321.   if MarkerAlignment=Value.MarkerAlignment then
  322.     inc(Result, RVMW_LISTMISC);
  323.   if Options=Value.Options then
  324.     inc(Result, RVMW_LISTMISC);
  325.   if ((FFont=nil) or (FFont.IsDefault)) and ((Value.FFont=nil) or (Value.FFont.IsDefault)) or
  326.       ((FFont<>nil) and (Value.FFont<>nil) and FFont.IsEqual(Value.FFont)) then
  327.     inc(Result, RVMW_LISTMISC);
  328.   if ArePicturesEqual(FPicture, Value.FPicture) then
  329.     inc(Result, RVMW_LISTMISC);
  330. end;
  331. {------------------------------------------------------------------------------}
  332. {$IFDEF RICHVIEWCBDEF3}
  333. { Designtime support. Returns a string which will be displayed for this item
  334.   in the collection editor.
  335.   It has a format
  336.     "<list type> <left indent>/<marker indent>/<first line indent>". }
  337. function TRVListLevel.GetDisplayName: String;
  338. begin
  339.   Result := Format(RVLISTLEVELDISPLAYNAME, [RVListTypeStr[ord(ListType)],
  340.     LeftIndent, MarkerIndent, FirstIndent]);
  341. end;
  342. {$ENDIF}
  343. {------------------------------------------------------------------------------}
  344. { READ method for Picture property. }
  345. function TRVListLevel.GetPicture: TPicture;
  346. begin
  347.   if FPicture=nil then
  348.     FPicture := TPicture.Create;
  349.   Result := FPicture;
  350. end;
  351. {------------------------------------------------------------------------------}
  352. { WRITE method for Picture property. }
  353. procedure TRVListLevel.SetPicture(const Value: TPicture);
  354. begin
  355.   if Value<>FPicture then begin
  356.     if (Value=nil) or (Value.Graphic=nil) then begin
  357.       FPicture.Free;
  358.       FPicture := nil;
  359.       end
  360.     else begin
  361.       GetPicture.Assign(Value);
  362.       {$IFDEF RICHVIEWDEF3}
  363.       FPicture.Graphic.Transparent := True;
  364.       {$ENDIF}
  365.     end;
  366.   end;
  367. end;
  368. {------------------------------------------------------------------------------}
  369. { STORED method for Picture property. }
  370. function TRVListLevel.StorePicture: Boolean;
  371. begin
  372.   Result := FPicture<>nil;
  373. end;
  374. {------------------------------------------------------------------------------}
  375. { Is value of Picture property nonempty? }
  376. function TRVListLevel.HasPicture: Boolean;
  377. begin
  378.   Result := (FPicture<>nil) and (FPicture.Graphic<>nil);
  379. end;
  380. {------------------------------------------------------------------------------}
  381. { Does this list level uses Font? (it depends on ListType). }
  382. function TRVListLevel.UsesFont: Boolean;
  383. begin
  384.   Result := ListType in [rvlstBullet,
  385.                  rvlstDecimal, rvlstLowerAlpha, rvlstUpperAlpha,
  386.                  rvlstLowerRoman, rvlstUpperRoman
  387.                  {$IFNDEF RVDONOTUSEUNICODE}, rvlstUnicodeBullet{$ENDIF} ];
  388. end;
  389. {------------------------------------------------------------------------------}
  390. { Does this list level uses numbering? (it depends on ListType). }
  391. function TRVListLevel.HasNumbering: Boolean;
  392. begin
  393.   Result := ListType in [rvlstDecimal, rvlstLowerAlpha, rvlstUpperAlpha,
  394.                  rvlstLowerRoman, rvlstUpperRoman, rvlstImageListCounter];
  395. end;
  396. {------------------------------------------------------------------------------}
  397. { Is width of marker of this list level variable? (it depends on ListType). }
  398. function TRVListLevel.HasVariableWidth: Boolean;
  399. begin
  400.   Result := ListType in [rvlstDecimal, rvlstLowerAlpha, rvlstUpperAlpha,
  401.                  rvlstLowerRoman, rvlstUpperRoman];
  402. end;
  403. {------------------------------------------------------------------------------}
  404. { (reserved) }
  405. function TRVListLevel.GetHTMLOpenTagForCSS: String;
  406. begin
  407.   if HasNumbering then
  408.     Result := 'ol'
  409.   else
  410.     Result := 'ul';
  411. end;
  412. {------------------------------------------------------------------------------}
  413. { Returns CSS to insert in <P> tag when SaveHTMLEx is called with
  414.   rvsoMarkersAsText option. }
  415. function TRVListLevel.GetIndentCSSForTextVersion: String;
  416. begin
  417.   if MarkerIndent-LeftIndent>=0 then
  418.     Result := Format('text-indent: %dpx; margin-left: %dpx;',
  419.       [MarkerIndent-LeftIndent, LeftIndent])
  420.   else
  421.     Result := Format('text-indent: %dpx; padding-left: %dpx; margin-left: %dpx;',
  422.       [MarkerIndent-LeftIndent, LeftIndent-MarkerIndent, MarkerIndent]);
  423. end;
  424. {------------------------------------------------------------------------------}
  425. { Writes opening HTML tag for this list level in Stream.
  426.   Used TRVMarkerItemInfo.HTMLOpenOrCloseTags. }
  427. procedure TRVListLevel.HTMLOpenTag(Stream: TStream; UseCSS: Boolean);
  428.   {..............................................}
  429.   function GetListType: String;
  430.   begin
  431.     case ListType of
  432.       rvlstLowerAlpha:
  433.         Result := 'a';
  434.       rvlstUpperAlpha:
  435.         Result := 'A';
  436.       rvlstLowerRoman:
  437.         Result := 'i';
  438.       rvlstUpperRoman:
  439.         Result := 'I';
  440.       else
  441.         Result := '';
  442.     end;
  443.     if Result<>'' then
  444.       Result := ' type='+Result;
  445.   end;
  446.   {..............................................}
  447. var CSS: String;
  448.     PrevIndent: Integer;
  449. begin
  450.   if UseCSS then begin
  451.     PrevIndent := 0;
  452.     if Index>0 then
  453.        PrevIndent := TRVListLevelCollection(Collection).Items[Index-1].LeftIndent;
  454.     if MarkerIndent>=LeftIndent then
  455.       CSS := Format('text-indent: %dpx; margin-left: %dpx; list-style-position: inside;',
  456.         [MarkerIndent-LeftIndent, LeftIndent-PrevIndent])
  457.     else
  458.       CSS := Format('text-indent: %dpx; margin-left: %dpx; list-style-position: outside;',
  459.         [FirstIndent, LeftIndent-PrevIndent]);
  460.     CSS := ' style="'+CSS+'"';
  461.     end
  462.   else
  463.     CSS := '';
  464.   if HasNumbering then
  465.     RVWrite(Stream,Format('<ol%s%s>',[GetListType,CSS]))
  466.   else
  467.     RVWrite(Stream,Format('<ul%s>',[CSS]));
  468. end;
  469. {------------------------------------------------------------------------------}
  470. { Writes closing HTML tag for this list level in Stream.
  471.   Used TRVMarkerItemInfo.HTMLOpenOrCloseTags. }
  472. procedure TRVListLevel.HTMLCloseTag(Stream: TStream; UseCSS: Boolean);
  473. begin
  474.   if HasNumbering then
  475.     RVWrite(Stream,'</ol>')
  476.   else
  477.     RVWrite(Stream,'</ul>');
  478. end;
  479. {------------------------------------------------------------------------------}
  480. { READ method for Font property. }
  481. function TRVListLevel.GetFont: TRVMarkerFont;
  482. begin
  483.   if FFont=nil then
  484.     FFont := TRVMarkerFont.Create;
  485.   Result := FFont;
  486. end;
  487. {------------------------------------------------------------------------------}
  488. { WRITE method for Font property. }
  489. procedure TRVListLevel.SetFont(const Value: TRVMarkerFont);
  490. begin
  491.   if Value<>FFont then begin
  492.     if (Value=nil) then begin
  493.       FFont.Free;
  494.       FFont := nil;
  495.       end
  496.     else
  497.       GetFont.Assign(Value);
  498.   end;
  499. end;
  500. {------------------------------------------------------------------------------}
  501. { STORED method for Font property. }
  502. function TRVListLevel.StoreFont: Boolean;
  503. begin
  504.   Result := FFont<>nil;
  505. end;
  506. {------------------------------------------------------------------------------}
  507. {$IFNDEF RVDONOTUSEINI}
  508. { Loads itself from the ini-file, from the section Section.
  509.   fs is a format string for ini keys.
  510.   ImageList is not loaded (to-do) }
  511. procedure TRVListLevel.SaveToINI(ini: TRVIniFile; const Section, fs: String);
  512. var Stream: TMemoryStream;
  513. begin
  514.   WriteIntToIniIfNE(ini, Section, Format(fs,[RVINI_LISTTYPE]), ord(ListType), ord(rvlstBullet));
  515.   // ImageList ?
  516.   WriteIntToIniIfNE(ini, Section, Format(fs,[RVINI_IMAGEINDEX]), ImageIndex, 0);
  517.   ini.WriteString(Section,  Format(fs,[RVINI_FORMATSTRING]), FormatString);
  518.   WriteIntToIniIfNE(ini, Section, Format(fs,[RVINI_LEFTINDENT]), LeftIndent, 0);
  519.   WriteIntToIniIfNE(ini, Section, Format(fs,[RVINI_FIRSTINDENT]), FirstIndent, 10);
  520.   WriteIntToIniIfNE(ini, Section, Format(fs,[RVINI_MARKERINDENT]), MarkerIndent, 0);
  521.   WriteIntToIniIfNE(ini, Section, Format(fs,[RVINI_MARKERALIGNMENT]), ord(FMarkerAlignment), ord(rvmaLeft));
  522.   if (FPicture<>nil) and (FPicture.Graphic<>nil) then begin
  523.     ini.WriteString(Section,  Format(fs,[RVINI_GRAPHICCLASS]), FPicture.Graphic.ClassName);
  524.     Stream :=  TMemoryStream.Create;
  525.     FPicture.Graphic.SaveToStream(Stream);
  526.     Stream.Position := 0;
  527.     WriteLongStringToINI(ini, Section,  Format(fs,[RVINI_PICTURE]), RVFStream2TextString(Stream));
  528.     Stream.Free;
  529.   end;
  530.   if FFont<>nil then
  531.     ini.WriteString(Section,  Format(fs,[RVINI_FONT]), FontToString(FFont));
  532.   WriteBoolToIniIfNE(ini, Section, Format(fs,[RVINI_LOCONTINUOUS]), rvloContinuous in Options, True);
  533.   WriteBoolToIniIfNE(ini, Section, Format(fs,[RVINI_LOLEVELRESET]), rvloLevelReset in Options, True);
  534.   {$IFNDEF RVDONOTUSEUNICODE}
  535.   {$IFDEF RICHVIEWCBDEF3}
  536.   if FFormatStringW<>'' then begin
  537.     Stream := TMemoryStream.Create;
  538.     Stream.WriteBuffer(Pointer(FFormatStringW)^, Length(FFormatStringW)*2);
  539.     Stream.Position := 0;
  540.     ini.WriteString(Section,  Format(fs,[RVINI_FORMATSTRINGW]), RVFStream2TextString(Stream));
  541.     Stream.Free;
  542.   end;
  543.   {$ENDIF}
  544.   {$ENDIF}
  545. end;
  546. {------------------------------------------------------------------------------}
  547. { Stores itself in the ini-file, in the section Section.
  548.   fs is a format string for ini keys.
  549.   ImageList is not stored (to-do). }
  550. procedure TRVListLevel.LoadFromINI(ini: TRVIniFile; const Section, fs: String);
  551. var s: String;
  552.   Stream: TMemoryStream;
  553.   GraphicClass: TGraphicClass;
  554.   Graphic: TGraphic;
  555. begin
  556.   ListType := TRVListType(ini.ReadInteger(Section, Format(fs,[RVINI_LISTTYPE]), ord(rvlstBullet)));
  557.   // ImageList ?
  558.   ImageIndex := ini.ReadInteger(Section, Format(fs,[RVINI_IMAGEINDEX]), 0);
  559.   FormatString := ini.ReadString(Section,  Format(fs,[RVINI_FORMATSTRING]), '');
  560.   LeftIndent := ini.ReadInteger(Section, Format(fs,[RVINI_LEFTINDENT]), 0);
  561.   FirstIndent := ini.ReadInteger(Section, Format(fs,[RVINI_FIRSTINDENT]), 10);
  562.   MarkerIndent := ini.ReadInteger(Section, Format(fs,[RVINI_MARKERINDENT]), 0);
  563.   FMarkerAlignment := TRVMarkerAlignment(ini.ReadInteger(Section, Format(fs,[RVINI_MARKERALIGNMENT]), ord(rvmaLeft)));
  564.   s := ini.ReadString(Section,  Format(fs,[RVINI_GRAPHICCLASS]), '');
  565.   GraphicClass := nil;
  566.   if s<>'' then
  567.     GraphicClass := TGraphicClass(GetClass(s));
  568.   if GraphicClass=nil then
  569.     Picture := nil
  570.   else begin
  571.     Graphic := RV_CreateGraphics(GraphicClass);
  572.     Picture.Graphic := Graphic;
  573.     Graphic.Free;
  574.     Stream :=  TMemoryStream.Create;
  575.     s := ReadLongStringFromINI(ini, Section,  Format(fs,[RVINI_PICTURE]));
  576.     RVFTextString2Stream(s, Stream);
  577.     Stream.Position := 0;
  578.     try
  579.       Picture.Graphic.LoadFromStream(Stream);
  580.     except
  581.       Picture := nil;
  582.     end;
  583.     Stream.Free;
  584.   end;
  585.   s := ini.ReadString(Section,  Format(fs,[RVINI_FONT]), '');
  586.   if s='' then
  587.     Font := nil
  588.   else
  589.     StringToFont(s, Font);
  590.   FOptions := [];
  591.   if IniReadBool(ini, Section, Format(fs,[RVINI_LOCONTINUOUS]), True) then
  592.     Include(FOptions,rvloContinuous);
  593.   if IniReadBool(ini, Section, Format(fs,[RVINI_LOLEVELRESET]), True) then
  594.     Include(FOptions,rvloLevelReset);
  595.   {$IFNDEF RVDONOTUSEUNICODE}
  596.   {$IFDEF RICHVIEWCBDEF3}
  597.   s := ini.ReadString(Section,  Format(fs,[RVINI_FORMATSTRINGW]), '');
  598.   Stream := TMemoryStream.Create;
  599.   RVFTextString2Stream(s, Stream);
  600.   SetLength(FFormatStringW, Stream.Size div 2);
  601.   Stream.Position := 0;
  602.   Stream.ReadBuffer(Pointer(FFormatStringW)^, Stream.Size);
  603.   Stream.Free;
  604.   {$ENDIF}
  605.   {$ENDIF}
  606. end;
  607. {$ENDIF}
  608. {------------------------------------------------------------------------------}
  609. { Writes ImageList.Tag as ILTag pseudo-property. }
  610. procedure TRVListLevel.ImageListTagWriter(Writer: TWriter);
  611. begin
  612.   Writer.WriteInteger(FImageList.Tag);
  613. end;
  614. { Returns RVData used to store this list level.
  615.   There are two possibilities
  616.   - storing in DFM: no RVData (nil)
  617.   - storing in RVF: returns RVData assigned to RVStyle.ListStyles.FRVData. }
  618. {------------------------------------------------------------------------------}
  619. function TRVListLevel.GetRVFRVData: TPersistent;
  620. begin
  621.   if (Collection<>nil) and (TRVListLevelCollection(Collection).FOwner<>nil) and
  622.      (TRVListInfo(TRVListLevelCollection(Collection).FOwner).Collection<>nil) then
  623.     Result := TRVListInfos(TRVListInfo(TRVListLevelCollection(Collection).FOwner).Collection).FRVData
  624.   else
  625.     Result := nil;
  626. end;
  627. {------------------------------------------------------------------------------}
  628. { Reads ILTag pseudo-property. When loading from RVF file, it contains a Tag
  629.   property of ImageList. It's used to call RVData.RVFImageListNeeded, which
  630.   calls RichView.OnRVFImageListNeeded event.
  631.   There must be no this property when loading from DFM. }
  632. procedure TRVListLevel.ImageListTagReader(Reader: TReader);
  633. var RVData: TCustomRVData;
  634.     Tag: Integer;
  635. begin
  636.   RVData := TCustomRVData(GetRVFRVData);
  637.   Tag := Reader.ReadInteger;
  638.   if RVData<>nil then
  639.     FImageList := RVData.RVFImageListNeeded(Tag)
  640.   else
  641.     FImageList := nil;
  642. end;
  643. {------------------------------------------------------------------------------}
  644. { STORED method for ILTag pseudo-property. It should be stored only if RVData is
  645.   assigned, i.e. when saving to RVF file. }
  646. function TRVListLevel.StoreImageList: Boolean;
  647. begin
  648.   Result := GetRVFRVData=nil;
  649. end;
  650. {------------------------------------------------------------------------------}
  651. {$IFNDEF RVDONOTUSEUNICODE}
  652. {$IFDEF RICHVIEWCBDEF3}
  653. { READ method for FormatStringWCode pseudo-property. This pseudo-property is
  654.   used for storing FormatStringW property.
  655.   This trick is used because new and old version of Delphi save strings
  656.   differently. If we will use standard Delphi streaming method for these
  657.   properties, programs compiled with older version of Delphi will not be able to
  658.   open RVF files saved with newer versions of Delphi. }
  659. procedure TRVListLevel.FormatStringWCodeReader(Reader: TReader);
  660. begin
  661.   FFormatStringW := RVDecodeWideString(Reader.ReadString);
  662. end;
  663. {------------------------------------------------------------------------------}
  664. { WRITE method for FormatStringWCode pseudo-property }
  665. procedure TRVListLevel.FormatStringWCodeWriter(Writer: TWriter);
  666. begin
  667.   Writer.WriteString(RVEncodeWideString(FFormatStringW));
  668. end;
  669. {$ENDIF}
  670. {$ENDIF}
  671. {------------------------------------------------------------------------------}
  672. { READ method for FormatStringCode pseudo-property. This pseudo-property is
  673.   used for storing FormatString property. }
  674. procedure TRVListLevel.FormatStringCodeReader(Reader: TReader);
  675. begin
  676.   FFormatString := RVDecodeString(Reader.ReadString);
  677. end;
  678. {------------------------------------------------------------------------------}
  679. { WRITE method for FormatStringCode pseudo-property. This pseudo-property is
  680.   used for storing FormatString property. }
  681. procedure TRVListLevel.FormatStringCodeWriter(Writer: TWriter);
  682. begin
  683.   Writer.WriteString(RVEncodeString(FFormatString));
  684. end;
  685. {------------------------------------------------------------------------------}
  686. { Defines additional properties (pseudo-properties): ILTag, FormatStringWCode,
  687.   FormatStringCode. }
  688. procedure TRVListLevel.DefineProperties(Filer: TFiler);
  689. begin
  690.   inherited;
  691.   if GetRVFRVData<>nil then
  692.     Filer.DefineProperty('ILTag', ImageListTagReader, ImageListTagWriter, FImageList<>nil);
  693.   {$IFNDEF RVDONOTUSEUNICODE}
  694.   {$IFDEF RICHVIEWCBDEF3}
  695.   Filer.DefineProperty('FormatStringWCode', FormatStringWCodeReader, FormatStringWCodeWriter, FFormatStringW<>'');
  696.   {$ENDIF}
  697.   {$ENDIF}
  698.   Filer.DefineProperty('FormatStringCode', FormatStringCodeReader, FormatStringCodeWriter, FFormatString<>#$B7);
  699. end;
  700. {========================= TRVListLevelCollection =============================}
  701. { Constructor. Creates empty collection of list levels. }
  702. constructor TRVListLevelCollection.Create(Owner: TPersistent);
  703. begin
  704.   inherited Create(TRVListLevel);
  705.   FOwner := Owner;
  706. end;
  707. {------------------------------------------------------------------------------}
  708. {$IFDEF RICHVIEWCBDEF3}
  709. { Designtime support, for the IDE collection editor. }
  710. function TRVListLevelCollection.GetOwner: TPersistent;
  711. begin
  712.   Result := FOwner;
  713. end;
  714. {$ENDIF}
  715. {------------------------------------------------------------------------------}
  716. { READ method for Items[] property. }
  717. function TRVListLevelCollection.GetItem(Index: Integer): TRVListLevel;
  718. begin
  719.   Result := TRVListLevel(inherited GetItem(Index));
  720. end;
  721. {------------------------------------------------------------------------------}
  722. { WRITE method for Items[] property. }
  723. procedure TRVListLevelCollection.SetItem(Index: Integer;
  724.   const Value: TRVListLevel);
  725. begin
  726.   inherited SetItem(Index, Value);
  727. end;
  728. {------------------------------------------------------------------------------}
  729. {$IFDEF RICHVIEWDEF4}
  730. { Inserts a new list level in the collection. This method is added for typecasting. }
  731. function TRVListLevelCollection.Insert(Index: Integer): TRVListLevel;
  732. begin
  733.   Result := TRVListLevel(inherited Insert(Index));
  734. end;
  735. {$ENDIF}
  736. {------------------------------------------------------------------------------}
  737. { Is this collection of list levels equal to Value? }
  738. function TRVListLevelCollection.IsSimpleEqual(Value: TRVListLevelCollection): Boolean;
  739. var i: Integer;
  740. begin
  741.   Result := False;
  742.   if Count<>Value.Count then
  743.     exit;
  744.   for i := 0 to Count-1 do
  745.     if not Items[i].IsSimpleEqual(Value[i]) then
  746.       exit;
  747.   Result := True;
  748. end;
  749. {------------------------------------------------------------------------------}
  750. { Adds new list level to the end of the collection. This method is added for
  751.   typecasting. }
  752. function TRVListLevelCollection.Add: TRVListLevel;
  753. begin
  754.   Result := TRVListLevel(inherited Add);
  755. end;
  756. {=========================== TRVListInfo ======================================}
  757. { Constructor. Creates a list style with 0 levels. }
  758. constructor TRVListInfo.Create(Collection: TCollection);
  759. begin
  760.   inherited Create(Collection);
  761.   FLevels := TRVListLevelCollection.Create(Self);
  762.   StyleName := RVDEFAULTLISTSTYLENAME;
  763. end;
  764. {------------------------------------------------------------------------------}
  765. { Destructor. }
  766. destructor TRVListInfo.Destroy;
  767. begin
  768.   FLevels.Free;
  769.   inherited Destroy;
  770. end;
  771. {------------------------------------------------------------------------------}
  772. { Assigns Source to Self, if Source is TRVListInfo. }
  773. procedure TRVListInfo.Assign(Source: TPersistent);
  774. begin
  775.   if Source is TRVListInfo then begin
  776.     Levels := TRVListInfo(Source).Levels;
  777.     OneLevelPreview := TRVListInfo(Source).OneLevelPreview;
  778.   end;
  779.   inherited Assign(Source);
  780. end;
  781. {------------------------------------------------------------------------------}
  782. { Is this list style equal to Value?
  783.   Mapping is not used. }
  784. function TRVListInfo.IsSimpleEqualEx(Value: TCustomRVInfo;
  785.   Mapping: TRVIntegerList): Boolean;
  786. begin
  787.   Result := IsSimpleEqual(Value, True, False);
  788.   {
  789.   if not Result then
  790.     exit;
  791.   Result := False;
  792.   if (Value.BaseStyleNo>=0) then begin
  793.     if (Value.BaseStyleNo>=Mapping.Count) then
  794.       Value.BaseStyleNo := -1 // fix up
  795.     else if (Mapping[Value.BaseStyleNo]<>BaseStyleNo) then
  796.       exit;
  797.   end;
  798.   Result := True;
  799.   }
  800. end;
  801. {------------------------------------------------------------------------------}
  802. { Is this list style equal to Value?
  803.   If IgnoreID, ListID properties are ignored. }
  804. function TRVListInfo.IsSimpleEqual(Value: TCustomRVInfo;
  805.   IgnoreReferences, IgnoreID: Boolean): Boolean;
  806. begin
  807.   Result := (OneLevelPreview=TRVListInfo(Value).OneLevelPreview) and
  808.     (Levels.Count = TRVListInfo(Value).Levels.Count) and
  809.     (IgnoreID or (ListID = TRVListInfo(Value).ListID));
  810.   if not Result then
  811.     exit;
  812.   Result := Levels.IsSimpleEqual(TRVListInfo(Value).Levels);
  813.   if Result and RichViewCompareStyleNames then
  814.     Result := StyleName=Value.StyleName;  
  815. end;
  816. {------------------------------------------------------------------------------}
  817. { Returns the value of similarity between this paragraph list and Value.
  818.   The larger return value - the larger similarity. }
  819. function TRVListInfo.SimilarityValue(Value: TCustomRVInfo): Integer;
  820. var i,min,max: Integer;
  821. begin
  822.   Result := 0;
  823.   if OneLevelPreview=TRVListInfo(Value).OneLevelPreview then
  824.     inc(Result, RVMW_LISTMISC);
  825.   if ListID=TRVListInfo(Value).ListID then
  826.     inc(Result, RVMW_LISTMISC div 2);
  827.   min := Levels.Count;
  828.   max := min;
  829.   if TRVListInfo(Value).Levels.Count<min then
  830.     min := TRVListInfo(Value).Levels.Count;
  831.   if TRVListInfo(Value).Levels.Count>max then
  832.     max := TRVListInfo(Value).Levels.Count;
  833.   for i := 0 to min-1 do
  834.     inc(Result, Levels[i].SimilarityValue(TRVListInfo(Value).Levels[i]));
  835.   dec(Result, RVMW_LISTMISC*(max-min));
  836. end;
  837. {------------------------------------------------------------------------------}
  838. { READ method for LstID pseudo-property.
  839.   This pseudo-property is used to store ListID property (which cannot be stored
  840.   by itself, because it's readonly. }
  841. procedure TRVListInfo.ReadListID(Reader: TReader);
  842. begin
  843.   FListID := Reader.ReadInteger;
  844. end;
  845. {------------------------------------------------------------------------------}
  846. { WRITE method for LstID pseudo-property. }
  847. procedure TRVListInfo.WriteListID(Writer: TWriter);
  848. begin
  849.   Writer.WriteInteger(ListID);
  850. end;
  851. {------------------------------------------------------------------------------}
  852. { Defines additional property: LstID.
  853.   See also comments to RVNoLstIDProperty. }
  854. procedure TRVListInfo.DefineProperties(Filer: TFiler);
  855. begin
  856.   inherited;
  857.   if not RVNoLstIDProperty then
  858.     Filer.DefineProperty('LstID', ReadListID, WriteListID, True);
  859. end;
  860. {------------------------------------------------------------------------------}
  861. { WRITE method for Levels[] property. }
  862. procedure TRVListInfo.SetLevels(const Value: TRVListLevelCollection);
  863. begin
  864.   if FLevels<>Value then
  865.     FLevels.Assign(Value);
  866. end;
  867. {------------------------------------------------------------------------------}
  868. { READ method for ListID property. }
  869. function TRVListInfo.GetListID: Integer;
  870. begin
  871.   while FListID=0 do
  872.     FListID := Random(MaxInt);
  873.   Result := FListID;
  874. end;
  875. {------------------------------------------------------------------------------}
  876. {$IFNDEF RVDONOTUSEINI}
  877. { Stores itself to the ini-file, to the section Section.
  878.   fs is a format string for ini keys. }
  879. procedure TRVListInfo.SaveToINI(ini: TRVIniFile; const Section, fs: String);
  880. var i: Integer;
  881. begin
  882.   inherited SaveToINI(ini, Section, fs);
  883.   WriteIntToIniIfNE(ini, Section, Format(fs,[RVINI_LEVELSCOUNT]),Levels.Count,0);
  884.   WriteBoolToIniIfNE(ini,Section, RVINI_ONELEVELPREVIEW, OneLevelPreview, False);
  885.   for i := 0 to Levels.Count-1 do
  886.     Levels[i].SaveToINI(ini, Section, Format(fs,[''])+RVINI_LEVELPREFIX+IntToStr(i));
  887. end;
  888. {------------------------------------------------------------------------------}
  889. { Loads itself from the ini-file, from the section Section.
  890.   fs is a format string for ini keys. }
  891. procedure TRVListInfo.LoadFromINI(ini: TRVIniFile; const Section, fs: String);
  892. var cnt,i: Integer;
  893. begin
  894.   inherited LoadFromINI(ini, Section, fs, RVDEFAULTLISTSTYLENAME);
  895.   OneLevelPreview := IniReadBool(ini, Section, RVINI_ONELEVELPREVIEW, False);
  896.   cnt := ini.ReadInteger(Section, Format(fs,[RVINI_LEVELSCOUNT]), 0);
  897.   for i := 0 to cnt-1 do
  898.     Levels.Add.LoadFromINI(ini, Section, Format(fs,[''])+RVINI_LEVELPREFIX+IntToStr(i));
  899. end;
  900. {$ENDIF}
  901. {------------------------------------------------------------------------------}
  902. { Is at least one of list levels a numbered list? }
  903. function TRVListInfo.HasNumbering: Boolean;
  904. var i: Integer;
  905. begin
  906.   Result := False;
  907.   for i := 0 to Levels.Count-1 do
  908.     if Levels[i].HasNumbering then begin
  909.       Result := True;
  910.       exit;
  911.     end;
  912. end;
  913. {------------------------------------------------------------------------------}
  914. { Are all list levels numbered lists? }
  915. function TRVListInfo.AllNumbered: Boolean;
  916. var i: Integer;
  917. begin
  918.   Result := True;
  919.   for i := 0 to Levels.Count-1 do
  920.     if not Levels[i].HasNumbering then begin
  921.       Result := False;
  922.       exit;
  923.     end;
  924. end;
  925. {------------------------------------------------------------------------------}
  926. { Does at least one of list levels have markers of variable width? }
  927. function TRVListInfo.HasVariableWidth: Boolean;
  928. var i: Integer;
  929. begin
  930.   Result := False;
  931.   for i := 0 to Levels.Count-1 do
  932.     if Levels[i].HasVariableWidth then begin
  933.       Result := True;
  934.       exit;
  935.     end;
  936. end;
  937. {============================== TRVListInfos ==================================}
  938. { READ method for Items[] property.
  939.   TODO: to implement InvalidItem, like for other styles. }
  940. function TRVListInfos.GetItem(Index: Integer): TRVListInfo;
  941. begin
  942.   Result := TRVListInfo(inherited GetItem(Index));
  943. end;
  944. {------------------------------------------------------------------------------}
  945. { WRITE method for Items[] property. }
  946. procedure TRVListInfos.SetItem(Index: Integer; const Value: TRVListInfo);
  947. begin
  948.   inherited SetItem(Index, Value);
  949. end;
  950. {------------------------------------------------------------------------------}
  951. {$IFDEF RICHVIEWDEF4}
  952. { Inserts a new list style in the collection. This method is added for typecasting. }
  953. function TRVListInfos.Insert(Index: Integer): TRVListInfo;
  954. begin
  955.   Result := TRVListInfo(inherited Insert(Index));
  956. end;
  957. {$ENDIF}
  958. {------------------------------------------------------------------------------}
  959. { Adds a new list style to the collection. This method is added for typecasting. }
  960. function TRVListInfos.Add: TRVListInfo;
  961. begin
  962.   Result := TRVListInfo(inherited Add);
  963. end;
  964. {------------------------------------------------------------------------------}
  965. { Removes all references from list levels to ImageList.
  966.   Called from TRVStyle.Notification, when removing ImageList. }
  967. procedure TRVListInfos.RemoveImageList(ImageList: TCustomImageList);
  968. var i, j: Integer;
  969. begin
  970.   for i := 0 to Count-1 do
  971.     for j := 0 to Items[i].Levels.Count-1 do
  972.       if Items[i].Levels[j].FImageList=ImageList then
  973.         Items[i].Levels[j].FImageList := nil;
  974. end;
  975. {------------------------------------------------------------------------------}
  976. {$IFNDEF RVDONOTUSEINI}
  977. { Loads itself from the ini-file, from the section Section. }
  978. procedure TRVListInfos.LoadFromINI(ini: TRVIniFile; const Section: String);
  979. var i, cnt: Integer;
  980. begin
  981.   cnt := ini.ReadInteger(Section, RVINI_LISTSTYLECOUNT, 0);
  982.   Clear;
  983.   for i:=0 to cnt-1 do
  984.     Add.LoadFromINI(ini, Section, RVINI_LISTSTYLEPREFIX+IntToStr(i));
  985. end;
  986. {------------------------------------------------------------------------------}
  987. { Stores itself to the ini-file, to the section Section. }
  988. procedure TRVListInfos.SaveToINI(ini: TRVIniFile; const Section: String);
  989. var i: Integer;
  990. begin
  991.   ini.WriteInteger(Section,RVINI_LISTSTYLECOUNT, Count);
  992.   for i:=0 to Count-1 do
  993.     Items[i].SaveToINI(ini, Section, RVINI_LISTSTYLEPREFIX+IntToStr(i));
  994. end;
  995. {$ENDIF}
  996. {------------------------------------------------------------------------------}
  997. { Searches for the list style equal to Style.
  998.   If AddIfNotFound, adds such style (with Standard property = False) to the end
  999.   of collection.
  1000.   ListID properties of list styles are ignored when comparing. 
  1001.   Returns index of the found style (or -1 if not found and not added). } 
  1002. function TRVListInfos.FindSuchStyle(Style: TRVListInfo; AddIfNotFound: Boolean): Integer;
  1003. var i: Integer;
  1004. begin
  1005.   for i:=0 to Count-1 do
  1006.     if Items[i].IsSimpleEqual(Style, False, True) then begin
  1007.       Result := i;
  1008.       exit;
  1009.     end;
  1010.   if AddIfNotFound then begin
  1011.     Add.Assign(Style);
  1012.     Result := Count-1;
  1013.     if RichViewResetStandardFlag then
  1014.       Items[Result].Standard := False;
  1015.     end
  1016.   else
  1017.     Result := -1;
  1018. end;
  1019. {------------------------------------------------------------------------------}
  1020. { Searches for the list style having levels equal to Levels.
  1021.   If AddIfNotFound, adds such style (with properties Standard=False;
  1022.   OneLevelPreview=True; StyleNo=StyleNameForAdding) to the end
  1023.   of collection.
  1024.   Returns index of the found style (or -1 if not found and not added). }
  1025. function TRVListInfos.FindStyleWithLevels(Levels: TRVListLevelCollection;
  1026.   const StyleNameForAdding: String; AddIfNotFound: Boolean): Integer;
  1027. var i: Integer;
  1028. begin
  1029.   for i:=0 to Count-1 do
  1030.     if Items[i].Levels.IsSimpleEqual(Levels) then begin
  1031.       Result := i;
  1032.       exit;
  1033.     end;
  1034.   if AddIfNotFound then begin
  1035.     Add;
  1036.     Result := Count-1;
  1037.     if RichViewResetStandardFlag then
  1038.       Items[Result].Standard := False;
  1039.     Items[Result].StyleName := StyleNameForAdding;
  1040.     Items[Result].OneLevelPreview := True;
  1041.     Items[Result].Levels := Levels;
  1042.     end
  1043.   else
  1044.     Result := -1;
  1045. end;
  1046. {$IFNDEF RVDONOTUSESTYLETEMPLATES}
  1047. {=============== TRVSTFontInfo, TRVSTParaInfo, TRVSTListInfo ==================}
  1048. { Hiding properties }
  1049. procedure TRVSTFontInfo.SetNoProp(const Value: Integer);
  1050. begin
  1051.   raise ERichViewError.Create(errRVInvProp);
  1052. end;
  1053. {------------------------------------------------------------------------------}
  1054. procedure TRVSTParaInfo.SetNoProp(const Value: Integer);
  1055. begin
  1056.   raise ERichViewError.Create(errRVInvProp);
  1057. end;
  1058. {------------------------------------------------------------------------------}
  1059. procedure TRVSTListInfo.SetNoProp(const Value: Integer);
  1060. begin
  1061.   raise ERichViewError.Create(errRVInvProp);
  1062. end;
  1063. {------------------------------------------------------------------------------}
  1064. {$IFDEF RICHVIEWCBDEF3}
  1065. { Allowing designtime editing of subcollections }
  1066. function TRVSTFontInfo.GetOwner: TPersistent;
  1067. begin
  1068.   Result := FOwner;
  1069. end;
  1070. {------------------------------------------------------------------------------}
  1071. function TRVSTParaInfo.GetOwner: TPersistent;
  1072. begin
  1073.   Result := FOwner;
  1074. end;
  1075. {------------------------------------------------------------------------------}
  1076. function TRVSTListInfo.GetOwner: TPersistent;
  1077. begin
  1078.   Result := FOwner;
  1079. end;
  1080. {$ENDIF}
  1081. {============================= TRVStyleTemplate ===============================}
  1082. { Constructor }
  1083. constructor TRVStyleTemplate.Create(Collection: TCollection);
  1084. begin
  1085.   inherited Create(Collection);
  1086.   FTextStyle := TRVSTFontInfo.Create(nil);
  1087.   FParaStyle := TRVSTParaInfo.Create(nil);
  1088.   FListStyle := TRVSTListInfo.Create(nil);
  1089.   {$IFDEF RICHVIEWCBDEF3}
  1090.   FParaStyle.FOwner := Self;
  1091.   FTextStyle.FOwner := Self;
  1092.   FListStyle.FOwner := Self;
  1093.   {$ENDIF}
  1094.   FParentId  := -1;
  1095.   if (Collection<>nil) and
  1096.      not ((TRVStyleTemplateCollection(Collection).FOwner<>nil) and
  1097.           (csLoading in TRVStyle(TRVStyleTemplateCollection(Collection).FOwner).ComponentState)) then
  1098.     TRVStyleTemplateCollection(Collection).AssignUniqueNameTo(Self);
  1099. end;
  1100. {------------------------------------------------------------------------------}
  1101. { Destructor }
  1102. destructor TRVStyleTemplate.Destroy;
  1103. var i: Integer;
  1104. begin
  1105.   if FParent<>nil then
  1106.     FParent.RemoveChild(Self);
  1107.   if FChildren<>nil then
  1108.     for i := 0 to FChildren.Count-1 do
  1109.       TRVStyleTemplate(FChildren.Items[i]).ParentId := -1;
  1110.   if (Collection<>nil) and
  1111.      (TRVStyleTemplateCollection(Collection).FNormalStyleTemplate=Self) then
  1112.     TRVStyleTemplateCollection(Collection).FNormalStyleTemplate := nil;
  1113.   FChildren.Free;
  1114.   FTextStyle.Free;
  1115.   FParaStyle.Free;
  1116.   FListStyle.Free;
  1117.   inherited;
  1118. end;
  1119. {------------------------------------------------------------------------------}
  1120. { Assigns Source to Self, if Source is TRVStyleTemplate }
  1121. procedure TRVStyleTemplate.Assign(Source: TPersistent);
  1122. begin
  1123.   if Source is TRVStyleTemplate then begin
  1124.     TextStyle := TRVStyleTemplate(Source).TextStyle;
  1125.     ParaStyle := TRVStyleTemplate(Source).ParaStyle;
  1126.     // ListStyle := TRVStyleTemplate(Source).ListStyle;
  1127.     if (Collection<>nil) and (Collection=TRVStyleTemplate(Source).Collection) then
  1128.       FParentId := TRVStyleTemplate(Source).ParentId;
  1129.     Name      := TRVStyleTemplate(Source).Name;
  1130.     ValidTextProperties  := TRVStyleTemplate(Source).ValidTextProperties;
  1131.     ValidParaProperties1 := TRVStyleTemplate(Source).ValidParaProperties1;
  1132.     ValidParaProperties2 := TRVStyleTemplate(Source).ValidParaProperties2;
  1133.     end
  1134.   else
  1135.     inherited Assign(Source);
  1136. end;
  1137. {------------------------------------------------------------------------------}
  1138. { Allows applying style template to text and paragraph styles using their
  1139.   Assign method. }
  1140. procedure TRVStyleTemplate.AssignTo(Dest: TPersistent);
  1141. begin
  1142.   inherited;
  1143.   if Dest is TCustomRVFontInfo then
  1144.     ApplyToTextStyle(TCustomRVFontInfo(Dest), nil, True)
  1145.   else if Dest is TCustomRVParaInfo then
  1146.     ApplyToParaStyle(TCustomRVParaInfo(Dest), True);
  1147. end;
  1148. {------------------------------------------------------------------------------}
  1149. { Assigns valid properties of this style template (and its parents) to ATextStyle.
  1150.   Only propeties listed in AllowedProps can be changed.
  1151.   Return value: list of assigned properties. }
  1152. function TRVStyleTemplate.AssignToTextStyle(ATextStyle: TCustomRVFontInfo;
  1153.   AllowedProps: TRVFontInfoProperties): TRVFontInfoProperties;
  1154. var Props: TRVFontInfoProperties;
  1155.     Template: TRVStyleTemplate;
  1156. begin
  1157.   Props := ValidTextProperties;
  1158.   Result := [];
  1159.   Template := Self;
  1160.   while True do begin
  1161.     Props := Props * AllowedProps;
  1162.     if Props<>[] then begin
  1163.       ATextStyle.AssignSelectedProperties(Template.TextStyle, Props);
  1164.       Result := Result+Props;
  1165.     end;
  1166.     Template := Template.FParent;
  1167.     if Template=nil then
  1168.       break;
  1169.     Props := Template.ValidTextProperties-Result;
  1170.   end;
  1171. end;
  1172. {------------------------------------------------------------------------------}
  1173. { Applies this style template (and its parents) to ATextStyle.
  1174.   1) Assigns properties listed in ValidTextProperies of this style template
  1175.     (and its parents).
  1176.     if ATextStyle is TFontInfo, then properties listed in
  1177.     ATextStyle.ModifiedProperties are assigned only if
  1178.     OverrideModifiedProperties = True.    
  1179.   2) If AParaStyle<>nil and has StyleTemplate, does the
  1180.     same with the paragraph's style template (but without overriding properties
  1181.     assigned on the step 1.)
  1182.   3) If ATextStyle is TFontInfo then
  1183.     4) If OverrideModifiedProperties = True, excludes the applied properties from
  1184.        ATextStyle.ModifiedProperties.
  1185.     5) Reverts other (not applied and not listed in ModifiedProperties)
  1186.       properties to their default values.
  1187.   Default values are taken from the style template having name 'Normal'.
  1188.   If this style template does not exist, RVStyle.TextStyles[0] is used instead.
  1189. }
  1190. procedure TRVStyleTemplate.ApplyToTextStyle(ATextStyle: TCustomRVFontInfo;
  1191.   AParaStyle: TCustomRVParaInfo; OverrideModifiedProperties: Boolean);
  1192. var AppliedProps, AppliedProps2, DefProps: TRVFontInfoProperties;
  1193.     Template: TRVStyleTemplate;
  1194.     Index: Integer;
  1195. begin
  1196.   AppliedProps := RVAllFontInfoProperties;
  1197.   if not OverrideModifiedProperties and (ATextStyle is TFontInfo) then
  1198.     AppliedProps := AppliedProps-TFontInfo(ATextStyle).ModifiedProperties;
  1199.   AppliedProps := AssignToTextStyle(ATextStyle, AppliedProps);
  1200.   if (AParaStyle<>nil) and (AParaStyle.StyleTemplateId>0) and (Collection<>nil) then begin
  1201.     Index := TRVStyleTemplateCollection(Collection).FindById(AParaStyle.StyleTemplateId);
  1202.     if Index>=0 then begin
  1203.       Template := TRVStyleTemplateCollection(Collection).Items[Index];
  1204.       AppliedProps2 := RVAllFontInfoProperties-AppliedProps;
  1205.       if (ATextStyle is TFontInfo) and (TFontInfo(ATextStyle).StyleTemplateId<>Template.Id) then
  1206.         AppliedProps2 := AppliedProps2-TFontInfo(ATextStyle).ModifiedProperties;
  1207.       AppliedProps := AppliedProps+Template.AssignToTextStyle(ATextStyle, AppliedProps2);
  1208.     end;
  1209.   end;
  1210.   if ATextStyle is TFontInfo then begin
  1211.     if OverrideModifiedProperties then begin
  1212.       TFontInfo(ATextStyle).ModifiedProperties := TFontInfo(ATextStyle).ModifiedProperties-AppliedProps;
  1213.       TFontInfo(ATextStyle).StyleTemplateId := Id;
  1214.     end;
  1215.     DefProps := RVAllFontInfoProperties - AppliedProps - TFontInfo(ATextStyle).ModifiedProperties;
  1216.     if DefProps=[] then
  1217.       exit;
  1218.     if Collection<>nil then
  1219.       Template := TRVStyleTemplateCollection(Collection).FNormalStyleTemplate
  1220.     else
  1221.       Template := nil;
  1222.     if Template<>nil then
  1223.       Template.AssignToTextStyle(ATextStyle, DefProps)
  1224.     else if (Collection<>nil) and
  1225.             (TRVStyleTemplateCollection(Collection).FOwner<>nil) then
  1226.       ATextStyle.AssignSelectedProperties(
  1227.        (TRVStyleTemplateCollection(Collection).FOwner as TRVStyle).TextStyles[0],
  1228.        DefProps);
  1229.   end;
  1230. end;
  1231. {------------------------------------------------------------------------------}
  1232. { Assigns valid properties of this style template (and its parents) to AParaStyle.
  1233.   Only propeties listed in AllowedProps can be changed.
  1234.   Return value: list of assigned properties. }
  1235. function TRVStyleTemplate.AssignToParaStyle(AParaStyle: TCustomRVParaInfo;
  1236.   AllowedProps: TRVParaInfoProperties): TRVParaInfoProperties;
  1237. var Props: TRVParaInfoProperties;
  1238.     Template: TRVStyleTemplate;
  1239. begin
  1240.   Props := ValidParaProperties1+ValidParaProperties2;
  1241.   Result := [];
  1242.   Template := Self;
  1243.   while True do begin
  1244.     Props := Props * AllowedProps;
  1245.     if (Props<>[]) then begin
  1246.       AParaStyle.AssignSelectedProperties(Template.ParaStyle, Props);
  1247.       Result := Result+Props;
  1248.     end;
  1249.     Template := Template.FParent;
  1250.     if Template=nil then
  1251.       break;
  1252.     Props := Template.ValidParaProperties1+Template.ValidParaProperties2-Result;
  1253.   end;
  1254. end;
  1255. {------------------------------------------------------------------------------}
  1256. { Applies this style template (and its parents) to AParaStyle.
  1257.   1) Assigns properties listed in ValidParaProperies (1 and 2) of this style template
  1258.     (and its parents). if AParaStyle is TParaInfo, then properties listed in
  1259.     AParaStyle.ModifiedProperties (1 and 2) are assigned only if
  1260.     OverrideModifiedProperties = True.
  1261.   2) If AParaStyle is TParaInfo then
  1262.     3) If OverrideModifiedProperties = True, excludes the applied properties from
  1263.        AParaStyle.ModifiedProperties (1 and 2).
  1264.     4) Reverts other (not applied and not listed in ModifiedProperties (1 and 2))
  1265.       properties to their default values.
  1266.   Default values are taken from the style template having name 'Normal'.
  1267.   If this style template does not exist, RVStyle.ParaStyles[0] is used instead.
  1268. }
  1269. procedure TRVStyleTemplate.ApplyToParaStyle(AParaStyle: TCustomRVParaInfo;
  1270.   OverrideModifiedProperties: Boolean);
  1271. var AppliedProps, DefProps: TRVParaInfoProperties;
  1272.     Template: TRVStyleTemplate;
  1273. begin
  1274.   AppliedProps := RVAllParaInfoProperties;
  1275.   if not OverrideModifiedProperties and (AParaStyle is TParaInfo) then
  1276.     AppliedProps := AppliedProps - TParaInfo(AParaStyle).ModifiedProperties1 -
  1277.       TParaInfo(AParaStyle).ModifiedProperties2;
  1278.   AppliedProps := AssignToParaStyle(AParaStyle, AppliedProps);
  1279.   if AParaStyle is TParaInfo then begin
  1280.     if OverrideModifiedProperties then begin
  1281.       TParaInfo(AParaStyle).ModifiedProperties1 :=
  1282.         TParaInfo(AParaStyle).ModifiedProperties1 - (AppliedProps * RVAllParaInfoProperties1);
  1283.       TParaInfo(AParaStyle).ModifiedProperties2 :=
  1284.         TParaInfo(AParaStyle).ModifiedProperties2 - (AppliedProps * RVAllParaInfoProperties2);
  1285.       AParaStyle.StyleTemplateId := Id;
  1286.     end;
  1287.     DefProps := RVAllParaInfoProperties - AppliedProps
  1288.       - TParaInfo(AParaStyle).ModifiedProperties1
  1289.       - TParaInfo(AParaStyle).ModifiedProperties1;
  1290.     if DefProps=[] then
  1291.       exit;
  1292.     if Collection<>nil then
  1293.       Template := TRVStyleTemplateCollection(Collection).FNormalStyleTemplate
  1294.     else
  1295.       Template := nil;
  1296.     if Template<>nil then
  1297.       Template.AssignToParaStyle(AParaStyle, DefProps)
  1298.     else if (Collection<>nil) and
  1299.             (TRVStyleTemplateCollection(Collection).FOwner<>nil) then
  1300.       AParaStyle.AssignSelectedProperties(
  1301.        (TRVStyleTemplateCollection(Collection).FOwner as TRVStyle).ParaStyles[0],
  1302.        DefProps);
  1303.   end;
  1304. end;
  1305. {------------------------------------------------------------------------------}
  1306. { Checks properties listed in PossibleProps.
  1307.   If they are in ValidTextProperties of this style template (or its parents),
  1308.   and their values are equal in ATextStyle and TextStyle property, they are excluded
  1309.   from ATextStyle.ModifiedProperties. }
  1310. procedure TRVStyleTemplate.ExcludeUnmodifiedTextStyleProperties(ATextStyle: TFontInfo;
  1311.       PossibleProps: TRVFontInfoProperties);
  1312. var Template: TRVStyleTemplate;
  1313.     Props: TRVFontInfoProperties;
  1314. begin
  1315.   Template := Self;
  1316.   while (PossibleProps<>[]) and (Template<>nil) do begin
  1317.     Props := PossibleProps * Template.ValidTextProperties;
  1318.     ATextStyle.ExcludeUnmodifiedProperties(TextStyle, Props);
  1319.     PossibleProps := PossibleProps - Props;
  1320.     Template := Template.FParent;
  1321.   end;
  1322. end;
  1323. {------------------------------------------------------------------------------}
  1324. { Checks properties listed in PossibleProps.
  1325.   If they are in ValidParaProperties (-1 or -2) of this style
  1326.   template (or its parents), and their values are equal in AParaStyle and
  1327.   ParaStyle property, they are excluded from AParaStyle.ModifiedProperties
  1328.   (-1 or -2). }
  1329. procedure TRVStyleTemplate.ExcludeUnmodifiedParaStyleProperties(AParaStyle: TParaInfo;
  1330.       PossibleProps: TRVParaInfoProperties);
  1331. var Template: TRVStyleTemplate;
  1332.     Props: TRVParaInfoProperties;
  1333. begin
  1334.   Template := Self;
  1335.   while (PossibleProps<>[]) and (Template<>nil) do begin
  1336.     Props := PossibleProps * (Template.ValidParaProperties1+Template.ValidParaProperties2);
  1337.     AParaStyle.ExcludeUnmodifiedProperties(ParaStyle, Props);
  1338.     PossibleProps := PossibleProps - Props;
  1339.     Template := Template.FParent;
  1340.   end;
  1341. end;
  1342. {------------------------------------------------------------------------------}
  1343. {$IFDEF RICHVIEWCBDEF3}
  1344. { Returns a name of the collection item, for design-time collection editor. }
  1345. function TRVStyleTemplate.GetDisplayName: String;
  1346. begin
  1347.   Result := Name;
  1348. end;
  1349. {$ENDIF}
  1350. {------------------------------------------------------------------------------}
  1351. { READ method for Id property. Value of this property is stored in FId field.
  1352.   If it's <= 0, it's undefined, and this method generates random value for it.
  1353.   If this item is inserted in the collection, the generated value is unique. }
  1354. function TRVStyleTemplate.GetId: TRVStyleTemplateId;
  1355. var i: Integer;
  1356.     found: Boolean;
  1357. begin
  1358.   if FId<=0 then
  1359.     repeat
  1360.       FId := Random(MaxInt);
  1361.       found := False;
  1362.       if Collection<>nil then
  1363.         for i := 0 to Collection.Count-1 do
  1364.           if (Collection.Items[i]<>Self) and
  1365.             (FId = TRVStyleTemplate(Collection.Items[i]).Id) then begin
  1366.             found := True;
  1367.             break;
  1368.           end;
  1369.     until not found;
  1370.   Result := FId;
  1371. end;
  1372. {------------------------------------------------------------------------------}
  1373. { WRITE method for ListStyle property }
  1374. {
  1375. procedure TRVStyleTemplate.SetListStyle(const Value: TRVSTListInfo);
  1376. begin
  1377.   FListStyle.Assign(Value);
  1378. end;
  1379. }
  1380. {------------------------------------------------------------------------------}
  1381. { WRITE method for ParaStyle property }
  1382. procedure TRVStyleTemplate.SetParaStyle(const Value: TRVSTParaInfo);
  1383. begin
  1384.   FParaStyle.Assign(Value);
  1385. end;
  1386. {------------------------------------------------------------------------------}
  1387. { WRITE method for TextStyle property }
  1388. procedure TRVStyleTemplate.SetTextStyle(const Value: TRVSTFontInfo);
  1389. begin
  1390.   FTextStyle.Assign(Value);
  1391. end;
  1392. {------------------------------------------------------------------------------}
  1393. { Overriden to add IDProp pseudo-property }
  1394. procedure TRVStyleTemplate.DefineProperties(Filer: TFiler);
  1395. begin
  1396.   inherited;
  1397.   Filer.DefineProperty('IDProp', ReadID, WriteID, True);
  1398. end;
  1399. {------------------------------------------------------------------------------}
  1400. { READ method for IDProp pseudo-property.
  1401.   This pseudo-property is used to store Id property (which cannot be stored
  1402.   by itself, because it's readonly. }
  1403. procedure TRVStyleTemplate.ReadID(Reader: TReader);
  1404. begin
  1405.   FId := Reader.ReadInteger;
  1406. end;
  1407. {------------------------------------------------------------------------------}
  1408. { WRITE method for IDProp pseudo-property. }
  1409. procedure TRVStyleTemplate.WriteID(Writer: TWriter);
  1410. begin
  1411.   Writer.WriteInteger(Id);
  1412. end;
  1413. {------------------------------------------------------------------------------}
  1414. { Adds Child to the FChildren collection. }
  1415. procedure TRVStyleTemplate.AddChild(Child: TRVStyleTemplate);
  1416. begin
  1417.   if FChildren=nil then
  1418.     FChildren := TList.Create;
  1419.   FChildren.Add(Child);
  1420. end;
  1421. {------------------------------------------------------------------------------}
  1422. { Removes Child from the FChildren collection. }
  1423. procedure TRVStyleTemplate.RemoveChild(Child: TRVStyleTemplate);
  1424. begin
  1425.   if FChildren<>nil then begin
  1426.     FChildren.Remove(Child);
  1427.     if FChildren.Count=0 then begin
  1428.       FChildren.Free;
  1429.       FChildren := nil;
  1430.     end;
  1431.   end;
  1432. end;
  1433. {------------------------------------------------------------------------------}
  1434. { WRITE method for ParentId property.
  1435.   If possible, references to parent and children are updated. }
  1436. procedure TRVStyleTemplate.SetParentId(const Value: TRVStyleTemplateId);
  1437. var CanUpdateReferences: Boolean;
  1438.     Index: Integer;
  1439. begin
  1440.   if Value=FParentId then
  1441.     exit;
  1442.   CanUpdateReferences := (Collection<>nil) and
  1443.     (TRVStyleTemplateCollection(Collection).FOwner<>nil) and
  1444.     not (csLoading in (TRVStyleTemplateCollection(Collection).FOwner as TComponent).ComponentState);
  1445.   if CanUpdateReferences and (ParentId>0) then begin
  1446.     Index := TRVStyleTemplateCollection(Collection).FindById(ParentId);
  1447.     if Index>=0 then
  1448.       TRVStyleTemplateCollection(Collection).Items[Index].RemoveChild(Self);
  1449.   end;
  1450.   FParentId := Value;
  1451.   FParent   := nil;
  1452.   if CanUpdateReferences and (ParentId>0) then begin
  1453.     Index := TRVStyleTemplateCollection(Collection).FindById(ParentId);
  1454.     if Index>=0 then begin
  1455.       FParent := TRVStyleTemplateCollection(Collection).Items[Index];
  1456.       if IsAncestorFor(FParent) then begin
  1457.         FParentId := -1;
  1458.         FParent := nil;
  1459.         raise ERichViewError.Create(errRVBadStyleTemplateParent);
  1460.       end;
  1461.       FParent.AddChild(Self);
  1462.     end;
  1463.   end;
  1464. end;
  1465. {------------------------------------------------------------------------------}
  1466. { WRITE method for Name property.
  1467.   Maintains TRVStyle.StyleTemplates.FNormalStyleTemplate property. }
  1468. procedure TRVStyleTemplate.SetName(const Value: TRVStyleTemplateName);
  1469. begin
  1470.   if Value<>FName then begin
  1471.     if FName=RVNORMALSTYLETEMPLATENAME then
  1472.       if (Collection<>nil) and
  1473.          (TRVStyleTemplateCollection(Collection).FNormalStyleTemplate=Self) then
  1474.         TRVStyleTemplateCollection(Collection).FNormalStyleTemplate := nil;
  1475.     FName := Value;
  1476.     if FName=RVNORMALSTYLETEMPLATENAME then
  1477.       if (Collection<>nil) then
  1478.         TRVStyleTemplateCollection(Collection).FNormalStyleTemplate := Self;
  1479.   end;
  1480. end;
  1481. {------------------------------------------------------------------------------}
  1482. { Updates references to parent and children. Called from
  1483.   TRVStyleTemplateCollection.UpdateParentReferences. }
  1484. procedure TRVStyleTemplate.UpdateParentReference;
  1485. var Index: Integer;
  1486. begin
  1487.   FParent := nil;
  1488.   if ParentId>0 then begin
  1489.     Index := TRVStyleTemplateCollection(Collection).FindById(ParentId);
  1490.     if Index>=0 then begin
  1491.       FParent := TRVStyleTemplateCollection(Collection).Items[Index];
  1492.       FParent.AddChild(Self);
  1493.     end;
  1494.   end;
  1495. end;
  1496. {------------------------------------------------------------------------------}
  1497. { Is Self an ancestor for StyleTemplate?
  1498.   I.e., of Self=StyleTemplate, or Self=StyleTemplate.FParent, or
  1499.   Self=StyleTemplate.FParent.FParent, etc. }
  1500. function TRVStyleTemplate.IsAncestorFor(StyleTemplate: TRVStyleTemplate): Boolean;
  1501. var Ancestors: TList;
  1502. begin
  1503.   Result := False;
  1504.   Ancestors := TList.Create;
  1505.   try
  1506.     while StyleTemplate<>nil do begin
  1507.       if StyleTemplate=Self then begin
  1508.         Result := True;
  1509.         break;
  1510.       end;
  1511.       Ancestors.Add(StyleTemplate);
  1512.       StyleTemplate := StyleTemplate.FParent;
  1513.       if (StyleTemplate<>nil) and (Ancestors.IndexOf(StyleTemplate)>=0) then
  1514.         StyleTemplate := nil; // exiting circular reference (bad)
  1515.     end;
  1516.   finally
  1517.     Ancestors.Free;
  1518.   end;
  1519. end;
  1520. {========================== TRVStyleTemplateCollection ========================}
  1521. { Constructor }
  1522. constructor TRVStyleTemplateCollection.Create(Owner: TPersistent);
  1523. begin
  1524.   inherited Create(TRVStyleTemplate);
  1525.   FOwner := Owner;
  1526.   FDefStyleName := RVDEFAULTSTYLETEMPLATENAME;
  1527. end;
  1528. {------------------------------------------------------------------------------}
  1529. { Resets counter used to generate unique item names }
  1530. procedure TRVStyleTemplateCollection.ResetNameCounter;
  1531. begin
  1532.   FNameCounter := 0;
  1533. end;
  1534. {------------------------------------------------------------------------------}
  1535. { Function for comparing names of style templates. Used to sort the collection.
  1536.   Case sensitive.}
  1537. function CompareStyleTemplateNames(Item1, Item2: Pointer): Integer;
  1538. begin
  1539.   Result :=  AnsiCompareStr(TRVStyleTemplate(Item1).Name,TRVStyleTemplate(Item2).Name);
  1540. end;
  1541. {------------------------------------------------------------------------------}
  1542. { Sorts items by Name in ascending order, case sensitive }
  1543. procedure TRVStyleTemplateCollection.Sort;
  1544. var
  1545.   i: Integer;
  1546.   List: TList;
  1547. begin
  1548.   List := TList.Create;
  1549.   try
  1550.     for i := 0 to Count - 1 do
  1551.       List.Add(Items[i]);
  1552.     List.Sort(CompareStyleTemplateNames);
  1553.     for i := 0 to List.Count - 1 do
  1554.       TRVStyleTemplate(List.Items[i]).Index := i
  1555.   finally
  1556.     List.Free;
  1557.   end;
  1558. end;
  1559. {------------------------------------------------------------------------------}
  1560. { Returns the index of the item having the given Id.
  1561.   If not found, returns -1. }
  1562. function TRVStyleTemplateCollection.FindById(Id: TRVStyleTemplateId): Integer;
  1563. var i: Integer;
  1564. begin
  1565.   for i := 0 to Count-1 do
  1566.     if Items[i].Id=Id then begin
  1567.       Result := i;
  1568.       exit;
  1569.     end;
  1570.   Result := -1;
  1571. end;
  1572. {------------------------------------------------------------------------------}
  1573. { Returns the index of the item having the given Name (case sensitive)
  1574.   If not found, returns -1. }
  1575. function TRVStyleTemplateCollection.FindByName(const Name: TRVStyleTemplateName): Integer;
  1576. var i: Integer;
  1577. begin
  1578.   for i := 0 to Count-1 do
  1579.     if Items[i].Name=Name then begin
  1580.       Result := i;
  1581.       exit;
  1582.     end;
  1583.   Result := -1;
  1584. end;
  1585. {------------------------------------------------------------------------------}
  1586. { The the style template named 'Normal'), or nil if not found. Fast. }
  1587. function TRVStyleTemplateCollection.GetNormalStyleTemplate: TRVStyleTemplate;
  1588. begin
  1589.   Result := FNormalStyleTemplate;
  1590. end;
  1591. {------------------------------------------------------------------------------}
  1592. { Assigns item names to Strings. If AssignObjects=True, then items are assigned
  1593.   to Strings.Objects. }
  1594. procedure TRVStyleTemplateCollection.AssignToStrings(Strings: TStrings;
  1595.   AssignObjects: Boolean);
  1596. var i: Integer;
  1597. begin
  1598.   Strings.BeginUpdate;
  1599.   try
  1600.     Strings.Clear;
  1601.     {$IFDEF RICHVIEWCBDEF3}
  1602.     Strings.Capacity := Count;
  1603.     {$ENDIF}
  1604.     for i := 0 to Count-1 do
  1605.       if AssignObjects then
  1606.         Strings.AddObject(Items[i].Name, Items[i])
  1607.       else
  1608.         Strings.Add(Items[i].Name);
  1609.   finally
  1610.     Strings.EndUpdate;
  1611.   end;
  1612. end;
  1613. {------------------------------------------------------------------------------}
  1614. { Assigns Source to Self, if Source is a TRVStyleTemplateCollection. }
  1615. procedure TRVStyleTemplateCollection.Assign(Source: TPersistent);
  1616. begin
  1617.   if Source is TRVStyleTemplateCollection then
  1618.     AssignStyleTemplates(TRVStyleTemplateCollection(Source), False)
  1619.   else
  1620.     inherited Assign(Source);
  1621. end;
  1622. {------------------------------------------------------------------------------}
  1623. { Assigns Source to Self. Two possible modes are possible:
  1624.   1. CopyIds=True : Id and ParentId properties are copied. Self becomes
  1625.      the exact copy of Source.
  1626.   2. CopyIds=False: Id properties are not copied, but ParentId properties
  1627.      point to items with the same indices as in the Source. }
  1628. procedure TRVStyleTemplateCollection.AssignStyleTemplates(
  1629.   Source: TRVStyleTemplateCollection; CopyIds: Boolean);
  1630. var i: Integer;
  1631. begin
  1632.   if Source=Self then
  1633.     exit;
  1634.   inherited Assign(Source);
  1635.   if CopyIDs then begin
  1636.     for i := 0 to Count-1 do
  1637.       Items[i].FId := Source.Items[i].Id;
  1638.     for i := 0 to Count-1 do
  1639.       Items[i].ParentId := Source.Items[i].ParentId;
  1640.     end
  1641.   else begin
  1642.     for i := 0 to Count-1 do
  1643.       if Source.Items[i].FParent<>nil then
  1644.         Items[i].ParentId := Items[Source.Items[i].FParent.Index].Id;
  1645.   end;
  1646. end;
  1647. {------------------------------------------------------------------------------}
  1648. { Clears format from ATextStyle:
  1649.   - if 'Normal' StyleTemplate exists, applies it;
  1650.   - otherwise assigns the ParaStyle[0] and clears references.
  1651.   AParaStyle is a style of paragraph where this text is located }
  1652. procedure TRVStyleTemplateCollection.ClearTextFormat(ATextStyle: TCustomRVFontInfo;
  1653.   AParaStyle: TCustomRVParaInfo);
  1654. begin
  1655.   if FNormalStyleTemplate<>nil then
  1656.     FNormalStyleTemplate.ApplyToTextStyle(ATextStyle, AParaStyle, True)
  1657.   else if (FOwner<>nil) then begin
  1658.     ATextStyle.Assign((FOwner as TRVStyle).TextStyles[0]);
  1659.     if ATextStyle is TFontInfo then begin
  1660.       TFontInfo(ATextStyle).ModifiedProperties := [];
  1661.       TFontInfo(ATextStyle).StyleTemplateId := -1;
  1662.     end;
  1663.   end;
  1664. end;
  1665. {------------------------------------------------------------------------------}
  1666. { Clears format from AParaStyle:
  1667.   - if 'Normal' StyleTemplate exists, applies it;
  1668.   - otherwise assigns the ParaStyle[0] and clears references. }
  1669. procedure TRVStyleTemplateCollection.ClearParaFormat(AParaStyle: TCustomRVParaInfo);
  1670. begin
  1671.   if FNormalStyleTemplate<>nil then
  1672.     FNormalStyleTemplate.ApplyToParaStyle(AParaStyle, True)
  1673.   else if (FOwner<>nil) then begin
  1674.     AParaStyle.Assign((FOwner as TRVStyle).ParaStyles[0]);
  1675.     if AParaStyle is TParaInfo then begin
  1676.       TParaInfo(AParaStyle).ModifiedProperties1 := [];
  1677.       TParaInfo(AParaStyle).ModifiedProperties2 := [];
  1678.       TParaInfo(AParaStyle).StyleTemplateId := -1;
  1679.     end;
  1680.   end;
  1681. end;
  1682. {------------------------------------------------------------------------------}
  1683. {$IFDEF RICHVIEWCBDEF3}
  1684. { Designtime support. Required for the collection editor. }
  1685. function TRVStyleTemplateCollection.GetOwner: TPersistent;
  1686. begin
  1687.   Result := FOwner;
  1688. end;
  1689. {$ENDIF}
  1690. {------------------------------------------------------------------------------}
  1691. { READ method for the property Items[]. }
  1692. function TRVStyleTemplateCollection.GetItem(Index: Integer): TRVStyleTemplate;
  1693. begin
  1694.   Result := TRVStyleTemplate(inherited GetItem(Index));
  1695. end;
  1696. {------------------------------------------------------------------------------}
  1697. { WRITE method for the property Items[]. }
  1698. procedure TRVStyleTemplateCollection.SetItem(Index: Integer;
  1699.   const Value: TRVStyleTemplate);
  1700. begin
  1701.   inherited SetItem(Index, Value);
  1702. end;
  1703. {------------------------------------------------------------------------------}
  1704. { STORE method for DefStyleName property }
  1705. function TRVStyleTemplateCollection.StoreDefStyleName: Boolean;
  1706. begin
  1707.   Result := FDefStyleName<>RVDEFAULTSTYLETEMPLATENAME;
  1708. end;
  1709. {------------------------------------------------------------------------------}
  1710. { Generates unique style name }
  1711. procedure TRVStyleTemplateCollection.AssignUniqueNameTo(Item: TRVStyleTemplate);
  1712. var i: Integer;
  1713.     found: Boolean;
  1714.     Name: String;
  1715. begin
  1716.   if (Count=1) and (Items[0]=Item) then
  1717.     FNameCounter := 0;
  1718.   if FNameCounter=MaxInt then
  1719.     FNameCounter := 0;
  1720.   repeat
  1721.     inc(FNameCounter);
  1722.     Name := Format(FDefStyleName, [FNameCounter]);
  1723.     found := False;
  1724.     for i := 0 to Count-1 do
  1725.       if (Items[i]<>Item) and (Items[i].Name=Name) then begin
  1726.         found := True;
  1727.         break;
  1728.       end;
  1729.   until not found;
  1730.   Item.Name := Name;
  1731. end;
  1732. {------------------------------------------------------------------------------}
  1733. { Updates references to parent and children of each item.
  1734.   Normally, references are updated automatically. Updates are deferred only
  1735.   when loading the collection from stream. }
  1736. procedure TRVStyleTemplateCollection.UpdateParentReferences;
  1737. var i: Integer;
  1738. begin
  1739.   for i := 0 to Count-1 do
  1740.     Items[i].UpdateParentReference;
  1741. end;
  1742. {$ENDIF}
  1743. {============================== TRVStyle ======================================}
  1744. { Constructor. Assigns default values to properties. Adds some default items
  1745.   to TextStyles and ParaStyles.
  1746.   Loads crJump and crRVFlipArrow cursors. }
  1747. constructor TRVStyle.Create(AOwner: TComponent);
  1748. var jumpcur : HCURSOR;
  1749. const IDC_HAND = MakeIntResource(32649);
  1750. begin
  1751.   inherited Create(AOwner);
  1752.   jumpcur := LoadCursor(0, IDC_HAND);
  1753.   if jumpcur=0 then
  1754.     jumpcur := LoadCursor(hInstance,RVRC_JUMP_CURSOR);
  1755.   Screen.Cursors[crJump] := jumpcur;
  1756.   Screen.Cursors[crRVFlipArrow] := LoadCursor(hInstance,RVRC_FLIPARROW_CURSOR);
  1757.   FSpacesInTab       := 0;
  1758.   FDefTabWidth       := 48;
  1759.   FFullRedraw        := False;
  1760.   FJumpCursor        := crJump;
  1761.   FLineSelectCursor  := crRVFlipArrow;
  1762.   FColor             := clWindow;
  1763.   FHoverColor        := clNone;
  1764.   FCurrentItemColor  := clNone;
  1765.   FSelColor          := clHighlight;
  1766.   FSelTextColor      := clHighlightText;
  1767.   FInactiveSelColor     := clHighlight;
  1768.   FInactiveSelTextColor := clHighlightText;
  1769.   FCheckpointColor   := clGreen;
  1770.   FCheckpointEvColor := clLime;
  1771.   FPageBreakColor    := clBtnShadow;
  1772.   FSoftPageBreakColor := clBtnFace;
  1773.   FLiveSpellingColor := clRed;
  1774.   FUseSound          := True;
  1775.   FSelectionMode     := rvsmWord;
  1776.   FSelectionStyle    := rvssItems;
  1777.   {$IFNDEF RVDONOTUSEUNICODE}
  1778.   FDefUnicodeStyle   := -1;
  1779.   FDefCodePage       := CP_ACP;
  1780.   {$ENDIF}
  1781.   FTextStyles := TFontInfos.Create(GetTextStyleClass, Self);
  1782.   FParaStyles := TParaInfos.Create(GetParaStyleClass, Self);
  1783.   FListStyles := TRVListInfos.Create(GetListStyleClass, Self);
  1784.   {$IFNDEF RVDONOTUSESTYLETEMPLATES}
  1785.   FStyleTemplates := TRVStyleTemplateCollection.Create(Self);
  1786.   {$ENDIF}
  1787.   ResetParaStyles;
  1788.   ResetTextStyles;
  1789. end;
  1790. {------------------------------------------------------------------------------}
  1791. { Returns class of item of ParaStyles collection. You can override this method
  1792.   to add new properties to paragraph style. }
  1793. function TRVStyle.GetParaStyleClass: TRVParaInfoClass;
  1794. begin
  1795.   Result := TParaInfo;
  1796. end;
  1797. {------------------------------------------------------------------------------}
  1798. { Returns class of item of TextStyles collection. You can override this method
  1799.   to add new properties to text style. }
  1800. function TRVStyle.GetTextStyleClass: TRVFontInfoClass;
  1801. begin
  1802.   Result := TFontInfo;
  1803. end;
  1804. {------------------------------------------------------------------------------}
  1805. { Returns class of item of ListStyles collection. You can override this method
  1806.   to add new properties to list style. }
  1807. function TRVStyle.GetListStyleClass: TRVListInfoClass;
  1808. begin
  1809.   Result := TRVListInfo;
  1810. end;
  1811. {------------------------------------------------------------------------------}
  1812. { Delphi streaming support (required for D2) }
  1813. procedure TRVStyle.ReadState(Reader: TReader);
  1814. begin
  1815.   {$IFNDEF RICHVIEWDEF3}
  1816.   ParaStyles.Clear;
  1817.   TextStyles.Clear;
  1818.   {$ENDIF}
  1819.   inherited ReadState(Reader);
  1820. end;
  1821. {------------------------------------------------------------------------------}
  1822. { Destructor. }
  1823. destructor TRVStyle.Destroy;
  1824. begin
  1825.   FTextStyles.Free;
  1826.   FParaStyles.Free;
  1827.   FListStyles.Free;
  1828.   FInvalidPicture.Free;
  1829.   {$IFNDEF RVDONOTUSESTYLETEMPLATES}
  1830.   FStyleTemplates.Free;
  1831.   {$ENDIF}
  1832.   inherited Destroy;
  1833. end;
  1834. {------------------------------------------------------------------------------}
  1835. { Applies TextStyle[StyleNo] to the Canvas (all properties except for colors).
  1836.   DefBiDiMode - bi-di mode of paragraph.
  1837.   CanUseCustomPPI allows using TextStyles.PixelsPerInch property.
  1838.   This method calls OnApplyStyle event, then (if allowed) TextStyles[StyleNo].Apply
  1839.   method. }
  1840. procedure TRVStyle.ApplyStyle(Canvas: TCanvas; StyleNo: Integer;
  1841.   DefBiDiMode: TRVBiDiMode; CanUseCustomPPI: Boolean);
  1842. var DoDefault: Boolean;
  1843. begin
  1844.   if Assigned(FOnApplyStyle) then begin
  1845.     DoDefault := True;
  1846.     FOnApplyStyle(Self, Canvas, StyleNo, DoDefault);
  1847.     if DoDefault then
  1848.       FTextStyles[StyleNo].Apply(Canvas, DefBiDiMode, CanUseCustomPPI);
  1849.     end
  1850.   else
  1851.     FTextStyles[StyleNo].Apply(Canvas, DefBiDiMode, CanUseCustomPPI);
  1852. end;
  1853. {------------------------------------------------------------------------------}
  1854. { Applies colors of TextStyle[StyleNo] to the Canvas.
  1855.   DrawState defines a state of text (selected, hot, etc.).
  1856.   This method calls OnApplyStyleColor event, then (if allowed)
  1857.   TextStyles[StyleNo].ApplyColor method.
  1858.   Colors are corrected according to the ColorMode.
  1859.   If Printing, this is a printing or print preview. }
  1860. procedure TRVStyle.ApplyStyleColor(Canvas: TCanvas; StyleNo: Integer;
  1861.   DrawState: TRVTextDrawStates; Printing: Boolean; ColorMode: TRVColorMode);
  1862. var DoDefault: Boolean;
  1863. begin
  1864.   if Assigned(FOnApplyStyleColor) then begin
  1865.     DoDefault := True;
  1866.     FOnApplyStyleColor(Self, Canvas, StyleNo, DrawState, DoDefault);
  1867.     if DoDefault then
  1868.       FTextStyles[StyleNo].ApplyColor(Canvas, Self, DrawState, Printing, ColorMode);
  1869.     end
  1870.   else
  1871.     FTextStyles[StyleNo].ApplyColor(Canvas, Self, DrawState, Printing, ColorMode);
  1872. end;
  1873. {------------------------------------------------------------------------------}
  1874. { Draws string s on Canvas using TextStyles[StyleNo].
  1875.   It's assumed that ApplyStyleColor and ApplyStyle were already called.
  1876.   (RVData, ItemNo, OffsetInItem) specify a location of this string in document.
  1877.   These properties will be assigned to the corresponding fields of Self (for using
  1878.   in events).
  1879.   If TextStyles[StyleNo].Unicode, s must contain a "raw unicode".
  1880.   Drawing item rectangle is Bounds(Left, Top, Width, Height).
  1881.   Text position is (Left+SpaceBefore, Top).
  1882.   DrawState defines a state of text (selected, hot, etc.).
  1883.   Colors are corrected according to the ColorMode.
  1884.   If Printing, this is a printing or print preview.
  1885.   If PreviewCorrection and Printing, this is a print preview that allows correction.
  1886.   DefBiDiMode - bi-di mode of paragraph.
  1887. }
  1888. procedure TRVStyle.DrawStyleText(const s: String; Canvas: TCanvas;
  1889.   ItemNo, OffsetInItem, StyleNo: Integer; RVData: TPersistent;
  1890.   SpaceBefore, Left, Top, Width, Height: Integer; DrawState: TRVTextDrawStates;
  1891.   Printing, PreviewCorrection: Boolean; ColorMode: TRVColorMode;
  1892.   DefBiDiMode: TRVBidiMode);
  1893. var DoDefault: Boolean;
  1894. begin
  1895.   if Assigned(FOnDrawStyleText) then begin
  1896.     DoDefault := True;
  1897.     Self.ItemNo := ItemNo;
  1898.     Self.RVData := RVData;
  1899.     Self.OffsetInItem := OffsetInItem;
  1900.     FOnDrawStyleText(Self, s, Canvas, StyleNo,
  1901.                      SpaceBefore, Left, Top, Width, Height, DrawState, DoDefault);
  1902.     if DoDefault then
  1903.       FTextStyles[StyleNo].Draw(s, Canvas, StyleNo, SpaceBefore, Left, Top, Width, Height,
  1904.         Self, DrawState, Printing, PreviewCorrection, ColorMode, DefBiDiMode);
  1905.     end
  1906.   else
  1907.     FTextStyles[StyleNo].Draw(s, Canvas, StyleNo, SpaceBefore, Left, Top, Width, Height,
  1908.       Self, DrawState, Printing, PreviewCorrection, ColorMode, DefBiDiMode);
  1909. end;
  1910. {------------------------------------------------------------------------------}
  1911. { Does text of TextStyles[StyleNo] require redrawing when mouse moves in/out?
  1912.   This function checks HoverColors (fore- and background) and calls
  1913.   OnStyleHoverSensitive event. }
  1914. function TRVStyle.StyleHoverSensitive(StyleNo: Integer): Boolean;
  1915. begin
  1916.   Result := (GetHoverColor(StyleNo)<>clNone) or
  1917.             (FTextStyles[StyleNo].HoverBackColor<>FTextStyles[StyleNo].BackColor);
  1918.   if Assigned(FOnStyleHoverSensitive) then
  1919.     FOnStyleHoverSensitive(Self, StyleNo, Result);
  1920. end;
  1921. {------------------------------------------------------------------------------}
  1922. { Draws text background at Bounds(Left,Top,Width,Height) on Canvas.
  1923.   This method calls OnDrawTextBackground event. If this event is not processed,
  1924.   it does nothing (because background is drawn in DrawStyleText).
  1925.   (RVData, ItemNo) specify position of text item in document.
  1926.   These properties will be assigned to the corresponding fields of Self
  1927.   (for using in event).
  1928.   DrawState defines a state of text (selected, hot, etc.) }
  1929. procedure TRVStyle.DrawTextBack(Canvas: TCanvas; ItemNo, StyleNo: Integer;
  1930.   RVData: TPersistent; Left, Top, Width, Height: Integer;
  1931.   DrawState: TRVTextDrawStates);
  1932. var DoDefault: Boolean;
  1933. begin
  1934.   if Assigned(FOnDrawTextBack) then begin
  1935.     DoDefault := True;
  1936.     Self.ItemNo := ItemNo;
  1937.     Self.RVData := RVData;
  1938.     FOnDrawTextBack(Self, Canvas, StyleNo, Left, Top, Width, Height, DrawState, DoDefault);
  1939.   end;
  1940. end;
  1941. {------------------------------------------------------------------------------}
  1942. { Draw checkpoint on Canvas.
  1943.   (X,Y) - top left corner of item owning the checkpoint.
  1944.   XShift specifies a horizontal scrolling position (useful if you want to draw
  1945.   something on margin rather than relative to the item's X coordinate).
  1946.   RaiseEvent - property of checkpoint.
  1947.   Control - TRichView where to draw.
  1948.   ItemNo - index of item owning this checkpoint.
  1949.   NOTE: this is old method. When it was created, it was possible to get additional
  1950.   checkpoint info using Control and ItemNo. TODO: to add RVData parameter.
  1951.   This method calls OnDrawCheckpoint event. Then (if allowed) draws checkpoint
  1952.   as a horizontal dotted line with a small circle at (X,Y).
  1953.   If RaiseEvent, CheckpointEvColor color is used, otherwise CheckpointColor.
  1954. }
  1955. procedure TRVStyle.DrawCheckpoint(Canvas: TCanvas; X,Y, AreaLeft, Width: Integer;
  1956.   RVData: TPersistent; ItemNo, XShift: Integer;
  1957.   RaiseEvent: Boolean; Control: TControl);
  1958. var DoDefault: Boolean;
  1959. begin
  1960.   DoDefault := True;
  1961.   if Assigned(FOnDrawCheckpoint) then begin
  1962.     Self.RVData := RVData;
  1963.     Self.ItemNo := ItemNo;
  1964.     FOnDrawCheckpoint(Self, Canvas, X, Y, ItemNo, XShift, RaiseEvent, Control,
  1965.       DoDefault);
  1966.   end;
  1967.   if DoDefault then begin
  1968.     Canvas.Pen.Width := 1;
  1969.     if RaiseEvent then
  1970.       Canvas.Pen.Color := CheckpointEvColor
  1971.     else
  1972.       Canvas.Pen.Color := CheckpointColor;
  1973.     Canvas.Brush.Style := bsClear;
  1974.     if ItemNo<>-1 then begin
  1975.       Canvas.Pen.Style := psSolid;
  1976.       Canvas.Ellipse(X-2,Y-2, X+2, Y+2);
  1977.     end;
  1978.     Canvas.Pen.Style := psDot;
  1979.     Canvas.MoveTo(AreaLeft-XShift, Y);
  1980.     Canvas.LineTo(AreaLeft+Width-XShift, Y);
  1981.   end;
  1982.   Canvas.Pen.Style := psSolid;
  1983.   Canvas.Brush.Style := bsClear;
  1984. end;
  1985. {------------------------------------------------------------------------------}
  1986. { Draws page break on Canvas. Y - vertical coordinate. XShift specifies
  1987.   a horizontal scrolling. Control is TRichView where to draw.
  1988.   PageBreakType - type of pagebreak (hard (explicit) or soft (automatic)).
  1989.   This method calls OnDrawPageBreak event. Then (if allowed) - draws a line
  1990.   with "dog ear" effect, using PageBreakColor or SoftPageBreakColor. }
  1991. procedure TRVStyle.DrawPageBreak(Canvas: TCanvas; Y, XShift: Integer;
  1992.   PageBreakType: TRVPageBreakType; Control: TControl);
  1993. var DoDefault: Boolean;
  1994.     x: Integer;
  1995. const CORNERSIZE=8;
  1996. begin
  1997.   DoDefault := True;
  1998.   if Assigned(FOnDrawPageBreak) then
  1999.     FOnDrawPageBreak(Self, Canvas, Y, XShift, PageBreakType, Control, DoDefault);
  2000.   if DoDefault then begin
  2001.     if PageBreakType = rvpbPageBreak then
  2002.       Canvas.Pen.Color := PageBreakColor
  2003.     else
  2004.       Canvas.Pen.Color := SoftPageBreakColor;
  2005.     Canvas.Pen.Width := 1;
  2006.     Canvas.Pen.Style := psSolid;
  2007.     x := Control.ClientWidth-XShift-CORNERSIZE;
  2008.     Canvas.Brush.Color := clWindow;
  2009.     Canvas.Brush.Style := bsSolid;
  2010.     Canvas.MoveTo(-XShift,Y);
  2011.     Canvas.LineTo(X,Y);
  2012.     Canvas.Polygon([Point(X,Y), Point(X+CORNERSIZE,Y+CORNERSIZE),
  2013.                    Point(X,Y+CORNERSIZE)]);
  2014.   end;
  2015.   Canvas.Pen.Style := psSolid;
  2016.   Canvas.Brush.Style := bsClear;
  2017. end;
  2018. {------------------------------------------------------------------------------}
  2019. { Draw background of ParaStyles[ParaNo] on Canvas at Rect.
  2020.   If Printing, this is printing or print preview.
  2021.   Colors are corrected according to ColorMode.
  2022.   This method calls OnDrawParaBack event, then (if allowed)
  2023.   ParaStyles[ParaNo].Background.Draw method.
  2024.   Note: when calling this method, Self.RVData and Self.ItemNo
  2025.   (index of the last item of the paragraph) are assigned. }
  2026. procedure TRVStyle.DrawParaBack(Canvas: TCanvas; ParaNo: Integer; const Rect: TRect;
  2027.   Printing: Boolean; ColorMode: TRVColorMode);
  2028. var DoDefault: Boolean;
  2029. begin
  2030.   DoDefault := True;
  2031.   if Assigned(FOnDrawParaBack) then
  2032.     FOnDrawParaBack(Self, Canvas, ParaNo, Rect, DoDefault);
  2033.   if DoDefault then
  2034.     FParaStyles[ParaNo].Background.Draw(Rect, Canvas, Printing, ColorMode);
  2035. end;
  2036. {------------------------------------------------------------------------------}
  2037. { Clears TextStyles and fills it with default items. }
  2038. procedure TRVStyle.ResetTextStyles;
  2039. var fi: TFontInfo;
  2040.     i : Integer;
  2041. begin
  2042.   FTextStyles.Clear;
  2043.   for i := 0 to LAST_DEFAULT_STYLE_NO do begin
  2044.     fi := FTextStyles.Add;
  2045.     case i of
  2046.      rvsNormal:
  2047.         begin
  2048.            fi.StyleName := RVDEFSTYLENAME0;
  2049.         end;
  2050.      rvsHeading:
  2051.         begin
  2052.            fi.Style := fi.Style + [fsBold];
  2053.            fi.Color := clBlue;
  2054.            fi.StyleName := RVDEFSTYLENAME1;
  2055.         end;
  2056.      rvsSubheading:
  2057.         begin
  2058.            fi.Style := fi.Style + [fsBold];
  2059.            fi.Color := clNavy;
  2060.            fi.StyleName := RVDEFSTYLENAME2;
  2061.         end;
  2062.      rvsKeyword:
  2063.         begin
  2064.            fi.Style := fi.Style + [fsItalic];
  2065.            fi.Color := clMaroon;
  2066.            fi.StyleName := RVDEFSTYLENAME3;
  2067.         end;
  2068.      rvsJump1, rvsJump2:
  2069.         begin
  2070.            fi.Style := fi.Style + [fsUnderline];
  2071.            fi.Color := clGreen;
  2072.            fi.Jump  := True;
  2073.            fi.JumpCursor := JumpCursor;
  2074.            if i=rvsJump1 then
  2075.              fi.StyleName := RVDEFSTYLENAME4
  2076.            else
  2077.              fi.StyleName := RVDEFSTYLENAME5;
  2078.         end;
  2079.     end;
  2080.   end;
  2081. end;
  2082. {------------------------------------------------------------------------------}
  2083. { Clears ParaStyles and fills it with default items. }
  2084. procedure TRVStyle.ResetParaStyles;
  2085. begin
  2086.   FParaStyles.Clear;
  2087.   FParaStyles.Add;
  2088.   with FParaStyles.Add as TParaInfo do begin
  2089.     StyleName := RVDEFPARASTYLENAME1;
  2090.     Alignment := rvaCenter;
  2091.   end;
  2092. end;
  2093. {------------------------------------------------------------------------------}
  2094. { WRITE method for TextStyles property. }
  2095. procedure TRVStyle.SetTextStyles(Value: TFontInfos);
  2096. begin
  2097.   if FTextStyles<>Value then
  2098.     FTextStyles.Assign(Value);
  2099. end;
  2100. {------------------------------------------------------------------------------}
  2101. { WRITE method for ParaStyles property. }
  2102. procedure TRVStyle.SetParaStyles(Value: TParaInfos);
  2103. begin
  2104.   if FParaStyles<>Value then
  2105.     FParaStyles.Assign(Value);
  2106. end;
  2107. {------------------------------------------------------------------------------}
  2108. { WRITE method for ListStyles property. }
  2109. procedure TRVStyle.SetListStyles(Value: TRVListInfos);
  2110. begin
  2111.   if FListStyles<>Value then
  2112.     FListStyles.Assign(Value);
  2113. end;
  2114. {------------------------------------------------------------------------------}
  2115. {$IFNDEF RVDONOTUSESTYLETEMPLATES}
  2116. { WRITE method for StyleTemplates property }
  2117. procedure TRVStyle.SetStyleTemplates(const Value: TRVStyleTemplateCollection);
  2118. begin
  2119.   if FStyleTemplates<>Value then
  2120.     FStyleTemplates.Assign(Value);
  2121. end;
  2122. {$ENDIF}
  2123. {------------------------------------------------------------------------------}
  2124. { Returns "hot" (under mouse) color for the specified Color. }
  2125. function TRVStyle.GetHoverColorByColor(Color: TColor): TColor;
  2126. begin
  2127.   if Color<>clNone then
  2128.     Result := Color
  2129.   else
  2130.     Result := HoverColor;
  2131. end;
  2132. {------------------------------------------------------------------------------}
  2133. { Returns "hot" (under mouse) text color for TextStyle[StyleNo]. }
  2134. function TRVStyle.GetHoverColor(StyleNo: Integer): TColor;
  2135. begin
  2136.   if FTextStyles[StyleNo].HoverColor<>clNone then
  2137.     Result := FTextStyles[StyleNo].HoverColor
  2138.   else
  2139.     Result := HoverColor;
  2140. end;
  2141. {------------------------------------------------------------------------------}
  2142. { (Deprecated) }
  2143. function TRVStyle.AddTextStyle: Integer;
  2144. begin
  2145.    FTextStyles.Add;
  2146.    AddTextStyle := FTextStyles.Count-1;
  2147. end;
  2148. {------------------------------------------------------------------------------}
  2149. { (Deprecated) }
  2150. procedure TRVStyle.DeleteTextStyle(Index: Integer);
  2151. begin
  2152.    FTextStyles[Index].Free;
  2153. end;
  2154. {------------------------------------------------------------------------------}
  2155. {$IFNDEF RVDONOTUSEINI}
  2156. { Loads itself from the ini-file, from the section Section. }
  2157. procedure TRVStyle.LoadFromINI(ini: TRVIniFile; Section: String);
  2158. begin
  2159.   Color             := ini.ReadInteger(Section, RVINI_COLOR,             clWindow);
  2160.   HoverColor        := ini.ReadInteger(Section, RVINI_HOVERCOLOR,        clNone);
  2161.   CurrentItemColor  := ini.ReadInteger(Section, RVINI_CURRENTITEMCOLOR,  clNone);
  2162.   SelColor          := ini.ReadInteger(Section, RVINI_SELCOLOR,          clHighlight);
  2163.   SelTextColor      := ini.ReadInteger(Section, RVINI_SELTEXTCOLOR,      clHighlightText);
  2164.   InactiveSelColor     := ini.ReadInteger(Section, RVINI_ISELCOLOR,      clHighlight);
  2165.   InactiveSelTextColor := ini.ReadInteger(Section, RVINI_ISELTEXTCOLOR,  clHighlightText);
  2166.   CheckpointColor   := ini.ReadInteger(Section, RVINI_CPCOLOR,   clGreen);
  2167.   CheckpointEvColor := ini.ReadInteger(Section, RVINI_CPEVCOLOR, clLime);
  2168.   PageBreakColor    := ini.ReadInteger(Section, RVINI_PAGEBREAKCOLOR,  clBtnShadow);
  2169.   SoftPageBreakColor := ini.ReadInteger(Section, RVINI_SOFTPAGEBREAKCOLOR, clBtnFace);
  2170.   LiveSpellingColor := ini.ReadInteger(Section, RVINI_LIVESPELLINGCOLOR, clRed);
  2171.   JumpCursor        := ini.ReadInteger(Section, RVINI_JUMPCURSOR,        crJump);
  2172.   UseSound          := Boolean(ini.ReadInteger(Section, RVINI_USESOUND,  Integer(True)));
  2173.   SelectionMode     := TRVSelectionMode(ini.ReadInteger(Section, RVINI_SELECTIONMODE, ord(rvsmWord)));
  2174.   SelectionStyle    := TRVSelectionStyle(ini.ReadInteger(Section, RVINI_SELECTIONSTYLE, ord(rvssItems)));
  2175.   SpacesInTab       := ini.ReadInteger(Section, RVINI_SPACESINTAB, 0);
  2176.   DefTabWidth       := ini.ReadInteger(Section, RVINI_DEFTABWIDTH, 48);
  2177.   {$IFNDEF RVDONOTUSEUNICODE}
  2178.   DefUnicodeStyle   := ini.ReadInteger(Section, RVINI_DEFUNICODESTYLE,   -1);
  2179.   DefCodePage       := ini.ReadInteger(Section, RVINI_DEFCODEPAGE,   CP_ACP);
  2180.   {$ENDIF}
  2181.   ParaStyles.LoadFromINI(ini, Section);
  2182.   TextStyles.LoadFromINI(ini, Section, JumpCursor);
  2183.   ListStyles.LoadFromINI(ini, Section);
  2184. end;
  2185. {------------------------------------------------------------------------------}
  2186. { Stores itself to the ini-file, to the section Section.
  2187.   WARNING: this Section is erased before writing! }
  2188. procedure TRVStyle.SaveToINI(ini: TRVIniFile; Section: String);
  2189. begin
  2190.   ini.EraseSection(Section);
  2191.   WriteIntToIniIfNE(ini, Section, RVINI_COLOR,             Color,             clWindow);
  2192.   WriteIntToIniIfNE(ini, Section, RVINI_HOVERCOLOR,        HoverColor,        clNone);
  2193.   WriteIntToIniIfNE(ini, Section, RVINI_CURRENTITEMCOLOR,  CurrentItemColor,  clNone);
  2194.   WriteIntToIniIfNE(ini, Section, RVINI_SELCOLOR,          SelColor,          clHighlight);
  2195.   WriteIntToIniIfNE(ini, Section, RVINI_SELTEXTCOLOR,      SelTextColor,      clHighlightText);
  2196.   WriteIntToIniIfNE(ini, Section, RVINI_ISELCOLOR,         InactiveSelColor,     clHighlight);
  2197.   WriteIntToIniIfNE(ini, Section, RVINI_ISELTEXTCOLOR,     InactiveSelTextColor, clHighlightText);
  2198.   WriteIntToIniIfNE(ini, Section, RVINI_CPCOLOR,   CheckpointColor,   clGreen);
  2199.   WriteIntToIniIfNE(ini, Section, RVINI_CPEVCOLOR, CheckpointEvColor, clLime);
  2200.   WriteIntToIniIfNE(ini, Section, RVINI_PAGEBREAKCOLOR,    PageBreakColor,      clBtnShadow);
  2201.   WriteIntToIniIfNE(ini, Section, RVINI_SOFTPAGEBREAKCOLOR, SoftPageBreakColor, clBtnFace);
  2202.   WriteIntToIniIfNE(ini, Section, RVINI_LIVESPELLINGCOLOR, LiveSpellingColor, clRed);
  2203.   WriteIntToIniIfNE(ini, Section, RVINI_JUMPCURSOR,        JumpCursor,        crJump);
  2204.   WriteBoolToIniIfNE(ini, Section, RVINI_USESOUND,         UseSound,          True);
  2205.   WriteIntToIniIfNE(ini, Section, RVINI_SELECTIONMODE,     ord(SelectionMode),  ord(rvsmWord));
  2206.   WriteIntToIniIfNE(ini, Section, RVINI_SELECTIONSTYLE,    ord(SelectionStyle), ord(rvssItems));
  2207.   WriteIntToIniIfNE(ini, Section, RVINI_SPACESINTAB,       SpacesInTab, 0);
  2208.   WriteIntToIniIfNE(ini, Section, RVINI_DEFTABWIDTH,       DefTabWidth, 48);  
  2209.   WriteIntToIniIfNE(ini, Section, RVINI_SELECTIONSTYLE,    ord(SelectionStyle), ord(rvssItems));
  2210.   {$IFNDEF RVDONOTUSEUNICODE}
  2211.   WriteIntToIniIfNE(ini, Section, RVINI_DEFUNICODESTYLE,   DefUnicodeStyle,   -1);
  2212.   WriteIntToIniIfNE(ini, Section, RVINI_DEFCODEPAGE,       DefCodePage,   CP_ACP);
  2213.   {$ENDIF}
  2214.   ParaStyles.SaveToINI(ini, Section);
  2215.   TextStyles.SaveToINI(ini, Section);
  2216.   ListStyles.SaveToINI(ini, Section);
  2217. end;
  2218. {------------------------------------------------------------------------------}
  2219. { Stores itself in the ini-file FileName, in the section Section. }
  2220. procedure TRVStyle.SaveINI(const FileName, Section: String);
  2221. var ini: TIniFile;
  2222. begin
  2223.   ini := TIniFile.Create(FileName);
  2224.   try
  2225.     SaveToINI(ini, Section);
  2226.   finally
  2227.     ini.Free;
  2228.   end;
  2229. end;
  2230. {------------------------------------------------------------------------------}
  2231. { Loads itself from the ini-file FileName, from the section Section. }
  2232. procedure TRVStyle.LoadINI(const FileName, Section: String);
  2233. var ini: TIniFile;
  2234. begin
  2235.   ini := TIniFile.Create(filename);
  2236.   try
  2237.     LoadFromINI(ini, Section);
  2238.   finally
  2239.     ini.Free;
  2240.   end;
  2241. end;
  2242. {$IFDEF RICHVIEWDEF4}
  2243. {------------------------------------------------------------------------------}
  2244. { Loads itself from the Registry, from the key BaseKey"RVStyle". }
  2245. procedure TRVStyle.LoadReg(const BaseKey: String);
  2246. var ini: TRegistryIniFile;
  2247. begin
  2248.   ini := TRegistryIniFile.Create(BaseKey);
  2249.   try
  2250.     LoadFromINI(ini, RVSTYLE_REG);
  2251.   finally
  2252.     ini.Free;
  2253.   end;
  2254. end;
  2255. {------------------------------------------------------------------------------}
  2256. { Stores itself to the Registry, to the key BaseKey"RVStyle". }
  2257. procedure TRVStyle.SaveReg(const BaseKey: String);
  2258. var ini: TRegistryIniFile;
  2259. begin
  2260.   ini := TRegistryIniFile.Create(BaseKey);
  2261.   try
  2262.     SaveToINI(ini, RVSTYLE_REG);
  2263.   finally
  2264.     ini.Free;
  2265.   end;
  2266. end;
  2267. {$ENDIF}
  2268. {$ENDIF}
  2269. {-----------------------------------------------------------------------}
  2270. {$IFNDEF RVDONOTUSEHTML}
  2271. {-----------------------------------------------------------------------}
  2272. { Exports as CSS (Cascading Style Sheet) file. }
  2273. function TRVStyle.SaveCSS(const FileName: String;
  2274.   AOptions: TRVSaveCSSOptions): Boolean;
  2275. var Stream: TFileStream;
  2276. begin
  2277.   Result := True;
  2278.   try
  2279.     Stream := TFileStream.Create(FileName, fmCreate);
  2280.     try
  2281.       SaveCSSToStream(Stream, AOptions);
  2282.     finally
  2283.       Stream.Free;
  2284.     end;
  2285.   except
  2286.     Result := False;
  2287.   end;
  2288. end;
  2289. {-----------------------------------------------------------------------}
  2290. { Exports as CSS (Cascading Style Sheet) to the Stream. }
  2291. procedure TRVStyle.SaveCSSToStream(Stream: TStream; AOptions: TRVSaveCSSOptions);
  2292. var i: Integer;
  2293.     comments: String;
  2294.     BaseStyle: TFontInfo;
  2295.     BaseParaStyle: TParaInfo;
  2296.     {..................................................}
  2297.     {$IFNDEF RVDONOTUSELISTS}
  2298.     (* Reserved for future - when browser will be CSS2 compatible    
  2299.     function GetListTagSequence(ListNo, Level: Integer): String;
  2300.     var i: Integer;
  2301.     begin
  2302.       Result := Format('%s.RVLS%d',
  2303.         [ListStyles[ListNo].Levels[0].GetHTMLOpenTagForCSS, ListNo]);
  2304.       with ListStyles[ListNo] do
  2305.         for i := 1 to Level do
  2306.           Result := Result+' '+Levels[i].GetHTMLOpenTagForCSS;
  2307.     end;
  2308.     {..................................................}
  2309.     function GetListTypeStr(ListType: TRVListType; Legal: Boolean): String;
  2310.     begin
  2311.       case ListType of
  2312.         rvlstBullet, rvlstPicture, rvlstUnicodeBullet, rvlstImageList:
  2313.            Result := '';
  2314.         rvlstLowerAlpha:
  2315.            Result := 'lower-alpha';
  2316.         rvlstUpperAlpha:
  2317.            Result := 'upper-alpha';
  2318.         rvlstLowerRoman:
  2319.            Result := 'lower-roman';
  2320.          rvlstUpperRoman:
  2321.            Result := 'upper-roman';
  2322.          else
  2323.            Result := 'decimal';
  2324.       end;
  2325.       if Legal and (Result<>'') then
  2326.          Result := 'decimal';
  2327.     end;
  2328.     {..................................................}
  2329.     function GetListContentStr(ListNo, Level: Integer): String;
  2330.     var CountersVal: array [0..255] of TVarRec;
  2331.         CountersStr: array [0..255] of String;
  2332.         s: String;
  2333.         i: Integer;
  2334.         Legal: Boolean;
  2335.     begin
  2336.       for i := 0 to 255 do begin
  2337.         CountersVal[i].VAnsiString := nil;
  2338.         CountersVal[i].VType := vtAnsiString;
  2339.       end;
  2340.       Legal := rvloLegalStyleNumbering in ListStyles[ListNo].Levels[Level].Options;
  2341.       for i := 0 to Level do begin
  2342.         s := GetListTypeStr(ListStyles[ListNo].Levels[i].ListType, Legal and (i<>Level));
  2343.         if s<>'' then begin
  2344.           CountersStr[i] := Format(#1' counter(c%dl%d,%s) '#1,[ListNo,i,s]);
  2345.           CountersVal[i].VAnsiString := PChar(CountersStr[i]);
  2346.         end
  2347.       end;
  2348.       s := Format(ListStyles[ListNo].Levels[Level].FormatString, CountersVal);
  2349.       repeat
  2350.         i := Pos(#1#1, s);
  2351.         if i>0 then
  2352.           Delete(s, i, 2);
  2353.       until i = 0;
  2354.       if Length(s)>0 then begin
  2355.         if s[1]=#1 then
  2356.           Delete(s,1,1)
  2357.         else
  2358.           s := '"'+s;
  2359.         if s[Length(s)]=#1 then
  2360.           Delete(s,Length(s),1)
  2361.         else
  2362.           s := s+'"';
  2363.       end;
  2364.       for i := 1 to Length(s) do
  2365.         if s[i]=#1 then
  2366.           s[i] := '"';
  2367.       Result := s;
  2368.     end;
  2369.     {..................................................}
  2370.     function GetListContent(ListNo, Level: Integer): String;
  2371.     var LevelInfo: TRVListLevel;
  2372.     begin
  2373.       LevelInfo := ListStyles[ListNo].Levels[Level];
  2374.       case LevelInfo.ListType of
  2375.         rvlstUnicodeBullet:
  2376.           {$IFDEF RICHVIEWCBDEF3}
  2377.           Result := RVU_GetHTMLEncodedUnicode(RVU_GetRawUnicode(LevelInfo.FFormatStringW), False,False);
  2378.           {$ELSE}
  2379.           Result := LevelInfo.FFormatStringW;
  2380.           {$ENDIF}
  2381.         rvlstBullet:
  2382.           Result := LevelInfo.FFormatString;
  2383.         else
  2384.           Result := GetListContentStr(ListNo,Level);
  2385.       end;
  2386.     end;
  2387.     *)
  2388.     {$ENDIF}
  2389.     {..................................................}    
  2390. begin
  2391.   RVWriteLn(Stream, '/* ========== Text Styles ========== */');
  2392.   RVWriteLn(Stream, 'hr { color: '+RV_GetHTMLRGBStr(FTextStyles[0].Color, False)+'}');
  2393.   for i:=0 to FTextStyles.Count-1 do
  2394.     with FTextStyles[i] do begin
  2395.       if Standard then begin
  2396.         Comments := Format(' /* %s */', [StyleName]);
  2397.         if rvcssUTF8 in AOptions then
  2398.           Comments := RVU_AnsiToUTF8(DefCodePage, Comments);
  2399.         end
  2400.       else
  2401.         Comments := '';
  2402.       if (i=0) and not Jump and (BackColor=clNone) and
  2403.          not (rvcssNoDefCSSStyle in AOptions) then
  2404.         RVWriteLn(Stream, Format('body, table%s', [Comments]))
  2405.       else if Jump then
  2406.         RVWriteLn(Stream, Format('a.rvts%d, span.rvts%d%s',[i,i, Comments]))
  2407.       else
  2408.         RVWriteLn(Stream, Format('span.rvts%d%s', [i, Comments]));
  2409.       if (rvcssOnlyDifference in AOptions) and
  2410.         (BaseStyleNo>=0) and (BaseStyleNo<TextStyles.Count) then
  2411.         BaseStyle := TextStyles[BaseStyleNo]
  2412.       else begin
  2413.         BaseStyle := nil;
  2414.         if (i>0) and not TextStyles[0].Jump and
  2415.            (TextStyles[0].BackColor=clNone) and
  2416.            not (rvcssNoDefCSSStyle in AOptions) then
  2417.           BaseStyle := TextStyles[0];
  2418.       end;
  2419.       RVWriteLn(Stream, '{');
  2420.       SaveCSSToStream(Stream, BaseStyle, True, rvcssUTF8 in AOptions);
  2421.       RVWriteLn(Stream, '}');
  2422.       if Jump and ((GetHoverColorByColor(HoverColor)<>clNone) or (HoverBackColor<>clNone)) then begin
  2423.         RVWrite(Stream, Format('a.rvts%d:hover {', [i]));
  2424.         if (((BaseStyle=nil) or not BaseStyle.Jump) and (GetHoverColorByColor(HoverColor)<>clNone)) or
  2425.            ((BaseStyle<>nil) and (GetHoverColorByColor(HoverColor)<>GetHoverColorByColor(BaseStyle.HoverColor))) then
  2426.           RVWrite(Stream, Format(' color: %s;', [RV_GetHTMLRGBStr(GetHoverColorByColor(HoverColor), False)]));
  2427.         if (((BaseStyle=nil) or not BaseStyle.Jump)  and (HoverBackColor<>clNone)) or
  2428.            ((BaseStyle<>nil) and (HoverBackColor<>BaseStyle.HoverBackColor)) then
  2429.           RVWrite(Stream, Format(' background-color: %s;', [RV_GetHTMLRGBStr(HoverBackColor, False)]));
  2430.         RVWriteLn(Stream, ' }');
  2431.       end;
  2432.     end;
  2433.   RVWriteLn(Stream, '/* ========== Para Styles ========== */');
  2434.   for i:=0 to FParaStyles.Count-1 do
  2435.     with FParaStyles[i] do begin
  2436.       if Standard then begin
  2437.         Comments := Format(' /* %s */', [StyleName]);
  2438.         if rvcssUTF8 in AOptions then
  2439.           Comments := RVU_AnsiToUTF8(DefCodePage, Comments);        
  2440.         end
  2441.       else
  2442.         Comments := '';
  2443.       if (i=0) and not (rvcssNoDefCSSStyle in AOptions) then
  2444.         RVWriteLn(Stream, Format('p,ul,ol%s',[Comments]))
  2445.       else
  2446.         RVWriteLn(Stream, Format('.rvps%d%s',[i,Comments]));
  2447.       if (rvcssOnlyDifference in AOptions) and
  2448.         (BaseStyleNo>=0) and (BaseStyleNo<ParaStyles.Count) then
  2449.         BaseParaStyle := ParaStyles[BaseStyleNo]
  2450.       else begin
  2451.         if (i>0) and not (rvcssNoDefCSSStyle in AOptions) then
  2452.           BaseParaStyle := ParaStyles[0]
  2453.         else
  2454.           BaseParaStyle := nil;
  2455.       end;
  2456.       RVWriteLn(Stream, '{');
  2457.       SaveCSSToStream(Stream, BaseParaStyle, True,
  2458.         rvcssIgnoreLeftAlignment in AOptions, False);
  2459.       RVWriteLn(Stream, '}');
  2460.     end;
  2461.   {$IFNDEF RVDONOTUSELISTS}
  2462.   (*
  2463.   RVWriteLn(Stream, '/*----------List Styles----------*/');
  2464.   for i:=0 to FListStyles.Count-1 do
  2465.     for j:=0 to FListStyles[i].Levels.Count-1 do
  2466.       with FListStyles[i].Levels[j] do begin
  2467.         s := GetListTagSequence(i,j);
  2468.         if j=0 then
  2469.           descr := Format('/* %s */ ',[FListStyles[i].StyleName])
  2470.         else
  2471.           descr := '';
  2472.         if MarkerIndent>=LeftIndent then
  2473.           s2 := Format('text-indent: %dpx !important; margin-left !important: %d; list-style:inside;',
  2474.             [MarkerIndent-LeftIndent, LeftIndent])
  2475.         else
  2476.           s2 := Format('text-indent: %dpx !important; margin-left: %d !important; list-style:outside;',
  2477.             [FirstIndent, LeftIndent]);
  2478.         RVWriteLn(Stream, Format('%s %s{ %s }', [s, descr, s2]));
  2479.       end;
  2480.   *)
  2481.   (*
  2482.   RVWriteLn(Stream, '/*----------List Styles----------*/');
  2483.   for i:=0 to FListStyles.Count-1 do
  2484.     for j:=0 to FListStyles[i].Levels.Count-1 do
  2485.       with FListStyles[i].Levels[j] do begin
  2486.         s := GetListTagSequence(i,j);
  2487.         if j=0 then
  2488.           descr := Format('/* %s */ ',[FListStyles[i].StyleName])
  2489.         else
  2490.           descr := '';
  2491.         if HasNumbering then begin
  2492.           if (rvloLevelReset in Options) then begin
  2493.             RVWriteLn(Stream, Format('%s %s{ counter-reset: c%dl%d; }', [s, descr, i,j]));
  2494.             descr := '';
  2495.           end;
  2496.           RVWriteLn(Stream, Format('%s > LI %s{ counter-increment: c%dl%d; }', [s, descr, i,j]));
  2497.           descr := '';
  2498.         end;
  2499.         RVWriteLn(Stream, Format('%s > LI:before %s{ content:%s }', [s, descr, GetListContent(i,j)]));
  2500.       end;
  2501.   *)
  2502.   {$ENDIF}
  2503. end;
  2504. {$ENDIF}
  2505. {------------------------------------------------------------------------------}
  2506. { Adjusting link when removing linked components. }
  2507. procedure TRVStyle.Notification(AComponent: TComponent;
  2508.   Operation: TOperation);
  2509. begin
  2510.   inherited Notification(AComponent, Operation);
  2511.   if (Operation=opRemove) and (AComponent is TCustomImageList) then
  2512.     FListStyles.RemoveImageList(TCustomImageList(AComponent));
  2513. end;
  2514. {------------------------------------------------------------------------------}
  2515. procedure TRVStyle.Loaded;
  2516. begin
  2517.   inherited Loaded;
  2518.   {$IFNDEF RVDONOTUSESTYLETEMPLATES}
  2519.   StyleTemplates.UpdateParentReferences;
  2520.   {$ENDIF}
  2521. end;
  2522. {------------------------------------------------------------------------------}
  2523. { READ method for InvalidPicture property. }
  2524. function TRVStyle.GetInvalidPicture: TPicture;
  2525. begin
  2526.   if FInvalidPicture=nil then begin
  2527.     FInvalidPicture := TPicture.Create;
  2528.     FInvalidPicture.Bitmap.Handle := LoadBitmap(hInstance, 'RV_BAD_PICTURE');
  2529.   end;
  2530.   Result := FInvalidPicture;
  2531. end;
  2532. {------------------------------------------------------------------------------}
  2533. { Write method for InvalidPicture property. }
  2534. procedure TRVStyle.SetInvalidPicture(const Value: TPicture);
  2535. begin
  2536.   if Value=nil then begin
  2537.     FInvalidPicture.Free;
  2538.     FInvalidPicture := nil;
  2539.     exit;
  2540.   end;
  2541.   if FInvalidPicture=Value then
  2542.     exit;
  2543.   if FInvalidPicture=nil then
  2544.     FInvalidPicture := TPicture.Create;
  2545.   FInvalidPicture.Assign(Value);
  2546. end;
  2547. {------------------------------------------------------------------------------}
  2548. { Returns the next tabstop after X. X is measured from the very left
  2549.   of document, including the left margin.
  2550.   The following values are returned: Position (from the very left), Align, Leader.
  2551.   LeftIndent and RightIndent are values of LeftIndent and RightIndent. They are
  2552.   in the target device resolution. sad specifies the resolution of target device.
  2553.   DefBiDiMode - bi-di mode of document (some corrections are done for RTL paragraphs).
  2554.   How it works:
  2555.   - first it searches in ParaStyles[ParaNo].Tabs[].Positions; LeftIndent is also
  2556.     treated as a tabstop (RightIndent for RTL paragraphs).
  2557.   - if not found, it calculates position using DefTabWidth property.
  2558. }
  2559. procedure TRVStyle.GetNextTab(ParaNo, X: Integer; sad: TRVScreenAndDevice;
  2560.   var Position: Integer; var Leader: String; var Align: TRVTabAlign;
  2561.   DefBiDiMode: TRVBiDiMode; LeftIndent, RightIndent: Integer);
  2562. var
  2563.     {$IFNDEF RVDONOTUSETABS}
  2564.     Tabs: TRVTabInfos;
  2565.     Pos, Indent, i: Integer;
  2566.     Found: Boolean;
  2567.     {$ENDIF}
  2568.     dtw: Integer;
  2569. begin
  2570.   if DefBiDiMode=rvbdUnspecified then
  2571.     DefBiDiMode := ParaStyles[ParaNo].BiDiMode;
  2572.   dec(X, sad.LeftMargin);
  2573.   if (DefBiDiMode=rvbdRightToLeft) then begin
  2574.     inc(X,RightIndent);
  2575.     dec(X,LeftIndent);
  2576.     {$IFNDEF RVDONOTUSETABS}
  2577.     Indent := RightIndent;
  2578.     {$ENDIF}
  2579.     end
  2580.    {$IFNDEF RVDONOTUSETABS}
  2581.   else
  2582.     Indent := LeftIndent
  2583.    {$ENDIF};
  2584.   {$IFNDEF RVDONOTUSETABS}
  2585.   Tabs := ParaStyles[ParaNo].Tabs;
  2586.   for i := 0 to Tabs.Count-1 do begin
  2587.     Found := False;
  2588.     Pos := RV_XToDevice(Tabs[i].Position, sad);
  2589.     if (Indent>X) and (Indent<Pos) then begin
  2590.       Found := True;
  2591.       Position := Indent+sad.LeftMargin;
  2592.       Leader := '';
  2593.       Align := rvtaLeft;
  2594.       end
  2595.     else if Pos>X then begin
  2596.       Found := True;
  2597.       Position := Pos+sad.LeftMargin;
  2598.       Leader := Tabs[i].Leader;
  2599.       Align := Tabs[i].Align;
  2600.     end;
  2601.     if Found then begin
  2602.       if DefBiDiMode=rvbdRightToLeft then begin
  2603.         dec(Position,RightIndent);
  2604.         inc(Position,LeftIndent);
  2605.       end;
  2606.       exit;
  2607.     end;
  2608.   end;
  2609.   if (Indent>X) and
  2610.      ((Tabs.Count=0) or (Indent>RV_XToDevice(Tabs[Tabs.Count-1].Position, sad))) then begin
  2611.     Position := Indent+sad.LeftMargin;
  2612.     Leader := '';
  2613.     Align := rvtaLeft;
  2614.     if (DefBiDiMode=rvbdRightToLeft) then begin
  2615.       dec(Position,RightIndent);
  2616.       inc(Position,LeftIndent);
  2617.     end;
  2618.     exit;
  2619.   end;
  2620.   {$ENDIF}
  2621.   dtw := DefTabWidth;
  2622.   if dtw<=0 then
  2623.     dtw := 1;
  2624.   dtw := RV_XToDevice(dtw, sad);
  2625.   Position := ((X+dtw) div dtw)*dtw+sad.LeftMargin;
  2626.   if  (DefBiDiMode=rvbdRightToLeft) then begin
  2627.     dec(Position,RightIndent);
  2628.     inc(Position,LeftIndent);
  2629.   end;
  2630.   Align := rvtaLeft;
  2631.   Leader := '';
  2632. end;
  2633. {==============================================================================}
  2634. { Writes s to Stream. }
  2635. procedure RVWrite(Stream: TStream; const s: String);
  2636. begin
  2637.   Stream.WriteBuffer(PChar(s)^, Length(s));
  2638. end;
  2639. {-----------------------------------------------------------------------}
  2640. { Writes s+line break to Stream }
  2641. procedure RVWriteLn(Stream: TStream; const s: String);
  2642. var crlf: String;
  2643. begin
  2644.   Stream.WriteBuffer(PChar(s)^, Length(s));
  2645.   crlf := #13#10;
  2646.   Stream.WriteBuffer(PChar(crlf)^, 2);
  2647. end;
  2648. {-----------------------------------------------------------------------}
  2649. { Writes s to Stream. If Multiline, writes line break after it. }
  2650. procedure RVWriteX(Stream: TStream; const s: String; Multiline: Boolean);
  2651. var crlf: String;
  2652. begin
  2653.   Stream.WriteBuffer(PChar(s)^, Length(s));
  2654.   if Multiline then begin
  2655.     crlf := #13#10;
  2656.     Stream.WriteBuffer(PChar(crlf)^, 2);
  2657.   end;
  2658. end;
  2659. end.