⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stylepars.pas

📁 查看html文件的控件
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{Version 9.4}
{*********************************************************}
{*                    STYLEPARS.PAS                      *}
{*               Copyright (c) 2001-2006 by              *}
{*                   L. David Baldwin                    *}
{*                 All rights reserved.                  *}
{*********************************************************}

{$i htmlcons.inc}

unit StylePars;

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Controls,
  Dialogs, StdCtrls, StyleUn;

type
  CharFunction = function: Char;

procedure DoStyle(Styles: TStyleList; var C: char; GC: CharFunction;
             const APath: string; FromLink: boolean);   
procedure ParsePropertyStr(const PropertyStr: string; var Propty: TProperties);
function SortContextualItems(S: string): string;   

implementation

uses Graphics, ReadHTML, UrlSubs, htmlun2;

const
  NeedPound = True;
  EofChar = #0;  

type
  TProcessProc = procedure (Obj: TObject; Selectors: TStringList; Prop, Value: string);

var
  LCh, Back: char;
  Get: CharFunction;
  LinkPath: string;

function GetC: char;
begin
if Back <> #0 then
  begin
  Result := Back;
  Back := #0;
  end
else Result := Get;
if Result = ^M then
  Result := ' ';
end;

procedure GetCh;
var
  Comment: boolean;
  NextCh: char;
begin
repeat    {in case a comment immediately follows another comment}
  Comment := False;
  LCh := GetC;
  if LCh = '/' then
    begin
    NextCh := GetC;
    if NextCh = '*' then
      repeat
        Comment := True;
        LCh := GetC;
        while (LCh <> '*') and (LCh <> EofChar) and (LCh <> '<') do
          LCh := GetC;
        if LCh <> '<' then
          LCh := GetC;
      until (LCh = '/') or (LCh = EofChar) or (LCh = '<')
    else Back := NextCh; {put character back}
    end;
until not Comment;
end;

{-------------SkipWhiteSpace}
procedure SkipWhiteSpace;
begin
while (LCh in [' ']) do
  GetCh;
end;

