{Version 9.45} {*********************************************************} {* FRAMBRWZ.PAS *} {*********************************************************} { Copyright (c) 1995-2008 by L. David Baldwin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Note that the source modules, HTMLGIF1.PAS, PNGZLIB1.PAS, DITHERUNIT.PAS, and URLCON.PAS are covered by separate copyright notices located in those modules. } {$i htmlcons.inc} unit FramBrwz; interface uses SysUtils, Classes, {$IFNDEF LCL} WinTypes, WinProcs, Messages, {$ELSE} LclIntf, LMessages, Types, LclType, HtmlMisc, {$ENDIF} Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Menus, htmlsubs, htmlview, htmlun2, readHTML, FramView; type TGetPostRequestEvent = procedure(Sender: TObject; IsGet: boolean; const URL, Query: string; Reload: boolean; var NewURL: string; var DocType: ThtmlFileType; var Stream: TMemoryStream) of Object; TGetPostRequestExEvent = procedure(Sender: TObject; IsGet: boolean; const URL, Query, EncType, Referer: string; Reload: boolean; var NewURL: string; var DocType: ThtmlFileType; var Stream: TMemoryStream) of Object; TbrFormSubmitEvent = procedure(Sender: TObject; Viewer: ThtmlViewer; const Action, Target, EncType, Method: string; Results: TStringList; var Handled: boolean) of Object; TbrFrameSet = class; TbrSubFrameSet = class; TbrFrameBase = class(TCustomPanel) {base class for other classes} MasterSet: TbrFrameSet; {Points to top (master) TbrFrameSet} private URLBase: string; UnLoaded: boolean; procedure UpdateFrameList; virtual; abstract; protected {$ifdef ver100_plus} {Delphi 3,4,5, C++Builder 3, 4} LocalCharSet: TFontCharset; {$endif} procedure FVMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); virtual; abstract; procedure FVMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); virtual; abstract; procedure FVMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); virtual; abstract; function CheckNoResize(var Lower, Upper: boolean): boolean; virtual; abstract; procedure LoadBrzFiles; virtual; abstract; procedure ReLoadFiles(APosition: LongInt); virtual; abstract; procedure UnloadFiles; virtual; abstract; public LOwner: TbrSubFrameSet; procedure InitializeDimensions(X, Y, Wid, Ht: integer); virtual; abstract; end; TbrFrame = class(TbrFrameBase) {TbrFrame holds a ThtmlViewer or TbrSubFrameSet} protected NoScroll: boolean; brMarginHeight, brMarginWidth: integer; frHistory: TStringList; frPositionHistory: TFreeList; frHistoryIndex: integer; RefreshTimer: TTimer; NextFile: string; procedure CreateViewer; procedure frBumpHistory(const NewName: string; NewPos, OldPos: LongInt; OldFormData: TFreeList); procedure frBumpHistory1(const NewName: string; Pos: LongInt); procedure frSetHistoryIndex(Value: integer); procedure UpdateFrameList; override; procedure RefreshEvent(Sender: TObject; Delay: integer; const URL: string); procedure RefreshTimerTimer(Sender: TObject); protected procedure FVMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure FVMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); override; procedure FVMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; function CheckNoResize(var Lower, Upper: boolean): boolean; override; procedure ReLoadFiles(APosition: LongInt); override; procedure UnloadFiles; override; procedure LoadBrzFiles; override; procedure frLoadFromBrzFile(const URL, Dest, Query, EncType, Referer: string; Bump, IsGet, Reload: boolean); procedure ReloadFile(const FName: string; APosition: LongInt); procedure URLExpandName(Sender: TObject; const SRC: string; var Rslt: string); public Viewer: ThtmlViewer; {the ThtmlViewer it holds if any} ViewerPosition: LongInt; ViewerFormData: TFreeList; FrameSet: TbrSubFrameSet; {or the TbrSubFrameSet it holds} Source, {Dos filename or URL for this frame} OrigSource, {Original Source name} Destination: String; {Destination offset for this frame} TheStream: TMemoryStream; TheStreamType: ThtmlFileType; WinName: String; {window name, if any, for this frame} NoReSize: boolean; constructor CreateIt(AOwner: TComponent; L: TAttributeList; Master: TbrFrameSet; const Path: string); destructor Destroy; override; procedure InitializeDimensions(X, Y, Wid, Ht: integer); override; procedure Repaint; override; procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override; end; TbrSubFrameSet = class(TbrFrameBase) {can contain one or more TbrFrames and/or TSubFrameSets} protected FBase: String; FBaseTarget: String; OuterBorder: integer; BorderSize: integer; FRefreshURL: string; FRefreshDelay: integer; RefreshTimer: TTimer; NextFile: string; procedure ClearFrameNames; procedure AddFrameNames; procedure UpdateFrameList; override; procedure HandleMeta(Sender: TObject; const HttpEq, Name, Content: string); procedure SetRefreshTimer; procedure RefreshTimerTimer(Sender: Tobject); virtual; protected OldRect: TRect; function GetRect: TRect; procedure FVMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure FVMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); override; procedure FVMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure FindLineAndCursor(Sender: TObject; X, Y: integer); function NearBoundary(X, Y: integer): boolean; function CheckNoResize(var Lower, Upper: boolean): boolean; override; procedure Clear; virtual; public First: boolean; {First time thru} Rows: boolean; {set if row frameset, else column frameset} List: TFreeList; {list of TbrFrames and TSubFrameSets in this TbrSubFrameSet} Dim, {col width or row height as read. Blanks may have been added} DimF, {col width or row height in pixels as calculated and displayed} Lines {pixel pos of lines, Lines[1]=0, Lines[DimCount]=width|height} : array[0..20] of SmallInt; Fixed {true if line not allowed to be dragged} : array[0..20] of boolean; DimCount: integer; DimFTot: integer; LineIndex: integer; constructor CreateIt(AOwner: TComponent; Master: TbrFrameSet); destructor Destroy; override; function AddFrame(Attr: TAttributeList; const FName: string): TbrFrame; procedure EndFrameSet; virtual; procedure DoAttributes(L: TAttributeList); procedure LoadBrzFiles; override; procedure ReLoadFiles(APosition: LongInt); override; procedure UnloadFiles; override; procedure InitializeDimensions(X, Y, Wid, Ht: integer); override; procedure CalcSizes(Sender: TObject); end; TFrameBrowser = class; TbrFrameSet = class(TbrSubFrameSet) {only one of these showing, others may be held as History} protected FTitle: String; FCurrentFile: String; FrameNames: TStringList; {list of Window names and their TFrames} Viewers: TList; {list of all ThtmlViewer pointers} Frames: TList; {list of all the Frames contained herein} HotSet: TbrFrameBase; {owner of line we're moving} OldWidth, OldHeight: integer; NestLevel: integer; FActive: ThtmlViewer; {the most recently active viewer} procedure ClearForwards; procedure UpdateFrameList; override; procedure RefreshTimerTimer(Sender: Tobject); override; protected procedure FVMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); override; procedure CheckActive(Sender: TObject); function GetActive: ThtmlViewer; public FrameViewer: TFrameBrowser; constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure EndFrameSet; override; procedure LoadFromBrzFile(Stream: TMemoryStream; StreamType: ThtmlFileType; const URL, Dest: string); procedure Clear; override; procedure CalcSizes(Sender: TObject); procedure Repaint; override; end; TFrameBrowser = class(TFVBase) protected FPosition: TList; FHistoryIndex: integer; FOnGetPostRequest: TGetPostRequestEvent; FOnGetPostRequestEx: TGetPostRequestExEvent; FOnImageRequest: TGetImageEvent; FOptions: TFrameViewerOptions; FOnViewerClear: TNotifyEvent; InFormSubmit: boolean; FOnFormSubmit: TbrFormSubmitEvent; FEncodePostArgs: boolean; FOnProgress: ThtProgressEvent; FBaseEx: String; function GetBase: string; procedure SetBase(Value: string); function GetBaseTarget: string; function GetTitle: string; function GetCurrentFile: string; procedure HotSpotCovered(Sender: TObject; const SRC: string); procedure SetHistoryIndex(Value: integer); procedure ChkFree(Obj: TObject); function GetActiveTarget: string; function GetFwdButtonEnabled: boolean; function GetBackButtonEnabled: boolean; procedure SetOnImageRequest(const Value: TGetImageEvent); procedure SetOptions(Value: TFrameViewerOptions); procedure fvDragDrop(Sender, Source: TObject; X, Y: Integer); procedure fvDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); procedure SetDragDrop(const Value: TDragDropEvent); procedure SetDragOver(const Value: TDragOverEvent); function GetViewers: TStrings; override; procedure SetOnProgress(Handler: ThtProgressEvent); protected CurbrFrameSet: TbrFrameSet; {the TbrFrameSet being displayed} function GetCurViewerCount: integer; override; function GetCurViewer(I: integer): ThtmlViewer; override; function GetActiveViewer: ThtmlViewer; override; procedure BumpHistory(OldFrameSet: TbrFrameSet; OldPos: LongInt); procedure BumpHistory1(const FileName, Title: string; OldPos: LongInt; ft: ThtmlFileType); procedure BumpHistory2(OldPos: LongInt); function HotSpotClickHandled(const FullUrl: string): boolean; procedure AddFrame(FrameSet: TObject; Attr: TAttributeList; const FName: string); override; function CreateSubFrameSet(FrameSet: TObject): TObject; override; procedure DoAttributes(FrameSet: TObject; Attr: TAttributeList); override; procedure EndFrameSet(FrameSet: TObject); override; procedure AddVisitedLink(const S: string); procedure CheckVisitedLinks; procedure LoadURLInternal(const URL, Query, EncType, Referer: string; IsGet, Reload: boolean); procedure DoFormSubmitEvent(Sender: TObject; const Action, Target, EncType, Method: string; Results: TStringList); procedure DoURLRequest(Sender: TObject; const SRC: string; var Stream: TMemoryStream); public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Reload; procedure Clear; procedure HotSpotClick(Sender: TObject; const AnURL: string; var Handled: boolean); procedure ClearHistory; override; function ViewerFromTarget(const Target: string): ThtmlViewer; procedure GoBack; procedure GoFwd; procedure Repaint; override; procedure GetPostQuery(const URL, Query, EncType: string; IsGet: boolean); procedure LoadURL(const URL: string); function GetViewerUrlBase(Viewer: ThtmlViewer): string; property Base: string read GetBase write SetBase; property BaseTarget: string read GetBaseTarget; property DocumentTitle: string read GetTitle; property CurrentFile: string read GetCurrentFile; property HistoryIndex: integer read FHistoryIndex write SetHistoryIndex; property EncodePostArgs: boolean read FEncodePostArgs write FEncodePostArgs; published property FwdButtonEnabled: boolean read GetFwdButtonEnabled; property BackButtonEnabled: boolean read GetBackButtonEnabled; property OnGetPostRequest: TGetPostRequestEvent read FOnGetPostRequest write FOnGetPostRequest; property OnGetPostRequestEx: TGetPostRequestExEvent read FOnGetPostRequestEx write FOnGetPostRequestEx; property OnImageRequest: TGetImageEvent read FOnImageRequest write SetOnImageRequest; property fvOptions: TFrameViewerOptions read FOptions write SetOptions default [fvPrintTableBackground, fvPrintMonochromeBlack]; property OnViewerClear: TNotifyEvent read FOnViewerClear write FOnViewerClear; property OnDragDrop: TDragDropEvent read FOnDragDrop write SetDragDrop; property OnDragOver: TDragOverEvent read FOnDragOver write SetDragOver; property OnFormSubmit: TbrFormSubmitEvent read FOnFormSubmit write FOnFormSubmit; property OnProgress: ThtProgressEvent read FOnProgress write SetOnProgress; end; implementation uses UrlSubs; const Sequence: integer = 10; type PositionObj = class(TObject) Pos: LongInt; Seq: integer; FormData: TFreeList; destructor Destroy; override; end; function StreamToString(Stream: TStream): string; var SL: TStringList; begin Result := ''; try SL := TStringList.Create; try SL.LoadFromStream(Stream); Result := SL.Text; finally Stream.Position := 0; SL.Free; end; except end; end; {----------------SplitURL} procedure SplitURL(const Src: string; var FName, Dest: string); {Split an URL into filename and Destination} var I: integer; begin I := Pos('#', Src); if I >= 1 then begin Dest := System.Copy(Src, I, Length(Src)-I+1); {local destination} FName := System.Copy(Src, 1, I-1); {the file name} end else begin FName := Src; Dest := ''; {no local destination} end; end; function ConvDosToHTML(const Name: string): string; forward; {----------------TbrFrame.CreateIt} constructor TbrFrame.CreateIt(AOwner: TComponent; L: TAttributeList; Master: TbrFrameSet; const Path: string); var I: integer; S: string; begin inherited Create(AOwner); {$ifdef ver100_plus} {Delphi 3,4,5, C++Builder 3, 4} if AOwner is TbrSubFrameSet then LocalCharSet := TbrSubFrameset(AOwner).LocalCharSet; {$endif} LOwner := AOwner as TbrSubFrameSet; MasterSet := Master; BevelInner := bvNone; brMarginWidth := MasterSet.FrameViewer.MarginWidth; brMarginHeight := MasterSet.FrameViewer.MarginHeight; if LOwner.BorderSize = 0 then BevelOuter := bvNone else begin BevelOuter := bvLowered; BevelWidth := LOwner.BorderSize; end; ParentColor := True; if Assigned(L) then for I := 0 to L.Count-1 do with TAttribute(L[I]) do case Which of SrcSy: begin SplitUrl(Trim(Name), S, Destination); S := ConvDosToHTML(S); if Pos(':/', S) <> 0 then URLBase := URLSubs.GetBase(S) {get new base} else if ReadHTML.Base <> '' then begin S := Combine(ReadHTML.Base, S); URLBase := ReadHTML.Base; end else begin URLBase := LOwner.URLBase; S := Combine(URLBase, S); end; Source := S; OrigSource := S; end; NameSy: WinName := Name; NoResizeSy: NoResize := True; ScrollingSy: if CompareText(Name, 'NO') = 0 then {auto and yes work the same} NoScroll := True; MarginWidthSy: brMarginWidth := Value; MarginHeightSy: brMarginHeight := Value; end; if WinName <> '' then {add it to the Window name list} (AOwner as TbrSubFrameSet).MasterSet.FrameNames.AddObject(Uppercase(WinName), Self); OnMouseDown := FVMouseDown; OnMouseMove := FVMouseMove; OnMouseUp := FVMouseUp; frHistory := TStringList.Create; frPositionHistory := TFreeList.Create; end; {----------------TbrFrame.Destroy} destructor TbrFrame.Destroy; var I: integer; begin if Assigned(MasterSet) then begin if (WinName <> '') and Assigned(MasterSet.FrameNames) and MasterSet.FrameNames.Find(WinName, I) and (MasterSet.FrameNames.Objects[I] = Self) then MasterSet.FrameNames.Delete(I); if Assigned(Viewer) then begin if Assigned(MasterSet.Viewers) then MasterSet.Viewers.Remove(Viewer); if Assigned(MasterSet.Frames) then MasterSet.Frames.Remove(Self); if Viewer = MasterSet.FActive then MasterSet.FActive := Nil; end; end; if Assigned(Viewer) then begin Viewer.Free; Viewer := Nil; end else if Assigned(FrameSet) then begin FrameSet.Free; FrameSet := Nil; end; frHistory.Free; frHistory := Nil; frPositionHistory.Free; frPositionHistory := Nil; ViewerFormData.Free; RefreshTimer.Free; inherited Destroy; end; procedure TbrFrame.SetBounds(ALeft, ATop, AWidth, AHeight: Integer); begin inherited; {in most cases, SetBounds results in a call to CalcSizes. However, to make sure for case where there is no actual change in the bounds.... } if Assigned(FrameSet) then FrameSet.CalcSizes(Nil); end; procedure TbrFrame.RefreshEvent(Sender: TObject; Delay: integer; const URL: string); var Ext: string; begin if not (fvMetaRefresh in MasterSet.FrameViewer.FOptions) then Exit; Ext := Lowercase(GetURLExtension(URL)); if (Ext = 'exe') or (Ext = 'zip') then Exit; if URL = '' then NextFile := Source else if not IsFullURL(URL) then NextFile := Combine(URLBase, URL) //URLBase + URL else NextFile := URL; if not Assigned(RefreshTimer) then RefreshTimer := TTimer.Create(Self); RefreshTimer.OnTimer := RefreshTimerTimer; RefreshTimer.Interval := Delay*1000; RefreshTimer.Enabled := True; end; procedure TbrFrame.RefreshTimerTimer(Sender: TObject); var S, D: string; begin RefreshTimer.Enabled := False; if Unloaded then Exit; if not IsFullUrl(NextFile) then NextFile := Combine(UrlBase, NextFile); if (MasterSet.Viewers.Count = 1) then {load a new FrameSet} MasterSet.FrameViewer.LoadURLInternal(NextFile, '', '', '', True, True) else begin SplitURL(NextFile, S, D); frLoadFromBrzFile(S, D, '', '', '', True, True, True); end; end; procedure TbrFrame.RePaint; begin if Assigned(Viewer) then Viewer.RePaint else if Assigned(FrameSet) then FrameSet.RePaint; inherited RePaint; end; {----------------TbrFrame.FVMouseDown} procedure TbrFrame.FVMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin (Parent as TbrSubFrameSet).FVMouseDown(Sender, Button, Shift, X+Left, Y+Top); end; {----------------TbrFrame.FVMouseMove} procedure TbrFrame.FVMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin if not NoResize then (Parent as TbrSubFrameSet).FVMouseMove(Sender, Shift, X+Left, Y+Top); end; {----------------TbrFrame.FVMouseUp} procedure TbrFrame.FVMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin (Parent as TbrSubFrameSet).FVMouseUp(Sender, Button, Shift, X+Left, Y+Top); end; {----------------TbrFrame.CheckNoResize} function TbrFrame.CheckNoResize(var Lower, Upper: boolean): boolean; begin Result := NoResize; Lower := NoResize; Upper := NoResize; end; {----------------TbrFrame.InitializeDimensions} procedure TbrFrame.InitializeDimensions(X, Y, Wid, Ht: integer); begin if Assigned(FrameSet) then FrameSet.InitializeDimensions(X, Y, Wid, Ht); end; {----------------TbrFrame.CreateViewer} procedure TbrFrame.CreateViewer; begin Viewer := ThtmlViewer.Create(Self); {the Viewer for the frame} Viewer.FrameOwner := Self; Viewer.Width := ClientWidth; Viewer.Height := ClientHeight; Viewer.Align := alClient; if (MasterSet.BorderSize = 0) or (fvNoFocusRect in MasterSet.FrameViewer.fvOptions) then Viewer.BorderStyle := htNone; Viewer.OnHotspotClick := LOwner.MasterSet.FrameViewer.HotSpotClick; Viewer.OnHotspotCovered := LOwner.MasterSet.FrameViewer.HotSpotCovered; if NoScroll then Viewer.Scrollbars := ssNone; Viewer.DefBackground := MasterSet.FrameViewer.FBackground; Viewer.Visible := False; InsertControl(Viewer); Viewer.SendToBack; Viewer.Visible := True; Viewer.Tabstop := True; {$ifdef ver100_plus} {Delphi 3,4,5, C++Builder 3, 4} Viewer.CharSet := LocalCharset; {$endif} MasterSet.Viewers.Add(Viewer); with MasterSet.FrameViewer do begin Viewer.ViewImages := FViewImages; Viewer.SetStringBitmapList(FBitmapList); Viewer.ImageCacheCount := FImageCacheCount; Viewer.NoSelect := FNoSelect; Viewer.DefFontColor := FFontColor; Viewer.DefHotSpotColor := FHotSpotColor; Viewer.DefVisitedLinkColor := FVisitedColor; Viewer.DefOverLinkColor := FOverColor; Viewer.DefFontSize := FFontSize; Viewer.DefFontName := FFontName; Viewer.DefPreFontName := FPreFontName; Viewer.OnBitmapRequest := FOnBitmapRequest; if fvOverLinksActive in FOptions then Viewer.htOptions := Viewer.htOptions + [htOverLinksActive]; if fvNoLinkUnderline in FOptions then Viewer.htOptions := Viewer.htOptions + [htNoLinkUnderline]; if not (fvPrintTableBackground in FOptions) then Viewer.htOptions := Viewer.htOptions - [htPrintTableBackground]; if (fvPrintBackground in FOptions) then Viewer.htOptions := Viewer.htOptions + [htPrintBackground]; if not (fvPrintMonochromeBlack in FOptions) then Viewer.htOptions := Viewer.htOptions - [htPrintMonochromeBlack]; if fvShowVScroll in FOptions then Viewer.htOptions := Viewer.htOptions + [htShowVScroll]; if fvNoWheelMouse in FOptions then Viewer.htOptions := Viewer.htOptions + [htNoWheelMouse]; if Assigned(FOnImageRequest) then Viewer.OnImageRequest := FOnImageRequest; if fvNoLinkHilite in FOptions then Viewer.htOptions := Viewer.htOptions + [htNoLinkHilite]; Viewer.OnFormSubmit := DoFormSubmitEvent; Viewer.OnLink := FOnLink; Viewer.OnMeta := FOnMeta; Viewer.OnMetaRefresh := RefreshEvent; Viewer.OnRightClick := FOnRightClick; Viewer.OnProcessing := CheckProcessing; Viewer.OnMouseDown := OnMouseDown; Viewer.OnMouseMove := OnMouseMove; Viewer.OnMouseUp := OnMouseUp; Viewer.OnKeyDown := OnKeyDown; Viewer.OnKeyUp := OnKeyUp; Viewer.OnKeyPress := OnKeyPress; Viewer.Cursor := Cursor; Viewer.HistoryMaxCount := FHistoryMaxCount; Viewer.OnScript := FOnScript; Viewer.PrintMarginLeft := FPrintMarginLeft; Viewer.PrintMarginRight := FPrintMarginRight; Viewer.PrintMarginTop := FPrintMarginTop; Viewer.PrintMarginBottom := FPrintMarginBottom; Viewer.PrintScale := FPrintScale; Viewer.OnPrintHeader := FOnPrintHeader; Viewer.OnPrintFooter := FOnPrintFooter; Viewer.OnPrintHtmlHeader := FOnPrintHtmlHeader; Viewer.OnPrintHtmlFooter := FOnPrintHtmlFooter; Viewer.OnInclude := FOnInclude; Viewer.OnSoundRequest := FOnSoundRequest; Viewer.OnImageOver := FOnImageOver; Viewer.OnImageClick := FOnImageClick; Viewer.OnFileBrowse := FOnFileBrowse; Viewer.OnObjectClick := FOnObjectClick; Viewer.OnObjectFocus := FOnObjectFocus; Viewer.OnObjectBlur := FOnObjectBlur; Viewer.OnObjectChange := FOnObjectChange; Viewer.ServerRoot := ServerRoot; Viewer.OnMouseDouble := FOnMouseDouble; Viewer.OnPanelCreate := FOnPanelCreate; Viewer.OnPanelDestroy := FOnPanelDestroy; Viewer.OnPanelPrint := FOnPanelPrint; Viewer.OnDragDrop := fvDragDrop; Viewer.OnDragOver := fvDragOver; Viewer.OnParseBegin := FOnParseBegin; Viewer.OnParseEnd := FOnParseEnd; Viewer.OnProgress := FOnProgress; Viewer.OnObjectTag := OnObjectTag; Viewer.OnhtStreamRequest := DoURLRequest; end; Viewer.MarginWidth := brMarginWidth; Viewer.MarginHeight := brMarginHeight; Viewer.OnEnter := MasterSet.CheckActive; Viewer.OnExpandName := UrlExpandName; end; {----------------TbrFrame.LoadBrzFiles} procedure TbrFrame.LoadBrzFiles; var Item: TbrFrameBase; I: integer; Upper, Lower: boolean; Msg: string[255]; NewURL: string; TheString: string; begin if (Source <> '') and (MasterSet.NestLevel < 4) then begin if not Assigned(TheStream) then begin NewURL := ''; if Assigned(MasterSet.FrameViewer.FOnGetPostRequestEx) then MasterSet.FrameViewer.FOnGetPostRequestEX(Self, True, Source, '', '', '', False, NewURL, TheStreamType, TheStream) else MasterSet.FrameViewer.FOnGetPostRequest(Self, True, Source, '', False, NewURL, TheStreamType, TheStream); if NewURL <> '' then Source := NewURL; end; URLBase := GetBase(Source); Inc(MasterSet.NestLevel); try TheString := StreamToString(TheStream); if (TheStreamType = HTMLType) and IsFrameString(LsString, '', TheString, MasterSet.FrameViewer) then begin FrameSet := TbrSubFrameSet.CreateIt(Self, MasterSet); FrameSet.Align := alClient; FrameSet.Visible := False; InsertControl(FrameSet); FrameSet.SendToBack; FrameSet.Visible := True; FrameParseString(MasterSet.FrameViewer, FrameSet, lsString, '', TheString, FrameSet.HandleMeta); Self.BevelOuter := bvNone; frBumpHistory1(Source, 0); with FrameSet do begin for I := 0 to List.Count-1 do Begin Item := TbrFrameBase(List.Items[I]); Item.LoadBrzFiles; end; CheckNoresize(Lower, Upper); if FRefreshDelay > 0 then SetRefreshTimer; end; end else begin CreateViewer; Viewer.Base := MasterSet.FBase; Viewer.LoadStream(Source, TheStream, TheStreamType); Viewer.PositionTo(Destination); frBumpHistory1(Source, Viewer.Position); end; except if not Assigned(Viewer) then CreateViewer; if Assigned(FrameSet) then begin FrameSet.Free; FrameSet := Nil; end; Msg := '
Can''t load '+Source;
Viewer.LoadFromBuffer(@Msg[1], Length(Msg), ''); {load an error message}
end;
Dec(MasterSet.NestLevel);
end
else
begin {so blank area will perform like the TFrameBrowser}
OnMouseDown := MasterSet.FrameViewer.OnMouseDown;
OnMouseMove := MasterSet.FrameViewer.OnMouseMove;
OnMouseUp := MasterSet.FrameViewer.OnMouseUp;
end;
end;
{----------------TbrFrame.ReloadFiles}
procedure TbrFrame.ReloadFiles(APosition: LongInt);
var
Item: TbrFrameBase;
I: integer;
Upper, Lower: boolean;
Dummy: string;
procedure DoError;
var
Msg: string;
begin
Msg := '
Can''t load '+Source;
Viewer.LoadFromBuffer(@Msg[1], Length(Msg), ''); {load an error message}
end;
begin
if Source <> '' then
if Assigned(FrameSet) then
begin
with FrameSet do
begin
for I := 0 to List.Count-1 do
Begin
Item := TbrFrameBase(List.Items[I]);
Item.ReloadFiles(APosition);
end;
CheckNoresize(Lower, Upper);
end;
end
else if Assigned(Viewer) then
begin
Viewer.Base := MasterSet.FBase; {only effective if no Base to be read}
try
if Assigned(MasterSet.FrameViewer.FOnGetPostRequestEx) then
MasterSet.FrameViewer.FOnGetPostRequestEx(Self, True, Source, '', '', '',False,
Dummy, TheStreamType, TheStream)
else
MasterSet.FrameViewer.FOnGetPostRequest(Self, True, Source, '', False,
Dummy, TheStreamType, TheStream);
Viewer.LoadStream(Source, TheStream, TheStreamType);
if APosition < 0 then
Viewer.Position := ViewerPosition
else Viewer.Position := APosition; {its History Position}
Viewer.FormData := ViewerFormData;
ViewerFormData.Free;
ViewerFormData := Nil;
except
DoError;
end;
end;
Unloaded := False;
end;
{----------------TbrFrame.UnloadFiles}
procedure TbrFrame.UnloadFiles;
var
Item: TbrFrameBase;
I: integer;
begin
if Assigned(RefreshTimer) then
RefreshTimer.Enabled := False;
if Assigned(FrameSet) then
begin
with FrameSet do
begin
for I := 0 to List.Count-1 do
Begin
Item := TbrFrameBase(List.Items[I]);
Item.UnloadFiles;
end;
end;
end
else if Assigned(Viewer) then
begin
ViewerPosition := Viewer.Position;
ViewerFormData := Viewer.FormData;
if Assigned(MasterSet.FrameViewer.FOnViewerClear) then
MasterSet.FrameViewer.FOnViewerClear(Viewer);
Viewer.Clear;
if MasterSet.FActive = Viewer then
MasterSet.FActive := Nil;
Viewer.OnSoundRequest := Nil;
end;
Unloaded := True;
end;
{----------------TbrFrame.frLoadFromBrzFile}
procedure TbrFrame.frLoadFromBrzFile(const URL, Dest, Query, EncType, Referer: string; Bump, IsGet, Reload: boolean);
{URL is full URL here, has been seperated from Destination}
var
OldPos: LongInt;
HS, S, S1, OldTitle, OldName, OldBase: string;
OldFormData: TFreeList;
SameName: boolean;
OldViewer: ThtmlViewer;
OldFrameSet: TbrSubFrameSet;
TheString: string;
Upper, Lower, FrameFile: boolean;
Item: TbrFrameBase;
I: integer;
begin
if Assigned(RefreshTimer) then RefreshTimer.Enabled := False;
OldName := Source;
OldBase := URLBase;
S := URL;
if S = '' then S := OldName
else URLBase := URLSubs.GetBase(S); {get new base}
HS := S;
SameName := CompareText(S, OldName)= 0;
{if SameName, will not have to reload anything unless Reload set}
if not SameName or Reload then
begin
if Assigned(Viewer) and Assigned(MasterSet.FrameViewer.FOnViewerClear) then
MasterSet.FrameViewer.FOnViewerClear(Viewer);
S1 := '';
if Assigned(MasterSet.FrameViewer.FOnGetPostRequestEx) then
MasterSet.FrameViewer.FOnGetPostRequestEx(Self, IsGet, S, Query, EncType, Referer, Reload, S1, TheStreamType, TheStream)
else
MasterSet.FrameViewer.FOnGetPostRequest(Self, IsGet, S, Query, Reload, S1, TheStreamType, TheStream);
if S1 <> '' then
begin
S := S1;
URLBase := GetBase(S);
end;
end;
Source := S;
try
TheString := StreamToString(TheStream);
if not SameName then
try
FrameFile := (TheStreamType = HTMLType) and
IsFrameString(lsString, '', TheString, MasterSet.FrameViewer);
except
Raise(EfvLoadError.Create('Can''t load: '+URL));
end
else FrameFile := not Assigned(Viewer);
if SameName and not Reload then
if Assigned(Viewer) then
begin
OldPos := Viewer.Position;
Viewer.PositionTo(Dest);
MasterSet.FrameViewer.AddVisitedLink(URL+Dest);
if Bump and (Viewer.Position <> OldPos) then
{Viewer to Viewer}
frBumpHistory(HS, Viewer.Position, OldPos, Nil);
end
else
begin
with FrameSet do
for I := 0 to List.Count-1 do
Begin
Item := TbrFrameBase(List.Items[I]);
if (Item is TbrFrame) then
with TbrFrame(Item) do
if CompareText(Source, OrigSource) <> 0 then
frLoadFromBrzFile(OrigSource, '', '', '', '', True, True, False);
end;
Exit;
end
else if Assigned(Viewer) and not FrameFile then {not samename or samename and reload}
begin {Viewer already assigned and it's not a Frame file}
OldPos := Viewer.Position;
OldTitle := Viewer.DocumentTitle;
if Bump and not SameName and (MasterSet.Viewers.Count > 1) then
OldFormData := Viewer.FormData
else OldFormData := Nil;
try
Viewer.Base := MasterSet.FBase;
Viewer.LoadStream(Source, TheStream, TheStreamType);
if (Dest <> '') then
Viewer.PositionTo(Dest);
MasterSet.FrameViewer.AddVisitedLink(URL+Dest);
if not samename then
begin {don't bump history on a forced reload}
if MasterSet.Viewers.Count > 1 then
begin
if Bump then
{Viewer to Viewer}
frBumpHistory(HS, Viewer.Position, OldPos, OldFormData)
else OldFormData.Free;
end
else if (MasterSet.Viewers.Count = 1) and Bump then
{a single viewer situation, bump the history here}
with MasterSet do
begin
FCurrentFile := Source;
FTitle := Viewer.DocumentTitle;
FBase := Viewer.Base;
FBaseTarget := Viewer.BaseTarget;
FrameViewer.BumpHistory1(OldName, OldTitle, OldPos, HTMLType);
end;
end;
except
OldFormData.Free;
Raise;
end;
end
else
begin {Viewer is not assigned or it is a Frame File}
{keep the old viewer or frameset around (free later) to minimize blink}
OldViewer := Viewer; Viewer := Nil;
OldFrameSet := FrameSet; FrameSet := Nil;
if OldFrameSet <> Nil then OldFrameSet.ClearFrameNames;
if FrameFile then
begin {it's a frame file}
FrameSet := TbrSubFrameSet.CreateIt(Self, MasterSet);
FrameSet.URLBase := URLBase;
FrameSet.Align := alClient;
FrameSet.Visible := False;
InsertControl(FrameSet);
FrameSet.SendToBack; {to prevent blink}
FrameSet.Visible := True;
FrameParseString(MasterSet.FrameViewer, FrameSet, lsString, '', TheString, FrameSet.HandleMeta);
MasterSet.FrameViewer.AddVisitedLink(URL);
Self.BevelOuter := bvNone;
with FrameSet do
begin
for I := 0 to List.Count-1 do
Begin
Item := TbrFrameBase(List.Items[I]);
Item.LoadBrzFiles;
end;
CheckNoresize(Lower, Upper);
if FRefreshDelay > 0 then
SetRefreshTimer;
end;
if Assigned(OldViewer) then
frBumpHistory(HS, 0, OldViewer.Position, OldViewer.FormData)
else frBumpHistory(S, 0, 0, Nil);
end
else
begin {not a frame file but needs a viewer}
CreateViewer;
Viewer.Base := MasterSet.FBase;
Viewer.LoadStream(Source, TheStream, TheStreamType);
Viewer.PositionTo(Dest);
MasterSet.FrameViewer.AddVisitedLink(URL+Dest);
{FrameSet to Viewer}
frBumpHistory(HS, Viewer.Position, 0, Nil);
end;
if Assigned(FrameSet) then
with FrameSet do
begin
with ClientRect do
InitializeDimensions(Left, Top, Right-Left, Bottom-Top);
CalcSizes(Nil);
end;
if Assigned(Viewer) then
begin
if MasterSet.BorderSize = 0 then
BevelOuter := bvNone
else
begin
BevelOuter := bvLowered;
BevelWidth := MasterSet.BorderSize;
end;
if (Dest <> '') then
Viewer.PositionTo(Dest);
end;
if Assigned(OldViewer) then
begin
MasterSet.Viewers.Remove(OldViewer);
if MasterSet.FActive = OldViewer then
MasterSet.FActive := Nil;
OldViewer.Free;
end
else if Assigned(OldFrameSet) then
begin
OldFrameSet.UnloadFiles;
OldFrameSet.Visible := False;
end;
RePaint;
end;
except
Source := OldName;
URLBase := OldBase;
Raise;
end;
end;
{----------------TbrFrame.ReloadFile}
procedure TbrFrame.ReloadFile(const FName: string; APosition: LongInt);
{It's known that there is only a single viewer, the file is not being changed,
only the position}
begin
Viewer.Position := APosition;
end;
function ConvDosToHTML(const Name: string): string;
{if Name is a Dos filename, convert it to HTML. Add the file:// if it is
a full pathe filename}
begin
Result := Name;
if Pos('\', Result) > 0 then
begin
Result := DosToHTML(Result);
if (Pos('|', Result) > 0) then {was something like c:\....}
Result := 'file:///'+Result;
end;
end;
{----------------TbrFrame.URLExpandName}
procedure TbrFrame.URLExpandName(Sender: TObject; const SRC: string; var Rslt: string);
var
S: string;
Viewer: ThtmlViewer;
begin
S := ConvDosToHTML(SRC);
if not IsFullUrl(S) then
begin
Viewer := Sender as ThtmlViewer;
if Viewer.Base <> '' then
Rslt := Combine(GetBase(ConvDosToHTML(Viewer.Base)), S)
else Rslt := Combine(UrlBase, S);
end
else Rslt := S;
end;
{----------------TbrFrame.frBumpHistory}
procedure TbrFrame.frBumpHistory(const NewName: string;
NewPos, OldPos: LongInt; OldFormData: TFreeList);
{applies to TFrames which hold a ThtmlViewer}{Viewer to Viewer}
var
PO: PositionObj;
begin
with frHistory do
begin
if (Count > 0) then
begin
PositionObj(frPositionHistory[frHistoryIndex]).Pos := OldPos;
if frHistory[frHistoryIndex] <> NewName then
PositionObj(frPositionHistory[frHistoryIndex]).FormData := OldFormData
else OldFormData.Free;
end
else OldFormData.Free;
MasterSet.ClearForwards; {clear the history list forwards}
frHistoryIndex := 0;
InsertObject(0, NewName, FrameSet); {FrameSet may be Nil here}
PO := PositionObj.Create;
PO.Pos := NewPos;
PO.Seq := Sequence;
Inc(Sequence);
frPositionHistory.Insert(0, PO);
MasterSet.UpdateFrameList;
with MasterSet.FrameViewer do
if Assigned(FOnHistoryChange) then
FOnHistoryChange(MasterSet.FrameViewer);
end;
end;
{----------------TbrFrame.frBumpHistory1}
procedure TbrFrame.frBumpHistory1(const NewName: string; Pos: LongInt);
{called from a fresh TbrFrame. History list is empty}
var
PO: PositionObj;
begin
with frHistory do
begin
frHistoryIndex := 0;
InsertObject(0, NewName, FrameSet); {FrameSet may be Nil here}
PO := PositionObj.Create;
PO.Pos := Pos;
PO.Seq := Sequence;
Inc(Sequence);
frPositionHistory.Insert(0, PO);
MasterSet.UpdateFrameList;
with MasterSet.FrameViewer do
if Assigned(FOnHistoryChange) then
FOnHistoryChange(MasterSet.FrameViewer);
end;
end;
{----------------TbrFrame.frSetHistoryIndex}
procedure TbrFrame.frSetHistoryIndex(Value: integer);
begin
with frHistory do
if (Value <> frHistoryIndex) and (Value >= 0) and (Value < Count) then
begin
if Assigned(RefreshTimer) then
RefreshTimer.Enabled := False; {cut off any timing underway}
if Assigned(Viewer) then {current is Viewer}
with PositionObj(frPositionHistory[frHistoryIndex]) do
begin
Pos := Viewer.Position; {save the old position}
{note that frHistoryIndex can only change by 1}
PositionObj(frPositionHistory[frHistoryIndex]).FormData := Viewer.FormData;
end
else
begin {Current is FrameSet}
FrameSet.UnloadFiles;
FrameSet.DestroyHandle;
FrameSet.ClearFrameNames;
FrameSet.Visible := False;
FrameSet := Nil; {it's not destroyed,though}
end;
if Objects[Value] is TbrSubFrameSet then
begin
FrameSet := TbrSubFrameSet(Objects[Value]);
FrameSet.Visible := True;
FrameSet.ReloadFiles(-1);
FrameSet.AddFrameNames;
if Assigned(Viewer) then
begin
if Assigned(MasterSet.Viewers) then
MasterSet.Viewers.Remove(Viewer);
if MasterSet.FActive = Viewer then
MasterSet.FActive := Nil;
Viewer.Free;
Viewer := Nil;
end;
end
else
begin
if not Assigned(Viewer) then
CreateViewer;
with PositionObj(frPositionHistory[Value]) do
begin
if (Source <> Strings[Value]) then
frLoadFromBrzFile(Strings[Value], '', '', '', '', False, True, False);
Viewer.FormData := FormData;
FormData.Free;
FormData := Nil;
Viewer.Position := Pos;
end;
end;
Source := Strings[Value];
frHistoryIndex := Value;
MasterSet.UpdateFrameList;
with MasterSet.FrameViewer do
if Assigned(FOnHistoryChange) then
FOnHistoryChange(MasterSet.FrameViewer);
MasterSet.FrameViewer.CheckVisitedLinks;
end;
end;
{----------------TbrFrame.UpdateFrameList}
procedure TbrFrame.UpdateFrameList;
begin
MasterSet.Frames.Add(Self);
if Assigned(FrameSet) then
FrameSet.UpdateFrameList;
end;
{----------------TbrSubFrameSet.CreateIt}
constructor TbrSubFrameSet.CreateIt(AOwner: TComponent; Master: TbrFrameSet);
begin
inherited Create(AOwner);
MasterSet := Master;
{$ifdef ver100_plus} {Delphi 3,4,5, C++Builder 3, 4}
if AOwner is TbrFrameBase then
LocalCharSet := TbrSubFrameset(AOwner).LocalCharSet;
{$endif}
OuterBorder := 0; {no border for subframesets}
if Self <> Master then
BorderSize := Master.BorderSize;
First := True;
List := TFreeList.Create;
FBase := '';
FBaseTarget := '';
OnResize := CalcSizes;
OnMouseDown := FVMouseDown;
OnMouseMove := FVMouseMove;
OnMouseUp := FVMouseUp;
{$ifdef delphi7_plus}
{$IFNDEF LCL}
ParentBackground := False;
{$ENDIF}
{$endif}
ParentColor := True;
if (AOwner is TbrFrameBase) then
URLBase := TbrFrameBase(AOwner).URLBase;
end;
{----------------TbrSubFrameSet.ClearFrameNames}
procedure TbrSubFrameSet.ClearFrameNames;
var
I, J: integer;
begin
for J := 0 to List.Count-1 do
if (TbrFrameBase(List[J]) is TbrFrame) then
begin
with TbrFrame(List[J]) do
if Assigned(MasterSet) and (WinName <> '')
and Assigned(MasterSet.FrameNames)
and MasterSet.FrameNames.Find(WinName, I) then
MasterSet.FrameNames.Delete(I);
end
else if (TbrFrameBase(List[J]) is TbrSubFrameSet) then
TbrSubFrameSet(List[J]).ClearFrameNames;
end;
{----------------TbrSubFrameSet.AddFrameNames}
procedure TbrSubFrameSet.AddFrameNames;
var
J: integer;
Frame: TbrFrame;
begin
for J := 0 to List.Count-1 do
if (TbrFrameBase(List[J]) is TbrFrame) then
begin
Frame := TbrFrame(List[J]);
with Frame do
if Assigned(MasterSet) and (WinName <> '')
and Assigned(MasterSet.FrameNames) then
begin
MasterSet.FrameNames.AddObject(Uppercase(WinName), Frame);
end;
end
else if (TbrFrameBase(List[J]) is TbrSubFrameSet) then
TbrSubFrameSet(List[J]).AddFrameNames;
end;
{----------------TbrSubFrameSet.Destroy}
destructor TbrSubFrameSet.Destroy;
begin
List.Free;
List := Nil;
RefreshTimer.Free;
inherited Destroy;
end;
{----------------TbrSubFrameSet.AddFrame}
function TbrSubFrameSet.AddFrame(Attr: TAttributeList; const FName: string): TbrFrame;
{called by the parser when is encountered within the