, which have
attributes.
Section:
The current section being built.
SectionList:
The list of sections which form the document. When in a Table,
SectionList will contain the list that makes up the current cell.
Key Routines:
GetCh:
Gets the next character from the stream. Fills Ch and LCh. Skips
comments.
Next:
Gets the next token. Fills Sy, LCToken, Attributes. Calls GetCh so the
next character after the present token is available. Each part of the
parser is responsible for calling Next after it does its thing.
}
unit LitePars;
interface
uses
{$IFDEF HL_LAZARUS}
Classes, SysUtils, LCLType, Messages, GraphType, Graphics, Controls,
Dialogs, StdCtrls, LiteUn2, LiteSubs, LiteSbs1;
{$ELSE}
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Dialogs, StdCtrls, LiteUn2, LiteSubs, LiteSbs1;
{$ENDIF}
const
MaxStack = 25;
FontConv: array[1..7] of integer = (8,10,12,14,18,24,36);
PreFontConv: array[1..7] of integer = (7,8,10,12,15,20,30);
type
LoadStyleType = (lsPrimary, lsInclude);
TIncludeType = procedure(Sender: TObject; const Command: string;
Params: TStrings; var IString: string) of Object;
TSoundType = procedure(Sender: TObject; const SRC: string; Loop: integer;
Terminate: boolean) of Object;
TMetaType = procedure(Sender: TObject; const HttpEq, Name, Content: string) of Object;
SymbSet = Set of Symb;
TLastChar = (lcOther, lcCR, lcLF);
ThlParser = Class
private
Sy : Symb;
PreFormat: boolean; {set when doing preformat text}
Justify: JustifyType;
BaseFontSize: integer;
InScript: boolean; {when in a ') = 0 then
Sy := ScriptEndSy;
end;
begin {already have fresh character loaded here}
LCToken.Clear;
if LCh = EofChar then Sy := EofSy
else if LCh = ^M then
begin
Sy := EolSy;
GetCh;
end
else if LCh = '<' then
GetTag1
else
begin
Sy := TextSy;
while (Length(LCToken.S) < 100) and not (LCh in [^M, '<', EofChar]) do
begin
LCToken.AddChar(LCh, SIndex);
GetCh;
end;
end;
end;
begin
try
if Assigned(AScript) then
begin
InScript := True;
if Attributes.Find(LanguageSy, T) then
Lang := T.Name
else Lang := '';
if Attributes.Find(NameSy, T) then
AName := T.Name
else AName := '';
GetMem(Buffer, Block);
Pos := 0;
Size := Block;
try
Next1;
while (Sy <> ScriptEndSy) and (Sy <> EofSy) do
begin
if Sy = EolSy then AddText(^M^J)
else
AddText(LCToken.S);
Next1;
end;
AddText(#0);
ReAllocMem(Buffer, Size);
AScript(CallingObject, AName, Lang, Buffer);
except
FreeMem(Buffer);
Raise;
end;
end
else
begin
repeat
Next1;
until Sy in [ScriptEndSy, EofSy];
end;
finally
InScript := False;
end;
end;
{----------------DoCommonSy}
procedure ThlParser.DoCommonSy(Lev: integer);
var
I: integer;
TxtArea: TTextAreaFormControlObj;
FormControl: TFormControlObj;
T: TAttribute;
TmpJustify, LastAlign: JustifyType;
Tmp: string;
function IncrementFont(Sy: Symb; Pre: boolean): boolean;
var
NewSize: integer;
function GetSizeIndex(Pre: boolean; Size: integer): integer;
begin
for Result := 1 to 7 do
if Pre and (Size = PreFontConv[Result]) then Exit
else if Size = FontConv[Result] then Exit;
Result := -1;
end;
begin
Result := False;
NewSize := GetSizeIndex(Pre, FontStack[StackIndex].NormalSize);
if (Sy = BigSy) then
begin
if (NewSize in [1..6]) then Inc(NewSize);
end
else
if NewSize in [2..7] then Dec(NewSize);
if PushNewFont then
begin
if Pre then NewSize := PreFontConv[NewSize]
else NewSize := FontConv[NewSize];
FontStack[StackIndex].SetNormalSize(MasterList, NewSize);
Result := True;
end;
end;
function ChangeTheFont(Sy: Symb; Pre: boolean): boolean;
var
FaceName: string[50];
NewColor: TColor;
NewSize, I, K: integer;
FontResults: set of (Face, Colr, Siz);
begin
FontResults := [];
NewSize := 0; {get rid of warning}
for I := 0 to Attributes.Count-1 do
with TAttribute(Attributes[I]) do
case Which of
SizeSy:
begin
if (Length(Name) >= 2) and (Name[1] in ['+', '-']) then
Value := BaseFontSize + Value;
NewSize := IntMax(1, IntMin(7, Value)); {limit 1..7}
if (Sy = BaseFontSy) then BaseFontSize := NewSize;
Include(FontResults, Siz);
end;
ColorSy:
if (Sy <> BaseFontSy) and GetColor(Name, NewColor) then Include(FontResults, Colr);
FaceSy:
if (Sy <> BaseFontSy) and (Name <> '') then
begin
FaceName := Name;
K := Pos(',', FaceName);
if K > 0 then
Delete(FaceName, K, 255);
FaceName := Trim(FaceName);
if FaceName <> '' then
Include(FontResults, Face);
end;
end;
Result := False;
if ((Sy <> BasefontSy) or (SectionList.Count = 0) and
(SectionList = MasterList)) and {new font only if at start for Basefont}
PushNewFont and (FontResults <> []) then
with FontStack[StackIndex] do
begin
if Colr in FontResults then
Color := NewColor or $2000000;
if Siz in FontResults then
begin
if Pre then NewSize := PreFontConv[NewSize]
else NewSize := FontConv[NewSize];
SetNormalSize(MasterList, NewSize);
end;
if Face in FontResults then
Name := FaceName;
Result := True;
end;
end;
procedure DoPreSy;
var
S: TokenObj;
Tmp: String;
Done: boolean;
I, InitialStackIndex: integer;
procedure NewSection;
begin
Section.AddTokenObj(S, NoBreak);
S.Clear;
SectionList.Add(Section);
Section := TPreFormated.Create(MasterList, Lev, FontStack[StackIndex],
CurrentUrlTarget, Left);
end;
begin
S := TokenObj.Create;
try
SectionList.Add(Section);
PushNewFont;
InitialStackIndex := StackIndex;
with FontStack[StackIndex] do
begin
Name := MasterList.PreFontName;
SetNormalSize(MasterList, 10);
Fixed := True;
end;
Section := TPreformated.Create(MasterList, Lev, FontStack[StackIndex],
CurrentUrlTarget, Left);
S.Clear;
PreFormat := True;
Done := False;
while not Done do
case Ch of
'&': begin
Next;
S.Concat(LCToken);
end;
'<':
begin
Next;
case Sy of
PSy, BRSy:
begin
NewSection;
if Ch = ^M then GetCh;
end;
PreEndSy, TDEndSy, THEndSy:
Done := True;
BSy, ISy, BEndSy, IEndSy, EmSy, EmEndSy, StrongSy, StrongEndSy,
USy, UEndSy, CiteSy, CiteEndSy, VarSy, VarEndSy,
SSy, SEndSy, StrikeSy, StrikeEndSy:
begin
Section.AddTokenObj(S, NoBreak);
S.Clear;
case Sy of
BSy, StrongSy: CurrentStyle := CurrentStyle + [fsBold];
BEndSy, StrongEndSy: CurrentStyle := CurrentStyle - [fsBold];
ISy, EmSy, CiteSy, VarSy: CurrentStyle := CurrentStyle + [fsItalic];
IEndSy, EmEndSy,
CiteEndSy, VarEndSy: CurrentStyle := CurrentStyle - [fsItalic];
USy: CurrentStyle := CurrentStyle + [fsUnderline];
UEndSy: CurrentStyle := CurrentStyle - [fsUnderline];
SSy, StrikeSy: CurrentStyle := CurrentStyle + [fsStrikeOut];
SEndSy, StrikeEndSy: CurrentStyle := CurrentStyle - [fsStrikeOut];
end;
TSection(Section).ChangeFont(MasterList, FontStack[StackIndex]);
end;
FontSy, BaseFontSy:
begin
Section.AddTokenObj(S, NoBreak);
S.Clear;
if ChangeTheFont(Sy, True) then
TSection(Section).ChangeFont(MasterList, FontStack[StackIndex]);
end;
FontEndSy:
if StackIndex > InitialStackIndex then
begin
PopFont;
Section.AddTokenObj(S, NoBreak);
S.Clear;
TSection(Section).ChangeFont(MasterList, FontStack[StackIndex]);
end;
ASy:
for I := 0 to Attributes.Count-1 do
with TAttribute(Attributes[I]) do
case Which of
NameSy:
if Name <> '' then
begin
Tmp := UpperCase(Name);
{Author may have added '#' by mistake}
if (Length(Tmp) > 0) and (Tmp[1] = '#') then
Delete(Tmp, 1, 1);
NameList.AddObject(Tmp, Section);
end;
HRefSy:
begin
Section.AddTokenObj(S, NoBreak);
S.Clear;
if InHref then DoAEnd;
if Name <> '' then {also have a string}
begin
if Attributes.Find(TargetSy, T) then
CurrentUrlTarget.Assign(Name, T.Name)
else CurrentUrlTarget.Assign(Name, '');
InHref := True;
PushNewFont;
with FontStack[StackIndex] do
begin
Style := Style + MasterList.UnLine;
Color := MasterList.HotSpotColor;
end;
end;
Section.HRef(HRefSy, MasterList, CurrentUrlTarget, FontStack[StackIndex]);
end;
end;
AEndSy:
begin
Section.AddTokenObj(S, NoBreak);
S.Clear;
DoAEnd;
end;
ImageSy:
begin
Section.AddTokenObj(S, NoBreak);
TSection(Section).AddImage(Attributes, SectionList, TagIndex, NoBreak);
S.Clear;
end;
InputSy, SelectSy:
begin
Section.AddTokenObj(S, NoBreak);
FormControl := TSection(Section).AddFormControl(Sy, MasterList,
Attributes, SectionList, TagIndex, NoBreak);
if Sy = SelectSy then
GetOptions(FormControl as TListBoxFormControlObj);
S.Clear;;
end;
TextAreaSy:
Begin
Section.AddTokenObj(S, NoBreak);
TxtArea := TSection(Section).AddFormControl(TextAreaSy, MasterList,
Attributes, SectionList, TagIndex, NoBreak) as TTextAreaFormControlObj;
DoTextArea(TxtArea);
S.Clear;
end;
FormSy:
CurrentForm := ThtmlForm.Create(MasterList, Attributes);
FormEndSy:
CurrentForm := Nil;
MapSy: DoMap;
ScriptSy: DoScript(MasterList.ScriptEvent);
end;
end;
^M : begin NewSection; GetCh; end;
EofChar : Done := True;
else
begin {all other chars}
S.AddChar(LCh, SIndex);
if Length(S.S) > 200 then
begin
Section.AddTokenObj(S, NoBreak);
S.Clear;
end;
GetCh;
end;
end;
Section.AddTokenObj(S, NoBreak);
SectionList.Add(Section);
Section := Nil;
PreFormat := False;
while StackIndex >= InitialStackIndex do
PopFont;
Next;
finally
S.Free;
end;
end;
function CreateFont(HeadNmb: integer; OldFont: TMyFont): TMyFont;
var
F : TMyFont;
Siz: integer;
begin
F := TMyFont.Create;
F.Assign(OldFont);
case HeadNmb of
0: Siz := 12; {0 is no heading}
1: Siz := 24;
2: Siz := 18;
3: Siz := 14;
4: Siz := 12;
5: Siz := 10;
6: Siz := 8;
else Siz := 12;
end;
if HeadNmb > 0 then
F.Style := F.Style + [fsBold];
F.SetNormalSize(MasterList, Siz);
Result := F;
end;
begin
writeln('ThlParser.DoCommonSy A ',SymbNames[Sy]);
case Sy of
TextSy :
begin
writeln('ThlParser.DoCommonSy B ',Assigned(Section),' ',LCToken.S);
if not Assigned(Section) then
Section := TSection.Create(MasterList, Lev, FontStack[StackIndex],
CurrentUrlTarget, Justify);
Section.AddTokenObj(LCToken, NoBreak);
Next;
end;
ImageSy:
begin
if not Assigned(Section) then
Section := TSection.Create(MasterList, Lev, FontStack[StackIndex],
CurrentUrlTarget, Justify);
TSection(Section).AddImage(Attributes, SectionList, TagIndex, NoBreak);
Next;
end;
InputSy, SelectSy:
begin
if not Assigned(Section) then
Section := TSection.Create(MasterList, Lev, FontStack[StackIndex],
CurrentUrlTarget, Justify);
FormControl := TSection(Section).AddFormControl(Sy, MasterList, Attributes, SectionList, TagIndex, NoBreak);
if Sy = SelectSy then
GetOptions(FormControl as TListBoxFormControlObj);
Next;
end;
TextAreaSy:
Begin
if not Assigned(Section) then
Section := TSection.Create(MasterList, Lev, FontStack[StackIndex],
CurrentUrlTarget, Justify);
TxtArea := TSection(Section).AddFormControl(TextAreaSy, MasterList,
Attributes, SectionList, TagIndex, NoBreak) as TTextAreaFormControlObj;
DoTextArea(TxtArea);
Next;
end;
TextAreaEndSy: {a syntax error but shouldn't hang}
Next;
FormSy:
begin
CurrentForm := ThtmlForm.Create(MasterList, Attributes);
Next;
end;
FormEndSy:
begin
CurrentForm := Nil;
Next;
end;
PSy, PEndSy:
begin
SectionList.Add(Section);
Section := Nil;
if Not NoPSpace then
SectionList.Add(TParagraphSpace.Create(MasterList));
SkipWhiteSpace;
LastAlign := FindAlignment;
NoPSpace := True;
Next;
while Sy in [PSy, PEndSy] do
begin {recognize only the first }
LastAlign := FindAlignment; {if a series of
, get last alignment}
SkipWhiteSpace;
NoPSpace := True;
Next;
end;
Section := TSection.Create(MasterList, Lev, FontStack[StackIndex],
CurrentUrlTarget, LastAlign);
end;
BRSy:
begin
if Assigned(Section) then
TmpJustify := TSection(Section).BreakInfo(TagIndex, NoBreak) {so
doesn't change justification}
else TmpJustify := Justify;
SectionList.Add(Section);
Section := TSection.Create(MasterList, Lev, FontStack[StackIndex],
CurrentUrlTarget, TmpJustify);
Section.DoClearAttribute(Attributes); {check for clear attribute}
Next;
end;
NoBrSy, NoBrEndSy:
begin
NoBreak := Sy = NoBrSy;
if Assigned(Section) then
Section.AddTokenObj(LCToken, NoBreak);
Next;
end;
WbrSy:
begin
if Assigned(Section) and NoBreak then
Section.AddChar(' ', TagIndex, NoBreak);
Next;
end;
BSy, ISy, BEndSy, IEndSy, EmSy, EmEndSy, StrongSy, StrongEndSy,
USy, UEndSy, CiteSy, CiteEndSy, VarSy, VarEndSy,
SubSy, SubEndSy, SupSy, SupEndSy, SSy, SEndSy, StrikeSy, StrikeEndSy:
begin
case Sy of
BSy, StrongSy: CurrentStyle := CurrentStyle + [fsBold];
BEndSy, StrongEndSy: CurrentStyle := CurrentStyle - [fsBold];
ISy, EmSy, CiteSy, VarSy: CurrentStyle := CurrentStyle + [fsItalic];
IEndSy, EmEndSy,
CiteEndSy, VarEndSy: CurrentStyle := CurrentStyle - [fsItalic];
USy: CurrentStyle := CurrentStyle + [fsUnderline];
UEndSy: CurrentStyle := CurrentStyle - [fsUnderline];
SSy, StrikeSy: CurrentStyle := CurrentStyle + [fsStrikeOut];
SEndSy, StrikeEndSy: CurrentStyle := CurrentStyle - [fsStrikeOut];
SubEndSy, SupEndSy: CurrentSScript := Normal;
SubSy, SupSy:
begin
if not Assigned(Section) then
Section := TSection.Create(MasterList, Lev, FontStack[StackIndex],
CurrentUrlTarget, Justify);
if Sy = SubSy then CurrentSScript := SubSc
else CurrentSScript := SupSc;
end;
end;
if Assigned(Section) then {CurrentStyle used in ChangeFont}
TSection(Section).ChangeFont(MasterList, FontStack[StackIndex]);
Next;
end;
TTSy, CodeSy, KbdSy, SampSy:
begin
if PushNewFont then
begin
with FontStack[StackIndex] do
begin
Name := MasterList.PreFontName;
SetNormalSize(MasterList, 10);
Fixed := True;
end;
if Assigned(Section) then
TSection(Section).ChangeFont(MasterList, FontStack[StackIndex]);
end;
Next;
end;
TTEndSy, CodeEndSy, KbdEndSy, SampEndSy, FontEndSy, BigEndSy, SmallEndSy:
begin
PopFont;
if Assigned(Section) then
TSection(Section).ChangeFont(MasterList, FontStack[StackIndex]);
Next;
end;
FontSy, BaseFontSy:
begin
if ChangeTheFont(Sy, False) and Assigned(Section) then
TSection(Section).ChangeFont(MasterList, FontStack[StackIndex]);
Next;
end;
BigSy, SmallSy:
begin
if IncrementFont(Sy, False) and Assigned(Section) then
TSection(Section).ChangeFont(MasterList, FontStack[StackIndex]);
Next;
end;
AddressSy:
begin
SectionList.Add(Section);
PushNewFont;
with FontStack[StackIndex] do
Style := Style + [fsItalic];
Section := TSection.Create(MasterList, Lev, FontStack[StackIndex],
CurrentUrlTarget, Justify);
Next;
end;
AddressEndSy:
begin
SectionList.Add(Section);
Section := Nil;
PopFont;
Next;
end;
ASy:
begin
for I := 0 to Attributes.Count-1 do
with TAttribute(Attributes[I]) do
case Which of
NameSy:
if Name <> '' then
begin
if not Assigned(Section) then
Section := TSection.Create(MasterList, Lev, FontStack[StackIndex],
CurrentUrlTarget, Justify);
Tmp := UpperCase(Name);
{Author may have added '#' by mistake}
if (Length(Tmp) > 0) and (Tmp[1] = '#') then
Delete(Tmp, 1, 1);
NameList.AddObject(Tmp, Section);
end;
HRefSy:
begin
if InHref then DoAEnd;
if Name <> '' then {also have a string}
begin
if Attributes.Find(TargetSy, T) then
CurrentUrlTarget.Assign(Name, T.Name)
else CurrentUrlTarget.Assign(Name, '');
InHref := True;
PushNewFont;
with FontStack[StackIndex] do
begin
Style := Style + MasterList.UnLine;
Color := MasterList.HotSpotColor;
end;
if Assigned(Section) then
Section.HRef(HRefSy, MasterList, CurrentUrlTarget, FontStack[StackIndex]);
end;
end;
end;
Next;
end;
AEndSy:
begin
DoAEnd;
Next;
end;
HeadingSy:
begin
if StackIndex < MaxStack then
begin
SectionList.Add(Section);
Inc(StackIndex);
FontStack[StackIndex] := CreateFont(Value, FontStack[StackIndex-1]);
SectionList.Add(THeadingSpace.Create(MasterList, Value));
Section := TSection.Create(MasterList, Lev, FontStack[StackIndex],
CurrentUrlTarget, FindAlignment);
end;
Next;
end;
HeadingEndSy:
begin
if StackIndex > 1 then
begin
SectionList.Add(Section);
SectionList.Add(THeadingSpace.Create(MasterList, Value));
Section := Nil;
PopFont;
end;
Next;
end;
PreSy: DoPreSy;
TableSy: DoTable(Lev);
MapSy: DoMap;
ScriptSy: begin DoScript(MasterList.ScriptEvent); Next; end;
end;
end; {DoCommon}
{-------------DoLists}
procedure ThlParser.DoLists(Level: integer; Sym: Symb; const TermSet: SymbSet);
var
LineCount, CurrentLevel: integer;
T: TAttribute;
Plain: boolean;
Index: char;
begin
LineCount := 1;
Index := '1';
Plain := False;
if (Sym = OLSy) then
begin
if Attributes.Find(StartSy, T) then
if T.Value >= 0 then LineCount := T.Value;
if Attributes.Find(TypeSy, T) and (T.Name <> '') then
Index := T.Name[1];
end
else Plain := (Sym = ULSy) and Attributes.Find(PlainSy, T);
CurrentLevel := Level;
SectionList.Add(Section);
Section := Nil;
Next;
if Sy in [OLEndSy, ULEndSy, DirEndSy, MenuEndSy, DLEndSy, BlockQuoteEndSy] then
Exit; {guard against
and similar combinations}
repeat
case Sy of
LISy:
begin
SectionList.Add(Section);
if Sym = OLSy then
begin
Section := TOListItem.Create(MasterList, Level, LineCount, Index,
FontStack[StackIndex], CurrentUrlTarget);
Inc(LineCount);
end
else Section := TUlistItem.Create(MasterList, Level, FontStack[StackIndex],
CurrentUrlTarget);
if (Sym = ULSy) and Plain then
TUlistItem(Section).Plain := True;
CurrentLevel := Level;
SkipWhiteSpace;
Next;
if Sy = PSy then Next;
end;
DTSy, DDSy:
begin
SectionList.Add(Section);
if Sy = DTSy then
CurrentLevel := Level-1
else CurrentLevel := Level;
Section := TDListItem.Create(MasterList, CurrentLevel, FontStack[StackIndex],
CurrentUrlTarget);
Next;
end;
OLSy, ULSy, DirSy, MenuSy, DLSy:
begin
DoLists(Level+1, Sy, TermSet);
Next;
end;
BlockQuoteSy:
begin
SectionList.Add(Section);
Section := Nil;
DoLists(Level+1, Sy, TermSet);
Next;
end;
DivSy, CenterSy:
DoBody(CurrentLevel, [OLEndSy, ULEndSy, DirEndSy, MenuEndSy, DLEndSy,
BlockQuoteEndSy, EofSy]+TermSet);
HRSy:
begin
SectionList.Add(Section);
SectionList.Add(THorzLine.Create(MasterList, Attributes));
Section := Nil;
Next;
end;
TableSy:
begin
if Assigned(Section) then
TSection(Section).BreakInfo(TagIndex, NoBreak);
DoTable(CurrentLevel);
end;
TextSy, BRSy, PSy, PEndSy,
BSy, ISy, BEndSy, IEndSy, EmSy, EmEndSy, StrongSy, StrongEndSy,
USy, UEndSy, CiteSy, CiteEndSy, VarSy, VarEndSy,
SubSy, SubEndSy, SupSy, SupEndSy, SSy, SEndSy, StrikeSy, StrikeEndSy,
TTSy, CodeSy, KbdSy, SampSy, TTEndSy, CodeEndSy, KbdEndSy, SampEndSy,
NameSy, HRefSy, ASy, AEndSy,
HeadingSy, HeadingEndSy, AddressSy, AddressEndSy, PreSy,
InputSy, FormSy, FormEndSy, TextAreaSy, TextAreaEndSy, SelectSy,
ImageSy, FontSy, FontEndSy, BaseFontSy, BigSy, BigEndSy, SmallSy,
SmallEndSy, MapSy, ScriptSy, NoBrSy, NoBrEndSy, WbrSy:
DoCommonSy(CurrentLevel);
else if Sy in TermSet then Exit
else Next;
end;
Until (Sy in [OLEndSy, ULEndSy, DirEndSy, MenuEndSy, DLEndSy,
BlockQuoteEndSy, EofSy]);
SectionList.Add(Section);
Section := Nil;
end;
{----------------DoBase}
procedure ThlParser.DoBase;
var
I: integer;
begin
with Attributes do
for I := 0 to Count-1 do
with TAttribute(Attributes[I]) do
if Which = HrefSy then
Base := Name
else if Which = TargetSy then
BaseTarget := Name;
Next;
end;
procedure ThlParser.DoSoundEvent;
begin
SoundEvent(CallingObject, ATName, ALoop, False);
end;
{----------------DoSound}
procedure ThlParser.DoSound;
var
T, T1: TAttribute;
begin
if Assigned(SoundEvent) and Attributes.Find(SrcSy, T) then
begin
if Attributes.Find(LoopSy, T1) then ALoop := T1.Value
else ALoop := 1;
ATName := T.Name;
TParseThread(ParseThread).Synchronize(
{$IFDEF HL_LAZARUS}@{$ENDIF}DoSoundEvent);
end;
Next;
end;
function ThlParser.TranslateCharset(DefCharset: TFontCharset;
const {$IFDEF HL_LAZARUS}NewContent{$ELSE}Content{$ENDIF}: string): TFontCharset;
type
XRec = record S: string; CSet: TFontCharset; end;
const
MaxX = 14;
XTable: array[1..MaxX] of XRec =
((S:'1252'; CSet:ANSI_CHARSET),
(S:'8859-1'; CSet:ANSI_CHARSET),
(S:'1253'; CSet:GREEK_CHARSET),
(S:'8859-7'; CSet:GREEK_CHARSET),
(S:'1250'; CSet:EASTEUROPE_CHARSET),
(S:'8859-2'; CSet:EASTEUROPE_CHARSET),
(S:'1251'; CSet:RUSSIAN_CHARSET),
(S:'8859-5'; CSet:RUSSIAN_CHARSET),
(S:'koi8-r'; CSet:RUSSIAN_CHARSET),
(S:'1254'; CSet:TURKISH_CHARSET),
(S:'8859-3'; CSet:TURKISH_CHARSET),
(S:'8859-9'; CSet:TURKISH_CHARSET),
(S:'1257'; CSet:BALTIC_CHARSET),
(S:'8859-4'; CSet:BALTIC_CHARSET));
var
I: integer;
begin
Result := DefCharset;
for I := 1 to MaxX do
if Pos(XTable[I].S,
Lowercase({$IFDEF HL_LAZARUS}NewContent{$ELSE}Content{$ENDIF})) > 0
then
Begin
Result := XTable[I].CSet;
Break;
end;
end;
procedure ThlParser.DoMetaEvent;
begin
MetaEvent(CallingObject, HttpEq, ATName, Content);
end;
{----------------DoMeta}
procedure ThlParser.DoMeta(Sender: TObject);
var
T: TAttribute;
{$ifdef ver100_plus}
Charset: TFontCharset;
{$endif}
begin
if Attributes.Find(HttpEqSy, T) then HttpEq := T.Name
else HttpEq := '';
if Attributes.Find(NameSy, T) then ATName := T.Name
else ATName := '';
if Attributes.Find(ContentSy, T) then Content := T.Name
else Content := '';
{$ifdef ver100_plus}
if (Sender is ThtmlLite) and (CompareText(HttpEq, 'content-type') = 0) then
begin
CharSet := TranslateCharset(TSectionList(SectionList).Charset, Content);
FontStack[StackIndex].Charset := Charset;
end;
{$endif}
if Assigned(MetaEvent) then
TParseThread(ParseThread).Synchronize({$IFDEF HL_LAZARUS}@{$ENDIF}DoMetaEvent);
Next;
end;
{----------------DoTitle}
procedure ThlParser.DoTitle;
begin
Title := '';
Next;
while Sy = TextSy do
begin
Title := Title+LCToken.S;
Next;
end;
end;
{-------------DoBody}
procedure ThlParser.DoBody(Level: integer; const TermSet: SymbSet);
var
I, SaveIndent: integer;
Val: TColor;
T: TAttribute;
SaveJustify: JustifyType;
S: string[10];
SaveSy: Symb;
begin
repeat
writeln('ThlParser.DoBody ',SymbNames[Sy]);
case Sy of
TextSy, BRSy, PSy, PEndSy,
NameSy, HRefSy, ASy, AEndSy,
BSy, ISy, BEndSy, IEndSy, EmSy, EmEndSy, StrongSy, StrongEndSy,
USy, UEndSy, CiteSy, CiteEndSy, VarSy, VarEndSy,
SubSy, SubEndSy, SupSy, SupEndSy, SSy, SEndSy, StrikeSy, StrikeEndSy,
TTSy, CodeSy, KbdSy, SampSy, TTEndSy, CodeEndSy, KbdEndSy, SampEndSy,
HeadingSy, HeadingEndSy, AddressSy, AddressEndSy, PreSy, TableSy,
InputSy, FormSy, FormEndSy, TextAreaSy, TextAreaEndSy, SelectSy,
ImageSy, FontSy, FontEndSy, BaseFontSy, BigSy, BigEndSy, SmallSy,
SmallEndSy, MapSy, ScriptSy, NoBrSy, NoBrEndSy, WbrSy:
DoCommonSy(Level);
BodySy:
begin
if SectionList.Count = 0 then {make sure we're at beginning}
begin
writeln('ThlParser.DoBody B ',SymbNames[Sy],' ');
Section.Free; {Will start with a new section}
for I := 0 to Attributes.Count-1 do
with TAttribute(Attributes[I]) do
case Which of
BackgroundSy: MasterList.SetBackgroundBitmap(Name);
TextSy: if GetColor(Name, Val) then
begin
FontStack[StackIndex].Color := Val or $2000000;
MasterList.FontColor := Val or $2000000;
end;
BGColorSy: if GetColor(Name, Val) then MasterList.SetBackGround(Val or $2000000);
LinkSy: if GetColor(Name, Val) then MasterList.HotSpotColor := Val or $2000000;
VLinkSy: if GetColor(Name, Val) then MasterList.LinkVisitedColor := Val or $2000000;
OLinkSy: if GetColor(Name, Val) then
begin
MasterList.LinkActiveColor := Val or $2000000;
MasterList.LinksActive := True;
end;
MarginWidthSy:
if CallingObject is ThtmlLite then
ThtmlLite(CallingObject).FMarginWidthX := IntMin(IntMax(0,Value), 200);
MarginHeightSy:
if CallingObject is ThtmlLite then
ThtmlLite(CallingObject).FMarginHeightX := IntMin(IntMax(0,Value), 200);
end;
Section := TSection.Create(MasterList, Level, FontStack[1], Nil, Justify);
end;
Next;
end;
HRSy:
begin
SectionList.Add(Section);
SectionList.Add(THorzLine.Create(MasterList, Attributes));
Section := Nil;
Next;
end;
OLSy, ULSy, DirSy, MenuSy, DLSy:
begin
DoLists(1, Sy, TermSet);
Next;
end;
LiSy:
if Level = 0 then
begin
SectionList.Add(Section);
SaveIndent := ListIndent;
ListIndent := SmallListIndent;
Section := TUlistItem.Create(MasterList, 1, FontStack[StackIndex],
CurrentUrlTarget);
SkipWhiteSpace;
Next;
while Sy in [TextSy, NoBrSy, NoBrEndSy, WbrSy, BSy, ISy, BEndSy, IEndSy,
EmSy, EmEndSy, StrongSy, StrongEndSy, USy, UEndSy, CiteSy,
CiteEndSy, VarSy, VarEndSy, SubSy, SubEndSy, SupSy, SupEndSy,
SSy, SEndSy, StrikeSy, StrikeEndSy, TTSy, CodeSy, KbdSy, SampSy,
TTEndSy, CodeEndSy, KbdEndSy, SampEndSy, FontEndSy, BigEndSy,
SmallEndSy, BigSy, SmallSy, ASy, AEndSy] do
begin
DoCommonSy(1);
end;
SectionList.Add(Section);
Section := Nil;
ListIndent := SaveIndent;
end
else Next;
BlockQuoteSy:
begin
SectionList.Add(Section);
Section := Nil;
DoLists(1, Sy, TermSet);
Next;
end;
DivSy, CenterSy:
begin
SaveSy := Sy;
SectionList.Add(Section);
SaveJustify := Justify;
if SaveSy = CenterSy then
Justify := Centered
else
if Attributes.Find(AlignSy, T) then
begin
S := LowerCase(T.Name);
if S = 'left' then Justify := Left
else if S = 'center' then Justify := Centered
else if S = 'right' then Justify := Right;
end;
Section := TSection.Create(MasterList, Level, FontStack[StackIndex],
CurrentUrlTarget, Justify);
Next;
DoBody(Level, [CenterEndSy, DivEndSy]+TermSet);
SectionList.Add(Section);
Justify := SaveJustify;
Section := TSection.Create(MasterList, Level, FontStack[StackIndex],
CurrentUrlTarget, Justify);
if Sy in [CenterEndSy, DivEndSy] then
Next;
end;
TitleSy:
DoTitle;
BgSoundSy:
DoSound;
MetaSy:
DoMeta(CallingObject);
BaseSy:
DoBase;
else if Sy in TermSet then Exit
else Next;
end;
Until (Sy = EofSy);
Next;
end;
procedure ThlParser.ParseInit(ASectionList: TList; ANameList: TStringList; AIncludeEvent: TIncludeType);
begin
SectionList := TSectionList(ASectionList);
MasterList := TSectionList(SectionList);
CallingObject := TSectionList(ASectionList).TheOwner;
IncludeEvent := AIncludeEvent;
NameList := ANameList;
PreFormat := False;
StackIndex := 1;
FontStack[1] := TMyFont.Create;
FontStack[1].Name := MasterList.FontName;
FontStack[1].Color := MasterList.FontColor;
FontStack[1].SetNormalSize(MasterList, 12);
{$ifdef ver100_plus}
FontStack[1].Charset := TSectionList(SectionList).Charset;
{$endif}
CurrentURLTarget := TUrlTarget.Create;
InHref := False;
BaseFontSize := 3;
Title := '';
Base := '';
BaseTarget := '';
Justify := Left;
CurrentStyle := [];
CurrentForm := Nil;
Section := TSection.Create(MasterList, 0, FontStack[1], Nil, Justify);
Attributes := TAttributeList.Create;
SIndex := -1;
InScript := False;
NoPSpace := False;
NoBreak := False;
end;
{----------------ThlParser.HtmlParseString}
procedure ThlParser.HtmlParseString(ASectionList: TList; ANameList: TStringList;
AIncludeEvent: TIncludeType; ASoundEvent: TSoundType;
AMetaEvent: TMetaType);
begin
LoadStyle := lsPrimary;
ParseInit(ASectionList, ANameList, AIncludeEvent);
SoundEvent := ASoundEvent;
MetaEvent := AMetaEvent;
Buffer := TParseThread(ParseThread).Buffer;
BuffEnd := TParseThread(ParseThread).BuffEnd;
try
try
GetCh; {get the reading started}
Next;
DoBody(0, []);
except
On EParseError do; {ignore this error}
end;
finally
Attributes.Free;
if Assigned(Section) then
SectionList.Add(Section);
while StackIndex >= 1 do
begin
FontStack[StackIndex].Free;
Dec(StackIndex);
end;
CurrentURLTarget.Free;
end;
end;
{----------------DoText}
procedure ThlParser.DoText;
var
S: TokenObj;
Done: boolean;
procedure NewSection;
begin
Section.AddTokenObj(S, NoBreak);
S.Clear;
SectionList.Add(Section);
Section := TPreFormated.Create(MasterList, 0, FontStack[StackIndex], CurrentURLTarget, Left);
end;
begin
S := TokenObj.Create;
try
SectionList.Add(Section);
PushNewFont;
with FontStack[StackIndex] do
begin
Name := MasterList.PreFontName;
SetNormalSize(MasterList, 10);
Fixed := True;
end;
Section := TPreformated.Create(MasterList, 0, FontStack[StackIndex],
CurrentURLTarget, Left);
PreFormat := True;
Done := False;
while not Done do
case Ch of
^M : begin NewSection; GetCh; end;
EofChar : Done := True;
else
begin {all other chars}
S.AddChar(LCh, SIndex);
if Length(S.S) > 200 then
begin
Section.AddTokenObj(S, NoBreak);
S.Clear;
end;
GetCh;
end;
end;
Section.AddTokenObj(S, NoBreak);
SectionList.Add(Section);
Section := Nil;
PreFormat := False;
PopFont;
finally
S.Free;
end;
end;
{-------------HtmlParseTextString}
procedure ThlParser.HtmlParseTextString(ASectionList: TList; ANameList: TStringList);
begin
LoadStyle := lsPrimary;
ParseInit(ASectionList, ANameList, Nil);
SoundEvent := Nil;
MetaEvent := NIl;
Buffer := TParseThread(ParseThread).Buffer;
BuffEnd := TParseThread(ParseThread).BuffEnd;
try
try
GetCh; {get the reading started}
DoText;
except
On EParseError do; {ignore this error}
end;
finally
Attributes.Free;
if Assigned(Section) then
SectionList.Add(Section);
while StackIndex >= 1 do
begin
FontStack[StackIndex].Free;
Dec(StackIndex);
end;
end; {finally}
end;
constructor ThlParser.Create;
begin
inherited;
LCToken := TokenObj.Create;
end;
destructor ThlParser.Destroy;
begin
LCToken.Free;
inherited;
end;
end.