RVFuncs.pas
上传用户:daoqigc
上传日期:2021-04-20
资源大小:2795k
文件大小:55k
- {*******************************************************}
- { }
- { RichView }
- { Miscellaneous procedures. }
- { }
- { Copyright (c) Sergey Tkachenko }
- { svt@trichview.com }
- { http://www.trichview.com }
- { }
- {*******************************************************}
- unit RVFuncs;
- interface
- {$I RV_Defs.inc}
- uses SysUtils, Windows, Classes, RVStyle, RVStr,
- {$IFNDEF RVDONOTUSEJPEGIMAGE}
- Jpeg,
- {$ENDIF}
- Graphics;
- const
- { Number of pixels in the screen inch. If 0 (default) - use screen resolution.
- Affects converting pixels to mm, inches, twips and vice versa:
- printing, RTF.
- Main possible values: 96 (small font mode), 120 (large font mode). }
- RichViewPixelsPerInch : Integer = 0;
- {--------------------------- Text & Tags ------------------------------------}
- function RV_CopyTag(SourceTag: Integer; TagsArePChars: Boolean): Integer;
- function RV_CompareTags(Tag1, Tag2: Integer; TagsArePChars: Boolean): Boolean;
- function RV_ReplaceTabsA(const s: String; SpacesInTab: Integer): String;
- function RV_ReplaceTabsW(const s: String; SpacesInTab: Integer): String;
- function RV_CharPos(const Str: PChar; Chr: Char; Length: Integer): Integer; assembler;
- procedure RV_ReplaceStr(var str: String; oldstr, newstr: String);
- function RV_GetHintStr(DocFormat: TRVSaveFormat; const Hint: String): String;
- {-------------------------- HTML functions ----------------------------------}
- function RV_GetHTMLRGBStr(Color: TColor; Quotes: Boolean): String;
- function RV_GetCSSBkColor(Color: TColor): String;
- function RV_GetHTMLPath(const Path: String; SaveOptions: TRVSaveOptions; CodePage: TRVCodePage): String;
- function RV_GetHTMLFontCSS(Font: TFont; UseFontName: Boolean): String;
- function RV_HTMLGetFontSize(pts: Integer): Integer;
- function RV_HTMLOpenFontTag(ts, normalts: TFontInfo; Relative: Boolean;
- SaveOptions: TRVSaveOptions): String;
- function RV_HTMLOpenFontTag2(fnt: TFont; normalts: TFontInfo; UseFontName: Boolean;
- SaveOptions: TRVSaveOptions): String;
- function RV_HTMLCloseFontTag(ts: TFontInfo; normalts: TFontInfo; Relative: Boolean):String;
- function RV_HTMLCloseFontTag2(fnt: TFont; normalts: TFontInfo;
- UseFontName: Boolean):String;
- {$IFNDEF RVDONOTUSEHTML}
- function RV_MakeHTMLSymbolStr(const s: String): String;
- function RV_MakeHTMLSymbolStrRaw(const s: String): String;
- function RV_MakeHTMLStr(const str:String; SpecialCode:Boolean): String;
- {$IFDEF RICHVIEWCBDEF3}
- function RV_CharSet2HTMLLang(CharSet: TFontCharset): String;
- {$ENDIF}
- {$ENDIF}
- function RV_DecodeURL(const s: String): String;
- function RV_HTMLGetEndingSlash(SaveOptions: TRVSaveOptions): String;
- function RV_HTMLGetNoValueAttribute(const Attr: String; SaveOptions: TRVSaveOptions): String;
- function RV_HTMLGetIntAttrVal(Value: Integer; SaveOptions: TRVSaveOptions): String;
- function RV_HTMLGetStrAttrVal(const Value: String; SaveOptions: TRVSaveOptions): String;
- {-------------------------- RTF functions -----------------------------------}
- {$IFNDEF RVDONOTUSERTF}
- function RVMakeRTFStr(const s:String; SpecialCode, UseNamedEntities: Boolean): String;
- function RVMakeRTFFileNameStr(const s:String): String;
- function MakeRTFIdentifierStr(const s:String): String;
- function MakeRTFBookmarkNameStr(const s:String): String;
- procedure RVWriteUnicodeRTFStr(Stream: TStream; const s: String;
- CodePage: TRVCodePage; SaveAnsi, SpecialCode: Boolean);
- {$ENDIF}
- {-------------------------- URL Detection -------------------------------------}
- function RVIsURL(const s: String): Boolean;
- function RVIsEmail(const s: String): Boolean;
- {---------------------- Conversion of coordinates ---------------------------}
- function RV_XToDevice(X: Integer; const sad: TRVScreenAndDevice): Integer;
- function RV_YToDevice(Y: Integer; const sad: TRVScreenAndDevice): Integer;
- function RV_XToScreen(X: Integer; const sad: TRVScreenAndDevice): Integer;
- function RV_YToScreen(Y: Integer; const sad: TRVScreenAndDevice): Integer;
- procedure RV_RectToScreen(var R: TRect; const sad: TRVScreenAndDevice);
- procedure RV_InfoAboutSaD(var sad:TRVScreenAndDevice; Canvas: TCanvas);
- function RV_GetPixelsPerInch: Integer;
- function RV_PointInRect(X,Y: Integer; Left,Top,Width,Height: Integer): Boolean;
- {------------------------ Graphics & Colors ---------------------------------}
- function RV_CreateGraphicsDefault(GraphicClass: TGraphicClass): TGraphic;
- procedure RV_AfterImportGraphicDefault(Graphic: TGraphic);
- function RV_GetLuminance(Color: TColor): Integer;
- function RV_GetGray(Color: TColor): TColor;
- function RV_GetPrnColor(Color: TColor): TColor;
- function RV_GetColor(Color: TColor; ColorMode: TRVColorMode): TColor;
- function RV_GetBackColor(Color: TColor; ColorMode: TRVColorMode): TColor;
- function RV_IsGraphicTransparent(gr: TGraphic): Boolean;
- procedure RV_SetPaletteToPicture(gr: TGraphic; PLogPal: PLogPalette);
- procedure RV_PictureToDevice(Canvas: TCanvas; x,y, width, height: Integer;
- sad:TRVScreenAndDevice; gr: TGraphic; ToScreen: Boolean);
- { ---------------------------- Others -----------------------------------------}
- {$IFNDEF RICHVIEWCBDEF3}
- function ExtractRelativePath(const BaseName, DestName: string): string;
- {$ENDIF}
- procedure RV_AddStr(var s1: String; const s2: String);
- type
- TRV_CreateGraphicsFunction = function (GraphicClass: TGraphicClass): TGraphic;
- TRV_AfterImportGraphicsProc = procedure(Graphic: TGraphic);
- var
- { Procedure for creating graphic object by graphic class
- used as a workaround for D2-D5, CB1-CB5 bug (private constructor in
- TGraphic). Assign your own procedure if you use third-party graphic
- classes }
- RV_CreateGraphics: TRV_CreateGraphicsFunction;
- { Procedure for calling after importing external graphics from RTF documents }
- RV_AfterImportGraphic: TRV_AfterImportGraphicsProc;
- implementation
- uses RVFMisc, RVUni, CRVData;
- type SetOfChar = set of Char;
- procedure ReplaceChars(var str: String; Replacer: Char; Replaced: SetOfChar); forward;
- {=========================== Text & Tags ====================================}
- { Returns a copy of SourceTag. If TagsArePChars, it assumes that SourceTag is
- a pointer to ANSIZ string, creates a copy of this string and returns it }
- function RV_CopyTag(SourceTag: Integer; TagsArePChars: Boolean): Integer;
- begin
- if (SourceTag<>0) and TagsArePChars then
- Result := Integer(StrNew(PChar(SourceTag)))
- else
- Result := SourceTag;
- end;
- {------------------------------------------------------------------------------}
- { Returns true if Tag1 is equal to Tag2. If TagsArePChars, tags are compared
- as strings, otherwise as integers }
- function RV_CompareTags(Tag1, Tag2: Integer; TagsArePChars: Boolean): Boolean;
- begin
- if TagsArePChars then
- if (Tag1=0) then
- if (Tag2=0) then
- Result := True
- else
- Result := False
- else
- if (Tag2=0) then
- Result := False
- else
- Result := StrComp(PChar(Tag1),PChar(Tag2))=0
- else
- Result := Tag1=Tag2;
- end;
- {------------------------------------------------------------------------------}
- { Replaces all tabs (#9) with a sequence of SpacesInTab space characters }
- function RV_ReplaceTabsA(const s: String; SpacesInTab: Integer): String;
- var p: Integer;
- spaces: String;
- begin
- Result := s;
- p := Pos(#9,Result);
- if p<>0 then begin
- SetLength(spaces,SpacesInTab);
- FillChar(PChar(spaces)^, SpacesInTab, ' ');
- end;
- while p<>0 do begin
- Delete(Result,p,1);
- Insert(spaces,Result,p);
- p := Pos(#9,Result);
- end;
- end;
- {------------------------------------------------------------------------------}
- { The same for unicode string (represented as "raw unicode") }
- function RV_ReplaceTabsW(const s: String; SpacesInTab: Integer): String;
- var i,p: Integer;
- spaces: String;
- begin
- Result := s;
- p := Pos(#9#0,Result);
- if p<>0 then begin
- SetLength(spaces,SpacesInTab*2);
- FillChar(PChar(spaces)^, SpacesInTab*2, 0);
- for i := 1 to SpacesInTab do
- spaces[(i-1)*2+1] := ' ';
- end;
- while p<>0 do begin
- Delete(Result,p,2);
- Insert(spaces,Result,p);
- p := Pos(#9#0,Result);
- end;
- end;
- {------------------------------------------------------------------------------}
- { Returns index of character (Chr) in string (Str) having length Length.
- Returns 0 if not found. Otherwise index of the first occurence of the character
- (1-based). }
- function RV_CharPos(const Str: PChar {EAX}; Chr: Char {DL} ; Length: Integer {ECX}): Integer; assembler;
- asm
- TEST EAX,EAX
- JE @@2
- PUSH EDI
- PUSH EBX
- MOV EDI,Str
- MOV EBX,Str
- MOV AL,Chr
- REPNE SCASB
- MOV EAX,0
- JNE @@1
- MOV EAX,EDI
- SUB EAX,EBX
- @@1: POP EBX
- POP EDI
- @@2:
- end;
- {------------------------------------------------------------------------------}
- { Replaces in str all substrings oldstr with substring newstr.
- Case insensitive. Newstr CANNOT contain oldstr as a substring. }
- procedure RV_ReplaceStr(var str: String; oldstr, newstr: String);
- var p: Integer;
- begin
- while true do begin
- p := pos(oldstr, str);
- if p=0 then break;
- Delete(str,p, Length(oldstr));
- Insert(newstr, str, p);
- end;
- end;
- {------------------------------------------------------------------------------}
- { Replaces in str all substrings oldstr with substring newstr.
- Case insensitive. Newstr can contain oldstr as a substring. }
- procedure RV_ReplaceStr2(var str: String; oldstr, newstr: String);
- var p,ptr: Integer;
- s: String;
- begin
- s := str;
- ptr := 1;
- while true do begin
- p := pos(oldstr, s);
- if p=0 then break;
- inc(p, ptr-1);
- Delete(str,p, Length(oldstr));
- Insert(newstr, str, p);
- ptr := p+Length(newstr);
- s := Copy(str, ptr, Length(str)+1-ptr);
- end;
- end;
- {------------------------------------------------------------------------------}
- { Returns code for inserting hint (tool tip) in HTML and RTF }
- function RV_GetHintStr(DocFormat: TRVSaveFormat; const Hint: String): String;
- begin
- Result := Hint;
- if Result='' then
- exit;
- case DocFormat of
- rvsfHTML:
- begin
- {$IFNDEF RVDONOTUSEHTML}
- ReplaceChars(Result , '''', ['"']);
- Result := 'title="'+Result+'"';
- {$ENDIF}
- end;
- rvsfRTF:
- begin
- {$IFNDEF RVDONOTUSERTF}
- ReplaceChars(Result , '''', ['"']);
- Result := MakeRTFIdentifierStr(Result);
- Result := 'o "'+Result+'"';
- {$ENDIF}
- end;
- end;
- end;
- {========================== HTML functions ==================================}
- { Returns HTML representation of color ('#RRGGBB' string).
- For clNone, returns empty string.
- Processes clWindowText as clBlack. }
- function RV_GetHTMLRGBStr(Color: TColor; Quotes: Boolean): String;
- begin
- if Color=clWindowText then
- Color := clBlack;
- if Color=clNone then
- Result := ''
- else begin
- Result := LowerCase(IntToHex(ColorToRGB(Color),6));
- Result := '#'+System.Copy(Result,5,2)+System.Copy(Result,3,2)+System.Copy(Result,1,2);
- if Quotes then
- Result := '"'+Result+'"';
- end;
- end;
- {------------------------------------------------------------------------------}
- { The same as RV_GetHTMLRGBStr, but returns 'transparent' for clNone }
- function RV_GetCSSBkColor(Color: TColor): String;
- begin
- if Color=clNone then
- Result := 'transparent'
- else
- Result := RV_GetHTMLRGBStr(Color, False);
- end;
- {------------------------------------------------------------------------------}
- { Replaces all '' with '/' }
- function RV_GetHTMLPath(const Path: String; SaveOptions: TRVSaveOptions;
- CodePage: TRVCodePage): String;
- var i: Integer;
- begin
- Result := Path;
- for i := 1 to Length(Result) do
- if Result[i]='' then
- Result[i] := '/';
- if rvsoUTF8 in SaveOptions then
- Result := RVU_AnsiToUTF8(CodePage, Result);
- end;
- {------------------------------------------------------------------------------}
- { Special concatenation of two strings }
- procedure RV_AddStr(var s1: String; const s2: String);
- begin
- if s1<>'' then begin
- if s2<>'' then
- s1 := s1+' '+s2
- end
- else
- s1 := s2;
- end;
- {------------------------------------------------------------------------------}
- { Returns string describing the given font in CSS format }
- function RV_GetHTMLFontCSS(Font: TFont; UseFontName: Boolean): String;
- var s: String;
- begin
- Result := '';
- if fsBold in Font.Style then
- Result := 'font-weight: bold;';
- if fsItalic in Font.Style then
- RV_AddStr(Result, 'font-style: italic;');
- if Font.Size>0 then
- RV_AddStr(Result, Format('font-size: %dpt;',[Font.Size]))
- else
- RV_AddStr(Result, Format('font-size: %dpx;',[Font.Height]));
- if UseFontName then begin
- s := ''''+Font.Name+'''';
- if (AnsiCompareText(Font.Name, RVFONT_SYMBOL)=0) or
- (AnsiCompareText(Font.Name, RVFONT_WINGDINGS)=0) then
- s := '''Arial Unicode MS'', ''Lucida Sans Unicode'', ''Arial''';
- RV_AddStr(Result, Format('font-family: %s;',[s]));
- end;
- s := '';
- if fsUnderline in Font.Style then
- s := 'underline';
- if fsStrikeOut in Font.Style then
- RV_AddStr(s, 'line-through');
- if s<>'' then
- Result := Format('%s text-decoration: %s;',[Result,s]);
- Result := Format('%s color: %s;',[Result,RV_GetHTMLRGBStr(Font.Color, False)]);
- end;
- {------------------------------------------------------------------------------}
- { Converts the font size in points to the font size for HTML (without CSS).
- HTML uses 7 font sizes. }
- function RV_HTMLGetFontSize(pts: Integer): Integer;
- begin
- if pts<=8 then
- Result := 1
- else
- case pts of
- 9..10: Result := 2;
- 11..12: Result := 3;
- 13..14: Result := 4;
- 15..18: Result := 5;
- 19..24: Result := 6;
- else Result := 7;
- end;
- end;
- {------------------------------------------------------------------------------}
- { Returns opening HTML tags for formatting of text style ts.
- If Relative, it returns a difference in formatting between ts and normalts }
- function RV_HTMLOpenFontTag(ts, normalts: TFontInfo; Relative: Boolean;
- SaveOptions: TRVSaveOptions): String;
- var s: String;
- begin
- s := '';
- if not Relative or (ts.Size<>normalts.Size) then
- s := s+' size='+RV_HTMLGetIntAttrVal(RV_HTMLGetFontSize(ts.Size), SaveOptions);
- if not Relative or (ts.Color<>normalts.Color) then
- s := s+' color='+RV_GetHTMLRGBStr(ts.Color, True);
- if not Relative or (AnsiCompareText(ts.FontName,normalts.FontName)<>0) then
- s := s+' face="'+ts.FontName+'"';
- if s<>'' then
- s := '<font'+s+'>';
- if Relative then begin
- if not (fsStrikeOut in ts.Style) and (fsStrikeOut in normalts.Style) then s := s+'</s>';
- if not (fsUnderline in ts.Style) and (fsUnderline in normalts.Style) then s := s+'</u>';
- if not (fsItalic in ts.Style) and (fsItalic in normalts.Style) then s := s+'</i>';
- if not (fsBold in ts.Style) and (fsBold in normalts.Style) then s := s+'</b>';
- if (fsBold in ts.Style) and not (fsBold in normalts.Style) then s := s+'<b>';
- if (fsItalic in ts.Style) and not (fsItalic in normalts.Style) then s := s+'<i>';
- if (fsUnderline in ts.Style) and not (fsUnderline in normalts.Style) then s := s+'<u>';
- if (fsStrikeOut in ts.Style) and not (fsStrikeOut in normalts.Style) then s := s+'<s>';
- end
- else begin
- if (fsBold in ts.Style) then s := s+'<b>';
- if (fsItalic in ts.Style) then s := s+'<i>';
- if (fsUnderline in ts.Style) then s := s+'<u>';
- if (fsStrikeOut in ts.Style) then s := s+'<s>';
- end;
- if ts.VShift < 0 then
- s := s+'<sub>'
- else if ts.VShift > 0 then
- s := s+'<sup>';
- Result := s;
- end;
- {------------------------------------------------------------------------------}
- { The same as RV_HTMLOpenFontTag(..., True), but formatting is defined by
- fnt: TFont }
- function RV_HTMLOpenFontTag2(fnt: TFont; normalts: TFontInfo;
- UseFontName: Boolean; SaveOptions: TRVSaveOptions): String;
- var s: String;
- begin
- s := '';
- if (fnt.Size<>normalts.Size) then
- s := s+' size='+RV_HTMLGetIntAttrVal(RV_HTMLGetFontSize(fnt.Size), SaveOptions);
- if (fnt.Color<>normalts.Color) then
- s := s+' color='+RV_GetHTMLRGBStr(fnt.Color, True);
- if UseFontName and (AnsiCompareText(fnt.Name,normalts.FontName)<>0) then
- s := s+' face="'+fnt.Name+'"';
- if s<>'' then
- s := '<font'+s+'>';
- if not (fsStrikeOut in fnt.Style) and (fsStrikeOut in normalts.Style) then s := s+'</s>';
- if not (fsUnderline in fnt.Style) and (fsUnderline in normalts.Style) then s := s+'</u>';
- if not (fsItalic in fnt.Style) and (fsItalic in normalts.Style) then s := s+'</i>';
- if not (fsBold in fnt.Style) and (fsBold in normalts.Style) then s := s+'</b>';
- if (fsBold in fnt.Style) and not (fsBold in normalts.Style) then s := s+'<b>';
- if (fsItalic in fnt.Style) and not (fsItalic in normalts.Style) then s := s+'<i>';
- if (fsUnderline in fnt.Style) and not (fsUnderline in normalts.Style) then s := s+'<u>';
- if (fsStrikeOut in fnt.Style) and not (fsStrikeOut in normalts.Style) then s := s+'<s>';
- Result := s;
- end;
- {------------------------------------------------------------------------------}
- { Closes HTML tags opened in RV_HTMLOpenFontTag }
- function RV_HTMLCloseFontTag(ts: TFontInfo; normalts: TFontInfo; Relative: Boolean):String;
- var s: String;
- begin
- if ts.VShift < 0 then
- s := s+'</sub>'
- else if ts.VShift > 0 then
- s := s+'</sup>';
- if Relative then begin
- if (fsStrikeOut in ts.Style) and not (fsStrikeOut in normalts.Style) then s := s+'</s>';
- if (fsUnderline in ts.Style) and not (fsUnderline in normalts.Style) then s := s+'</u>';
- if (fsItalic in ts.Style) and not (fsItalic in normalts.Style) then s := s+'</i>';
- if (fsBold in ts.Style) and not (fsBold in normalts.Style) then s := s+'</b>';
- if not (fsBold in ts.Style) and (fsBold in normalts.Style) then s := s+'<b>';
- if not (fsItalic in ts.Style) and (fsItalic in normalts.Style) then s := s+'<i>';
- if not (fsUnderline in ts.Style) and (fsUnderline in normalts.Style) then s := s+'<u>';
- if not (fsStrikeOut in ts.Style) and (fsStrikeOut in normalts.Style) then s := s+'<s>';
- end
- else begin
- if (fsStrikeOut in ts.Style) then s := s+'</s>';
- if (fsUnderline in ts.Style) then s := s+'</u>';
- if (fsItalic in ts.Style) then s := s+'</i>';
- if (fsBold in ts.Style) then s := s+'</b>';
- end;
- if not Relative or (ts.Size<>normalts.Size) or (ts.Color<>normalts.Color) or
- (AnsiCompareText(ts.FontName,normalts.FontName)<>0) then
- s:= s+'</font>';
- Result := s;
- end;
- {------------------------------------------------------------------------------}
- { Closes HTML tags opened in RV_HTMLOpenFontTag2 }
- function RV_HTMLCloseFontTag2(fnt: TFont; normalts: TFontInfo; UseFontName: Boolean):String;
- var s: String;
- begin
- if (fsStrikeOut in fnt.Style) and not (fsStrikeOut in normalts.Style) then s := s+'</s>';
- if (fsUnderline in fnt.Style) and not (fsUnderline in normalts.Style) then s := s+'</u>';
- if (fsItalic in fnt.Style) and not (fsItalic in normalts.Style) then s := s+'</i>';
- if (fsBold in fnt.Style) and not (fsBold in normalts.Style) then s := s+'</b>';
- if not (fsBold in fnt.Style) and (fsBold in normalts.Style) then s := s+'<b>';
- if not (fsItalic in fnt.Style) and (fsItalic in normalts.Style) then s := s+'<i>';
- if not (fsUnderline in fnt.Style) and (fsUnderline in normalts.Style) then s := s+'<u>';
- if not (fsStrikeOut in fnt.Style) and (fsStrikeOut in normalts.Style) then s := s+'<s>';
- if (fnt.Size<>normalts.Size) or (fnt.Color<>normalts.Color) or
- (UseFontName and (AnsiCompareText(fnt.Name,normalts.FontName)<>0)) then
- s:= s+'</font>';
- Result := s;
- end;
- {------------------------------------------------------------------------------}
- {$IFNDEF RVDONOTUSEHTML}
- const SymbolEntities: array [$20..$FE] of PChar =
- (
- ' ',
- '!', 'forall', '#', 'exist', '%', '&', '?', '(', ')', '*',
- '+', ',', '-', '.', '/', '0', '1', '2', '3', '4',
- '5', '6', '7', '8', '9', ':', ';', '<', '=', '>',
- '?', 'cong', 'Alpha', 'Beta', 'Chi', 'Delta', 'Epsilon', 'Phi', 'Gamma', 'Eta',
- 'Iota', '#977', 'Kappa', 'Lambda', 'Mu', 'Nu', 'Omicron', 'Pi', 'Theta', 'Rho',
- 'Sigma', 'Tau', 'Upsilon', 'sigmaf', 'Omega', 'Xi', 'Psi', 'Zeta', '[', 'there4',
- ']', 'perp', '_', '-', 'alpha', 'beta', 'chi', 'delta', 'epsilon', '#981',
- 'gamma', 'eta', 'iota', 'phi', 'kappa', 'lambda', 'mu', 'nu', 'omicron', 'pi',
- 'theta', 'rho', 'sigma', 'tau', 'upsilon', '#982', 'omega', 'xi', 'psi', 'zeta',
- '{', '|', '}', '~', '', '', '', '', '', '',
- '', '', '', '', '', '', '', '', '', '',
- '', '', '', '', '', '', '', '', '', '',
- '', '', '', '', '', '', '', '', '#978', 'prime',
- 'le', 'frasl', 'infin', 'fnof', 'clubs', 'diams', 'hearts', 'spades', 'harr', 'larr',
- 'uarr', 'rarr', 'darr', '