lazarus-ccr/components/thtmlport/package/framview.pas

4415 lines
123 KiB
ObjectPascal

{Version 9.45}
{*********************************************************}
{* FRAMVIEW.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 FramView;
interface
uses
SysUtils, Classes,
{$IFNDEF LCL}
WinTypes, WinProcs, Messages,
{$ELSE}
LclIntf, LMessages, Types, LclType, FPimage, HtmlMisc,
{$ENDIF}
Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Menus,
htmlsubs, htmlview, htmlun2, readHTML;
type
{common to TFrameViewer and TFrameBrowser}
THotSpotTargetClickEvent = procedure(Sender: TObject; const Target, URL: string;
var Handled: boolean) of Object;
THotSpotTargetEvent = procedure(Sender: TObject; const Target, URL: string) of Object;
TWindowRequestEvent = procedure(Sender: TObject; const Target, URL: string) of Object;
fvOptionEnum = (fvMetaRefresh, fvNoBorder, fvNoLinkUnderline, fvOverLinksActive,
fvPrintMonochromeBlack, fvPrintTableBackground, fvPrintBackground,
fvShowVScroll, fvNoFocusRect, fvShowDummyCaret, fvNoWheelMouse,
fvNoLinkHilite);
TFrameViewerOptions = set of fvOptionEnum;
{for TFrameViewer}
TStreamRequestEvent = procedure(Sender: TObject; const SRC: string;
var Stream: TStream) of Object;
TBufferRequestEvent = procedure(Sender: TObject; const SRC: string;
var Buffer: PChar; var BuffSize: integer) of Object;
TStringsRequestEvent = procedure(Sender: TObject; const SRC: string;
var Strings: TStrings) of Object;
TFileRequestEvent = procedure(Sender: TObject; const SRC: string;
var NewName: string) of Object;
EfvLoadError = class(Exception);
{common base class for TFrameViewer and TFrameBrowser}
TFVBase = class(TFrameViewerBase) {TFrameViewerBase is in ReadHTML.pas}
protected
FURL: string;
FTarget: string;
FLinkText: string;
FLinkAttributes: TStringList;
FOnHotSpotTargetClick: THotSpotTargetClickEvent;
FOnHotSpotTargetCovered: THotSpotTargetEvent;
ProcessList: TList; {list of viewers that are processing}
FViewImages: boolean;
FImageCacheCount: integer;
FBitmapList: TStringBitmapList;
FProcessing, FViewerProcessing: boolean;
FNoSelect: boolean;
FOnHistoryChange: TNotifyEvent;
FOnBitmapRequest: TGetBitmapEvent;
FOnImageRequest: TGetImageEvent;
FOnBlankWindowRequest: TWindowRequestEvent;
FOnMeta: TMetaType;
FOnScript: TScriptEvent;
FOnImageClick: TImageClickEvent;
FOnImageOver: TImageOverEvent;
FOnFileBrowse: TFileBrowseEvent;
FOnObjectClick: TObjectClickEvent;
FOnObjectFocus: ThtObjectEvent;
FOnObjectBlur: ThtObjectEvent;
FOnObjectChange: ThtObjectEvent;
FOnRightClick: TRightClickEvent;
FOnMouseDouble: TMouseEvent;
FServerRoot: string;
FOnInclude: TIncludeType;
FOnSoundRequest: TSoundType;
FPrintMarginLeft,
FPrintMarginRight,
FPrintMarginTop,
FPrintMarginBottom: double;
FMarginWidth, FMarginHeight: integer;
FOnPrintHeader, FOnPrintFooter: TPagePrinted;
FOnPrintHTMLHeader, FOnPrintHTMLFooter: ThtmlPagePrinted;
FVisitedMaxCount: integer;
FBackground: TColor;
FFontName: string;
FPreFontName: string;
FFontColor: TColor;
FHotSpotColor, FVisitedColor, FOverColor: TColor;
FFontSize: integer;
FCursor: TCursor;
FHistoryMaxCount: integer;
{$ifdef ver100_plus} {Delphi 3,4,5, C++Builder 3, 4}
FCharset: TFontCharset;
{$endif}
FOnProcessing: TProcessingEvent;
FHistory, FTitleHistory: TStrings;
FDither: boolean;
FOnPanelCreate: TPanelCreateEvent;
FOnPanelDestroy: TPanelDestroyEvent;
FOnPanelPrint: TPanelPrintEvent;
Visited: TStringList; {visited URLs}
FOnDragDrop: TDragDropEvent;
FOnDragOver: TDragOverEvent;
FViewerList: TStrings;
FOnParseBegin: TParseEvent;
FOnParseEnd: TNotifyEvent;
FPrintScale: double;
FOnObjectTag: TObjectTagEvent;
function GetCurViewerCount: integer; virtual; abstract;
function GetCurViewer(I: integer): ThtmlViewer; virtual; abstract;
function GetFURL: string;
function GetProcessing: boolean;
function GetTarget: String;
procedure SetViewImages(Value: boolean);
procedure SetImageCacheCount(Value: integer);
procedure SetNoSelect(Value: boolean);
procedure SetOnBitmapRequest(Handler: TGetBitmapEvent);
procedure SetOnMeta(Handler: TMetaType);
procedure SetOnLink(Handler: TLinkType);
procedure SetOnScript(Handler: TScriptEvent);
procedure SetImageOver(Handler: TImageOverEvent);
procedure SetImageClick(Handler: TImageClickEvent);
procedure SetOnFileBrowse(Handler: TFileBrowseEvent);
procedure SetOnObjectClick(Handler: TObjectClickEvent);
procedure SetOnObjectFocus(Handler: ThtObjectEvent);
procedure SetOnObjectBlur(Handler: ThtObjectEvent);
procedure SetOnObjectChange(Handler: ThtObjectEvent);
procedure SetOnRightClick(Handler: TRightClickEvent);
procedure SetMouseDouble(Handler: TMouseEvent);
procedure SetServerRoot(Value: string);
procedure SetPrintMarginLeft(Value: Double);
procedure SetPrintMarginRight(Value: Double);
procedure SetPrintMarginTop(Value: Double);
procedure SetPrintMarginBottom(Value: Double);
procedure SetPrintScale(Value: double);
procedure SetPrintHeader(Handler: TPagePrinted);
procedure SetPrintFooter(Handler: TPagePrinted);
procedure SetPrintHtmlHeader(Handler: THtmlPagePrinted);
procedure SetPrintHtmlFooter(Handler: THtmlPagePrinted);
procedure SetMarginHeight(Value: integer);
procedure SetMarginWidth(Value: integer);
procedure SetVisitedMaxCount(Value: integer);
procedure SetColor(Value: TColor);
function GetFontName: TFontName;
procedure SetFontName(Value: TFontName);
function GetPreFontName: TFontName;
procedure SetPreFontName(Value: TFontName);
procedure SetFontSize(Value: integer);
procedure SetFontColor(Value: TColor);
procedure SetHotSpotColor(Value: TColor);
procedure SetActiveColor(Value: TColor);
procedure SetVisitedColor(Value: TColor);
procedure SetHistoryMaxCount(Value: integer);
procedure SetCursor(Value: TCursor);
function GetSelLength: integer;
procedure SetSelLength(Value: integer);
function GetSelStart: integer;
procedure SetSelStart(Value: integer);
{$ifdef ver100_plus} {Delphi 3,4,5, C++Builder 3, 4}
procedure SetCharset(Value: TFontCharset);
{$endif}
function GetOurPalette: HPalette;
procedure SetOurPalette(Value: HPalette);
procedure SetDither(Value: boolean);
function GetCaretPos: integer;
procedure SetCaretPos(Value: integer);
function GetSelText: WideString;
function GetSelTextBuf(Buffer: PWideChar; BufSize: integer): integer;
procedure SetProcessing(Local, Viewer: boolean);
procedure CheckProcessing(Sender: TObject; ProcessingOn: boolean);
procedure SetOnPanelCreate(Handler: TPanelCreateEvent);
procedure SetOnPanelDestroy(Handler: TPanelDestroyEvent);
procedure SetOnPanelPrint(Handler: TPanelPrintEvent);
procedure SetOnParseBegin(Handler: TParseEvent);
procedure SetOnParseEnd(Handler: TNotifyEvent);
procedure SetOnObjectTag(Handler: TObjectTagEvent);
function GetActiveViewer: ThtmlViewer; virtual; abstract;
function GetViewers: TStrings; virtual; abstract;
property CurViewer[I: integer]: ThtmlViewer read GetCurViewer;
property OnBitmapRequest: TGetBitmapEvent read FOnBitmapRequest
write SetOnBitmapRequest;
property ServerRoot: string read FServerRoot write SetServerRoot;
public
procedure ClearHistory; virtual; abstract;
procedure SetFocus; override;
function InsertImage(Viewer: ThtmlViewer; const Src: string; Stream: TMemoryStream): boolean;
function NumPrinterPages: integer; overload;
function NumPrinterPages(var WidthRatio: double): integer; overload;
procedure Print(FromPage, ToPage: integer);
property URL: string read GetFURL;
property Target: string read GetTarget;
property Processing: boolean read GetProcessing;
property ActiveViewer: ThtmlViewer read GetActiveViewer;
property History: TStrings read FHistory;
property TitleHistory: TStrings read FTitleHistory;
property Palette: HPalette read GetOurPalette write SetOurPalette;
property Dither: boolean read FDither write SetDither default True;
property CaretPos: integer read GetCaretPos write SetCaretPos;
property SelLength: integer read GetSelLength write SetSelLength;
property SelStart: integer read GetSelStart write SetSelStart;
property SelText: WideString read GetSelText;
procedure CopyToClipboard;
procedure SelectAll;
function FindEx(const S: WideString; MatchCase, Reverse: boolean): boolean;
function Find(const S: WideString; MatchCase: boolean): boolean;
property Viewers: TStrings read GetViewers;
property LinkText: string read FLinkText;
property LinkAttributes: TStringList read FLinkAttributes;
published
property OnHotSpotTargetCovered: THotSpotTargetEvent read FOnHotSpotTargetCovered
write FOnHotSpotTargetCovered;
property OnHotSpotTargetClick: THotSpotTargetClickEvent read FOnHotSpotTargetClick
write FOnHotSpotTargetClick;
property ViewImages: boolean read FViewImages write SetViewImages default True;
property ImageCacheCount: integer read FImageCacheCount
write SetImageCacheCount default 5;
property OnHistoryChange: TNotifyEvent read FOnHistoryChange
write FOnHistoryChange;
property NoSelect: boolean read FNoSelect write SetNoSelect;
property OnBlankWindowRequest: TWindowRequestEvent read FOnBlankWindowRequest
write FOnBlankWindowRequest;
property OnScript: TScriptEvent read FOnScript write SetOnScript;
property OnImageClick: TImageClickEvent read FOnImageClick write SetImageClick;
property OnImageOver: TImageOverEvent read FOnImageOver write SetImageOver;
property OnFileBrowse: TFileBrowseEvent read FOnFileBrowse write SetOnFileBrowse;
property OnObjectClick: TObjectClickEvent read FOnObjectClick write SetOnObjectClick;
property OnObjectFocus: ThtObjectEvent read FOnObjectFocus write SetOnObjectFocus;
property OnObjectBlur: ThtObjectEvent read FOnObjectBlur write SetOnObjectBlur;
property OnObjectChange: ThtObjectEvent read FOnObjectChange write SetOnObjectChange;
property OnRightClick: TRightClickEvent read FOnRightClick write SetOnRightClick;
property OnMouseDouble: TMouseEvent read FOnMouseDouble write SetMouseDouble;
property OnInclude: TIncludeType read FOnInclude write FOnInclude;
property OnSoundRequest: TSoundType read FOnSoundRequest write FOnSoundRequest;
property PrintMarginLeft: double read FPrintMarginLeft write SetPrintMarginLeft;
property PrintMarginRight: double read FPrintMarginRight write SetPrintMarginRight;
property PrintMarginTop: double read FPrintMarginTop write SetPrintMarginTop;
property PrintMarginBottom: double read FPrintMarginBottom write SetPrintMarginBottom;
property PrintScale: double read FPrintScale write SetPrintScale;
property MarginWidth: integer read FMarginWidth write SetMarginWidth default 10;
property MarginHeight: integer read FMarginHeight write SetMarginHeight default 5;
property OnPrintHeader: TPagePrinted read FOnPrintHeader write SetPrintHeader;
property OnPrintFooter: TPagePrinted read FOnPrintFooter write SetPrintFooter;
property OnPrintHTMLHeader: ThtmlPagePrinted read FOnPrintHTMLHeader write SetPrintHTMLHeader;
property OnPrintHTMLFooter: ThtmlPagePrinted read FOnPrintHTMLFooter write SetPrintHTMLFooter;
property OnMeta: TMetaType read FOnMeta write SetOnMeta;
property OnLink: TLinkType read FOnLink write SetOnLink;
property OnPanelCreate: TPanelCreateEvent read FOnPanelCreate write SetOnPanelCreate;
property OnPanelDestroy: TPanelDestroyEvent read FOnPanelDestroy write SetOnPanelDestroy;
property OnPanelPrint: TPanelPrintEvent read FOnPanelPrint write SetOnPanelPrint;
property OnParseBegin: TParseEvent read FOnParseBegin write SetOnParseBegin;
property OnParseEnd: TNotifyEvent read FOnParseEnd write SetOnParseEnd;
property DefBackground: TColor read FBackground write SetColor default clBtnFace;
property DefFontName: TFontName read GetFontName write SetFontName;
property DefPreFontName: TFontName read GetPreFontName write SetPreFontName;
property DefFontSize: integer read FFontSize write SetFontSize default 12;
property DefFontColor: TColor read FFontColor write SetFontColor
default clBtnText;
property DefHotSpotColor: TColor read FHotSpotColor write SetHotSpotColor
default clBlue;
property DefVisitedLinkColor: TColor read FVisitedColor write SetVisitedColor
default clPurple;
property DefOverLinkColor: TColor read FOverColor write SetActiveColor
default clBlue;
property VisitedMaxCount: integer read FVisitedMaxCount write SetVisitedMaxCount default 50;
property HistoryMaxCount: integer read FHistoryMaxCount write SetHistoryMaxCount;
property Cursor: TCursor read FCursor write SetCursor default crIBeam;
{$ifdef ver100_plus} {Delphi 3,4,5, C++Builder 3, 4}
property CharSet: TFontCharset read FCharSet write SetCharset;
{$endif}
property OnProcessing: TProcessingEvent read FOnProcessing write FOnProcessing;
property OnObjectTag: TObjectTagEvent read FOnObjectTag write SetOnObjectTag;
property Align;
{$ifdef ver120_plus}
property Anchors;
{$endif}
property Enabled;
property PopupMenu;
property ShowHint;
property TabOrder;
property TabStop default False;
property Visible;
property Height default 150;
property Width default 150;
property OnEnter;
property OnExit;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnKeyDown;
property OnKeyUp;
property OnKeyPress;
end;
{TFrameViewer Types}
PEventRec = ^EventRec;
EventRec = record
LStyle: LoadStyleType;
NewName: string;
AString: string;
end;
TFrameSet = class;
TSubFrameSet = class;
TFrameBase = class(TCustomPanel) {base class for other classes}
MasterSet: TFrameSet; {Points to top (master) TFrameSet}
private
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 LoadFiles(PEV: PEventRec); virtual; abstract;
procedure ReLoadFiles(APosition: integer); virtual; abstract;
procedure UnloadFiles; virtual; abstract;
public
LOwner: TSubFrameSet;
procedure InitializeDimensions(X, Y, Wid, Ht: integer); virtual; abstract;
end;
TfvFrame = class(TFrameBase) {TfvFrame holds a ThtmlViewer or TSubFrameSet}
protected
NoScroll: boolean;
frMarginHeight, frMarginWidth: integer;
frHistory: TStringList;
frPositionHistory: TFreeList;
frHistoryIndex: integer;
RefreshTimer: TTimer;
NextFile: string;
procedure CreateViewer;
procedure frBumpHistory(const NewName: string; NewPos, OldPos: integer;
OldFormData: TFreeList);
procedure frBumpHistory1(const NewName: string; Pos: integer);
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 LoadFiles(PEV: PEventRec); override;
procedure ReLoadFiles(APosition: integer); override;
procedure UnloadFiles; override;
procedure frLoadFromFile(const FName, Dest: string; Bump, Reload: boolean);
procedure ReloadFile(const FName: string; APosition: integer);
public
Viewer: ThtmlViewer; {the ThtmlViewer it holds if any}
ViewerPosition: integer;
ViewerFormData: TFreeList;
FrameSet: TSubFrameSet; {or the TSubFrameSet it holds}
Source, {Dos filename or URL for this frame}
OrigSource, {Original Source name}
Destination: string; {Destination offset for this frame}
WinName: string; {window name, if any, for this frame}
NoReSize: boolean;
constructor CreateIt(AOwner: TComponent; L: TAttributeList;
Master: TFrameSet; 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;
TSubFrameSet = class(TFrameBase) {can contain one or more TFrames 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;
procedure LoadFromFile(const FName, Dest: string);
public
First: boolean; {First time thru}
Rows: boolean; {set if row frameset, else column frameset}
List: TFreeList; {list of TFrames and TSubFrameSets in this TSubFrameSet}
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: TFrameSet);
destructor Destroy; override;
function AddFrame(Attr: TAttributeList; const FName: string): TfvFrame;
procedure EndFrameSet; virtual;
procedure DoAttributes(L: TAttributeList);
procedure LoadFiles(PEV: PEventRec); override;
procedure ReLoadFiles(APosition: integer); override;
procedure UnloadFiles; override;
procedure InitializeDimensions(X, Y, Wid, Ht: integer); override;
procedure CalcSizes(Sender: TObject);
end;
TFrameViewer = class;
TFrameSet = class(TSubFrameSet) {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: TFrameBase; {owner of line we're moving}
OldWidth, OldHeight: integer;
NestLevel: integer;
FActive: ThtmlViewer; {the most recently active viewer}
function RequestEvent: boolean;
function TriggerEvent(const Src: string; PEV: PEventRec): boolean;
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: TFrameViewer;
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure EndFrameSet; override;
procedure LoadFromFile(const FName, Dest: string);
procedure Clear; override;
procedure CalcSizes(Sender: TObject);
procedure Repaint; override;
end;
TFrameViewer = class(TFVBase)
protected
FPosition: TList;
FHistoryIndex: integer;
FOnFormSubmit: TFormSubmitEvent;
FOptions: TFrameViewerOptions;
UrlRequestStream: TMemoryStream;
FOnStreamRequest: TStreamRequestEvent;
FOnBufferRequest: TBufferRequestEvent;
FOnStringsRequest: TStringsRequestEvent;
FOnFileRequest: TFileRequestEvent;
FOnProgress: ThtProgressEvent;
FBaseEx: string;
procedure SetOnImageRequest(Handler: TGetImageEvent);
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 SetOnFormSubmit(Handler: TFormSubmitEvent);
procedure ChkFree(Obj: TObject);
function GetActiveBase: string;
function GetActiveTarget: string;
function GetFwdButtonEnabled: boolean;
function GetBackButtonEnabled: boolean;
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
CurFrameSet: TFrameSet; {the TFrameSet being displayed}
function GetCurViewerCount: integer; override;
function GetCurViewer(I: integer): ThtmlViewer; override;
function GetActiveViewer: ThtmlViewer; override;
procedure BumpHistory(OldFrameSet: TFrameSet; OldPos: integer);
procedure BumpHistory1(const FileName, Title: string;
OldPos: integer; ft: ThtmlFileType);
procedure BumpHistory2(OldPos: integer);
function HotSpotClickHandled: boolean;
procedure LoadFromFileInternal(const FName: string);
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 DoURLRequest(Sender: TObject; const SRC: string; var RStream: TMemoryStream);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure LoadFromFile(const FName: string);
procedure Load(const SRC: string);
procedure LoadTargetFromFile(const Target, FName: string);
procedure LoadImageFile(const FName: string);
procedure Reload;
procedure Clear;
procedure HotSpotClick(Sender: TObject; const AnURL: string;
var Handled: boolean);
function HTMLExpandFilename(const Filename: string): string; virtual;
procedure ClearHistory; override;
function ViewerFromTarget(const Target: string): ThtmlViewer;
procedure GoBack;
procedure GoFwd;
procedure Repaint; override;
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;
published
property OnImageRequest: TGetImageEvent read FOnImageRequest
write SetOnImageRequest;
property OnFormSubmit: TFormSubmitEvent read FOnFormSubmit
write SetOnFormSubmit;
property FwdButtonEnabled: boolean read GetFwdButtonEnabled;
property BackButtonEnabled: boolean read GetBackButtonEnabled;
property fvOptions: TFrameViewerOptions read FOptions write SetOptions
default [fvPrintTableBackground, fvPrintMonochromeBlack];
property OnStreamRequest: TStreamRequestEvent read FOnStreamRequest write FOnStreamRequest;
property OnStringsRequest: TStringsRequestEvent read FOnStringsRequest write FOnStringsRequest;
property OnBufferRequest: TBufferRequestEvent read FOnBufferRequest write FOnBufferRequest;
property OnFileRequest: TFileRequestEvent read FOnFileRequest write FOnFileRequest;
property OnBitmapRequest;
property ServerRoot;
property OnDragDrop: TDragDropEvent read FOnDragDrop write SetDragDrop;
property OnDragOver: TDragOverEvent read FOnDragOver write SetDragOver;
property OnProgress: ThtProgressEvent read FOnProgress write SetOnProgress;
end;
implementation
const
Sequence: integer = 10;
type
PositionObj = class(TObject)
Pos: integer;
Seq: integer;
FormData: TFreeList;
destructor Destroy; override;
end;
function ImageFile(Const S: string): boolean;
var
Ext: string[5];
begin
Ext := Lowercase(ExtractFileExt(S));
Result := (Ext = '.gif') or (Ext = '.jpg') or (Ext = '.jpeg') or (Ext = '.bmp')
or (Ext = '.png');
end;
function TexFile(Const S: string): boolean;
var
Ext: string[5];
begin
Ext := Lowercase(ExtractFileExt(S));
Result := (Ext = '.txt');
end;
{----------------FileToString}
function FileToString(const Name: String): string;
var
FS: TFileStream;
begin
Result := '';
FS := TFileStream.Create(Name, fmOpenRead or fmShareDenyWrite);
try
SetLength(Result, FS.Size);
FS.ReadBuffer(Result[1], FS.Size);
finally
FS.Free;
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;
{----------------TfvFrame.CreateIt}
constructor TfvFrame.CreateIt(AOwner: TComponent; L: TAttributeList;
Master: TFrameSet; const Path: string);
var
I: integer;
S, Dest: string;
begin
inherited Create(AOwner);
{$ifdef ver100_plus} {Delphi 3,4,5, C++Builder 3, 4}
if AOwner is TSubFrameSet then
LocalCharSet := TSubFrameset(AOwner).LocalCharSet;
{$endif}
LOwner := AOwner as TSubFrameSet;
MasterSet := Master;
BevelInner := bvNone;
frMarginWidth := MasterSet.FrameViewer.MarginWidth;
frMarginHeight := 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, Dest);
Destination := Dest;
if not Master.RequestEvent then
begin
S := HTMLServerToDos(S, Master.FrameViewer.ServerRoot);
{$IFDEF MSWINDOWS}
if Pos(':', S) = 0 then
{$ELSE}
if Pos('/', S) <> 1 then
{$ENDIF}
begin
if ReadHTML.Base <> '' then {a Base was found}
if CompareText(ReadHTML.Base, 'DosPath') = 0 then
S := ExpandFilename(S)
else
S := ExtractFilePath(HTMLToDos(ReadHTML.Base)) + S
else S := Path + S;
end;
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: frMarginWidth := Value;
MarginHeightSy: frMarginHeight := Value;
end;
if WinName <> '' then {add it to the Window name list}
(AOwner as TSubFrameSet).MasterSet.FrameNames.AddObject(Uppercase(WinName), Self);
OnMouseDown := FVMouseDown;
OnMouseMove := FVMouseMove;
OnMouseUp := FVMouseUp;
frHistory := TStringList.Create;
frPositionHistory := TFreeList.Create;
end;
{----------------TfvFrame.Destroy}
destructor TfvFrame.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 TfvFrame.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 TfvFrame.RefreshEvent(Sender: TObject; Delay: integer; const URL: string);
begin
if not (fvMetaRefresh in MasterSet.FrameViewer.FOptions) then
Exit;
if URL = '' then
NextFile := Source
else NextFile := MasterSet.FrameViewer.HTMLExpandFilename(URL);
if not FileExists(NextFile) and not MasterSet.RequestEvent then
Exit;
if not Assigned(RefreshTimer) then
RefreshTimer := TTimer.Create(Self);
RefreshTimer.OnTimer := RefreshTimerTimer;
RefreshTimer.Interval := Delay*1000;
RefreshTimer.Enabled := True;
end;
procedure TfvFrame.RefreshTimerTimer(Sender: TObject);
begin
RefreshTimer.Enabled := False;
if Unloaded then Exit;
if (MasterSet.Viewers.Count = 1) then {load a new FrameSet}
begin
if CompareText(NextFile, MasterSet.FCurrentFile) = 0 then
MasterSet.FrameViewer.Reload
else MasterSet.FrameViewer.LoadFromFileInternal(NextFile);
end
else
frLoadFromFile(NextFile, '', True, True); {reload set}
end;
procedure TfvFrame.RePaint;
begin
if Assigned(Viewer) then Viewer.RePaint
else if Assigned(FrameSet) then FrameSet.RePaint;
inherited RePaint;
end;
{----------------TfvFrame.FVMouseDown}
procedure TfvFrame.FVMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
(Parent as TSubFrameSet).FVMouseDown(Sender, Button, Shift, X+Left, Y+Top);
end;
{----------------TfvFrame.FVMouseMove}
procedure TfvFrame.FVMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if not NoResize then
(Parent as TSubFrameSet).FVMouseMove(Sender, Shift, X+Left, Y+Top);
end;
{----------------TfvFrame.FVMouseUp}
procedure TfvFrame.FVMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
(Parent as TSubFrameSet).FVMouseUp(Sender, Button, Shift, X+Left, Y+Top);
end;
{----------------TfvFrame.CheckNoResize}
function TfvFrame.CheckNoResize(var Lower, Upper: boolean): boolean;
begin
Result := NoResize;
Lower := NoResize;
Upper := NoResize;
end;
{----------------TfvFrame.InitializeDimensions}
procedure TfvFrame.InitializeDimensions(X, Y, Wid, Ht: integer);
begin
if Assigned(FrameSet) then
FrameSet.InitializeDimensions(X, Y, Wid, Ht);
end;
{----------------TfvFrame.CreateViewer}
procedure TfvFrame.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 fvShowDummyCaret in FOptions then
Viewer.htOptions := Viewer.htOptions + [htShowDummyCaret];
if fvNoLinkHilite in FOptions then
Viewer.htOptions := Viewer.htOptions + [htNoLinkHilite];
Viewer.OnImageRequest := FOnImageRequest;
Viewer.OnFormSubmit := FOnFormSubmit;
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;
if MasterSet.RequestEvent then
Viewer.OnhtStreamRequest := DoURLRequest;
end;
Viewer.MarginWidth := frMarginWidth;
Viewer.MarginHeight := frMarginHeight;
Viewer.OnEnter := MasterSet.CheckActive;
end;
{----------------TfvFrame.LoadFiles}
procedure TfvFrame.LoadFiles(PEV: PEventRec);
var
Item: TFrameBase;
I: integer;
Upper, Lower, Image, Tex: boolean;
Msg: string;
EV: EventRec;
Event: boolean;
begin
if ((Source <> '') or Assigned(PEV)) and (MasterSet.NestLevel < 4) then
begin
Image := ImageFile(Source) and not MasterSet.RequestEvent;
Tex := TexFile(Source) and not MasterSet.RequestEvent;
EV.LStyle := lsFile;
if Image or Tex then
EV.NewName := MasterSet.FrameViewer.HTMLExpandFilename(Source)
else
begin
if Assigned(PEV) then
begin
Event := True;
EV := PEV^;
end
else
Event := MasterSet.TriggerEvent(Source, @EV);
if not Event then
EV.NewName := MasterSet.FrameViewer.HTMLExpandFilename(Source);
end;
Inc(MasterSet.NestLevel);
try
if not Image and not Tex and IsFrameString(EV.LStyle, EV.NewName, EV.AString, MasterSet.FrameViewer) then
begin
FrameSet := TSubFrameSet.CreateIt(Self, MasterSet);
FrameSet.Align := alClient;
FrameSet.Visible := False;
InsertControl(FrameSet);
FrameSet.SendToBack;
FrameSet.Visible := True;
FrameParseString(MasterSet.FrameViewer, FrameSet, EV.LStyle, EV.NewName, EV.AString,
FrameSet.HandleMeta);
Self.BevelOuter := bvNone;
frBumpHistory1(Source, 0);
with FrameSet do
begin
for I := 0 to List.Count-1 do
Begin
Item := TFrameBase(List.Items[I]);
Item.LoadFiles(Nil);
end;
CheckNoresize(Lower, Upper);
if FRefreshDelay > 0 then
SetRefreshTimer;
end;
end
else
begin
CreateViewer;
Viewer.Base := MasterSet.FBase;
if Image then
Viewer.LoadImageFile(EV.NewName)
else if Tex then
Viewer.LoadTextFile(EV.NewName)
else
begin
case EV.LStyle of
lsFile: Viewer.LoadFromFile(EV.NewName+Destination);
lsString:
Viewer.LoadFromString(EV.AString, Source);
end;
if EV.LStyle <> lsFile then
Viewer.PositionTo(Destination);
end;
frBumpHistory1(Source, Viewer.Position);
end;
except
if not Assigned(Viewer) then
CreateViewer;
if Assigned(FrameSet) then
begin
FrameSet.Free;
FrameSet := Nil;
end;
Msg := '<p><img src="qw%&.bmp" alt="Error"> Can''t load '+EV.NewName;
Viewer.LoadFromBuffer(@Msg[1], Length(Msg), ''); {load an error message}
end;
Dec(MasterSet.NestLevel);
end
else
begin {so blank area will perform like the TFrameViewer}
OnMouseDown := MasterSet.FrameViewer.OnMouseDown;
OnMouseMove := MasterSet.FrameViewer.OnMouseMove;
OnMouseUp := MasterSet.FrameViewer.OnMouseUp;
end;
end;
{----------------TfvFrame.ReloadFiles}
procedure TfvFrame.ReloadFiles(APosition: integer);
var
Item: TFrameBase;
I: integer;
Upper, Lower: boolean;
EV: EventRec;
procedure DoError;
var
Msg: string;
begin
Msg := '<p><img src="qw%&.bmp" alt="Error"> 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 := TFrameBase(List.Items[I]);
Item.ReloadFiles(APosition);
end;
CheckNoresize(Lower, Upper);
end;
end
else if Assigned(Viewer) then
begin
Viewer.Base := MasterSet.FBase;
if ImageFile(Source) then
try
Viewer.LoadImageFile(Source)
except end {leave blank on error}
else if TexFile(Source) then
try
Viewer.LoadTextFile(Source)
except end
else
begin
try
if MasterSet.TriggerEvent(Source, @EV) then
case EV.LStyle of
lsFile: Viewer.LoadFromFile(EV.NewName);
lsString: Viewer.LoadFromString(EV.AString, '');
end
else
Viewer.LoadFromFile(Source);
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;
end;
Unloaded := False;
end;
{----------------TfvFrame.UnloadFiles}
procedure TfvFrame.UnloadFiles;
var
Item: TFrameBase;
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 := TFrameBase(List.Items[I]);
Item.UnloadFiles;
end;
end;
end
else if Assigned(Viewer) then
begin
ViewerPosition := Viewer.Position;
ViewerFormData := Viewer.FormData;
Viewer.Clear;
if MasterSet.FActive = Viewer then
MasterSet.FActive := Nil;
Viewer.OnSoundRequest := Nil;
end;
Unloaded := True;
end;
{----------------TfvFrame.frLoadFromFile}
procedure TfvFrame.frLoadFromFile(const FName, Dest: string; Bump, Reload: boolean);
{Note: if FName not '' and there is no RequestEvent, it has been HTML expanded
and contains the path}
var
OldPos: integer;
HS, OldTitle, OldName: string;
OldFormData: TFreeList;
SameName, Tex, Img: boolean;
OldViewer: ThtmlViewer;
OldFrameSet: TSubFrameSet;
EV: EventRec;
Upper, Lower, FrameFile: boolean;
Item: TFrameBase;
I: integer;
begin
if Assigned(RefreshTimer) then RefreshTimer.Enabled := False;
OldName := Source;
EV.NewName := FName;
if EV.NewName = '' then EV.NewName := OldName;
Source := EV.NewName;
HS := EV.NewName;
SameName := CompareText(EV.NewName, OldName)= 0;
{if SameName, will not have to reload anything}
Img := ImageFile(EV.NewName) and not MasterSet.RequestEvent;
Tex := TexFile(EV.NewName) and not MasterSet.RequestEvent;
EV.LStyle := lsFile;
if not Img and not Tex and not SameName then
MasterSet.TriggerEvent(EV.NewName, @EV);
try
if not SameName then
try
FrameFile := not Img and not Tex and
IsFrameString(EV.LStyle, EV.NewName, EV.AString, MasterSet.FrameViewer);
except
Raise(EfvLoadError.Create('Can''t load: '+EV.NewName));
end
else FrameFile := not Assigned(Viewer);
if SameName then
if Assigned(Viewer) then
begin
OldPos := Viewer.Position;
if Reload then
begin {this for Meta Refresh only}
case EV.LStyle of
lsFile: Viewer.LoadFromFile(EV.NewName+Dest);
lsString:
Viewer.LoadFromString(EV.AString, '');
end;
Viewer.Position := OldPos;
end
else
begin
Viewer.PositionTo(Dest);
if Bump and (Viewer.Position <> OldPos) then
{Viewer to Viewer}
frBumpHistory(HS, Viewer.Position, OldPos, Nil);
end;
MasterSet.FrameViewer.AddVisitedLink(EV.NewName+Dest);
end
else
begin
with FrameSet do
begin
for I := 0 to List.Count-1 do
Begin
Item := TFrameBase(List.Items[I]);
if (Item is TfvFrame) then
with TfvFrame(Item) do
if CompareText(Source, OrigSource) <> 0 then
begin
frLoadFromFile(OrigSource, '', True, False);
end;
end;
end;
Exit;
end
else if Assigned(Viewer) and not FrameFile then {not Same Name}
begin {Viewer already assigned and it's not a Frame file}
OldPos := Viewer.Position;
OldTitle := Viewer.DocumentTitle;
OldFormData := Viewer.FormData;
try
if Img then Viewer.LoadImageFile(EV.NewName)
else if Tex then Viewer.LoadTextFile(EV.NewName + Dest)
else
begin
Viewer.Base := MasterSet.FBase;
case EV.LStyle of
lsFile: Viewer.LoadFromFile(EV.NewName+Dest);
lsString:
Viewer.LoadFromString(EV.AString, '');
end;
if (EV.LStyle <> lsFile) and (Dest <> '') then
Viewer.PositionTo(Dest);
end;
MasterSet.FrameViewer.AddVisitedLink(EV.NewName+Dest);
if MasterSet.Viewers.Count > 1 then
begin
if Bump then
{Viewer to Viewer}
frBumpHistory(HS, Viewer.Position, OldPos, OldFormData)
else OldFormData.Free;
end
else OldFormData.Free;
except
OldFormData.Free;
Raise;
end;
if (MasterSet.Viewers.Count = 1) and Bump then
{a single viewer situation, bump the history here}
with MasterSet do
begin
FCurrentFile := Viewer.CurrentFile;
FTitle := Viewer.DocumentTitle;
FBase := Viewer.Base;
FBaseTarget := Viewer.BaseTarget;
FrameViewer.BumpHistory1(OldName, OldTitle, OldPos, HTMLType);
end;
end
else
begin {Viewer is not assigned or it is a Frame File} {not Same Name here either}
{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 not Img and not Tex and FrameFile then
begin {it's a frame file}
FrameSet := TSubFrameSet.CreateIt(Self, MasterSet);
FrameSet.Align := alClient;
FrameSet.Visible := False;
InsertControl(FrameSet);
FrameSet.SendToBack; {to prevent blink}
FrameSet.Visible := True;
FrameParseString(MasterSet.FrameViewer, FrameSet, EV.LStyle, EV.NewName,
EV.AString, FrameSet.HandleMeta);
MasterSet.FrameViewer.AddVisitedLink(EV.NewName);
Self.BevelOuter := bvNone;
with FrameSet do
begin
for I := 0 to List.Count-1 do
Begin
Item := TFrameBase(List.Items[I]);
Item.LoadFiles(Nil);
end;
CheckNoresize(Lower, Upper);
if FRefreshDelay > 0 then
SetRefreshTimer;
end;
if Assigned(OldViewer) then
frBumpHistory(HS, 0, OldViewer.Position, OldViewer.FormData)
else frBumpHistory(EV.NewName, 0, 0, Nil);
end
else
begin {not a frame file but needs a viewer}
CreateViewer;
if Img then
Viewer.LoadImageFile(EV.NewName)
else if Tex then
Viewer.LoadTextFile(EV.NewName)
else
begin
Viewer.Base := MasterSet.FBase;
case EV.LStyle of
lsFile: Viewer.LoadFromFile(EV.NewName+Dest);
lsString:
Viewer.LoadFromString(EV.AString, '');
end;
if EV.LStyle <> lsFile then
Viewer.PositionTo(Dest);
end;
MasterSet.FrameViewer.AddVisitedLink(EV.NewName+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;
OldFrameSet.DestroyHandle;
end;
RePaint;
end;
except
Source := OldName;
Raise;
end;
end;
{----------------TfvFrame.ReloadFile}
procedure TfvFrame.ReloadFile(const FName: string; APosition: integer);
{It's known that there is only a single viewer, the file is not being changed,
only the position}
begin
Viewer.Position := APosition;
end;
{----------------TfvFrame.frBumpHistory}
procedure TfvFrame.frBumpHistory(const NewName: string;
NewPos, OldPos: integer; 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;
{----------------TfvFrame.frBumpHistory1}
procedure TfvFrame.frBumpHistory1(const NewName: string; Pos: integer);
{called from a fresh TfvFrame. 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;
{----------------TfvFrame.frSetHistoryIndex}
procedure TfvFrame.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 TSubFrameSet then
begin
FrameSet := TSubFrameSet(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
begin
frLoadFromFile(Strings[Value], '', False, False);
Viewer.FormData := FormData;
FormData.Free;
FormData := Nil;
end;
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;
{----------------TfvFrame.UpdateFrameList}
procedure TfvFrame.UpdateFrameList;
begin
MasterSet.Frames.Add(Self);
if Assigned(FrameSet) then
FrameSet.UpdateFrameList;
end;
{----------------TSubFrameSet.CreateIt}
constructor TSubFrameSet.CreateIt(AOwner: TComponent; Master: TFrameSet);
begin
inherited Create(AOwner);
MasterSet := Master;
{$ifdef ver100_plus} {Delphi 3,4,5, C++Builder 3, 4}
if AOwner is TFrameBase then
LocalCharSet := TSubFrameset(AOwner).LocalCharSet;
{$endif}
OuterBorder := 0; {no border for subframesets}
if Self <> Master then
BorderSize := Master.BorderSize;
First := True;
List := TFreeList.Create;
OnResize := CalcSizes;
OnMouseDown := FVMouseDown;
OnMouseMove := FVMouseMove;
OnMouseUp := FVMouseUp;
{$ifdef delphi7_plus}
{$IFNDEF LCL}
ParentBackground := False;
{$ENDIF}
{$endif}
ParentColor := True;
end;
{----------------TSubFrameSet.ClearFrameNames}
procedure TSubFrameSet.ClearFrameNames;
var
I, J: integer;
begin
for J := 0 to List.Count-1 do
if (TFrameBase(List[J]) is TfvFrame) then
begin
with TfvFrame(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 (TFrameBase(List[J]) is TSubFrameSet) then
TSubFrameSet(List[J]).ClearFrameNames;
end;
{----------------TSubFrameSet.AddFrameNames}
procedure TSubFrameSet.AddFrameNames;
var
J: integer;
Frame: TfvFrame;
begin
for J := 0 to List.Count-1 do
if (TFrameBase(List[J]) is TfvFrame) then
begin
Frame := TfvFrame(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 (TFrameBase(List[J]) is TSubFrameSet) then
TSubFrameSet(List[J]).AddFrameNames;
end;
{----------------TSubFrameSet.Destroy}
destructor TSubFrameSet.Destroy;
begin
List.Free;
List := Nil;
RefreshTimer.Free;
inherited Destroy;
end;
{----------------TSubFrameSet.AddFrame}
function TSubFrameSet.AddFrame(Attr: TAttributeList; const FName: string): TfvFrame;
{called by the parser when <Frame> is encountered within the <Frameset>
definition}
begin
Result := TfvFrame.CreateIt(Self, Attr, MasterSet, ExtractFilePath(FName));
List.Add(Result);
Result.SetBounds(OuterBorder, OuterBorder, Width-2*OuterBorder, Height-2*OuterBorder);
InsertControl(Result);
end;
{----------------TSubFrameSet.DoAttributes}
procedure TSubFrameSet.DoAttributes(L: TAttributeList);
{called by the parser to process the <Frameset> attributes}
var
T: TAttribute;
S: string;
Numb: string[20];
procedure GetDims;
const
EOL = ^M;
var
Ch: char;
I, N: integer;
procedure GetCh;
begin
if I > Length(S) then Ch := EOL
else
begin
Ch := S[I];
Inc(I);
end;
end;
begin
if Name = '' then S := T.Name
else Exit;
I := 1; DimCount := 0;
repeat
Inc(DimCount);
Numb := '';
GetCh;
while not (Ch in ['0'..'9', '*', EOL, ',']) do GetCh;
if Ch in ['0'..'9'] then
begin
while Ch in ['0'..'9'] do
begin
Numb := Numb+Ch;
GetCh;
end;
N := IntMax(1, StrToInt(Numb)); {no zeros}
while not (Ch in ['*', '%', ',', EOL]) do GetCh;
if ch = '*' then
begin
Dim[DimCount] := -IntMin(99, N);{store '*' relatives as negative, -1..-99}
GetCh;
end
else if Ch = '%' then
begin {%'s stored as -(100 + %), i.e. -110 is 10% }
Dim[DimCount] := -IntMin(1000, N+100); {limit to 900%}
GetCh;
end
else Dim[DimCount] := IntMin(N, 5000); {limit absolute to 5000}
end
else if Ch in ['*', ',', EOL] then
begin
Dim[DimCount] := -1;
if Ch = '*' then GetCh;
end;
while not (Ch in [',', EOL]) do GetCh;
until (Ch = EOL) or (DimCount = 20);
end;
begin
{read the row or column widths into the Dim array}
If L.Find(RowsSy, T) then
begin
Rows := True;
GetDims;
end;
if L.Find(ColsSy, T) and (DimCount <=1) then
begin
Rows := False;
DimCount := 0;
GetDims;
end;
if (Self = MasterSet) and not (fvNoBorder in MasterSet.FrameViewer.FOptions) then
{BorderSize already defined as 0}
if L.Find(BorderSy, T) or L.Find(FrameBorderSy, T)then
begin
BorderSize := T.Value;
OuterBorder := IntMax(2-BorderSize, 0);
if OuterBorder >= 1 then
begin
BevelWidth := OuterBorder;
BevelOuter := bvLowered;
end;
end
else BorderSize := 2;
end;
{----------------TSubFrameSet.LoadFiles}
procedure TSubFrameSet.LoadFiles;
var
I: integer;
Item: TFrameBase;
begin
for I := 0 to List.Count-1 do
begin
Item := TFrameBase(List.Items[I]);
Item.LoadFiles(Nil);
end;
end;
{----------------TSubFrameSet.ReloadFiles}
procedure TSubFrameSet.ReloadFiles(APosition: integer);
var
I: integer;
Item: TFrameBase;
begin
for I := 0 to List.Count-1 do
begin
Item := TFrameBase(List.Items[I]);
Item.ReloadFiles(APosition);
end;
if (FRefreshDelay > 0) and Assigned(RefreshTimer) then
SetRefreshTimer;
Unloaded := False;
end;
{----------------TSubFrameSet.UnloadFiles}
procedure TSubFrameSet.UnloadFiles;
var
I: integer;
Item: TFrameBase;
begin
if Assigned(RefreshTimer) then
RefreshTimer.Enabled := False;
for I := 0 to List.Count-1 do
begin
Item := TFrameBase(List.Items[I]);
Item.UnloadFiles;
end;
if Assigned(MasterSet.FrameViewer.FOnSoundRequest) then
MasterSet.FrameViewer.FOnSoundRequest(MasterSet, '', 0, True);
Unloaded := True;
end;
{----------------TSubFrameSet.EndFrameSet}
procedure TSubFrameSet.EndFrameSet;
{called by the parser when </FrameSet> is encountered}
var
I: integer;
begin
if List.Count > DimCount then {a value left out}
begin {fill in any blanks in Dim array}
for I := DimCount+1 to List.Count do
begin
Dim[I] := -1; {1 relative unit}
Inc(DimCount);
end;
end
else while DimCount > List.Count do {or add Frames if more Dims than Count}
AddFrame(Nil, '');
if ReadHTML.Base <> '' then
FBase := ReadHTML.Base
else FBase := MasterSet.FrameViewer.FBaseEx;
FBaseTarget := ReadHTML.BaseTarget;
end;
{----------------TSubFrameSet.InitializeDimensions}
procedure TSubFrameSet.InitializeDimensions(X, Y, Wid, Ht: integer);
var
I, Total, PixTot, PctTot, RelTot, Rel, Sum,
Remainder, PixDesired, PixActual: integer;
begin
if Rows then
Total := Ht
else Total := Wid;
PixTot := 0; RelTot := 0; PctTot := 0; DimFTot := 0;
for I := 1 to DimCount do {count up the total pixels, %'s and relatives}
if Dim[I] >= 0 then
PixTot := PixTot + Dim[I]
else if Dim[I] <= -100 then
PctTot := PctTot + (-Dim[I]-100)
else RelTot := RelTot - Dim[I];
Remainder := Total - PixTot;
if Remainder <= 0 then
begin {% and Relative are 0, must scale absolutes}
for I := 1 to DimCount do
begin
if Dim[I] >= 0 then
DimF[I] := MulDiv(Dim[I], Total, PixTot) {reduce to fit}
else DimF[I] := 0;
Inc(DimFTot, DimF[I]);
end;
end
else {some remainder left for % and relative}
begin
PixDesired := MulDiv(Total, PctTot, 100);
if PixDesired > Remainder then
PixActual := Remainder
else PixActual := PixDesired;
Dec(Remainder, PixActual); {Remainder will be >= 0}
if RelTot > 0 then
Rel := Remainder div RelTot {calc each relative unit}
else Rel := 0;
for I := 1 to DimCount do {calc the actual pixel widths (heights) in DimF}
begin
if Dim[I] >= 0 then
DimF[I] := Dim[I]
else if Dim[I] <= -100 then
DimF[I] := MulDiv(-Dim[I]-100, PixActual, PctTot)
else DimF[I] := -Dim[I] * Rel;
Inc(DimFTot, DimF[I]);
end;
end;
Sum := 0;
for I := 0 to List.Count-1 do {intialize the dimensions of contained items}
begin
if Rows then
TFrameBase(List.Items[I]).InitializeDimensions(X, Y+Sum, Wid, DimF[I+1])
else
TFrameBase(List.Items[I]).InitializeDimensions(X+Sum, Y, DimF[I+1], Ht);
Sum := Sum+DimF[I+1];
end;
end;
{----------------TSubFrameSet.CalcSizes}
{OnResize event comes here}
procedure TSubFrameSet.CalcSizes(Sender: TObject);
var
I, Step, Sum, ThisTotal: integer;
ARect: TRect;
begin
{Note: this method gets called during Destroy as it's in the OnResize event.
Hence List may be Nil.}
if Assigned(List) and (List.Count > 0) then
begin
ARect := ClientRect;
InflateRect(ARect, -OuterBorder, -OuterBorder);
Sum := 0;
if Rows then ThisTotal := ARect.Bottom - ARect.Top
else ThisTotal := ARect.Right-ARect.Left;
for I := 0 to List.Count-1 do
begin
Step := MulDiv(DimF[I+1], ThisTotal, DimFTot);
if Rows then
TFrameBase(List.Items[I]).SetBounds(ARect.Left, ARect.Top+Sum, ARect.Right-ARect.Left, Step)
else
TFrameBase(List.Items[I]).SetBounds(ARect.Left+Sum, ARect.Top, Step, ARect.Bottom-Arect.Top);
Sum := Sum+Step;
Lines[I+1] := Sum;
end;
end;
end;
{----------------TSubFrameSet.NearBoundary}
function TSubFrameSet.NearBoundary(X, Y: integer): boolean;
begin
Result := (Abs(X) < 4) or (Abs(X - Width) < 4) or
(Abs(Y) < 4) or (Abs(Y-Height) < 4);
end;
{----------------TSubFrameSet.GetRect}
function TSubFrameSet.GetRect: TRect;
{finds the FocusRect to draw when draging boundaries}
var
Pt, Pt1, Pt2: TPoint;
begin
Pt1 := Point(0, 0);
Pt1 := ClientToScreen(Pt1);
Pt2 := Point(ClientWidth, ClientHeight);
Pt2 := ClientToScreen(Pt2);
GetCursorPos(Pt);
if Rows then
Result := Rect(Pt1.X, Pt.Y-1, Pt2.X, Pt.Y+1)
else
Result := Rect(Pt.X-1, Pt1.Y, Pt.X+1, Pt2.Y);
OldRect := Result;
end;
{----------------DrawRect}
procedure DrawRect(ARect: TRect);
{Draws a Focus Rect}
var
DC: HDC;
begin
DC := GetDC(0);
DrawFocusRect(DC, ARect);
ReleaseDC(0, DC);
end;
{----------------TSubFrameSet.FVMouseDown}
procedure TSubFrameSet.FVMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
ACursor: TCursor;
RP: record
case boolean of
True: (P1, P2: TPoint);
False:(R: TRect);
end;
begin
if Button <> mbLeft then Exit;
if NearBoundary(X, Y) then
begin
if Parent is TFrameBase then
(Parent as TFrameBase).FVMouseDown(Sender, Button, Shift, X+Left, Y+Top)
else
Exit;
end
else
begin
ACursor := (Sender as TFrameBase).Cursor;
if (ACursor = crVSplit) or(ACursor = crHSplit) then
begin
MasterSet.HotSet := Self;
with RP do
begin {restrict cursor to lines on both sides}
if Rows then
R := Rect(0, Lines[LineIndex-1]+1, ClientWidth, Lines[LineIndex+1]-1)
else
R := Rect(Lines[LineIndex-1]+1, 0, Lines[LineIndex+1]-1, ClientHeight);
P1 := ClientToScreen(P1);
P2 := ClientToScreen(P2);
ClipCursor(@R);
end;
DrawRect(GetRect);
end;
end;
end;
{----------------TSubFrameSet.FindLineAndCursor}
procedure TSubFrameSet.FindLineAndCursor(Sender: TObject; X, Y: integer);
var
ACursor: TCursor;
Gap, ThisGap, Line, I: integer;
begin
if not Assigned(MasterSet.HotSet) then
begin {here we change the cursor as mouse moves over lines,button up or down}
if Rows then Line := Y else Line := X;
Gap := 9999;
for I := 1 to DimCount-1 do
begin
ThisGap := Line-Lines[I];
if Abs(ThisGap) < Abs(Gap) then
begin
Gap := Line - Lines[I];
LineIndex := I;
end
else if Abs(ThisGap) = Abs(Gap) then {happens if 2 lines in same spot}
if ThisGap >= 0 then {if Pos, pick the one on right (bottom)}
LineIndex := I;
end;
if (Abs(Gap) <= 4) and not Fixed[LineIndex] then
begin
if Rows then
ACursor := crVSplit
else ACursor := crHSplit;
(Sender as TFrameBase).Cursor := ACursor;
end
else (Sender as TFrameBase).Cursor := MasterSet.FrameViewer.Cursor;
end
else
with TSubFrameSet(MasterSet.HotSet) do
begin
DrawRect(OldRect);
DrawRect(GetRect);
end;
end;
{----------------TSubFrameSet.FVMouseMove}
procedure TSubFrameSet.FVMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if NearBoundary(X, Y) then
(Parent as TFrameBase).FVMouseMove(Sender, Shift, X+Left, Y+Top)
else
FindLineAndCursor(Sender, X, Y);
end;
{----------------TSubFrameSet.FVMouseUp}
procedure TSubFrameSet.FVMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
var
I: integer;
begin
if Button <> mbLeft then Exit;
if MasterSet.HotSet = Self then
begin
MasterSet.HotSet := Nil;
DrawRect(OldRect);
ClipCursor(Nil);
if Rows then
Lines[LineIndex] := Y else Lines[LineIndex] := X;
for I := 1 to DimCount do
if I = 1 then DimF[1] := MulDiv(Lines[1], DimFTot, Lines[DimCount])
else DimF[I] := MulDiv((Lines[I] - Lines[I-1]), DimFTot, Lines[DimCount]);
CalcSizes(Self);
Invalidate;
end
else if (Parent is TFrameBase) then
(Parent as TFrameBase).FVMouseUp(Sender, Button, Shift, X+Left, Y+Top);
end;
{----------------TSubFrameSet.CheckNoResize}
function TSubFrameSet.CheckNoResize(var Lower, Upper: boolean): boolean;
var
Lw, Up: boolean;
I: integer;
begin
Result := False; Lower := False; Upper := False;
for I := 0 to List.Count-1 do
with TFrameBase(List[I]) do
if CheckNoResize(Lw, Up) then
begin
Result := True; {sides are fixed}
Fixed[I] := True; {these edges are fixed}
Fixed[I+1] := True;
If Lw and (I = 0) then Lower := True;
If Up and (I = List.Count-1) then Upper := True;
end;
end;
{----------------TSubFrameSet.Clear}
procedure TSubFrameSet.Clear;
var
I: integer;
X: TFrameBase;
begin
for I := List.Count-1 downto 0 do
begin
X := List.Items[I];
List.Delete(I);
RemoveControl(X);
X.Free;
end;
DimCount := 0;
First := True;
Rows := False;
FillChar(Fixed, Sizeof(Fixed), 0);
FillChar(Lines, Sizeof(Lines), 0);
FBase := '';
FBaseTarget := '';
end;
{----------------TSubFrameSet.LoadFromFile}
procedure TSubFrameSet.LoadFromFile(const FName, Dest: string);
var
Frame: TfvFrame;
begin
Clear;
Frame := AddFrame(Nil, '');
Frame.Source := FName;
Frame.Destination := Dest;
EndFrameSet;
Frame.LoadFiles(Nil);
if Assigned(Frame.FrameSet) then
with Frame.FrameSet do
begin
with ClientRect do
InitializeDimensions(Left, Top, Right-Left, Bottom-Top);
CalcSizes(Nil);
end
else if Assigned(Frame.Viewer) then
Frame.Viewer.PositionTo(Dest);
MasterSet.FrameViewer.AddVisitedLink(FName+Dest);
end;
{----------------TSubFrameSet.UpdateFrameList}
procedure TSubFrameSet.UpdateFrameList;
var
I: integer;
begin
for I := 0 to List.Count-1 do
TFrameBase(List[I]).UpdateFrameList;
end;
{----------------TSubFrameSet.HandleMeta}
procedure TSubFrameSet.HandleMeta(Sender: TObject; const HttpEq, Name, Content: string);
var
DelTime, I: integer;
begin
{$ifdef ver100_plus} {Delphi 3,4,5, C++Builder 3, 4}
if CompareText(HttpEq, 'content-type') = 0 then
TranslateCharset(Content, LocalCharset);
{$endif}
with MasterSet.FrameViewer do
begin
if Assigned(FOnMeta) then FOnMeta(Sender, HttpEq, Name, Content);
if not (fvMetaRefresh in FOptions) then Exit;
end;
if CompareText(Lowercase(HttpEq), 'refresh') = 0 then
begin
I := Pos(';', Content);
if I > 0 then
DelTime := StrToIntDef(copy(Content, 1, I-1), -1)
else DelTime := StrToIntDef(Content, -1);
if DelTime < 0 then Exit
else if DelTime = 0 then DelTime := 1;
I := Pos('url=', Lowercase(Content));
if I > 0 then
FRefreshURL := Copy(Content, I+4, Length(Content)-I-3)
else if Owner is TfvFrame then
FRefreshURL := TfvFrame(Owner).Source
else FRefreshURL := '';
FRefreshDelay := DelTime;
end;
end;
{----------------TSubFrameSet.SetRefreshTimer}
procedure TSubFrameSet.SetRefreshTimer;
begin
NextFile := HTMLToDos(FRefreshURL);
if not FileExists(NextFile) then
Exit;
if not Assigned(RefreshTimer) then
RefreshTimer := TTimer.Create(Self);
RefreshTimer.OnTimer := RefreshTimerTimer;
RefreshTimer.Interval := FRefreshDelay*1000;
RefreshTimer.Enabled := True;
end;
{----------------TSubFrameSet.RefreshTimerTimer}
procedure TSubFrameSet.RefreshTimerTimer(Sender: Tobject);
var
S, D: string;
begin
RefreshTimer.Enabled := False;
if Unloaded then Exit;
if Owner is TfvFrame then
begin
SplitURL(NextFile, S, D);
TfvFrame(Owner).frLoadFromFile(S, D, True, True);
end;
end;
{----------------TFrameSet.Create}
constructor TFrameSet.Create(AOwner: TComponent);
begin
inherited CreateIt(AOwner, Self);
FrameViewer := AOwner as TFrameViewer;
{$ifdef ver100_plus} {Delphi 3,4,5, C++Builder 3, 4}
LocalCharSet := FrameViewer.FCharset;
{$endif}
if fvNoBorder in FrameViewer.FOptions then
BorderSize := 0
else
BorderSize := 2;
BevelOuter := bvNone;
FTitle := '';
FCurrentFile:= '';
FrameNames := TStringList.Create;
FrameNames.Sorted := True;
Viewers := TList.Create;
Frames := TList.Create;
OnResize := CalcSizes;
end;
{----------------TFrameSet.Destroy}
destructor TFrameSet.Destroy;
begin
FrameNames.Free;
FrameNames := Nil; {is tested later}
Viewers.Free;
Viewers := Nil;
Frames.Free;
Frames := Nil;
inherited Destroy;
end;
{----------------TFrameSet.Clear}
procedure TFrameSet.Clear;
begin
inherited Clear;
FrameNames.Clear;
Viewers.Clear;
Frames.Clear;
HotSet := Nil;
FTitle := '';
FCurrentFile := '';
OldHeight := 0;
OldWidth := 0;
FActive := Nil;
end;
procedure TFrameSet.RePaint;
var
I: integer;
begin
if Assigned(Frames) then
for I := 0 to Frames.Count-1 do
{$IFNDEF LCL}
TWinControl(Frames[I]).RePaint;
{$ELSE}
TCustomControl(Frames[I]).RePaint;
{$ENDIF}
inherited;
end;
{----------------TFrameSet.RequestEvent}
function TFrameSet.RequestEvent: boolean;
begin
with FrameViewer do
Result := Assigned(FOnStringsRequest) or Assigned(FOnStreamRequest)
or Assigned(FOnBufferRequest) or Assigned(FOnFileRequest);
end;
{----------------TFrameSet.TriggerEvent}
function TFrameSet.TriggerEvent(const Src: string; PEV: PEventRec): boolean;
var
AName: string;
BStream: TMemoryStream;
Strings: TStrings;
Stream: TStream;
Buffer: PChar;
BuffSize: integer;
begin
with PEV^ do
begin
Result := False; LStyle := lsFile;
Buffer := Nil; BuffSize := 0;
AName := '';
AString := '';
Stream := Nil;
with FrameViewer do
if Assigned(FOnStringsRequest) then
begin
FOnStringsRequest(Self, Src, Strings);
Result := Assigned(Strings);
if Result then
begin
LStyle := lsString;
AString := Strings.Text;
end;
end
else if Assigned(FOnStreamRequest) then
begin
FOnStreamRequest(Self, Src, Stream);
Result := Assigned(Stream);
if Result then
begin
LStyle := lsString;
BStream := TMemoryStream.Create;
try
BStream.LoadFromStream(Stream);
SetLength(AString, BStream.Size);
Move(BStream.Memory^, AString[1], BStream.Size);
finally
BStream.Free;
end;
end;
end
else if Assigned(FOnBufferRequest) then
begin
FOnBufferRequest(Self, Src, Buffer, BuffSize);
Result := (BuffSize > 0) and Assigned(Buffer);
if Result then
begin
LStyle := lsString;
SetLength(AString, BuffSize);
Move(Buffer^, AString[1], BuffSize);
end;
end
else if Assigned(FOnFileRequest) then
begin
FOnFileRequest(Self, Src, AName);
Result := AName <> '';
if Result then
begin
LStyle := lsFile;
NewName := AName;
AString := FileToString(NewName);
end;
end;
end;
end;
{----------------TFrameSet.EndFrameSet}
procedure TFrameSet.EndFrameSet;
begin
FTitle := ReadHTML.Title;
inherited EndFrameSet;
with ClientRect do
InitializeDimensions(Left, Top, Right-Left, Bottom-Top);
end;
{----------------TFrameSet.CalcSizes}
{OnResize event comes here}
procedure TFrameSet.CalcSizes(Sender: TObject);
var
ARect: TRect;
begin
ARect := ClientRect;
InflateRect(ARect, -OuterBorder, -OuterBorder);
with ARect do
begin
if (OldWidth <> Right-Left) or (OldHeight <> Bottom-Top) then
begin
InitializeDimensions(Left, Top, Right-Left, Bottom-Top);
inherited CalcSizes(Sender);
end;
OldWidth := Right-Left;
OldHeight := Bottom-Top;
end;
end;
{----------------TFrameSet.CheckActive}
procedure TFrameSet.CheckActive(Sender: TObject);
begin
if Sender is ThtmlViewer then
FActive := ThtmlViewer(Sender);
end;
{----------------TFrameSet.GetActive}
function TFrameSet.GetActive: ThtmlViewer;
begin
if Viewers.Count = 1 then
Result := ThtmlViewer(Viewers[0])
else
try
if FActive is ThtmlViewer then Result := FActive
else Result := Nil;
except
Result := Nil;
end;
end;
{----------------TFrameSet.FVMouseMove}
procedure TFrameSet.FVMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
FindLineAndCursor(Sender, X, Y);
if (LineIndex = 0) or (LineIndex = DimCount) then
begin {picked up the outer boundary}
(Sender as TFrameBase).Cursor := MasterSet.FrameViewer.Cursor;
Cursor := MasterSet.FrameViewer.Cursor;
end;
end;
{----------------TFrameSet.LoadFromFile}
procedure TFrameSet.LoadFromFile(const FName, Dest: string);
var
I: integer;
Item: TFrameBase;
Frame: TfvFrame;
Lower, Upper: boolean;
EV: EventRec;
EventPointer: PEventRec;
Img, Tex: boolean;
begin
Clear;
NestLevel := 0;
EV.LStyle := lsFile;
Img := ImageFile(FName) and not RequestEvent;
Tex := TexFile(FName) and not RequestEvent;
if Img or Tex or
not TriggerEvent(FName, @EV) then
begin
EV.NewName := ExpandFileName(FName);
FCurrentFile := EV.NewName;
end
else
begin {triggerevent}
FCurrentFile := FName;
end;
FRefreshDelay := 0;
if not Img and not Tex
and IsFrameString(EV.LStyle, EV.NewName, EV.AString, MasterSet.FrameViewer) then
begin {it's a Frameset html file}
FrameParseString(MasterSet.FrameViewer, Self, EV.LStyle, EV.NewName, EV.AString, HandleMeta);
for I := 0 to List.Count-1 do
Begin
Item := TFrameBase(List.Items[I]);
Item.LoadFiles(Nil);
end;
CalcSizes(Self);
CheckNoresize(Lower, Upper);
if FRefreshDelay > 0 then
SetRefreshTimer;
end
else
begin {it's a non frame file}
Frame := AddFrame(Nil, '');
if not Img and not Tex and RequestEvent then
begin
Frame.Source := FName;
EventPointer := @EV;
end
else
begin
Frame.Source := EV.NewName;
EventPointer := Nil;
end;
Frame.Destination := Dest;
EndFrameSet;
CalcSizes(Self);
Frame.Loadfiles(EventPointer);
FTitle := ReadHTML.Title;
FBaseTarget := ReadHTML.BaseTarget;
end;
end;
procedure TFrameSet.RefreshTimerTimer(Sender: Tobject);
begin
RefreshTimer.Enabled := False;
if (Self = MasterSet.FrameViewer.CurFrameSet) then
FrameViewer.LoadFromFileInternal(NextFile);
end;
{----------------TFrameSet.ClearForwards}
procedure TFrameSet.ClearForwards;
{clear all the forward items in the history lists}
var
I, J: integer;
Frame: TfvFrame;
AList: TList;
Obj: TObject;
begin
AList := TList.Create;
for J := 0 to Frames.Count-1 do
begin
Frame := TfvFrame(Frames[J]);
with Frame do
begin
for I := 0 to frHistoryIndex-1 do
begin
Obj := frHistory.Objects[0];
if Assigned(Obj) and (AList.IndexOf(Obj) < 0) then
AList.Add(Obj);
frHistory.Delete(0);
PositionObj(frPositionHistory[0]).Free;
frPositionHistory.Delete(0);
end;
frHistoryIndex := 0;
end;
end;
for J := 0 to Frames.Count-1 do {now see which Objects are no longer used}
begin
Frame := TfvFrame(Frames[J]);
with Frame do
begin
for I := 0 to frHistory.Count-1 do
begin
Obj := frHistory.Objects[I];
if Assigned(Obj) and (AList.IndexOf(Obj) > -1) then
AList.Remove(Obj); {remove it if it's there}
end;
end;
end;
for I := 0 to AList.Count-1 do {destroy what's left}
TObject(AList[I]).Free;
AList.Free;
end;
{----------------TFrameSet.UpdateFrameList}
procedure TFrameSet.UpdateFrameList;
{Fill Frames with a list of all current TFrames}
begin
Frames.Clear;
inherited UpdateFrameList;
end;
{----------------TFrameViewer.Create}
constructor TFrameViewer.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Height := 150;
Width := 150;
ProcessList := TList.Create;
FLinkAttributes := TStringList.Create;
FViewImages := True;
FBitmapList := TStringBitmapList.Create;
FImageCacheCount := 5;
FHistory := TStringList.Create;
FPosition := TList.Create;
FTitleHistory := TStringList.Create;
FBackground := clBtnFace;
FFontColor := clBtnText;
FHotSpotColor := clBlue;
FVisitedColor := clPurple;
FOverColor := clBlue;
FVisitedMaxCount := 50;
FFontSize := 12;
FFontName := 'Times New Roman';
FPreFontName := 'Courier New';
FCursor := crIBeam;
FDither := True;
TabStop := False;
FPrintMarginLeft := 2.0;
FPrintMarginRight := 2.0;
FPrintMarginTop := 2.0;
FPrintMarginBottom := 2.0;
FPrintScale := 1.0;
FMarginWidth := 10;
FMarginHeight := 5;
FOptions := [fvPrintTableBackground, fvPrintMonochromeBlack];
{$ifdef ver100_plus} {Delphi 3,4,5, C++Builder 3, 4}
FCharset := DEFAULT_CHARSET;
{$endif}
Visited := TStringList.Create;
CurFrameSet := TFrameSet.Create(Self);
if fvNoBorder in FOptions then
begin
CurFrameSet.OuterBorder := 0;
CurFrameSet.BevelOuter := bvNone;
end
else
begin
CurFrameSet.OuterBorder := 2;
CurFrameSet.BevelWidth := 2;
CurFrameSet.BevelOuter := bvLowered;
end;
CurFrameSet.Align := alClient;
CurFrameSet.OnDragDrop := FOnDragDrop;
CurFrameSet.OnDragOver := FOnDragOver;
InsertControl(CurFrameSet);
end;
{----------------TFrameViewer.Destroy}
destructor TFrameViewer.Destroy;
begin
UrlRequestStream.Free;
ProcessList.Free;
FLinkAttributes.Free;
FHistory.Free;
FPosition.Free;
FTitleHistory.Free;
Visited.Free;
FViewerList.Free;
inherited Destroy;
FBitmapList.Free;
end;
{----------------TFrameViewer.Clear}
procedure TFrameViewer.Clear;
var
I: integer;
Obj: TObject;
begin
if not Processing then
begin
for I := 0 to FHistory.Count-1 do
with FHistory do
begin
Obj := Objects[0];
Delete(0);
if Obj <> CurFrameset then
ChkFree(Obj);
end;
with CurFrameSet do
begin
Clear;
BevelOuter := bvLowered;
BevelWidth := 2;
end;
FBitmapList.Clear;
FURL := '';
FTarget := '';
FBaseEx := '';
FHistoryIndex := 0;
FPosition.Clear;
FTitleHistory.Clear;
if Assigned(FOnHistoryChange) then
FOnHistoryChange(Self);
Visited.Clear;
if Assigned(FViewerList) then
FViewerList.Clear;
end;
end;
{----------------TFrameViewer.LoadFromFile}
procedure TFrameViewer.LoadFromFile(const FName: string);
var
S, Dest: string;
begin
if not Processing then
begin
SplitURL(FName, S, Dest);
if not FileExists(S) then
Raise(EfvLoadError.Create('Can''t locate file: '+S));
LoadFromFileInternal(FName);
end;
end;
{----------------TFrameViewer.LoadFromFileInternal}
procedure TFrameViewer.LoadFromFileInternal(const FName: string);
var
OldFrameSet: TFrameSet;
OldFile, S, Dest: string;
OldPos: integer;
Tmp: TObject;
SameName: boolean;
{$ifdef Windows}
Dummy: integer;
{$endif}
begin
FProcessing := True;
if Assigned(FOnProcessing) then
FOnProcessing(Self, True);
{$ifdef windows}
Dummy :=
{$endif}
IOResult; {remove any pending file errors}
SplitURL(FName, S, Dest);
try
OldFile := CurFrameSet.FCurrentFile;
ProcessList.Clear;
if Assigned(FOnSoundRequest) then
FOnSoundRequest(Self, '', 0, True);
SameName := CompareText(OldFile, S) = 0;
if not SameName then
begin
OldFrameSet := CurFrameSet;
CurFrameSet := TFrameSet.Create(Self);
CurFrameSet.Align := alClient;
CurFrameSet.visible := False;
InsertControl(CurFrameSet);
CurFrameSet.SendToBack;
CurFrameSet.Visible := True;
try
CurFrameSet.LoadFromFile(S, Dest);
except
RemoveControl(CurFrameSet);
CurFrameSet.Free;
CurFrameSet := OldFrameSet;
Raise;
end;
OldPos := 0;
if (OldFrameSet.Viewers.Count = 1) then
begin
Tmp := OldFrameSet.Viewers[0];
if Tmp is ThtmlViewer then
OldPos := ThtmlViewer(Tmp).Position;
end;
OldFrameSet.UnloadFiles;
CurFrameSet.Visible := True;
if Visible then
begin
SendMessage(Handle, wm_SetRedraw, 0, 0);
try
CurFrameSet.BringToFront;
finally
SendMessage(Handle, wm_SetRedraw, 1, 0);
Repaint;
end;
CurFrameSet.Repaint;
end;
RemoveControl(OldFrameSet);
BumpHistory(OldFrameSet, OldPos);
end
else
begin {Same Name}
OldPos := 0;
if (CurFrameSet.Viewers.Count = 1) then
begin
Tmp := CurFrameSet.Viewers[0];
if Tmp is ThtmlViewer then
OldPos := ThtmlViewer(Tmp).Position;
end;
SendMessage(Handle, wm_SetRedraw, 0, 0);
try
CurFrameSet.LoadFromFile(S, Dest);
finally
SendMessage(Handle, wm_SetRedraw, 1, 0);
Repaint;
end;
BumpHistory2(OldPos); {not executed if exception occurs}
end;
AddVisitedLink(S+Dest);
CheckVisitedLinks;
finally
FProcessing := False;
if Assigned(FOnProcessing) then
FOnProcessing(Self, False);
end;
end;
{----------------TFrameViewer.Load}
procedure TFrameViewer.Load(const SRC: string);
begin
if Assigned(FOnStringsRequest) or Assigned(FOnStreamRequest)
or Assigned(FOnBufferRequest) or Assigned(FOnFileRequest) then
LoadFromFileInternal(SRC);
end;
{----------------TFrameViewer.LoadTargetFromFile}
procedure TFrameViewer.LoadTargetFromFile(const Target, FName: string);
var
I: integer;
FrameTarget: TFrameBase;
S, Dest: string;
begin
if Processing then Exit;
if CurFrameSet.FrameNames.Find(Target, I) then
FrameTarget := (CurFrameSet.FrameNames.Objects[I] as TfvFrame)
else if (Target = '') or (CompareText(Target, '_top') = 0) or
(CompareText(Target, '_parent') = 0) or (CompareText(Target, '_self') = 0)then
begin
LoadFromFileInternal(Fname);
Exit;
end
else
begin {_blank or unknown target}
if Assigned(FOnBlankWindowRequest) then
FOnBlankWindowRequest(Self, Target, FName);
Exit;
end;
SplitURL(FName, S, Dest);
if not FileExists(S) and not Assigned(OnStreamRequest) then
Raise(EfvLoadError.Create('Can''t locate file: '+S));
FProcessing := True;
if Assigned(FOnProcessing) then
FOnProcessing(Self, True);
try
if FrameTarget is TfvFrame then
TfvFrame(FrameTarget).frLoadFromFile(S, Dest, True, False)
else if FrameTarget is TSubFrameSet then
TSubFrameSet(FrameTarget).LoadFromFile(S, Dest);
finally
if Assigned(FOnProcessing) then
FOnProcessing(Self, False);
FProcessing := False;
end;
end;
{----------------TFrameViewer.LoadImageFile}
procedure TFrameViewer.LoadImageFile(const FName: string);
begin
if ImageFile(FName) then
LoadFromFile(FName);
end;
{----------------TFrameViewer.Reload}
procedure TFrameViewer.Reload;
begin
FProcessing := True;
if Assigned(FOnProcessing) then
FOnProcessing(Self, True);
try
ProcessList.Clear;
CurFrameSet.UnloadFiles;
CurFrameSet.ReloadFiles(-1);
CheckVisitedLinks;
finally
FProcessing := False;
if Assigned(FOnProcessing) then
FOnProcessing(Self, False);
end;
end;
{----------------TFrameViewer.GetFwdButtonEnabled}
function TFrameViewer.GetFwdButtonEnabled: boolean;
var
I: integer;
Frame: TfvFrame;
begin
Result := fHistoryIndex >= 1;
if not Result then
for I := 0 to CurFrameSet.Frames.Count-1 do
begin
Frame := TfvFrame(CurFrameSet.Frames[I]);
with Frame do
if frHistoryIndex >= 1 then
begin
Result := True;
Exit;
end;
end;
end;
{----------------TFrameViewer.GetBackButtonEnabled}
function TFrameViewer.GetBackButtonEnabled: boolean;
var
I: integer;
Frame: TfvFrame;
begin
Result := fHistoryIndex <= fHistory.Count-2;
if not Result then
for I := 0 to CurFrameSet.Frames.Count-1 do
begin
Frame := TfvFrame(CurFrameSet.Frames[I]);
with Frame do
if frHistoryIndex <= frHistory.Count-2 then
begin
Result := True;
Exit;
end;
end;
end;
procedure TFrameViewer.GoFwd;
var
I, Smallest, Index: integer;
Frame, TheFrame: TfvFrame;
begin
Smallest := 9999;
Index := 0; TheFrame := Nil; {to quiet the warnings}
for I := 0 to CurFrameSet.Frames.Count-1 do
begin
Frame := TfvFrame(CurFrameSet.Frames[I]);
with Frame do
if frHistoryIndex >= 1 then
with PositionObj(frPositionHistory[frHistoryIndex-1]) do
if Seq < Smallest then
begin
Smallest := Seq;
TheFrame := Frame;
Index := frHistoryIndex;
end;
end;
if Smallest < 9999 then
TheFrame.frSetHistoryIndex(Index - 1)
else SetHistoryIndex(fHistoryIndex - 1);
if Assigned(FOnSoundRequest) then
FOnSoundRequest(Self, '', 0, True);
end;
procedure TFrameViewer.GoBack;
var
I, Largest, Index: integer;
Frame, TheFrame: TfvFrame;
begin
Largest := -1;
Index := 0; TheFrame := Nil; {to quiet the warnings}
for I := 0 to CurFrameSet.Frames.Count-1 do
begin
Frame := TfvFrame(CurFrameSet.Frames[I]);
with Frame do
if frHistoryIndex <= frHistory.Count-2 then
with PositionObj(frPositionHistory[frHistoryIndex]) do
if Seq > Largest then
begin
Largest := Seq;
TheFrame := Frame;
Index := frHistoryIndex;
end;
end;
if Largest >= 0 then
TheFrame.frSetHistoryIndex(Index + 1)
else
SetHistoryIndex(fHistoryIndex+1);
if Assigned(FOnSoundRequest) then
FOnSoundRequest(Self, '', 0, True);
end;
{----------------TFrameViewer.HotSpotClickHandled:}
function TFrameViewer.HotSpotClickHandled: boolean;
var
Handled: boolean;
begin
Handled := False;
if Assigned(FOnHotSpotTargetClick) then
FOnHotSpotTargetClick(Self, FTarget, FURL, Handled);
Result := Handled;
end;
{----------------TFrameViewer.HotSpotClick}
procedure TFrameViewer.HotSpotClick(Sender: TObject; const AnURL: string;
var Handled: boolean);
var
I: integer;
Viewer: ThtmlViewer;
FrameTarget: TFrameBase;
S, Dest, Query: string;
begin
if Processing then
begin
Handled := True;
Exit;
end;
Viewer := (Sender as ThtmlViewer);
FURL := AnURL;
FTarget := GetActiveTarget;
FLinkAttributes.Text := Viewer.LinkAttributes.Text;
FLinkText := Viewer.LinkText;
Handled := HotSpotClickHandled;
if not Handled then
begin
Handled := True;
S := AnURL;
I := Pos('#', S);
if I >= 1 then
begin
Dest := System.Copy(S, I, Length(S)-I+1); {local destination}
S := System.Copy(S, 1, I-1); {the file name}
end
else
Dest := ''; {no local destination}
I := Pos('?', S); {remove any query string}
if I >= 1 then
begin
Query := System.Copy(S, I, Length(S)-I+1);
S := System.Copy(S, 1, I-1); {the file name}
end
else Query := '';
if (S <> '') and not CurFrameSet.RequestEvent then
S := Viewer.HTMLExpandFileName(S);
if (FTarget = '') or (CompareText(FTarget, '_self') = 0) then {no target or _self target}
begin
FrameTarget := Viewer.FrameOwner as TfvFrame;
if not Assigned(FrameTarget) then Exit;
end
else if CurFrameSet.FrameNames.Find(FTarget, I) then
FrameTarget := (CurFrameSet.FrameNames.Objects[I] as TfvFrame)
else if CompareText(FTarget, '_top') = 0 then
FrameTarget := CurFrameSet
else if CompareText(FTarget, '_parent') = 0 then
begin
FrameTarget := (Viewer.FrameOwner as TfvFrame).Owner as TFrameBase;
while Assigned(FrameTarget) and not (FrameTarget is TfvFrame)
and not (FrameTarget is TFrameSet) do
FrameTarget := FrameTarget.Owner as TFrameBase;
end
else
begin
if Assigned(FOnBlankWindowRequest) then
begin
AddVisitedLink(S+Query+Dest);
CheckVisitedLinks;
FOnBlankWindowRequest(Self, FTarget, AnURL);
Handled := True;
end
else Handled := FTarget <> ''; {true if can't find target window}
Exit;
end;
FProcessing := True;
if Assigned(FOnProcessing) then
FOnProcessing(Self, True);
if (FrameTarget is TfvFrame) and (CurFrameSet.Viewers.Count = 1) and (S <> '')
and (CompareText(S, CurFrameSet.FCurrentFile) <> 0) then
FrameTarget := CurFrameSet; {force a new FrameSet on name change}
try
if FrameTarget is TfvFrame then
TfvFrame(FrameTarget).frLoadFromFile(S, Dest, True, False)
else if FrameTarget is TFrameSet then
Self.LoadFromFileInternal(S + Dest)
else if FrameTarget is TSubFrameSet then
TSubFrameSet(FrameTarget).LoadFromFile(S, Dest);
if Query <> '' then
AddVisitedLink(S+Query+Dest);
CheckVisitedLinks;
finally
FProcessing := False; {changed position}
if Assigned(FOnProcessing) then
FOnProcessing(Self, False);
end;
end;
end;
function TFrameViewer.GetCurViewerCount: integer;
begin
Result := CurFrameSet.Viewers.Count;
end;
function TFrameViewer.GetCurViewer(I: integer): ThtmlViewer;
begin
Result := CurFrameSet.Viewers[I];
end;
{----------------TFrameViewer.HotSpotCovered}
procedure TFrameViewer.HotSpotCovered(Sender: TObject; const SRC: string);
begin
if Assigned(FOnHotSpotTargetCovered) then
with (Sender as ThtmlViewer) do
begin
FLinkText := LinkText;
FLinkAttributes.Text := LinkAttributes.Text;
FOnHotSpotTargetCovered(Sender, Target, Src);
end;
end;
{----------------TFrameViewer.GetActiveTarget}
function TFrameViewer.GetActiveTarget: string;
var
Vw: ThtmlViewer;
Done: boolean;
FSet: TSubFrameSet;
begin
Result := '';
Vw := GetActiveViewer;
if Assigned(Vw) then
begin
Result := Vw.Target;
if Result = '' then Result := Vw.BaseTarget;
Done := False;
FSet := TfvFrame(Vw.FrameOwner).LOwner;
while (Result = '') and Assigned(FSet) and not Done do
begin
Result := FSet.FBaseTarget;
Done := FSet = CurFrameSet;
if not Done then FSet := FSet.LOwner;
end;
end;
end;
{----------------TFrameViewer.GetActiveBase}
function TFrameViewer.GetActiveBase: string;
var
Vw: ThtmlViewer;
Done: boolean;
FSet: TSubFrameSet;
begin
Result := '';
Vw := GetActiveViewer;
if Assigned(Vw) then
begin
Result := Vw.Base;
Done := False;
FSet := TfvFrame(Vw.FrameOwner).LOwner;
while (Result = '') and Assigned(FSet) and not Done do
begin
Result := FSet.FBase;
Done := FSet = CurFrameSet;
if not Done then FSet := FSet.LOwner;
end;
end;
end;
{----------------TFrameViewer.HTMLExpandFilename}
function TFrameViewer.HTMLExpandFilename(const Filename: string): string;
var
BasePath: string;
Viewer: ThtmlViewer;
begin
Result := HTMLServerToDos(Trim(Filename), FServerRoot);
{$IFDEF MSWINDOWS}
if (Pos(':', Result)<> 2) and (Pos('\\', Result) <> 1) then
{$ELSE}
if Pos('/', Result) <> 1 then
{$ENDIF}
begin
BasePath := GetActiveBase;
if CompareText(BasePath, 'DosPath') = 0 then {let Dos find the path}
else
begin
if BasePath <> '' then
Result := HTMLToDos(BasePath) + Result
else
begin
Viewer := ActiveViewer;
if Assigned(Viewer) then
Result := Viewer.HTMLExpandFilename(Result)
else
Result := ExtractFilePath(CurFrameSet.FCurrentFile) + Result;
end;
end;
end;
end;
function TFrameViewer.GetBase: string;
begin
Result := CurFrameSet.FBase;
end;
procedure TFrameViewer.SetBase(Value: string);
begin
CurFrameSet.FBase := Value;
FBaseEx := Value;
end;
function TFrameViewer.GetBaseTarget: string;
begin
Result := CurFrameSet.FBaseTarget;
end;
function TFrameViewer.GetTitle: string;
begin
Result := CurFrameSet.FTitle;
end;
function TFrameViewer.GetCurrentFile: string;
begin
Result := CurFrameSet.FCurrentFile;
end;
{----------------TFrameViewer.GetActiveViewer}
function TFrameViewer.GetActiveViewer: ThtmlViewer;
begin
Result := CurFrameSet.GetActive;
end;
{----------------TFrameViewer.BumpHistory}
procedure TFrameViewer.BumpHistory(OldFrameSet: TFrameSet; OldPos: integer);
{OldFrameSet never equals CurFrameSet when this method called}
var
I: integer;
Obj: TObject;
begin
if (FHistoryMaxCount > 0) and (CurFrameSet.FCurrentFile <> '') then
with FHistory do
begin
if (Count > 0) then
begin
Strings[FHistoryIndex] := OldFrameSet.FCurrentFile;
Objects[FHistoryIndex] := OldFrameSet;
FTitleHistory[FHistoryIndex] := OldFrameSet.FTitle;
FPosition[FHistoryIndex] := TObject(OldPos);
OldFrameSet.ClearForwards;
end
else OldFrameSet.Free;
for I := 0 to FHistoryIndex-1 do
begin
Obj := Objects[0];
Delete(0);
ChkFree(Obj);
FTitleHistory.Delete(0);
FPosition.Delete(0);
end;
FHistoryIndex := 0;
Insert(0, CurFrameSet.FCurrentFile);
Objects[0] := CurFrameSet;
FTitleHistory.Insert(0, CurFrameSet.FTitle);
FPosition.Insert(0, Nil);
if Count > FHistoryMaxCount then
begin
Obj := Objects[FHistoryMaxCount];
Delete(FHistoryMaxCount);
ChkFree(Obj);
FTitleHistory.Delete(FHistoryMaxCount);
FPosition.Delete(FHistoryMaxCount);
end;
if Assigned(FOnHistoryChange) then FOnHistoryChange(Self);
end
else OldFrameSet.Free;
end;
{----------------TFrameViewer.BumpHistory1}
procedure TFrameViewer.BumpHistory1(const FileName, Title: string;
OldPos: integer; ft: ThtmlFileType);
{This variation called when CurFrameSet contains only a single viewer before
and after the change}
var
I: integer;
Obj: TObject;
begin
if (FHistoryMaxCount > 0) and (Filename <> '') then
with FHistory do
begin
if (Count > 0) then
begin
Strings[FHistoryIndex] := Filename;
Objects[FHistoryIndex] := CurFrameSet;
FTitleHistory[FHistoryIndex] := Title;
FPosition[FHistoryIndex] := TObject(OldPos);
end;
for I := 0 to FHistoryIndex-1 do
begin
Obj := Objects[0];
Delete(0);
ChkFree(Obj);
FTitleHistory.Delete(0);
FPosition.Delete(0);
end;
FHistoryIndex := 0;
Insert(0, CurFrameSet.FCurrentFile);
Objects[0] := CurFrameSet;
FTitleHistory.Insert(0, CurFrameSet.FTitle);
FPosition.Insert(0, Nil);
if Count > FHistoryMaxCount then
begin
Obj := Objects[FHistoryMaxCount];
Delete(FHistoryMaxCount);
ChkFree(Obj);
FTitleHistory.Delete(FHistoryMaxCount);
FPosition.Delete(FHistoryMaxCount);
end;
if Assigned(FOnHistoryChange) then FOnHistoryChange(Self);
end;
end;
{----------------TFrameViewer.BumpHistory2}
procedure TFrameViewer.BumpHistory2(OldPos: integer);
{CurFrameSet has not changed when this method called}
var
I: integer;
Obj: TObject;
begin
if (FHistoryMaxCount > 0) and (CurFrameSet.FCurrentFile <> '') then
with FHistory do
begin
if (Count > 0) then
begin
Strings[FHistoryIndex] := CurFrameSet.FCurrentFile;
Objects[FHistoryIndex] := CurFrameSet;
FTitleHistory[FHistoryIndex] := CurFrameSet.FTitle;
FPosition[FHistoryIndex] := TObject(OldPos);
end;
for I := 0 to FHistoryIndex-1 do
begin
Obj := Objects[0];
Delete(0);
ChkFree(Obj);
FTitleHistory.Delete(0);
FPosition.Delete(0);
end;
FHistoryIndex := 0;
Insert(0, CurFrameSet.FCurrentFile);
Objects[0] := CurFrameSet;
FTitleHistory.Insert(0, CurFrameSet.FTitle);
FPosition.Insert(0, Nil);
if Count > FHistoryMaxCount then
begin
Obj := Objects[FHistoryMaxCount];
Delete(FHistoryMaxCount);
ChkFree(Obj);
FTitleHistory.Delete(FHistoryMaxCount);
FPosition.Delete(FHistoryMaxCount);
end;
if Assigned(FOnHistoryChange) then FOnHistoryChange(Self);
end;
end;
{----------------TFrameViewer.SetHistoryIndex}
procedure TFrameViewer.SetHistoryIndex(Value: integer);
var
FrameSet, FrameSet1: TFrameSet;
Tmp: TObject;
begin
with CurFrameSet, FHistory do
if (Value <> FHistoryIndex) and (Value >= 0) and (Value < Count)
and not Processing then
begin
if CurFrameSet.Viewers.Count > 0 then
Tmp := CurFrameSet.Viewers[0]
else Tmp := Nil;
if FCurrentFile <> '' then
begin
{Objects[FHistoryIndex] should have CurFrameSet here}
FTitleHistory[FHistoryIndex] := CurFrameSet.FTitle;
if (Tmp is ThtmlViewer) then
FPosition[FHistoryIndex] := TObject((Tmp as ThtmlViewer).Position)
else FPosition[FHistoryIndex] := Nil;
end;
FrameSet := Objects[Value] as TFrameSet;
if FrameSet <> CurFrameSet then
begin
FrameSet1 := CurFrameSet; {swap framesets}
CurFrameSet := FrameSet;
CurFrameSet.OldWidth := 0; {encourage recalc of internal layout}
CurFrameSet.Visible := False;
Self.InsertControl(CurFrameSet);
if CurFrameSet.Viewers.Count = 1 then
CurFrameSet.ReloadFiles(integer(FPosition[Value]))
else
CurFrameSet.ReloadFiles(-1);
SendMessage(Self.handle, wm_SetRedraw, 0, 0);
CurFrameSet.Visible := True;
SendMessage(Self.handle, wm_SetRedraw, 1, 0);
CurFrameSet.Repaint;
FrameSet1.Unloadfiles;
Self.RemoveControl(FrameSet1);
end
else
begin
if (Tmp is ThtmlViewer) then
TfvFrame(ThtmlViewer(Tmp).FrameOwner).ReloadFile(FHistory[Value],
integer(FPosition[Value]));
end;
FHistoryIndex := Value;
if Assigned(FOnHistoryChange) then FOnHistoryChange(Self);
CheckVisitedLinks;
end;
end;
{----------------TFrameViewer.ChkFree}
procedure TFrameViewer.ChkFree(Obj: TObject);
{Frees a TFrameSet only if it no longer exists in FHistory}
var
I: integer;
begin
for I := 0 to FHistory.Count-1 do
if Obj = FHistory.Objects[I] then Exit;
(Obj as TFrameSet).Free;
end;
{----------------TFrameViewer.ClearHistory}
procedure TFrameViewer.ClearHistory;
var
I: integer;
Obj: TObject;
DidSomething: boolean;
begin
DidSomething := FHistory.Count > 0;
for I := FHistory.Count-1 downto 0 do
begin
Obj := FHistory.Objects[I];
FHistory.Delete(I);
if Obj <> CurFrameSet then
ChkFree(Obj);
end;
if Assigned(CurFrameSet) then
for I := 0 to CurFrameSet.Frames.Count-1 do
with TfvFrame(CurFrameSet.Frames[I]) do
begin
DidSomething := DidSomething or (frHistory.Count > 0);
frHistoryIndex := 0;
frHistory.Clear;
frPositionHistory.Clear;
end;
FHistory.Clear;
FTitleHistory.Clear;
FPosition.Clear;
FHistoryIndex := 0;
if DidSomething and Assigned(FOnHistoryChange) then
FOnHistoryChange(Self);
end;
procedure TFrameViewer.SetOnFormSubmit(Handler: TFormSubmitEvent);
var
I: integer;
begin
FOnFormSubmit := Handler;
with CurFrameSet do
for I := 0 to Viewers.Count-1 do
with ThtmlViewer(Viewers[I]) do
OnFormSubmit := Handler;
end;
procedure TFrameViewer.SetOnProgress(Handler: ThtProgressEvent);
var
I: integer;
begin
FOnProgress := Handler;
with CurFrameSet do
for I := 0 to Viewers.Count-1 do
with ThtmlViewer(Viewers[I]) do
OnProgress := Handler;
end;
procedure TFrameViewer.SetDragDrop(const Value: TDragDropEvent);
var
I: integer;
begin
FOnDragDrop := Value;
if Assigned(CurFrameSet) then
if Assigned(Value) then
CurFrameSet.OnDragDrop := fvDragDrop
else CurFrameSet.OnDragDrop := Nil;
for I := 0 to GetCurViewerCount-1 do
if Assigned(Value) then
CurViewer[I].OnDragDrop := fvDragDrop
else CurViewer[I].OnDragDrop := Nil;
end;
procedure TFrameViewer.fvDragDrop(Sender, Source: TObject; X, Y: Integer);
begin
if Assigned(FOnDragDrop) then
FOnDragDrop(Self, Source, X, Y);
end;
procedure TFrameViewer.SetDragOver(const Value: TDragOverEvent);
var
I: integer;
begin
FOnDragOver := Value;
if Assigned(CurFrameSet) then
if Assigned(Value) then
CurFrameSet.OnDragOver := fvDragOver
else CurFrameSet.OnDragOver := Nil;
for I := 0 to GetCurViewerCount-1 do
if Assigned(Value) then
CurViewer[I].OnDragOver := fvDragOver
else CurViewer[I].OnDragOver := Nil;
end;
procedure TFrameViewer.fvDragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
if Assigned(FOnDragOver) then
FOnDragOver(Self, Source, X, Y, State, Accept);
end;
procedure TFrameViewer.SetOnImageRequest(Handler: TGetImageEvent);
var
I: integer;
begin
FOnImageRequest := Handler;
with CurFrameSet do
for I := 0 to Viewers.Count-1 do
with ThtmlViewer(Viewers[I]) do
OnImageRequest := Handler;
end;
function TFrameViewer.ViewerFromTarget(const Target: string): ThtmlViewer;
var
I: integer;
begin
if Assigned(CurFrameSet) and Assigned(CurFrameSet.FrameNames)
and CurFrameSet.FrameNames.Find(Target, I)
and (CurFrameSet.FrameNames.Objects[I] <> Nil)
and Assigned((CurFrameSet.FrameNames.Objects[I] as TfvFrame).Viewer) then
Result := TfvFrame(CurFrameSet.FrameNames.Objects[I]).Viewer as ThtmlViewer
else Result := Nil;
end;
procedure TFrameViewer.RePaint;
begin
if Assigned(CurFrameSet) then
CurFrameSet.RePaint;
end;
procedure TFrameViewer.SetOptions(Value: TFrameViewerOptions);
var
I: integer;
begin
if (fvNoBorder in FOptions) <> (fvNoBorder in Value) then
if fvNoBorder in Value then
begin
CurFrameSet.OuterBorder := 0;
CurFrameSet.BevelOuter := bvNone;
CurFrameSet.BorderSize := 0;
end
else
begin
CurFrameSet.BevelWidth := 2;
CurFrameSet.BevelOuter := bvLowered;
CurFrameSet.BorderSize := 2;
end;
for I := 0 to CurFrameSet.Viewers.Count-1 do
with ThtmlViewer(CurFrameSet.Viewers[I]) do
begin
if (fvOverLinksActive in Value) then
htOptions := htOptions + [htOverLinksActive]
else htOptions := htOptions - [htOverLinksActive];
if (fvNoLinkUnderline in Value) then
htOptions := htOptions + [htNoLinkUnderline]
else htOptions := htOptions - [htNoLinkUnderline];
if (fvPrintTableBackground in Value) then
htOptions := htOptions + [htPrintTableBackground]
else htOptions := htOptions - [htPrintTableBackground];
if (fvPrintBackground in Value) then
htOptions := htOptions + [htPrintBackground]
else htOptions := htOptions - [htPrintBackground];
if (fvPrintMonochromeBlack in Value) then
htOptions := htOptions + [htPrintMonochromeBlack]
else htOptions := htOptions - [htPrintMonochromeBlack];
if (fvShowVScroll in Value) then
htOptions := htOptions + [htShowVScroll]
else htOptions := htOptions - [htShowVScroll];
if (fvNoWheelMouse in Value) then
htOptions := htOptions + [htNoWheelMouse]
else htOptions := htOptions - [htNoWheelMouse];
if (fvShowDummyCaret in Value) then
htOptions := htOptions + [htShowDummyCaret]
else htOptions := htOptions - [htShowDummyCaret];
if (fvNoLinkHilite in Value) then
htOptions := htOptions + [htNoLinkHilite]
else htOptions := htOptions - [htNoLinkHilite];
if (fvNoFocusRect in Value) or (fvNoBorder in Value) then
BorderStyle := htNone
else BorderStyle := htFocused;
end;
FOptions := Value;
end;
procedure TFrameViewer.AddFrame(FrameSet: TObject; Attr: TAttributeList; const FName: string);
begin
(FrameSet as TSubFrameSet).AddFrame(Attr, FName);
end;
function TFrameViewer.CreateSubFrameSet(FrameSet: TObject): TObject;
var
NewFrameSet, FS: TSubFrameSet;
begin
FS := (FrameSet as TSubFrameSet);
NewFrameSet := TSubFrameSet.CreateIt(FS, CurFrameSet);
FS.List.Add(NewFrameSet);
FS.InsertControl(NewFrameSet);
Result := NewFrameSet;
end;
procedure TFrameViewer.DoAttributes(FrameSet: TObject; Attr: TAttributeList);
begin
(FrameSet as TSubFrameSet).DoAttributes(Attr);
end;
procedure TFrameViewer.EndFrameSet(FrameSet: TObject);
begin
(FrameSet as TSubFrameSet).EndFrameSet;
end;
{----------------TFrameViewer.AddVisitedLink}
procedure TFrameViewer.AddVisitedLink(const S: string);
var
I: integer;
begin
if (FVisitedMaxCount = 0) then
Exit;
I := Visited.IndexOf(S);
if I = 0 then
Exit
else if I > 0 then
Visited.Delete(I); {thus moving it to the top}
Visited.Insert(0, S);
for I := Visited.Count-1 downto FVisitedMaxCount do
Visited.Delete(I);
end;
{----------------TFrameViewer.CheckVisitedLinks}
procedure TFrameViewer.CheckVisitedLinks;
var
I, J, K: integer;
S, S1, Src: string;
Viewer: ThtmlViewer;
RequestEvent: boolean;
begin
if FVisitedMaxCount = 0 then
Exit;
RequestEvent := CurFrameSet.RequestEvent;
for K := 0 to CurFrameSet.Viewers.Count-1 do
begin
Viewer := ThtmlViewer(CurFrameSet.Viewers[K]);
if RequestEvent then
Src := TfvFrame(Viewer.FrameOwner).Source;
for I := 0 to Visited.Count-1 do
begin
S := Visited[I];
for J := 0 to Viewer.LinkList.Count-1 do
with TFontObj(Viewer.LinkList[J]) do
begin
if not RequestEvent then
begin
if (Url <> '') and (Url[1] = '#') then
S1 := Viewer.CurrentFile+Url
else
S1 := Viewer.HTMLExpandFilename(Url);
end
else
if (Url <> '') and (Url[1] = '#') then
S1 := Src+Url
else
S1 := URL;
if CompareText(S, S1) = 0 then
Visited := True;
end;
end;
Viewer.Invalidate;
end;
end;
{----------------TFrameViewer.DoURLRequest}
procedure TFrameViewer.DoURLRequest(Sender: TObject; const SRC: string;
var RStream: TMemoryStream);
var
EV: EventRec;
begin
if CurFrameSet.TriggerEvent(Src, @EV) then
with EV do
begin
if not Assigned(UrlRequestStream) then
UrlRequestStream := TMemoryStream.Create;
case LStyle of
lsFile:
UrlRequestStream.LoadFromFile(NewName);
lsString:
begin
UrlRequestStream.SetSize(Length(AString));
System.Move(AString[1], UrlRequestStream.Memory^, Length(AString));
end;
end;
RStream := UrlRequestStream;
end;
end;
{----------------TFrameViewer.GetViewers:}
function TFrameViewer.GetViewers: TStrings;
var
I: integer;
S: string;
AFrame: TfvFrame;
Viewer: ThtmlViewer;
Pt1, Pt2: TPoint;
begin
if not Assigned(FViewerList) then
FViewerList := TStringList.Create
else FViewerList.Clear;
for I := 0 to CurFrameSet.Viewers.Count-1 do
begin
Viewer := CurFrameSet.Viewers[I];
if Viewer.SectionList.Count > 0 then
begin
S := '';
AFrame := TfvFrame(Viewer.FrameOwner);
Pt1 := AFrame.ClientToScreen(Point(0,0));
Pt2 := CurFrameSet.ClientToScreen(Point(0,0));
if Pt1.X <= Pt2.X +2 then
S := S+'l';
if Pt1.Y <= Pt2.Y +2 then
S := S+'t';
Pt1 := AFrame.ClientToScreen(Point(AFrame.ClientWidth, AFrame.ClientHeight));
Pt2 := CurFrameSet.ClientToScreen(Point(CurFrameSet.ClientWidth, CurFrameSet.ClientHeight));
if Pt1.X >= Pt2.X -2 then
S := S+'r';
if Pt1.Y >= Pt2.Y -2 then
S := S+'b';
FViewerList.AddObject(S, Viewer);
end;
end;
Result := FViewerList;
end;
{----------------TFVBase.GetFURL} {base class for TFrameViewer and TFrameBrowser}
function TFVBase.GetFURL: string;
begin
Result := FURL;
end;
function TFVBase.GetTarget: string;
begin
Result := FTarget;
end;
procedure TFVBase.SetViewImages(Value: boolean);
var
I : integer;
begin
if (FViewImages <> Value) and not Processing then
begin
FViewImages := Value;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].ViewImages := Value;
end;
end;
procedure TFVBase.SetImageCacheCount(Value: integer);
var
I : integer;
begin
if (FImageCacheCount <> Value) and not Processing then
begin
FImageCacheCount := Value;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].ImageCacheCount := Value;
end;
end;
function TFVBase.GetProcessing: boolean;
begin
Result := FProcessing or FViewerProcessing;
end;
{----------------TFVBase.SetNoSelect}
procedure TFVBase.SetNoSelect(Value: boolean);
var
I: integer;
begin
if Value <> FNoSelect then
begin
FNoSelect := Value;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].NoSelect := Value;
end;
end;
procedure TFVBase.SetOnBitmapRequest(Handler: TGetBitmapEvent);
var
I: integer;
begin
FOnBitmapRequest := Handler;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].OnBitmapRequest := Handler;
end;
procedure TFVBase.SetOnMeta(Handler: TMetaType);
var
I: integer;
begin
FOnMeta := Handler;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].OnMeta := Handler;
end;
procedure TFVBase.SetOnLink(Handler: TLinkType);
var
I: integer;
begin
FOnLink := Handler;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].OnLink := Handler;
end;
procedure TFVBase.SetOnScript(Handler: TScriptEvent);
var
I: integer;
begin
FOnScript := Handler;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].OnScript := Handler;
end;
procedure TFVBase.SetImageOver(Handler: TImageOverEvent);
var
I: integer;
begin
FOnImageOver := Handler;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].OnImageOver := Handler;
end;
procedure TFVBase.SetImageClick(Handler: TImageClickEvent);
var
I: integer;
begin
FOnImageClick := Handler;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].OnImageClick := Handler;
end;
procedure TFVBase.SetOnRightClick(Handler: TRightClickEvent);
var
I: integer;
begin
FOnRightClick := Handler;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].OnRightClick := Handler;
end;
procedure TFVBase.SetOnObjectFocus(Handler: ThtObjectEvent);
var
I: integer;
begin
FOnObjectFocus := Handler;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].OnObjectFocus := Handler;
end;
procedure TFVBase.SetOnObjectBlur(Handler: ThtObjectEvent);
var
I: integer;
begin
FOnObjectBlur := Handler;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].OnObjectBlur := Handler;
end;
procedure TFVBase.SetOnObjectChange(Handler: ThtObjectEvent);
var
I: integer;
begin
FOnObjectChange := Handler;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].OnObjectChange := Handler;
end;
procedure TFVBase.SetOnFileBrowse(Handler: TFileBrowseEvent);
var
I: integer;
begin
FOnFileBrowse := Handler;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].OnFileBrowse := Handler;
end;
procedure TFVBase.SetOnObjectClick(Handler: TObjectClickEvent);
var
I: integer;
begin
FOnObjectClick := Handler;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].OnObjectClick := Handler;
end;
procedure TFVBase.SetMouseDouble(Handler: TMouseEvent);
var
I: integer;
begin
FOnMouseDouble := Handler;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].OnMouseDouble := Handler;
end;
procedure TFVBase.SetServerRoot(Value: string);
begin
Value := Trim(Value);
if (Length(Value) >= 1) and (Value[Length(Value)] = '\') then
SetLength(Value, Length(Value)-1);
FServerRoot := Value;
end;
procedure TFVBase.SetPrintMarginLeft(Value: Double);
var
I: integer;
begin
if FPrintMarginLeft <> Value then
begin
FPrintMarginLeft := Value;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].PrintMarginLeft := Value;
end;
end;
procedure TFVBase.SetPrintMarginRight(Value: Double);
var
I: integer;
begin
if FPrintMarginRight <> Value then
begin
FPrintMarginRight := Value;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].PrintMarginRight := Value;
end;
end;
procedure TFVBase.SetPrintMarginTop(Value: Double);
var
I: integer;
begin
if FPrintMarginTop <> Value then
begin
FPrintMarginTop := Value;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].PrintMarginTop := Value;
end;
end;
procedure TFVBase.SetPrintMarginBottom(Value: Double);
var
I: integer;
begin
if FPrintMarginBottom <> Value then
begin
FPrintMarginBottom := Value;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].PrintMarginBottom := Value;
end;
end;
procedure TFVBase.SetPrintScale(Value: Double);
var
I: integer;
begin
if FPrintScale <> Value then
begin
FPrintScale := Value;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].PrintScale := Value;
end;
end;
procedure TFVBase.SetMarginWidth(Value: integer);
var
I: integer;
begin
if FMarginWidth <> Value then
begin
FMarginWidth := Value;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].MarginWidth := Value;
end;
end;
procedure TFVBase.SetMarginHeight(Value: integer);
var
I: integer;
begin
if FMarginHeight <> Value then
begin
FMarginHeight := Value;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].MarginHeight := Value;
end;
end;
procedure TFVBase.SetPrintHeader(Handler: TPagePrinted);
var
I: integer;
begin
FOnPrintHeader := Handler;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].OnPrintHeader := Handler;
end;
procedure TFVBase.SetPrintFooter(Handler: TPagePrinted);
var
I: integer;
begin
FOnPrintFooter := Handler;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].OnPrintFooter := Handler;
end;
procedure TFVBase.SetPrintHtmlHeader(Handler: THtmlPagePrinted);
var
I: integer;
begin
FOnPrintHtmlHeader := Handler;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].OnPrintHtmlHeader := Handler;
end;
procedure TFVBase.SetPrintHtmlFooter(Handler: THtmlPagePrinted);
var
I: integer;
begin
FOnPrintHtmlFooter := Handler;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].OnPrintHtmlFooter := Handler;
end;
procedure TFVBase.SetVisitedMaxCount(Value: integer);
var
I, J: integer;
begin
Value := IntMax(Value, 0);
if Value <> FVisitedMaxCount then
begin
FVisitedMaxCount := Value;
if FVisitedMaxCount = 0 then
begin
Visited.Clear;
for I := 0 to GetCurViewerCount-1 do
with CurViewer[I] do
for J := 0 to SectionList.LinkList.Count-1 do
TFontObj(LinkList[J]).Visited := False;
RePaint;
end
else
begin
FVisitedMaxCount := Value;
for I := Visited.Count-1 downto FVisitedMaxCount do
Visited.Delete(I);
end;
end;
end;
{----------------TFVBase.SetColor}
procedure TFVBase.SetColor(Value: TColor);
var
I: integer;
begin
if (FBackground <> Value) then
begin
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].DefBackground := Value;
FBackground := Value;
Color := Value;
end;
end;
function TFVBase.GetFontName: TFontName;
begin
Result := FFontName;
end;
procedure TFVBase.SetFontName(Value: TFontName);
var
I: integer;
begin
if CompareText(Value, FFontName) <> 0 then
begin
FFontName := Value;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].DefFontName := Value;
end;
end;
function TFVBase.GetPreFontName: TFontName;
begin
Result := FPreFontName;
end;
procedure TFVBase.SetPreFontName(Value: TFontName);
var
I: integer;
begin
if CompareText(Value, FPreFontName) <> 0 then
begin
FPreFontName := Value;
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].DefPreFontName := Value;
end;
end;
procedure TFVBase.SetFontSize(Value: integer);
var
I: integer;
begin
if (FFontSize <> Value) then
begin
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].DefFontSize := Value;
FFontSize := Value;
end;
end;
procedure TFVBase.SetFontColor(Value: TColor);
var
I: integer;
begin
if (FFontColor <> Value) then
begin
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].DefFontColor := Value;
FFontColor := Value;
end;
end;
procedure TFVBase.SetHotSpotColor(Value: TColor);
var
I: integer;
begin
if (FHotSpotColor <> Value) then
begin
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].DefHotSpotColor := Value;
FHotSpotColor := Value;
end;
end;
procedure TFVBase.SetActiveColor(Value: TColor);
var
I: integer;
begin
if (FOverColor <> Value) then
begin
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].DefOverLinkColor := Value;
FOverColor := Value;
end;
end;
procedure TFVBase.SetVisitedColor(Value: TColor);
var
I: integer;
begin
if (FVisitedColor <> Value) then
begin
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].DefVisitedLinkColor := Value;
FVisitedColor := Value;
end;
end;
{----------------TFVBase.SetHistoryMaxCount}
procedure TFVBase.SetHistoryMaxCount(Value: integer);
var
I: integer;
begin
if (Value = FHistoryMaxCount) or (Value < 0) then Exit;
ClearHistory;
for I := 0 to GetCurViewerCount-1 do
with CurViewer[I] do
begin
ClearHistory;
HistoryMaxCount := Value;
end;
FHistoryMaxCount := Value;
end;
procedure TFVBase.SetCursor(Value: TCursor);
var
I: integer;
begin
if Value = OldThickIBeamCursor then
Value := crIBeam;
if (FCursor <> Value) then
begin
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].Cursor := Value;
FCursor := Value;
end;
end;
procedure TFVBase.SetOnPanelCreate(Handler: TPanelCreateEvent);
var
I: integer;
begin
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].OnPanelCreate := Handler;
FOnPanelCreate := Handler;
end;
procedure TFVBase.SetOnPanelDestroy(Handler: TPanelDestroyEvent);
var
I: integer;
begin
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].OnPanelDestroy := Handler;
FOnPanelDestroy := Handler;
end;
procedure TFVBase.SetOnPanelPrint(Handler: TPanelPrintEvent);
var
I: integer;
begin
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].OnPanelPrint := Handler;
FOnPanelPrint := Handler;
end;
procedure TFVBase.SetOnParseBegin(Handler: TParseEvent);
var
I: integer;
begin
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].OnParseBegin:= Handler;
FOnParseBegin := Handler;
end;
procedure TFVBase.SetOnParseEnd(Handler: TNotifyEvent);
var
I: integer;
begin
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].OnParseEnd:= Handler;
FOnParseEnd := Handler;
end;
Function TFVBase.GetSelLength: integer;
var
AViewer: ThtmlViewer;
begin
AViewer := GetActiveViewer;
if Assigned(AViewer) then
Result := AViewer.SelLength
else Result := 0;
end;
procedure TFVBase.SetSelLength(Value: integer);
var
AViewer: ThtmlViewer;
begin
AViewer := GetActiveViewer;
if Assigned(AViewer) then
AViewer.SelLength := Value;
end;
Function TFVBase.GetSelStart: integer;
var
AViewer: ThtmlViewer;
begin
AViewer := GetActiveViewer;
if Assigned(AViewer) then
Result := AViewer.SelStart
else Result := 0;
end;
procedure TFVBase.SetSelStart(Value: integer);
var
AViewer: ThtmlViewer;
begin
AViewer := GetActiveViewer;
if Assigned(AViewer) then
AViewer.SelStart := Value;
end;
{$ifdef ver100_plus} {Delphi 3,4,5, C++Builder 3, 4}
procedure TFVBase.SetCharset(Value: TFontCharset);
var
I: integer;
begin
if (FCharset <> Value) then
begin
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].Charset := Value;
FCharset := Value;
end;
end;
{$endif}
procedure TFVBase.SetOnObjectTag(Handler: TObjectTagEvent);
var
I: integer;
begin
for I := 0 to GetCurViewerCount-1 do
CurViewer[I].OnObjectTag := Handler;
FOnObjectTag := Handler;
end;
{----------------TFVBase.GetOurPalette:}
function TFVBase.GetOurPalette: HPalette;
begin
if ColorBits = 8 then
Result := CopyPalette(ThePalette)
else Result := 0;
end;
{----------------TFVBase.SetOurPalette}
procedure TFVBase.SetOurPalette(Value: HPalette);
var
NewPalette: HPalette;
begin
if (Value <> 0) and (ColorBits = 8) then
begin
NewPalette := CopyPalette(Value);
if NewPalette <> 0 then
begin
if ThePalette <> 0 then
DeleteObject(ThePalette);
ThePalette := NewPalette;
if FDither then SetGlobalPalette(ThePalette);
end;
end;
end;
{----------------TFVBase.SetDither}
procedure TFVBase.SetDither(Value: boolean);
begin
if (Value <> FDither) and (ColorBits = 8) then
begin
FDither := Value;
if Value then SetGlobalPalette(ThePalette)
else SetGLobalPalette(0);
end;
end;
function TFVBase.GetCaretPos: integer;
var
Vw: ThtmlViewer;
begin
Vw := GetActiveViewer;
if Assigned(Vw) then
Result := Vw.CaretPos
else Result := 0;
end;
procedure TFVBase.SetCaretPos(Value: integer);
var
Vw: ThtmlViewer;
begin
Vw := GetActiveViewer;
if Assigned(Vw) then
Vw.CaretPos := Value;
end;
function TFVBase.GetSelText: WideString;
var
AViewer: ThtmlViewer;
begin
AViewer := GetActiveViewer;
if Assigned(AViewer) then
Result := AViewer.SelText
else Result := '';
end;
function TFVBase.GetSelTextBuf(Buffer: PWideChar; BufSize: integer): integer;
var
AViewer: ThtmlViewer;
begin
if BufSize <= 0 then
Result := 0
else
begin
AViewer := GetActiveViewer;
if Assigned(AViewer) then
Result := AViewer.GetSelTextBuf(Buffer, BufSize)
else
begin
Buffer[0] := #0;
Result := 1;
end;
end;
end;
{----------------TFVBase.InsertImage}
function TFVBase.InsertImage(Viewer: ThtmlViewer; const Src: string;
Stream: TMemoryStream): boolean;
begin
try
Result := (Viewer as ThtmlViewer).InsertImage(Src, Stream);
except
Result := True; {consider exceptions done}
end;
end;
procedure TFVBase.SetFocus;
var
AViewer: ThtmlViewer;
begin
AViewer := GetActiveViewer;
if Assigned(AViewer) and AViewer.CanFocus then
try
AViewer.SetFocus;
except {just in case}
inherited SetFocus;
end
else inherited SetFocus;
end;
{----------------TFVBase.SetProcessing}
procedure TFVBase.SetProcessing(Local, Viewer: boolean);
var
Change: boolean;
begin
Change := (Local or Viewer <> FProcessing or FViewerProcessing);
FProcessing := Local;
FViewerProcessing := Viewer;
if Change and Assigned(FOnProcessing) then
FOnProcessing(Self, Local or Viewer);
end;
procedure TFVBase.CheckProcessing(Sender: TObject; ProcessingOn: boolean);
begin
with ProcessList do
begin
if ProcessingOn then
begin
if IndexOf(Sender) = -1 then
Add(Sender);
end
else Remove(Sender);
SetProcessing(FProcessing, Count > 0);
end;
end;
{----------------TFVBase.Print}
procedure TFVBase.Print(FromPage, ToPage: integer);
var
AViewer: ThtmlViewer;
begin
AViewer := GetActiveViewer;
if Assigned(AViewer) then
AViewer.Print(FromPage, ToPage);
end;
{----------------TFVBase.NumPrinterPages}
function TFVBase.NumPrinterPages(var WidthRatio: double): integer;
var
AViewer: ThtmlViewer;
begin
AViewer := GetActiveViewer;
if Assigned(AViewer) then
Result := AViewer.NumPrinterPages(WidthRatio)
else Result := 0;
end;
function TFVBase.NumPrinterPages: integer;
var
Dummy: double;
begin
Result := NumPrinterPages(Dummy);
end;
{----------------TFVBase.CopyToClipboard}
procedure TFVBase.CopyToClipboard;
var
AViewer: ThtmlViewer;
begin
AViewer := GetActiveViewer;
if Assigned(AViewer) and (AViewer.SelLength <> 0) then
AViewer.CopyToClipboard;
end;
procedure TFVBase.SelectAll;
var
AViewer: ThtmlViewer;
begin
AViewer := GetActiveViewer;
if Assigned(AViewer) then
AViewer.SelectAll;
end;
{----------------TFVBase.Find}
function TFVBase.Find(const S: WideString; MatchCase: boolean): boolean;
begin
Result := FindEx(S, MatchCase, False);
end;
{----------------TFVBase.FindEx}
function TFVBase.FindEx(const S: WideString; MatchCase, Reverse: boolean): boolean;
var
AViewer: ThtmlViewer;
begin
AViewer := GetActiveViewer;
if Assigned(AViewer) then
Result := AViewer.FindEx(S, MatchCase, Reverse)
else Result := False;
end;
{----------------PositionObj}
destructor PositionObj.Destroy;
begin
FormData.Free;
inherited;
end;
end.