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

RichEdit

开发平台:

Delphi

  1. {*******************************************************}
  2. {                                                       }
  3. {       RichView                                        }
  4. {       Miscellaneous procedures.                       }
  5. {                                                       }
  6. {       Copyright (c) Sergey Tkachenko                  }
  7. {       svt@trichview.com                               }
  8. {       http://www.trichview.com                        }
  9. {                                                       }
  10. {*******************************************************}
  11. unit RVFuncs;
  12. interface
  13. {$I RV_Defs.inc}
  14. uses SysUtils, Windows, Classes, RVStyle, RVStr,
  15.      {$IFNDEF RVDONOTUSEJPEGIMAGE}
  16.      Jpeg,
  17.     {$ENDIF}
  18.      Graphics;
  19. const
  20.   { Number of pixels in the screen inch. If 0 (default) - use screen resolution.
  21.     Affects converting pixels to mm, inches, twips and vice versa:
  22.     printing, RTF.
  23.     Main possible values: 96 (small font mode), 120 (large font mode). }
  24.   RichViewPixelsPerInch : Integer = 0;
  25. {---------------------------  Text & Tags  ------------------------------------}
  26. function RV_CopyTag(SourceTag: Integer; TagsArePChars: Boolean): Integer;
  27. function RV_CompareTags(Tag1, Tag2: Integer; TagsArePChars: Boolean): Boolean;
  28. function RV_ReplaceTabsA(const s: String; SpacesInTab: Integer): String;
  29. function RV_ReplaceTabsW(const s: String; SpacesInTab: Integer): String;
  30. function RV_CharPos(const Str: PChar; Chr: Char; Length: Integer): Integer; assembler;
  31. procedure RV_ReplaceStr(var str: String; oldstr, newstr: String);
  32. function RV_GetHintStr(DocFormat: TRVSaveFormat; const Hint: String): String;
  33. {--------------------------  HTML functions  ----------------------------------}
  34. function RV_GetHTMLRGBStr(Color: TColor; Quotes: Boolean): String;
  35. function RV_GetCSSBkColor(Color: TColor): String;
  36. function RV_GetHTMLPath(const Path: String; SaveOptions: TRVSaveOptions; CodePage: TRVCodePage): String;
  37. function RV_GetHTMLFontCSS(Font: TFont; UseFontName: Boolean): String;
  38. function RV_HTMLGetFontSize(pts: Integer): Integer;
  39. function RV_HTMLOpenFontTag(ts, normalts: TFontInfo; Relative: Boolean;
  40.   SaveOptions: TRVSaveOptions): String;
  41. function RV_HTMLOpenFontTag2(fnt: TFont; normalts: TFontInfo; UseFontName: Boolean;
  42.   SaveOptions: TRVSaveOptions): String;
  43. function RV_HTMLCloseFontTag(ts: TFontInfo; normalts: TFontInfo; Relative: Boolean):String;
  44. function RV_HTMLCloseFontTag2(fnt: TFont; normalts: TFontInfo;
  45.   UseFontName: Boolean):String;
  46. {$IFNDEF RVDONOTUSEHTML}
  47. function RV_MakeHTMLSymbolStr(const s: String): String;
  48. function RV_MakeHTMLSymbolStrRaw(const s: String): String;
  49. function RV_MakeHTMLStr(const str:String; SpecialCode:Boolean): String;
  50. {$IFDEF RICHVIEWCBDEF3}
  51. function RV_CharSet2HTMLLang(CharSet: TFontCharset): String;
  52. {$ENDIF}
  53. {$ENDIF}
  54. function RV_DecodeURL(const s: String): String;
  55. function RV_HTMLGetEndingSlash(SaveOptions: TRVSaveOptions): String;
  56. function RV_HTMLGetNoValueAttribute(const Attr: String; SaveOptions: TRVSaveOptions): String;
  57. function RV_HTMLGetIntAttrVal(Value: Integer; SaveOptions: TRVSaveOptions): String;
  58. function RV_HTMLGetStrAttrVal(const Value: String; SaveOptions: TRVSaveOptions): String;
  59. {--------------------------  RTF functions  -----------------------------------}
  60. {$IFNDEF RVDONOTUSERTF}
  61. function RVMakeRTFStr(const s:String; SpecialCode, UseNamedEntities: Boolean): String;
  62. function RVMakeRTFFileNameStr(const s:String): String;
  63. function MakeRTFIdentifierStr(const s:String): String;
  64. function MakeRTFBookmarkNameStr(const s:String): String;
  65. procedure RVWriteUnicodeRTFStr(Stream: TStream; const s: String;
  66.   CodePage: TRVCodePage; SaveAnsi, SpecialCode: Boolean);
  67. {$ENDIF}
  68. {-------------------------- URL Detection -------------------------------------}
  69. function RVIsURL(const s: String): Boolean;
  70. function RVIsEmail(const s: String): Boolean;
  71. {----------------------  Conversion of coordinates  ---------------------------}
  72. function RV_XToDevice(X: Integer; const sad: TRVScreenAndDevice): Integer;
  73. function RV_YToDevice(Y: Integer; const sad: TRVScreenAndDevice): Integer;
  74. function RV_XToScreen(X: Integer; const sad: TRVScreenAndDevice): Integer;
  75. function RV_YToScreen(Y: Integer; const sad: TRVScreenAndDevice): Integer;
  76. procedure RV_RectToScreen(var R: TRect; const sad: TRVScreenAndDevice);
  77. procedure RV_InfoAboutSaD(var sad:TRVScreenAndDevice; Canvas: TCanvas);
  78. function RV_GetPixelsPerInch: Integer;
  79. function RV_PointInRect(X,Y: Integer; Left,Top,Width,Height: Integer): Boolean;
  80. {------------------------  Graphics & Colors  ---------------------------------}
  81. function RV_CreateGraphicsDefault(GraphicClass: TGraphicClass): TGraphic;
  82. procedure RV_AfterImportGraphicDefault(Graphic: TGraphic);
  83. function RV_GetLuminance(Color: TColor): Integer;
  84. function RV_GetGray(Color: TColor): TColor;
  85. function RV_GetPrnColor(Color: TColor): TColor;
  86. function RV_GetColor(Color: TColor; ColorMode: TRVColorMode): TColor;
  87. function RV_GetBackColor(Color: TColor; ColorMode: TRVColorMode): TColor;
  88. function RV_IsGraphicTransparent(gr: TGraphic): Boolean;
  89. procedure RV_SetPaletteToPicture(gr: TGraphic; PLogPal: PLogPalette);
  90. procedure RV_PictureToDevice(Canvas: TCanvas; x,y, width, height: Integer;
  91.   sad:TRVScreenAndDevice; gr: TGraphic; ToScreen: Boolean);
  92. { ---------------------------- Others -----------------------------------------}
  93. {$IFNDEF RICHVIEWCBDEF3}
  94. function ExtractRelativePath(const BaseName, DestName: string): string;
  95. {$ENDIF}
  96. procedure RV_AddStr(var s1: String; const s2: String);
  97. type
  98.   TRV_CreateGraphicsFunction = function (GraphicClass: TGraphicClass): TGraphic;
  99.   TRV_AfterImportGraphicsProc = procedure(Graphic: TGraphic);
  100. var
  101.   { Procedure for creating graphic object by graphic class
  102.     used as a workaround for D2-D5, CB1-CB5 bug (private constructor in
  103.     TGraphic). Assign your own procedure if you use third-party graphic
  104.     classes }
  105.   RV_CreateGraphics: TRV_CreateGraphicsFunction;
  106.   { Procedure for calling after importing external graphics from RTF documents }
  107.   RV_AfterImportGraphic: TRV_AfterImportGraphicsProc;
  108. implementation
  109. uses RVFMisc, RVUni, CRVData;
  110. type SetOfChar = set of Char;
  111. procedure ReplaceChars(var str: String; Replacer: Char; Replaced: SetOfChar); forward;
  112. {===========================  Text & Tags  ====================================}
  113. { Returns a copy of SourceTag. If TagsArePChars, it assumes that SourceTag is
  114.   a pointer to ANSIZ string, creates a copy of this string and returns it      }
  115. function RV_CopyTag(SourceTag: Integer; TagsArePChars: Boolean): Integer;
  116. begin
  117.   if (SourceTag<>0) and TagsArePChars then
  118.     Result := Integer(StrNew(PChar(SourceTag)))
  119.   else
  120.     Result := SourceTag;
  121. end;
  122. {------------------------------------------------------------------------------}
  123. { Returns true if Tag1 is equal to Tag2. If TagsArePChars, tags are compared
  124.   as strings, otherwise as integers                                            }
  125. function RV_CompareTags(Tag1, Tag2: Integer; TagsArePChars: Boolean): Boolean;
  126. begin
  127.   if TagsArePChars then
  128.     if (Tag1=0) then
  129.       if (Tag2=0) then
  130.         Result := True
  131.       else
  132.         Result := False
  133.     else
  134.       if (Tag2=0) then
  135.         Result := False
  136.       else
  137.         Result := StrComp(PChar(Tag1),PChar(Tag2))=0
  138.   else
  139.     Result := Tag1=Tag2;
  140. end;
  141. {------------------------------------------------------------------------------}
  142. { Replaces all tabs (#9) with a sequence of SpacesInTab space characters       }
  143. function RV_ReplaceTabsA(const s: String; SpacesInTab: Integer): String;
  144. var p: Integer;
  145.     spaces: String;
  146. begin
  147.   Result := s;
  148.   p := Pos(#9,Result);
  149.   if p<>0 then begin
  150.     SetLength(spaces,SpacesInTab);
  151.     FillChar(PChar(spaces)^, SpacesInTab, ' ');
  152.   end;
  153.   while p<>0 do begin
  154.     Delete(Result,p,1);
  155.     Insert(spaces,Result,p);
  156.     p := Pos(#9,Result);
  157.   end;
  158. end;
  159. {------------------------------------------------------------------------------}
  160. { The same for unicode string (represented as "raw unicode")                   }
  161. function RV_ReplaceTabsW(const s: String; SpacesInTab: Integer): String;
  162. var i,p: Integer;
  163.     spaces: String;
  164. begin
  165.   Result := s;
  166.   p := Pos(#9#0,Result);
  167.   if p<>0 then begin
  168.     SetLength(spaces,SpacesInTab*2);
  169.     FillChar(PChar(spaces)^, SpacesInTab*2, 0);
  170.     for i := 1 to SpacesInTab do
  171.       spaces[(i-1)*2+1] := ' ';
  172.   end;
  173.   while p<>0 do begin
  174.     Delete(Result,p,2);
  175.     Insert(spaces,Result,p);
  176.     p := Pos(#9#0,Result);
  177.   end;
  178. end;
  179. {------------------------------------------------------------------------------}
  180. { Returns index of character (Chr) in string (Str) having length Length.
  181.   Returns 0 if not found. Otherwise index of the first occurence of the character
  182.   (1-based).                                                                   }
  183. function RV_CharPos(const Str: PChar {EAX}; Chr: Char {DL} ; Length: Integer {ECX}): Integer; assembler;
  184. asm
  185.         TEST    EAX,EAX
  186.         JE      @@2
  187.         PUSH    EDI
  188.         PUSH    EBX
  189.         MOV     EDI,Str
  190.         MOV     EBX,Str
  191.         MOV     AL,Chr
  192.         REPNE   SCASB
  193.         MOV     EAX,0
  194.         JNE     @@1
  195.         MOV     EAX,EDI
  196.         SUB     EAX,EBX
  197. @@1:    POP     EBX
  198.         POP     EDI
  199. @@2:
  200. end;
  201. {------------------------------------------------------------------------------}
  202. { Replaces in str all substrings oldstr with substring newstr.
  203.   Case insensitive. Newstr CANNOT contain oldstr as a substring.               }
  204. procedure RV_ReplaceStr(var str: String; oldstr, newstr: String);
  205. var p: Integer;
  206. begin
  207.    while true do begin
  208.      p := pos(oldstr, str);
  209.      if p=0 then break;
  210.      Delete(str,p, Length(oldstr));
  211.      Insert(newstr, str, p);
  212.    end;
  213. end;
  214. {------------------------------------------------------------------------------}
  215. { Replaces in str all substrings oldstr with substring newstr.
  216.   Case insensitive. Newstr can contain oldstr as a substring.                  }
  217. procedure RV_ReplaceStr2(var str: String; oldstr, newstr: String);
  218. var p,ptr: Integer;
  219.     s: String;
  220. begin
  221.    s := str;
  222.    ptr := 1;
  223.    while true do begin
  224.      p := pos(oldstr, s);
  225.      if p=0 then break;
  226.      inc(p, ptr-1);
  227.      Delete(str,p, Length(oldstr));
  228.      Insert(newstr, str, p);
  229.      ptr := p+Length(newstr);
  230.      s := Copy(str, ptr, Length(str)+1-ptr);
  231.    end;
  232. end;
  233. {------------------------------------------------------------------------------}
  234. { Returns code for inserting hint (tool tip) in HTML and RTF                   }
  235. function RV_GetHintStr(DocFormat: TRVSaveFormat; const Hint: String): String;
  236. begin
  237.   Result := Hint;
  238.   if Result='' then
  239.     exit;
  240.   case DocFormat of
  241.     rvsfHTML:
  242.       begin
  243.         {$IFNDEF RVDONOTUSEHTML}
  244.         ReplaceChars(Result , '''', ['"']);
  245.         Result := 'title="'+Result+'"';
  246.         {$ENDIF}
  247.       end;
  248.     rvsfRTF:
  249.       begin
  250.         {$IFNDEF RVDONOTUSERTF}
  251.         ReplaceChars(Result , '''', ['"']);
  252.         Result := MakeRTFIdentifierStr(Result);
  253.         Result := 'o "'+Result+'"';
  254.         {$ENDIF}
  255.       end;
  256.   end;
  257. end;
  258. {==========================  HTML functions  ==================================}
  259. { Returns HTML representation of color ('#RRGGBB' string).
  260.   For clNone, returns empty string.
  261.   Processes clWindowText as clBlack.                                           }
  262. function RV_GetHTMLRGBStr(Color: TColor; Quotes: Boolean): String;
  263. begin
  264.   if Color=clWindowText then
  265.     Color := clBlack;
  266.   if Color=clNone then
  267.     Result := ''
  268.   else begin
  269.     Result := LowerCase(IntToHex(ColorToRGB(Color),6));
  270.     Result := '#'+System.Copy(Result,5,2)+System.Copy(Result,3,2)+System.Copy(Result,1,2);
  271.     if Quotes then
  272.       Result := '"'+Result+'"';
  273.   end;
  274. end;
  275. {------------------------------------------------------------------------------}
  276. { The same as RV_GetHTMLRGBStr, but returns 'transparent' for clNone           }
  277. function RV_GetCSSBkColor(Color: TColor): String;
  278. begin
  279.   if Color=clNone then
  280.     Result := 'transparent'
  281.   else
  282.     Result := RV_GetHTMLRGBStr(Color, False);
  283. end;
  284. {------------------------------------------------------------------------------}
  285. { Replaces all '' with '/'                                                    }
  286. function RV_GetHTMLPath(const Path: String; SaveOptions: TRVSaveOptions;
  287.   CodePage: TRVCodePage): String;
  288. var i: Integer;
  289. begin
  290.   Result := Path;
  291.   for i := 1 to Length(Result) do
  292.     if Result[i]='' then
  293.       Result[i] := '/';
  294.   if rvsoUTF8 in SaveOptions then
  295.     Result := RVU_AnsiToUTF8(CodePage, Result);
  296. end;
  297. {------------------------------------------------------------------------------}
  298. { Special concatenation of two strings                                         }
  299. procedure RV_AddStr(var s1: String; const s2: String);
  300. begin
  301.   if s1<>'' then begin
  302.     if s2<>'' then
  303.       s1 := s1+' '+s2
  304.     end
  305.   else
  306.     s1 := s2;
  307. end;
  308. {------------------------------------------------------------------------------}
  309. { Returns string describing the given font in CSS format                       }
  310. function RV_GetHTMLFontCSS(Font: TFont; UseFontName: Boolean): String;
  311. var s: String;
  312. begin
  313.   Result := '';
  314.   if fsBold in Font.Style then
  315.     Result := 'font-weight: bold;';
  316.   if fsItalic in Font.Style then
  317.     RV_AddStr(Result, 'font-style: italic;');
  318.   if Font.Size>0 then
  319.     RV_AddStr(Result, Format('font-size: %dpt;',[Font.Size]))
  320.   else
  321.     RV_AddStr(Result, Format('font-size: %dpx;',[Font.Height]));
  322.   if UseFontName then begin
  323.     s := ''''+Font.Name+'''';
  324.     if (AnsiCompareText(Font.Name, RVFONT_SYMBOL)=0) or
  325.        (AnsiCompareText(Font.Name, RVFONT_WINGDINGS)=0) then
  326.       s := '''Arial Unicode MS'', ''Lucida Sans Unicode'', ''Arial''';
  327.     RV_AddStr(Result, Format('font-family: %s;',[s]));
  328.   end;
  329.   s := '';
  330.   if fsUnderline in Font.Style then
  331.     s := 'underline';
  332.   if fsStrikeOut in Font.Style then
  333.     RV_AddStr(s, 'line-through');
  334.   if s<>'' then
  335.     Result := Format('%s text-decoration: %s;',[Result,s]);
  336.   Result := Format('%s color: %s;',[Result,RV_GetHTMLRGBStr(Font.Color, False)]);
  337. end;
  338. {------------------------------------------------------------------------------}
  339. { Converts the font size in points to the font size for HTML (without CSS).
  340.   HTML uses 7 font sizes.                                                      }
  341. function RV_HTMLGetFontSize(pts: Integer): Integer;
  342. begin
  343.   if pts<=8 then
  344.     Result := 1
  345.   else
  346.     case pts of
  347.       9..10:  Result := 2;
  348.       11..12: Result := 3;
  349.       13..14: Result := 4;
  350.       15..18: Result := 5;
  351.       19..24: Result := 6;
  352.       else    Result := 7;
  353.     end;
  354. end;
  355. {------------------------------------------------------------------------------}
  356. { Returns opening HTML tags for formatting of text style ts.
  357.   If Relative, it returns a difference in formatting between ts and normalts   }
  358. function RV_HTMLOpenFontTag(ts, normalts: TFontInfo; Relative: Boolean;
  359.   SaveOptions: TRVSaveOptions): String;
  360. var s: String;
  361. begin
  362.   s := '';
  363.   if not Relative or (ts.Size<>normalts.Size) then
  364.     s := s+' size='+RV_HTMLGetIntAttrVal(RV_HTMLGetFontSize(ts.Size), SaveOptions);
  365.   if not Relative or (ts.Color<>normalts.Color) then
  366.     s := s+' color='+RV_GetHTMLRGBStr(ts.Color, True);
  367.   if not Relative or (AnsiCompareText(ts.FontName,normalts.FontName)<>0) then
  368.     s := s+' face="'+ts.FontName+'"';
  369.   if s<>'' then
  370.     s := '<font'+s+'>';
  371.   if Relative then begin
  372.     if not (fsStrikeOut in ts.Style) and (fsStrikeOut in normalts.Style) then s := s+'</s>';
  373.     if not (fsUnderline in ts.Style) and (fsUnderline in normalts.Style) then s := s+'</u>';
  374.     if not (fsItalic    in ts.Style) and (fsItalic    in normalts.Style) then s := s+'</i>';
  375.     if not (fsBold      in ts.Style) and (fsBold      in normalts.Style) then s := s+'</b>';
  376.     if (fsBold      in ts.Style) and not (fsBold      in normalts.Style) then s := s+'<b>';
  377.     if (fsItalic    in ts.Style) and not (fsItalic    in normalts.Style) then s := s+'<i>';
  378.     if (fsUnderline in ts.Style) and not (fsUnderline in normalts.Style) then s := s+'<u>';
  379.     if (fsStrikeOut in ts.Style) and not (fsStrikeOut in normalts.Style) then s := s+'<s>';
  380.     end
  381.   else begin
  382.     if (fsBold in ts.Style)      then s := s+'<b>';
  383.     if (fsItalic in ts.Style)    then s := s+'<i>';
  384.     if (fsUnderline in ts.Style) then s := s+'<u>';
  385.     if (fsStrikeOut in ts.Style) then s := s+'<s>';
  386.   end;
  387.   if ts.VShift < 0 then
  388.     s := s+'<sub>'
  389.   else if ts.VShift > 0 then
  390.     s := s+'<sup>';
  391.   Result := s;
  392. end;
  393. {------------------------------------------------------------------------------}
  394. { The same as RV_HTMLOpenFontTag(..., True), but formatting is defined by
  395.   fnt: TFont                                                                   }
  396. function RV_HTMLOpenFontTag2(fnt: TFont; normalts: TFontInfo;
  397.   UseFontName: Boolean; SaveOptions: TRVSaveOptions): String;
  398. var s: String;
  399. begin
  400.   s := '';
  401.   if (fnt.Size<>normalts.Size) then
  402.     s := s+' size='+RV_HTMLGetIntAttrVal(RV_HTMLGetFontSize(fnt.Size), SaveOptions);
  403.   if (fnt.Color<>normalts.Color) then
  404.     s := s+' color='+RV_GetHTMLRGBStr(fnt.Color, True);
  405.   if UseFontName and (AnsiCompareText(fnt.Name,normalts.FontName)<>0) then
  406.     s := s+' face="'+fnt.Name+'"';
  407.   if s<>'' then
  408.     s := '<font'+s+'>';
  409.   if not (fsStrikeOut in fnt.Style) and (fsStrikeOut in normalts.Style) then s := s+'</s>';
  410.   if not (fsUnderline in fnt.Style) and (fsUnderline in normalts.Style) then s := s+'</u>';
  411.   if not (fsItalic    in fnt.Style) and (fsItalic    in normalts.Style) then s := s+'</i>';
  412.   if not (fsBold      in fnt.Style) and (fsBold      in normalts.Style) then s := s+'</b>';
  413.   if (fsBold      in fnt.Style) and not (fsBold      in normalts.Style) then s := s+'<b>';
  414.   if (fsItalic    in fnt.Style) and not (fsItalic    in normalts.Style) then s := s+'<i>';
  415.   if (fsUnderline in fnt.Style) and not (fsUnderline in normalts.Style) then s := s+'<u>';
  416.   if (fsStrikeOut in fnt.Style) and not (fsStrikeOut in normalts.Style) then s := s+'<s>';
  417.   Result := s;
  418. end;
  419. {------------------------------------------------------------------------------}
  420. { Closes HTML tags opened in RV_HTMLOpenFontTag                                }
  421. function RV_HTMLCloseFontTag(ts: TFontInfo; normalts: TFontInfo; Relative: Boolean):String;
  422. var s: String;
  423. begin
  424.   if ts.VShift < 0 then
  425.     s := s+'</sub>'
  426.   else if ts.VShift > 0 then
  427.     s := s+'</sup>';
  428.   if Relative then begin
  429.     if (fsStrikeOut in ts.Style) and not (fsStrikeOut in normalts.Style) then s := s+'</s>';
  430.     if (fsUnderline in ts.Style) and not (fsUnderline in normalts.Style) then s := s+'</u>';
  431.     if (fsItalic    in ts.Style) and not (fsItalic    in normalts.Style) then s := s+'</i>';
  432.     if (fsBold      in ts.Style) and not (fsBold      in normalts.Style) then s := s+'</b>';
  433.     if not (fsBold      in ts.Style) and (fsBold      in normalts.Style) then s := s+'<b>';
  434.     if not (fsItalic    in ts.Style) and (fsItalic    in normalts.Style) then s := s+'<i>';
  435.     if not (fsUnderline in ts.Style) and (fsUnderline in normalts.Style) then s := s+'<u>';
  436.     if not (fsStrikeOut in ts.Style) and (fsStrikeOut in normalts.Style) then s := s+'<s>';
  437.     end
  438.   else begin
  439.     if (fsStrikeOut in ts.Style) then s := s+'</s>';
  440.     if (fsUnderline in ts.Style) then s := s+'</u>';
  441.     if (fsItalic in ts.Style)    then s := s+'</i>';
  442.     if (fsBold in ts.Style)      then s := s+'</b>';
  443.   end;
  444.   if not Relative or (ts.Size<>normalts.Size) or (ts.Color<>normalts.Color) or
  445.     (AnsiCompareText(ts.FontName,normalts.FontName)<>0) then
  446.     s:= s+'</font>';
  447.   Result := s;
  448. end;
  449. {------------------------------------------------------------------------------}
  450. { Closes HTML tags opened in RV_HTMLOpenFontTag2                               }
  451. function RV_HTMLCloseFontTag2(fnt: TFont; normalts: TFontInfo; UseFontName: Boolean):String;
  452. var s: String;
  453. begin
  454.   if (fsStrikeOut in fnt.Style) and not (fsStrikeOut in normalts.Style) then s := s+'</s>';
  455.   if (fsUnderline in fnt.Style) and not (fsUnderline in normalts.Style) then s := s+'</u>';
  456.   if (fsItalic    in fnt.Style) and not (fsItalic    in normalts.Style) then s := s+'</i>';
  457.   if (fsBold      in fnt.Style) and not (fsBold      in normalts.Style) then s := s+'</b>';
  458.   if not (fsBold      in fnt.Style) and (fsBold      in normalts.Style) then s := s+'<b>';
  459.   if not (fsItalic    in fnt.Style) and (fsItalic    in normalts.Style) then s := s+'<i>';
  460.   if not (fsUnderline in fnt.Style) and (fsUnderline in normalts.Style) then s := s+'<u>';
  461.   if not (fsStrikeOut in fnt.Style) and (fsStrikeOut in normalts.Style) then s := s+'<s>';
  462.   if (fnt.Size<>normalts.Size) or (fnt.Color<>normalts.Color) or
  463.     (UseFontName and (AnsiCompareText(fnt.Name,normalts.FontName)<>0)) then
  464.     s:= s+'</font>';
  465.   Result := s;
  466. end;
  467. {------------------------------------------------------------------------------}
  468. {$IFNDEF RVDONOTUSEHTML}
  469. const SymbolEntities: array [$20..$FE] of PChar =
  470. (
  471.   ' ',
  472.   '!', 'forall', '#', 'exist', '%', '&', '?', '(', ')', '*',
  473.   '+', ',', '-', '.', '/', '0', '1', '2', '3', '4',
  474.   '5', '6', '7', '8', '9', ':', ';', '<', '=', '>',
  475.   '?', 'cong', 'Alpha', 'Beta', 'Chi', 'Delta', 'Epsilon', 'Phi', 'Gamma', 'Eta',
  476.   'Iota', '#977', 'Kappa', 'Lambda', 'Mu', 'Nu', 'Omicron', 'Pi', 'Theta', 'Rho',
  477.   'Sigma', 'Tau', 'Upsilon', 'sigmaf', 'Omega', 'Xi', 'Psi', 'Zeta', '[', 'there4',
  478.   ']', 'perp', '_', '-', 'alpha', 'beta', 'chi', 'delta', 'epsilon', '#981',
  479.   'gamma', 'eta', 'iota', 'phi', 'kappa', 'lambda', 'mu', 'nu', 'omicron', 'pi',
  480.   'theta', 'rho', 'sigma', 'tau', 'upsilon', '#982', 'omega', 'xi', 'psi', 'zeta',
  481.   '{', '|', '}', '~', '', '', '', '', '', '',
  482.   '', '', '', '', '', '', '', '', '', '',
  483.   '', '', '', '', '', '', '', '', '', '',
  484.   '', '', '', '', '', '', '', '', '#978', 'prime',
  485.   'le', 'frasl', 'infin', 'fnof', 'clubs', 'diams', 'hearts', 'spades', 'harr', 'larr',
  486.   'uarr', 'rarr', 'darr', '