mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 14:27:59 +02:00
1442 lines
39 KiB
ObjectPascal
1442 lines
39 KiB
ObjectPascal
{
|
|
This file is part of the Free Pascal Integrated Development Environment
|
|
Copyright (c) 1998 by Berczi Gabor
|
|
|
|
Help display objects
|
|
|
|
See the file COPYING.FPC, included in this distribution,
|
|
for details about the copyright.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
**********************************************************************}
|
|
unit WHlpView;
|
|
{$H-}
|
|
|
|
interface
|
|
|
|
uses
|
|
Objects,Drivers,Views,
|
|
FVConsts,
|
|
WEditor,WCEdit,
|
|
WUtils,WHelp;
|
|
|
|
type
|
|
TEditor = TCodeEditor;
|
|
PEditor = PCodeEditor;
|
|
|
|
const
|
|
cmPrevTopic = 90;
|
|
HistorySize = 30;
|
|
|
|
CHelpViewer = #33#34#35#36;
|
|
CHelpFrame = #37#37#38#38#39;
|
|
|
|
cmHelpFilesChanged = 57340;
|
|
|
|
type
|
|
PHelpLink = ^THelpLink;
|
|
THelpLink = record
|
|
Bounds : TRect;
|
|
FileID : longint;
|
|
Context : THelpCtx;
|
|
end;
|
|
|
|
PHelpColorArea = ^THelpColorArea;
|
|
THelpColorArea = record
|
|
Color : byte;
|
|
Bounds : TRect;
|
|
AttrMask : byte;
|
|
end;
|
|
|
|
PHelpKeyword = ^THelpKeyword;
|
|
THelpKeyword = record
|
|
KWord : PString;
|
|
Index : sw_integer;
|
|
end;
|
|
|
|
PLinkCollection = ^TLinkCollection;
|
|
TLinkCollection = object(TCollection)
|
|
procedure FreeItem(Item: Pointer); virtual;
|
|
end;
|
|
|
|
PColorAreaCollection = ^TColorAreaCollection;
|
|
TColorAreaCollection = object(TCollection)
|
|
procedure FreeItem(Item: Pointer); virtual;
|
|
end;
|
|
|
|
PKeywordCollection = ^TKeywordCollection;
|
|
TKeywordCollection = object({TSorted}TCollection)
|
|
function At(Index: sw_Integer): PHelpKeyword;
|
|
procedure FreeItem(Item: Pointer); virtual;
|
|
function Compare(Key1, Key2: Pointer): sw_Integer; virtual;
|
|
end;
|
|
|
|
{ TSearchRelation = (srEqual,srGreater,srLess,srGreatEqu,srLessEqu);
|
|
|
|
PAdvancedStringCollection = ^TAdvancedStringCollection;
|
|
TAdvancedStringCollection = object(TStringCollection)
|
|
function SearchItem(Key: pointer; Rel: TSearchRelation; var Index: integer): boolean; virtual;
|
|
end;}
|
|
|
|
PNamedMark = ^TNamedMark;
|
|
TNamedMark = object(TObject)
|
|
constructor Init(const AName: string; AX, AY: integer);
|
|
function GetName: string;
|
|
destructor Done; virtual;
|
|
private
|
|
Name: PString;
|
|
Pos: TPoint;
|
|
end;
|
|
|
|
PNamedMarkCollection = ^TNamedMarkCollection;
|
|
TNamedMarkCollection = object(TSortedCollection)
|
|
function At(Index: sw_Integer): PNamedMark;
|
|
function Compare(Key1, Key2: Pointer): sw_Integer; virtual;
|
|
function SearchMark(const Name: string): PNamedMark;
|
|
function GetMarkPos(const Name: string; var P: TPoint): boolean;
|
|
procedure Add(const Name: string; P: TPoint);
|
|
end;
|
|
|
|
PLinePosCollection = ^TLinePosCollection;
|
|
TLinePosCollection = object(TNoDisposeCollection)
|
|
function At(Index: sw_Integer): sw_integer;
|
|
procedure Insert (Item: pointer);virtual;
|
|
end;
|
|
|
|
PHelpTopic = ^THelpTopic;
|
|
THelpTopic = object(TObject)
|
|
Topic: PTopic;
|
|
Lines: PUnsortedStringCollection;
|
|
LinesPos: PLinePosCollection;
|
|
Links: PLinkCollection;
|
|
NamedMarks: PNamedMarkCollection;
|
|
ColorAreas: PColorAreaCollection;
|
|
public
|
|
constructor Init(ATopic: PTopic);
|
|
procedure SetParams(AMargin, AWidth: sw_integer); virtual;
|
|
function GetLineCount: sw_integer; virtual;
|
|
function GetLineText(Line: sw_integer): string; virtual;
|
|
function GetLinkCount: sw_integer; virtual;
|
|
procedure GetLinkBounds(Index: sw_integer; var R: TRect); virtual;
|
|
function GetLinkFileID(Index: sw_integer): word; virtual;
|
|
function GetLinkContext(Index: sw_integer): THelpCtx; virtual;
|
|
function GetColorAreaCount: sw_integer; virtual;
|
|
procedure GetColorAreaBounds(Index: sw_integer; var R: TRect); virtual;
|
|
function GetColorAreaColor(Index: sw_integer): word; virtual;
|
|
function GetColorAreaMask(Index: sw_integer): word; virtual;
|
|
destructor Done; virtual;
|
|
private
|
|
Width,Margin: sw_integer;
|
|
{ StockItem: boolean;}
|
|
procedure ReBuild;
|
|
end;
|
|
|
|
THelpHistoryEntry = record
|
|
Context_ : THelpCtx;
|
|
Delta_ : TPoint;
|
|
CurPos_ : TPoint;
|
|
CurLink_ : sw_integer;
|
|
FileID_ : word;
|
|
end;
|
|
|
|
PHelpViewer = ^THelpViewer;
|
|
THelpViewer = object(TEditor)
|
|
Margin: sw_integer;
|
|
HelpTopic: PHelpTopic;
|
|
CurLink: sw_integer;
|
|
constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
|
|
procedure ChangeBounds(var Bounds: TRect); virtual;
|
|
procedure Draw; virtual;
|
|
procedure HandleEvent(var Event: TEvent); virtual;
|
|
procedure SetCurPtr(X,Y: sw_integer); virtual;
|
|
function GetLineCount: sw_integer; virtual;
|
|
function GetLine(LineNo: sw_integer): PCustomLine; virtual;
|
|
function GetLineText(Line: sw_integer): sw_astring; virtual;
|
|
function GetDisplayText(I: sw_integer): sw_astring; virtual;
|
|
function GetLinkCount: sw_integer; virtual;
|
|
procedure GetLinkBounds(Index: sw_integer; var R: TRect); virtual;
|
|
function GetLinkFileID(Index: sw_integer): word; virtual;
|
|
function GetLinkContext(Index: sw_integer): THelpCtx; virtual;
|
|
function GetLinkTarget(Index: sw_integer): string; virtual;
|
|
function GetLinkText(Index: sw_integer): string; virtual;
|
|
function GetColorAreaCount: sw_integer; virtual;
|
|
procedure GetColorAreaBounds(Index: sw_integer; var R: TRect); virtual;
|
|
function GetColorAreaColor(Index: sw_integer): word; virtual;
|
|
function GetColorAreaMask(Index: sw_integer): word; virtual;
|
|
procedure SelectNextLink(ANext: boolean); virtual;
|
|
procedure SwitchToIndex; virtual;
|
|
procedure SwitchToTopic(SourceFileID: word; Context: THelpCtx); virtual;
|
|
procedure SetTopic(Topic: PTopic); virtual;
|
|
procedure SetCurLink(Link: sw_integer); virtual;
|
|
procedure SelectLink(Index: sw_integer); virtual;
|
|
procedure PrevTopic; virtual;
|
|
procedure RenderTopic; virtual;
|
|
procedure Lookup(S: string); virtual;
|
|
function GetPalette: PPalette; virtual;
|
|
constructor Load(var S: TStream);
|
|
procedure Store(var S: TStream);
|
|
destructor Done; virtual;
|
|
private
|
|
History : array[0..HistorySize] of THelpHistoryEntry;
|
|
HistoryPtr : integer;
|
|
WordList : PKeywordCollection;
|
|
Lookupword : string;
|
|
InLookUp : boolean;
|
|
IndexTopic : PTopic;
|
|
IndexHelpTopic: PHelpTopic;
|
|
function LinkContainsPoint(var R: TRect; var P: TPoint): boolean;
|
|
procedure ISwitchToTopic(SourceFileID: word; Context: THelpCtx; RecordInHistory: boolean);
|
|
procedure ISwitchToTopicPtr(P: PTopic; RecordInHistory: boolean);
|
|
procedure BuildTopicWordList;
|
|
end;
|
|
|
|
PHelpFrame = ^THelpFrame;
|
|
THelpFrame = object(TFrame)
|
|
function GetPalette: PPalette; virtual;
|
|
end;
|
|
|
|
PHelpWindow = ^THelpWindow;
|
|
THelpWindow = object(TWindow)
|
|
HSB,VSB : PScrollBar;
|
|
HelpView: PHelpViewer;
|
|
HideOnClose: boolean;
|
|
constructor Init(var Bounds: TRect; ATitle: TTitleStr; ASourceFileID: word; AContext: THelpCtx; ANumber: Integer);
|
|
procedure InitFrame; virtual;
|
|
procedure InitScrollBars; virtual;
|
|
procedure InitHelpView; virtual;
|
|
procedure ShowIndex; virtual;
|
|
procedure ShowDebugInfos; virtual;
|
|
procedure ShowTopic(SourceFileID: word; Context: THelpCtx); virtual;
|
|
procedure HandleEvent(var Event: TEvent); virtual;
|
|
procedure Close; virtual;
|
|
function GetPalette: PPalette; virtual; { needs to be overridden }
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
Video,
|
|
WConsts;
|
|
|
|
const CommentColor = Blue;
|
|
|
|
function NewLink(FileID: longint; Topic: THelpCtx; StartP, EndP: TPoint): PHelpLink;
|
|
var P: PHelpLink;
|
|
begin
|
|
New(P); FillChar(P^, SizeOf(P^), 0);
|
|
P^.FileID:=FileID;
|
|
P^.Context:=Topic; P^.Bounds.A:=StartP; P^.Bounds.B:=EndP;
|
|
NewLink:=P;
|
|
end;
|
|
|
|
procedure DisposeLink(P: PHelpLink);
|
|
begin
|
|
if P<>nil then Dispose(P);
|
|
end;
|
|
|
|
function NewColorArea(Color, AttrMask: byte; StartP, EndP: TPoint): PHelpColorArea;
|
|
var P: PHelpColorArea;
|
|
begin
|
|
New(P); FillChar(P^, SizeOf(P^), 0);
|
|
P^.Color:=Color; P^.AttrMask:=AttrMask;
|
|
P^.Bounds.A:=StartP; P^.Bounds.B:=EndP;
|
|
NewColorArea:=P;
|
|
end;
|
|
|
|
procedure DisposeColorArea(P: PHelpColorArea);
|
|
begin
|
|
if P<>nil then Dispose(P);
|
|
end;
|
|
|
|
function NewKeyword(Index: sw_integer; KWord: string): PHelpKeyword;
|
|
var P: PHelpKeyword;
|
|
begin
|
|
New(P); FillChar(P^, SizeOf(P^), 0);
|
|
P^.Index:=Index; P^.KWord:=NewStr(KWord);
|
|
NewKeyword:=P;
|
|
end;
|
|
|
|
procedure DisposeKeyword(P: PHelpKeyword);
|
|
begin
|
|
if P<>nil then
|
|
begin
|
|
if P^.KWord<>nil then DisposeStr(P^.KWord);
|
|
Dispose(P);
|
|
end;
|
|
end;
|
|
|
|
procedure TLinkCollection.FreeItem(Item: Pointer);
|
|
begin
|
|
if Item<>nil then DisposeLink(Item);
|
|
end;
|
|
|
|
procedure TColorAreaCollection.FreeItem(Item: Pointer);
|
|
begin
|
|
if Item<>nil then DisposeColorArea(Item);
|
|
end;
|
|
|
|
function TKeywordCollection.At(Index: sw_Integer): PHelpKeyword;
|
|
begin
|
|
At:=inherited At(Index);
|
|
end;
|
|
|
|
procedure TKeywordCollection.FreeItem(Item: Pointer);
|
|
begin
|
|
if Item<>nil then DisposeKeyword(Item);
|
|
end;
|
|
|
|
function TKeywordCollection.Compare(Key1, Key2: Pointer): sw_Integer;
|
|
var R: sw_integer;
|
|
K1: PHelpKeyword absolute Key1;
|
|
K2: PHelpKeyword absolute Key2;
|
|
S1,S2: string;
|
|
begin
|
|
S1:=UpcaseStr(K1^.KWord^); S2:=UpcaseStr(K2^.KWord^);
|
|
if S1<S2 then R:=-1 else
|
|
if S1>S2 then R:=1 else
|
|
R:=0;
|
|
Compare:=R;
|
|
end;
|
|
|
|
{function TAdvancedStringCollection.SearchItem(Key: pointer; Rel: TSearchRelation; var Index: sw_integer): boolean;
|
|
var
|
|
L, H, I, C: sw_Integer;
|
|
const resSmaller = -1; resEqual = 0; resGreater = 1;
|
|
begin
|
|
Index:=-1;
|
|
case Rel of
|
|
srEqual :
|
|
while (L <= H) and (Index=-1) do
|
|
begin
|
|
I := (L + H) shr 1;
|
|
C := Compare(KeyOf(Items^[I]), Key);
|
|
if C = resSmaller then L := I + 1 else
|
|
begin
|
|
H := I - 1;
|
|
if C = resEqual then
|
|
begin
|
|
if not Duplicates then L := I;
|
|
Index := L;
|
|
end;
|
|
end;
|
|
end;
|
|
srGreater :
|
|
begin
|
|
end;
|
|
srLess :
|
|
;
|
|
srGreatEqu :
|
|
;
|
|
srLessEqu :
|
|
;
|
|
else Exit;
|
|
end;
|
|
Search:=Index<>-1;
|
|
end;}
|
|
|
|
constructor TNamedMark.Init(const AName: string; AX, AY: integer);
|
|
begin
|
|
inherited Init;
|
|
Name:=NewStr(AName);
|
|
Pos.X:=AX; Pos.Y:=AY;
|
|
end;
|
|
|
|
function TNamedMark.GetName: string;
|
|
begin
|
|
GetName:=GetStr(Name);
|
|
end;
|
|
|
|
destructor TNamedMark.Done;
|
|
begin
|
|
if Assigned(Name) then DisposeStr(Name); Name:=nil;
|
|
inherited Done;
|
|
end;
|
|
|
|
function TNamedMarkCollection.At(Index: sw_Integer): PNamedMark;
|
|
begin
|
|
At:=inherited At(Index);
|
|
end;
|
|
|
|
function TNamedMarkCollection.Compare(Key1, Key2: Pointer): sw_Integer;
|
|
var K1: PNamedMark absolute Key1;
|
|
K2: PNamedMark absolute Key2;
|
|
R: integer;
|
|
N1,N2: string;
|
|
begin
|
|
N1:=UpcaseStr(K1^.GetName); N2:=UpcaseStr(K2^.GetName);
|
|
if N1<N2 then R:=-1 else
|
|
if N1>N2 then R:= 1 else
|
|
R:=0;
|
|
Compare:=R;
|
|
end;
|
|
|
|
function TNamedMarkCollection.SearchMark(const Name: string): PNamedMark;
|
|
var M,P: PNamedMark;
|
|
I: sw_integer;
|
|
begin
|
|
New(M, Init(Name,0,0));
|
|
if Search(M,I)=false then P:=nil else
|
|
P:=At(I);
|
|
Dispose(M, Done);
|
|
SearchMark:=P;
|
|
end;
|
|
|
|
function TNamedMarkCollection.GetMarkPos(const Name: string; var P: TPoint): boolean;
|
|
var M: PNamedMark;
|
|
begin
|
|
M:=SearchMark(Name);
|
|
if Assigned(M) then
|
|
P:=M^.Pos;
|
|
GetMarkPos:=Assigned(M);
|
|
end;
|
|
|
|
procedure TNamedMarkCollection.Add(const Name: string; P: TPoint);
|
|
begin
|
|
Insert(New(PNamedMark, Init(Name, P.X, P.Y)));
|
|
end;
|
|
|
|
function TLinePosCollection.At(Index: sw_Integer): sw_integer;
|
|
begin
|
|
at := longint (inherited at(Index));
|
|
end;
|
|
|
|
procedure TLinePosCollection.Insert (Item: pointer);
|
|
begin
|
|
Inherited Insert(Item);
|
|
end;
|
|
|
|
constructor THelpTopic.Init(ATopic: PTopic);
|
|
begin
|
|
inherited Init;
|
|
Topic:=ATopic;
|
|
New(Lines, Init(100,100));
|
|
New(LinesPos, Init(100,100));
|
|
New(Links, Init(50,50));
|
|
New(ColorAreas, Init(50,50));
|
|
New(NamedMarks, Init(10,10));
|
|
end;
|
|
|
|
procedure THelpTopic.SetParams(AMargin, AWidth: sw_integer);
|
|
begin
|
|
if Width<>AWidth then
|
|
begin
|
|
Width:=AWidth; Margin:=AMargin;
|
|
ReBuild;
|
|
end;
|
|
end;
|
|
|
|
procedure THelpTopic.ReBuild;
|
|
var TextPos,LinePos,LinkNo,NamedMarkNo: sw_word;
|
|
Line,CurWord: string;
|
|
C: AnsiChar;
|
|
InLink,InCodeArea,InColorArea,InImage: boolean;
|
|
LinkStart,LinkEnd,CodeAreaStart,CodeAreaEnd: TPoint;
|
|
ColorAreaStart,ColorAreaEnd: TPoint;
|
|
ColorAreaType: (atText,atFull);
|
|
CurPos: TPoint;
|
|
ZeroLevel: sw_integer;
|
|
LineStart,NextLineStart: sw_integer;
|
|
LineAlign : (laLeft,laCenter,laRight);
|
|
FirstLink,LastLink: sw_integer;
|
|
AreaColor: word;
|
|
NextByte: (nbNormal,nbAreaColor,nbDirect);
|
|
procedure ClearLine;
|
|
begin
|
|
Line:='';
|
|
end;
|
|
procedure AddWord(TheWord: string); forward;
|
|
procedure NextLine;
|
|
var P: sw_integer;
|
|
I,Delta: sw_integer;
|
|
begin
|
|
Line:=CharStr(' ',Margin)+Line;
|
|
if not InImage then
|
|
repeat
|
|
P:=Pos(#255,Line);
|
|
if P>0 then
|
|
Line[P]:=#32;
|
|
until P=0;
|
|
if Not InImage then
|
|
while copy(Line,length(Line),1)=' ' do
|
|
Delete(Line,length(Line),1);
|
|
Delta:=0;
|
|
if Line<>'' then
|
|
case LineAlign of
|
|
laLeft : ;
|
|
laCenter : if Margin+length(Line)+Margin<Width then
|
|
begin
|
|
Delta:=(Width-(Margin+length(Line)+Margin)) div 2;
|
|
Line:=CharStr(' ',Delta)+Line;
|
|
end;
|
|
laRight : if Margin+length(Line)+Margin<Width then
|
|
begin
|
|
Delta:=Width-(Margin+length(Line)+Margin);
|
|
Line:=CharStr(' ',Delta)+Line;
|
|
end;
|
|
end;
|
|
if (Delta>0) and (FirstLink<>LastLink) then
|
|
for I:=FirstLink to LastLink-1 do
|
|
with PHelpLink(Links^.At(I))^ do
|
|
Bounds.Move(Delta,0);
|
|
if Line='' then Line:=' ';
|
|
Lines^.Insert(NewStr(Line));
|
|
LinesPos^.Insert(pointer(LinePos));
|
|
ClearLine;
|
|
LineStart:=NextLineStart;
|
|
CurPos.X:=Margin+LineStart; Line:=CharStr(#255,LineStart); Inc(CurPos.Y);
|
|
if InLink then LinkStart:=CurPos;
|
|
FirstLink:=LastLink;
|
|
LinePos:=TextPos;
|
|
end;
|
|
procedure FlushLine;
|
|
var W: string;
|
|
begin
|
|
if CurWord<>'' then begin W:=CurWord; CurWord:=''; AddWord(W); end;
|
|
NextLine;
|
|
end;
|
|
procedure AddWord(TheWord: string);
|
|
var W: string;
|
|
begin
|
|
W:=TheWord;
|
|
while (length(W)>0) and (W[length(W)] in [' ',#255]) do
|
|
Delete(W,length(W),1);
|
|
if (copy(Line+TheWord,1,1)<>' ') then
|
|
if (Line<>'') and (Margin+length(Line)+length(W)+Margin>Width) and
|
|
not InImage then
|
|
NextLine;
|
|
Line:=Line+TheWord;
|
|
CurPos.X:=Margin+length(Line);
|
|
end;
|
|
procedure CheckZeroLevel;
|
|
begin
|
|
if ZeroLevel<>0 then
|
|
begin
|
|
if CurWord<>'' then AddWord(CurWord+' ');
|
|
CurWord:='';
|
|
ZeroLevel:=0;
|
|
end;
|
|
end;
|
|
procedure EndColorArea;
|
|
var Mask: word;
|
|
begin
|
|
if ColorAreaType=atText then Mask:=$f0 else Mask:=$00;
|
|
if CurWord<>'' then AddWord(CurWord); CurWord:='';
|
|
ColorAreaEnd:=CurPos; Dec(ColorAreaEnd.X);
|
|
ColorAreas^.Insert(NewColorArea(AreaColor,Mask,ColorAreaStart,ColorAreaEnd));
|
|
InColorArea:=false; AreaColor:=0;
|
|
end;
|
|
begin
|
|
Lines^.FreeAll; LinesPos^.FreeAll;
|
|
Links^.FreeAll; NamedMarks^.FreeAll; ColorAreas^.FreeAll;
|
|
if Topic=nil then Lines^.Insert(NewStr(msg_nohelpavailabelforthistopic)) else
|
|
begin
|
|
LineStart:=0; NextLineStart:=0;
|
|
TextPos:=0; ClearLine; CurWord:=''; Line:='';
|
|
CurPos.X:=Margin+LineStart; CurPos.Y:=0; LinkNo:=0;
|
|
NamedMarkNo:=0; LinePos:=0;
|
|
InLink:=false; InCodeArea:=false; InColorArea:=false;
|
|
InImage:=false;
|
|
ZeroLevel:=0;
|
|
LineAlign:=laLeft;
|
|
FirstLink:=0; LastLink:=0; NextByte:=nbNormal;
|
|
while (TextPos<Topic^.TextSize) or InImage do
|
|
begin
|
|
C:=chr(PByteArray(Topic^.Text)^[TextPos]);
|
|
case NextByte of
|
|
nbAreaColor :
|
|
begin
|
|
AreaColor:=ord(C);
|
|
NextByte:=nbNormal;
|
|
end;
|
|
nbDirect :
|
|
begin
|
|
NextByte:=nbNormal;
|
|
CurWord:=CurWord+C;
|
|
end;
|
|
nbNormal :
|
|
begin
|
|
case C of
|
|
hscLineBreak :
|
|
{if ZeroLevel=0 then ZeroLevel:=1 else
|
|
begin FlushLine; FlushLine; ZeroLevel:=0; end;}
|
|
if InLink then CurWord:=CurWord+' ' else
|
|
begin
|
|
NextLineStart:=0;
|
|
FlushLine;
|
|
LineStart:=0;
|
|
LineAlign:=laLeft;
|
|
end;
|
|
#1 : {Break};
|
|
hscLink :
|
|
begin
|
|
CheckZeroLevel;
|
|
if InLink=false then
|
|
begin LinkStart:=CurPos; InLink:=true; end else
|
|
begin
|
|
if CurWord<>'' then AddWord(CurWord); CurWord:='';
|
|
LinkEnd:=CurPos; Dec(LinkEnd.X);
|
|
if Topic^.Links<>nil then
|
|
begin
|
|
if LinkNo<Topic^.LinkCount then
|
|
begin
|
|
Inc(LastLink);
|
|
Links^.Insert(NewLink(Topic^.Links^[LinkNo].FileID,
|
|
Topic^.Links^[LinkNo].Context,LinkStart,LinkEnd));
|
|
end;
|
|
Inc(LinkNo);
|
|
end;
|
|
InLink:=false;
|
|
end;
|
|
end;
|
|
hscLineStart :
|
|
begin
|
|
NextLineStart:=length(Line)+length(CurWord);
|
|
{ LineStart:=LineStart+(NextLineStart-LineStart);}
|
|
end;
|
|
hscCode :
|
|
begin
|
|
if InCodeArea=false then
|
|
CodeAreaStart:=CurPos else
|
|
begin
|
|
if CurWord<>'' then AddWord(CurWord); CurWord:='';
|
|
CodeAreaEnd:=CurPos; Dec(CodeAreaEnd.X);
|
|
ColorAreas^.Insert(NewColorArea(CommentColor,$f0,CodeAreaStart,CodeAreaEnd));
|
|
end;
|
|
InCodeArea:=not InCodeArea;
|
|
end;
|
|
hscCenter :
|
|
LineAlign:=laCenter;
|
|
hscRight :
|
|
LineAlign:=laRight{was laCenter, typo error ? PM };
|
|
hscNamedMark :
|
|
begin
|
|
if NamedMarkNo<Topic^.NamedMarks^.Count then
|
|
NamedMarks^.Add(GetStr(Topic^.NamedMarks^.At(NamedMarkNo)),CurPos);
|
|
Inc(NamedMarkNo);
|
|
end;
|
|
hscTextAttr,hscTextColor :
|
|
begin
|
|
if InColorArea then
|
|
EndColorArea;
|
|
if C=hscTextAttr then
|
|
ColorAreaType:=atFull
|
|
else
|
|
ColorAreaType:=atText;
|
|
NextByte:=nbAreaColor;
|
|
ColorAreaStart:=CurPos;
|
|
InColorArea:=true;
|
|
end;
|
|
hscDirect :
|
|
NextByte:=nbDirect;
|
|
hscInImage :
|
|
begin
|
|
InImage := not InImage;
|
|
end;
|
|
hscNormText :
|
|
begin
|
|
if InColorArea then
|
|
EndColorArea;
|
|
end;
|
|
#32: if InLink then CurWord:=CurWord+C else
|
|
begin CheckZeroLevel; AddWord(CurWord+C); CurWord:=''; end;
|
|
else begin CheckZeroLevel; CurWord:=CurWord+C; end;
|
|
end;
|
|
end;
|
|
end;
|
|
CurPos.X:=Margin+length(Line)+length(CurWord);
|
|
Inc(TextPos);
|
|
end;
|
|
if (Line<>'') or (CurWord<>'') then FlushLine;
|
|
end;
|
|
end;
|
|
|
|
function THelpTopic.GetLineCount: sw_integer;
|
|
begin
|
|
GetLineCount:=Lines^.Count;
|
|
end;
|
|
|
|
function THelpTopic.GetLineText(Line: sw_integer): string;
|
|
var S: string;
|
|
begin
|
|
if Line<GetLineCount then S:=PString(Lines^.At(Line))^ else S:='';
|
|
GetLineText:=S;
|
|
end;
|
|
|
|
function THelpTopic.GetLinkCount: sw_integer;
|
|
begin
|
|
GetLinkCount:=Links^.Count;
|
|
end;
|
|
|
|
procedure THelpTopic.GetLinkBounds(Index: sw_integer; var R: TRect);
|
|
var P: PHelpLink;
|
|
begin
|
|
P:=Links^.At(Index);
|
|
R:=P^.Bounds;
|
|
end;
|
|
|
|
function THelpTopic.GetLinkFileID(Index: sw_integer): word;
|
|
var P: PHelpLink;
|
|
begin
|
|
P:=Links^.At(Index);
|
|
GetLinkFileID:=P^.FileID;
|
|
end;
|
|
|
|
function THelpTopic.GetLinkContext(Index: sw_integer): THelpCtx;
|
|
var P: PHelpLink;
|
|
begin
|
|
P:=Links^.At(Index);
|
|
GetLinkContext:=P^.Context;
|
|
end;
|
|
|
|
function THelpTopic.GetColorAreaCount: sw_integer;
|
|
begin
|
|
GetColorAreaCount:=ColorAreas^.Count;
|
|
end;
|
|
|
|
procedure THelpTopic.GetColorAreaBounds(Index: sw_integer; var R: TRect);
|
|
var P: PHelpColorArea;
|
|
begin
|
|
P:=ColorAreas^.At(Index);
|
|
R:=P^.Bounds;
|
|
end;
|
|
|
|
function THelpTopic.GetColorAreaColor(Index: sw_integer): word;
|
|
var P: PHelpColorArea;
|
|
begin
|
|
P:=ColorAreas^.At(Index);
|
|
GetColorAreaColor:=P^.Color;
|
|
end;
|
|
|
|
function THelpTopic.GetColorAreaMask(Index: sw_integer): word;
|
|
var P: PHelpColorArea;
|
|
begin
|
|
P:=ColorAreas^.At(Index);
|
|
GetColorAreaMask:=P^.AttrMask;
|
|
end;
|
|
|
|
destructor THelpTopic.Done;
|
|
begin
|
|
inherited Done;
|
|
Dispose(Lines, Done);
|
|
Dispose(LinesPos, Done);
|
|
Dispose(Links, Done);
|
|
Dispose(ColorAreas, Done);
|
|
Dispose(NamedMarks, Done);
|
|
if (Topic<>nil) then DisposeTopic(Topic);
|
|
end;
|
|
|
|
constructor THelpViewer.Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
|
|
begin
|
|
inherited Init(Bounds, AHScrollBar, AVScrollBar, nil, nil);
|
|
Flags:=efInsertMode or efPersistentBlocks;
|
|
ReadOnly:=true;
|
|
New(WordList, Init(50,50));
|
|
Margin:=1; CurLink:=-1;
|
|
end;
|
|
|
|
procedure THelpViewer.ChangeBounds(var Bounds: TRect);
|
|
var
|
|
LinePos,NewLineIndex,I : longint;
|
|
ymin, ymax : sw_integer;
|
|
prop : real;
|
|
begin
|
|
if Owner<>nil then Owner^.Lock;
|
|
ymin:=Delta.Y;
|
|
ymax:=ymin+Size.Y;
|
|
if ymax>ymin then
|
|
prop:=(CurPos.Y-ymin)/(ymax-ymin)
|
|
else
|
|
prop:=0;
|
|
inherited ChangeBounds(Bounds);
|
|
if (HelpTopic<>nil) and (HelpTopic^.Topic<>nil) and
|
|
(HelpTopic^.Topic^.FileID<>0) then
|
|
Begin
|
|
LinePos:=HelpTopic^.LinesPos^.At(CurPos.Y)+CurPos.X;
|
|
RenderTopic;
|
|
NewLineIndex:=-1;
|
|
For i:=0 to HelpTopic^.LinesPos^.Count-1 do
|
|
if LinePos<HelpTopic^.LinesPos^.At(i) then
|
|
begin
|
|
NewLineIndex:=i-1;
|
|
break;
|
|
end;
|
|
if NewLineIndex>=0 then
|
|
Begin
|
|
ymin:=NewLineIndex - trunc(prop * Size.Y);
|
|
if ymin<0 then
|
|
ymin:=0;
|
|
ScrollTo(0,ymin);
|
|
SetCurPtr(LinePos-HelpTopic^.LinesPos^.At(NewLineIndex),NewLineIndex);
|
|
End;
|
|
End;
|
|
if Owner<>nil then Owner^.UnLock;
|
|
end;
|
|
|
|
procedure THelpViewer.RenderTopic;
|
|
begin
|
|
if HelpTopic<>nil then
|
|
HelpTopic^.SetParams(Margin,Size.X);
|
|
SetLimit(255,GetLineCount);
|
|
DrawView;
|
|
end;
|
|
|
|
function THelpViewer.LinkContainsPoint(var R: TRect; var P: TPoint): boolean;
|
|
var OK: boolean;
|
|
begin
|
|
if (R.A.Y=R.B.Y) then
|
|
OK:= (P.Y=R.A.Y) and (R.A.X<=P.X) and (P.X<=R.B.X) else
|
|
OK:=
|
|
( (R.A.Y=P.Y) and (R.A.X<=P.X) ) or
|
|
( (R.A.Y<P.Y) and (P.Y<R.B.Y) ) or
|
|
( (R.B.Y=P.Y) and (P.X<=R.B.X) );
|
|
LinkContainsPoint:=OK;
|
|
end;
|
|
|
|
procedure THelpViewer.SetCurPtr(X,Y: sw_integer);
|
|
var OldCurLink,I: sw_integer;
|
|
OldPos,P: TPoint;
|
|
R: TRect;
|
|
begin
|
|
OldPos:=CurPos;
|
|
OldCurLink:=CurLink;
|
|
inherited SetCurPtr(X,Y);
|
|
CurLink:=-1;
|
|
P:=CurPos;
|
|
for I:=0 to GetLinkCount-1 do
|
|
begin
|
|
GetLinkBounds(I,R);
|
|
if LinkContainsPoint(R,P) then
|
|
begin CurLink:=I; Break; end;
|
|
end;
|
|
if OldCurLink<>CurLink then DrawView;
|
|
if ((OldPos.X<>CurPos.X) or (OldPos.Y<>CurPos.Y)) and (InLookup=false) then
|
|
Lookup('');
|
|
end;
|
|
|
|
function THelpViewer.GetLineCount: sw_integer;
|
|
var Count: sw_integer;
|
|
begin
|
|
if HelpTopic=nil then Count:=0 else Count:=HelpTopic^.GetLineCount;
|
|
GetLineCount:=Count;
|
|
end;
|
|
|
|
function THelpViewer.GetLine(LineNo: sw_integer): PCustomLine;
|
|
begin
|
|
{Abstract; used in wcedit unit ! }
|
|
GetLine:=nil;
|
|
end;
|
|
function THelpViewer.GetDisplayText(I: sw_integer): sw_astring;
|
|
begin
|
|
GetDisplayText:=ExtractTabs(GetLineText(I),DefaultTabSize);
|
|
end;
|
|
|
|
function THelpViewer.GetLineText(Line: sw_integer): sw_astring;
|
|
var S: sw_astring;
|
|
begin
|
|
if HelpTopic=nil then S:='' else S:=HelpTopic^.GetLineText(Line);
|
|
GetLineText:=S;
|
|
end;
|
|
|
|
function THelpViewer.GetLinkCount: sw_integer;
|
|
var Count: sw_integer;
|
|
begin
|
|
if HelpTopic=nil then Count:=0 else Count:=HelpTopic^.GetLinkCount;
|
|
GetLinkCount:=Count;
|
|
end;
|
|
|
|
procedure THelpViewer.GetLinkBounds(Index: sw_integer; var R: TRect);
|
|
begin
|
|
HelpTopic^.GetLinkBounds(Index,R);
|
|
end;
|
|
|
|
function THelpViewer.GetLinkFileID(Index: sw_integer): word;
|
|
begin
|
|
GetLinkFileID:=HelpTopic^.GetLinkFileID(Index);
|
|
end;
|
|
|
|
function THelpViewer.GetLinkContext(Index: sw_integer): THelpCtx;
|
|
begin
|
|
GetLinkContext:=HelpTopic^.GetLinkContext(Index);
|
|
end;
|
|
|
|
function THelpViewer.GetLinkTarget(Index: sw_integer): string;
|
|
var
|
|
Ctx : THelpCtx;
|
|
ID : sw_integer;
|
|
begin
|
|
GetLinkTarget:='';
|
|
if HelpTopic=nil then begin ID:=0; Ctx:=0; end else
|
|
begin
|
|
ID:=GetLinkFileID(Index);
|
|
Ctx:=GetLinkContext(Index);
|
|
end;
|
|
GetLinkTarget:=HelpFacility^.GetTopicInfo(ID,CTx);
|
|
end;
|
|
|
|
function THelpViewer.GetLinkText(Index: sw_integer): string;
|
|
var S: string;
|
|
R: TRect;
|
|
Y,StartX,EndX: sw_integer;
|
|
begin
|
|
S:=''; GetLinkBounds(Index,R);
|
|
Y:=R.A.Y;
|
|
while (Y<=R.B.Y) do
|
|
begin
|
|
if Y=R.A.Y then StartX:=R.A.X else StartX:=Margin;
|
|
if Y=R.B.Y then EndX:=R.B.X else EndX:=High(S);
|
|
S:=S+copy(GetLineText(Y),StartX+1,EndX-StartX+1); { Note: AnsiString to ShortString convertino}
|
|
Inc(Y);
|
|
end;
|
|
GetLinkText:=S;
|
|
end;
|
|
|
|
function THelpViewer.GetColorAreaCount: sw_integer;
|
|
var Count: sw_integer;
|
|
begin
|
|
if HelpTopic=nil then Count:=0 else Count:=HelpTopic^.GetColorAreaCount;
|
|
GetColorAreaCount:=Count;
|
|
end;
|
|
|
|
procedure THelpViewer.GetColorAreaBounds(Index: sw_integer; var R: TRect);
|
|
begin
|
|
HelpTopic^.GetColorAreaBounds(Index,R);
|
|
end;
|
|
|
|
function THelpViewer.GetColorAreaColor(Index: sw_integer): word;
|
|
begin
|
|
GetColorAreaColor:=HelpTopic^.GetColorAreaColor(Index);
|
|
end;
|
|
|
|
function THelpViewer.GetColorAreaMask(Index: sw_integer): word;
|
|
begin
|
|
GetColorAreaMask:=HelpTopic^.GetColorAreaMask(Index);
|
|
end;
|
|
|
|
procedure THelpViewer.SelectNextLink(ANext: boolean);
|
|
var I,Link: sw_integer;
|
|
R: TRect;
|
|
begin
|
|
if HelpTopic=nil then Exit;
|
|
Link:=CurLink;
|
|
if Link<>-1 then
|
|
begin
|
|
if ANext then
|
|
begin Inc(Link); if Link>=GetLinkCount then Link:=0; end else
|
|
begin Dec(Link); if Link=-1 then Link:=GetLinkCount-1; end;
|
|
end else
|
|
for I:=0 to GetLinkCount-1 do
|
|
begin
|
|
GetLinkBounds(I,R);
|
|
if (R.A.Y>CurPos.Y) or
|
|
(R.A.Y=CurPos.Y) and (R.A.X>CurPos.X) then
|
|
begin Link:=I; Break; end;
|
|
end;
|
|
if (Link=-1) and (GetLinkCount>0) then
|
|
if ANext then Link:=0
|
|
else Link:=GetLinkCount-1;
|
|
SetCurLink(Link);
|
|
end;
|
|
|
|
procedure THelpViewer.SetCurLink(Link: sw_integer);
|
|
var R: TRect;
|
|
begin
|
|
if Link<>-1 then
|
|
begin
|
|
GetLinkBounds(Link,R);
|
|
SetCurPtr(R.A.X,R.A.Y);
|
|
TrackCursor(do_centre);
|
|
{St:=GetLinkTarget(Link);
|
|
If St<>'' then
|
|
SetTitle('Help '+St);}
|
|
end;
|
|
end;
|
|
|
|
procedure THelpViewer.SwitchToIndex;
|
|
begin
|
|
if IndexTopic=nil then
|
|
IndexTopic:=HelpFacility^.BuildIndexTopic;
|
|
ISwitchToTopicPtr(IndexTopic,true);
|
|
end;
|
|
|
|
procedure THelpViewer.SwitchToTopic(SourceFileID: word; Context: THelpCtx);
|
|
begin
|
|
ISwitchToTopic(SourceFileID,Context,true);
|
|
end;
|
|
|
|
procedure THelpViewer.ISwitchToTopic(SourceFileID: word; Context: THelpCtx; RecordInHistory: boolean);
|
|
var P: PTopic;
|
|
begin
|
|
if HelpFacility=nil then P:=nil else
|
|
if (SourceFileID=0) and (Context=0) and (HelpTopic<>nil) then
|
|
P:=IndexTopic else
|
|
P:=HelpFacility^.LoadTopic(SourceFileID, Context);
|
|
ISwitchToTopicPtr(P,RecordInHistory);
|
|
end;
|
|
|
|
procedure THelpViewer.ISwitchToTopicPtr(P: PTopic; RecordInHistory: boolean);
|
|
var HistoryFull: boolean;
|
|
begin
|
|
if (P<>nil) and RecordInHistory and (HelpTopic<>nil) then
|
|
begin
|
|
HistoryFull:=HistoryPtr>=HistorySize;
|
|
if HistoryFull then
|
|
Move(History[1],History[0],SizeOf(History)-SizeOf(History[0]));
|
|
with History[HistoryPtr] do
|
|
begin
|
|
{SourceTopic_:=SourceTopic; }Context_:=HelpTopic^.Topic^.HelpCtx;
|
|
FileID_:=HelpTopic^.Topic^.FileID;
|
|
Delta_:=Delta; CurPos_:=CurPos; CurLink_:=CurLink;
|
|
end;
|
|
if HistoryFull=false then Inc(HistoryPtr);
|
|
end;
|
|
|
|
if Owner<>nil then Owner^.Lock;
|
|
SetTopic(P);
|
|
DrawView;
|
|
if Owner<>nil then Owner^.UnLock;
|
|
end;
|
|
|
|
procedure THelpViewer.PrevTopic;
|
|
begin
|
|
if HistoryPtr>0 then
|
|
begin
|
|
if Owner<>nil then Owner^.Lock;
|
|
Dec(HistoryPtr);
|
|
with History[HistoryPtr] do
|
|
begin
|
|
ISwitchToTopic(FileID_,Context_,false);
|
|
ScrollTo(Delta_.X,Delta_.Y);
|
|
SetCurPtr(CurPos_.X,CurPos_.Y);
|
|
TrackCursor(do_not_centre);
|
|
if CurLink<>CurLink_ then SetCurLink(CurLink_);
|
|
end;
|
|
DrawView;
|
|
if Owner<>nil then Owner^.UnLock;
|
|
end;
|
|
end;
|
|
|
|
procedure THelpViewer.SetTopic(Topic: PTopic);
|
|
var Bookmark: string;
|
|
P: TPoint;
|
|
begin
|
|
CurLink:=-1;
|
|
if (HelpTopic=nil) or (Topic<>HelpTopic^.Topic) then
|
|
begin
|
|
if (HelpTopic<>nil) and (HelpTopic<>IndexHelpTopic) then
|
|
Dispose(HelpTopic, Done);
|
|
HelpTopic:=nil;
|
|
if Topic<>nil then
|
|
begin
|
|
if (Topic=IndexTopic) and (IndexHelpTopic<>nil) then
|
|
HelpTopic:=IndexHelpTopic else
|
|
New(HelpTopic, Init(Topic));
|
|
if Topic=IndexTopic then
|
|
IndexHelpTopic:=HelpTopic;
|
|
end;
|
|
end;
|
|
if Owner<>nil then
|
|
Owner^.Lock;
|
|
SetCurPtr(0,0);
|
|
TrackCursor(do_not_centre);
|
|
RenderTopic;
|
|
BuildTopicWordList;
|
|
Lookup('');
|
|
if Assigned(Topic) then
|
|
if Topic^.StartNamedMark>0 then
|
|
if Topic^.NamedMarks^.Count>=Topic^.StartNamedMark then
|
|
begin
|
|
Bookmark:=GetStr(Topic^.NamedMarks^.At(Topic^.StartNamedMark-1));
|
|
if HelpTopic^.NamedMarks^.GetMarkPos(Bookmark,P) then
|
|
begin
|
|
SetCurPtr(P.X,P.Y);
|
|
ScrollTo(0,Max(0,P.Y-1));
|
|
end;
|
|
end;
|
|
SetSelection(CurPos,CurPos);
|
|
DrawView;
|
|
if Owner<>nil then Owner^.UnLock;
|
|
end;
|
|
|
|
procedure THelpViewer.BuildTopicWordList;
|
|
var I: sw_integer;
|
|
begin
|
|
WordList^.FreeAll;
|
|
for I:=0 to GetLinkCount-1 do
|
|
WordList^.Insert(NewKeyword(I,Trim(GetLinkText(I))));
|
|
end;
|
|
|
|
procedure THelpViewer.Lookup(S: string);
|
|
var Index, I: Sw_integer;
|
|
W: string;
|
|
OldLookup: string;
|
|
R: TRect;
|
|
P: PHelpKeyword;
|
|
begin
|
|
InLookup:=true;
|
|
OldLookup:=LookupWord;
|
|
S:=UpcaseStr(S);
|
|
Index:=-1;
|
|
I:=0; {J:=0;
|
|
while (J<GetLinkCount) do
|
|
begin
|
|
GetLinkBounds(J,R);
|
|
if (R.A.Y<CurPos.Y) or ((R.A.Y=CurPos.Y) and (R.B.X<CurPos.X))
|
|
then Inc(J) else
|
|
begin I:=J; Break; end;
|
|
end;}
|
|
if S='' then LookupWord:='' else
|
|
begin
|
|
while (Index=-1) and (I<WordList^.Count) do
|
|
begin
|
|
P:=WordList^.At(I);
|
|
if P^.KWord<>nil then
|
|
begin
|
|
W:=UpcaseStr(Trim(P^.KWord^));
|
|
if copy(W,1,length(S))=S then Index:=I;
|
|
end;
|
|
{ if W>S then Break else}
|
|
Inc(I);
|
|
end;
|
|
if Index<>-1 then
|
|
begin
|
|
W:=Trim(WordList^.At(Index)^.KWord^);
|
|
LookupWord:=copy(W,1,length(S));
|
|
end;
|
|
end;
|
|
|
|
if LookupWord<>OldLookup then
|
|
begin
|
|
if Index=-1 then SetCurLink(CurLink) else
|
|
begin
|
|
if Owner<>nil then Owner^.Lock;
|
|
P:=WordList^.At(Index);
|
|
S:=GetLinkText(P^.Index);
|
|
I:=Pos(LookupWord,S); if I=0 then I:=1;
|
|
GetLinkBounds(P^.Index,R);
|
|
SetCurPtr(R.A.X+(I-1)+length(Lookupword),R.A.Y);
|
|
CurLink:=P^.Index; DrawView;
|
|
TrackCursor(do_centre);
|
|
if Owner<>nil then Owner^.UnLock;
|
|
end;
|
|
end;
|
|
InLookup:=false;
|
|
end;
|
|
|
|
procedure THelpViewer.SelectLink(Index: sw_integer);
|
|
var ID: word;
|
|
Ctx: THelpCtx;
|
|
begin
|
|
if Index=-1 then Exit;
|
|
if HelpTopic=nil then begin ID:=0; Ctx:=0; end else
|
|
begin
|
|
ID:=GetLinkFileID(Index);
|
|
Ctx:=GetLinkContext(Index);
|
|
end;
|
|
SwitchToTopic(ID,Ctx);
|
|
end;
|
|
|
|
procedure THelpViewer.HandleEvent(var Event: TEvent);
|
|
var DontClear: boolean;
|
|
procedure GetMousePos(var P: TPoint);
|
|
begin
|
|
MakeLocal(Event.Where,P);
|
|
Inc(P.X,Delta.X); Inc(P.Y,Delta.Y);
|
|
end;
|
|
begin
|
|
case Event.What of
|
|
evMouseDown :
|
|
if MouseInView(Event.Where) then
|
|
if (Event.Buttons=mbLeftButton) and (Event.Double) then
|
|
begin
|
|
inherited HandleEvent(Event);
|
|
if CurLink<>-1 then
|
|
SelectLink(CurLink);
|
|
end;
|
|
evBroadcast :
|
|
case Event.Command of
|
|
cmHelpFilesChanged :
|
|
begin
|
|
if HelpTopic=IndexHelpTopic then HelpTopic:=nil;
|
|
IndexTopic:=nil;
|
|
if IndexHelpTopic<>nil then Dispose(IndexHelpTopic, Done);
|
|
IndexHelpTopic:=nil;
|
|
end;
|
|
end;
|
|
evCommand :
|
|
begin
|
|
DontClear:=false;
|
|
case Event.Command of
|
|
cmPrevTopic :
|
|
PrevTopic;
|
|
else DontClear:=true;
|
|
end;
|
|
if not DontClear then ClearEvent(Event);
|
|
end;
|
|
evKeyDown :
|
|
begin
|
|
DontClear:=false;
|
|
case Event.KeyCode of
|
|
kbTab :
|
|
SelectNextLink(true);
|
|
kbShiftTab :
|
|
begin
|
|
NoSelect:=true;
|
|
SelectNextLink(false);
|
|
NoSelect:=false;
|
|
end;
|
|
kbEnter :
|
|
if CurLink<>-1 then
|
|
SelectLink(CurLink);
|
|
kbBack,kbDel :
|
|
if Length(LookupWord)>0 then
|
|
Lookup(Copy(LookupWord,1,Length(LookupWord)-1));
|
|
else
|
|
case Event.CharCode of
|
|
#32..#255 :
|
|
begin
|
|
NoSelect:=true;
|
|
Lookup(LookupWord+Event.CharCode);
|
|
NoSelect:=false;
|
|
end;
|
|
else
|
|
DontClear:=true;
|
|
end;
|
|
end;
|
|
TrackCursor(do_not_centre);
|
|
if not DontClear then
|
|
ClearEvent(Event);
|
|
end;
|
|
end;
|
|
inherited HandleEvent(Event);
|
|
end;
|
|
|
|
procedure THelpViewer.Draw;
|
|
var NormalColor, LinkColor,
|
|
SelectColor, SelectionColor: word;
|
|
B: TDrawBuffer;
|
|
DX,DY,X,Y,I,MinX,MaxX,ScreenX: sw_integer;
|
|
LastLinkDrawn,LastColorAreaDrawn: sw_integer;
|
|
S: sw_astring;
|
|
R: TRect;
|
|
SelR : TRect;
|
|
C,Mask: word;
|
|
CurP: TPoint;
|
|
ANDSB,ORSB: word;
|
|
begin
|
|
if ELockFlag>0 then
|
|
begin
|
|
DrawCalled:=true;
|
|
Exit;
|
|
end;
|
|
DrawCalled:=false;
|
|
|
|
|
|
NormalColor:=GetColor(1); LinkColor:=GetColor(2);
|
|
SelectColor:=GetColor(3); SelectionColor:=GetColor(4);
|
|
SelR.A:=SelStart; SelR.B:=SelEnd;
|
|
LastLinkDrawn:=0; LastColorAreaDrawn:=0;
|
|
for DY:=0 to Size.Y-1 do
|
|
begin
|
|
Y:=Delta.Y+DY;
|
|
MoveChar(B,' ',NormalColor,Size.X);
|
|
if Y<GetLineCount then
|
|
begin
|
|
S:=GetLineText(Y);
|
|
S:=copy(S,Delta.X+1,Length(S));
|
|
S:=copy(S,1,MaxViewWidth);
|
|
MoveStr(B,S,NormalColor);
|
|
|
|
for I:=LastColorAreaDrawn to GetColorAreaCount-1 do
|
|
begin
|
|
GetColorAreaBounds(I,R);
|
|
if R.A.Y>Y then Break;
|
|
LastColorAreaDrawn:=I;
|
|
if Y=R.B.Y then MaxX:=R.B.X else MaxX:=(length(S)+Delta.X-1);
|
|
if Y=R.A.Y then MinX:=R.A.X else MinX:=0;
|
|
if (R.A.Y<=Y) and (Y<=R.B.Y) then
|
|
begin
|
|
C:=GetColorAreaColor(I);
|
|
Mask:=GetColorAreaMask(I);
|
|
for DX:=MinX to MaxX do
|
|
begin
|
|
X:=DX;
|
|
ScreenX:=X-(Delta.X);
|
|
if (ScreenX>=0) and (ScreenX<=High(B)) then
|
|
begin
|
|
{ CurP.X:=X; CurP.Y:=Y;
|
|
if LinkAreaContainsPoint(R,CurP) then}
|
|
(* B[ScreenX]:=(B[ScreenX] and $f0ff) or (C shl 8);*)
|
|
ANDSB:=(Mask shl 8)+$ff;
|
|
ORSB:=(C shl 8);
|
|
B[ScreenX]:=(B[ScreenX] and ANDSB) or ORSB;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
for I:=LastLinkDrawn to GetLinkCount-1 do
|
|
begin
|
|
GetLinkBounds(I,R);
|
|
if R.A.Y>Y then Break;
|
|
LastLinkDrawn:=I;
|
|
if Y=R.B.Y then MaxX:=R.B.X else MaxX:=(length(S)-1);
|
|
if Y=R.A.Y then MinX:=R.A.X else MinX:=0;
|
|
if (R.A.Y<=Y) and (Y<=R.B.Y) then
|
|
for DX:=MinX to MaxX do
|
|
begin
|
|
X:=DX;
|
|
ScreenX:=X-(Delta.X);
|
|
if (ScreenX>=0) and (ScreenX<=High(B)) then
|
|
begin
|
|
CurP.X:=X; CurP.Y:=Y;
|
|
if LinkContainsPoint(R,CurP) then
|
|
if I=CurLink then C:=SelectColor else C:=LinkColor;
|
|
B[ScreenX]:=(B[ScreenX] and $ff) or (C shl 8);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
if ((SelR.A.X<>SelR.B.X) or (SelR.A.Y<>SelR.B.Y)) and (SelR.A.Y<=Y) and (Y<=SelR.B.Y) then
|
|
begin
|
|
if Y=SelR.A.Y then MinX:=SelR.A.X else MinX:=0;
|
|
if Y=SelR.B.Y then MaxX:=SelR.B.X-1 else MaxX:=High(string);
|
|
for DX:=MinX to MaxX do
|
|
begin
|
|
X:=DX;
|
|
ScreenX:=X-(Delta.X);
|
|
if (ScreenX>=0) and (ScreenX<High(B)) then
|
|
B[ScreenX]:=(B[ScreenX] and $0fff) or ((SelectionColor and $f0) shl 8);
|
|
end;
|
|
end;
|
|
|
|
end;
|
|
WriteLine(0,DY,Size.X,1,B);
|
|
end;
|
|
DrawCursor;
|
|
end;
|
|
|
|
function THelpViewer.GetPalette: PPalette;
|
|
const P: string[length(CHelpViewer)] = CHelpViewer;
|
|
begin
|
|
GetPalette:=@P;
|
|
end;
|
|
|
|
constructor THelpViewer.Load(var S: TStream);
|
|
begin
|
|
inherited Load(S);
|
|
end;
|
|
|
|
procedure THelpViewer.Store(var S: TStream);
|
|
begin
|
|
inherited Store(S);
|
|
end;
|
|
|
|
destructor THelpViewer.Done;
|
|
begin
|
|
if (HelpTopic<>nil) and (HelpTopic<>IndexHelpTopic) then
|
|
Dispose(HelpTopic, Done);
|
|
HelpTopic:=nil;
|
|
if IndexHelpTopic<>nil then
|
|
Dispose(IndexHelpTopic, Done);
|
|
IndexHelpTopic:=nil;
|
|
inherited Done;
|
|
if assigned(WordList) then
|
|
Dispose(WordList, Done);
|
|
end;
|
|
|
|
function THelpFrame.GetPalette: PPalette;
|
|
const P: string[length(CHelpFrame)] = CHelpFrame;
|
|
begin
|
|
GetPalette:=@P;
|
|
end;
|
|
|
|
constructor THelpWindow.Init(var Bounds: TRect; ATitle: TTitleStr; ASourceFileID: word; AContext: THelpCtx; ANumber: Integer);
|
|
begin
|
|
inherited Init(Bounds, ATitle, ANumber);
|
|
InitScrollBars;
|
|
if Assigned(HSB) then Insert(HSB);
|
|
if Assigned(VSB) then Insert(VSB);
|
|
InitHelpView;
|
|
if Assigned(HelpView) then
|
|
begin
|
|
if (ASourceFileID<>0) or (AContext<>0) then
|
|
ShowTopic(ASourceFileID, AContext);
|
|
Insert(HelpView);
|
|
end;
|
|
end;
|
|
|
|
procedure THelpWindow.ShowDebugInfos;
|
|
begin
|
|
{$ifdef DEBUG}
|
|
DebugMessage(GetTitle(255),'Generic Help window',1,1);
|
|
if HelpView^.CurLink<>-1 then
|
|
begin
|
|
DebugMessage('','Curlink is '+IntToStr(HelpView^.CurLink),1,1);
|
|
DebugMessage('',HelpView^.GetLinkTarget(HelpView^.CurLink),1,1);
|
|
end;
|
|
{$endif DEBUG}
|
|
end;
|
|
|
|
procedure THelpWindow.InitScrollBars;
|
|
var R: TRect;
|
|
begin
|
|
GetExtent(R); R.Grow(0,-1); R.A.X:=R.B.X-1;
|
|
New(VSB, Init(R)); VSB^.GrowMode:=gfGrowLoX+gfGrowHiX+gfGrowHiY;
|
|
GetExtent(R); R.Grow(-1,0); R.A.Y:=R.B.Y-1;
|
|
New(HSB, Init(R)); HSB^.GrowMode:=gfGrowLoY+gfGrowHiX+gfGrowHiY;
|
|
end;
|
|
|
|
procedure THelpWindow.InitHelpView;
|
|
var R: TRect;
|
|
begin
|
|
GetExtent(R); R.Grow(-1,-1);
|
|
New(HelpView, Init(R, HSB, VSB));
|
|
HelpView^.GrowMode:=gfGrowHiX+gfGrowHiY;
|
|
end;
|
|
|
|
procedure THelpWindow.InitFrame;
|
|
var R: TRect;
|
|
begin
|
|
GetExtent(R);
|
|
Frame:=New(PHelpFrame, Init(R));
|
|
end;
|
|
|
|
procedure THelpWindow.ShowIndex;
|
|
begin
|
|
HelpView^.SwitchToIndex;
|
|
end;
|
|
|
|
procedure THelpWindow.ShowTopic(SourceFileID: word; Context: THelpCtx);
|
|
begin
|
|
HelpView^.SwitchToTopic(SourceFileID, Context);
|
|
end;
|
|
|
|
procedure THelpWindow.HandleEvent(var Event: TEvent);
|
|
begin
|
|
case Event.What of
|
|
evKeyDown :
|
|
case Event.KeyCode of
|
|
kbEsc :
|
|
begin
|
|
Event.What:=evCommand; Event.Command:=cmClose;
|
|
end;
|
|
end;
|
|
end;
|
|
inherited HandleEvent(Event);
|
|
end;
|
|
|
|
procedure THelpWindow.Close;
|
|
begin
|
|
if HideOnClose then Hide else inherited Close;
|
|
end;
|
|
|
|
function THelpWindow.GetPalette: PPalette;
|
|
begin
|
|
GetPalette:=nil;
|
|
end;
|
|
|
|
END.
|