{----------------RemoveQuotes}
function RemoveQuotes(const S: string): string;
{if string is a quoted string, remove the quotes (either ' or ")}
begin
if (Length(S) >= 2) and (S[1] in ['''', '"']) and (S[Length(S)] = S[1]) then
  Result := Copy(S, 2, Length(S)-2)
else Result := S;
end;

{----------------AddPath}
function AddPath(S: string): string;
{for <link> styles, the path is relative to that of the stylesheet directory
 and must be added now}
begin
S := ReadUrl(S);   {extract the info from url(....) }
if (Pos('://', LinkPath) > 0) then  {it's TFrameBrowser and URL}
  if not IsFullUrl(S) then
    Result := Combine(LinkPath, S)
  else ReSult := S
else
  begin
  S := HTMLToDos(S);
  if (Pos(':', S) <> 2) and (Pos('\\', Result) <> 1) then
     Result := LinkPath + S
  else Result := S;
  end;
Result := 'url(' + Result + ')';
end;

{----------------ProcessProperty}
procedure ProcessProperty(Styles: TObject; Selectors: TStringList; Prop, Value: string);
var
  I: integer;
begin
for I := 0 to Selectors.Count-1 do
  (Styles as TStyleList).AddModifyProp(Selectors[I], Prop, Value);
end;

{---------  Detect Shorthand syntax }
type
  ShortIndex = (MarginX, PaddingX, BorderWidthX, BorderX,
                BorderTX, BorderRX, BorderBX, BorderLX,
                FontX, BackgroundX, ListStyleX, BorderColorX,
                BorderStyleX);    
var
  ShortHands: array[Low(ShortIndex)..High(ShortIndex)] of string =
     ('margin', 'padding', 'border-width', 'border',
      'border-top', 'border-right', 'border-bottom', 'border-left',
      'font', 'background', 'list-style', 'border-color',
      'border-style');        

function FindShortHand(S: string; var Index: ShortIndex): boolean;
var
  I: ShortIndex;
begin
for I := Low(ShortIndex) to High(ShortIndex) do
  if S = ShortHands[I] then
    begin
    Result := True;
    Index := I;
    Exit;
    end;
Result := False;
end;

procedure SplitString(Src: string; var Dest: array of string; var Count: integer);
{Split a Src string into pieces returned in the Dest string array.  Splitting
 is on spaces with spaces within quotes being ignored.  String containing a '/'
 are also split to allow for the "size/line-height" Font construct. }
var
  I, Q, Q1, N: integer;
  Z: string;
  Done: boolean;
  Match: char;
begin
Src := Trim(Src);
I := Pos('  ', Src);
while I > 0 do   {simplify operation by removing extra white space}
  begin
  Delete(Src, I+1, 1);
  I := Pos('  ', Src);
  end;
I := Pos(', ', Src);
while I > 0 do   {simplify operation by removing spaces after commas}
  begin
  Delete(Src, I+1, 1);
  I := Pos(', ', Src);
  end;

N := 0;
while (N <= High(Dest)) and (Src <> '') do
  begin
  Z := '';
  repeat
    Done := True;
    I := Pos(' ', Src);
    Q := Pos('"', Src);
    Q1 := Pos('''', Src);
    if (Q1 > 0) and ((Q > 0) and (Q1 < Q) or (Q = 0)) then
      begin
      Q := Q1;
      Match := '''';   {the matching quote char}
      end
    else Match := '"';
    if I = 0 then
      begin
      Z := Z + Src;
      Src := '';
      end
    else if (Q=0) or (I<Q) then
      begin
      Z := Z + Copy(Src, 1, I-1);
      Delete(Src, 1, I);
      end
    else    {Q<I}  {quoted string found}
      begin
      Z := Z + Copy(Src, 1, Q);  {copy to quote}
      Delete(Src, 1, Q);
      Q := Pos(Match, Src);   {find next quote}
      if Q > 0 then
        begin
        Z := Z+Copy(Src, 1, Q); {copy to second quote}
        Delete(Src, 1, Q);
        Done := False;  {go back and find the space}
        end
      else        {oops, missing second quote, copy remaining}
        begin
        Z := Z + Src;
        Src := '';
        end;
      end;
  until Done;
  I := Pos('/', Z);    {look for splitter for Line-height}
  if I >= 2 then
    begin         {this part is font size}
    Dest[N] := Copy(Z, 1, I-1);
    Delete(Z, 1, I-1);
    Inc(N);
    end;
  if N <= High(Dest) then
    Dest[N] := Z;
  Inc(N);
  end;
Count := N;
end;

procedure ExtractParn(var Src: string; var Dest: array of string; var Count: integer);
{Look for strings in parenthesis like "url(....)" or rgb(...)".  Return these in
 Dest Array.  Return Src without the extracted string}
var
  I, J: integer;

begin
Count := 0;
while (Count <= High(Dest)) and (Src <> '') do
  begin
  I := Pos('url(', Src);
  if I = 0 then
    I := Pos('rgb(', Src);
  if I = 0 then
    Exit;
  J := Pos(')', Src);
  if (J = 0) or (J < I) then
    Exit;
  Dest[Count] := Copy(Src, I, J-I+1);
  Delete(Src, I, J-I+1);
  Inc(Count);
  end;
end;

{$ifndef ver120_plus}
{Delphi 3 doesn't like this to be inside DoFont}
type
  FontEnum =
    (italic, oblique, normal, bolder, lighter, bold, smallcaps,
     larger, smaller, xxsmall, xsmall, small, medium, large,
     xlarge, xxlarge);
const
  FontWords: array[italic..xxlarge] of string =
    ('italic', 'oblique', 'normal', 'bolder', 'lighter', 'bold', 'small-caps',
     'larger', 'smaller', 'xx-small', 'x-small', 'small', 'medium', 'large',
     'x-large', 'xx-large');
{$endif}

procedure DoFont(Styles: TObject; Selectors: TStringList; Prop, Value: string;
             Process: TProcessProc);
{ do the Font shorthand property specifier }
{$ifdef ver120_plus}
type
  FontEnum =
    (italic, oblique, normal, bolder, lighter, bold, smallcaps,
     larger, smaller, xxsmall, xsmall, small, medium, large,
     xlarge, xxlarge);
const
  FontWords: array[italic..xxlarge] of string =
    ('italic', 'oblique', 'normal', 'bolder', 'lighter', 'bold', 'small-caps',
     'larger', 'smaller', 'xx-small', 'x-small', 'small', 'medium', 'large',
     'x-large', 'xx-large');
{$endif}
var
  S: array[0..6] of string;
  Count, I: integer;
  Index: FontEnum;

  function FindWord(const S: string; var Index: FontEnum):boolean;
  var
    I: FontEnum;
  begin
  Result := False;
  for I := Low(FontEnum) to High(FontEnum) do
    if FontWords[I] = S then
      begin
      Result := True;
      Index := I;
      Exit;
      end;
  end;

begin
SplitString(Value, S, Count);
for I := 0 to Count-1 do
  begin
  if S[I,1] = '/' then
    begin
    Process(Styles, Selectors, 'line-height', Copy(S[I], 2, Length(S[I])-1));
    Continue;
    end;
  if FindWord(S[I], Index) then
    begin
    case Index of
      italic, oblique:
        Process(Styles, Selectors, 'font-style', S[I]);
      normal..bold:
        Process(Styles, Selectors, 'font-weight', S[I]);
      smallcaps:
        Process(Styles, Selectors, 'font-variant', S[I]);
      larger..xxlarge:
        Process(Styles, Selectors, 'font-size', S[I]);
      end;
    continue;
    end;
  if S[I,1] in ['0'..'9'] then
    Process(Styles, Selectors, 'font-size', S[I])
  else
    Process(Styles, Selectors, 'font-family', S[I])
  end;
end;

procedure DoBackground(Styles: TObject; Selectors: TStringList; Prop, Value: string;
             Process: TProcessProc);
{ do the Background shorthand property specifier }
var
  S: array[0..6] of string;
  S1: string;
  Count, I, N: integer;
  Dummy: TColor;

begin
ExtractParn(Value, S, Count);
for I := 0 to Count-1 do
  begin
  if Pos('rgb(', S[I]) > 0 then
    Process(Styles, Selectors, 'background-color', S[I])
  else if (Pos('url(', S[I]) > 0) then
    begin
    if LinkPath <> '' then  {path added now only for <link...>}
      S[I] := AddPath(S[I]);
    Process(Styles, Selectors, 'background-image', S[I]);
    end;
  end;
SplitString(Value, S, Count);
for I := 0 to Count-1 do
  if ColorFromString(S[I], NeedPound, Dummy) then
    begin
    Process(Styles, Selectors, 'background-color', S[I]);
    S[I] := '';
    end
  else if S[I] = 'none' then
    begin
    Process(Styles, Selectors, 'background-image', S[I]);
    S[I] := '';
    end;
for I := 0 to Count-1 do
  if Pos('repeat', S[I]) > 0 then
    begin
    Process(Styles, Selectors, 'background-repeat', S[I]);
    S[I] := '';
    end;
for I := 0 to Count-1 do     
  if (S[I] = 'fixed') or (S[I] = 'scroll') then
    begin
    Process(Styles, Selectors, 'background-attachment', S[I]);
    S[I] := '';
    end;
N := 0;  S1 := '';  {any remaining are assumed to be position info}
for I := Count-1 downto 0 do
  if S[I] <> '' then
    begin
    S1 := S[I]+' '+S1;
    Inc(N);
    if N >= 2 then Break;  {take only last two}
    end;
if S1 <> '' then
  Process(Styles, Selectors, 'background-position', S1);
end;

procedure DoBorder(Styles: TObject; Selectors: TStringList; Prop, Value: string;
             Process: TProcessProc);
{ do the Border, Border-Top/Right/Bottom/Left shorthand properties.  However, there
  currently is only one style and color supported for all border sides }
var
  S: array[0..6] of string;
  Count, I: integer;
  Dummy: TColor;

  function FindStyle(const S: string): boolean;
  const
    Ar: array[1..9] of string = ('none', 'solid', 'dashed', 'dotted', 'double', 'groove',
        'inset', 'outset', 'ridge');
  var
    I: integer;
  begin
  for I := 1 to 9 do
    if S = Ar[I] then
      begin
      Result := True;
      Exit;
      end;
  Result := False;
  end;

begin
ExtractParn(Value, S, Count);
for I := 0 to Count-1 do
  if ColorFromString(S[I], NeedPound, Dummy) then
    Process(Styles, Selectors, Prop+'-color', S[I]);

SplitString(Value, S, Count);
for I := 0 to Count-1 do
  begin
  if ColorFromString(S[I], NeedPound, Dummy) then
    Process(Styles, Selectors, Prop+'-color', S[I])
  else if FindStyle(S[I]) then
    Process(Styles, Selectors, Prop+'-style', S[I])  {Border-Style will change all four sides}
  else if Prop = 'border' then
    begin
    Process(Styles, Selectors, 'border-top-width', S[I]);
    Process(Styles, Selectors, 'border-right-width', S[I]);
    Process(Styles, Selectors, 'border-bottom-width', S[I]);
    Process(Styles, Selectors, 'border-left-width', S[I]);
    end
  else
    Process(Styles, Selectors, Prop+'-width', S[I]);
  end;
end;

procedure DoListStyle(Styles: TObject; Selectors: TStringList; Prop, Value: string;
             Process: TProcessProc);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -